From 18b0b097786d5a5b4399eacccf1d5b92e737339a Mon Sep 17 00:00:00 2001 From: Contrabang <91113370+Contrabang@users.noreply.github.com> Date: Thu, 20 Jun 2024 07:38:23 -0400 Subject: [PATCH] adds spawners for NPC zombies (#25873) * lmao * lol * yes * yeah sure * fix * Apply suggestions from code review Co-authored-by: 1080pCat <96908085+1080pCat@users.noreply.github.com> Signed-off-by: Contrabang <91113370+Contrabang@users.noreply.github.com> * lewc review + duplicate --------- Signed-off-by: Contrabang <91113370+Contrabang@users.noreply.github.com> Co-authored-by: 1080pCat <96908085+1080pCat@users.noreply.github.com> --- code/__HELPERS/trait_helpers.dm | 2 ++ code/_globalvars/traits.dm | 3 +- code/datums/components/zombie_regen.dm | 2 +- .../objects/items/weapons/dnascrambler.dm | 9 +----- .../antagonists/zombie/zombie_spells.dm | 2 +- code/modules/awaymissions/mob_spawn.dm | 27 ++++++++++++++++ .../mob/living/carbon/human/human_mob.dm | 10 ++++++ .../living/carbon/human/species/_species.dm | 32 ++++++++++--------- 8 files changed, 61 insertions(+), 26 deletions(-) diff --git a/code/__HELPERS/trait_helpers.dm b/code/__HELPERS/trait_helpers.dm index cb1146caf35..dc47f48dad1 100644 --- a/code/__HELPERS/trait_helpers.dm +++ b/code/__HELPERS/trait_helpers.dm @@ -231,6 +231,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_CAN_STRIP "can_strip" // This mob can strip other mobs. #define TRAIT_CLING_BURSTING "cling_bursting" // This changeling is about to burst into a headslug, block cremation / gibber to prevent nullspace issues #define TRAIT_I_WANT_BRAINS "mob_zombie" // A general trait for tracking if the mob is a zombie. +#define TRAIT_NON_INFECTIOUS_ZOMBIE "non_infectious_zombie" // A trait for checking if a zombie shouldn't be able to infect other people +#define TRAIT_NPC_ZOMBIE "npc_zombie" // A trait for checking if a zombie should act like an NPC and attack #define TRAIT_ABSTRACT_HANDS "abstract_hands" // Mobs with this trait can only pick up abstract items. #define TRAIT_LANGUAGE_LOCKED "language_locked" // cant add/remove languages until removed (excludes babel because fuck everything i guess) #define TRAIT_HAS_IV_BAG "iv_bag" // Used to check if there is an active IV bag. Currently blocks another IV bags from being inserted. diff --git a/code/_globalvars/traits.dm b/code/_globalvars/traits.dm index 03b2aa2b9b1..841cbcebe23 100644 --- a/code/_globalvars/traits.dm +++ b/code/_globalvars/traits.dm @@ -96,7 +96,8 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_I_WANT_BRAINS" = TRAIT_I_WANT_BRAINS, "TRAIT_ABSTRACT_HANDS" = TRAIT_ABSTRACT_HANDS, "TRAIT_LANGUAGE_LOCKED" = TRAIT_LANGUAGE_LOCKED, - "TRAIT_HAS_IV_BAG" = TRAIT_HAS_IV_BAG + "TRAIT_HAS_IV_BAG" = TRAIT_HAS_IV_BAG, + "TRAIT_NON_INFECTIOUS_ZOMBIE" = TRAIT_NON_INFECTIOUS_ZOMBIE ), /datum/mind = list( diff --git a/code/datums/components/zombie_regen.dm b/code/datums/components/zombie_regen.dm index a23f2e81037..561446571e3 100644 --- a/code/datums/components/zombie_regen.dm +++ b/code/datums/components/zombie_regen.dm @@ -36,7 +36,7 @@ return if(zomboid.client || isLivingSSD(zomboid)) return - if(zomboid.last_known_ckey && !zomboid.key) // make sure they were player inhabited and not admin ghosted + if((zomboid.last_known_ckey || HAS_TRAIT(zomboid, TRAIT_NPC_ZOMBIE)) && !zomboid.key) // make sure they were player inhabited and not admin ghosted mindless_hunger() /datum/component/zombie_regen/proc/zombie_rejuv() diff --git a/code/game/objects/items/weapons/dnascrambler.dm b/code/game/objects/items/weapons/dnascrambler.dm index c977da3fda7..3fb6d3d8122 100644 --- a/code/game/objects/items/weapons/dnascrambler.dm +++ b/code/game/objects/items/weapons/dnascrambler.dm @@ -40,14 +40,7 @@ /obj/item/dnascrambler/proc/injected(mob/living/carbon/human/target, mob/living/carbon/user) if(istype(target)) var/mob/living/carbon/human/H = target - scramble(1, H, 100) - H.real_name = random_name(H.gender, H.dna.species.name) //Give them a name that makes sense for their species. - H.sync_organ_dna(assimilate = 1) - H.update_body() - H.reset_hair() //No more winding up with hairstyles you're not supposed to have, and blowing your cover. - H.reset_markings() //...Or markings. - H.dna.ResetUIFrom(H) - H.flavor_text = "" + H.get_dna_scrambled() target.update_icons() add_attack_logs(user, target, "injected with [src]") diff --git a/code/modules/antagonists/zombie/zombie_spells.dm b/code/modules/antagonists/zombie/zombie_spells.dm index b1526e8a254..5d30f5a6d27 100644 --- a/code/modules/antagonists/zombie/zombie_spells.dm +++ b/code/modules/antagonists/zombie/zombie_spells.dm @@ -128,7 +128,7 @@ /obj/item/zombie_claw/proc/try_infect(mob/living/carbon/human/target, mob/living/user) - if(!ishuman(target)) + if(!ishuman(target) || HAS_TRAIT(user, TRAIT_NON_INFECTIOUS_ZOMBIE)) return if(!(user.zone_selected in list(BODY_ZONE_CHEST, BODY_ZONE_HEAD))) to_chat(user, "Our infection cannot spread without their head or chest.") diff --git a/code/modules/awaymissions/mob_spawn.dm b/code/modules/awaymissions/mob_spawn.dm index f750c7d850d..399e91b4117 100644 --- a/code/modules/awaymissions/mob_spawn.dm +++ b/code/modules/awaymissions/mob_spawn.dm @@ -183,6 +183,8 @@ assignedrole = "Ghost Role" var/husk = null + /// Should we fully dna-scramble these humans? + var/dna_scrambled = FALSE //these vars are for lazy mappers to override parts of the outfit //these cannot be null by default, or mappers cannot set them to null if they want nothing in that slot var/uniform = -1 @@ -259,6 +261,9 @@ H.s_tone = random_skin_tone() H.skin_colour = rand_hex_color() + if(dna_scrambled) + H.get_dna_scrambled() + H.update_body(rebuild_base = TRUE) if(outfit) @@ -581,6 +586,28 @@ mob_species = /datum/species/skeleton/brittle mob_gender = NEUTER +/obj/effect/mob_spawn/human/alive/zombie + name = "NPC Zombie (Infectious)" + icon = 'icons/mob/human.dmi' + icon_state = "zombie_s" + roundstart = TRUE + dna_scrambled = TRUE + +/obj/effect/mob_spawn/human/alive/zombie/equip(mob/living/carbon/human/H) + ADD_TRAIT(H, TRAIT_NPC_ZOMBIE, ROUNDSTART_TRAIT) + H.ForceContractDisease(new /datum/disease/zombie) + for(var/datum/disease/zombie/zomb in H.viruses) + zomb.stage = 8 + + return ..() + +/obj/effect/mob_spawn/human/alive/zombie/non_infectious + name = "NPC Zombie (Non-infectious)" + +/obj/effect/mob_spawn/human/alive/zombie/non_infectious/equip(mob/living/carbon/human/H) + ADD_TRAIT(H, TRAIT_NON_INFECTIOUS_ZOMBIE, ROUNDSTART_TRAIT) + return ..() + ////////Non-human spawners//////// /obj/effect/mob_spawn/mouse diff --git a/code/modules/mob/living/carbon/human/human_mob.dm b/code/modules/mob/living/carbon/human/human_mob.dm index 93f7b6ecf15..07f388cc4c1 100644 --- a/code/modules/mob/living/carbon/human/human_mob.dm +++ b/code/modules/mob/living/carbon/human/human_mob.dm @@ -2046,3 +2046,13 @@ Eyes need to have significantly high darksight to shine unless the mob has the X return dna.species.unarmed return zombie.claw_attack +/mob/living/carbon/human/proc/get_dna_scrambled() + scramble(1, src, 100) + real_name = random_name(gender, dna.species.name) // Give them a name that makes sense for their species. + sync_organ_dna(assimilate = 1) + update_body() + reset_hair() // No more winding up with hairstyles you're not supposed to have, and blowing your cover. + reset_markings() // ...Or markings. + dna.ResetUIFrom(src) + flavor_text = "" + diff --git a/code/modules/mob/living/carbon/human/species/_species.dm b/code/modules/mob/living/carbon/human/species/_species.dm index 56fdac5bc74..b81dace99f1 100644 --- a/code/modules/mob/living/carbon/human/species/_species.dm +++ b/code/modules/mob/living/carbon/human/species/_species.dm @@ -1087,17 +1087,18 @@ It'll return null if the organ doesn't correspond, so include null checks when u playsound(user.loc, 'sound/misc/moist_impact.ogg', 50, TRUE) user.do_attack_animation(target, ATTACK_EFFECT_BITE) target.apply_damage(20, BRUTE, user.zone_selected) - if(!target.HasDisease(/datum/disease/zombie)) - var/datum/disease/zombie/zomb = new /datum/disease/zombie - if(target.CanContractDisease(zomb)) // biosuit aint going to protect you buddy - target.ForceContractDisease(zomb) - target.Dizzy(10 SECONDS) - target.Confused(10 SECONDS) - else - qdel(zomb) + if(!HAS_TRAIT(user, TRAIT_NON_INFECTIOUS_ZOMBIE)) + if(!target.HasDisease(/datum/disease/zombie)) + var/datum/disease/zombie/zomb = new /datum/disease/zombie + if(target.CanContractDisease(zomb)) // biosuit aint going to protect you buddy + target.ForceContractDisease(zomb) + target.Dizzy(10 SECONDS) + target.Confused(10 SECONDS) + else + qdel(zomb) - for(var/datum/disease/zombie/zomb in target.viruses) - zomb.stage = max(rand(3, 4), zomb.stage) + for(var/datum/disease/zombie/zomb in target.viruses) + zomb.stage = max(rand(3, 4), zomb.stage) qdel(grabby) return TRUE @@ -1126,12 +1127,13 @@ It'll return null if the organ doesn't correspond, so include null checks when u eat_brain.custom_pain("OH GOD!!! THEY'RE EATING MY [uppertext(eat_brain.name)]!!") // gnarly user.visible_message("[user] digs their claws into [target]'s [brain_house.name], eating their [eat_brain]!", "We feast on [target]'s brains.") - if(!target.HasDisease(/datum/disease/zombie)) - var/datum/disease/zombie/zomb = new /datum/disease/zombie - target.ContractDisease(zomb) + if(!HAS_TRAIT(user, TRAIT_NON_INFECTIOUS_ZOMBIE)) + if(!target.HasDisease(/datum/disease/zombie)) + var/datum/disease/zombie/zomb = new /datum/disease/zombie + target.ContractDisease(zomb) - for(var/datum/disease/zombie/zomb in target.viruses) - zomb.stage = max(5, zomb.stage) + for(var/datum/disease/zombie/zomb in target.viruses) + zomb.stage = max(5, zomb.stage) if(!do_mob(user, target, 1 SECONDS)) return