diff --git a/code/game/objects/items/poi_items.dm b/code/game/objects/items/poi_items.dm
index 85a8b27854..394212e4c4 100644
--- a/code/game/objects/items/poi_items.dm
+++ b/code/game/objects/items/poi_items.dm
@@ -52,8 +52,9 @@
/obj/structure/largecrate/animal/crashedshuttle
name = "SCP"
+
/obj/structure/largecrate/animal/crashedshuttle/initialize()
- starts_with = pick(/mob/living/simple_animal/hostile/statue, /obj/item/cursed_marble)
+ starts_with = pick(/mob/living/simple_animal/hostile/statue, /obj/item/cursed_marble, /obj/item/weapon/deadringer)
name = pick("Spicy Crust Pizzeria", "Soap and Care Products", "Sally's Computer Parts", "Steve's Chocolate Pastries", "Smith & Christian's Plastics","Standard Containers & Packaging Co.", "Sanitary Chemical Purgation (LTD)")
name += " delivery crate"
return ..()
diff --git a/code/modules/artifice/deadringer.dm b/code/modules/artifice/deadringer.dm
new file mode 100644
index 0000000000..99061b6624
--- /dev/null
+++ b/code/modules/artifice/deadringer.dm
@@ -0,0 +1,184 @@
+/obj/item/weapon/deadringer
+ name = "silver pocket watch"
+ desc = "A fancy silver-plated digital pocket watch. Looks expensive."
+ icon = 'icons/obj/deadringer.dmi'
+ icon_state = "deadringer"
+ w_class = ITEMSIZE_SMALL
+ slot_flags = SLOT_ID | SLOT_BELT | SLOT_TIE
+ origin_tech = list(TECH_ILLEGAL = 3)
+ var/activated = 0
+ var/timer = 0
+ var/bruteloss_prev = 999999
+ var/fireloss_prev = 999999
+ var/mob/living/carbon/human/corpse = null
+ var/mob/living/carbon/human/watchowner = null
+
+
+/obj/item/weapon/deadringer/New()
+ ..()
+ processing_objects |= src
+
+/obj/item/weapon/deadringer/Destroy() //just in case some smartass tries to stay invisible by destroying the watch
+ uncloak()
+ processing_objects -= src
+ ..()
+
+
+/obj/item/weapon/deadringer/dropped()
+ if(timer > 20)
+ uncloak()
+ watchowner = null
+ return
+
+/obj/item/weapon/deadringer/attack_self(var/mob/living/user as mob)
+ var/mob/living/H = src.loc
+ if (!istype(H, /mob/living/carbon/human))
+ to_chat(H,"You have no clue what to do with this thing.")
+ return
+ if(!activated)
+ if(timer == 0)
+ to_chat(H, "You press a small button on [src]'s side. It starts to hum quietly.")
+ bruteloss_prev = H.getBruteLoss()
+ fireloss_prev = H.getFireLoss()
+ activated = 1
+ return
+ else
+ to_chat(H,"You press a small button on [src]'s side. It buzzes a little.")
+ return
+ if(activated)
+ to_chat(H,"You press a small button on [src]'s side. It stops humming.")
+ activated = 0
+ return
+
+
+/obj/item/weapon/deadringer/process()
+ if(activated)
+ if (ismob(src.loc))
+ var/mob/living/carbon/human/H = src.loc
+ watchowner = H
+ if(H.getBruteLoss() > bruteloss_prev || H.getFireLoss() > fireloss_prev)
+ deathprevent()
+ activated = 0
+ if(watchowner.isSynthetic())
+ to_chat(watchowner, "You fade into nothingness! [src]'s screen blinks, being unable to copy your synthetic body!")
+ else
+ to_chat(watchowner, "You fade into nothingness, leaving behind a fake body!")
+ icon_state = "deadringer_cd"
+ timer = 50
+ return
+ if(timer > 0)
+ timer--
+ if(timer == 20)
+ uncloak()
+ if(corpse)
+ new /obj/effect/effect/smoke/chem(corpse.loc)
+ qdel(corpse)
+ if(timer == 0)
+ icon_state = "deadringer"
+ return
+
+
+/obj/item/weapon/deadringer/proc/deathprevent()
+ for(var/mob/living/simple_animal/D in oviewers(7, src))
+ D.LoseTarget()
+ watchowner.emote("deathgasp")
+ watchowner.invisibility = 85
+ watchowner.alpha = 127
+ makeacorpse(watchowner)
+ for(var/mob/living/simple_animal/D in oviewers(7, src))
+ D.LoseTarget()
+ return
+
+/obj/item/weapon/deadringer/proc/uncloak()
+ if(watchowner)
+ watchowner.invisibility = 0
+ watchowner.alpha = 255
+ playsound(get_turf(src), 'sound/effects/uncloak.ogg', 35, 1, -1)
+ return
+
+/obj/item/weapon/deadringer/proc/makeacorpse(var/mob/living/carbon/human/H)
+ if(H.isSynthetic())
+ return
+ corpse = new /mob/living/carbon/human(H.loc)
+ corpse.setDNA(H.dna.Clone())
+ corpse.death(1) //Kills the new mob
+ var/obj/item/clothing/temp = null
+ if(H.get_equipped_item(slot_w_uniform))
+ corpse.equip_to_slot_or_del(new /obj/item/clothing/under/chameleon/changeling(corpse), slot_w_uniform)
+ temp = corpse.get_equipped_item(slot_w_uniform)
+ var/obj/item/clothing/c_type = H.get_equipped_item(slot_w_uniform)
+ temp.disguise(c_type.type)
+ temp.canremove = 0
+ if(H.get_equipped_item(slot_wear_suit))
+ corpse.equip_to_slot_or_del(new /obj/item/clothing/suit/chameleon/changeling(corpse), slot_wear_suit)
+ temp = corpse.get_equipped_item(slot_wear_suit)
+ var/obj/item/clothing/c_type = H.get_equipped_item(slot_wear_suit)
+ temp.disguise(c_type.type)
+ temp.canremove = 0
+ if(H.get_equipped_item(slot_shoes))
+ corpse.equip_to_slot_or_del(new /obj/item/clothing/shoes/chameleon/changeling(corpse), slot_shoes)
+ temp = corpse.get_equipped_item(slot_shoes)
+ var/obj/item/clothing/c_type = H.get_equipped_item(slot_shoes)
+ temp.disguise(c_type.type)
+ temp.canremove = 0
+ if(H.get_equipped_item(slot_gloves))
+ corpse.equip_to_slot_or_del(new /obj/item/clothing/gloves/chameleon/changeling(corpse), slot_gloves)
+ temp = corpse.get_equipped_item(slot_gloves)
+ var/obj/item/clothing/c_type = H.get_equipped_item(slot_gloves)
+ temp.disguise(c_type.type)
+ temp.canremove = 0
+ if(H.get_equipped_item(slot_l_ear))
+ temp = H.get_equipped_item(slot_l_ear)
+ corpse.equip_to_slot_or_del(new temp.type(corpse), slot_l_ear)
+ temp = corpse.get_equipped_item(slot_l_ear)
+ temp.canremove = 0
+ if(H.get_equipped_item(slot_glasses))
+ corpse.equip_to_slot_or_del(new /obj/item/clothing/glasses/chameleon/changeling(corpse), slot_glasses)
+ temp = corpse.get_equipped_item(slot_glasses)
+ var/obj/item/clothing/c_type = H.get_equipped_item(slot_glasses)
+ temp.disguise(c_type.type)
+ temp.canremove = 0
+ if(H.get_equipped_item(slot_wear_mask))
+ corpse.equip_to_slot_or_del(new /obj/item/clothing/mask/chameleon/changeling(corpse), slot_wear_mask)
+ temp = corpse.get_equipped_item(slot_wear_mask)
+ var/obj/item/clothing/c_type = H.get_equipped_item(slot_wear_mask)
+ temp.disguise(c_type.type)
+ temp.canremove = 0
+ if(H.get_equipped_item(slot_head))
+ corpse.equip_to_slot_or_del(new /obj/item/clothing/head/chameleon/changeling(corpse), slot_head)
+ temp = corpse.get_equipped_item(slot_head)
+ var/obj/item/clothing/c_type = H.get_equipped_item(slot_head)
+ temp.disguise(c_type.type)
+ temp.canremove = 0
+ if(H.get_equipped_item(slot_belt))
+ corpse.equip_to_slot_or_del(new /obj/item/weapon/storage/belt/chameleon/changeling(corpse), slot_belt)
+ temp = corpse.get_equipped_item(slot_belt)
+ var/obj/item/clothing/c_type = H.get_equipped_item(slot_belt)
+ temp.disguise(c_type.type)
+ temp.canremove = 0
+ if(H.get_equipped_item(slot_back))
+ corpse.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/chameleon/changeling(corpse), slot_back)
+ temp = corpse.get_equipped_item(slot_back)
+ var/obj/item/clothing/c_type = H.get_equipped_item(slot_back)
+ temp.disguise(c_type.type)
+ temp.canremove = 0
+ corpse.identifying_gender = H.identifying_gender
+ corpse.flavor_texts = H.flavor_texts.Copy()
+ corpse.real_name = H.real_name
+ corpse.name = H.name
+ corpse.set_species(corpse.dna.species)
+ corpse.change_hair(H.h_style)
+ corpse.change_facial_hair(H.f_style)
+ corpse.change_hair_color(H.r_hair, H.g_hair, H.b_hair)
+ corpse.change_facial_hair_color(H.r_facial, H.g_facial, H.b_facial)
+ corpse.change_skin_color(H.r_skin, H.g_skin, H.b_skin)
+ corpse.adjustFireLoss(H.getFireLoss())
+ corpse.adjustBruteLoss(H.getBruteLoss())
+ corpse.UpdateAppearance()
+ corpse.regenerate_icons()
+ for(var/obj/item/organ/internal/I in corpse.internal_organs)
+ var/obj/item/organ/internal/G = I
+ G.Destroy()
+ return
+
+
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index 566af1d805..6eb4f22164 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -796,6 +796,8 @@
var/mob/living/L = target_mob
if(L.stat != DEAD)
return 1
+ if(L.invisibility < INVISIBILITY_LEVEL_ONE)
+ return 1
if (istype(target_mob,/obj/mecha))
var/obj/mecha/M = target_mob
if (M.occupant)
@@ -915,6 +917,8 @@
continue
else if(L in friends)
continue
+ else if(L.invisibility >= INVISIBILITY_LEVEL_ONE)
+ continue
else if(!SA_attackable(L))
continue
else if(!special_target_check(L))
@@ -1242,7 +1246,7 @@
ai_log("AttackTarget() Bailing because we're disabled",2)
LoseTarget()
return 0
- if(!target_mob || !SA_attackable(target_mob))
+ if(!target_mob || !SA_attackable(target_mob) || (target_mob.invisibility >= INVISIBILITY_LEVEL_ONE)) //if the target went invisible, you can't follow it
LoseTarget()
return 0
if(!(target_mob in ListTargets(view_range)))
diff --git a/icons/effects/timestop.dmi b/icons/effects/timestop.dmi
new file mode 100644
index 0000000000..0e69eba984
Binary files /dev/null and b/icons/effects/timestop.dmi differ
diff --git a/icons/obj/deadringer.dmi b/icons/obj/deadringer.dmi
new file mode 100644
index 0000000000..6220057782
Binary files /dev/null and b/icons/obj/deadringer.dmi differ
diff --git a/maps/submaps/surface_submaps/mountains/deadspy.dmm b/maps/submaps/surface_submaps/mountains/deadspy.dmm
new file mode 100644
index 0000000000..f255e79cd7
--- /dev/null
+++ b/maps/submaps/surface_submaps/mountains/deadspy.dmm
@@ -0,0 +1,31 @@
+"a" = (/obj/effect/decal/cleanable/liquid_fuel/flamethrower_fuel,/obj/effect/decal/cleanable/molten_item,/turf/template_noop,/area/submap/deadspy)
+"b" = (/obj/item/weapon/flamethrower,/obj/effect/decal/cleanable/liquid_fuel/flamethrower_fuel,/turf/template_noop,/area/submap/deadspy)
+"c" = (/obj/effect/decal/cleanable/liquid_fuel/flamethrower_fuel,/obj/effect/decal/cleanable/ash,/obj/random/landmine,/turf/template_noop,/area/submap/deadspy)
+"d" = (/obj/item/weapon/material/butterfly,/obj/effect/decal/cleanable/liquid_fuel,/turf/template_noop,/area/submap/deadspy)
+"e" = (/obj/item/weapon/flame/lighter/zippo,/obj/effect/decal/cleanable/liquid_fuel,/turf/template_noop,/area/submap/deadspy)
+"f" = (/obj/effect/decal/cleanable/liquid_fuel,/obj/effect/decal/cleanable/liquid_fuel/flamethrower_fuel,/turf/template_noop,/area/submap/deadspy)
+"g" = (/obj/effect/decal/cleanable/liquid_fuel,/obj/random/landmine,/turf/template_noop,/area/submap/deadspy)
+"h" = (/obj/item/weapon/deadringer,/obj/effect/decal/cleanable/liquid_fuel,/turf/template_noop,/area/submap/deadspy)
+"i" = (/obj/effect/decal/cleanable/liquid_fuel,/obj/item/weapon/storage/fancy/cigarettes/professionals,/turf/template_noop,/area/submap/deadspy)
+"j" = (/obj/effect/decal/cleanable/liquid_fuel/flamethrower_fuel,/turf/template_noop,/area/submap/deadspy)
+"k" = (/obj/effect/decal/cleanable/liquid_fuel/flamethrower_fuel,/obj/effect/decal/cleanable/ash,/turf/template_noop,/area/submap/deadspy)
+"l" = (/obj/effect/decal/cleanable/liquid_fuel,/obj/effect/decal/cleanable/molten_item,/turf/template_noop,/area/submap/deadspy)
+"m" = (/obj/effect/decal/remains/human,/obj/item/clothing/mask/balaclava,/obj/item/clothing/under/suit_jacket/really_black,/obj/effect/decal/cleanable/ash,/obj/effect/decal/cleanable/liquid_fuel,/obj/effect/decal/cleanable/ash,/turf/template_noop,/area/submap/deadspy)
+"n" = (/obj/effect/decal/cleanable/liquid_fuel,/obj/effect/decal/cleanable/liquid_fuel,/obj/effect/decal/cleanable/ash,/turf/template_noop,/area/submap/deadspy)
+"o" = (/obj/effect/decal/cleanable/liquid_fuel,/obj/effect/decal/cleanable/liquid_fuel,/obj/random/landmine,/turf/template_noop,/area/submap/deadspy)
+"p" = (/obj/effect/decal/cleanable/liquid_fuel/flamethrower_fuel,/obj/random/landmine,/turf/template_noop,/area/submap/deadspy)
+"q" = (/obj/effect/decal/remains/xeno,/obj/item/clothing/mask/gas,/obj/item/clothing/suit/fire/firefighter,/turf/template_noop,/area/submap/deadspy)
+"r" = (/turf/template_noop,/area/submap/deadspy)
+"s" = (/obj/effect/decal/remains/human,/obj/item/weapon/wrench,/obj/item/clothing/head/hardhat,/turf/template_noop,/area/submap/deadspy)
+"t" = (/obj/machinery/porta_turret/poi{desc = "Looking at this heavy caliber, tripod-mounted, little ol' number makes you want to square-dance."; lethal = 0; name = "sentry turret"},/turf/template_noop,/area/submap/deadspy)
+"u" = (/obj/item/weapon/card/emag_broken,/turf/template_noop,/area/submap/deadspy)
+
+(1,1,1) = {"
+qrrrrrr
+rabfjcr
+rjgldjs
+rjemnjt
+rjhoiju
+rpjkjjr
+rrrrrrr
+"}
diff --git a/maps/submaps/surface_submaps/mountains/mountains.dm b/maps/submaps/surface_submaps/mountains/mountains.dm
index dd409e0e62..56a267c475 100644
--- a/maps/submaps/surface_submaps/mountains/mountains.dm
+++ b/maps/submaps/surface_submaps/mountains/mountains.dm
@@ -31,6 +31,7 @@
#include "SupplyDrop1.dmm"
#include "BlastMine1.dmm"
#include "crashedcontainmentshuttle.dmm"
+#include "deadspy.dmm"
#endif
// The 'mountains' is the mining z-level, and has a lot of caves.
@@ -191,6 +192,12 @@
mappath = 'maps/submaps/surface_submaps/mountains/crashedcontainmentshuttle.dmm'
cost = 30
+/datum/map_template/surface/mountains/normal/deadspy
+ name = "Spy Remains"
+ desc = "W+M1 = Salt."
+ mappath = 'maps/submaps/surface_submaps/mountains/deadspy.dmm'
+ cost = 15
+
/**************
* Deep Caves *
@@ -265,4 +272,3 @@
desc = "An abandoned blast mining site, seems that local wildlife has moved in."
mappath = 'maps/submaps/surface_submaps/mountains/BlastMine1.dmm'
cost = 20
-
diff --git a/maps/submaps/surface_submaps/mountains/mountains_areas.dm b/maps/submaps/surface_submaps/mountains/mountains_areas.dm
index 3baf48c75c..f1045f22f0 100644
--- a/maps/submaps/surface_submaps/mountains/mountains_areas.dm
+++ b/maps/submaps/surface_submaps/mountains/mountains_areas.dm
@@ -88,4 +88,7 @@
name = "Blast Mine 1"
/area/submap/crashedcontainmentshuttle
- name = "Crashed Containment Shuttle"
\ No newline at end of file
+ name = "Crashed Containment Shuttle"
+
+/area/submap/deadspy
+ name = "Dead Spy"
\ No newline at end of file
diff --git a/sound/effects/uncloak.ogg b/sound/effects/uncloak.ogg
new file mode 100644
index 0000000000..a2cedc8c73
Binary files /dev/null and b/sound/effects/uncloak.ogg differ
diff --git a/vorestation.dme b/vorestation.dme
index 5331c30de2..546e0d200b 100644
--- a/vorestation.dme
+++ b/vorestation.dme
@@ -1406,6 +1406,7 @@
#include "code\modules\alarm\fire_alarm.dm"
#include "code\modules\alarm\motion_alarm.dm"
#include "code\modules\alarm\power_alarm.dm"
+#include "code\modules\artifice\deadringer.dm"
#include "code\modules\assembly\assembly.dm"
#include "code\modules\assembly\helpers.dm"
#include "code\modules\assembly\holder.dm"