From ead0e859db6fcc8e68296d8954d63805e0877ca2 Mon Sep 17 00:00:00 2001
From: Arkatos1 <43862960+Arkatos1@users.noreply.github.com>
Date: Fri, 27 Nov 2020 03:05:52 +0100
Subject: [PATCH] Merge type variable fixes and unit test (#55173)
This PR fixes a case where certain materials caused issues when working with stacking machines, because they did not have set merge_type from the get go, which meant that initial() of that variable returned null.
To clarify further - if /obj/item/stack does not have set merge_type, it is generated merge_type upon Initialize(), which is the same as its typepath. For example, currently /obj/item/stack/sheet/bluespace_crystal does not have any merge_type set, and it is given merge_type = /obj/item/stack/sheet/bluespace_crystal upon Initialize(). Each Initialize(). Again and again.
There are quite a bit of these cases in the codebase, especially if its some older code. I have gone through them and set all of them their set merge_type, which they would inevitably receive anyway upon initializing and it fixes a bug mentioned above.
To prevent this happening again, I have also included unit test to check if merge types are set for stacks, included exceptions are usually abstract paths like /obj/item/stack/sheet/mineral, which contains zero behavior on its own and does not spawn unless done via admin tools.
---
.../game/objects/items/devices/polycircuit.dm | 1 +
.../objects/items/stacks/ammonia_crystals.dm | 1 +
code/game/objects/items/stacks/bscrystal.dm | 7 ++++-
code/game/objects/items/stacks/cash.dm | 9 ++++++
.../objects/items/stacks/license_plates.dm | 2 ++
code/game/objects/items/stacks/medical.dm | 13 ++++++++
code/game/objects/items/stacks/rods.dm | 5 ++-
.../objects/items/stacks/sheets/hot_ice.dm | 1 +
.../objects/items/stacks/sheets/leather.dm | 31 ++++++++++++++-----
.../game/objects/items/stacks/sheets/light.dm | 1 +
.../items/stacks/sheets/sheet_types.dm | 5 +--
code/game/objects/items/stacks/tape.dm | 6 +++-
code/game/objects/items/stacks/telecrystal.dm | 1 +
code/game/objects/items/stacks/tickets.dm | 1 +
code/game/objects/items/stacks/tiles/light.dm | 1 +
.../items/stacks/tiles/tile_mineral.dm | 19 ++++++++++++
.../objects/items/stacks/tiles/tile_types.dm | 29 +++++++++++++++++
code/game/objects/items/stacks/wrap.dm | 4 +++
code/modules/events/crystal_event.dm | 1 +
code/modules/mining/ores_coins.dm | 12 ++++++-
code/modules/recycling/conveyor2.dm | 1 +
.../research/xenobiology/xenobiology.dm | 4 +--
code/modules/unit_tests/_unit_tests.dm | 1 +
code/modules/unit_tests/merge_type.dm | 15 +++++++++
24 files changed, 154 insertions(+), 17 deletions(-)
create mode 100644 code/modules/unit_tests/merge_type.dm
diff --git a/code/game/objects/items/devices/polycircuit.dm b/code/game/objects/items/devices/polycircuit.dm
index 3cd2cedeec1..4ca456e3fcf 100644
--- a/code/game/objects/items/devices/polycircuit.dm
+++ b/code/game/objects/items/devices/polycircuit.dm
@@ -5,6 +5,7 @@
inhand_icon_state = "rods"
w_class = WEIGHT_CLASS_TINY
max_amount = 8
+ merge_type = /obj/item/stack/circuit_stack
var/circuit_type = /obj/item/electronics/airlock
var/chosen_circuit = "airlock"
diff --git a/code/game/objects/items/stacks/ammonia_crystals.dm b/code/game/objects/items/stacks/ammonia_crystals.dm
index 1be04147bc0..2ed83319290 100644
--- a/code/game/objects/items/stacks/ammonia_crystals.dm
+++ b/code/game/objects/items/stacks/ammonia_crystals.dm
@@ -7,3 +7,4 @@
resistance_flags = FLAMMABLE
max_amount = 50
grind_results = list(/datum/reagent/ammonia = 10)
+ merge_type = /obj/item/stack/ammonia_crystals
diff --git a/code/game/objects/items/stacks/bscrystal.dm b/code/game/objects/items/stacks/bscrystal.dm
index 59a535810ae..6634fc11e47 100644
--- a/code/game/objects/items/stacks/bscrystal.dm
+++ b/code/game/objects/items/stacks/bscrystal.dm
@@ -9,15 +9,18 @@
w_class = WEIGHT_CLASS_TINY
mats_per_unit = list(/datum/material/bluespace=MINERAL_MATERIAL_AMOUNT)
points = 50
- var/blink_range = 8 // The teleport range when crushed/thrown at someone.
refined_type = /obj/item/stack/sheet/bluespace_crystal
grind_results = list(/datum/reagent/bluespace = 20)
scan_state = "rock_BScrystal"
+ merge_type = /obj/item/stack/ore/bluespace_crystal
+ /// The teleport range when crushed/thrown at someone.
+ var/blink_range = 8
/obj/item/stack/ore/bluespace_crystal/refined
name = "refined bluespace crystal"
points = 0
refined_type = null
+ merge_type = /obj/item/stack/ore/bluespace_crystal/refined
/obj/item/stack/ore/bluespace_crystal/Initialize()
. = ..()
@@ -56,6 +59,7 @@
points = 0 //nice try
refined_type = null
grind_results = list(/datum/reagent/bluespace = 10, /datum/reagent/silicon = 20)
+ merge_type = /obj/item/stack/ore/bluespace_crystal/artificial
//Polycrystals, aka stacks
/obj/item/stack/sheet/bluespace_crystal
@@ -71,6 +75,7 @@
novariants = TRUE
grind_results = list(/datum/reagent/bluespace = 20)
point_value = 30
+ merge_type = /obj/item/stack/sheet/bluespace_crystal
var/crystal_type = /obj/item/stack/ore/bluespace_crystal/refined
/obj/item/stack/sheet/bluespace_crystal/attack_self(mob/user)// to prevent the construction menu from ever happening
diff --git a/code/game/objects/items/stacks/cash.dm b/code/game/objects/items/stacks/cash.dm
index 1243bd5e3d7..d49c8db08bf 100644
--- a/code/game/objects/items/stacks/cash.dm
+++ b/code/game/objects/items/stacks/cash.dm
@@ -59,43 +59,52 @@
icon_state = "spacecash"
singular_name = "one credit bill"
value = 1
+ merge_type = /obj/item/stack/spacecash/c1
/obj/item/stack/spacecash/c10
icon_state = "spacecash10"
singular_name = "ten credit bill"
value = 10
+ merge_type = /obj/item/stack/spacecash/c10
/obj/item/stack/spacecash/c20
icon_state = "spacecash20"
singular_name = "twenty credit bill"
value = 20
+ merge_type = /obj/item/stack/spacecash/c20
/obj/item/stack/spacecash/c50
icon_state = "spacecash50"
singular_name = "fifty credit bill"
value = 50
+ merge_type = /obj/item/stack/spacecash/c50
/obj/item/stack/spacecash/c100
icon_state = "spacecash100"
singular_name = "one hundred credit bill"
value = 100
+ merge_type = /obj/item/stack/spacecash/c100
/obj/item/stack/spacecash/c200
icon_state = "spacecash200"
singular_name = "two hundred credit bill"
value = 200
+ merge_type = /obj/item/stack/spacecash/c200
/obj/item/stack/spacecash/c500
icon_state = "spacecash500"
singular_name = "five hundred credit bill"
value = 500
+ merge_type = /obj/item/stack/spacecash/c500
/obj/item/stack/spacecash/c1000
icon_state = "spacecash1000"
singular_name = "one thousand credit bill"
value = 1000
+ merge_type = /obj/item/stack/spacecash/c1000
/obj/item/stack/spacecash/c10000
icon_state = "spacecash10000"
singular_name = "ten thousand credit bill"
value = 10000
+ merge_type = /obj/item/stack/spacecash/c10000
diff --git a/code/game/objects/items/stacks/license_plates.dm b/code/game/objects/items/stacks/license_plates.dm
index 06dc86ee615..12060f073d4 100644
--- a/code/game/objects/items/stacks/license_plates.dm
+++ b/code/game/objects/items/stacks/license_plates.dm
@@ -9,6 +9,7 @@
/obj/item/stack/license_plates/empty
name = "empty license plate"
desc = "Instead of a license plate number, this could contain a quote like \"Live laugh love\"."
+ merge_type = /obj/item/stack/license_plates/empty
/obj/item/stack/license_plates/empty/fifty
amount = 50
@@ -17,6 +18,7 @@
name = "license plate"
desc = "Prison labor paying off."
icon_state = "filled_plate_1_1"
+ merge_type = /obj/item/stack/license_plates/filled
///Override to allow for variations
/obj/item/stack/license_plates/filled/update_icon_state()
diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm
index 1896b57a898..c880a1ce856 100644
--- a/code/game/objects/items/stacks/medical.dm
+++ b/code/game/objects/items/stacks/medical.dm
@@ -14,6 +14,7 @@
item_flags = NOBLUDGEON
cost = 250
source = /datum/robot_energy_storage/medical
+ merge_type = /obj/item/stack/medical
var/self_delay = 50
var/other_delay = 0
var/repeating = FALSE
@@ -90,6 +91,7 @@
self_delay = 40
other_delay = 20
grind_results = list(/datum/reagent/medicine/c2/libital = 10)
+ merge_type = /obj/item/stack/medical/bruise_pack
/obj/item/stack/medical/bruise_pack/heal(mob/living/M, mob/user)
if(M.stat == DEAD)
@@ -129,6 +131,7 @@
absorption_rate = 0.25
absorption_capacity = 5
splint_factor = 0.35
+ merge_type = /obj/item/stack/medical/gauze
// gauze is only relevant for wounds, which are handled in the wounds themselves
/obj/item/stack/medical/gauze/try_heal(mob/living/M, mob/user, silent)
@@ -190,6 +193,7 @@
other_delay = 30
absorption_rate = 0.15
absorption_capacity = 4
+ merge_type = /obj/item/stack/medical/gauze/improvised
/obj/item/stack/medical/suture
name = "suture"
@@ -205,6 +209,7 @@
heal_brute = 10
stop_bleeding = 0.6
grind_results = list(/datum/reagent/medicine/spaceacillin = 2)
+ merge_type = /obj/item/stack/medical/suture
/obj/item/stack/medical/suture/emergency
name = "emergency suture"
@@ -212,6 +217,7 @@
heal_brute = 5
amount = 5
max_amount = 5
+ merge_type = /obj/item/stack/medical/suture/emergency
/obj/item/stack/medical/suture/medicated
name = "medicated suture"
@@ -220,6 +226,7 @@
heal_brute = 15
stop_bleeding = 0.75
grind_results = list(/datum/reagent/medicine/polypyr = 1)
+ merge_type = /obj/item/stack/medical/suture/medicated
/obj/item/stack/medical/suture/heal(mob/living/M, mob/user)
. = ..()
@@ -259,6 +266,7 @@
flesh_regeneration = 2.5
sanitization = 0.25
grind_results = list(/datum/reagent/medicine/c2/lenturi = 10)
+ merge_type = /obj/item/stack/medical/ointment
/obj/item/stack/medical/ointment/heal(mob/living/M, mob/user)
if(M.stat == DEAD)
@@ -289,6 +297,7 @@
var/is_open = TRUE ///This var determines if the sterile packaging of the mesh has been opened.
grind_results = list(/datum/reagent/medicine/spaceacillin = 2)
+ merge_type = /obj/item/stack/medical/mesh
/obj/item/stack/medical/mesh/Initialize()
. = ..()
@@ -349,6 +358,7 @@
sanitization = 1.25
flesh_regeneration = 3.5
grind_results = list(/datum/reagent/consumable/aloejuice = 1)
+ merge_type = /obj/item/stack/medical/mesh/advanced
/obj/item/stack/medical/mesh/advanced/update_icon_state()
if(!is_open)
@@ -371,6 +381,7 @@
repeating = TRUE
var/heal = 3
grind_results = list(/datum/reagent/consumable/aloejuice = 1)
+ merge_type = /obj/item/stack/medical/aloe
/obj/item/stack/medical/aloe/heal(mob/living/M, mob/user)
. = ..()
@@ -415,6 +426,7 @@
self_delay = 20
grind_results = list(/datum/reagent/medicine/c2/libital = 10)
novariants = TRUE
+ merge_type = /obj/item/stack/medical/bone_gel
/obj/item/stack/medical/bone_gel/attack(mob/living/M, mob/user)
to_chat(user, "Bone gel can only be used on fractured limbs!")
@@ -457,6 +469,7 @@
drop_sound = 'sound/misc/moist_impact.ogg'
mob_throw_hit_sound = 'sound/misc/moist_impact.ogg'
hitsound = 'sound/misc/moist_impact.ogg'
+ merge_type = /obj/item/stack/medical/poultice
/obj/item/stack/medical/poultice/heal(mob/living/M, mob/user)
. = .. ()
diff --git a/code/game/objects/items/stacks/rods.dm b/code/game/objects/items/stacks/rods.dm
index c0b1b03a113..d01ab1e56c1 100644
--- a/code/game/objects/items/stacks/rods.dm
+++ b/code/game/objects/items/stacks/rods.dm
@@ -30,6 +30,7 @@ GLOBAL_LIST_INIT(rod_recipes, list ( \
matter_amount = 2
cost = 250
source = /datum/robot_energy_storage/metal
+ merge_type = /obj/item/stack/rods
/obj/item/stack/rods/suicide_act(mob/living/carbon/user)
user.visible_message("[user] begins to stuff \the [src] down [user.p_their()] throat! It looks like [user.p_theyre()] trying to commit suicide!")//it looks like theyre ur mum
@@ -70,9 +71,6 @@ GLOBAL_LIST_INIT(rod_recipes, list ( \
else
return ..()
-/obj/item/stack/rods/cyborg
- merge_type = /obj/item/stack/rods
-
/obj/item/stack/rods/cyborg/ComponentInitialize()
. = ..()
AddElement(/datum/element/update_icon_blocker)
@@ -98,6 +96,7 @@ GLOBAL_LIST_INIT(rod_recipes, list ( \
mats_per_unit = list(/datum/material/iron=1000, /datum/material/plasma=500, /datum/material/titanium=2000)
max_amount = 30
resistance_flags = FIRE_PROOF | LAVA_PROOF
+ merge_type = /obj/item/stack/rods/lava
/obj/item/stack/rods/lava/thirty
amount = 30
diff --git a/code/game/objects/items/stacks/sheets/hot_ice.dm b/code/game/objects/items/stacks/sheets/hot_ice.dm
index 3a7105c9d46..8267e3a9b30 100644
--- a/code/game/objects/items/stacks/sheets/hot_ice.dm
+++ b/code/game/objects/items/stacks/sheets/hot_ice.dm
@@ -7,6 +7,7 @@
mats_per_unit = list(/datum/material/hot_ice=MINERAL_MATERIAL_AMOUNT)
grind_results = list(/datum/reagent/toxin/hot_ice = 25)
material_type = /datum/material/hot_ice
+ merge_type = /obj/item/stack/sheet/hot_ice
/obj/item/stack/sheet/hot_ice/suicide_act(mob/living/carbon/user)
user.visible_message("[user] begins licking \the [src]! It looks like [user.p_theyre()] trying to commit suicide!")
diff --git a/code/game/objects/items/stacks/sheets/leather.dm b/code/game/objects/items/stacks/sheets/leather.dm
index a6dc4a861d7..23cc41191ca 100644
--- a/code/game/objects/items/stacks/sheets/leather.dm
+++ b/code/game/objects/items/stacks/sheets/leather.dm
@@ -4,12 +4,14 @@
icon_state = "sheet-hide"
inhand_icon_state = "sheet-hide"
novariants = TRUE
+ merge_type = /obj/item/stack/sheet/animalhide
/obj/item/stack/sheet/animalhide/human
name = "human skin"
desc = "The by-product of human farming."
singular_name = "human skin piece"
novariants = FALSE
+ merge_type = /obj/item/stack/sheet/animalhide/human
GLOBAL_LIST_INIT(human_recipes, list( \
new/datum/stack_recipe("bloated human costume", /obj/item/clothing/suit/hooded/bloated_human, 5), \
@@ -24,6 +26,7 @@ GLOBAL_LIST_INIT(human_recipes, list( \
desc = "A piece of skin."
singular_name = "skin piece"
novariants = FALSE
+ merge_type = /obj/item/stack/sheet/animalhide/generic
/obj/item/stack/sheet/animalhide/corgi
name = "corgi hide"
@@ -31,7 +34,7 @@ GLOBAL_LIST_INIT(human_recipes, list( \
singular_name = "corgi hide piece"
icon_state = "sheet-corgi"
inhand_icon_state = "sheet-corgi"
-
+ merge_type = /obj/item/stack/sheet/animalhide/corgi
GLOBAL_LIST_INIT(gondola_recipes, list ( \
new/datum/stack_recipe("gondola mask", /obj/item/clothing/mask/gondola, 1), \
@@ -44,6 +47,7 @@ GLOBAL_LIST_INIT(gondola_recipes, list ( \
singular_name = "gondola hide piece"
icon_state = "sheet-gondola"
inhand_icon_state = "sheet-gondola"
+ merge_type = /obj/item/stack/sheet/animalhide/gondola
/obj/item/stack/sheet/animalhide/gondola/get_main_recipes()
. = ..()
@@ -63,6 +67,7 @@ GLOBAL_LIST_INIT(corgi_recipes, list ( \
singular_name = "cat hide piece"
icon_state = "sheet-cat"
inhand_icon_state = "sheet-cat"
+ merge_type = /obj/item/stack/sheet/animalhide/cat
/obj/item/stack/sheet/animalhide/monkey
name = "monkey hide"
@@ -70,6 +75,7 @@ GLOBAL_LIST_INIT(corgi_recipes, list ( \
singular_name = "monkey hide piece"
icon_state = "sheet-monkey"
inhand_icon_state = "sheet-monkey"
+ merge_type = /obj/item/stack/sheet/animalhide/monkey
GLOBAL_LIST_INIT(monkey_recipes, list ( \
new/datum/stack_recipe("monkey mask", /obj/item/clothing/mask/gas/monkeymask, 1), \
@@ -86,6 +92,7 @@ GLOBAL_LIST_INIT(monkey_recipes, list ( \
singular_name = "lizard skin piece"
icon_state = "sheet-lizard"
inhand_icon_state = "sheet-lizard"
+ merge_type = /obj/item/stack/sheet/animalhide/lizard
/obj/item/stack/sheet/animalhide/xeno
name = "alien hide"
@@ -93,6 +100,7 @@ GLOBAL_LIST_INIT(monkey_recipes, list ( \
singular_name = "alien hide piece"
icon_state = "sheet-xeno"
inhand_icon_state = "sheet-xeno"
+ merge_type = /obj/item/stack/sheet/animalhide/xeno
GLOBAL_LIST_INIT(xeno_recipes, list ( \
new/datum/stack_recipe("alien helmet", /obj/item/clothing/head/xenos, 1), \
@@ -111,6 +119,7 @@ GLOBAL_LIST_INIT(xeno_recipes, list ( \
icon = 'icons/mob/alien.dmi'
icon_state = "chitin"
novariants = TRUE
+ merge_type = /obj/item/stack/sheet/xenochitin
/obj/item/xenos_claw
name = "alien claw"
@@ -130,6 +139,7 @@ GLOBAL_LIST_INIT(xeno_recipes, list ( \
singular_name = "hairless hide piece"
icon_state = "sheet-hairlesshide"
inhand_icon_state = "sheet-hairlesshide"
+ merge_type = /obj/item/stack/sheet/hairlesshide
/obj/item/stack/sheet/wethide
name = "wet hide"
@@ -137,8 +147,11 @@ GLOBAL_LIST_INIT(xeno_recipes, list ( \
singular_name = "wet hide piece"
icon_state = "sheet-wetleather"
inhand_icon_state = "sheet-wetleather"
- var/wetness = 30 //Reduced when exposed to high temperautres
- var/drying_threshold_temperature = 500 //Kelvin to start drying
+ merge_type = /obj/item/stack/sheet/wethide
+ /// Reduced when exposed to high temperatures
+ var/wetness = 30
+ /// Kelvin to start drying
+ var/drying_threshold_temperature = 500
/obj/item/stack/sheet/wethide/Initialize(mapload, new_amount, merge)
. = ..()
@@ -153,6 +166,7 @@ GLOBAL_LIST_INIT(xeno_recipes, list ( \
singular_name = "leather piece"
icon_state = "sheet-leather"
inhand_icon_state = "sheet-leather"
+ merge_type = /obj/item/stack/sheet/leather
GLOBAL_LIST_INIT(leather_recipes, list ( \
new/datum/stack_recipe("wallet", /obj/item/storage/wallet, 1), \
@@ -180,12 +194,13 @@ GLOBAL_LIST_INIT(leather_recipes, list ( \
singular_name = "watcher sinew"
icon_state = "sinew"
novariants = TRUE
+ merge_type = /obj/item/stack/sheet/sinew
/obj/item/stack/sheet/sinew/wolf
name = "wolf sinew"
desc = "Long stringy filaments which came from the insides of a wolf."
singular_name = "wolf sinew"
-
+ merge_type = /obj/item/stack/sheet/sinew/wolf
GLOBAL_LIST_INIT(sinew_recipes, list ( \
new/datum/stack_recipe("sinew restraints", /obj/item/restraints/handcuffs/cable/sinew, 1), \
@@ -195,9 +210,9 @@ GLOBAL_LIST_INIT(sinew_recipes, list ( \
. = ..()
. += GLOB.sinew_recipes
- /*
+/*
* Plates
- */
+ */
/obj/item/stack/sheet/animalhide/goliath_hide
name = "goliath hide plates"
desc = "Pieces of a goliath's rocky hide, these might be able to make your suit a bit more durable to attack from the local fauna."
@@ -209,12 +224,14 @@ GLOBAL_LIST_INIT(sinew_recipes, list ( \
item_flags = NOBLUDGEON
w_class = WEIGHT_CLASS_NORMAL
layer = MOB_LAYER
+ merge_type = /obj/item/stack/sheet/animalhide/goliath_hide
/obj/item/stack/sheet/animalhide/goliath_hide/polar_bear_hide
name = "polar bear hides"
desc = "Pieces of a polar bear's fur, these might be able to make your suit a bit more durable to attack from the local fauna."
icon_state = "polar_bear_hide"
singular_name = "polar bear hide"
+ merge_type = /obj/item/stack/sheet/animalhide/goliath_hide/polar_bear_hide
/obj/item/stack/sheet/animalhide/ashdrake
name = "ash drake hide"
@@ -227,7 +244,7 @@ GLOBAL_LIST_INIT(sinew_recipes, list ( \
item_flags = NOBLUDGEON
w_class = WEIGHT_CLASS_NORMAL
layer = MOB_LAYER
-
+ merge_type = /obj/item/stack/sheet/animalhide/ashdrake
//Step one - dehairing.
diff --git a/code/game/objects/items/stacks/sheets/light.dm b/code/game/objects/items/stacks/sheets/light.dm
index 84062a0ce69..2ec427147e2 100644
--- a/code/game/objects/items/stacks/sheets/light.dm
+++ b/code/game/objects/items/stacks/sheets/light.dm
@@ -12,6 +12,7 @@
flags_1 = CONDUCT_1
max_amount = 60
grind_results = list(/datum/reagent/silicon = 20, /datum/reagent/copper = 5)
+ merge_type = /obj/item/stack/light_w
/obj/item/stack/light_w/attackby(obj/item/O, mob/user, params)
if(istype(O, /obj/item/stack/sheet/metal))
diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm
index 6a03e300685..5ba0fe76cf5 100644
--- a/code/game/objects/items/stacks/sheets/sheet_types.dm
+++ b/code/game/objects/items/stacks/sheets/sheet_types.dm
@@ -614,7 +614,7 @@ GLOBAL_LIST_INIT(bronze_recipes, list ( \
icon_state = "sheet-lessergem"
inhand_icon_state = "sheet-lessergem"
novariants = TRUE
-
+ merge_type = /obj/item/stack/sheet/lessergem
/obj/item/stack/sheet/greatergem
name = "greater gems"
@@ -623,8 +623,9 @@ GLOBAL_LIST_INIT(bronze_recipes, list ( \
icon_state = "sheet-greatergem"
inhand_icon_state = "sheet-greatergem"
novariants = TRUE
+ merge_type = /obj/item/stack/sheet/greatergem
- /*
+/*
* Bones
*/
/obj/item/stack/sheet/bone
diff --git a/code/game/objects/items/stacks/tape.dm b/code/game/objects/items/stacks/tape.dm
index c0364d3529b..26daedd82f9 100644
--- a/code/game/objects/items/stacks/tape.dm
+++ b/code/game/objects/items/stacks/tape.dm
@@ -15,7 +15,7 @@
resistance_flags = FLAMMABLE
grind_results = list(/datum/reagent/cellulose = 5)
splint_factor = 0.8
-
+ merge_type = /obj/item/stack/sticky_tape
var/list/conferred_embed = EMBED_HARMLESS
var/overwrite_existing = FALSE
@@ -59,6 +59,7 @@
prefix = "super sticky"
conferred_embed = EMBED_HARMLESS_SUPERIOR
splint_factor = 0.6
+ merge_type = /obj/item/stack/sticky_tape/super
/obj/item/stack/sticky_tape/pointy
name = "pointy tape"
@@ -67,6 +68,7 @@
icon_state = "tape_evil"
prefix = "pointy"
conferred_embed = EMBED_POINTY
+ merge_type = /obj/item/stack/sticky_tape/pointy
/obj/item/stack/sticky_tape/pointy/super
name = "super pointy tape"
@@ -75,6 +77,7 @@
icon_state = "tape_spikes"
prefix = "super pointy"
conferred_embed = EMBED_POINTY_SUPERIOR
+ merge_type = /obj/item/stack/sticky_tape/pointy/super
/obj/item/stack/sticky_tape/surgical
name = "surgical tape"
@@ -85,3 +88,4 @@
conferred_embed = list("embed_chance" = 30, "pain_mult" = 0, "jostle_pain_mult" = 0, "ignore_throwspeed_threshold" = TRUE)
splint_factor = 0.4
custom_price = PAYCHECK_MEDIUM
+ merge_type = /obj/item/stack/sticky_tape/surgical
diff --git a/code/game/objects/items/stacks/telecrystal.dm b/code/game/objects/items/stacks/telecrystal.dm
index d5abf13210e..d390ec63cd1 100644
--- a/code/game/objects/items/stacks/telecrystal.dm
+++ b/code/game/objects/items/stacks/telecrystal.dm
@@ -8,6 +8,7 @@
w_class = WEIGHT_CLASS_TINY
max_amount = 50
item_flags = NOBLUDGEON
+ merge_type = /obj/item/stack/telecrystal
/obj/item/stack/telecrystal/attack(mob/target, mob/user)
if(target == user) //You can't go around smacking people with crystals to find out if they have an uplink or not.
diff --git a/code/game/objects/items/stacks/tickets.dm b/code/game/objects/items/stacks/tickets.dm
index 93a7f883c6a..45db72771ac 100644
--- a/code/game/objects/items/stacks/tickets.dm
+++ b/code/game/objects/items/stacks/tickets.dm
@@ -6,6 +6,7 @@
inhand_icon_state = "tickets"
w_class = WEIGHT_CLASS_TINY
max_amount = 30
+ merge_type = /obj/item/stack/arcadeticket
/obj/item/stack/arcadeticket/Initialize(mapload, new_amount, merge = TRUE)
. = ..()
diff --git a/code/game/objects/items/stacks/tiles/light.dm b/code/game/objects/items/stacks/tiles/light.dm
index 04ab24b0e8b..9206be0b33d 100644
--- a/code/game/objects/items/stacks/tiles/light.dm
+++ b/code/game/objects/items/stacks/tiles/light.dm
@@ -7,6 +7,7 @@
attack_verb_continuous = list("bashes", "batters", "bludgeons", "thrashes", "smashes")
attack_verb_simple = list("bash", "batter", "bludgeon", "thrash", "smash")
turf_type = /turf/open/floor/light
+ merge_type = /obj/item/stack/tile/light
var/state = 0
/obj/item/stack/tile/light/attackby(obj/item/O, mob/user, params)
diff --git a/code/game/objects/items/stacks/tiles/tile_mineral.dm b/code/game/objects/items/stacks/tiles/tile_mineral.dm
index 626da228121..0a51c7ebd35 100644
--- a/code/game/objects/items/stacks/tiles/tile_mineral.dm
+++ b/code/game/objects/items/stacks/tiles/tile_mineral.dm
@@ -7,6 +7,7 @@
turf_type = /turf/open/floor/mineral/plasma
mineralType = "plasma"
mats_per_unit = list(/datum/material/plasma=500)
+ merge_type = /obj/item/stack/tile/mineral/plasma
/obj/item/stack/tile/mineral/uranium
name = "uranium tile"
@@ -17,6 +18,7 @@
turf_type = /turf/open/floor/mineral/uranium
mineralType = "uranium"
mats_per_unit = list(/datum/material/uranium=500)
+ merge_type = /obj/item/stack/tile/mineral/uranium
/obj/item/stack/tile/mineral/gold
name = "gold tile"
@@ -27,6 +29,7 @@
turf_type = /turf/open/floor/mineral/gold
mineralType = "gold"
mats_per_unit = list(/datum/material/gold=500)
+ merge_type = /obj/item/stack/tile/mineral/gold
/obj/item/stack/tile/mineral/silver
name = "silver tile"
@@ -37,6 +40,7 @@
turf_type = /turf/open/floor/mineral/silver
mineralType = "silver"
mats_per_unit = list(/datum/material/silver=500)
+ merge_type = /obj/item/stack/tile/mineral/silver
/obj/item/stack/tile/mineral/diamond
name = "diamond tile"
@@ -47,6 +51,7 @@
turf_type = /turf/open/floor/mineral/diamond
mineralType = "diamond"
mats_per_unit = list(/datum/material/diamond=500)
+ merge_type = /obj/item/stack/tile/mineral/diamond
/obj/item/stack/tile/mineral/bananium
name = "bananium tile"
@@ -57,6 +62,7 @@
turf_type = /turf/open/floor/mineral/bananium
mineralType = "bananium"
mats_per_unit = list(/datum/material/bananium=500)
+ merge_type = /obj/item/stack/tile/mineral/bananium
/obj/item/stack/tile/mineral/abductor
name = "alien floor tile"
@@ -68,6 +74,7 @@
mats_per_unit = list(/datum/material/alloy/alien=MINERAL_MATERIAL_AMOUNT*0.25)
turf_type = /turf/open/floor/mineral/abductor
mineralType = "abductor"
+ merge_type = /obj/item/stack/tile/mineral/abductor
/obj/item/stack/tile/mineral/titanium
name = "titanium tile"
@@ -78,6 +85,7 @@
turf_type = /turf/open/floor/mineral/titanium
mineralType = "titanium"
mats_per_unit = list(/datum/material/titanium=500)
+ merge_type = /obj/item/stack/tile/mineral/titanium
tile_reskin_types = list(
/obj/item/stack/tile/mineral/titanium,
/obj/item/stack/tile/mineral/titanium/yellow,
@@ -97,6 +105,7 @@
desc = "Sleek yellow titanium tiles. Use while in your hand to change what type of titanium tiles you want."
turf_type = /turf/open/floor/mineral/titanium/yellow
icon_state = "tile_titanium_yellow"
+ merge_type = /obj/item/stack/tile/mineral/titanium/yellow
/obj/item/stack/tile/mineral/titanium/blue
name = "blue titanium tile"
@@ -104,6 +113,7 @@
desc = "Sleek blue titanium tiles. Use while in your hand to change what type of titanium tiles you want."
turf_type = /turf/open/floor/mineral/titanium/blue
icon_state = "tile_titanium_blue"
+ merge_type = /obj/item/stack/tile/mineral/titanium/blue
/obj/item/stack/tile/mineral/titanium/white
name = "white titanium tile"
@@ -111,6 +121,7 @@
desc = "Sleek white titanium tiles. Use while in your hand to change what type of titanium tiles you want."
turf_type = /turf/open/floor/mineral/titanium/white
icon_state = "tile_titanium_white"
+ merge_type = /obj/item/stack/tile/mineral/titanium/white
/obj/item/stack/tile/mineral/titanium/purple
name = "purple titanium tile"
@@ -118,6 +129,7 @@
desc = "Sleek purple titanium tiles. Use while in your hand to change what type of titanium tiles you want."
turf_type = /turf/open/floor/mineral/titanium/purple
icon_state = "tile_titanium_purple"
+ merge_type = /obj/item/stack/tile/mineral/titanium/purple
/obj/item/stack/tile/mineral/titanium/tiled
name = "tiled titanium tile"
@@ -125,6 +137,7 @@
desc = "Titanium floor tiles. Use while in your hand to change what type of titanium tiles you want."
turf_type = /turf/open/floor/mineral/titanium/tiled
icon_state = "tile_titanium_tiled"
+ merge_type = /obj/item/stack/tile/mineral/titanium/tiled
/obj/item/stack/tile/mineral/titanium/tiled/yellow
name = "yellow titanium tile"
@@ -132,6 +145,7 @@
desc = "Yellow titanium floor tiles. Use while in your hand to change what type of titanium tiles you want."
turf_type = /turf/open/floor/mineral/titanium/tiled/yellow
icon_state = "tile_titanium_tiled_yellow"
+ merge_type = /obj/item/stack/tile/mineral/titanium/tiled/yellow
/obj/item/stack/tile/mineral/titanium/tiled/blue
name = "blue titanium tile"
@@ -139,6 +153,7 @@
desc = "Blue titanium floor tiles. Use while in your hand to change what type of titanium tiles you want."
turf_type = /turf/open/floor/mineral/titanium/tiled/blue
icon_state = "tile_titanium_tiled_blue"
+ merge_type = /obj/item/stack/tile/mineral/titanium/tiled/blue
/obj/item/stack/tile/mineral/titanium/tiled/white
name = "white titanium tile"
@@ -146,6 +161,7 @@
desc = "White titanium floor tiles. Use while in your hand to change what type of titanium tiles you want."
turf_type = /turf/open/floor/mineral/titanium/tiled/white
icon_state = "tile_titanium_tiled_white"
+ merge_type = /obj/item/stack/tile/mineral/titanium/tiled/white
/obj/item/stack/tile/mineral/titanium/tiled/purple
name = "purple titanium tile"
@@ -153,6 +169,7 @@
desc = "Purple titanium floor tiles. Use while in your hand to change what type of titanium tiles you want."
turf_type = /turf/open/floor/mineral/titanium/tiled/purple
icon_state = "tile_titanium_tiled_purple"
+ merge_type = /obj/item/stack/tile/mineral/titanium/tiled/purple
/obj/item/stack/tile/mineral/plastitanium
name = "plastitanium tile"
@@ -164,6 +181,7 @@
mineralType = "plastitanium"
mats_per_unit = list(/datum/material/alloy/plastitanium=MINERAL_MATERIAL_AMOUNT*0.25)
material_flags = MATERIAL_NO_EFFECTS
+ merge_type = /obj/item/stack/tile/mineral/plastitanium
/obj/item/stack/tile/mineral/snow
name = "snow tile"
@@ -173,3 +191,4 @@
inhand_icon_state = "tile-silver"
turf_type = /turf/open/floor/grass/snow/safe
mineralType = "snow"
+ merge_type = /obj/item/stack/tile/mineral/snow
diff --git a/code/game/objects/items/stacks/tiles/tile_types.dm b/code/game/objects/items/stacks/tiles/tile_types.dm
index 976c528d28f..d96140090d8 100644
--- a/code/game/objects/items/stacks/tiles/tile_types.dm
+++ b/code/game/objects/items/stacks/tiles/tile_types.dm
@@ -103,6 +103,7 @@
inhand_icon_state = "tile-grass"
turf_type = /turf/open/floor/grass
resistance_flags = FLAMMABLE
+ merge_type = /obj/item/stack/tile/grass
//Fairygrass
/obj/item/stack/tile/fairygrass
@@ -113,6 +114,7 @@
inhand_icon_state = "tile-fairygrass"
turf_type = /turf/open/floor/grass/fairy
resistance_flags = FLAMMABLE
+ merge_type = /obj/item/stack/tile/fairygrass
//Wood
/obj/item/stack/tile/wood
@@ -123,6 +125,7 @@
inhand_icon_state = "tile-wood"
turf_type = /turf/open/floor/wood
resistance_flags = FLAMMABLE
+ merge_type = /obj/item/stack/tile/wood
//Basalt
/obj/item/stack/tile/basalt
@@ -132,6 +135,7 @@
icon_state = "tile_basalt"
inhand_icon_state = "tile-basalt"
turf_type = /turf/open/floor/grass/fakebasalt
+ merge_type = /obj/item/stack/tile/basalt
//Carpets
/obj/item/stack/tile/carpet
@@ -143,6 +147,7 @@
turf_type = /turf/open/floor/carpet
resistance_flags = FLAMMABLE
tableVariant = /obj/structure/table/wood/fancy
+ merge_type = /obj/item/stack/tile/carpet
/obj/item/stack/tile/carpet/black
name = "black carpet"
@@ -150,6 +155,7 @@
inhand_icon_state = "tile-carpet-black"
turf_type = /turf/open/floor/carpet/black
tableVariant = /obj/structure/table/wood/fancy/black
+ merge_type = /obj/item/stack/tile/carpet/black
/obj/item/stack/tile/carpet/blue
name = "blue carpet"
@@ -157,6 +163,7 @@
inhand_icon_state = "tile-carpet-blue"
turf_type = /turf/open/floor/carpet/blue
tableVariant = /obj/structure/table/wood/fancy/blue
+ merge_type = /obj/item/stack/tile/carpet/blue
/obj/item/stack/tile/carpet/cyan
name = "cyan carpet"
@@ -164,6 +171,7 @@
inhand_icon_state = "tile-carpet-cyan"
turf_type = /turf/open/floor/carpet/cyan
tableVariant = /obj/structure/table/wood/fancy/cyan
+ merge_type = /obj/item/stack/tile/carpet/cyan
/obj/item/stack/tile/carpet/green
name = "green carpet"
@@ -171,6 +179,7 @@
inhand_icon_state = "tile-carpet-green"
turf_type = /turf/open/floor/carpet/green
tableVariant = /obj/structure/table/wood/fancy/green
+ merge_type = /obj/item/stack/tile/carpet/green
/obj/item/stack/tile/carpet/orange
name = "orange carpet"
@@ -178,6 +187,7 @@
inhand_icon_state = "tile-carpet-orange"
turf_type = /turf/open/floor/carpet/orange
tableVariant = /obj/structure/table/wood/fancy/orange
+ merge_type = /obj/item/stack/tile/carpet/orange
/obj/item/stack/tile/carpet/purple
name = "purple carpet"
@@ -185,6 +195,7 @@
inhand_icon_state = "tile-carpet-purple"
turf_type = /turf/open/floor/carpet/purple
tableVariant = /obj/structure/table/wood/fancy/purple
+ merge_type = /obj/item/stack/tile/carpet/purple
/obj/item/stack/tile/carpet/red
name = "red carpet"
@@ -192,6 +203,7 @@
inhand_icon_state = "tile-carpet-red"
turf_type = /turf/open/floor/carpet/red
tableVariant = /obj/structure/table/wood/fancy/red
+ merge_type = /obj/item/stack/tile/carpet/red
/obj/item/stack/tile/carpet/royalblack
name = "royal black carpet"
@@ -199,6 +211,7 @@
inhand_icon_state = "tile-carpet-royalblack"
turf_type = /turf/open/floor/carpet/royalblack
tableVariant = /obj/structure/table/wood/fancy/royalblack
+ merge_type = /obj/item/stack/tile/carpet/royalblack
/obj/item/stack/tile/carpet/royalblue
name = "royal blue carpet"
@@ -206,24 +219,28 @@
inhand_icon_state = "tile-carpet-royalblue"
turf_type = /turf/open/floor/carpet/royalblue
tableVariant = /obj/structure/table/wood/fancy/royalblue
+ merge_type = /obj/item/stack/tile/carpet/royalblue
/obj/item/stack/tile/carpet/executive
name = "executive carpet"
icon_state = "tile_carpet_executive"
inhand_icon_state = "tile-carpet-royalblue"
turf_type = /turf/open/floor/carpet/executive
+ merge_type = /obj/item/stack/tile/carpet/executive
/obj/item/stack/tile/carpet/stellar
name = "stellar carpet"
icon_state = "tile_carpet_stellar"
inhand_icon_state = "tile-carpet-royalblue"
turf_type = /turf/open/floor/carpet/stellar
+ merge_type = /obj/item/stack/tile/carpet/stellar
/obj/item/stack/tile/carpet/donk
name = "donk co promotional carpet"
icon_state = "tile_carpet_donk"
inhand_icon_state = "tile-carpet-orange"
turf_type = /turf/open/floor/carpet/donk
+ merge_type = /obj/item/stack/tile/carpet/donk
/obj/item/stack/tile/carpet/fifty
amount = 50
@@ -311,6 +328,7 @@
icon_state = "tile_bcircuit"
inhand_icon_state = "tile-bcircuit"
turf_type = /turf/open/floor/circuit
+ merge_type = /obj/item/stack/tile/circuit
/obj/item/stack/tile/circuit/green
name = "green circuit tile"
@@ -319,9 +337,11 @@
icon_state = "tile_gcircuit"
inhand_icon_state = "tile-gcircuit"
turf_type = /turf/open/floor/circuit/green
+ merge_type = /obj/item/stack/tile/circuit/green
/obj/item/stack/tile/circuit/green/anim
turf_type = /turf/open/floor/circuit/green/anim
+ merge_type = /obj/item/stack/tile/circuit/green/anim
/obj/item/stack/tile/circuit/red
name = "red circuit tile"
@@ -330,9 +350,11 @@
icon_state = "tile_rcircuit"
inhand_icon_state = "tile-rcircuit"
turf_type = /turf/open/floor/circuit/red
+ merge_type = /obj/item/stack/tile/circuit/red
/obj/item/stack/tile/circuit/red/anim
turf_type = /turf/open/floor/circuit/red/anim
+ merge_type = /obj/item/stack/tile/circuit/red/anim
//Pod floor
/obj/item/stack/tile/pod
@@ -342,6 +364,7 @@
icon_state = "tile_pod"
inhand_icon_state = "tile-pod"
turf_type = /turf/open/floor/pod
+ merge_type = /obj/item/stack/tile/pod
/obj/item/stack/tile/pod/light
name = "light pod floor tile"
@@ -349,6 +372,7 @@
desc = "A lightly colored grooved floor tile."
icon_state = "tile_podlight"
turf_type = /turf/open/floor/pod/light
+ merge_type = /obj/item/stack/tile/pod/light
/obj/item/stack/tile/pod/dark
name = "dark pod floor tile"
@@ -356,6 +380,7 @@
desc = "A darkly colored grooved floor tile."
icon_state = "tile_poddark"
turf_type = /turf/open/floor/pod/dark
+ merge_type = /obj/item/stack/tile/pod/dark
//Plasteel (normal)
/obj/item/stack/tile/plasteel
@@ -375,6 +400,7 @@
matter_amount = 1
cost = 125
source = /datum/robot_energy_storage/metal
+ merge_type = /obj/item/stack/tile/plasteel
/obj/item/stack/tile/plastic
name = "plastic tile"
@@ -383,6 +409,7 @@
icon_state = "tile_plastic"
mats_per_unit = list(/datum/material/plastic=500)
turf_type = /turf/open/floor/plastic
+ merge_type = /obj/item/stack/tile/plastic
/obj/item/stack/tile/material
name = "floor tile"
@@ -392,6 +419,7 @@
icon_state = "material_tile"
turf_type = /turf/open/floor/material
material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS
+ merge_type = /obj/item/stack/tile/material
/obj/item/stack/tile/eighties
name = "retro tile"
@@ -399,6 +427,7 @@
desc = "A stack of floor tiles that remind you of an age of funk."
icon_state = "tile_eighties"
turf_type = /turf/open/floor/eighties
+ merge_type = /obj/item/stack/tile/eighties
/obj/item/stack/tile/eighties/loaded
amount = 15
diff --git a/code/game/objects/items/stacks/wrap.dm b/code/game/objects/items/stacks/wrap.dm
index d673021ee11..035618ff811 100644
--- a/code/game/objects/items/stacks/wrap.dm
+++ b/code/game/objects/items/stacks/wrap.dm
@@ -13,6 +13,7 @@
amount = 25
max_amount = 25
resistance_flags = FLAMMABLE
+ merge_type = /obj/item/stack/wrapping_paper
/obj/item/stack/wrapping_paper/use(used, transfer)
var/turf/T = get_turf(src)
@@ -23,6 +24,7 @@
/obj/item/stack/wrapping_paper/small
desc = "Wrap packages with this festive paper to make gifts. This roll looks a bit skimpy."
amount = 10
+ merge_type = /obj/item/stack/wrapping_paper/small
/*
* Package Wrap
@@ -39,6 +41,7 @@
max_amount = 25
resistance_flags = FLAMMABLE
grind_results = list(/datum/reagent/cellulose = 5)
+ merge_type = /obj/item/stack/package_wrap
/obj/item/stack/package_wrap/suicide_act(mob/living/user)
user.visible_message("[user] begins wrapping [user.p_them()]self in \the [src]! It looks like [user.p_theyre()] trying to commit suicide!")
@@ -128,6 +131,7 @@
desc = "You can use this to wrap items in. This roll looks a bit skimpy."
w_class = WEIGHT_CLASS_SMALL
amount = 5
+ merge_type = /obj/item/stack/package_wrap/small
/obj/item/c_tube
name = "cardboard tube"
diff --git a/code/modules/events/crystal_event.dm b/code/modules/events/crystal_event.dm
index cd9e15803a6..258e3a7b6d7 100644
--- a/code/modules/events/crystal_event.dm
+++ b/code/modules/events/crystal_event.dm
@@ -477,6 +477,7 @@ This section is for the crystal stabilizer item and the crystal from the closed
singular_name = "otherworld crystal"
icon = 'icons/obj/stack_objects.dmi'
material_type = /datum/material/otherworld_crystal
+ merge_type = /obj/item/stack/sheet/otherworld_crystal
/*
This section is for the signaler part of the crystal portals
diff --git a/code/modules/mining/ores_coins.dm b/code/modules/mining/ores_coins.dm
index 557aeda6b78..a0d6e521f35 100644
--- a/code/modules/mining/ores_coins.dm
+++ b/code/modules/mining/ores_coins.dm
@@ -78,6 +78,7 @@
mine_experience = 6
scan_state = "rock_Uranium"
spreadChance = 5
+ merge_type = /obj/item/stack/ore/uranium
/obj/item/stack/ore/iron
name = "iron ore"
@@ -90,6 +91,7 @@
mine_experience = 1
scan_state = "rock_Iron"
spreadChance = 20
+ merge_type = /obj/item/stack/ore/iron
/obj/item/stack/ore/glass
name = "sand pile"
@@ -101,6 +103,7 @@
refined_type = /obj/item/stack/sheet/glass
w_class = WEIGHT_CLASS_TINY
mine_experience = 0 //its sand
+ merge_type = /obj/item/stack/ore/glass
GLOBAL_LIST_INIT(sand_recipes, list(\
new /datum/stack_recipe("sandstone", /obj/item/stack/sheet/mineral/sandstone, 1, 1, 50),\
@@ -135,6 +138,7 @@ GLOBAL_LIST_INIT(sand_recipes, list(\
inhand_icon_state = "volcanic_sand"
singular_name = "volcanic ash pile"
mine_experience = 0
+ merge_type = /obj/item/stack/ore/glass/basalt
/obj/item/stack/ore/plasma
name = "plasma ore"
@@ -147,12 +151,12 @@ GLOBAL_LIST_INIT(sand_recipes, list(\
mine_experience = 5
scan_state = "rock_Plasma"
spreadChance = 8
+ merge_type = /obj/item/stack/ore/plasma
/obj/item/stack/ore/plasma/welder_act(mob/living/user, obj/item/I)
to_chat(user, "You can't hit a high enough temperature to smelt [src] properly!")
return TRUE
-
/obj/item/stack/ore/silver
name = "silver ore"
icon_state = "Silver ore"
@@ -164,6 +168,7 @@ GLOBAL_LIST_INIT(sand_recipes, list(\
refined_type = /obj/item/stack/sheet/mineral/silver
scan_state = "rock_Silver"
spreadChance = 5
+ merge_type = /obj/item/stack/ore/silver
/obj/item/stack/ore/gold
name = "gold ore"
@@ -176,6 +181,7 @@ GLOBAL_LIST_INIT(sand_recipes, list(\
refined_type = /obj/item/stack/sheet/mineral/gold
scan_state = "rock_Gold"
spreadChance = 5
+ merge_type = /obj/item/stack/ore/gold
/obj/item/stack/ore/diamond
name = "diamond ore"
@@ -187,6 +193,7 @@ GLOBAL_LIST_INIT(sand_recipes, list(\
refined_type = /obj/item/stack/sheet/mineral/diamond
mine_experience = 10
scan_state = "rock_Diamond"
+ merge_type = /obj/item/stack/ore/diamond
/obj/item/stack/ore/bananium
name = "bananium ore"
@@ -198,6 +205,7 @@ GLOBAL_LIST_INIT(sand_recipes, list(\
refined_type = /obj/item/stack/sheet/mineral/bananium
mine_experience = 15
scan_state = "rock_Bananium"
+ merge_type = /obj/item/stack/ore/bananium
/obj/item/stack/ore/titanium
name = "titanium ore"
@@ -210,6 +218,7 @@ GLOBAL_LIST_INIT(sand_recipes, list(\
mine_experience = 3
scan_state = "rock_Titanium"
spreadChance = 5
+ merge_type = /obj/item/stack/ore/titanium
/obj/item/stack/ore/slag
name = "slag"
@@ -217,6 +226,7 @@ GLOBAL_LIST_INIT(sand_recipes, list(\
icon_state = "slag"
inhand_icon_state = "slag"
singular_name = "slag chunk"
+ merge_type = /obj/item/stack/ore/slag
/obj/item/gibtonite
name = "gibtonite ore"
diff --git a/code/modules/recycling/conveyor2.dm b/code/modules/recycling/conveyor2.dm
index d968700ed6c..21e5c69996d 100644
--- a/code/modules/recycling/conveyor2.dm
+++ b/code/modules/recycling/conveyor2.dm
@@ -421,6 +421,7 @@ GLOBAL_LIST_EMPTY(conveyors_by_id)
max_amount = 30
singular_name = "conveyor belt"
w_class = WEIGHT_CLASS_BULKY
+ merge_type = /obj/item/stack/conveyor
///id for linking
var/id = ""
diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm
index a2ad651e4eb..846b669dce9 100644
--- a/code/modules/research/xenobiology/xenobiology.dm
+++ b/code/modules/research/xenobiology/xenobiology.dm
@@ -1044,7 +1044,7 @@
flags_1 = CONDUCT_1
max_amount = 60
turf_type = /turf/open/floor/bluespace
-
+ merge_type = /obj/item/stack/tile/bluespace
/obj/item/stack/tile/sepia
name = "sepia floor tile"
@@ -1061,7 +1061,7 @@
flags_1 = CONDUCT_1
max_amount = 60
turf_type = /turf/open/floor/sepia
-
+ merge_type = /obj/item/stack/tile/sepia
/obj/item/areaeditor/blueprints/slime
name = "cerulean prints"
diff --git a/code/modules/unit_tests/_unit_tests.dm b/code/modules/unit_tests/_unit_tests.dm
index 95f2639a912..444b7a8a47f 100644
--- a/code/modules/unit_tests/_unit_tests.dm
+++ b/code/modules/unit_tests/_unit_tests.dm
@@ -45,6 +45,7 @@
#include "keybinding_init.dm"
#include "machine_disassembly.dm"
#include "medical_wounds.dm"
+#include "merge_type.dm"
#include "metabolizing.dm"
#include "outfit_sanity.dm"
#include "pills.dm"
diff --git a/code/modules/unit_tests/merge_type.dm b/code/modules/unit_tests/merge_type.dm
new file mode 100644
index 00000000000..bd653bf1263
--- /dev/null
+++ b/code/modules/unit_tests/merge_type.dm
@@ -0,0 +1,15 @@
+/datum/unit_test/merge_type/Run()
+ var/list/blacklist = list(/obj/item/stack/sheet,
+ /obj/item/stack/sheet/mineral,
+ /obj/item/stack/ore,
+ /obj/item/stack/spacecash,
+ /obj/item/stack/license_plates,
+ /obj/item/stack/tile/mineral,
+ /obj/item/stack/tile)
+
+ var/list/paths = subtypesof(/obj/item/stack) - blacklist
+
+ for(var/stackpath in paths)
+ var/obj/item/stack/stack = stackpath
+ if(!initial(stack.merge_type))
+ Fail("([stack]) lacks set merge_type variable!")