diff --git a/code/__SPLURTCODE/DEFINES/traits.dm b/code/__SPLURTCODE/DEFINES/traits.dm index 4dcb8e375bca..2ab293497828 100644 --- a/code/__SPLURTCODE/DEFINES/traits.dm +++ b/code/__SPLURTCODE/DEFINES/traits.dm @@ -27,3 +27,4 @@ #define TRAIT_NUDIST "Nudist" #define TRAIT_CLOTH_EATER "cloth_eater" #define TRAIT_WEREWOLF "Werewolf" +#define TRAIT_UNDEAD_QUIRK "quirk_zombie" diff --git a/modular_splurt/code/controllers/subsystem/processing/quirks.dm b/modular_splurt/code/controllers/subsystem/processing/quirks.dm new file mode 100644 index 000000000000..e32519d33b1c --- /dev/null +++ b/modular_splurt/code/controllers/subsystem/processing/quirks.dm @@ -0,0 +1,28 @@ +// Add incompatible quirks +/datum/controller/subsystem/processing/quirks/Initialize(timeofday) + . = ..() + + // Prevent incompatible quirks + LAZYADD(quirk_blacklist, list( + // BLOCKED: Mechanic + // Zombies can't regenerate blood + list("Postmortem Flesh","Polycythemia vera"), + + // BLOCKED: Mechanic + // Zombies are slower and clumsier + list("Postmortem Flesh","Freerunning"), + list("Postmortem Flesh","Light Step"), + list("Postmortem Flesh","Quick Step"), + + // BLOCKED: Mechanic + // Zombies can't evaluate wounds properly + list("Postmortem Flesh","Self-Aware"), + + // BLOCKED: Mechanic + // Zombies are already cold blooded + list("Postmortem Flesh","Cold-blooded"), + + // BLOCKED: Mechanic + // Zombies already can't be cloned + list("Postmortem Flesh","DNC Order"), + )) diff --git a/modular_splurt/code/datums/traits/neutral.dm b/modular_splurt/code/datums/traits/neutral.dm index 5fdca5e6f58e..7895271b1af5 100644 --- a/modular_splurt/code/datums/traits/neutral.dm +++ b/modular_splurt/code/datums/traits/neutral.dm @@ -678,3 +678,179 @@ var/obj/item/clothing/mask/gas/cosmetic/gasmask = new(get_turf(quirk_holder)) // Uses a custom gas mask H.equip_to_slot(gasmask, ITEM_SLOT_MASK) H.regenerate_icons() + +/datum/quirk/zombie + name = "Postmortem Flesh" + desc = "You've been freed from the mortal coil, and passed on to become a zombie! Your body rapidly regenerates, and can't be put into critical condition. However, you won't be able to cheat death a second time..." + value = 2 + medical_record_text = "Scans indicate the patient to be deceased." + mob_trait = TRAIT_UNDEAD_QUIRK + gain_text = span_notice("Your flesh rots and burns as it clings to life.") + lose_text = span_warning("The mortal coil binds you once again.") + processing_quirk = FALSE // Don't process by default + + // Amount of damage to heal + var/regen_amount = -2 + + // Time in ticks after taking damage before regenerating + var/regen_delay = 60 + + // Cooldown before regeneration can occur + var/regen_cooldown + +/datum/quirk/zombie/add() + // Define quirk mob + var/mob/living/carbon/human/quirk_mob = quirk_holder + + // Add quirk traits, based on zombie race + ADD_TRAIT(quirk_mob,TRAIT_EASYDISMEMBER,TRAIT_UNDEAD_QUIRK) + ADD_TRAIT(quirk_mob,TRAIT_LIMBATTACHMENT,TRAIT_UNDEAD_QUIRK) + ADD_TRAIT(quirk_mob,TRAIT_NOBREATH,TRAIT_UNDEAD_QUIRK) + ADD_TRAIT(quirk_mob,TRAIT_FAKEDEATH,TRAIT_UNDEAD_QUIRK) + ADD_TRAIT(quirk_mob,TRAIT_NOSOFTCRIT,TRAIT_UNDEAD_QUIRK) + ADD_TRAIT(quirk_mob,TRAIT_NOHARDCRIT,TRAIT_UNDEAD_QUIRK) + ADD_TRAIT(quirk_mob,TRAIT_NOCLONE,TRAIT_UNDEAD_QUIRK) + ADD_TRAIT(quirk_mob,TRAIT_NOMARROW,TRAIT_UNDEAD_QUIRK) + ADD_TRAIT(quirk_mob,TRAIT_COLDBLOODED,TRAIT_UNDEAD_QUIRK) + + // Check for halloween + if(SSevents.holidays && SSevents.holidays[HALLOWEEN]) + // Prevent dying by traditional means + ADD_TRAIT(quirk_mob, TRAIT_NODEATH,TRAIT_UNDEAD_QUIRK) + + // Double regeneration rate + regen_amount *= 3 + + // Half cooldown time + regen_delay *= 0.5 + + // Not halloween + else + // Add speed reduction + quirk_mob.add_movespeed_modifier(/datum/movespeed_modifier/undead_quirk_speedmod, TRUE) + + // Add undead biotype + quirk_mob.mob_biotypes |= MOB_UNDEAD + + // Set screwy health HUD + quirk_mob.set_screwyhud(SCREWYHUD_HEALTHY) + + // Add register signal for taking damage + RegisterSignal(quirk_holder, COMSIG_MOB_APPLY_DAMAGE, .proc/set_damage_cooldown, TRUE) + +/datum/quirk/zombie/post_add() + // Check for halloween + if(SSevents.holidays && SSevents.holidays[HALLOWEEN]) + // Display notice message + to_chat(quirk_holder, span_alert("The spooky season has empowered you with the ability to avoid death forever! Nothing can stop you now!")) + +/datum/quirk/zombie/on_spawn() + // Get organ target: Infection + var/obj/item/organ/undead_infection/organ_infection = quirk_holder.getorganslot(ORGAN_SLOT_ZOMBIE) + + // Check if zombie organ exists + if(!organ_infection) + // Create and insert organ + organ_infection = new() + organ_infection.Insert(quirk_holder) + + // Get organ target: Tongue + var/obj/item/organ/tongue/old_tongue = quirk_holder.getorganslot(ORGAN_SLOT_TONGUE) + var/obj/item/organ/tongue/zombie/new_tongue = new + + // Replace tongue + qdel(old_tongue) + new_tongue.Insert(quirk_holder) + +/datum/quirk/zombie/remove() + // Define quirk mob + var/mob/living/carbon/human/quirk_mob = quirk_holder + + // Check if quirk mob still exists + if(!istype(quirk_mob)) + return + + // Define infection organ + var/obj/item/organ/undead_infection/organ_infection = quirk_mob.getorganslot(ORGAN_SLOT_ZOMBIE) + + // Check if zombie organ exists + if(organ_infection) + // Remove organ + organ_infection.Remove() + + // Remove quirk traits + REMOVE_TRAIT(quirk_mob,TRAIT_EASYDISMEMBER,TRAIT_UNDEAD_QUIRK) + REMOVE_TRAIT(quirk_mob,TRAIT_LIMBATTACHMENT,TRAIT_UNDEAD_QUIRK) + REMOVE_TRAIT(quirk_mob,TRAIT_NOBREATH,TRAIT_UNDEAD_QUIRK) + REMOVE_TRAIT(quirk_mob,TRAIT_FAKEDEATH,TRAIT_UNDEAD_QUIRK) + REMOVE_TRAIT(quirk_mob,TRAIT_NOSOFTCRIT,TRAIT_UNDEAD_QUIRK) + REMOVE_TRAIT(quirk_mob,TRAIT_NOMARROW,TRAIT_UNDEAD_QUIRK) + REMOVE_TRAIT(quirk_mob,TRAIT_NOCLONE,TRAIT_UNDEAD_QUIRK) + REMOVE_TRAIT(quirk_mob,TRAIT_NODEATH,TRAIT_UNDEAD_QUIRK) + REMOVE_TRAIT(quirk_mob,TRAIT_COLDBLOODED,TRAIT_UNDEAD_QUIRK) + + // Remove undead biotype + quirk_mob.mob_biotypes -= MOB_UNDEAD + + // Remove speed reduction + quirk_mob.remove_movespeed_modifier(/datum/movespeed_modifier/undead_quirk_speedmod, TRUE) + + // Remove screwy health HUD + quirk_mob.set_screwyhud(SCREWYHUD_NONE) + + // Remove signal for taking damage + UnregisterSignal(quirk_holder, COMSIG_MOB_APPLY_DAMAGE) + +/datum/quirk/zombie/on_process() + // Check cooldown time + if(regen_cooldown > world.time) + return + + // Define quirk mob + var/mob/living/carbon/human/quirk_mob = quirk_holder + + // Check if quick holder is damaged + if(quirk_mob.health >= quirk_mob.maxHealth) + // Stop processing and return + STOP_PROCESSING(SSquirks, src) + return + + // Check for sufficient blood + if(quirk_mob.blood_volume <= BLOOD_VOLUME_SURVIVE) + return + + // Define initial health + var/health_start = quirk_mob.health + + // Check for brute damage + if(quirk_mob.getBruteLoss()) + // Remove brute damage + quirk_mob.adjustBruteLoss(regen_amount) + + // Check for burn damage + if(quirk_mob.getFireLoss()) + // Remove burn damage + quirk_mob.adjustFireLoss(regen_amount) + + // Check for toxin damage + if(quirk_mob.getToxLoss()) + // Remove toxin damage + quirk_mob.adjustToxLoss(regen_amount) + + // Check for cellular damage + if(quirk_mob.getCloneLoss()) + // Remove toxin damage + quirk_mob.adjustCloneLoss(regen_amount) + + // Remove blood as compensation for healing + // Value is determined by amount healed + quirk_mob.blood_volume -= (quirk_mob.health - health_start) + +/datum/quirk/zombie/proc/set_damage_cooldown() + SIGNAL_HANDLER + + // Set cooldown time + regen_cooldown = world.time + regen_delay + + // Start processing + START_PROCESSING(SSquirks, src) diff --git a/modular_splurt/code/modules/mob/living/carbon/human/species_types/zombies2.dm b/modular_splurt/code/modules/mob/living/carbon/human/species_types/zombies2.dm index e812380fbc60..789b0bc4ecb7 100644 --- a/modular_splurt/code/modules/mob/living/carbon/human/species_types/zombies2.dm +++ b/modular_splurt/code/modules/mob/living/carbon/human/species_types/zombies2.dm @@ -415,3 +415,13 @@ icon_state = "pill5" color = "#830000" list_reagents = list(/datum/reagent/draughtofundeath = 1) + +// Block round-start selection for zombies +/datum/species/mammal/undead/check_roundstart_eligible() + return FALSE + +/datum/species/insect/undead/check_roundstart_eligible() + return FALSE + +/datum/species/lizard/undead/check_roundstart_eligible() + return FALSE diff --git a/modular_splurt/code/modules/movespeed/modifiers/mobs.dm b/modular_splurt/code/modules/movespeed/modifiers/mobs.dm new file mode 100644 index 000000000000..d871ced74641 --- /dev/null +++ b/modular_splurt/code/modules/movespeed/modifiers/mobs.dm @@ -0,0 +1,4 @@ +/datum/movespeed_modifier/undead_quirk_speedmod + multiplicative_slowdown = 1.4 + blacklisted_movetypes = FLOATING|FLYING + flags = IGNORE_NOSLOW diff --git a/tgstation.dme b/tgstation.dme index b07269057e2e..b895b0555294 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -4302,6 +4302,7 @@ #include "modular_splurt\code\controllers\subsystem\redbot.dm" #include "modular_splurt\code\controllers\subsystem\ticker.dm" #include "modular_splurt\code\controllers\subsystem\processing\station.dm" +#include "modular_splurt\code\controllers\subsystem\processing\quirks.dm" #include "modular_splurt\code\datums\ai_laws.dm" #include "modular_splurt\code\datums\bark.dm" #include "modular_splurt\code\datums\dna.dm" @@ -4720,6 +4721,7 @@ #include "modular_splurt\code\modules\mob\living\simple_animal\hostile\megafauna\blood_drunk_miner.dm" #include "modular_splurt\code\modules\mob\living\simple_animal\hostile\megafauna\king_of_goats.dm" #include "modular_splurt\code\modules\mob\living\simple_animal\hostile\megafauna\sand.dm" +#include "modular_splurt\code\modules\movespeed\modifiers\mobs.dm" #include "modular_splurt\code\modules\paperwork\pen.dm" #include "modular_splurt\code\modules\photography\photos\album.dm" #include "modular_splurt\code\modules\photography\photos\photo.dm"