Refactor split_stack to two separate procs, fixes a hard delete in the process (#91306)

## About The Pull Request

I was trying to fix a hard delete and it became a whole thing
- Reworks `/obj/item/stack/proc/split_stack` to no longer also try to
put it in the user's hands, or take a user at all. The proc now purely
splits the stack and returns the new one
- Creates `/obj/item/stack/proc/split_n_take` which uses `split_stack`
and does the other behaviors like fingerprint adding and putting in the
user's hands
- Update usages of `split_stack` to either properly use it and remove
the code added to get around the put in hands behavior, or change them
to use `split_n_take` instead
- Fix a random bug in pipe bomb building I noticed while testing

## Why It's Good For The Game

Ultimately this fixes a hard delete with goldgrubs eating a piece of ore
while sitting on top of another piece of ore of the same type (the put
in hands behavior of split stack would cause the ore being consumed to
drop to the ground briefly, merge with the ore there, and then qdel
while still being moved to the goldgrub contents), but also added bonus
that it makes `split_stack` just split the stack and not some other
stuff too. Also a pipe bomb bug fix

## Changelog

🆑
fix: fixed being able to add seemingly infinite refined bluespace
crystals to pipe bombs
refactor: /obj/item/stack/split_stack no longer tries to move the stack
into the user's hands, use /obj/item/stack/split_n_take for that
/🆑
This commit is contained in:
Roxy
2025-05-24 20:14:53 -04:00
committed by GitHub
parent 245f453a43
commit 7d08da9fd6
9 changed files with 39 additions and 32 deletions
+25 -14
View File
@@ -695,7 +695,7 @@
if(user.get_inactive_held_item() == src)
if(is_zero_amount(delete_if_zero = TRUE))
return
return split_stack(user, 1)
return split_n_take(user, 1)
else
. = ..()
@@ -712,30 +712,41 @@
var/stackmaterial = tgui_input_number(user, "How many sheets do you wish to take out of this stack?", "Stack Split", max_value = max)
if(!stackmaterial || QDELETED(user) || QDELETED(src) || !usr.can_perform_action(src, FORBID_TELEKINESIS_REACH))
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
split_stack(user, stackmaterial)
split_n_take(user, stackmaterial)
to_chat(user, span_notice("You take [stackmaterial] sheets out of the stack."))
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
/** Splits the stack into two stacks.
/** Splits the stack into two stacks, returns the new stack.
*
* Arguments:
* - [user][/mob]: The mob splitting the stack.
* - amount: The number of units to split from this stack.
*/
/obj/item/stack/proc/split_stack(mob/user, amount)
/obj/item/stack/proc/split_stack(amount)
if(!use(amount, TRUE, FALSE))
return null
var/obj/item/stack/F = new type(user? user : drop_location(), amount, FALSE, mats_per_unit)
. = F
F.copy_evidences(src)
var/obj/item/stack/new_stack = new type(null, amount, FALSE, mats_per_unit)
new_stack.copy_evidences(src)
loc.atom_storage?.refresh_views()
if(user)
if(!user.put_in_hands(F, merge_stacks = FALSE))
F.forceMove(user.drop_location())
add_fingerprint(user)
F.add_fingerprint(user)
is_zero_amount(delete_if_zero = TRUE)
return new_stack
/**
* Splits amount items from stack, attempts to place new stack in user's hands.
* Returns the new stack.
* Arguments:
* * [user][/mob] - Mob performing the split, non-nullable
* * amount - Number of units to split from this stack
*/
/obj/item/stack/proc/split_n_take(mob/user, amount)
if(!user)
return null
add_fingerprint(user)
var/obj/item/stack/new_stack = split_stack(amount)
if(isnull(new_stack))
return null
new_stack.add_fingerprint(user)
user.put_in_hands(new_stack, merge_stacks = FALSE)
return new_stack
/obj/item/stack/attackby(obj/item/W, mob/user, list/modifiers, list/attack_modifiers)
if(can_merge(W, inhand = TRUE))