Fixes ore bags being able to reject any ores despite having ample space, stack merging sanity/QOL (#93451)

## About The Pull Request

Ore bags try to insert the stack without actually checking if it can
merge with anything, meaning that ores can take up limited slots which
may end up with 7 single-ore stacks preventing any more ore from
entering the bag, despite there being ample space for 49 more ore of
each type. Now bags will actually try to merge picked up ore into
themselves first, ensuring that this doesn't occur, and that the bag
will always be topped up (This needed additional logic to ensure that
stacks don't merge beyond the size that the storage they're in can
handle)

Additionally, I've changed how stacks merge when dragged (instead of
merging themselves into the target, target is merged into themselves)
and prevent dragging from changing focus to stack that is being merged
into if the merging stack isn't empty, fixing the "pull churn" issue
that locks out player inputs if you try to pry and drag floor tiles due
to constantly swapping the pull target after every tile pried, plus I've
removed that weird ore box `insertion` animation (which I recon is an
oversight) and ore bags sucking up the ores you drop from your hand
because you're probably doing so intentionally

## Changelog
🆑
fix: Fixed ore bags being able to reject any ores despite having ample
space
fix: Pulling a stack behind you and getting it topped up by lying items
will no longer spam pulls and lock out your inputs
fix: Picking up ores into an ore box via an ore bag will no longer play
a jank animation
qol: Ore bags and MODule ore bags no longer pick up ores you've dropped
from your hand until you walk over them again
/🆑
This commit is contained in:
SmArtKar
2025-10-15 15:28:22 +02:00
committed by GitHub
parent 2dc405fc43
commit f8cae70510
3 changed files with 64 additions and 19 deletions
+46 -14
View File
@@ -123,14 +123,14 @@
/obj/item/stack/Moved(atom/old_loc, movement_dir, forced, list/old_locs, momentum_change)
. = ..()
if((!throwing || throwing.target_turf == loc) && old_loc != loc && (flags_1 & INITIALIZED_1))
merge_with_loc()
merge_with_loc(merge_into_ourselves = !isnull(pulledby))
///Called to lazily update the materials of the item whenever the used or if more is added
/obj/item/stack/proc/update_custom_materials()
if(length(mats_per_unit))
set_custom_materials(mats_per_unit, amount)
/obj/item/stack/proc/find_other_stack(list/already_found)
/obj/item/stack/proc/find_other_stack(list/already_found, merge_into_ourselves = FALSE)
if(QDELETED(src) || isnull(loc))
return
for(var/obj/item/stack/item_stack in loc)
@@ -141,20 +141,23 @@
var/stack_ref = REF(item_stack)
if(already_found[stack_ref])
continue
if(can_merge(item_stack))
if(merge_into_ourselves ? item_stack.can_merge(src) : can_merge(item_stack))
already_found[stack_ref] = TRUE
return item_stack
/// Tries to merge the stack with everything on the same tile.
/obj/item/stack/proc/merge_with_loc()
/obj/item/stack/proc/merge_with_loc(merge_into_ourselves = FALSE)
var/list/already_found = list() // change to alist whenever dreamchecker and such finally supports that
var/obj/item/other_stack = find_other_stack(already_found)
var/obj/item/stack/other_stack = find_other_stack(already_found, merge_into_ourselves)
var/sanity = max_amount // just in case
while(other_stack && sanity > 0)
sanity--
if(merge(other_stack))
if(!merge_into_ourselves)
if(merge(other_stack))
return FALSE
else if (other_stack.merge(src) && !QDELETED(other_stack))
return FALSE
other_stack = find_other_stack(already_found)
other_stack = find_other_stack(already_found, TRUE)
return TRUE
/obj/item/stack/apply_material_effects(list/materials)
@@ -208,12 +211,14 @@
return list() //empty list
/obj/item/stack/proc/update_weight()
if(amount <= (max_amount * (1/3)))
update_weight_class(clamp(full_w_class-2, WEIGHT_CLASS_TINY, full_w_class))
else if (amount <= (max_amount * (2/3)))
update_weight_class(clamp(full_w_class-1, WEIGHT_CLASS_TINY, full_w_class))
else
update_weight_class(full_w_class)
update_weight_class(get_weight_from_size(amount))
/obj/item/stack/proc/get_weight_from_size(stack_amount)
if(stack_amount <= (max_amount * (1/3)))
return clamp(full_w_class - 2, WEIGHT_CLASS_TINY, full_w_class)
if(stack_amount <= (max_amount * (2/3)))
return clamp(full_w_class - 1, WEIGHT_CLASS_TINY, full_w_class)
return full_w_class
/obj/item/stack/update_icon_state()
if(novariants)
@@ -671,8 +676,35 @@
transfer = min(transfer, round((target_stack.source.max_energy - target_stack.source.energy) / target_stack.cost))
else
transfer = min(transfer, (limit ? limit : target_stack.max_amount) - target_stack.amount)
if(pulledby)
// Ensure that we're not bloating the target stack to the point where it falls out of storage
if(target_stack.loc?.atom_storage)
var/datum/storage/target_storage = target_stack.loc?.atom_storage
var/cur_size = target_stack.w_class
var/new_size = target_stack.get_weight_from_size(target_stack.amount + transfer)
var/real_new_size = new_size
var/real_cur_size = cur_size
// Ensure that we don't end up with two mergeable stacks if our own size gets reduced enough from the merge and we share the space
if (!is_cyborg && loc == target_stack.loc)
real_cur_size += w_class
if (amount > transfer)
real_new_size += get_weight_from_size(amount - transfer)
// If total size changed, check for overflows
if(new_size > cur_size)
var/size_limit = max(new_size - target_storage.max_specific_storage, target_storage.get_total_weight() + real_new_size - real_cur_size - target_storage.max_total_storage)
// If we're over the stack limit the storage container can support, reduce the transferred amount
// to the nearest size threshold, then by a third of the target stack per excess size
if(size_limit > 0)
var/to_threshold = FLOOR(target_stack.amount + transfer, floor(target_stack.max_amount / 3))
transfer = clamp(to_threshold - floor(target_stack.max_amount / 3) * (size_limit - 1) - target_stack.amount, 0, transfer)
if(!transfer)
return
if(pulledby && is_zero_amount(delete_if_zero = FALSE))
pulledby.start_pulling(target_stack)
target_stack.copy_evidences(src)
use(transfer, transfer = TRUE, check = FALSE)
target_stack.add(transfer)