From 4732787733433a3816ea394f355bab92e41193e9 Mon Sep 17 00:00:00 2001 From: Iajret Creature <122297233+Steals-The-PRs@users.noreply.github.com> Date: Mon, 11 Dec 2023 00:59:55 +0300 Subject: [PATCH] [MIRROR] Changes Virology Rather Than Killing It [MDB IGNORE] (#1053) * Changes Virology Rather Than Killing It (#79854) --------- Co-authored-by: SkyratBot <59378654+SkyratBot@users.noreply.github.com> Co-authored-by: Higgin --- code/__DEFINES/diseases.dm | 55 +++++++ code/datums/diseases/_MobProcs.dm | 2 +- code/datums/diseases/_disease.dm | 135 +++++++++++++++++- code/datums/diseases/advance/advance.dm | 26 ++-- .../advance/floor_diseases/carpellosis.dm | 2 +- code/datums/diseases/brainrot.dm | 1 + code/datums/diseases/chronic_illness.dm | 1 + code/datums/diseases/decloning.dm | 3 +- code/datums/diseases/dna_spread.dm | 1 + code/datums/diseases/gastrolisis.dm | 3 +- code/datums/diseases/gbs.dm | 1 + code/datums/diseases/magnitis.dm | 1 + code/datums/diseases/parrotpossession.dm | 2 +- code/datums/diseases/retrovirus.dm | 1 + code/datums/diseases/rhumba_beat.dm | 1 + code/datums/diseases/transformation.dm | 1 + code/datums/diseases/wizarditis.dm | 1 + code/datums/id_trim/jobs.dm | 5 +- .../crates_lockers/closets/l3closet.dm | 4 + .../antagonists/disease/disease_disease.dm | 4 + .../antagonists/revenant/revenant_blight.dm | 2 +- .../chemistry/reagents/other_reagents.dm | 10 +- 22 files changed, 242 insertions(+), 20 deletions(-) diff --git a/code/__DEFINES/diseases.dm b/code/__DEFINES/diseases.dm index 7fdb3182218..a3d35e9c533 100644 --- a/code/__DEFINES/diseases.dm +++ b/code/__DEFINES/diseases.dm @@ -53,3 +53,58 @@ DEFINE_BITFIELD(spread_flags, list( #define DISEASE_SEVERITY_BIOHAZARD "BIOHAZARD" /// Diseases that are uncurable (hms) #define DISEASE_SEVERITY_UNCURABLE "Uncurable" + +//Severity Guaranteed Cycles or how long before a disease can potentially self-cure +/// Positive diseases should not self-cure by themselves, but if they do, they cure fast +#define DISEASE_CYCLES_POSITIVE 15 +/// Roughly 6 minutes for a harmless virus +#define DISEASE_CYCLES_NONTHREAT 180 +/// Roughly 5 minutes for a disruptive nuisance virus +#define DISEASE_CYCLES_MINOR 150 +/// Roughly 4 minutes for a medium virus +#define DISEASE_CYCLES_MEDIUM 120 +/// Roughly 3 minutes for a dangerous virus +#define DISEASE_CYCLES_DANGEROUS 90 +/// Roughly 2 minutes for a harmful virus +#define DISEASE_CYCLES_HARMFUL 60 +/// Roughly 1 minute for a biohazard kill-death-evil-bad virus +#define DISEASE_CYCLES_BIOHAZARD 30 + +//Natural Immunity/Recovery Balance Levers +/// Recovery Constant - starting point, 'base' recovery when you get initially infected. +//// Minimum stage_prob is 1 for most advanced diseases. Don't raise it above that if you don't want those diseases to start naturally curing themselves. +#define DISEASE_RECOVERY_CONSTANT 0 +/// Recovery Scaling - the divisor of the number of adjusted cycles at max_stages divided by Severity Guaranteed Cycles. +//// Raise to make over-time scaling more aggressive as you get further away from Severity Guaranteed Cycles. +//// Basically, once you hit Severity Guaranteed Cycles or equivalent, this will be your flat recovery chance, increasing by 1% for every Severity Guaranteed Cycles/this value cycles. So, if SGC = 30 and this = 3, every 10 cycles should give you another 1% per-cycle chance to recover. +#define DISEASE_RECOVERY_SCALING 2 +/// Peaked Recovery Multiplier - Once we hit max_stages, multiplicative bonus to recovery scaling. +//// Adjust to make it faster or slower to cure once the virus has reached its peak. +#define DISEASE_PEAKED_RECOVERY_MULTIPLIER 1.2 +/// Slowdown Recovery Bonus - set this to the maximum extra chance per tick you want people to get to recover from spaceacillin or other slowdown/virus resistance effects +#define DISEASE_SLOWDOWN_RECOVERY_BONUS 1 +/// Slowdown Recovery Bonus Duration - set this to the maximum # of cycles you want things that cause slowdown/virus resistance to be able to add a bonus up to DISEASE_SLOWDOWN_RECOVERY_BONUS.______qdel_list_wrapper(list/L) +//// Scales down linearly over time. +#define DISEASE_SLOWDOWN_RECOVERY_BONUS_DURATION 100 +/// Negative Malnutrition Recovery Penalty +//// Flat penalty to recovery chance if malnourished or starving +#define DISEASE_MALNUTRITION_RECOVERY_PENALTY 1.5 +/// Satiety Recovery Multiplier - added chance to recover based on positive satiety +//// Multiplier of satiety/max_satiety if satiety is positive or zero. Increase to make satiety more valuable, decrease for less. +#define DISEASE_SATIETY_RECOVERY_MULTIPLIER 1 +/// Good Sleeping Recovery Bonus - additive benefits for various types of good sleep (blanket, bed, darkness, pillows.) +//// Raise to make each factor add this much chance to recover. +#define DISEASE_GOOD_SLEEPING_RECOVERY_BONUS 0.2 +/// Sleeping Recovery Multiplier - multiplies ALL recovery chance effects by this amount. +//// Set to 1 for no effect on recovery chances from sleeping. +#define DISEASE_SLEEPING_RECOVERY_MULTIPLIER 2 +/// Final Cure Chance Multiplier - multiplies the disease's cure chance to get the probability of moving from stage 1 to a final cure. +//// Must be greater than zero for diseases to self cure. +#define DISEASE_FINAL_CURE_CHANCE_MULTIPLIER 3 +/// Symptom Offset Duration - number of cycles over which sleeping/having spaceacillin or a slowdown effect can prevent symptoms appearing +//// Set to maximum # of cycles you want to be able to offset symptoms. Scales down linearly over time. +#define DISEASE_SYMPTOM_OFFSET_DURATION 100 + +///Symptom Frequency Modifier +//// Raise to make symptoms fire less frequently, lower to make them fire more frequently. Keep at 0 or above. +#define DISEASE_SYMPTOM_FREQUENCY_MODIFIER 1 diff --git a/code/datums/diseases/_MobProcs.dm b/code/datums/diseases/_MobProcs.dm index 1aa8b6654cd..62ee5e457ca 100644 --- a/code/datums/diseases/_MobProcs.dm +++ b/code/datums/diseases/_MobProcs.dm @@ -46,7 +46,7 @@ if(prob(15/disease.spreading_modifier)) return - if(satiety>0 && prob(satiety/10)) // positive satiety makes it harder to contract the disease. + if(satiety>0 && prob(satiety/2)) // positive satiety makes it harder to contract the disease. return if(!target_zone) diff --git a/code/datums/diseases/_disease.dm b/code/datums/diseases/_disease.dm index 9d63a8c21b9..edb1ca6c635 100644 --- a/code/datums/diseases/_disease.dm +++ b/code/datums/diseases/_disease.dm @@ -19,6 +19,16 @@ var/stage_prob = 2 /// How long this infection incubates (non-visible) before revealing itself var/incubation_time + /// Has the virus hit its limit? + var/stage_peaked = FALSE + /// How many cycles has the virus been at its peak? + var/peaked_cycles = 0 + /// How many cycles do we need to have been active after hitting our max stage to start rolling back? + var/cycles_to_beat = 0 + /// Number of cycles we've prevented symptoms from appearing + var/symptom_offsets = 0 + /// Number of cycles we've benefited from chemical or other non-resting symptom protection + var/chemical_offsets = 0 //Other var/list/viable_mobtypes = list() //typepaths of viable mobs @@ -67,10 +77,11 @@ ///Proc to process the disease and decide on whether to advance, cure or make the symptoms appear. Returns a boolean on whether to continue acting on the symptoms or not. /datum/disease/proc/stage_act(seconds_per_tick, times_fired) var/slowdown = HAS_TRAIT(affected_mob, TRAIT_VIRUS_RESISTANCE) ? 0.5 : 1 // spaceacillin slows stage speed by 50% + var/recovery_prob = 0 if(required_organ) if(!has_required_infectious_organ(affected_mob, required_organ)) - cure() + cure(add_resistance = FALSE) return FALSE if(has_cure()) @@ -83,14 +94,115 @@ if(disease_flags & CURABLE && SPT_PROB(cure_chance, seconds_per_tick)) cure() return FALSE - else if(SPT_PROB(stage_prob*slowdown, seconds_per_tick)) + + if(stage == max_stages && stage_peaked != TRUE) //mostly a sanity check in case we manually set a virus to max stages + stage_peaked = TRUE + + if(SPT_PROB(stage_prob*slowdown, seconds_per_tick)) update_stage(min(stage + 1, max_stages)) - return !carrier + if(!(disease_flags & CHRONIC) && disease_flags & CURABLE && bypasses_immunity != TRUE) + switch(severity) + if(DISEASE_SEVERITY_POSITIVE) //good viruses don't go anywhere after hitting max stage - you can try to get rid of them by sleeping earlier + cycles_to_beat = max(DISEASE_RECOVERY_SCALING, DISEASE_CYCLES_POSITIVE) //because of the way we later check for recovery_prob, we need to floor this at least equal to the scaling to avoid infinitely getting less likely to cure + if((HAS_TRAIT(affected_mob, TRAIT_NOHUNGER)) || affected_mob.nutrition < NUTRITION_LEVEL_STARVING || affected_mob.satiety < 0 || slowdown == 1) //any sort of malnourishment/immunosuppressant opens you to losing a good virus + return TRUE + if(DISEASE_SEVERITY_NONTHREAT) + cycles_to_beat = max(DISEASE_RECOVERY_SCALING, DISEASE_CYCLES_NONTHREAT) + if(DISEASE_SEVERITY_MINOR) + cycles_to_beat = max(DISEASE_RECOVERY_SCALING, DISEASE_CYCLES_MINOR) + if(DISEASE_SEVERITY_MEDIUM) + cycles_to_beat = max(DISEASE_RECOVERY_SCALING, DISEASE_CYCLES_MEDIUM) + if(DISEASE_SEVERITY_DANGEROUS) + cycles_to_beat = max(DISEASE_RECOVERY_SCALING, DISEASE_CYCLES_DANGEROUS) + if(DISEASE_SEVERITY_HARMFUL) + cycles_to_beat = max(DISEASE_RECOVERY_SCALING, DISEASE_CYCLES_HARMFUL) + if(DISEASE_SEVERITY_BIOHAZARD) + cycles_to_beat = max(DISEASE_RECOVERY_SCALING, DISEASE_CYCLES_BIOHAZARD) + peaked_cycles += stage/max_stages //every cycle we spend sick counts towards eventually curing the virus, faster at higher stages + recovery_prob += DISEASE_RECOVERY_CONSTANT + (peaked_cycles / (cycles_to_beat / DISEASE_RECOVERY_SCALING)) //more severe viruses are beaten back more aggressively after the peak + if(stage_peaked) + recovery_prob *= DISEASE_PEAKED_RECOVERY_MULTIPLIER + if(slowdown != 1) //using spaceacillin can help get them over the finish line to kill a virus with decreasing effect over time + recovery_prob += clamp((((1 - slowdown)*(DISEASE_SLOWDOWN_RECOVERY_BONUS * 2)) * ((DISEASE_SLOWDOWN_RECOVERY_BONUS_DURATION - chemical_offsets) / DISEASE_SLOWDOWN_RECOVERY_BONUS_DURATION)), 0, DISEASE_SLOWDOWN_RECOVERY_BONUS) + chemical_offsets = min(chemical_offsets + 1, DISEASE_SLOWDOWN_RECOVERY_BONUS_DURATION) + if(!HAS_TRAIT(affected_mob, TRAIT_NOHUNGER)) + if(affected_mob.satiety < 0 || affected_mob.nutrition < NUTRITION_LEVEL_STARVING) //being malnourished makes it a lot harder to defeat your illness + recovery_prob -= DISEASE_MALNUTRITION_RECOVERY_PENALTY + else + if(affected_mob.satiety >= 0) + recovery_prob += round((DISEASE_SATIETY_RECOVERY_MULTIPLIER * (affected_mob.satiety/MAX_SATIETY)), 0.1) + + if(affected_mob.mob_mood) // this and most other modifiers below a shameless rip from sleeping healing buffs, but feeling good helps make it go away quicker + switch(affected_mob.mob_mood.sanity_level) + if(SANITY_LEVEL_GREAT) + recovery_prob += 0.2 + if(SANITY_LEVEL_NEUTRAL) + recovery_prob += 0.1 + if(SANITY_LEVEL_DISTURBED) + recovery_prob += 0 + if(SANITY_LEVEL_UNSTABLE) + recovery_prob += 0 + if(SANITY_LEVEL_CRAZY) + recovery_prob += -0.1 + if(SANITY_LEVEL_INSANE) + recovery_prob += -0.2 + + if((HAS_TRAIT(affected_mob, TRAIT_NOHUNGER) || !(affected_mob.satiety < 0 || affected_mob.nutrition < NUTRITION_LEVEL_STARVING)) && HAS_TRAIT(affected_mob, TRAIT_KNOCKEDOUT)) //resting starved won't help, but resting helps + var/turf/rest_turf = get_turf(affected_mob) + var/is_sleeping_in_darkness = rest_turf.get_lumcount() <= LIGHTING_TILE_IS_DARK + + if(affected_mob.is_blind_from(EYES_COVERED) || is_sleeping_in_darkness) + recovery_prob += DISEASE_GOOD_SLEEPING_RECOVERY_BONUS + + // sleeping in silence is always better + if(HAS_TRAIT(affected_mob, TRAIT_DEAF)) + recovery_prob += DISEASE_GOOD_SLEEPING_RECOVERY_BONUS + + // check for beds + if((locate(/obj/structure/bed) in affected_mob.loc)) + recovery_prob += DISEASE_GOOD_SLEEPING_RECOVERY_BONUS + else if((locate(/obj/structure/table) in affected_mob.loc)) + recovery_prob += (DISEASE_GOOD_SLEEPING_RECOVERY_BONUS / 2) + + // don't forget the bedsheet + if(locate(/obj/item/bedsheet) in affected_mob.loc) + recovery_prob += DISEASE_GOOD_SLEEPING_RECOVERY_BONUS + + // you forgot the pillow + if(locate(/obj/item/pillow) in affected_mob.loc) + recovery_prob += DISEASE_GOOD_SLEEPING_RECOVERY_BONUS + + recovery_prob *= DISEASE_SLEEPING_RECOVERY_MULTIPLIER //any form of sleeping magnifies all effects a little bit + + recovery_prob = clamp(recovery_prob, 0, 100) + + if(recovery_prob) + if(SPT_PROB(recovery_prob, seconds_per_tick)) + if(stage == 1 && prob(cure_chance * DISEASE_FINAL_CURE_CHANCE_MULTIPLIER)) //if we reduce FROM stage == 1, cure the virus - after defeating its cure_chance in a final battle + if(!HAS_TRAIT(affected_mob, TRAIT_NOHUNGER) && (affected_mob.satiety < 0 || affected_mob.nutrition < NUTRITION_LEVEL_STARVING)) + if(stage_peaked == FALSE) //if you didn't ride out the virus from its peak, if you're malnourished when it cures, you don't get resistance + cure(add_resistance = FALSE) + return FALSE + else if(prob(50)) //if you rode it out from the peak, challenge cure_chance on if you get resistance or not + cure(add_resistance = TRUE) + return FALSE + else + cure(add_resistance = TRUE) //stay fed and cure it at any point, you're immune + return FALSE + update_stage(max(stage - 1, 1)) + + if(HAS_TRAIT(affected_mob, TRAIT_KNOCKEDOUT) || slowdown != 1) //sleeping and using spaceacillin lets us nosell applicable virus symptoms firing with decreasing effectiveness over time + if(prob(100 - min((100 * (symptom_offsets / DISEASE_SYMPTOM_OFFSET_DURATION)), 100 - cure_chance * DISEASE_FINAL_CURE_CHANCE_MULTIPLIER))) //viruses with higher cure_chance will ultimately be more possible to offset symptoms on + symptom_offsets = min(symptom_offsets + 1, DISEASE_SYMPTOM_OFFSET_DURATION) + return FALSE + return !carrier /datum/disease/proc/update_stage(new_stage) stage = new_stage + if(new_stage == max_stages && !(stage_peaked)) //once a virus has hit its peak, set it to have done so + stage_peaked = TRUE /datum/disease/proc/has_cure() if(!(disease_flags & (CURABLE | CHRONIC))) @@ -111,7 +223,19 @@ if(!(spread_flags & DISEASE_SPREAD_AIRBORNE) && !force_spread) return - if(HAS_TRAIT(affected_mob, TRAIT_VIRUS_RESISTANCE) || (affected_mob.satiety > 0 && prob(affected_mob.satiety/10))) + if(affected_mob.internal) //if you keep your internals on, no airborne spread at least + return + + if(HAS_TRAIT(affected_mob, TRAIT_NOBREATH)) //also if you don't breathe + return + + if(!has_required_infectious_organ(affected_mob, ORGAN_SLOT_LUNGS)) //also if you lack lungs + return + + if(!affected_mob.CanSpreadAirborneDisease()) //should probably check this huh + return + + if(HAS_TRAIT(affected_mob, TRAIT_VIRUS_RESISTANCE) || (affected_mob.satiety > 0 && prob(affected_mob.satiety/2))) //being full or on spaceacillin makes you less likely to spread a virus return var/spread_range = 2 @@ -144,6 +268,9 @@ if(affected_mob) if(add_resistance && (disease_flags & CAN_RESIST)) LAZYOR(affected_mob.disease_resistances, GetDiseaseID()) + if(affected_mob.ckey) + var/cure_turf = get_turf(affected_mob) + log_virus("[key_name(affected_mob)] was cured of virus: [src.admin_details()] at [loc_name(cure_turf)]") qdel(src) /datum/disease/proc/IsSame(datum/disease/D) diff --git a/code/datums/diseases/advance/advance.dm b/code/datums/diseases/advance/advance.dm index 26a60c8e8a1..23462256342 100644 --- a/code/datums/diseases/advance/advance.dm +++ b/code/datums/diseases/advance/advance.dm @@ -130,10 +130,13 @@ sortTim(advance_diseases, GLOBAL_PROC_REF(cmp_advdisease_resistance_asc)) for(var/i in 1 to replace_num) var/datum/disease/advance/competition = advance_diseases[i] - if(totalTransmittable() > competition.totalResistance()) - competition.cure(FALSE) - else - return FALSE //we are not strong enough to bully our way in + if(!competition.bypasses_immunity) + if(bypasses_immunity) //viruses with bypasses_immunity get a free pass on beating normal advanced diseases + competition.cure(FALSE) + if(totalTransmittable() > competition.totalResistance()) + competition.cure(FALSE) + else + return FALSE //we are not strong enough to bully our way in infect(infectee, make_copy) return TRUE @@ -152,7 +155,7 @@ for(var/s in symptoms) var/datum/symptom/symptom_datum = s if(symptom_datum.Start(src)) //this will return FALSE if the symptom is neutered - symptom_datum.next_activation = world.time + rand(symptom_datum.symptom_delay_min SECONDS, symptom_datum.symptom_delay_max SECONDS) + symptom_datum.next_activation = world.time + (rand(symptom_datum.symptom_delay_min SECONDS, symptom_datum.symptom_delay_max SECONDS) * DISEASE_SYMPTOM_FREQUENCY_MODIFIER) symptom_datum.on_stage_change(src) for(var/s in symptoms) @@ -254,7 +257,14 @@ properties["stage_rate"] += S.stage_speed properties["transmittable"] += S.transmittable if(!S.neutered) - properties["severity"] = max(properties["severity"], S.severity) // severity is based on the highest severity non-neutered symptom + properties["severity"] += S.severity // severity is based on the sum of all non-neutered symptoms' severity + if(properties["severity"] > 0) + properties["severity"] += round((properties["resistance"] / 12), 1) + properties["severity"] += round((properties["stage_rate"] / 11), 1) + properties["severity"] += round((properties["transmittable"] / 8), 1) + properties["severity"] = round((properties["severity"] / 2), 1) + properties["severity"] *= (symptoms.len / VIRUS_SYMPTOM_LIMIT) //fewer symptoms, less severity + properties["severity"] = clamp(properties["severity"], 1, 7) // Assign the properties that are in the list. /datum/disease/advance/proc/assign_properties() @@ -275,9 +285,9 @@ set_spread(DISEASE_SPREAD_BLOOD) spreading_modifier = max(CEILING(0.4 * properties["transmittable"], 1), 1) - cure_chance = clamp(7.5 - (0.5 * properties["resistance"]), 5, 10) // can be between 5 and 10 + cure_chance = clamp(7.5 - (0.5 * properties["resistance"]), 1, 10) // can be between 1 and 10 stage_prob = max(0.5 * properties["stage_rate"], 1) - set_severity(properties["severity"]) + set_severity(round(properties["severity"]), 1) generate_cure(properties) else CRASH("Our properties were empty or null!") diff --git a/code/datums/diseases/advance/floor_diseases/carpellosis.dm b/code/datums/diseases/advance/floor_diseases/carpellosis.dm index 8343c0dc8ad..b8630bed29f 100644 --- a/code/datums/diseases/advance/floor_diseases/carpellosis.dm +++ b/code/datums/diseases/advance/floor_diseases/carpellosis.dm @@ -67,7 +67,7 @@ QDEL_NULL(rift_ability) return ..() -/datum/disease/advance/carpellosis/cure() +/datum/disease/advance/carpellosis/cure(add_resistance = TRUE) if(ability_granted) rift_ability.Remove(affected_mob) if(max_stage_reached && prob(ella_spawn_chance)) diff --git a/code/datums/diseases/brainrot.dm b/code/datums/diseases/brainrot.dm index 838908bde77..dd0975b30eb 100644 --- a/code/datums/diseases/brainrot.dm +++ b/code/datums/diseases/brainrot.dm @@ -11,6 +11,7 @@ desc = "This disease destroys the braincells, causing brain fever, brain necrosis and general intoxication." required_organ = ORGAN_SLOT_BRAIN severity = DISEASE_SEVERITY_HARMFUL + bypasses_immunity = TRUE /datum/disease/brainrot/stage_act(seconds_per_tick, times_fired) //Removed toxloss because damaging diseases are pretty horrible. Last round it killed the entire station because the cure didn't work -- Urist -ACTUALLY Removed rather than commented out, I don't see it returning - RR . = ..() diff --git a/code/datums/diseases/chronic_illness.dm b/code/datums/diseases/chronic_illness.dm index 129883c17b5..d99d29e61a8 100644 --- a/code/datums/diseases/chronic_illness.dm +++ b/code/datums/diseases/chronic_illness.dm @@ -14,6 +14,7 @@ viable_mobtypes = list(/mob/living/carbon/human) desc = "A disease discovered in an Interdyne laboratory caused by subjection to timesteam correction technology." severity = DISEASE_SEVERITY_UNCURABLE + bypasses_immunity = TRUE /datum/disease/chronic_illness/stage_act(seconds_per_tick, times_fired) . = ..() diff --git a/code/datums/diseases/decloning.dm b/code/datums/diseases/decloning.dm index 5716b2910c9..4e13341dab6 100644 --- a/code/datums/diseases/decloning.dm +++ b/code/datums/diseases/decloning.dm @@ -12,8 +12,9 @@ spread_flags = DISEASE_SPREAD_NON_CONTAGIOUS spread_text = "Organic meltdown" process_dead = TRUE + bypasses_immunity = TRUE -/datum/disease/decloning/cure() +/datum/disease/decloning/cure(add_resistance = TRUE) affected_mob.remove_status_effect(/datum/status_effect/decloning) return ..() diff --git a/code/datums/diseases/dna_spread.dm b/code/datums/diseases/dna_spread.dm index 48ca9506e2e..6fd926f60d3 100644 --- a/code/datums/diseases/dna_spread.dm +++ b/code/datums/diseases/dna_spread.dm @@ -12,6 +12,7 @@ var/transformed = 0 desc = "This disease transplants the genetic code of the initial vector into new hosts." severity = DISEASE_SEVERITY_MEDIUM + bypasses_immunity = TRUE /datum/disease/dnaspread/stage_act(seconds_per_tick, times_fired) diff --git a/code/datums/diseases/gastrolisis.dm b/code/datums/diseases/gastrolisis.dm index f82f8b3269f..c3a24903b81 100644 --- a/code/datums/diseases/gastrolisis.dm +++ b/code/datums/diseases/gastrolisis.dm @@ -9,6 +9,7 @@ stage_prob = 0.5 disease_flags = CURABLE cures = list(/datum/reagent/consumable/salt, /datum/reagent/medicine/mutadone) + bypasses_immunity = TRUE /datum/disease/gastrolosis/stage_act(seconds_per_tick, times_fired) @@ -79,7 +80,7 @@ OT.MakeSlippery(TURF_WET_LUBE, 100) -/datum/disease/gastrolosis/cure() +/datum/disease/gastrolosis/cure(add_resistance = TRUE) . = ..() if(affected_mob && !is_species(affected_mob, /datum/species/snail)) //undo all the snail fuckening var/mob/living/carbon/human/H = affected_mob diff --git a/code/datums/diseases/gbs.dm b/code/datums/diseases/gbs.dm index abf2116a92f..c9faf303674 100644 --- a/code/datums/diseases/gbs.dm +++ b/code/datums/diseases/gbs.dm @@ -11,6 +11,7 @@ disease_flags = CAN_CARRY|CAN_RESIST|CURABLE spreading_modifier = 1 severity = DISEASE_SEVERITY_BIOHAZARD + bypasses_immunity = TRUE /datum/disease/gbs/stage_act(seconds_per_tick, times_fired) . = ..() diff --git a/code/datums/diseases/magnitis.dm b/code/datums/diseases/magnitis.dm index dbe7d09cbb5..a0fbc957e74 100644 --- a/code/datums/diseases/magnitis.dm +++ b/code/datums/diseases/magnitis.dm @@ -11,6 +11,7 @@ desc = "This disease disrupts the magnetic field of your body, making it act as if a powerful magnet. Injections of iron help stabilize the field." severity = DISEASE_SEVERITY_MEDIUM infectable_biotypes = MOB_ORGANIC|MOB_ROBOTIC + bypasses_immunity = TRUE process_dead = TRUE diff --git a/code/datums/diseases/parrotpossession.dm b/code/datums/diseases/parrotpossession.dm index bbe587b2a8d..114d144902a 100644 --- a/code/datums/diseases/parrotpossession.dm +++ b/code/datums/diseases/parrotpossession.dm @@ -31,7 +31,7 @@ affected_mob.say(potential_phrase, forced = "parrot possession") -/datum/disease/parrot_possession/cure() +/datum/disease/parrot_possession/cure(add_resistance = FALSE) var/atom/movable/inside_parrot = locate(/mob/living/basic/parrot/poly/ghost) in affected_mob if(inside_parrot) UnregisterSignal(inside_parrot, list(COMSIG_PREQDELETED, COMSIG_MOVABLE_MOVED)) diff --git a/code/datums/diseases/retrovirus.dm b/code/datums/diseases/retrovirus.dm index 4c012eaaf80..4524c2af346 100644 --- a/code/datums/diseases/retrovirus.dm +++ b/code/datums/diseases/retrovirus.dm @@ -12,6 +12,7 @@ spreading_modifier = 0.4 stage_prob = 1 var/restcure = 0 + bypasses_immunity = TRUE /datum/disease/dna_retrovirus/New() ..() diff --git a/code/datums/diseases/rhumba_beat.dm b/code/datums/diseases/rhumba_beat.dm index e64002ab528..ee38d36b1f7 100644 --- a/code/datums/diseases/rhumba_beat.dm +++ b/code/datums/diseases/rhumba_beat.dm @@ -9,6 +9,7 @@ viable_mobtypes = list(/mob/living/carbon/human) spreading_modifier = 1 severity = DISEASE_SEVERITY_BIOHAZARD + bypasses_immunity = TRUE /datum/disease/rhumba_beat/stage_act(seconds_per_tick, times_fired) . = ..() diff --git a/code/datums/diseases/transformation.dm b/code/datums/diseases/transformation.dm index a3449e366df..259a1b28dff 100644 --- a/code/datums/diseases/transformation.dm +++ b/code/datums/diseases/transformation.dm @@ -10,6 +10,7 @@ stage_prob = 5 visibility_flags = HIDDEN_SCANNER|HIDDEN_PANDEMIC disease_flags = CURABLE + bypasses_immunity = TRUE var/list/stage1 = list("You feel unremarkable.") var/list/stage2 = list("You feel boring.") var/list/stage3 = list("You feel utterly plain.") diff --git a/code/datums/diseases/wizarditis.dm b/code/datums/diseases/wizarditis.dm index c2394dd645b..c497c0be039 100644 --- a/code/datums/diseases/wizarditis.dm +++ b/code/datums/diseases/wizarditis.dm @@ -9,6 +9,7 @@ viable_mobtypes = list(/mob/living/carbon/human) disease_flags = CAN_CARRY|CAN_RESIST|CURABLE spreading_modifier = 0.75 + bypasses_immunity = TRUE desc = "Some speculate that this virus is the cause of the Space Wizard Federation's existence. \ Subjects affected show the signs of brain damage, yelling obscure sentences or total gibberish. \ On late stages subjects sometime express the feelings of inner power, and cite \ diff --git a/code/datums/id_trim/jobs.dm b/code/datums/id_trim/jobs.dm index 237a8a8656b..986f0b188f9 100644 --- a/code/datums/id_trim/jobs.dm +++ b/code/datums/id_trim/jobs.dm @@ -440,6 +440,7 @@ extra_access = list( ACCESS_PSYCHOLOGY, ACCESS_PHARMACY, + ACCESS_VIROLOGY, ) template_access = list( ACCESS_CAPTAIN, @@ -695,7 +696,6 @@ sechud_icon_state = SECHUD_MEDICAL_DOCTOR extra_access = list( ACCESS_PLUMBING, - ACCESS_VIROLOGY, ) minimal_access = list( ACCESS_MECH_MEDICAL, @@ -704,6 +704,7 @@ ACCESS_MORGUE, ACCESS_PHARMACY, ACCESS_SURGERY, + ACCESS_VIROLOGY, ) template_access = list( ACCESS_CAPTAIN, @@ -754,6 +755,7 @@ ) extra_access = list( ACCESS_SURGERY, + ACCESS_VIROLOGY, ) template_access = list( ACCESS_CAPTAIN, @@ -1168,6 +1170,7 @@ ACCESS_MEDICAL, ACCESS_MINERAL_STOREROOM, ACCESS_VIROLOGY, + ACCESS_PHARMACY, ) extra_access = list( ACCESS_PLUMBING, diff --git a/code/game/objects/structures/crates_lockers/closets/l3closet.dm b/code/game/objects/structures/crates_lockers/closets/l3closet.dm index e7dfed3c88b..f996aef956f 100644 --- a/code/game/objects/structures/crates_lockers/closets/l3closet.dm +++ b/code/game/objects/structures/crates_lockers/closets/l3closet.dm @@ -9,6 +9,7 @@ new /obj/item/clothing/head/bio_hood/general(src) new /obj/item/clothing/mask/breath(src) new /obj/item/tank/internals/oxygen(src) + new /obj/item/reagent_containers/syringe/antiviral(src) /obj/structure/closet/l3closet/scientist icon_door = "bio_sci" @@ -30,6 +31,7 @@ new /obj/item/clothing/head/bio_hood/virology(src) new /obj/item/clothing/mask/breath(src) new /obj/item/tank/internals/oxygen(src) + new /obj/item/reagent_containers/syringe/antiviral(src) /obj/structure/closet/l3closet/security @@ -40,6 +42,7 @@ new /obj/item/clothing/head/bio_hood/security(src) new /obj/item/clothing/mask/breath(src) new /obj/item/tank/internals/oxygen(src) + new /obj/item/reagent_containers/syringe/antiviral(src) /obj/structure/closet/l3closet/janitor @@ -50,3 +53,4 @@ new /obj/item/clothing/head/bio_hood/janitor(src) new /obj/item/clothing/mask/breath(src) new /obj/item/tank/internals/oxygen(src) + new /obj/item/reagent_containers/syringe/antiviral(src) diff --git a/code/modules/antagonists/disease/disease_disease.dm b/code/modules/antagonists/disease/disease_disease.dm index 6b25a8bea98..8960ac27689 100644 --- a/code/modules/antagonists/disease/disease_disease.dm +++ b/code/modules/antagonists/disease/disease_disease.dm @@ -4,6 +4,7 @@ desc = "An apparently sentient virus, extremely adaptable and resistant to outside sources of mutation." viable_mobtypes = list(/mob/living/carbon/human) mutable = FALSE + bypasses_immunity = TRUE var/mob/camera/disease/overmind var/disease_id @@ -46,6 +47,9 @@ if(overmind) overmind.add_infection(src) +/datum/disease/advance/sentient_disease/GenerateProperties() + ..() + src.properties["stealth"] += 6 //SD gets an extra bit of stealth, as a treat, to avoid getting caught out so early /datum/disease/advance/sentient_disease/GetDiseaseID() if (!disease_id) //if we don't set this here it can reinfect people after the disease dies, since overmind.tag won't be null when the disease is alive, but will be null afterwards, thus the disease ID changes diff --git a/code/modules/antagonists/revenant/revenant_blight.dm b/code/modules/antagonists/revenant/revenant_blight.dm index c56df7bd4ea..dcbc9bc8181 100644 --- a/code/modules/antagonists/revenant/revenant_blight.dm +++ b/code/modules/antagonists/revenant/revenant_blight.dm @@ -15,7 +15,7 @@ var/stagedamage = 0 //Highest stage reached. var/finalstage = 0 //Because we're spawning off the cure in the final stage, we need to check if we've done the final stage's effects. -/datum/disease/revblight/cure() +/datum/disease/revblight/cure(add_resistance = FALSE) if(affected_mob) affected_mob.remove_atom_colour(TEMPORARY_COLOUR_PRIORITY, "#1d2953") if(affected_mob.dna && affected_mob.dna.species) diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index 3d407473d77..6ee908cabb7 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -50,6 +50,14 @@ else if((methods & TOUCH) && (strain.spread_flags & DISEASE_SPREAD_CONTACT_FLUIDS)) exposed_mob.ContactContractDisease(strain) + if(data && data["resistances"]) + if(methods & (INGEST|INJECT)) //have to inject or ingest it. no curefoam/cheap curesprays + for(var/stuff in exposed_mob.diseases) + var/datum/disease/infection = stuff + if(infection.GetDiseaseID() in data["resistances"]) + if(!infection.bypasses_immunity) + infection.cure(add_resistance = FALSE) + if(iscarbon(exposed_mob)) var/mob/living/carbon/exposed_carbon = exposed_mob if(exposed_carbon.get_blood_id() == type && ((methods & INJECT) || ((methods & INGEST) && HAS_TRAIT(exposed_carbon, TRAIT_DRINKS_BLOOD)))) @@ -161,7 +169,7 @@ for(var/thing in exposed_mob.diseases) var/datum/disease/infection = thing if(infection.GetDiseaseID() in data) - infection.cure() + infection.cure(add_resistance = TRUE) LAZYOR(exposed_mob.disease_resistances, data) /datum/reagent/vaccine/on_merge(list/data)