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"