From f57ebfa1a03d08845c0d67c05c7401a9ffcb9b46 Mon Sep 17 00:00:00 2001
From: chuga-git <98280110+chuga-git@users.noreply.github.com>
Date: Tue, 10 Sep 2024 17:14:01 -0500
Subject: [PATCH] Fixes stacks, attempt 2 (#26633)
* this is hell pain
* fixes merge issues when cutting up various items
* adds early return to attackby
---
code/game/objects/items/stacks/stack.dm | 50 +++++++++++++-------
code/game/objects/items/weapons/shards.dm | 12 +----
code/game/objects/structures/bedsheet_bin.dm | 2 +-
code/modules/hydroponics/grown/towercap.dm | 7 +--
4 files changed, 37 insertions(+), 34 deletions(-)
diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm
index 72924db35c1..5b9397d1a9a 100644
--- a/code/game/objects/items/stacks/stack.dm
+++ b/code/game/objects/items/stacks/stack.dm
@@ -37,7 +37,6 @@
var/parent_stack = FALSE
/obj/item/stack/Initialize(mapload, new_amount, merge = TRUE)
- . = ..()
if(dynamic_icon_state) //If we have a dynamic icon state, we don't want item states to follow the same pattern.
item_state = initial(icon_state)
@@ -51,13 +50,14 @@
if(!merge_type)
merge_type = type
- if(merge && !(amount >= max_amount))
+ . = ..()
+ if(merge)
for(var/obj/item/stack/item_stack in loc)
if(item_stack == src)
continue
- if(item_stack.merge_type == merge_type)
+ if(can_merge(item_stack))
INVOKE_ASYNC(src, PROC_REF(merge_without_del), item_stack)
- // we do not want to qdel during initialization, so we just check whether or not we're a 0 count stack
+ // we do not want to qdel during initialization, so we just check whether or not we're a 0 count stack and let the hint handle deletion
if(is_zero_amount(FALSE))
return INITIALIZE_HINT_QDEL
@@ -76,17 +76,20 @@
icon_state = "[initial(icon_state)]_[state]"
/obj/item/stack/Crossed(obj/O, oldloc)
+ if(O == src)
+ return
+
if(amount >= max_amount || ismob(loc)) // Prevents unnecessary call. Also prevents merging stack automatically in a mob's inventory
return
- if(istype(O, merge_type) && !O.throwing)
- merge(O)
+ if(!O.throwing && can_merge(O))
+ INVOKE_ASYNC(src, PROC_REF(merge), O)
..()
-/obj/item/stack/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum)
- if(istype(AM, merge_type) && !(amount >= max_amount))
- merge(AM)
+/obj/item/stack/hitby(atom/movable/hitting, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum)
+ if(can_merge(hitting, inhand = TRUE))
+ merge(hitting)
. = ..()
/obj/item/stack/examine(mob/user)
@@ -114,6 +117,22 @@
amount += newamount
update_icon(UPDATE_ICON_STATE)
+/** Checks whether this stack can merge itself into another stack.
+ *
+ * Arguments:
+ * - [check][/obj/item/stack]: The stack to check for mergeability.
+ * - [inhand][boolean]: Whether or not the stack to check should act like it's in a mob's hand.
+ */
+/obj/item/stack/proc/can_merge(obj/item/stack/check, inhand = FALSE)
+ // We don't only use istype here, since that will match subtypes, and stack things that shouldn't stack
+ if(!istype(check, merge_type) || check.merge_type != merge_type)
+ return FALSE
+ if(is_cyborg) // No merging cyborg stacks into other stacks
+ return FALSE
+ if(ismob(loc) && !inhand) // no merging with items that are on the mob
+ return FALSE
+ return TRUE
+
/obj/item/stack/attack_self(mob/user)
ui_interact(user)
@@ -144,12 +163,12 @@
ui_interact(user)
/obj/item/stack/attackby(obj/item/thing, mob/user, params)
- if((!parent_stack && !istype(thing, merge_type)) || (parent_stack && thing.type != type))
+ if(!can_merge(thing, TRUE))
return ..()
var/obj/item/stack/material = thing
- merge(material)
- to_chat(user, "Your [material.name] stack now contains [material.get_amount()] [material.singular_name]\s.")
+ if(merge(material))
+ to_chat(user, "Your [material.name] stack now contains [material.get_amount()] [material.singular_name]\s.")
/obj/item/stack/use(used, check = TRUE)
if(check && is_zero_amount(TRUE))
@@ -162,8 +181,8 @@
return FALSE
amount -= used
- if(check)
- is_zero_amount(TRUE)
+ if(check && is_zero_amount(TRUE))
+ return TRUE
update_icon(UPDATE_ICON_STATE)
return TRUE
@@ -305,9 +324,6 @@
return source.amount < cost
if(amount < 1)
- if(ismob(loc))
- var/mob/living/L = loc // At this stage, stack code is so horrible and atrocious, I wouldn't be all surprised ghosts can somehow have stacks. If this happens, then the world deserves to burn.
- L.unEquip(src, TRUE)
if(delete_if_zero)
qdel(src)
return TRUE
diff --git a/code/game/objects/items/weapons/shards.dm b/code/game/objects/items/weapons/shards.dm
index 931c03fd2ba..ee3eb8349f0 100644
--- a/code/game/objects/items/weapons/shards.dm
+++ b/code/game/objects/items/weapons/shards.dm
@@ -66,16 +66,8 @@
. = TRUE
if(!I.use_tool(src, user, volume = I.tool_volume))
return
- var/obj/item/stack/sheet/NG = new welded_type(user.loc)
- for(var/obj/item/stack/sheet/G in user.loc)
- if(!istype(G, welded_type))
- continue
- if(G == NG)
- continue
- if(G.amount >= G.max_amount)
- continue
- G.attackby(NG, user)
- to_chat(user, "You add the newly-formed glass to the stack. It now contains [NG.amount] sheet\s.")
+ var/obj/item/stack/sheet/new_glass = new welded_type(user.loc)
+ to_chat(user, "You add the newly-formed glass to the stack.")
qdel(src)
/obj/item/shard/Crossed(mob/living/L, oldloc)
diff --git a/code/game/objects/structures/bedsheet_bin.dm b/code/game/objects/structures/bedsheet_bin.dm
index e4d99b404fe..32052fae848 100644
--- a/code/game/objects/structures/bedsheet_bin.dm
+++ b/code/game/objects/structures/bedsheet_bin.dm
@@ -50,8 +50,8 @@ LINEN BINS
var/obj/item/stack/sheet/cloth/C = new (get_turf(src), 3)
transfer_fingerprints_to(C)
C.add_fingerprint(user)
- qdel(src)
to_chat(user, "You tear [src] up.")
+ qdel(src)
else
return ..()
diff --git a/code/modules/hydroponics/grown/towercap.dm b/code/modules/hydroponics/grown/towercap.dm
index 584f9404661..90632195054 100644
--- a/code/modules/hydroponics/grown/towercap.dm
+++ b/code/modules/hydroponics/grown/towercap.dm
@@ -62,12 +62,7 @@
if(seed)
seed_modifier = round(seed.potency / 25)
var/obj/item/stack/plank = new plank_type(user.loc, 1 + seed_modifier)
- var/old_plank_amount = plank.amount
- for(var/obj/item/stack/ST in user.loc)
- if(ST != plank && istype(ST, plank_type) && ST.amount < ST.max_amount)
- ST.attackby(plank, user) //we try to transfer all old unfinished stacks to the new stack we created.
- if(plank.amount > old_plank_amount)
- to_chat(user, "You add the newly-formed [plank_name] to the stack. It now contains [plank.amount] [plank_name].")
+ to_chat(user, "You add the newly-formed [plank_name] to the stack.")
qdel(src)
if(CheckAccepted(W))