diff --git a/code/modules/mining/abandonedcrates.dm b/code/modules/mining/abandonedcrates.dm
index 2ba613a389d..719aea59dd7 100644
--- a/code/modules/mining/abandonedcrates.dm
+++ b/code/modules/mining/abandonedcrates.dm
@@ -113,7 +113,7 @@
if(90)
new/obj/item/organ/heart(src)
if(91)
- new/obj/item/device/soulstone(src)
+ new/obj/item/poppet(src)
if(92)
new/obj/item/weapon/material/sword/katana(src)
if(93)
diff --git a/code/modules/spells/artifacts.dm b/code/modules/spells/artifacts.dm
index 1565f706388..5699131ab7e 100644
--- a/code/modules/spells/artifacts.dm
+++ b/code/modules/spells/artifacts.dm
@@ -142,8 +142,8 @@
/obj/item/phylactery/Initialize()
. = ..()
world_phylactery += src
- create_reagents(30)
- reagents.add_reagent("undead_ichor", 30)
+ create_reagents(120)
+ reagents.add_reagent("undead_ichor", 120)
/obj/item/phylactery/Destroy()
lich << "Your phylactery was destroyed, your soul is cast into the abyss as your immortality vanishes away!"
@@ -170,4 +170,167 @@
if(!user.is_wizard() && src.lich)
user << "As you pick up \the [src], you feel a wave of dread wash over you."
for(var/obj/machinery/light/P in view(7, user))
- P.flicker(1)
\ No newline at end of file
+ P.flicker(1)
+
+
+//magic poppet
+/obj/item/poppet
+ name = "poppet"
+ desc = "A rustic doll with a vague humanoid shape."
+ icon = 'icons/obj/wizard.dmi'
+ icon_state = "poppet"
+ w_class = 2
+ var/datum/weakref/target = null
+ var/countenance = null //what species does it looks like?
+ var/cooldown_time = 120
+ var/cooldown = 0
+
+/obj/item/poppet/Destroy()
+ if(target)
+ to_chat(target, "The strange presence vanishes away...")
+ return ..()
+
+/obj/item/poppet/examine(mob/user)
+ ..(user)
+ if(countenance)
+ to_chat(user, "It is modeled after a [countenance].")
+
+/obj/item/poppet/afterattack(var/atom/A, var/mob/user, var/proximity)
+
+ if(!proximity)
+ return
+
+ if(A.blood_DNA)
+ var/marked = pick(A.blood_DNA)
+
+ for(var/mob/living/carbon/human/H in mob_list)
+ if(H.dna.unique_enzymes == marked)
+ target = WEAKREF(H)
+ countenance = H.dna.species
+ to_chat(H, "You feel a strange presence looming over you.")
+
+
+/obj/item/poppet/attack_self(mob/user as mob)
+ var/mob/living/carbon/human/H = target.resolve()
+ if(H && cooldown < world.time)
+ var/target_zone = user.zone_sel.selecting
+
+ if(target_zone == "mouth")
+ var/voice = sanitize(input(user, "What would you like the victim to say", "Poppet", null) as text)
+ H.say(voice)
+ log_and_message_admins("forced [H] to say [voice] with a poppet", user)
+
+ if(target_zone == "eyes")
+ to_chat(user, "You cover \the [src]'s eyes.")
+ to_chat(H, "Your vision is covered by a shadow!")
+ H.eye_blind = 3
+ H.eye_blurry = 5
+
+ if(target_zone == "r_leg" || target_zone == "l_leg")
+ to_chat(user, "You move \the [src]'s legs around.")
+ if(H.canmove && !H.restrained() && !(istype(H.loc, /turf/space)))
+ step(H, pick(cardinal))
+
+ if(target_zone == "l_hand" || target_zone == "l_arm")
+ to_chat(user, "You twist \the [src]'s left arm.")
+ H.drop_l_hand()
+
+ if(target_zone == "r_hand" || target_zone == "r_arm")
+ to_chat(user, "You twist \the [src]'s right arm..")
+ H.drop_r_hand()
+
+ if(target_zone == "head")
+ to_chat(user, "You smack \the [src]'s head with your hand.")
+ H.confused += 10
+ H.stuttering += 5
+ to_chat(H, "You suddenly feel as if your head was hit by something!")
+ playsound(get_turf(H), "punch", 50, 1, -1)
+
+ cooldown = world.time + cooldown_time
+
+/obj/item/poppet/attackby(obj/item/W as obj, mob/user as mob)
+ var/mob/living/carbon/human/H = target.resolve()
+ if(H && cooldown < world.time)
+ var/target_zone = user.zone_sel.selecting
+
+ if(isflamesource(W))
+ fire_act()
+
+ if(istype(W, /obj/item/weapon/melee/baton))
+ H.electrocute_act(W.force * 2, W, def_zone = target_zone)
+ playsound(get_turf(H), 'sound/weapons/Egloves.ogg', 50, 1, -1)
+
+ if(istype(W, /obj/item/device/flashlight))
+ to_chat(H, "You direct \the [W] towards \the [src]'s eyes!")
+ playsound(get_turf(H), 'sound/items/flashlight.ogg', 50, 1, -1)
+ flick("flash", H.flash)
+ H.eye_blurry = 5
+
+ if(iscoil(W))
+ to_chat(H, "You strangle \the [src] with \the [W]!")
+ H.silent += 10
+ playsound(get_turf(H), 'sound/effects/noosed.ogg', 50, 1, -1)
+ if(!(H.species.flags & NO_BREATHE))
+ H.emote("me", 1, "gasps for air!")
+ H.losebreath += 5
+
+ if(istype(W, /obj/item/weapon/bikehorn))
+ playsound(get_turf(H), 'sound/items/bikehorn.ogg', 50, 1, -1)
+
+ if(W.edge)
+ to_chat(H, "You stab \the [src] with \the [W]!")
+ H.apply_damage(2, BRUTE, target_zone, edge = TRUE)
+ playsound(get_turf(H), 'sound/weapons/bladeslice.ogg', 50, 1, -1)
+ if(!(H.species.flags & NO_PAIN))
+ var/obj/item/organ/external/organ = H.get_organ(target_zone)
+ to_chat(H, "You feel a stabbing pain in your [organ.name]!")
+
+
+ cooldown = world.time + cooldown_time
+
+/obj/item/poppet/throw_impact(atom/hit_atom)
+ ..()
+ var/mob/living/carbon/human/H = target.resolve()
+ if(H)
+ H.throw_at(get_edge_target_turf(H,pick(alldirs)), 5, 1)
+
+/obj/item/poppet/emp_act(severity)
+ var/mob/living/carbon/human/H = target.resolve()
+ if(H)
+ H.emp_act(severity)
+ playsound(get_turf(H), 'sound/effects/EMPulse.ogg', 50, 1, -1)
+
+/obj/item/poppet/water_act(amount)
+ var/mob/living/carbon/human/H = target.resolve()
+ if(H)
+ H.water_act(amount)
+
+/obj/item/poppet/ex_act(severity)
+ var/mob/living/carbon/human/H = target.resolve()
+ if(H)
+ H.ex_act(severity)
+
+/obj/item/poppet/tesla_act(var/power)
+ var/mob/living/carbon/human/H = target.resolve()
+ if(H)
+ H.electrocute_act(power, src)
+
+/obj/item/poppet/bullet_act(var/obj/item/projectile/Proj)
+ var/mob/living/carbon/human/H = target.resolve()
+ if(H)
+ H.apply_damage(Proj.damage, HALLOSS)
+
+/obj/item/poppet/fire_act()
+ var/mob/living/carbon/human/H = target.resolve()
+ if(H)
+ H.adjust_fire_stacks(2)
+ H.IgniteMob()
+ to_chat(H, "You suddenly burst into flames!!")
+
+/obj/item/poppet/crush_act()
+ var/mob/living/carbon/human/H = target.resolve()
+ if(H)
+ to_chat(H, "You feel an outworldly force crushing you!")
+ H.adjustBruteLoss(35)
+ H.apply_effect(6, WEAKEN)
+ qdel(src)
\ No newline at end of file
diff --git a/code/modules/spells/spellbook/battlemage.dm b/code/modules/spells/spellbook/battlemage.dm
index db166e4a8f8..e093ebf0329 100644
--- a/code/modules/spells/spellbook/battlemage.dm
+++ b/code/modules/spells/spellbook/battlemage.dm
@@ -25,11 +25,11 @@
/spell/targeted/flesh_to_stone = 1,
/spell/noclothes = 1,
/obj/structure/closet/wizard/armor = 1,
+ /spell/aoe_turf/blink = 1,
/obj/item/weapon/gun/energy/staff/focus = 1,
/obj/item/weapon/gun/energy/staff/chaos = 1,
/obj/item/weapon/storage/belt/wands/full = 2,
/obj/item/weapon/melee/energy/wizard = 2,
/obj/item/weapon/monster_manual = 2,
- /obj/item/weapon/contract/apprentice = 1,
- /spell/aoe_turf/blink = 1
+ /obj/item/weapon/contract/apprentice = 1
)
diff --git a/code/modules/spells/spellbook/cleric.dm b/code/modules/spells/spellbook/cleric.dm
index 457b97776f4..57465c3aac4 100644
--- a/code/modules/spells/spellbook/cleric.dm
+++ b/code/modules/spells/spellbook/cleric.dm
@@ -30,5 +30,6 @@
/spell/targeted/mindcontrol = 2,
/obj/item/weapon/gun/energy/staff/focus = 2,
/obj/item/weapon/storage/belt/wands/full = 2,
- /obj/item/weapon/contract/apprentice = 1
+ /obj/item/weapon/contract/apprentice = 1,
+ /obj/item/poppet = 1
)
diff --git a/code/modules/spells/spellbook/druid.dm b/code/modules/spells/spellbook/druid.dm
index 1511802389d..a28820d104b 100644
--- a/code/modules/spells/spellbook/druid.dm
+++ b/code/modules/spells/spellbook/druid.dm
@@ -29,5 +29,6 @@
/spell/targeted/flesh_to_stone = 1,
/obj/structure/closet/wizard/souls = 1,
/obj/item/weapon/monster_manual = 1,
- /obj/item/weapon/contract/apprentice = 1
+ /obj/item/weapon/contract/apprentice = 1,
+ /obj/item/poppet = 1
)
diff --git a/icons/obj/wizard.dmi b/icons/obj/wizard.dmi
index 82ff281aaa2..9356e97b4fa 100644
Binary files a/icons/obj/wizard.dmi and b/icons/obj/wizard.dmi differ