From 1ad5ec1fc35f3cd4f2ce2cc35f89700eab5b4f84 Mon Sep 17 00:00:00 2001 From: SkyratBot <59378654+SkyratBot@users.noreply.github.com> Date: Thu, 4 Jul 2024 07:13:59 +0200 Subject: [PATCH] [MIRROR] Refactors genetic meltdowns into datums (#28588) * Refactors genetic meltdowns into datums (#84558) ## About The Pull Request Genetic meltdowns now use datums instead of a prob and switch monstrocity, making them far more readable. Requested by Jacquerel on discord. Additionally, removed 0.83% chance for a meltdown to turn you into a dullahan, as those are extremely broken right now. Closes #83592 ## Why It's Good For The Game This system is much nicer, readable and more extendable than the current one. ## Changelog :cl: del: You can no longer get turned into a dullahan by a genetic meltdown refactor: Refactored genetic meltdown code into datums, making it more extendable. /:cl: --------- Co-authored-by: Time-Green <7501474+Time-Green@ users.noreply.github.com> * Refactors genetic meltdowns into datums --------- Co-authored-by: SmArtKar <44720187+SmArtKar@users.noreply.github.com> Co-authored-by: Time-Green <7501474+Time-Green@ users.noreply.github.com> --- code/datums/dna.dm | 97 ++++------------- code/datums/instability_meltdown.dm | 163 ++++++++++++++++++++++++++++ tgstation.dme | 1 + 3 files changed, 185 insertions(+), 76 deletions(-) create mode 100644 code/datums/instability_meltdown.dm diff --git a/code/datums/dna.dm b/code/datums/dna.dm index 92c8a2dc45a..3c405619456 100644 --- a/code/datums/dna.dm +++ b/code/datums/dna.dm @@ -107,7 +107,10 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) var/stability = 100 ///Did we take something like mutagen? In that case we cant get our genes scanned to instantly cheese all the powers. var/scrambled = FALSE - + /// Weighted list of nonlethal meltdowns + var/static/list/nonfatal_meltdowns = list() + /// Weighted list of lethal meltdowns + var/static/list/fatal_meltdowns = list() /datum/dna/New(mob/living/new_holder) if(istype(new_holder)) @@ -958,81 +961,23 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) var/instability = -dna.stability dna.remove_all_mutations() dna.stability = 100 - if(prob(max(70-instability,0))) - switch(rand(0,11)) //not complete and utter death - if(0) - monkeyize() - if(1) - gain_trauma(/datum/brain_trauma/severe/paralysis/paraplegic) - new/obj/vehicle/ridden/wheelchair(get_turf(src)) //don't buckle, because I can't imagine to plethora of things to go through that could otherwise break - to_chat(src, span_warning("My flesh turned into a wheelchair and I can't feel my legs.")) - if(2) - corgize() - if(3) - to_chat(src, span_notice("Oh, I actually feel quite alright!")) - if(4) - to_chat(src, span_notice("Oh, I actually feel quite alright!")) - physiology.damage_resistance -= 20000 //you thought - if(5) - to_chat(src, span_notice("Oh, I actually feel quite alright!")) - reagents.add_reagent(/datum/reagent/aslimetoxin, 10) - if(6) - apply_status_effect(/datum/status_effect/go_away) - if(7) - to_chat(src, span_notice("Oh, I actually feel quite alright!")) - ForceContractDisease(new /datum/disease/decloning) // slow acting, non-viral GBS - if(8) - var/list/elligible_organs = list() - for(var/obj/item/organ/internal/internal_organ in organs) //make sure we dont get an implant or cavity item - elligible_organs += internal_organ - vomit(VOMIT_CATEGORY_DEFAULT, lost_nutrition = 10) - if(elligible_organs.len) - var/obj/item/organ/O = pick(elligible_organs) - O.Remove(src) - visible_message(span_danger("[src] vomits up [p_their()] [O.name]!"), span_danger("You vomit up your [O.name]")) //no "vomit up your heart" - O.forceMove(drop_location()) - if(prob(20)) - O.animate_atom_living() - if(9 to 10) - ForceContractDisease(new/datum/disease/gastrolosis()) - to_chat(src, span_notice("Oh, I actually feel quite alright!")) - if(11) - to_chat(src, span_notice("Your DNA mutates into the ultimate biological form!")) - crabize() - else - switch(rand(0,6)) - if(0) - investigate_log("has been gibbed by DNA instability.", INVESTIGATE_DEATHS) - gib(DROP_ALL_REMAINS) - if(1) - investigate_log("has been dusted by DNA instability.", INVESTIGATE_DEATHS) - dust() - if(2) - investigate_log("has been transformed into a statue by DNA instability.", INVESTIGATE_DEATHS) - death() - petrify(statue_timer = INFINITY, save_brain = FALSE) - ghostize(FALSE) - if(3) - if(prob(95)) - var/obj/item/bodypart/BP = get_bodypart(pick(BODY_ZONE_CHEST,BODY_ZONE_HEAD)) - if(BP) - BP.dismember() - else - investigate_log("has been gibbed by DNA instability.", INVESTIGATE_DEATHS) - gib(DROP_ALL_REMAINS) - else - set_species(/datum/species/dullahan) - if(4) - visible_message(span_warning("[src]'s skin melts off!"), span_boldwarning("Your skin melts off!")) - spawn_gibs() - set_species(/datum/species/skeleton) - if(prob(90)) - addtimer(CALLBACK(src, PROC_REF(death)), 3 SECONDS) - if(5) - to_chat(src, span_phobia("LOOK UP!")) - addtimer(CALLBACK(src, PROC_REF(something_horrible_mindmelt)), 3 SECONDS) - if(6) - slow_psykerize() + + var/nonfatal = prob(max(70-instability, 0)) + + if(!dna.nonfatal_meltdowns.len) + for(var/datum/instability_meltdown/meltdown_type as anything in typecacheof(/datum/instability_meltdown, ignore_root_path = TRUE)) + if(initial(meltdown_type.abstract_type) == meltdown_type) + continue + + if (initial(meltdown_type.fatal)) + dna.fatal_meltdowns[meltdown_type] = initial(meltdown_type.meltdown_weight) + continue + + dna.nonfatal_meltdowns[meltdown_type] = initial(meltdown_type.meltdown_weight) + + var/picked_type = pick_weight(nonfatal ? dna.nonfatal_meltdowns : dna.fatal_meltdowns) + var/datum/instability_meltdown/meltdown = new picked_type + meltdown.meltdown(src) /mob/living/carbon/human/proc/something_horrible_mindmelt() if(!is_blind()) diff --git a/code/datums/instability_meltdown.dm b/code/datums/instability_meltdown.dm new file mode 100644 index 00000000000..d8e6fbd77ac --- /dev/null +++ b/code/datums/instability_meltdown.dm @@ -0,0 +1,163 @@ +/// A possible genetic meltdown that occurs when someone exceeds 100 genetic instability +/datum/instability_meltdown + /// How likely a meltdown is to be picked + var/meltdown_weight = 1 + /// If this meltdown is considered "fatal" or not + var/fatal = FALSE + /// Used to ensure that abstract subtypes do not get picked + var/abstract_type = /datum/instability_meltdown + +/// Code that runs when this meltdown is picked +/datum/instability_meltdown/proc/meltdown(mob/living/carbon/human/victim) + return + +// Nonfatal meltdowns + +/// Turns you into a monkey +/datum/instability_meltdown/monkey + +/datum/instability_meltdown/monkey/meltdown(mob/living/carbon/human/victim) + victim.monkeyize() + +/// Gives you brain trauma that makes your legs disfunctional and gifts you a wheelchair +/datum/instability_meltdown/paraplegic + +/datum/instability_meltdown/paraplegic/meltdown(mob/living/carbon/human/victim) + victim.gain_trauma(/datum/brain_trauma/severe/paralysis/paraplegic) + new /obj/vehicle/ridden/wheelchair(get_turf(victim)) + to_chat(victim, span_warning("My flesh turned into a wheelchair and I can't feel my legs.")) + +/// Turns you into a corgi +/datum/instability_meltdown/corgi + +/datum/instability_meltdown/corgi/meltdown(mob/living/carbon/human/victim) + victim.corgize() + +/// Does nothing +/datum/instability_meltdown/alright + +/datum/instability_meltdown/alright/meltdown(mob/living/carbon/human/victim) + to_chat(victim, span_notice("Oh, I actually feel quite alright!")) + +/// Gives you the same text as above but now when you're hit you take 200 times more damage +/datum/instability_meltdown/not_alright + +/datum/instability_meltdown/not_alright/meltdown(mob/living/carbon/human/victim) + to_chat(victim, span_notice("Oh, I actually feel quite alright!")) + victim.physiology.damage_resistance -= 20000 //you thought + victim.log_message("has received x200 damage multiplier from [type] genetic meltdown") + +/// Turns you into a slime +/datum/instability_meltdown/slime + +/datum/instability_meltdown/slime/meltdown(mob/living/carbon/human/victim) + to_chat(victim, span_notice("Oh, I actually feel quite alright!")) + victim.reagents.add_reagent(/datum/reagent/aslimetoxin, 10) + +/// Makes you phase through walls into a random direction +/datum/instability_meltdown/yeet + +/datum/instability_meltdown/yeet/meltdown(mob/living/carbon/human/victim) + victim.apply_status_effect(/datum/status_effect/go_away) + +/// Makes you take cell damage and gibs you after some time +/datum/instability_meltdown/decloning + +/datum/instability_meltdown/decloning/meltdown(mob/living/carbon/human/victim) + to_chat(src, span_notice("Oh, I actually feel quite alright!")) + victim.ForceContractDisease(new /datum/disease/decloning) // slow acting, non-viral GBS + +/// Makes you vomit up a random organ +/datum/instability_meltdown/organ_vomit + +/datum/instability_meltdown/organ_vomit/meltdown(mob/living/carbon/human/victim) + var/list/elligible_organs = list() + for(var/obj/item/organ/internal/internal_organ in victim.organs) //make sure we dont get an implant or cavity item + elligible_organs += internal_organ + victim.vomit(VOMIT_CATEGORY_DEFAULT, lost_nutrition = 10) + if(!elligible_organs.len) + return + var/obj/item/organ/picked_organ = pick(elligible_organs) + picked_organ.Remove(src) + victim.visible_message(span_danger("[victim] vomits up [p_their()] [picked_organ.name]!"), span_danger("You vomit up your [picked_organ.name]")) //no "vomit up your heart" + picked_organ.forceMove(victim.drop_location()) + if(prob(20)) + picked_organ.animate_atom_living() + +/// Turns you into a snail +/datum/instability_meltdown/snail + meltdown_weight = 2 + +/datum/instability_meltdown/snail/meltdown(mob/living/carbon/human/victim) + to_chat(victim, span_notice("Oh, I actually feel quite alright!")) + victim.ForceContractDisease(new/datum/disease/gastrolosis()) + +/// Turns you into the ultimate lifeform +/datum/instability_meltdown/crab + +/datum/instability_meltdown/crab/meltdown(mob/living/carbon/human/victim) + to_chat(victim, span_notice("Your DNA mutates into the ultimate biological form!")) + victim.crabize() + +// Fatal meltdowns + +/datum/instability_meltdown/fatal + fatal = TRUE + abstract_type = /datum/instability_meltdown/fatal + +/// Instantly gibs you +/datum/instability_meltdown/fatal/gib + +/datum/instability_meltdown/fatal/gib/meltdown(mob/living/carbon/human/victim) + victim.investigate_log("has been gibbed by DNA instability.", INVESTIGATE_DEATHS) + victim.gib(DROP_ALL_REMAINS) + +/// Dusts you +/datum/instability_meltdown/fatal/dust + +/datum/instability_meltdown/fatal/dust/meltdown(mob/living/carbon/human/victim) + victim.investigate_log("has been dusted by DNA instability.", INVESTIGATE_DEATHS) + victim.dust() + +/// Turns you into a statue +/datum/instability_meltdown/fatal/petrify + +/datum/instability_meltdown/fatal/petrify/meltdown(mob/living/carbon/human/victim) + victim.investigate_log("has been transformed into a statue by DNA instability.", INVESTIGATE_DEATHS) + victim.death() + victim.petrify(statue_timer = INFINITY, save_brain = FALSE) + victim.ghostize(FALSE) + +/// Either dismembers you, or if unable to, gibs you +/datum/instability_meltdown/fatal/dismember + +/datum/instability_meltdown/fatal/dismember/meltdown(mob/living/carbon/human/victim) + var/obj/item/bodypart/part = victim.get_bodypart(pick(BODY_ZONE_CHEST,BODY_ZONE_HEAD)) + if(part) + part.dismember() + return + victim.investigate_log("has been gibbed by DNA instability.", INVESTIGATE_DEATHS) + victim.gib(DROP_ALL_REMAINS) + +/// Turns you into a skeleton, with a high chance of killing you soon after +/datum/instability_meltdown/fatal/skeletonize + +/datum/instability_meltdown/fatal/skeletonize/meltdown(mob/living/carbon/human/victim) + victim.visible_message(span_warning("[victim]'s skin melts off!"), span_boldwarning("Your skin melts off!")) + victim.spawn_gibs() + victim.set_species(/datum/species/skeleton) + if(prob(90)) + addtimer(CALLBACK(victim, TYPE_PROC_REF(/mob/living, death)), 3 SECONDS) + +/// Makes you look up and melts out your eyes +/datum/instability_meltdown/fatal/ceiling + +/datum/instability_meltdown/fatal/ceiling/meltdown(mob/living/carbon/human/victim) + to_chat(victim, span_phobia("LOOK UP!")) + addtimer(CALLBACK(victim, TYPE_PROC_REF(/mob/living/carbon/human, something_horrible_mindmelt)), 3 SECONDS) + +/// Slowly turns you into a psyker +/datum/instability_meltdown/fatal/psyker + +/datum/instability_meltdown/fatal/psyker/meltdown(mob/living/carbon/human/victim) + victim.slow_psykerize() diff --git a/tgstation.dme b/tgstation.dme index bf968a6ada9..981e7facb97 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -880,6 +880,7 @@ #include "code\datums\hotkeys_help.dm" #include "code\datums\http.dm" #include "code\datums\hud.dm" +#include "code\datums\instability_meltdown.dm" #include "code\datums\json_database.dm" #include "code\datums\json_savefile.dm" #include "code\datums\lazy_template.dm"