diff --git a/code/__DEFINES/genetics.dm b/code/__DEFINES/genetics.dm
index 0fb9253a083..bc8b8236032 100644
--- a/code/__DEFINES/genetics.dm
+++ b/code/__DEFINES/genetics.dm
@@ -23,6 +23,8 @@
// MUTATIONS
///////////////////////////////////////
+#define CHECK_DNA_AND_SPECIES(C) if((!(C.dna)) || (!(C.dna.species))) return
+
// Generic mutations:
#define TK 1
#define COLDRES 2
@@ -146,4 +148,5 @@
#define RESISTHOT 16
#define RESISTCOLD 17
#define NO_EXAMINE 18
-#define CAN_WINGDINGS 19
\ No newline at end of file
+#define CAN_WINGDINGS 19
+#define NOZOMBIE 20
\ No newline at end of file
diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm
index ba0d1858616..d793737eb6b 100644
--- a/code/__DEFINES/is_helpers.dm
+++ b/code/__DEFINES/is_helpers.dm
@@ -4,6 +4,7 @@
// Mobs
#define ismegafauna(A) istype(A, /mob/living/simple_animal/hostile/megafauna)
+#define iszombie(A) (is_species(A, /datum/species/zombie))
//Simple animals
#define isshade(A) (istype(A, /mob/living/simple_animal/shade))
diff --git a/code/_globalvars/lists/objects.dm b/code/_globalvars/lists/objects.dm
index e6f463d6f23..00417c5b47a 100644
--- a/code/_globalvars/lists/objects.dm
+++ b/code/_globalvars/lists/objects.dm
@@ -16,6 +16,7 @@ GLOBAL_LIST_INIT(prisoncomputer_list, list())
GLOBAL_LIST_INIT(celltimers_list, list()) // list of all cell timers
GLOBAL_LIST_INIT(cell_logs, list())
GLOBAL_LIST_INIT(navigation_computers, list())
+GLOBAL_LIST_INIT(zombie_infection_list, list())
GLOBAL_LIST_INIT(all_areas, list())
GLOBAL_LIST_INIT(machines, list())
diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm
index 13c3fb64f33..17e1abf3b7b 100644
--- a/code/datums/datumvars.dm
+++ b/code/datums/datumvars.dm
@@ -738,22 +738,7 @@
if(!istype(M))
to_chat(usr, "This can only be used on instances of type /mob")
return
- to_chat(M, "Control of your mob has been offered to dead players.")
- log_admin("[key_name(usr)] has offered control of ([key_name(M)]) to ghosts.")
- var/minhours = input(usr, "Minimum hours required to play [M]?", "Set Min Hrs", 10) as num
- message_admins("[key_name_admin(usr)] has offered control of ([key_name_admin(M)]) to ghosts with [minhours] hrs playtime")
- var/list/mob/dead/observer/candidates = pollCandidates("Do you want to play as [M.real_name ? M.real_name : M.name]?", poll_time = 100, min_hours = minhours)
- var/mob/dead/observer/theghost = null
-
- if(candidates.len)
- theghost = pick(candidates)
- to_chat(M, "Your mob has been taken over by a ghost!")
- message_admins("[key_name_admin(theghost)] has taken control of ([key_name_admin(M)])")
- M.ghostize()
- M.key = theghost.key
- else
- to_chat(M, "There were no ghosts willing to take control.")
- message_admins("No ghosts were willing to take control of [key_name_admin(M)])")
+ offer_control(M)
else if(href_list["delete"])
if(!check_rights(R_DEBUG, 0))
diff --git a/code/datums/uplink_item.dm b/code/datums/uplink_item.dm
index b6167338ad3..4a21c92ffa9 100644
--- a/code/datums/uplink_item.dm
+++ b/code/datums/uplink_item.dm
@@ -190,6 +190,13 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
cost = 1
job = list("Clown")
+/datum/uplink_item/stealthy_weapons/romerol_kit
+ name = "Romerol"
+ reference = "ROM"
+ desc = "A highly experimental bioterror agent which creates dormant nodules to be etched into the grey matter of the brain. On death, these nodules take control of the dead body, causing limited revivification, along with slurred speech, aggression, and the ability to infect others with this agent."
+ item = /obj/item/storage/box/syndie_kit/romerol
+ cost = 25
+
//mime
/datum/uplink_item/jobspecific/caneshotgun
name = "Cane Shotgun and Assassination Shells"
@@ -638,6 +645,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
/datum/uplink_item/dangerous/guardian
name = "Holoparasites"
+ reference = "HPA"
desc = "Though capable of near sorcerous feats via use of hardlight holograms and nanomachines, they require an organic host as a home base and source of fuel. \
The holoparasites are unable to incoporate themselves to changeling and vampire agents."
item = /obj/item/storage/box/syndie_kit/guardian
diff --git a/code/game/objects/items/weapons/storage/uplink_kits.dm b/code/game/objects/items/weapons/storage/uplink_kits.dm
index 56db11ad058..06ea21b4f4e 100644
--- a/code/game/objects/items/weapons/storage/uplink_kits.dm
+++ b/code/game/objects/items/weapons/storage/uplink_kits.dm
@@ -113,6 +113,19 @@
desc = "A sleek, sturdy box"
icon_state = "box_of_doom"
+/obj/item/storage/box/syndie_kit/romerol
+ name = "Romerol Kit"
+ desc = "A box containing a deadly virus capable of reanimating dead as zombies."
+ max_w_class = WEIGHT_CLASS_NORMAL
+ can_hold = list(/obj/item/reagent_containers/glass/bottle/romerol,/obj/item/reagent_containers/syringe,/obj/item/reagent_containers/dropper)
+
+/obj/item/storage/box/syndie_kit/romerol/New()
+ ..()
+ new /obj/item/reagent_containers/glass/bottle/romerol(src)
+ new /obj/item/reagent_containers/syringe(src)
+ new /obj/item/reagent_containers/dropper(src)
+ return
+
/obj/item/storage/box/syndie_kit/space
name = "Boxed Space Suit and Helmet"
can_hold = list(/obj/item/clothing/suit/space/syndicate/black/red, /obj/item/clothing/head/helmet/space/syndicate/black/red, /obj/item/tank/emergency_oxygen/syndi, /obj/item/clothing/mask/gas/syndicate)
diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm
index d6c667b1b74..fe048fb8137 100644
--- a/code/modules/mob/living/carbon/human/life.dm
+++ b/code/modules/mob/living/carbon/human/life.dm
@@ -14,7 +14,6 @@
handle_heartbeat()
handle_drunk()
dna.species.handle_life(src)
-
if(!client)
dna.species.handle_npc(src)
diff --git a/code/modules/mob/living/carbon/human/species/_species.dm b/code/modules/mob/living/carbon/human/species/_species.dm
index 7dc6c042e0c..c82433e557e 100644
--- a/code/modules/mob/living/carbon/human/species/_species.dm
+++ b/code/modules/mob/living/carbon/human/species/_species.dm
@@ -51,9 +51,10 @@
var/clone_mod = 1 // Clone damage reduction/amplification
var/brain_mod = 1 // Brain damage damage reduction/amplification
var/stun_mod = 1 // If a species is more/less impacated by stuns/weakens/paralysis
-
+ var/speedmod = 0 // this affects the race's speed. positive numbers make it move slower, negative numbers make it move faster
+ var/armor = 0 // overall defense for the race... or less defense, if it's negative.
var/blood_damage_type = OXY //What type of damage does this species take if it's low on blood?
-
+ var/obj/item/mutanthands
var/total_health = 100
var/punchdamagelow = 0 //lowest possible punch damage
var/punchdamagehigh = 9 //highest possible punch damage
@@ -307,6 +308,12 @@
/datum/species/proc/handle_death(mob/living/carbon/human/H) //Handles any species-specific death events (such as dionaea nymph spawns).
return
+/datum/species/proc/spec_death(mob/living/carbon/human/C)
+ return
+
+/datum/species/proc/spec_stun(mob/living/carbon/human/H,amount)
+ return
+
/datum/species/proc/spec_electrocute_act(mob/living/carbon/human/H, shock_damage, obj/source, siemens_coeff = 1, safety = FALSE, override = FALSE, tesla_shock = FALSE, illusion = FALSE, stun = TRUE)
return
diff --git a/code/modules/mob/living/carbon/human/species/zombies.dm b/code/modules/mob/living/carbon/human/species/zombies.dm
new file mode 100644
index 00000000000..9fa6cf37de2
--- /dev/null
+++ b/code/modules/mob/living/carbon/human/species/zombies.dm
@@ -0,0 +1,70 @@
+#define REGENERATION_DELAY 60 // After taking damage, how long it takes for automatic regeneration to begin
+
+/datum/species/zombie
+ // 1spooky
+ name = "High-Functioning Zombie"
+ name_plural = "High-Functioning Zombies"
+ icobase = 'icons/mob/human_races/r_human.dmi'
+ deform = 'icons/mob/human_races/r_def_human.dmi'
+ dies_at_threshold = TRUE
+ species_traits = list(NO_BLOOD,NOZOMBIE,NOTRANSSTING,NO_BREATHE, RADIMMUNE, NO_SCAN)
+ var/static/list/spooks = list('sound/hallucinations/growl1.ogg','sound/hallucinations/growl2.ogg','sound/hallucinations/growl3.ogg','sound/hallucinations/veryfar_noise.ogg','sound/hallucinations/wail.ogg')
+ warning_low_pressure = 50
+ hazard_low_pressure = 0
+
+/datum/species/zombie/infectious
+ name = "Infectious Zombie"
+ mutanthands = /obj/item/zombie_hand
+ armor = 20 // 120 damage to KO a zombie, which kills it
+ speedmod = 1.6
+ var/heal_rate = 1
+ var/regen_cooldown = 0
+
+/datum/species/zombie/infectious/spec_stun(mob/living/carbon/human/H,amount)
+ . = min(20, amount)
+
+/datum/species/zombie/infectious/spec_attacked_by(damage, damagetype = BRUTE, def_zone = null, blocked, mob/living/carbon/human/H)
+ if(.)
+ regen_cooldown = world.time + REGENERATION_DELAY
+
+/datum/species/zombie/infectious/handle_life(mob/living/carbon/human/C)
+ . = ..()
+ C.a_intent = INTENT_HARM // THE SUFFERING MUST FLOW
+
+ //Zombies never actually die, they just fall down until they regenerate enough to rise back up.
+ //They must be restrained, beheaded or gibbed to stop being a threat.
+ if(regen_cooldown < world.time)
+ var/heal_amt = heal_rate
+ if(C.InCritical())
+ heal_amt *= 2
+ C.heal_overall_damage(heal_amt,heal_amt)
+ C.adjustToxLoss(-heal_amt)
+ if(!C.InCritical() && prob(4))
+ playsound(C, pick(spooks), 50, TRUE, 10)
+
+//Congrats you somehow died so hard you stopped being a zombie
+/datum/species/zombie/infectious/spec_death(mob/living/carbon/C)
+ . = ..()
+ var/obj/item/organ/internal/zombie_infection/infection
+ infection = C.get_organ_slot("zombie_infection")
+ if(infection)
+ qdel(infection)
+
+/datum/species/zombie/infectious/on_species_gain(mob/living/carbon/human/C, datum/species/old_species)
+ . = ..()
+ // Deal with the source of this zombie corruption
+ // Infection organ needs to be handled separately from mutant_organs
+ // because it persists through species transitions
+ if(mutanthands)
+ C.drop_l_hand()
+ C.drop_r_hand()
+ C.put_in_hands(new mutanthands())
+ C.put_in_hands(new mutanthands())
+ C.ChangeToHusk()
+ var/obj/item/organ/internal/zombie_infection/infection
+ infection = C.get_organ_slot("zombie_infection")
+ if(!infection)
+ infection = new()
+ infection.insert(C)
+
+#undef REGENERATION_DELAY
diff --git a/code/modules/mob/living/carbon/human/status_procs.dm b/code/modules/mob/living/carbon/human/status_procs.dm
index 30653023751..10bbd27edcc 100644
--- a/code/modules/mob/living/carbon/human/status_procs.dm
+++ b/code/modules/mob/living/carbon/human/status_procs.dm
@@ -5,21 +5,29 @@
. = ..()
/mob/living/carbon/human/SetStunned(amount, updating = 1, force = 0)
- if(dna.species)
+ if(dna.species.stun_mod)
amount = amount * dna.species.stun_mod
+ else
+ amount = dna.species.spec_stun(src,amount)
..()
/mob/living/carbon/human/SetWeakened(amount, updating = 1, force = 0)
- if(dna.species)
+ if(dna.species.stun_mod)
amount = amount * dna.species.stun_mod
+ else
+ amount = dna.species.spec_stun(src,amount)
..()
/mob/living/carbon/human/SetParalysis(amount, updating = 1, force = 0)
- if(dna.species)
+ if(dna.species.stun_mod)
amount = amount * dna.species.stun_mod
+ else
+ amount = dna.species.spec_stun(src,amount)
..()
/mob/living/carbon/human/SetSleeping(amount, updating = 1, no_alert = FALSE)
- if(dna.species)
+ if(dna.species.stun_mod)
amount = amount * dna.species.stun_mod
+ else
+ amount = dna.species.spec_stun(src,amount)
..()
\ No newline at end of file
diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm
index beb474539f1..fa3275a053b 100644
--- a/code/modules/mob/mob_helpers.dm
+++ b/code/modules/mob/mob_helpers.dm
@@ -113,6 +113,24 @@
return U.sensor_mode
return SUIT_SENSOR_OFF
+/proc/offer_control(mob/M)
+ to_chat(M, "Control of your mob has been offered to dead players.")
+ log_admin("[key_name(usr)] has offered control of ([key_name(M)]) to ghosts.")
+ var/minhours = input(usr, "Minimum hours required to play [M]?", "Set Min Hrs", 10) as num
+ message_admins("[key_name_admin(usr)] has offered control of ([key_name_admin(M)]) to ghosts with [minhours] hrs playtime")
+ var/list/mob/dead/observer/candidates = pollCandidates("Do you want to play as [M.real_name ? M.real_name : M.name]?", poll_time = 100, min_hours = minhours)
+ var/mob/dead/observer/theghost = null
+
+ if(candidates.len)
+ theghost = pick(candidates)
+ to_chat(M, "Your mob has been taken over by a ghost!")
+ message_admins("[key_name_admin(theghost)] has taken control of ([key_name_admin(M)])")
+ M.ghostize()
+ M.key = theghost.key
+ else
+ to_chat(M, "There were no ghosts willing to take control.")
+ message_admins("No ghosts were willing to take control of [key_name_admin(M)])")
+
/proc/check_zone(zone)
if(!zone) return "chest"
switch(zone)
diff --git a/code/modules/reagents/chemistry/reagents/toxins.dm b/code/modules/reagents/chemistry/reagents/toxins.dm
index 4cf50c9f661..8a9976bddba 100644
--- a/code/modules/reagents/chemistry/reagents/toxins.dm
+++ b/code/modules/reagents/chemistry/reagents/toxins.dm
@@ -203,6 +203,23 @@
return ..()
+datum/reagent/romerol
+ name = "romerol"
+ // the REAL zombie powder
+ id = "romerol"
+ description = "Romerol is a highly experimental bioterror agent \
+ which causes dormant nodules to be etched into the grey matter of \
+ the subject. These nodules only become active upon death of the \
+ host, upon which, the secondary structures activate and take control \
+ of the host body."
+ color = "#123524" // RGB (18, 53, 36)
+ metabolization_rate = INFINITY
+
+/datum/reagent/romerol/reaction_mob(mob/living/carbon/human/H)
+ // Silently add the zombie infection organ to be activated upon death
+ new /obj/item/organ/internal/zombie_infection(H)
+ ..()
+
/datum/reagent/stable_mutagen/on_tick()
var/datum/reagent/blood/B = locate() in holder.reagent_list
if(B && islist(B.data) && !data)
diff --git a/code/modules/reagents/reagent_containers/bottle.dm b/code/modules/reagents/reagent_containers/bottle.dm
index 6aeafd92cf0..3e5c69ff484 100644
--- a/code/modules/reagents/reagent_containers/bottle.dm
+++ b/code/modules/reagents/reagent_containers/bottle.dm
@@ -12,6 +12,11 @@
container_type = OPENCONTAINER
volume = 30
+/obj/item/reagent_containers/glass/bottle/romerol
+ name = "romerol bottle"
+ desc = "A small bottle of Romerol. The REAL zombie powder."
+ list_reagents = list("romerol" = 30)
+
/obj/item/reagent_containers/glass/bottle/on_reagent_change()
update_icon()
diff --git a/code/modules/zombie/items.dm b/code/modules/zombie/items.dm
new file mode 100644
index 00000000000..e939299f1ed
--- /dev/null
+++ b/code/modules/zombie/items.dm
@@ -0,0 +1,112 @@
+/obj/item/zombie_hand
+ name = "zombie claw"
+ desc = "A zombie's claw is its primary tool, capable of infecting \
+ unconcious or dead humans, butchering all other living things to \
+ sustain the zombie, forcing open airlock doors and opening \
+ child-safe caps on bottles."
+ flags = NODROP|ABSTRACT
+ icon = 'icons/effects/blood.dmi'
+ icon_state = "bloodhand_left"
+ var/icon_left = "bloodhand_left"
+ var/icon_right = "bloodhand_right"
+ //hitsound = 'sound/hallucinations/growl1.ogg'
+ force = 25
+ damtype = "brute"
+
+ var/removing_airlock = FALSE
+
+/obj/item/zombie_hand/equipped(mob/user, slot)
+ . = ..()
+ switch(slot)
+ // Yes, these intentionally don't match
+ if(slot_l_hand)
+ icon_state = icon_right
+ if(slot_r_hand)
+ icon_state = icon_left
+
+/obj/item/zombie_hand/dropped(mob/user)
+ . = ..()
+ // Zombie hands are force dropped upon species loss
+ qdel(src)
+
+/obj/item/zombie_hand/afterattack(atom/target, mob/user, proximity_flag)
+ . = ..()
+ if(!proximity_flag)
+ return
+ if(istype(target, /obj/machinery/door/airlock) && !removing_airlock)
+ tear_airlock(target, user)
+
+ else if(isliving(target))
+ if(ishuman(target))
+ check_infection(target, user)
+ else
+ check_feast(target, user)
+
+/obj/item/zombie_hand/proc/check_infection(var/mob/living/carbon/human/target, var/mob/user)
+ CHECK_DNA_AND_SPECIES(target)
+ var/mob/living/carbon/human/T = target
+ if(NOZOMBIE in T.dna.species.species_traits)
+ // cannot infect any NOZOMBIE subspecies (such as high functioning
+ // zombies)
+ return
+
+ var/obj/item/organ/internal/zombie_infection/infection
+ infection = target.get_organ_slot("zombie_infection")
+ if(!infection)
+ if (target.InCritical || (!target.check_death_method && H.health <= HEALTH_THRESHOLD_DEAD))
+ infection = new(target)
+
+/obj/item/zombie_hand/proc/check_feast(mob/living/target, mob/living/user)
+ if(target.stat == DEAD)
+ var/hp_gained = target.maxHealth
+ target.gib()
+ user.adjustBruteLoss(-hp_gained)
+ user.adjustToxLoss(-hp_gained)
+ user.adjustFireLoss(-hp_gained)
+ user.adjustCloneLoss(-hp_gained)
+ user.adjustBrainLoss(-hp_gained) // Zom Bee gibbers "BRAAAAISNSs!1!"
+
+/obj/item/zombie_hand/proc/tear_airlock(obj/machinery/door/airlock/A, mob/user)
+ removing_airlock = TRUE
+ to_chat(user,"You start tearing apart the airlock...\
+ ")
+
+ playsound(src.loc, 'sound/machines/airlock_alien_prying.ogg', 100, 1)
+ A.audible_message("You hear a loud metallic \
+ grinding sound.")
+
+ spawn(20)
+ if(removing_airlock)
+ playsound(src.loc, 'sound/hallucinations/growl3.ogg', 50, 1)
+ user.audible_message("[user] growls as \
+ their claws dig into the metal frame...")
+
+ if(do_after(user, delay=160, needhand=FALSE, target=A, progress=TRUE))
+ playsound(src.loc, 'sound/hallucinations/far_noise.ogg', 50, 1)
+ A.audible_message("With a screech, [A] is torn \
+ apart!")
+ var/obj/structure/door_assembly/door = new A.assemblytype(get_turf(A))
+ door.density = 0
+ door.anchored = 1
+ door.name = "ravaged [door]"
+ door.desc = "An airlock that has been torn apart. Looks like it \
+ won't be keeping much out now."
+ qdel(A)
+ removing_airlock = FALSE
+
+/obj/item/zombie_hand/suicide_act(mob/living/carbon/human/user)
+ // Suiciding as a zombie brings someone else in to play it
+ user.visible_message("[user] is lying down.")
+ if(!istype(user))
+ return
+
+ user.Weaken(30)
+ var/success = offer_control(user)
+ if(success)
+ user.visible_message("[user] appears to have \
+ found new spirit.")
+ return SHAME
+ else
+ user.visible_message("[user] stops moving.\
+ ")
+ return OXYLOSS
\ No newline at end of file
diff --git a/code/modules/zombie/organs.dm b/code/modules/zombie/organs.dm
new file mode 100644
index 00000000000..bed6f646200
--- /dev/null
+++ b/code/modules/zombie/organs.dm
@@ -0,0 +1,87 @@
+#define START_TIMER reanimation_timer = world.time + rand(600,1200)
+
+/obj/item/organ/internal/zombie_infection
+ name = "festering ooze"
+ desc = "A black web of pus and vicera."
+ parent_organ = "head"
+ slot = "zombie_infection"
+ icon_state = "blacktumor"
+ var/causes_damage = TRUE
+ var/reanimation_timer
+ var/datum/species/old_species = /datum/species/human
+ var/living_transformation_time = 5
+ var/converts_living = FALSE
+
+/obj/item/organ/internal/zombie_infection/New()
+ . = ..()
+ if(iscarbon(loc))
+ insert(loc)
+ GLOB.zombie_infection_list += src
+
+/obj/item/organ/internal/zombie_infection/Destroy()
+ GLOB.zombie_infection_list -= src
+ . = ..()
+
+/obj/item/organ/internal/zombie_infection/insert(mob/living/carbon/human/M, special = 0)
+ . = ..()
+ START_PROCESSING(SSobj, src)
+
+/obj/item/organ/internal/zombie_infection/remove(mob/living/carbon/human/M, special = 0)
+ . = ..()
+ STOP_PROCESSING(SSobj, src)
+ if(iszombie(M) && old_species)
+ M.set_species(old_species)
+
+/obj/item/organ/internal/zombie_infection/on_find(mob/living/finder)
+ to_chat(finder,"Inside the head is a disgusting black \
+ web of pus and vicera, bound tightly around the brain like some \
+ biological harness.")
+
+/obj/item/organ/internal/zombie_infection/process()
+ if(!ishuman(owner)) // We do not support monkey or xeno zombies. Yet.
+ qdel(src)
+ return
+ if(owner.suiciding)
+ return
+ if(owner.stat != DEAD && !converts_living)
+ return
+ if (causes_damage && !iszombie(owner) && owner.stat != DEAD)
+ owner.adjustToxLoss(1)
+ if (prob(10))
+ to_chat(owner, "You feel sick...")
+ if(!owner.get_int_organ(/obj/item/organ/internal/brain))
+ return
+ else if(reanimation_timer && (reanimation_timer < world.time))
+ zombify() // Rise and shine, Mr Romero... rise and shine.
+ reanimation_timer = null
+ else if(owner.stat == DEAD && !reanimation_timer)
+ START_TIMER
+ else if(converts_living && !iszombie(owner) && !reanimation_timer)
+ START_TIMER
+
+/obj/item/organ/internal/zombie_infection/remove(mob/living/carbon/human/M, special = 0)
+ . = ..()
+ CHECK_DNA_AND_SPECIES(M)
+ if(iszombie(M) && old_species)
+ M.set_species(old_species)
+
+/obj/item/organ/internal/zombie_infection/proc/zombify()
+ CHECK_DNA_AND_SPECIES(owner)
+ var/datum/species/zombie = /datum/species/zombie/infectious
+ if(!iszombie(owner))
+ old_species = owner.dna.species
+ owner.set_species(zombie)
+ //Fully heal the zombie's damage the first time they rise
+ owner.setToxLoss(0, 0)
+ owner.setOxyLoss(0, 0)
+ owner.heal_overall_damage(INFINITY, INFINITY, INFINITY, null, TRUE)
+
+ if(!owner.revive())
+ return
+
+ owner.grab_ghost()
+ owner.visible_message("[owner] suddenly convulses, as [owner.p_they()] stagger to [owner.p_their()] feet and gain a ravenous hunger in [owner.p_their()] eyes!", "You HUNGER!")
+ playsound(owner.loc, 'sound/hallucinations/far_noise.ogg', 50, 1)
+ to_chat(owner, "You are now a zombie!")
+
+#undef START_TIMER
\ No newline at end of file
diff --git a/icons/obj/surgery.dmi b/icons/obj/surgery.dmi
index e212d9c5882..963bb718a39 100644
Binary files a/icons/obj/surgery.dmi and b/icons/obj/surgery.dmi differ
diff --git a/paradise.dme b/paradise.dme
index 79c465913f7..ec0edef3ebb 100644
--- a/paradise.dme
+++ b/paradise.dme
@@ -1762,6 +1762,7 @@
#include "code\modules\mob\living\carbon\human\species\vox.dm"
#include "code\modules\mob\living\carbon\human\species\vulpkanin.dm"
#include "code\modules\mob\living\carbon\human\species\wryn.dm"
+#include "code\modules\mob\living\carbon\human\species\zombies.dm"
#include "code\modules\mob\living\carbon\slime\death.dm"
#include "code\modules\mob\living\carbon\slime\emote.dm"
#include "code\modules\mob\living\carbon\slime\examine.dm"
@@ -2382,6 +2383,8 @@
#include "code\modules\vr\vr_controller.dm"
#include "code\modules\vr\vr_goggles.dm"
#include "code\modules\vr\vr_outfits.dm"
+#include "code\modules\zombie\items.dm"
+#include "code\modules\zombie\organs.dm"
#include "goon\code\datums\browserOutput.dm"
#include "interface\interface.dm"
#include "interface\skin.dmf"