Adds Zombies (Admin-spawn) (#25381)

* fuck it good enough

* Apply suggestions from code review

Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com>
Signed-off-by: Contrabang <91113370+Contrabang@users.noreply.github.com>

* TRIPLE-REVIEW

* this should do it

* wow

* bruh

* FIX

* fix

* yeah

* sirryan review

* aaaaa

* Apply suggestions from code review

Co-authored-by: DGamerL <108773801+DGamerL@users.noreply.github.com>
Signed-off-by: Contrabang <91113370+Contrabang@users.noreply.github.com>

---------

Signed-off-by: Contrabang <91113370+Contrabang@users.noreply.github.com>
Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com>
Co-authored-by: DGamerL <108773801+DGamerL@users.noreply.github.com>
This commit is contained in:
Contrabang
2024-05-30 22:17:31 -04:00
committed by GitHub
parent 247e24ba9f
commit bc0c8344cf
62 changed files with 1326 additions and 148 deletions
+2 -1
View File
@@ -23,7 +23,8 @@ GLOBAL_LIST_INIT(huds, list(
ANTAG_HUD_ABDUCTOR = new/datum/atom_hud/antag/hidden(),
DATA_HUD_ABDUCTOR = new/datum/atom_hud/abductor(),
ANTAG_HUD_EVENTMISC = new/datum/atom_hud/antag/hidden(),
ANTAG_HUD_BLOB = new/datum/atom_hud/antag/hidden()
ANTAG_HUD_BLOB = new/datum/atom_hud/antag/hidden(),
ANTAG_HUD_ZOMBIE = new/datum/atom_hud/antag()
))
/datum/atom_hud
+155
View File
@@ -0,0 +1,155 @@
/datum/component/zombie_regen/Initialize()
if(!ishuman(parent))
return COMPONENT_INCOMPATIBLE
START_PROCESSING(SSprocessing, src)
/datum/component/zombie_regen/Destroy(force, silent)
STOP_PROCESSING(SSprocessing, src)
return ..()
/datum/component/zombie_regen/process()
if(!ishuman(parent))
return
var/mob/living/carbon/human/zomboid = parent
if(zomboid.suiciding)
return
var/turf/current_turf = get_turf(zomboid)
var/healing_factor = max(1, 6 * (1 - current_turf.get_lumcount()))
if(zomboid.reagents.has_reagent("zombiecure3"))
healing_factor /= 3
if(zomboid.stat == DEAD)
healing_factor *= 2
zomboid.heal_overall_damage(healing_factor, healing_factor)
zomboid.adjustBrainLoss(-healing_factor)
if(zomboid.stat == DEAD && zomboid.getBruteLoss() <= 1 && zomboid.getFireLoss() <= 1 && (zomboid.timeofdeath + 15 SECONDS <= world.time))
var/datum/reagent/the_cure = zomboid.reagents.has_reagent("zombiecure4")
if(the_cure) // dead bodies dont process chemicals, so we gotta do it manually.
zomboid.reagents.remove_reagent("zombiecure4", the_cure.metabolization_rate * zomboid.metabolism_efficiency)
return
zombie_rejuv()
to_chat(zomboid, "<span class='zombielarge'>We... Awaken...</span>")
// If no client, but they were a player thats not SSD (debrained, revived but hasn't returned to body, etc)
if(zomboid.stat != CONSCIOUS || HAS_TRAIT(zomboid, TRAIT_HANDS_BLOCKED))
return
if(zomboid.client || isLivingSSD(zomboid))
return
if(zomboid.last_known_ckey && !zomboid.key) // make sure they were player inhabited and not admin ghosted
mindless_hunger()
/datum/component/zombie_regen/proc/zombie_rejuv()
var/mob/living/carbon/human/zomboid = parent
zomboid.setToxLoss(0)
zomboid.setOxyLoss(0)
zomboid.setCloneLoss(0)
zomboid.setBrainLoss(0)
zomboid.setStaminaLoss(0)
zomboid.SetSleeping(0)
zomboid.SetParalysis(0, TRUE)
zomboid.SetStunned(0, TRUE)
zomboid.SetWeakened(0, TRUE)
zomboid.SetSlowed(0)
zomboid.SetImmobilized(0)
zomboid.SetKnockDown(0)
zomboid.SetLoseBreath(0)
zomboid.SetDizzy(0)
zomboid.SetJitter(0)
zomboid.SetStuttering(0)
zomboid.SetConfused(0)
zomboid.SetDrowsy(0)
zomboid.radiation = 0
zomboid.SetDruggy(0)
zomboid.SetHallucinate(0)
zomboid.bodytemperature = 310
zomboid.cure_blind()
zomboid.cure_nearsighted()
zomboid.CureMute()
zomboid.CureDeaf()
zomboid.CureTourettes()
zomboid.CureEpilepsy()
zomboid.CureCoughing()
zomboid.CureNervous()
zomboid.SetEyeBlind(0)
zomboid.SetEyeBlurry(0)
zomboid.SetDeaf(0)
zomboid.heal_overall_damage(1000, 1000)
zomboid.ExtinguishMob()
SEND_SIGNAL(zomboid, COMSIG_LIVING_CLEAR_STUNS)
zomboid.fire_stacks = 0
zomboid.on_fire = 0
zomboid.suiciding = 0
zomboid.set_nutrition(max(zomboid.nutrition, NUTRITION_LEVEL_HUNGRY))
if(zomboid.buckled) //Unbuckle the mob and clear the alerts.
zomboid.buckled.unbuckle_mob(src, force = TRUE)
var/datum/organ/heart/heart = zomboid.get_int_organ_datum(ORGAN_DATUM_HEART)
var/heart_type = zomboid.dna?.species?.has_organ["heart"]
if(!heart && heart_type)
var/obj/item/organ/internal/new_heart = new heart_type()
new_heart.insert(zomboid)
var/datum/organ/lungs/lungs = zomboid.get_int_organ_datum(ORGAN_DATUM_LUNGS)
var/lung_type = zomboid.dna?.species?.has_organ["lungs"]
if(!lungs && lung_type)
var/obj/item/organ/internal/new_lungs = new lung_type()
new_lungs.insert(zomboid)
zomboid.set_heartattack(FALSE)
zomboid.restore_blood()
zomboid.decaylevel = 0
zomboid.remove_all_embedded_objects()
zomboid.restore_all_organs()
if(zomboid.stat == DEAD)
zomboid.update_revive()
else if(zomboid.stat == UNCONSCIOUS)
zomboid.WakeUp()
zomboid.update_fire()
zomboid.regenerate_icons()
zomboid.restore_blood()
zomboid.update_eyes()
for(var/datum/disease/critical/crit in zomboid.viruses) // cure all crit conditions
crit.cure()
/datum/component/zombie_regen/proc/mindless_hunger()
var/mob/living/carbon/human/zomboid = parent
var/list/targets = list()
for(var/mob/living/carbon/human/target in view(6, zomboid))
if(target.stat == CONSCIOUS && !HAS_TRAIT(target, TRAIT_I_WANT_BRAINS))
targets |= target
if(zomboid.Adjacent(target))
break // we're just gonna hit em
var/target
if(length(targets))
target = pick(targets)
if(zomboid.Adjacent(target) && safe_active_hand(zomboid))
zomboid.a_intent = INTENT_HARM
zomboid.ClickOn(target)
return
if(!target && prob(90)) // a small chance to wander
return
var/targetted_direction = pick(GLOB.cardinal)
if(target)
targetted_direction = get_dir(zomboid, target)
var/delay = zomboid.movement_delay()
if(IS_DIR_DIAGONAL(targetted_direction))
delay *= SQRT_2
zomboid.glide_for(delay)
step(zomboid, targetted_direction)
/datum/component/zombie_regen/proc/safe_active_hand(mob/living/carbon/human/zomboid)
if(zomboid.get_organ("[zomboid.hand ? "l" : "r" ]_hand"))
return TRUE
zomboid.swap_hand()
if(zomboid.get_organ("[zomboid.hand ? "l" : "r" ]_hand"))
return TRUE
return FALSE
+2 -2
View File
@@ -1045,7 +1045,7 @@
to_chat(usr, "Mob doesn't exist anymore")
return
if(H.add_language(new_language))
if(H.add_language(new_language, TRUE))
to_chat(usr, "Added [new_language] to [H].")
message_admins("[key_name_admin(usr)] has given [key_name_admin(H)] the language [new_language]")
log_admin("[key_name(usr)] has given [key_name(H)] the language [new_language]")
@@ -1073,7 +1073,7 @@
to_chat(usr, "Mob doesn't exist anymore")
return
if(H.remove_language(rem_language.name))
if(H.remove_language(rem_language.name, TRUE))
to_chat(usr, "Removed [rem_language] from [H].")
message_admins("[key_name_admin(usr)] has removed language [rem_language] from [key_name_admin(H)]")
log_admin("[key_name(usr)] has removed language [rem_language] from [key_name(H)]")
+3 -1
View File
@@ -8,7 +8,7 @@
/mob/proc/CanContractDisease(datum/disease/D)
if(stat == DEAD)
if(stat == DEAD && !D.allow_dead)
return FALSE
if(D.GetDiseaseID() in resistances)
@@ -30,6 +30,7 @@
if(!CanContractDisease(D))
return 0
AddDisease(D)
return TRUE
/mob/proc/AddDisease(datum/disease/D, respect_carrier = FALSE)
@@ -127,6 +128,7 @@
if(passed)
AddDisease(D)
return passed
/**
+14 -11
View File
@@ -71,6 +71,8 @@ GLOBAL_LIST_INIT(diseases, subtypesof(/datum/disease))
var/list/required_organs = list()
var/needs_all_cures = TRUE
var/list/strain_data = list() //dna_spread special bullshit
/// Allow the virus to infect and process while the affected_mob is dead
var/allow_dead = FALSE
/datum/disease/Destroy()
affected_mob = null
@@ -87,23 +89,24 @@ GLOBAL_LIST_INIT(diseases, subtypesof(/datum/disease))
stage = min(stage, max_stages)
if(!cure)
if(prob(stage_prob))
stage = min(stage + 1,max_stages)
if(!discovered && stage >= CEILING(max_stages * discovery_threshold, 1)) // Once we reach a late enough stage, medical HUDs can pick us up even if we regress
discovered = TRUE
affected_mob.med_hud_set_status()
else
if(prob(cure_chance))
stage = max(stage - 1, 1)
if(!cure && prob(stage_prob))
stage = min(stage + 1, max_stages)
if(!discovered && stage >= CEILING(max_stages * discovery_threshold, 1)) // Once we reach a late enough stage, medical HUDs can pick us up even if we regress
discovered = TRUE
affected_mob.med_hud_set_status()
return handle_cure_testing(cure)
/datum/disease/proc/handle_cure_testing(has_cure = FALSE)
if(has_cure && prob(cure_chance))
stage = max(stage - 1, 1)
if(disease_flags & CURABLE)
if(cure && prob(cure_chance))
if(has_cure && prob(cure_chance))
cure()
return FALSE
return TRUE
/datum/disease/proc/has_cure()
if(!(disease_flags & CURABLE))
return 0
+141
View File
@@ -0,0 +1,141 @@
/datum/disease/zombie
name = "Necrotizing Plague"
medical_name = "Advanced Resurrection Syndrome"
desc = "This virus infects humanoids and drives them insane with a hunger for flesh, along with possessing regenerative abilities."
max_stages = 7
spread_text = "Blood and Saliva"
spread_flags = BLOOD
cure_text = "Anti-plague viral solutions"
cures = list()
agent = ""
viable_mobtypes = list(/mob/living/carbon/human)
severity = BIOHAZARD
allow_dead = TRUE
disease_flags = CAN_CARRY
virus_heal_resistant = TRUE
stage_prob = 1
cure_chance = 20
/// How far this particular virus is in being cured (0-4)
var/cure_stage = 0
/datum/disease/zombie/stage_act()
if(stage == 8)
// adminbus for immediate zombie
var/mob/living/carbon/human/H = affected_mob
if(!istype(H))
return FALSE
for(var/obj/item/organ/limb as anything in H.bodyparts)
if(!(limb.status & ORGAN_DEAD) && !limb.is_robotic())
limb.necrotize(TRUE, TRUE)
if(!..())
return FALSE
if(HAS_TRAIT(affected_mob, TRAIT_I_WANT_BRAINS) || affected_mob.mind?.has_antag_datum(/datum/antagonist/zombie))
handle_rot(TRUE)
stage = 7
return FALSE
switch(stage)
if(1) // cured by lvl 1 cure
if(prob(4))
to_chat(affected_mob, "<span class='warning'>[pick("Your scalp itches.", "Your skin feels flakey.")]</span>")
else if(prob(5))
to_chat(affected_mob, "<span class='warning'>Your [pick("back", "arm", "leg", "elbow", "head")] itches.</span>")
if(2)
if(prob(2))
to_chat(affected_mob, "<span class='danger'>Mucous runs down the back of your throat.</span>")
else if(prob(5))
to_chat(affected_mob, "<span class='warning'>[pick("You feel hungry.", "You crave for something to eat.")]</span>")
if(3) // cured by lvl 2 cure
if(prob(2))
affected_mob.emote("sneeze")
else if(prob(2))
affected_mob.emote("cough")
else if(prob(5))
to_chat(affected_mob, "<span class='warning'><i>[pick("So hungry...", "You'd kill someone for a bite of food...", "Hunger cramps seize you...")]</i></span>")
if(prob(5))
affected_mob.adjustToxLoss(1)
if(4) // shows up on medhuds
if(prob(2))
affected_mob.emote("stare")
else if(prob(2))
affected_mob.emote("drool")
else if(prob(5))
to_chat(affected_mob, "<span class='danger'>You feel a cold sweat form.</span>")
if(prob(25))
affected_mob.adjustToxLoss(1)
if(5, 6) // 5 is cured by lvl 3 cure. 6+ needs lvl 4 cure
var/turf/T = get_turf(affected_mob)
if(T.get_lumcount() >= 0.5)
if(prob(5))
to_chat(affected_mob, "<span class='danger'>Those lights seem bright. It stings.</span>")
if(prob(25))
affected_mob.adjustFireLoss(2)
if(prob(2))
affected_mob.emote("drool")
if(stage == 6 && !affected_mob.reagents.has_reagent("zombiecure3")) // cure 3 can delay it, but not cure it
if(prob(10))
to_chat(affected_mob, "<span class='danger zombie'>You feel your flesh rotting.</span>")
handle_rot()
if(7)
if(!handle_rot(TRUE))
stage = 6
return
/datum/disease/zombie/proc/handle_rot(forced = FALSE)
if(!prob(20) && !forced && affected_mob.stat != DEAD)
return FALSE
var/mob/living/carbon/human/H = affected_mob
if(!istype(H))
return FALSE
for(var/obj/item/organ/limb as anything in H.bodyparts)
if(!(limb.status & ORGAN_DEAD) && !limb.vital && !limb.is_robotic())
limb.necrotize()
return FALSE
for(var/obj/item/organ/limb as anything in H.bodyparts)
if(!(limb.status & ORGAN_DEAD) && !limb.is_robotic())
limb.necrotize(FALSE, TRUE)
return FALSE
if(!HAS_TRAIT(affected_mob, TRAIT_I_WANT_BRAINS))
affected_mob.AddComponent(/datum/component/zombie_regen)
ADD_TRAIT(affected_mob, TRAIT_I_WANT_BRAINS, ZOMBIE_TRAIT)
affected_mob.med_hud_set_health()
affected_mob.med_hud_set_status()
affected_mob.update_hands_hud()
H.update_body()
if(affected_mob.mind && !affected_mob.mind.has_antag_datum(/datum/antagonist/zombie))
affected_mob.mind.add_antag_datum(/datum/antagonist/zombie)
return TRUE
/datum/disease/zombie/handle_cure_testing(has_cure = FALSE)
if(has_cure && prob(cure_chance))
stage = max(stage - 1, 0)
if(stage <= 0 && has_cure)
cure()
return FALSE
return TRUE
/datum/disease/zombie/proc/update_cure_stage()
for(var/datum/reagent/zombie_cure/reag in affected_mob.reagents?.reagent_list)
cure_stage = max(cure_stage, reag.cure_level)
if(cure_stage)
var/stages = list("Stabilized", "Weakened", "Faltering", "Suppressed")
name = "[stages[cure_stage]] [initial(name)]"
/datum/disease/zombie/has_cure()
update_cure_stage()
var/required_reagent = (stage + 1) / 2 // stage 1 can be cured by cure 1, stage 3 with 2, stage 5 with 3, stage 7 with 4
return cure_stage >= required_reagent
/datum/disease/zombie/cure()
affected_mob.mind?.remove_antag_datum(/datum/antagonist/zombie)
REMOVE_TRAIT(affected_mob, TRAIT_I_WANT_BRAINS, ZOMBIE_TRAIT)
qdel(affected_mob.GetComponent(/datum/component/zombie_regen))
affected_mob.med_hud_set_health()
affected_mob.med_hud_set_status()
return ..()
+7 -2
View File
@@ -273,9 +273,14 @@
if(age_based && ishuman(user))
var/mob/living/carbon/human/H = user
// Vary needs to be true as otherwise frequency changes get ignored deep within playsound_local :(
playsound(user.loc, sound_path, sound_volume, TRUE, frequency = H.get_age_pitch(H.dna.species.max_age))
playsound(user.loc, sound_path, sound_volume, TRUE, frequency = H.get_age_pitch(H.dna.species.max_age) * alter_emote_pitch(user))
else
playsound(user.loc, sound_path, sound_volume, vary)
playsound(user.loc, sound_path, sound_volume, TRUE, frequency = alter_emote_pitch(user))
/datum/emote/proc/alter_emote_pitch(mob/user)
if(HAS_TRAIT(user, TRAIT_I_WANT_BRAINS))
return 0.7
return 1
/**
* Send an emote to runechat for all (listening) users in the vicinity.
+51
View File
@@ -417,6 +417,16 @@
. += _memory_edit_role_enabled(ROLE_ABDUCTOR)
/datum/mind/proc/memory_edit_zombie(mob/living/H)
. = _memory_edit_header("zombie", list())
if(has_antag_datum(/datum/antagonist/zombie))
. += "<a href='byond://?src=[UID()];zombie=clear'>no</a>|<b><font color='red'>ZOMBIE</font></b>"
return
if(current.HasDisease(/datum/disease/zombie))
. += "<b>NO</b>|<a href='byond://?src=[UID()];zombie=zombie'>zombie</a>|<a href='byond://?src=[UID()];zombie=zombievirusno'><font color='red'>dis-infect</font></a>"
else
. += "<b>NO</b>|<a href='byond://?src=[UID()];zombie=zombie'>zombie</a>|<a href='byond://?src=[UID()];zombie=zombievirus'>infect</a>"
/datum/mind/proc/memory_edit_eventmisc(mob/living/H)
. = _memory_edit_header("event", list())
if(src in SSticker.mode.eventmiscs)
@@ -546,6 +556,8 @@
sections["nuclear"] = memory_edit_nuclear(H)
/** Abductors **/
sections["abductor"] = memory_edit_abductor(H)
/** Zombies **/
sections["zombie"] = memory_edit_zombie(H)
sections["eventmisc"] = memory_edit_eventmisc(H)
/** TRAITOR ***/
sections["traitor"] = memory_edit_traitor()
@@ -1170,6 +1182,45 @@
log_admin("[key_name(usr)] has eventantag'ed [current].")
current.create_log(MISC_LOG, "[current] was made into an event antagonist by [key_name_admin(usr)]")
else if(href_list["zombie"])
switch(href_list["zombie"])
if("clear")
if(!has_antag_datum(/datum/antagonist/zombie))
return
remove_antag_datum(/datum/antagonist/zombie)
for(var/datum/disease/zombie/D in current.viruses)
D.cure()
if(ishuman(current))
var/mob/living/carbon/human/human_current = current
for(var/obj/item/organ/limb as anything in human_current.bodyparts)
if(limb.status & ORGAN_DEAD && !limb.is_robotic())
limb.status &= ~ORGAN_DEAD
human_current.update_body()
message_admins("[key_name_admin(usr)] has de-zombied'ed [key_name(current)].")
log_admin("[key_name(usr)] has de-zombied'ed [key_name(current)].")
if("zombie")
if(has_antag_datum(/datum/antagonist/zombie))
return
add_antag_datum(/datum/antagonist/zombie)
message_admins("[key_name_admin(usr)] has zombie'ed [key_name(current)].")
log_admin("[key_name(usr)] has zombie'ed [key_name(current)].")
current.create_log(MISC_LOG, "[key_name(current)] was made into an zombie by [key_name_admin(usr)]")
if("zombievirus")
if(has_antag_datum(/datum/antagonist/zombie) || !ishuman(current))
return
current.AddDisease(new /datum/disease/zombie)
message_admins("[key_name_admin(usr)] has given a zombie virus to [key_name(current)].")
log_admin("[key_name(usr)] has given a zombie virus to [key_name(current)].")
current.create_log(MISC_LOG, "[key_name(current)] was admin-infected with a zombie virus by [key_name_admin(usr)]")
if("zombievirusno")
if(has_antag_datum(/datum/antagonist/zombie))
return
for(var/datum/disease/zombie/D in current.viruses)
D.cure()
message_admins("[key_name_admin(usr)] has removed the zombie virus from [key_name(current)].")
log_admin("[key_name(usr)] has removed the zombie virus from [key_name(current)].")
current.create_log(MISC_LOG, "[key_name(current)] had their zombie virus admin-removed by [key_name_admin(usr)]")
else if(href_list["traitor"])
switch(href_list["traitor"])
if("clear")