Skip to content

Commit

Permalink
[MIRROR] Change setting item weight class to a setter to patch some w…
Browse files Browse the repository at this point in the history
…eight class related shenanigans (#2789)

* 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:

* Change setting item weight class to a setter to patch some weight class related shenanigans

---------

Co-authored-by: NovaBot <[email protected]>
Co-authored-by: MrMelbert <[email protected]>
  • Loading branch information
3 people authored Apr 9, 2024
1 parent 4440af9 commit dfa44bb
Show file tree
Hide file tree
Showing 28 changed files with 127 additions and 58 deletions.
5 changes: 5 additions & 0 deletions code/__DEFINES/dcs/signals/signals_object.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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"
3 changes: 3 additions & 0 deletions code/__DEFINES/inventory.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion code/datums/components/customizable_reagent_holder.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions code/datums/components/transforming.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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))
Expand Down
12 changes: 12 additions & 0 deletions code/datums/storage/storage.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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)
18 changes: 2 additions & 16 deletions code/datums/storage/subtypes/fish_case.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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))
21 changes: 21 additions & 0 deletions code/game/objects/items.dm
Original file line number Diff line number Diff line change
Expand Up @@ -1755,3 +1755,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
4 changes: 2 additions & 2 deletions code/game/objects/items/dualsaber.dm
Original file line number Diff line number Diff line change
Expand Up @@ -61,15 +61,15 @@
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)

/// 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)
Expand Down
6 changes: 3 additions & 3 deletions code/game/objects/items/stacks/stack.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion code/game/objects/items/stacks/wrap.dm
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,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()
Expand Down
4 changes: 2 additions & 2 deletions code/game/objects/items/tanks/tanks.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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.
Expand Down
4 changes: 2 additions & 2 deletions code/game/objects/items/tools/spess_knife.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
4 changes: 2 additions & 2 deletions code/modules/antagonists/heretic/items/forbidden_book.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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)
. = ..()
Expand Down
6 changes: 3 additions & 3 deletions code/modules/detectivework/evidence.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -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)
Expand All @@ -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."

Expand Down
10 changes: 5 additions & 5 deletions code/modules/fishing/fish/_fish.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
8 changes: 5 additions & 3 deletions code/modules/food_and_drinks/plate.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion code/modules/hallucination/inhand_fake_item.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
3 changes: 1 addition & 2 deletions code/modules/mining/equipment/explorer_gear.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -353,4 +353,3 @@
desc = "An armoured hood for exploring harsh environments."
icon_state = "explorer_syndicate"
armor_type = /datum/armor/hooded_explorer_syndicate

6 changes: 3 additions & 3 deletions code/modules/mining/equipment/mining_tools.dm
Original file line number Diff line number Diff line change
Expand Up @@ -257,23 +257,23 @@
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")
if("Shovel")
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")
if("Pick")
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")
Expand Down
2 changes: 1 addition & 1 deletion code/modules/mob/living/carbon/human/_species.dm
Original file line number Diff line number Diff line change
Expand Up @@ -871,7 +871,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
Expand Down
18 changes: 18 additions & 0 deletions code/modules/mob/living/carbon/human/init_signals.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
2 changes: 1 addition & 1 deletion code/modules/mob/living/inhand_holder.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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)
. = ..()

Expand Down
Loading

0 comments on commit dfa44bb

Please sign in to comment.