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))