diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index 108d70c0b91..6a61416366e 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -197,7 +197,7 @@
QDEL_NULL(proximity_monitor)
QDEL_NULL(language_holder)
-
+
unbuckle_all_mobs(force=1)
. = ..()
@@ -686,3 +686,10 @@
//Returns an atom's power cell, if it has one. Overload for individual items.
/atom/movable/proc/get_cell()
return
+
+/atom/movable/proc/can_be_pulled(user)
+ if(src == user || !isturf(loc))
+ return FALSE
+ if(anchored || throwing)
+ return FALSE
+ return TRUE
\ No newline at end of file
diff --git a/code/game/gamemodes/objective_items.dm b/code/game/gamemodes/objective_items.dm
index 72baa586c74..703f1a9760c 100644
--- a/code/game/gamemodes/objective_items.dm
+++ b/code/game/gamemodes/objective_items.dm
@@ -83,6 +83,16 @@
/datum/objective_item/steal/nuke_core/New()
special_equipment += /obj/item/weapon/storage/box/syndie_kit/nuke
+ ..()
+
+/datum/objective_item/steal/supermatter
+ name = "a sliver of a supermatter crystal. Be sure to use the proper safety equipment when extracting the sliver!"
+ targetitem = /obj/item/nuke_core/supermatter_sliver
+ difficulty = 15
+
+/datum/objective_item/steal/supermatter/New()
+ special_equipment += /obj/item/weapon/storage/box/syndie_kit/supermatter
+ ..()
//Items with special checks!
/datum/objective_item/steal/plasma
diff --git a/code/game/objects/items/nuke_tools.dm b/code/game/objects/items/nuke_tools.dm
deleted file mode 100644
index 40c7887914c..00000000000
--- a/code/game/objects/items/nuke_tools.dm
+++ /dev/null
@@ -1,83 +0,0 @@
-//Items for nuke theft traitor objective
-
-//the nuke core - objective item
-/obj/item/nuke_core
- name = "plutonium core"
- desc = "Extremely radioactive. Wear goggles."
- icon = 'icons/obj/nuke_tools.dmi'
- icon_state = "plutonium_core"
- item_state = "plutoniumcore"
- resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
- var/pulse = 0
- var/cooldown = 0
-
-/obj/item/nuke_core/New()
- ..()
- START_PROCESSING(SSobj, src)
-
-/obj/item/nuke_core/attackby(obj/item/nuke_core_container/container, mob/user)
- if(istype(container))
- container.load(src, user)
- else
- return ..()
-
-/obj/item/nuke_core/process()
- if(cooldown < world.time - 60)
- cooldown = world.time
- flick("plutonium_core_pulse", src)
- radiation_pulse(get_turf(src), 1, 4, 40, 1)
-
-//nuke core box, for carrying the core
-/obj/item/nuke_core_container
- name = "nuke core container"
- desc = "Solid container for radioactive objects."
- icon = 'icons/obj/nuke_tools.dmi'
- icon_state = "core_container_empty"
- item_state = "tile"
- var/obj/item/nuke_core/core = null
-
-/obj/item/nuke_core_container/proc/load(obj/item/nuke_core/ncore, mob/user)
- if(core || !istype(ncore))
- return 0
- ncore.forceMove(src)
- core = ncore
- icon_state = "core_container_loaded"
- to_chat(user, "Container is sealing...")
- addtimer(CALLBACK(src, .proc/seal), 50)
- return 1
-
-/obj/item/nuke_core_container/proc/seal()
- if(istype(core))
- STOP_PROCESSING(SSobj, core)
- icon_state = "core_container_sealed"
- playsound(loc, 'sound/items/deconstruct.ogg', 60, 1)
- if(ismob(loc))
- to_chat(loc, "[src] is permanently sealed, [core]'s radiation is contained.")
-
-/obj/item/nuke_core_container/attackby(obj/item/nuke_core/core, mob/user)
- if(istype(core))
- if(!user.temporarilyRemoveItemFromInventory(core))
- to_chat(user, "The [core] is stuck to your hand!")
- return
- else
- load(core, user)
- else
- return ..()
-
-//snowflake screwdriver, works as a key to start nuke theft, traitor only
-/obj/item/weapon/screwdriver/nuke
- name = "screwdriver"
- desc = "A screwdriver with an ultra thin tip."
- icon = 'icons/obj/nuke_tools.dmi'
- icon_state = "screwdriver_nuke"
- toolspeed = 0.5
-
-/obj/item/weapon/paper/nuke_instructions
- info = "How to break into a Nanotrasen self-destruct terminal and remove its plutonium core:
\
-
\
- - Use a screwdriver with a very thin tip (provided) to unscrew the terminal's front panel
\
- - Dislodge and remove the front panel with a crowbar
\
- - Cut the inner metal plate with a welding tool
\
- - Pry off the inner plate with a crowbar to expose the radioactive core
\
- - Use the core container to remove the plutonium core; the container will take some time to seal
\
- - ???
"
diff --git a/code/game/objects/items/theft_tools.dm b/code/game/objects/items/theft_tools.dm
new file mode 100644
index 00000000000..ec82a376ade
--- /dev/null
+++ b/code/game/objects/items/theft_tools.dm
@@ -0,0 +1,243 @@
+//Items for nuke theft, supermatter theft traitor objective
+
+
+// STEALING THE NUKE
+
+//the nuke core - objective item
+/obj/item/nuke_core
+ name = "plutonium core"
+ desc = "Extremely radioactive. Wear goggles."
+ icon = 'icons/obj/nuke_tools.dmi'
+ icon_state = "plutonium_core"
+ item_state = "plutoniumcore"
+ resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
+ var/pulse = 0
+ var/cooldown = 0
+ var/pulseicon = "plutonium_core_pulse"
+
+/obj/item/nuke_core/Initialize()
+ . = ..()
+ START_PROCESSING(SSobj, src)
+
+/obj/item/nuke_core/Destroy()
+ STOP_PROCESSING(SSobj, src)
+ return ..()
+
+/obj/item/nuke_core/attackby(obj/item/nuke_core_container/container, mob/user)
+ if(istype(container))
+ container.load(src, user)
+ else
+ return ..()
+
+/obj/item/nuke_core/process()
+ if(cooldown < world.time - 60)
+ cooldown = world.time
+ flick(pulseicon, src)
+ radiation_pulse(get_turf(src), 1, 4, 40, 1)
+
+//nuke core box, for carrying the core
+/obj/item/nuke_core_container
+ name = "nuke core container"
+ desc = "Solid container for radioactive objects."
+ icon = 'icons/obj/nuke_tools.dmi'
+ icon_state = "core_container_empty"
+ item_state = "tile"
+ var/obj/item/nuke_core/core
+
+/obj/item/nuke_core_container/Destroy()
+ QDEL_NULL(core)
+ return ..()
+
+/obj/item/nuke_core_container/proc/load(obj/item/nuke_core/ncore, mob/user)
+ if(core || !istype(ncore))
+ return FALSE
+ ncore.forceMove(src)
+ core = ncore
+ icon_state = "core_container_loaded"
+ to_chat(user, "Container is sealing...")
+ addtimer(CALLBACK(src, .proc/seal), 50)
+ return TRUE
+
+/obj/item/nuke_core_container/proc/seal()
+ if(istype(core))
+ STOP_PROCESSING(SSobj, core)
+ icon_state = "core_container_sealed"
+ playsound(src, 'sound/items/deconstruct.ogg', 60, 1)
+ if(ismob(loc))
+ to_chat(loc, "[src] is permanently sealed, [core]'s radiation is contained.")
+
+/obj/item/nuke_core_container/attackby(obj/item/nuke_core/core, mob/user)
+ if(istype(core))
+ if(!user.temporarilyRemoveItemFromInventory(core))
+ to_chat(user, "The [core] is stuck to your hand!")
+ return
+ else
+ load(core, user)
+ else
+ return ..()
+
+//snowflake screwdriver, works as a key to start nuke theft, traitor only
+/obj/item/weapon/screwdriver/nuke
+ name = "screwdriver"
+ desc = "A screwdriver with an ultra thin tip."
+ icon = 'icons/obj/nuke_tools.dmi'
+ icon_state = "screwdriver_nuke"
+ toolspeed = 0.5
+
+/obj/item/weapon/paper/nuke_instructions
+ info = "How to break into a Nanotrasen self-destruct terminal and remove its plutonium core:
\
+ \
+ - Use a screwdriver with a very thin tip (provided) to unscrew the terminal's front panel
\
+ - Dislodge and remove the front panel with a crowbar
\
+ - Cut the inner metal plate with a welding tool
\
+ - Pry off the inner plate with a crowbar to expose the radioactive core
\
+ - Use the core container to remove the plutonium core; the container will take some time to seal
\
+ - ???
\
+
"
+
+// STEALING SUPERMATTER
+
+/obj/item/weapon/paper/supermatter_sliver_instructions
+ info = "How to safely extract a supermatter sliver:
\
+ \
+ - Approach an active supermatter crystal with proper protective gear. DO NOT MAKE PHYSICAL CONTACT.
\
+ - Use a supermatter scalpel (provided) to slice off a sliver of the crystal.
\
+ - Use supermatter extraction tongs (also provided) to safely remove the sliver.
\
+ - Physical contact of any object with the sliver will dust the object, as well as yourself.
\
+ - Use the tongs to place the sliver into the provided container, which will take some time to seal
\
+ - Get the hell out before the crystal delaminates.
\
+ - ???
\
+
"
+
+/obj/item/nuke_core/supermatter_sliver
+ name = "supermatter sliver"
+ desc = "A tiny, highly volatile sliver of a supermatter crystal. Do not handle without protection!"
+ icon_state = "supermatter_sliver"
+ item_state = "supermattersliver"
+ pulseicon = "supermatter_sliver_pulse"
+
+/obj/item/nuke_core/supermatter_sliver/attack_tk() // no TK dusting memes
+ return FALSE
+
+/obj/item/nuke_core/supermatter_sliver/can_be_pulled(user) // no drag memes
+ return FALSE
+
+/obj/item/nuke_core/supermatter_sliver/attackby(obj/item/W, mob/living/user, params)
+ if(istype(W, /obj/item/weapon/hemostat/supermatter))
+ var/obj/item/weapon/hemostat/supermatter/tongs = W
+ if (tongs.sliver)
+ to_chat(user, "\The [tongs] is already holding a supermatter sliver!")
+ return FALSE
+ forceMove(tongs)
+ tongs.sliver = src
+ tongs.icon_state = "supermatter_tongs_loaded"
+ to_chat(user, "You carefully pick up [src] with [tongs].")
+ else if(istype(W, /obj/item/weapon/scalpel/supermatter) || istype(W, /obj/item/nuke_core_container/supermatter/)) // we don't want it to dust
+ return
+ else
+ to_chat(user, "As it touches \the [src], both \the [src] and \the [W] burst into dust!")
+ radiation_pulse(get_turf(user), 1, 2, 10, 1)
+ playsound(src, 'sound/effects/supermatter.ogg', 50, 1)
+ qdel(W)
+ qdel(src)
+
+/obj/item/nuke_core/supermatter_sliver/pickup(mob/living/user)
+ ..()
+ if(!iscarbon(user))
+ return FALSE
+ var/mob/ded = user
+ to_chat(user, "You reach for the supermatter sliver with your hands. That was dumb.")
+ radiation_pulse(get_turf(user), 2, 4, 50, 1)
+ playsound(get_turf(user), 'sound/effects/supermatter.ogg', 50, 1)
+ ded.dust()
+
+/obj/item/nuke_core_container/supermatter
+ name = "supermatter bin"
+ desc = "A tiny receptacle that releases an inert freon mix upon sealing, allowing a sliver of a supermatter crystal to be safely stored.."
+ var/obj/item/nuke_core/supermatter_sliver/sliver
+
+/obj/item/nuke_core_container/supermatter/Destroy()
+ QDEL_NULL(sliver)
+ return ..()
+
+/obj/item/nuke_core_container/supermatter/load(obj/item/weapon/hemostat/supermatter/T, mob/user)
+ if(!istype(T) || !T.sliver)
+ return FALSE
+ T.sliver.forceMove(src)
+ sliver = T.sliver
+ T.sliver = null
+ icon_state = "core_container_loaded"
+ to_chat(user, "Container is sealing...")
+ addtimer(CALLBACK(src, .proc/seal), 50)
+ return TRUE
+
+/obj/item/nuke_core_container/supermatter/seal()
+ if(istype(sliver))
+ STOP_PROCESSING(SSobj, sliver)
+ icon_state = "core_container_sealed"
+ playsound(src, 'sound/items/Deconstruct.ogg', 60, 1)
+ if(ismob(loc))
+ to_chat(loc, "[src] is permanently sealed, [sliver] is safely contained.")
+
+/obj/item/nuke_core_container/supermatter/attackby(obj/item/weapon/hemostat/supermatter/tongs, mob/user)
+ if(istype(tongs))
+ if(!user.temporarilyRemoveItemFromInventory(tongs))
+ to_chat(user, "\The [tongs] is stuck to your hand!")
+ else
+ load(sliver, user)
+ else
+ return ..()
+
+/obj/item/weapon/scalpel/supermatter
+ name = "supermatter scalpel"
+ desc = "A scalpel with a tip of condensed freon gas, searingly cold to the touch, that can safely shave a sliver off a supermatter crystal."
+ icon = 'icons/obj/nuke_tools.dmi'
+ icon_state = "supermatter_scalpel"
+ toolspeed = 0.5
+ damtype = "fire"
+ usesound = 'sound/weapons/bladeslice.ogg'
+
+/obj/item/weapon/hemostat/supermatter
+ name = "supermatter extraction tongs"
+ desc = "A pair of tongs made from condensed freon gas, searingly cold to the touch, that can safely grip a supermatter sliver."
+ icon = 'icons/obj/nuke_tools.dmi'
+ icon_state = "supermatter_tongs"
+ toolspeed = 0.75
+ damtype = "fire"
+ var/obj/item/nuke_core/supermatter_sliver/sliver
+
+/obj/item/weapon/hemostat/supermatter/Destroy()
+ QDEL_NULL(sliver)
+ return ..()
+
+/obj/item/weapon/hemostat/supermatter/afterattack(atom/O, mob/user, proximity)
+ if(!sliver)
+ return
+ if(ismovableatom(O))
+ Consume(O)
+
+/obj/item/weapon/hemostat/supermatter/throw_impact(atom/hit_atom) // no instakill supermatter javelins
+ if(sliver)
+ sliver.forceMove(loc)
+ to_chat(usr, "\The [sliver] falls out of \the [src] as you throw them.")
+ sliver = null
+ ..()
+
+/obj/item/weapon/hemostat/supermatter/proc/Consume(atom/movable/AM, mob/user)
+ if(ismob(AM))
+ var/mob/victim = AM
+ victim.dust()
+ message_admins("[src] has consumed [key_name_admin(victim)] [ADMIN_JMP(src)].")
+ investigate_log("has consumed [key_name(victim)].", "supermatter")
+ else
+ investigate_log("has consumed [AM].", "supermatter")
+ qdel(AM)
+ user.visible_message("As [user] touches \the [AM] with \a [src], silence fills the room...",\
+ "You touch \the [AM] with \the [src], and everything suddenly goes silent.\n\The [AM] flashes into dust, and soon as you can register this, you do as well.",\
+ "Everything suddenly goes silent.")
+ radiation_pulse(get_turf(user), 2, 4, 50, 1)
+ playsound(src, 'sound/effects/supermatter.ogg', 50, 1)
+ user.dust()
+ icon_state = "supermatter_tongs"
+ QDEL_NULL(sliver)
+
diff --git a/code/game/objects/items/weapons/storage/uplink_kits.dm b/code/game/objects/items/weapons/storage/uplink_kits.dm
index 6dc32122e6f..c80f9cf08f2 100644
--- a/code/game/objects/items/weapons/storage/uplink_kits.dm
+++ b/code/game/objects/items/weapons/storage/uplink_kits.dm
@@ -238,6 +238,15 @@
new /obj/item/nuke_core_container(src)
new /obj/item/weapon/paper/nuke_instructions(src)
+/obj/item/weapon/storage/box/syndie_kit/supermatter
+ name = "box"
+
+/obj/item/weapon/storage/box/syndie_kit/supermatter/PopulateContents()
+ new /obj/item/weapon/scalpel/supermatter(src)
+ new /obj/item/weapon/hemostat/supermatter(src)
+ new /obj/item/nuke_core_container/supermatter(src)
+ new /obj/item/weapon/paper/supermatter_sliver_instructions(src)
+
/obj/item/weapon/storage/box/syndie_kit/tuberculosisgrenade
name = "boxed virus grenade kit"
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index e9ed212fd10..e3b0673cece 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -928,3 +928,6 @@
if((movement_type & FLYING) && !stat)
return
..()
+
+/mob/living/can_be_pulled()
+ return ..() && !(buckled && buckled.buckle_prevents_pull)
\ No newline at end of file
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 80956cf08f5..36344adf242 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -306,17 +306,11 @@
//this and stop_pulling really ought to be /mob/living procs
/mob/proc/start_pulling(atom/movable/AM, supress_message = 0)
if(!AM || !src)
- return
- if(AM == src || !isturf(AM.loc))
- return
- if(AM.anchored || AM.throwing)
- return
- if(isliving(AM))
- var/mob/living/L = AM
- if(L.buckled && L.buckled.buckle_prevents_pull)
- return
+ return FALSE
+ if(!(AM.can_be_pulled(src)))
+ return FALSE
if(throwing || incapacitated())
- return
+ return FALSE
AM.add_fingerprint(src)
diff --git a/code/modules/power/supermatter/supermatter.dm b/code/modules/power/supermatter/supermatter.dm
index df309c72523..e7c255212ab 100644
--- a/code/modules/power/supermatter/supermatter.dm
+++ b/code/modules/power/supermatter/supermatter.dm
@@ -464,7 +464,14 @@
/obj/machinery/power/supermatter_shard/attackby(obj/item/W, mob/living/user, params)
if(!istype(W) || (W.flags & ABSTRACT) || !istype(user))
return
- if(user.drop_item(W))
+ if(istype(W, /obj/item/weapon/scalpel/supermatter))
+ playsound(src, W.usesound, 100, 1)
+ to_chat(user, "You carefully begin to scrape \the [src] with \the [W]...")
+ if(do_after(user, 60 * W.toolspeed, TRUE, src))
+ to_chat(user, "You extract a sliver from \the [src]. \The [src] begins to react violently!")
+ new /obj/item/nuke_core/supermatter_sliver(user.loc)
+ matter_power += 200
+ else if(user.dropItemToGround(W))
user.visible_message("As [user] touches \the [src] with \a [W], silence fills the room...",\
"You touch \the [src] with \the [W], and everything suddenly goes silent.\n\The [W] flashes into dust as you flinch away from \the [src].",\
"Everything suddenly goes silent.")
diff --git a/icons/obj/nuke_tools.dmi b/icons/obj/nuke_tools.dmi
index 11f90a3825a..2c10b5424ff 100644
Binary files a/icons/obj/nuke_tools.dmi and b/icons/obj/nuke_tools.dmi differ
diff --git a/tgstation.dme b/tgstation.dme
index e9f5b8b5218..1a78510eee9 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -724,10 +724,10 @@
#include "code\game\objects\items\documents.dm"
#include "code\game\objects\items\eightball.dm"
#include "code\game\objects\items\latexballoon.dm"
-#include "code\game\objects\items\nuke_tools.dm"
#include "code\game\objects\items\religion.dm"
#include "code\game\objects\items\shooting_range.dm"
#include "code\game\objects\items\taster.dm"
+#include "code\game\objects\items\theft_tools.dm"
#include "code\game\objects\items\toys.dm"
#include "code\game\objects\items\trash.dm"
#include "code\game\objects\items\devices\aicard.dm"
diff --git a/tools/tgstation-server b/tools/tgstation-server
index 8c6d31f3942..979d00ea6f9 160000
--- a/tools/tgstation-server
+++ b/tools/tgstation-server
@@ -1 +1 @@
-Subproject commit 8c6d31f3942e5837fcc7b8111cda8ab1cbc7a5c3
+Subproject commit 979d00ea6f98ecb5699f55c83cc7a921b47a9803