diff --git a/code/datums/components/infective.dm b/code/datums/components/infective.dm index cd605749a17..6d89f6e5cd9 100644 --- a/code/datums/components/infective.dm +++ b/code/datums/components/infective.dm @@ -43,9 +43,19 @@ RegisterSignal(parent, COMSIG_PILL_CONSUMED, PROC_REF(try_infect_eat)) if(istype(parent, /obj/item/reagent_containers/cup)) RegisterSignal(parent, COMSIG_GLASS_DRANK, PROC_REF(try_infect_drink)) + if(isorgan(parent)) + RegisterSignal(parent, COMSIG_ORGAN_IMPLANTED, PROC_REF(on_organ_insertion)) else if(istype(parent, /obj/effect/decal/cleanable/blood/gibs)) RegisterSignal(parent, COMSIG_GIBS_STREAK, PROC_REF(try_infect_streak)) +/datum/component/infective/proc/on_organ_insertion(obj/item/organ/target, mob/living/carbon/receiver) + SIGNAL_HANDLER + + for(var/datum/disease/disease in diseases) + receiver.ForceContractDisease(disease) + + qdel(src) // once organ is implanted delete the infective component + /datum/component/infective/proc/try_infect_eat(datum/source, mob/living/eater, mob/living/feeder) SIGNAL_HANDLER @@ -55,19 +65,27 @@ if(is_weak && !prob(weak_infection_chance)) return - for(var/V in diseases) - eater.ForceContractDisease(V) + for(var/datum/disease/disease in diseases) + if(!disease.has_required_infectious_organ(eater, ORGAN_SLOT_STOMACH)) + continue + + eater.ForceContractDisease(disease) + try_infect(feeder, BODY_ZONE_L_ARM) /datum/component/infective/proc/try_infect_drink(datum/source, mob/living/drinker, mob/living/feeder) SIGNAL_HANDLER - for(var/disease in diseases) - drinker.ForceContractDisease(disease) var/appendage_zone = feeder.held_items.Find(source) appendage_zone = appendage_zone == 0 ? BODY_ZONE_CHEST : appendage_zone % 2 ? BODY_ZONE_R_ARM : BODY_ZONE_L_ARM try_infect(feeder, appendage_zone) + for(var/datum/disease/disease in diseases) + if(!disease.has_required_infectious_organ(drinker, ORGAN_SLOT_STOMACH)) + continue + + drinker.ForceContractDisease(disease) + /datum/component/infective/proc/clean(datum/source, clean_types) SIGNAL_HANDLER diff --git a/code/datums/diseases/_MobProcs.dm b/code/datums/diseases/_MobProcs.dm index ce0e6169a73..e64e91c5533 100644 --- a/code/datums/diseases/_MobProcs.dm +++ b/code/datums/diseases/_MobProcs.dm @@ -101,11 +101,15 @@ if(((disease.spread_flags & DISEASE_SPREAD_AIRBORNE) || force_spread) && prob((50*disease.spreading_modifier) - 1)) ForceContractDisease(disease) -/mob/living/carbon/AirborneContractDisease(datum/disease/D, force_spread) +/mob/living/carbon/AirborneContractDisease(datum/disease/disease, force_spread) if(internal) return if(HAS_TRAIT(src, TRAIT_NOBREATH)) return + + if(!disease.has_required_infectious_organ(src, ORGAN_SLOT_LUNGS)) + return + ..() @@ -122,14 +126,14 @@ return TRUE -/mob/living/carbon/human/CanContractDisease(datum/disease/D) +/mob/living/carbon/human/CanContractDisease(datum/disease/disease) if(dna) - if(HAS_TRAIT(src, TRAIT_VIRUSIMMUNE) && !D.bypasses_immunity) + if(HAS_TRAIT(src, TRAIT_VIRUSIMMUNE) && !disease.bypasses_immunity) + return FALSE + if(disease.required_organ) + if(!disease.has_required_infectious_organ(src, disease.required_organ)) return FALSE - for(var/thing in D.required_organs) - if(!((locate(thing) in bodyparts) || (locate(thing) in organs))) - return FALSE return ..() /mob/living/proc/CanSpreadAirborneDisease() diff --git a/code/datums/diseases/_disease.dm b/code/datums/diseases/_disease.dm index 61008a13d52..b3ded1bd36b 100644 --- a/code/datums/diseases/_disease.dm +++ b/code/datums/diseases/_disease.dm @@ -30,7 +30,8 @@ var/bypasses_immunity = FALSE //Does it skip species virus immunity check? Some things may diseases and not viruses var/spreading_modifier = 1 var/severity = DISEASE_SEVERITY_NONTHREAT - var/list/required_organs = list() + /// If the disease requires an organ for the effects to function, robotic organs are immune to disease unless inorganic biology symptom is present + var/required_organ var/needs_all_cures = TRUE var/list/strain_data = list() //dna_spread special bullshit var/infectable_biotypes = MOB_ORGANIC //if the disease can spread on organics, synthetics, or undead @@ -61,11 +62,14 @@ var/turf/source_turf = get_turf(infectee) log_virus("[key_name(infectee)] was infected by virus: [src.admin_details()] at [loc_name(source_turf)]") - ///Proc to process the disease and decide on whether to advance, cure or make the sympthoms 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% + if(required_organ) + if(!has_required_infectious_organ(affected_mob, required_organ)) + return FALSE + if(has_cure()) if(disease_flags & CHRONIC && SPT_PROB(cure_chance, seconds_per_tick)) update_stage(1) @@ -149,7 +153,7 @@ //note that stage is not copied over - the copy starts over at stage 1 var/static/list/copy_vars = list("name", "visibility_flags", "disease_flags", "spread_flags", "form", "desc", "agent", "spread_text", "cure_text", "max_stages", "stage_prob", "viable_mobtypes", "cures", "infectivity", "cure_chance", - "bypasses_immunity", "spreading_modifier", "severity", "required_organs", "needs_all_cures", "strain_data", + "required_organ", "bypasses_immunity", "spreading_modifier", "severity", "needs_all_cures", "strain_data", "infectable_biotypes", "process_dead") var/datum/disease/D = copy_type ? new copy_type() : new type() @@ -193,6 +197,21 @@ return FALSE +/// Checks if the mob has the required organ and it's not robotic or affected by inorganic biology +/datum/disease/proc/has_required_infectious_organ(mob/living/carbon/target, required_organ_slot) + if(!iscarbon(target)) + return FALSE + + var/obj/item/organ/target_organ = target.get_organ_slot(required_organ_slot) + if(!istype(target_organ)) + return FALSE + + // robotic organs are immune to disease unless 'inorganic biology' symptom is present + if(IS_ROBOTIC_ORGAN(target_organ) && !(infectable_biotypes & MOB_ROBOTIC)) + return FALSE + + return TRUE + //Use this to compare severities /proc/get_disease_severity_value(severity) switch(severity) diff --git a/code/datums/diseases/advance/floor_diseases/carpellosis.dm b/code/datums/diseases/advance/floor_diseases/carpellosis.dm index 3cbc105c572..b5ef9175ed3 100644 --- a/code/datums/diseases/advance/floor_diseases/carpellosis.dm +++ b/code/datums/diseases/advance/floor_diseases/carpellosis.dm @@ -8,9 +8,9 @@ agent = "Carp Ella" cures = list(/datum/reagent/carpet) viable_mobtypes = list(/mob/living/carbon/human) - required_organs = list(/obj/item/organ/internal/stomach) spread_flags = DISEASE_SPREAD_NON_CONTAGIOUS severity = DISEASE_SEVERITY_MEDIUM + required_organ = ORGAN_SLOT_STOMACH max_stages = 5 /// The chance of Carp Ella to spawn on cure var/ella_spawn_chance = 10 diff --git a/code/datums/diseases/advance/floor_diseases/gastritium.dm b/code/datums/diseases/advance/floor_diseases/gastritium.dm index 59b619c6fb1..a7334db0fe7 100644 --- a/code/datums/diseases/advance/floor_diseases/gastritium.dm +++ b/code/datums/diseases/advance/floor_diseases/gastritium.dm @@ -6,10 +6,10 @@ agent = "Atmobacter Polyri" cures = list(/datum/reagent/firefighting_foam) viable_mobtypes = list(/mob/living/carbon/human) - required_organs = list(/obj/item/organ/internal/stomach) spread_flags = DISEASE_SPREAD_NON_CONTAGIOUS severity = DISEASE_SEVERITY_HARMFUL max_stages = 5 + required_organ = ORGAN_SLOT_STOMACH /// The chance of burped out tritium to be hot during max stage var/tritium_burp_hot_chance = 10 diff --git a/code/datums/diseases/advance/floor_diseases/nebula_nausea.dm b/code/datums/diseases/advance/floor_diseases/nebula_nausea.dm index 6ffc127ba63..8dba0435b9b 100644 --- a/code/datums/diseases/advance/floor_diseases/nebula_nausea.dm +++ b/code/datums/diseases/advance/floor_diseases/nebula_nausea.dm @@ -6,9 +6,9 @@ agent = "Stars" cures = list(/datum/reagent/bluespace) viable_mobtypes = list(/mob/living/carbon/human) - required_organs = list(/obj/item/organ/internal/stomach) spread_flags = DISEASE_SPREAD_NON_CONTAGIOUS severity = DISEASE_SEVERITY_MEDIUM + required_organ = ORGAN_SLOT_STOMACH max_stages = 5 /datum/disease/advance/nebula_nausea/New() diff --git a/code/datums/diseases/advance/symptoms/choking.dm b/code/datums/diseases/advance/symptoms/choking.dm index a677ae51e91..165b22cf189 100644 --- a/code/datums/diseases/advance/symptoms/choking.dm +++ b/code/datums/diseases/advance/symptoms/choking.dm @@ -20,6 +20,7 @@ base_message_chance = 15 symptom_delay_min = 10 symptom_delay_max = 30 + required_organ = ORGAN_SLOT_LUNGS threshold_descs = list( "Stage Speed 8" = "Causes choking more frequently.", "Stealth 4" = "The symptom remains hidden until active." @@ -35,26 +36,28 @@ if(A.totalStealth() >= 4) suppress_warning = TRUE -/datum/symptom/choking/Activate(datum/disease/advance/A) +/datum/symptom/choking/Activate(datum/disease/advance/advanced_disease) . = ..() if(!.) return - var/mob/living/M = A.affected_mob - switch(A.stage) + + var/mob/living/carbon/infected_mob = advanced_disease.affected_mob + + switch(advanced_disease.stage) if(1, 2) if(prob(base_message_chance) && !suppress_warning) - to_chat(M, span_warning("[pick("You're having difficulty breathing.", "Your breathing becomes heavy.")]")) + to_chat(infected_mob, span_warning("[pick("You're having difficulty breathing.", "Your breathing becomes heavy.")]")) if(3, 4) if(!suppress_warning) - to_chat(M, span_warning("[pick("Your windpipe feels like a straw.", "Your breathing becomes tremendously difficult.")]")) + to_chat(infected_mob, span_warning("[pick("Your windpipe feels like a straw.", "Your breathing becomes tremendously difficult.")]")) else - to_chat(M, span_warning("You feel very [pick("dizzy","woozy","faint")].")) //fake bloodloss messages - Choke_stage_3_4(M, A) - M.emote("gasp") + to_chat(infected_mob, span_warning("You feel very [pick("dizzy","woozy","faint")].")) //fake bloodloss messages + Choke_stage_3_4(infected_mob, advanced_disease) + infected_mob.emote("gasp") else - to_chat(M, span_userdanger("[pick("You're choking!", "You can't breathe!")]")) - Choke(M, A) - M.emote("gasp") + to_chat(infected_mob, span_userdanger("[pick("You're choking!", "You can't breathe!")]")) + Choke(infected_mob, advanced_disease) + infected_mob.emote("gasp") /datum/symptom/choking/proc/Choke_stage_3_4(mob/living/M, datum/disease/advance/A) M.adjustOxyLoss(rand(6,13)) @@ -82,7 +85,6 @@ Bonus */ /datum/symptom/asphyxiation - name = "Acute respiratory distress syndrome" desc = "The virus causes shrinking of the host's lungs, causing severe asphyxiation. May also lead to heart attacks." illness = "Iron Lungs" @@ -95,11 +97,12 @@ Bonus base_message_chance = 15 symptom_delay_min = 14 symptom_delay_max = 30 - var/paralysis = FALSE + required_organ = ORGAN_SLOT_LUNGS threshold_descs = list( "Stage Speed 8" = "Additionally synthesizes pancuronium and sodium thiopental inside the host.", "Transmission 8" = "Doubles the damage caused by the symptom." ) + var/paralysis = FALSE /datum/symptom/asphyxiation/Start(datum/disease/advance/A) diff --git a/code/datums/diseases/advance/symptoms/cough.dm b/code/datums/diseases/advance/symptoms/cough.dm index efef945a772..4c2715668ba 100644 --- a/code/datums/diseases/advance/symptoms/cough.dm +++ b/code/datums/diseases/advance/symptoms/cough.dm @@ -19,7 +19,7 @@ base_message_chance = 15 symptom_delay_min = 2 symptom_delay_max = 15 - var/spread_range = 1 + required_organ = ORGAN_SLOT_LUNGS threshold_descs = list( "Resistance 11" = "The host will drop small items when coughing.", "Resistance 15" = "Occasionally causes coughing fits that stun the host. The extra coughs do not spread the virus.", @@ -31,6 +31,7 @@ COOLDOWN_DECLARE(cough_cooldown) ///if FALSE, there is a percentage chance that the mob will emote coughing while cough_cooldown is on cooldown. If TRUE, won't emote again until after the off cooldown cough occurs. var/off_cooldown_coughed = FALSE + var/spread_range = 1 /datum/symptom/cough/Start(datum/disease/advance/active_disease) . = ..() diff --git a/code/datums/diseases/advance/symptoms/deafness.dm b/code/datums/diseases/advance/symptoms/deafness.dm index 51378344260..c93d94023df 100644 --- a/code/datums/diseases/advance/symptoms/deafness.dm +++ b/code/datums/diseases/advance/symptoms/deafness.dm @@ -19,6 +19,7 @@ base_message_chance = 100 symptom_delay_min = 25 symptom_delay_max = 80 + required_organ = ORGAN_SLOT_EARS threshold_descs = list( "Resistance 9" = "Causes permanent deafness, instead of intermittent.", "Stealth 4" = "The symptom remains hidden until active.", @@ -38,15 +39,15 @@ REMOVE_TRAIT(advanced_disease.affected_mob, TRAIT_DEAF, DISEASE_TRAIT) return ..() -/datum/symptom/deafness/Activate(datum/disease/advance/A) +/datum/symptom/deafness/Activate(datum/disease/advance/advanced_disease) . = ..() if(!.) return - var/mob/living/carbon/infected_mob = A.affected_mob + + var/mob/living/carbon/infected_mob = advanced_disease.affected_mob var/obj/item/organ/internal/ears/ears = infected_mob.get_organ_slot(ORGAN_SLOT_EARS) - if(!ears) - return //cutting off your ears to cure the deafness: the ultimate own - switch(A.stage) + + switch(advanced_disease.stage) if(3, 4) if(prob(base_message_chance) && !suppress_warning) to_chat(infected_mob, span_warning("[pick("You hear a ringing in your ear.", "Your ears pop.")]")) diff --git a/code/datums/diseases/advance/symptoms/dizzy.dm b/code/datums/diseases/advance/symptoms/dizzy.dm index 7e21f3f389f..5612f0e31a9 100644 --- a/code/datums/diseases/advance/symptoms/dizzy.dm +++ b/code/datums/diseases/advance/symptoms/dizzy.dm @@ -8,7 +8,6 @@ */ /datum/symptom/dizzy // Not the egg - name = "Dizziness" desc = "The virus causes inflammation of the vestibular system, leading to bouts of dizziness." illness = "Motion Sickness" diff --git a/code/datums/diseases/advance/symptoms/heal.dm b/code/datums/diseases/advance/symptoms/heal.dm index 916154d5139..5c56cb3ad6e 100644 --- a/code/datums/diseases/advance/symptoms/heal.dm +++ b/code/datums/diseases/advance/symptoms/heal.dm @@ -11,7 +11,6 @@ symptom_delay_max = 1 var/passive_message = "" //random message to infected but not actively healing people - /datum/symptom/heal/Activate(datum/disease/advance/A) . = ..() if(!.) @@ -181,17 +180,18 @@ */ /datum/symptom/heal/chem name = "Toxolysis" + desc = "The virus rapidly breaks down any foreign chemicals in the bloodstream." stealth = 0 resistance = -2 stage_speed = 2 transmittable = -2 level = 7 - var/food_conversion = FALSE - desc = "The virus rapidly breaks down any foreign chemicals in the bloodstream." + required_organ = ORGAN_SLOT_HEART threshold_descs = list( "Resistance 7" = "Increases chem removal speed.", "Stage Speed 6" = "Consumed chemicals nourish the host.", ) + var/food_conversion = FALSE /datum/symptom/heal/chem/Start(datum/disease/advance/A) . = ..() @@ -222,19 +222,20 @@ */ /datum/symptom/heal/metabolism name = "Metabolic Boost" + desc = "The virus causes the host's metabolism to accelerate rapidly, making them process chemicals twice as fast,\ + but also causing increased hunger." stealth = -1 resistance = -2 stage_speed = 2 transmittable = 1 level = 7 - var/triple_metabolism = FALSE - var/reduced_hunger = FALSE - desc = "The virus causes the host's metabolism to accelerate rapidly, making them process chemicals twice as fast,\ - but also causing increased hunger." + required_organ = ORGAN_SLOT_STOMACH threshold_descs = list( "Stealth 3" = "Reduces hunger rate.", "Stage Speed 10" = "Chemical metabolization is tripled instead of doubled.", ) + var/triple_metabolism = FALSE + var/reduced_hunger = FALSE /datum/symptom/heal/metabolism/Start(datum/disease/advance/A) . = ..() @@ -245,17 +246,16 @@ if(A.totalStealth() >= 3) reduced_hunger = TRUE -/datum/symptom/heal/metabolism/Heal(mob/living/carbon/C, datum/disease/advance/A, actual_power) - if(!istype(C)) - return +/datum/symptom/heal/metabolism/Heal(mob/living/carbon/infected_mob, datum/disease/advance/A, actual_power) var/metabolic_boost = triple_metabolism ? 2 : 1 - C.reagents.metabolize(C, metabolic_boost * SSMOBS_DT, 0, can_overdose=TRUE) //this works even without a liver; it's intentional since the virus is metabolizing by itself - C.overeatduration = max(C.overeatduration - 4 SECONDS, 0) + infected_mob.reagents.metabolize(infected_mob, metabolic_boost * SSMOBS_DT, 0, can_overdose=TRUE) //this works even without a liver; it's intentional since the virus is metabolizing by itself + infected_mob.overeatduration = max(infected_mob.overeatduration - 4 SECONDS, 0) var/lost_nutrition = 9 - (reduced_hunger * 5) - C.adjust_nutrition(-lost_nutrition * HUNGER_FACTOR) //Hunger depletes at 10x the normal speed + infected_mob.adjust_nutrition(-lost_nutrition * HUNGER_FACTOR) //Hunger depletes at 10x the normal speed if(prob(2)) - to_chat(C, span_notice("You feel an odd gurgle in your stomach, as if it was working much faster than normal.")) - return 1 + to_chat(infected_mob, span_notice("You feel an odd gurgle in your stomach, as if it was working much faster than normal.")) + return TRUE + /*Nocturnal Regeneration * Increases stealth * Slightly reduces resistance @@ -312,6 +312,7 @@ if(M.getBruteLoss() || M.getFireLoss()) return TRUE return FALSE + /*Regen Coma * No effect on stealth * Increases resistance @@ -427,11 +428,12 @@ transmittable = 1 level = 6 passive_message = span_notice("Your skin feels oddly dry...") - var/absorption_coeff = 1 + required_organ = ORGAN_SLOT_LIVER threshold_descs = list( "Resistance 5" = "Water is consumed at a much slower rate.", "Stage Speed 7" = "Increases healing speed.", ) + var/absorption_coeff = 1 /datum/symptom/heal/water/Start(datum/disease/advance/A) . = ..() @@ -442,17 +444,18 @@ if(A.totalResistance() >= 5) absorption_coeff = 0.25 -/datum/symptom/heal/water/CanHeal(datum/disease/advance/A) +/datum/symptom/heal/water/CanHeal(datum/disease/advance/advanced_disease) . = 0 - var/mob/living/M = A.affected_mob - if(M.fire_stacks < 0) - M.adjust_fire_stacks(min(absorption_coeff, -M.fire_stacks)) + var/mob/living/carbon/infected_mob = advanced_disease.affected_mob + + if(infected_mob.fire_stacks < 0) + infected_mob.adjust_fire_stacks(min(absorption_coeff, -infected_mob.fire_stacks)) . += power - if(M.reagents.has_reagent(/datum/reagent/water/holywater, needs_metabolizing = FALSE)) - M.reagents.remove_reagent(/datum/reagent/water/holywater, 0.5 * absorption_coeff) + if(infected_mob.reagents.has_reagent(/datum/reagent/water/holywater, needs_metabolizing = FALSE)) + infected_mob.reagents.remove_reagent(/datum/reagent/water/holywater, 0.5 * absorption_coeff) . += power * 0.75 - else if(M.reagents.has_reagent(/datum/reagent/water, needs_metabolizing = FALSE)) - M.reagents.remove_reagent(/datum/reagent/water, 0.5 * absorption_coeff) + else if(infected_mob.reagents.has_reagent(/datum/reagent/water, needs_metabolizing = FALSE)) + infected_mob.reagents.remove_reagent(/datum/reagent/water, 0.5 * absorption_coeff) . += power * 0.5 /datum/symptom/heal/water/Heal(mob/living/carbon/M, datum/disease/advance/A, actual_power) @@ -472,9 +475,10 @@ return 1 -/datum/symptom/heal/water/passive_message_condition(mob/living/M) - if(M.getBruteLoss() || M.getFireLoss()) +/datum/symptom/heal/water/passive_message_condition(mob/living/carbon/infected_mob) + if(infected_mob.getBruteLoss() || infected_mob.getFireLoss()) return TRUE + return FALSE /// Determines the rate at which Plasma Fixation heals based on the amount of plasma in the air @@ -499,11 +503,12 @@ transmittable = -2 level = 8 passive_message = span_notice("You feel an odd attraction to plasma.") - var/temp_rate = 1 + required_organ = ORGAN_SLOT_LIVER threshold_descs = list( "Transmission 6" = "Increases temperature adjustment rate.", "Stage Speed 7" = "Increases healing speed.", ) + var/temp_rate = 1 /datum/symptom/heal/plasma/Start(datum/disease/advance/A) . = ..() @@ -535,7 +540,7 @@ // Check internals breath, environmental plasma, and plasma in bloodstream to determine the heal power /datum/symptom/heal/plasma/CanHeal(datum/disease/advance/advanced_disease) - var/mob/living/diseased_mob = advanced_disease.affected_mob + var/mob/living/carbon/infected_mob = advanced_disease.affected_mob var/datum/gas_mixture/environment var/list/gases @@ -545,24 +550,23 @@ /// the amount of mols in a breath is significantly lower than in the environment so we are just going to use the tank's /// distribution pressure as an abstraction rather than calculate it using the ideal gas equation. /// balanced around a tank set to 4kpa = about 0.2 healing power. maxes out at 0.75 healing power, or 15kpa. - if(iscarbon(diseased_mob)) - var/mob/living/carbon/breather = diseased_mob - var/obj/item/tank/internals/internals_tank = breather.internal - if(internals_tank) - var/datum/gas_mixture/tank_contents = internals_tank.return_air() - if(tank_contents && round(tank_contents.return_pressure())) // make sure the tank is not empty or 0 pressure - if(tank_contents.gases[/datum/gas/plasma]) - // higher tank distribution pressure leads to more healing, but once you get to about 15kpa you reach the max - . += power * min(MAX_HEAL_COEFFICIENT_INTERNALS, internals_tank.distribute_pressure * HEALING_PER_BREATH_PRESSURE) - // Check environment - if(diseased_mob.loc) - environment = diseased_mob.loc.return_air() - if(environment) - gases = environment.gases - if(gases[/datum/gas/plasma]) - . += power * min(MAX_HEAL_COEFFICIENT_INTERNALS, gases[/datum/gas/plasma][MOLES] * HEALING_PER_MOL) + var/obj/item/tank/internals/internals_tank = infected_mob.internal + if(internals_tank) + var/datum/gas_mixture/tank_contents = internals_tank.return_air() + if(tank_contents && round(tank_contents.return_pressure())) // make sure the tank is not empty or 0 pressure + if(tank_contents.gases[/datum/gas/plasma]) + // higher tank distribution pressure leads to more healing, but once you get to about 15kpa you reach the max + . += power * min(MAX_HEAL_COEFFICIENT_INTERNALS, internals_tank.distribute_pressure * HEALING_PER_BREATH_PRESSURE) + else // Check environment + if(infected_mob.loc) + environment = infected_mob.loc.return_air() + if(environment) + gases = environment.gases + if(gases[/datum/gas/plasma]) + . += power * min(MAX_HEAL_COEFFICIENT_INTERNALS, gases[/datum/gas/plasma][MOLES] * HEALING_PER_MOL) + // Check for reagents in bloodstream - if(diseased_mob.reagents.has_reagent(/datum/reagent/toxin/plasma, needs_metabolizing = TRUE)) + if(infected_mob.reagents.has_reagent(/datum/reagent/toxin/plasma, needs_metabolizing = TRUE)) . += power * MAX_HEAL_COEFFICIENT_BLOODSTREAM //Determines how much the symptom heals if injected or ingested /datum/symptom/heal/plasma/Heal(mob/living/carbon/M, datum/disease/advance/A, actual_power) diff --git a/code/datums/diseases/advance/symptoms/oxygen.dm b/code/datums/diseases/advance/symptoms/oxygen.dm index 630f2e2d7fb..89da211b06b 100644 --- a/code/datums/diseases/advance/symptoms/oxygen.dm +++ b/code/datums/diseases/advance/symptoms/oxygen.dm @@ -17,10 +17,11 @@ base_message_chance = 5 symptom_delay_min = 1 symptom_delay_max = 1 - var/regenerate_blood = FALSE + required_organ = ORGAN_SLOT_LUNGS threshold_descs = list( "Resistance 8" = "Additionally regenerates lost blood." ) + var/regenerate_blood = FALSE /datum/symptom/oxygen/Start(datum/disease/advance/A) . = ..() @@ -29,20 +30,21 @@ if(A.totalResistance() >= 8) //blood regeneration regenerate_blood = TRUE -/datum/symptom/oxygen/Activate(datum/disease/advance/A) +/datum/symptom/oxygen/Activate(datum/disease/advance/advanced_disease) . = ..() if(!.) return - var/mob/living/carbon/M = A.affected_mob - switch(A.stage) + + var/mob/living/carbon/infected_mob = advanced_disease.affected_mob + switch(advanced_disease.stage) if(4, 5) - M.adjustOxyLoss(-7, 0) - M.losebreath = max(0, M.losebreath - 4) - if(regenerate_blood && M.blood_volume < BLOOD_VOLUME_NORMAL) - M.blood_volume += 1 + infected_mob.adjustOxyLoss(-7, 0) + infected_mob.losebreath = max(0, infected_mob.losebreath - 4) + if(regenerate_blood && infected_mob.blood_volume < BLOOD_VOLUME_NORMAL) + infected_mob.blood_volume += 1 else if(prob(base_message_chance)) - to_chat(M, span_notice("[pick("Your lungs feel great.", "You realize you haven't been breathing.", "You don't feel the need to breathe.")]")) + to_chat(infected_mob, span_notice("[pick("Your lungs feel great.", "You realize you haven't been breathing.", "You don't feel the need to breathe.")]")) return /datum/symptom/oxygen/on_stage_change(datum/disease/advance/A) diff --git a/code/datums/diseases/advance/symptoms/sensory.dm b/code/datums/diseases/advance/symptoms/sensory.dm index 6edc24eeeef..fa9f86abbaa 100644 --- a/code/datums/diseases/advance/symptoms/sensory.dm +++ b/code/datums/diseases/advance/symptoms/sensory.dm @@ -87,34 +87,34 @@ symptom_delay_min = 1 symptom_delay_max = 1 -/datum/symptom/sensory_restoration/Activate(datum/disease/advance/source_disease) +/datum/symptom/sensory_restoration/Activate(datum/disease/advance/advanced_disease) . = ..() if(!.) return - var/mob/living/carbon/ill_mob = source_disease.affected_mob - switch(source_disease.stage) + var/mob/living/carbon/infected_mob = advanced_disease.affected_mob + switch(advanced_disease.stage) if(4, 5) - var/obj/item/organ/internal/ears/ears = ill_mob.get_organ_slot(ORGAN_SLOT_EARS) - if(ears) + if(advanced_disease.has_required_infectious_organ(infected_mob, ORGAN_SLOT_EARS)) + var/obj/item/organ/internal/ears/ears = infected_mob.get_organ_slot(ORGAN_SLOT_EARS) ears.adjustEarDamage(-4, -4) - ill_mob.adjust_temp_blindness(-4 SECONDS) - ill_mob.adjust_eye_blur(-4 SECONDS) - - var/obj/item/organ/internal/eyes/eyes = ill_mob.get_organ_slot(ORGAN_SLOT_EYES) - if(!eyes) // only dealing with eye stuff from here on out + if(!advanced_disease.has_required_infectious_organ(infected_mob, ORGAN_SLOT_EYES)) return + var/obj/item/organ/internal/eyes/eyes = infected_mob.get_organ_slot(ORGAN_SLOT_EYES) + infected_mob.adjust_temp_blindness(-4 SECONDS) + infected_mob.adjust_eye_blur(-4 SECONDS) + eyes.apply_organ_damage(-2) if(prob(20)) - if(ill_mob.is_blind_from(EYE_DAMAGE)) - to_chat(ill_mob, span_warning("Your vision slowly returns...")) - ill_mob.adjust_eye_blur(20 SECONDS) + if(infected_mob.is_blind_from(EYE_DAMAGE)) + to_chat(infected_mob, span_warning("Your vision slowly returns...")) + infected_mob.adjust_eye_blur(20 SECONDS) - else if(ill_mob.is_nearsighted_from(EYE_DAMAGE)) - to_chat(ill_mob, span_warning("The blackness in your peripheral vision begins to fade.")) - ill_mob.adjust_eye_blur(5 SECONDS) + else if(infected_mob.is_nearsighted_from(EYE_DAMAGE)) + to_chat(infected_mob, span_warning("The blackness in your peripheral vision begins to fade.")) + infected_mob.adjust_eye_blur(5 SECONDS) else if(prob(base_message_chance)) - to_chat(ill_mob, span_notice("[pick("Your eyes feel great.","You feel like your eyes can focus more clearly.", "You don't feel the need to blink.","Your ears feel great.","Your hearing feels more acute.")]")) + to_chat(infected_mob, span_notice("[pick("Your eyes feel great.","You feel like your eyes can focus more clearly.", "You don't feel the need to blink.","Your ears feel great.","Your hearing feels more acute.")]")) diff --git a/code/datums/diseases/advance/symptoms/sneeze.dm b/code/datums/diseases/advance/symptoms/sneeze.dm index 85f5c2d58b7..762d5a29a8d 100644 --- a/code/datums/diseases/advance/symptoms/sneeze.dm +++ b/code/datums/diseases/advance/symptoms/sneeze.dm @@ -18,8 +18,7 @@ severity = 1 symptom_delay_min = 5 symptom_delay_max = 35 - var/spread_range = 4 - var/cartoon_sneezing = FALSE //ah, ah, AH, AH-CHOO!! + required_organ = ORGAN_SLOT_LUNGS threshold_descs = list( "Transmission 9" = "Increases sneezing range, spreading the virus over 6 meter cone instead of over a 4 meter cone.", "Stealth 4" = "The symptom remains hidden until active.", @@ -27,6 +26,8 @@ ) ///Emote cooldowns COOLDOWN_DECLARE(sneeze_cooldown) + var/spread_range = 4 + var/cartoon_sneezing = FALSE //ah, ah, AH, AH-CHOO!! ///if FALSE, there is a percentage chance that the mob will emote sneezing while sneeze_cooldown is on cooldown. If TRUE, won't emote again until after the off cooldown sneeze occurs. var/off_cooldown_sneezed = FALSE diff --git a/code/datums/diseases/advance/symptoms/symptoms.dm b/code/datums/diseases/advance/symptoms/symptoms.dm index ceda0f9c1d3..6b00d967192 100644 --- a/code/datums/diseases/advance/symptoms/symptoms.dm +++ b/code/datums/diseases/advance/symptoms/symptoms.dm @@ -37,6 +37,8 @@ var/list/thresholds ///If this symptom can appear from /datum/disease/advance/GenerateSymptoms() var/naturally_occuring = TRUE + ///If the symptom requires an organ for the effects to function, robotic organs are immune to disease unless inorganic biology symptom is present + var/required_organ /datum/symptom/New() var/list/S = SSdisease.list_symptoms @@ -58,9 +60,13 @@ return FALSE return TRUE -/datum/symptom/proc/Activate(datum/disease/advance/A) +/datum/symptom/proc/Activate(datum/disease/advance/advanced_disease) if(neutered) return FALSE + if(required_organ) + if(!advanced_disease.has_required_infectious_organ(advanced_disease.affected_mob, required_organ)) + return FALSE + if(world.time < next_activation) return FALSE else diff --git a/code/datums/diseases/advance/symptoms/vision.dm b/code/datums/diseases/advance/symptoms/vision.dm index f6cbddbd668..e53faf5bac5 100644 --- a/code/datums/diseases/advance/symptoms/vision.dm +++ b/code/datums/diseases/advance/symptoms/vision.dm @@ -19,11 +19,11 @@ base_message_chance = 50 symptom_delay_min = 25 symptom_delay_max = 80 + required_organ = ORGAN_SLOT_EYES threshold_descs = list( "Resistance 12" = "Weakens extraocular muscles, eventually leading to complete detachment of the eyes.", "Stealth 4" = "The symptom remains hidden until active.", ) - /// At max stage: If FALSE, cause blindness. If TRUE, cause their eyes to fall out. var/remove_eyes = FALSE @@ -40,41 +40,40 @@ . = ..() if(!.) return - var/mob/living/carbon/ill_mob = source_disease.affected_mob - var/obj/item/organ/internal/eyes/eyes = ill_mob.get_organ_slot(ORGAN_SLOT_EYES) - if(!eyes) - return // can't do much + + var/mob/living/carbon/infected_mob = source_disease.affected_mob + var/obj/item/organ/internal/eyes/eyes = infected_mob.get_organ_slot(ORGAN_SLOT_EYES) switch(source_disease.stage) if(1, 2) if(prob(base_message_chance) && !suppress_warning) - to_chat(ill_mob, span_warning("Your eyes itch.")) + to_chat(infected_mob, span_warning("Your eyes itch.")) if(3, 4) - to_chat(ill_mob, span_boldwarning("Your eyes burn!")) - ill_mob.set_eye_blur_if_lower(20 SECONDS) + to_chat(infected_mob, span_boldwarning("Your eyes burn!")) + infected_mob.set_eye_blur_if_lower(20 SECONDS) eyes.apply_organ_damage(1) else - ill_mob.set_eye_blur_if_lower(40 SECONDS) + infected_mob.set_eye_blur_if_lower(40 SECONDS) eyes.apply_organ_damage(5) // Applies nearsighted at minimum - if(!ill_mob.is_nearsighted_from(EYE_DAMAGE) && eyes.damage <= eyes.low_threshold) + if(!infected_mob.is_nearsighted_from(EYE_DAMAGE) && eyes.damage <= eyes.low_threshold) eyes.set_organ_damage(eyes.low_threshold) if(prob(eyes.damage - eyes.low_threshold + 1)) if(remove_eyes) - ill_mob.visible_message( - span_warning("[ill_mob]'s eyes fall out of their sockets!"), + infected_mob.visible_message( + span_warning("[infected_mob]'s eyes fall out of their sockets!"), span_userdanger("Your eyes fall out of their sockets!"), ) - eyes.Remove(ill_mob) - eyes.forceMove(get_turf(ill_mob)) + eyes.Remove(infected_mob) + eyes.forceMove(get_turf(infected_mob)) - else if(!ill_mob.is_blind_from(EYE_DAMAGE)) - to_chat(ill_mob, span_userdanger("You go blind!")) + else if(!infected_mob.is_blind_from(EYE_DAMAGE)) + to_chat(infected_mob, span_userdanger("You go blind!")) eyes.apply_organ_damage(eyes.maxHealth) else - to_chat(ill_mob, span_userdanger("Your eyes burn horrifically!")) + to_chat(infected_mob, span_userdanger("Your eyes burn horrifically!")) diff --git a/code/datums/diseases/advance/symptoms/voice_change.dm b/code/datums/diseases/advance/symptoms/voice_change.dm index 7e287bbeb9f..255c2a3f3a7 100644 --- a/code/datums/diseases/advance/symptoms/voice_change.dm +++ b/code/datums/diseases/advance/symptoms/voice_change.dm @@ -20,13 +20,14 @@ base_message_chance = 100 symptom_delay_min = 60 symptom_delay_max = 120 - var/scramble_language = FALSE - var/datum/language/current_language + required_organ = ORGAN_SLOT_TONGUE threshold_descs = list( "Transmission 14" = "The host's language center of the brain is damaged, leading to complete inability to speak or understand any language.", "Stage Speed 7" = "Changes voice more often.", "Stealth 3" = "The symptom remains hidden until active." ) + var/scramble_language = FALSE + var/datum/language/current_language /datum/symptom/voice_change/Start(datum/disease/advance/A) . = ..() diff --git a/code/datums/diseases/advance/symptoms/vomit.dm b/code/datums/diseases/advance/symptoms/vomit.dm index 4ad1a721a55..72558f69ba9 100644 --- a/code/datums/diseases/advance/symptoms/vomit.dm +++ b/code/datums/diseases/advance/symptoms/vomit.dm @@ -20,14 +20,15 @@ and your disease can spread via people walking on vomit. base_message_chance = 100 symptom_delay_min = 25 symptom_delay_max = 80 - var/vomit_nebula = FALSE - var/vomit_blood = FALSE - var/proj_vomit = 0 + required_organ = ORGAN_SLOT_STOMACH threshold_descs = list( "Resistance 7" = "Host will vomit blood, causing internal damage.", "Transmission 7" = "Host will projectile vomit, increasing vomiting range.", "Stealth 4" = "The symptom remains hidden until active." ) + var/vomit_nebula = FALSE + var/vomit_blood = FALSE + var/proj_vomit = 0 /datum/symptom/vomit/Start(datum/disease/advance/A) . = ..() diff --git a/code/datums/diseases/advance/symptoms/weight.dm b/code/datums/diseases/advance/symptoms/weight.dm index 86fbd75a6d1..b62bc08d661 100644 --- a/code/datums/diseases/advance/symptoms/weight.dm +++ b/code/datums/diseases/advance/symptoms/weight.dm @@ -18,6 +18,7 @@ base_message_chance = 100 symptom_delay_min = 15 symptom_delay_max = 45 + required_organ = ORGAN_SLOT_STOMACH threshold_descs = list( "Stealth 4" = "The symptom is less noticeable." ) diff --git a/code/datums/diseases/brainrot.dm b/code/datums/diseases/brainrot.dm index 1a080efa838..838908bde77 100644 --- a/code/datums/diseases/brainrot.dm +++ b/code/datums/diseases/brainrot.dm @@ -9,10 +9,9 @@ viable_mobtypes = list(/mob/living/carbon/human) cure_chance = 7.5 //higher chance to cure, since two reagents are required desc = "This disease destroys the braincells, causing brain fever, brain necrosis and general intoxication." - required_organs = list(/obj/item/organ/internal/brain) + required_organ = ORGAN_SLOT_BRAIN severity = DISEASE_SEVERITY_HARMFUL - /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 . = ..() if(!.) diff --git a/code/datums/diseases/cold.dm b/code/datums/diseases/cold.dm index 5aafb5d12e6..f7bf6cf4b18 100644 --- a/code/datums/diseases/cold.dm +++ b/code/datums/diseases/cold.dm @@ -9,6 +9,7 @@ spreading_modifier = 0.5 spread_text = "Airborne" severity = DISEASE_SEVERITY_NONTHREAT + required_organ = ORGAN_SLOT_LUNGS /datum/disease/cold/stage_act(seconds_per_tick, times_fired) diff --git a/code/datums/diseases/cold9.dm b/code/datums/diseases/cold9.dm index 543a021eee8..2e55df23b7e 100644 --- a/code/datums/diseases/cold9.dm +++ b/code/datums/diseases/cold9.dm @@ -9,7 +9,7 @@ viable_mobtypes = list(/mob/living/carbon/human) desc = "If left untreated the subject will slow, as if partly frozen." severity = DISEASE_SEVERITY_HARMFUL - + required_organ = ORGAN_SLOT_LUNGS /datum/disease/cold9/stage_act(seconds_per_tick, times_fired) . = ..() diff --git a/code/datums/diseases/death_sandwich_poisoning.dm b/code/datums/diseases/death_sandwich_poisoning.dm index 66930cb776f..5d52ac7281c 100644 --- a/code/datums/diseases/death_sandwich_poisoning.dm +++ b/code/datums/diseases/death_sandwich_poisoning.dm @@ -14,7 +14,7 @@ spread_flags = DISEASE_SPREAD_SPECIAL visibility_flags = HIDDEN_SCANNER bypasses_immunity = TRUE - + required_organ = ORGAN_SLOT_STOMACH /datum/disease/death_sandwich_poisoning/stage_act(seconds_per_tick, times_fired) . = ..() diff --git a/code/datums/diseases/flu.dm b/code/datums/diseases/flu.dm index 0da9a5b8e92..9412d2a2a2f 100644 --- a/code/datums/diseases/flu.dm +++ b/code/datums/diseases/flu.dm @@ -10,7 +10,7 @@ spreading_modifier = 0.75 desc = "If left untreated the subject will feel quite unwell." severity = DISEASE_SEVERITY_MINOR - + required_organ = ORGAN_SLOT_LUNGS /datum/disease/flu/stage_act(seconds_per_tick, times_fired) . = ..() diff --git a/code/datums/diseases/fluspanish.dm b/code/datums/diseases/fluspanish.dm index 109b7ac470b..6919884b2fe 100644 --- a/code/datums/diseases/fluspanish.dm +++ b/code/datums/diseases/fluspanish.dm @@ -10,7 +10,7 @@ spreading_modifier = 0.75 desc = "If left untreated the subject will burn to death for being a heretic." severity = DISEASE_SEVERITY_DANGEROUS - + required_organ = ORGAN_SLOT_LUNGS /datum/disease/fluspanish/stage_act(seconds_per_tick, times_fired) . = ..() diff --git a/code/datums/diseases/heart_failure.dm b/code/datums/diseases/heart_failure.dm index f996ebbaabc..1a4f05bfb8a 100644 --- a/code/datums/diseases/heart_failure.dm +++ b/code/datums/diseases/heart_failure.dm @@ -13,7 +13,7 @@ spread_flags = DISEASE_SPREAD_NON_CONTAGIOUS spread_text = "Organ failure" visibility_flags = HIDDEN_PANDEMIC - required_organs = list(/obj/item/organ/internal/heart) + required_organ = ORGAN_SLOT_HEART bypasses_immunity = TRUE // Immunity is based on not having an appendix; this isn't a virus var/sound = FALSE diff --git a/code/datums/diseases/parasitic_infection.dm b/code/datums/diseases/parasitic_infection.dm index d383db7c3f2..f2489ab068a 100644 --- a/code/datums/diseases/parasitic_infection.dm +++ b/code/datums/diseases/parasitic_infection.dm @@ -11,10 +11,9 @@ severity = DISEASE_SEVERITY_HARMFUL disease_flags = CAN_CARRY|CAN_RESIST spread_flags = DISEASE_SPREAD_NON_CONTAGIOUS - required_organs = list(/obj/item/organ/internal/liver) + required_organ = ORGAN_SLOT_LIVER bypasses_immunity = TRUE - /datum/disease/parasite/stage_act(seconds_per_tick, times_fired) . = ..() if(!.) diff --git a/code/datums/diseases/pierrot_throat.dm b/code/datums/diseases/pierrot_throat.dm index d24afb6fe5b..afc27eff07a 100644 --- a/code/datums/diseases/pierrot_throat.dm +++ b/code/datums/diseases/pierrot_throat.dm @@ -10,7 +10,7 @@ spreading_modifier = 0.75 desc = "If left untreated the subject will probably drive others to insanity." severity = DISEASE_SEVERITY_MEDIUM - + required_organ = ORGAN_SLOT_TONGUE /datum/disease/pierrot_throat/stage_act(seconds_per_tick, times_fired) . = ..() diff --git a/code/datums/diseases/tuberculosis.dm b/code/datums/diseases/tuberculosis.dm index f40515f6b57..16ce69fc181 100644 --- a/code/datums/diseases/tuberculosis.dm +++ b/code/datums/diseases/tuberculosis.dm @@ -9,7 +9,7 @@ viable_mobtypes = list(/mob/living/carbon/human) cure_chance = 2.5 //like hell are you getting out of hell desc = "A rare highly transmissible virulent virus. Few samples exist, rumoured to be carefully grown and cultured by clandestine bio-weapon specialists. Causes fever, blood vomiting, lung damage, weight loss, and fatigue." - required_organs = list(/obj/item/organ/internal/lungs) + required_organ = ORGAN_SLOT_LUNGS severity = DISEASE_SEVERITY_BIOHAZARD bypasses_immunity = TRUE // TB primarily impacts the lungs; it's also bacterial or fungal in nature; viral immunity should do nothing. diff --git a/code/datums/diseases/wizarditis.dm b/code/datums/diseases/wizarditis.dm index 8f14f9edef7..c2394dd645b 100644 --- a/code/datums/diseases/wizarditis.dm +++ b/code/datums/diseases/wizarditis.dm @@ -16,7 +16,6 @@ A gulp of strong, manly spirits usually reverts them to normal, humanlike, condition. \ A form of magical grounding can help, too, but will not cure it on its own." severity = DISEASE_SEVERITY_HARMFUL - required_organs = list(/obj/item/bodypart/head) /// List of random non-targeted spells to pick from to cast var/list/datum/action/cooldown/spell/random_spells = list() diff --git a/code/datums/elements/earhealing.dm b/code/datums/elements/earhealing.dm index 9221f7799b8..f1b34652059 100644 --- a/code/datums/elements/earhealing.dm +++ b/code/datums/elements/earhealing.dm @@ -27,7 +27,7 @@ for(var/i in user_by_item) var/mob/living/carbon/user = user_by_item[i] var/obj/item/organ/internal/ears/ears = user.get_organ_slot(ORGAN_SLOT_EARS) - if(!ears || !ears.damage || ears.organ_flags & ORGAN_FAILING) + if(!ears || !ears.damage || (ears.organ_flags & ORGAN_FAILING) || IS_ROBOTIC_ORGAN(ears)) continue ears.deaf = max(ears.deaf - 0.25 * seconds_per_tick, (ears.damage < ears.maxHealth ? 0 : 1)) // Do not clear deafness if our ears are too damaged ears.apply_organ_damage(-0.025 * seconds_per_tick) diff --git a/code/modules/antagonists/changeling/powers/tiny_prick.dm b/code/modules/antagonists/changeling/powers/tiny_prick.dm index c3182c69c7d..cb45c005ed2 100644 --- a/code/modules/antagonists/changeling/powers/tiny_prick.dm +++ b/code/modules/antagonists/changeling/powers/tiny_prick.dm @@ -195,7 +195,7 @@ /datum/action/changeling/sting/blind name = "Blind Sting" desc = "We temporarily blind our victim. Costs 25 chemicals." - helptext = "This sting completely blinds a target for a short time, and leaves them with blurred vision for a long time." + helptext = "This sting completely blinds a target for a short time, and leaves them with blurred vision for a long time. Does not work if target has robotic or missing eyes." button_icon_state = "sting_blind" chemical_cost = 25 dna_cost = 1 @@ -206,6 +206,10 @@ user.balloon_alert(user, "no eyes!") return FALSE + if(IS_ROBOTIC_ORGAN(eyes)) + user.balloon_alert(user, "robotic eyes!") + return FALSE + log_combat(user, target, "stung", "blind sting") to_chat(target, span_danger("Your eyes burn horrifically!")) eyes.apply_organ_damage(eyes.maxHealth * 0.8) diff --git a/code/modules/food_and_drinks/machinery/smartfridge.dm b/code/modules/food_and_drinks/machinery/smartfridge.dm index a8a5a890b96..4a3ee4171fc 100644 --- a/code/modules/food_and_drinks/machinery/smartfridge.dm +++ b/code/modules/food_and_drinks/machinery/smartfridge.dm @@ -597,8 +597,11 @@ repair_rate = max(0, STANDARD_ORGAN_HEALING * (matter_bin.tier - 1) * 0.5) /obj/machinery/smartfridge/organ/process(seconds_per_tick) - for(var/obj/item/organ/organ in contents) - organ.apply_organ_damage(-repair_rate * organ.maxHealth * seconds_per_tick) + for(var/obj/item/organ/target_organ in contents) + if(!target_organ.damage) + continue + + target_organ.apply_organ_damage(-repair_rate * target_organ.maxHealth * seconds_per_tick, required_organ_flag = ORGAN_ORGANIC) /obj/machinery/smartfridge/organ/Exited(atom/movable/gone, direction) . = ..() diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 81a6029d0f0..c7420b753ce 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -851,8 +851,11 @@ if(dna && !HAS_TRAIT(src, TRAIT_NOBLOOD)) blood_volume += (excess_healing * 2) //1 excess = 10 blood - for(var/obj/item/organ/organ as anything in organs) - organ.apply_organ_damage(excess_healing * -1) //1 excess = 5 organ damage healed + for(var/obj/item/organ/target_organ as anything in organs) + if(!target_organ.damage) + continue + + target_organ.apply_organ_damage(excess_healing * -1, required_organ_flag = ORGAN_ORGANIC) //1 excess = 5 organ damage healed return ..() diff --git a/code/modules/reagents/chemistry/reagents/atmos_gas_reagents.dm b/code/modules/reagents/chemistry/reagents/atmos_gas_reagents.dm index 690d20fdd67..32ca971bf41 100644 --- a/code/modules/reagents/chemistry/reagents/atmos_gas_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/atmos_gas_reagents.dm @@ -127,7 +127,10 @@ return ..() for(var/obj/item/organ/organ_being_healed as anything in breather.organs) - organ_being_healed.apply_organ_damage(-0.5 * REM * seconds_per_tick) + if(!organ_being_healed.damage) + continue + + organ_being_healed.apply_organ_damage(-0.5 * REM * seconds_per_tick, required_organ_flag = ORGAN_ORGANIC) return ..() diff --git a/code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm b/code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm index a1122ad0e73..c269e5295f5 100644 --- a/code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm @@ -227,17 +227,17 @@ if(SPT_PROB(2.5, seconds_per_tick) && iscarbon(drinker)) var/obj/item/organ/internal/eyes/eyes = drinker.get_organ_slot(ORGAN_SLOT_EYES) - if(drinker.is_blind()) - if(istype(eyes)) + if(eyes && IS_ORGANIC_ORGAN(eyes)) // doesn't affect robotic eyes + if(drinker.is_blind()) eyes.Remove(drinker) eyes.forceMove(get_turf(drinker)) to_chat(drinker, span_userdanger("You double over in pain as you feel your eyeballs liquify in your head!")) drinker.emote("scream") drinker.adjustBruteLoss(15, required_bodytype = affected_bodytype) - else - to_chat(drinker, span_userdanger("You scream in terror as you go blind!")) - eyes.apply_organ_damage(eyes.maxHealth) - drinker.emote("scream") + else + to_chat(drinker, span_userdanger("You scream in terror as you go blind!")) + eyes.apply_organ_damage(eyes.maxHealth) + drinker.emote("scream") if(SPT_PROB(1.5, seconds_per_tick) && iscarbon(drinker)) drinker.visible_message(span_danger("[drinker] starts having a seizure!"), span_userdanger("You have a seizure!")) diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm index c532f847dd5..ded0cc1f3da 100644 --- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm @@ -730,7 +730,7 @@ // Healing eye damage will cure nearsightedness and blindness from ... eye damage eyes.apply_organ_damage(-2 * REM * seconds_per_tick * normalise_creation_purity(), required_organ_flag = affected_organ_flags) // If our eyes are seriously damaged, we have a probability of causing eye blur while healing depending on purity - if(eyes.damaged && SPT_PROB(16 - min(normalized_purity * 6, 12), seconds_per_tick)) + if(eyes.damaged && IS_ORGANIC_ORGAN(eyes) && SPT_PROB(16 - min(normalized_purity * 6, 12), seconds_per_tick)) // While healing, gives some eye blur if(affected_mob.is_blind_from(EYE_DAMAGE)) to_chat(affected_mob, span_warning("Your vision slowly returns...")) diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index b9121765736..72801222c13 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -32,9 +32,22 @@ if((strain.spread_flags & DISEASE_SPREAD_SPECIAL) || (strain.spread_flags & DISEASE_SPREAD_NON_CONTAGIOUS)) continue - if(methods & (INJECT|INGEST|PATCH)) + if(methods & INGEST) + if(!strain.has_required_infectious_organ(exposed_mob, ORGAN_SLOT_STOMACH)) + continue + exposed_mob.ForceContractDisease(strain) - else if((methods & (TOUCH|VAPOR)) && (strain.spread_flags & DISEASE_SPREAD_CONTACT_FLUIDS)) + else if(methods & (INJECT|PATCH)) + if(!strain.has_required_infectious_organ(exposed_mob, ORGAN_SLOT_HEART)) + continue + + exposed_mob.ForceContractDisease(strain) + else if((methods & VAPOR) && (strain.spread_flags & DISEASE_SPREAD_CONTACT_FLUIDS)) + if(!strain.has_required_infectious_organ(exposed_mob, ORGAN_SLOT_LUNGS)) + continue + + exposed_mob.ContactContractDisease(strain) + else if((methods & TOUCH) && (strain.spread_flags & DISEASE_SPREAD_CONTACT_FLUIDS)) exposed_mob.ContactContractDisease(strain) if(iscarbon(exposed_mob)) diff --git a/code/modules/surgery/organs/_organ.dm b/code/modules/surgery/organs/_organ.dm index 3f2c98cdd85..04103648fda 100644 --- a/code/modules/surgery/organs/_organ.dm +++ b/code/modules/surgery/organs/_organ.dm @@ -150,6 +150,9 @@ INITIALIZE_IMMEDIATE(/obj/item/organ) /obj/item/organ/proc/on_remove(mob/living/carbon/organ_owner, special) SHOULD_CALL_PARENT(TRUE) + if(!iscarbon(organ_owner)) + stack_trace("Organ removal should not be happening on non carbon mobs: [organ_owner]") + for(var/trait in organ_traits) REMOVE_TRAIT(organ_owner, trait, REF(src)) @@ -163,6 +166,24 @@ INITIALIZE_IMMEDIATE(/obj/item/organ) SEND_SIGNAL(src, COMSIG_ORGAN_REMOVED, organ_owner) SEND_SIGNAL(organ_owner, COMSIG_CARBON_LOSE_ORGAN, src, special) + var/list/diseases = organ_owner.get_static_viruses() + if(!LAZYLEN(diseases)) + return + + var/list/datum/disease/diseases_to_add = list() + for(var/datum/disease/disease as anything in diseases) + // robotic organs are immune to disease unless 'inorganic biology' symptom is present + if(IS_ROBOTIC_ORGAN(src) && !(disease.infectable_biotypes & MOB_ROBOTIC)) + continue + + // admin or special viruses that should not be reproduced + if(disease.spread_flags & (DISEASE_SPREAD_SPECIAL | DISEASE_SPREAD_NON_CONTAGIOUS)) + continue + + diseases_to_add += disease + if(LAZYLEN(diseases_to_add)) + AddComponent(/datum/component/infective, diseases_to_add) + /// Add a Trait to an organ that it will give its owner. /obj/item/organ/proc/add_organ_trait(trait) LAZYADD(organ_traits, trait) diff --git a/code/modules/surgery/organs/internal/_internal_organ.dm b/code/modules/surgery/organs/internal/_internal_organ.dm index 0c314237a47..eb8629347e6 100644 --- a/code/modules/surgery/organs/internal/_internal_organ.dm +++ b/code/modules/surgery/organs/internal/_internal_organ.dm @@ -64,6 +64,9 @@ if(!damage) // No sense healing if you're not even hurt bro return + if(IS_ROBOTIC_ORGAN(src)) // Robotic organs don't naturally heal + return + ///Damage decrements by a percent of its maxhealth var/healing_amount = healing_factor ///Damage decrements again by a percent of its maxhealth, up to a total of 4 extra times depending on the owner's health diff --git a/strings/tips.txt b/strings/tips.txt index c9244f79944..fe3e75cf8c4 100644 --- a/strings/tips.txt +++ b/strings/tips.txt @@ -196,6 +196,7 @@ As the Quartermaster, be sure to check the manifests on crates you receive to ma As the Quartermaster, you can construct an express supply console that instantly delivers crates by drop pod. The impact will cause a small explosion as well. As the Research Director, you can lock down cyborgs instead of blowing them up. Then you can have their laws reset or if that doesn't work, safely dismantled. As the Research Director, you can take AIs out of their cores by loading them into an intelliCard, which lets you see their laws, even ion/syndicate ones. It can then be placed into an AI system integrity restorer computer to revive and/or repair them. +As the Virologist, robotic organs can give immunity to disease effects and transmissibility. Make use of the inorganic biology symptom to bypass the protection. As the Virologist, you only require small amounts of vaccine to heal a sick patient. Work with the Chemist to distribute your cures more efficiently. As the Virologist, your viruses can range from healing powers so great that you can heal out of critical status, or diseases so dangerous they can kill the entire crew with airborne spontaneous combustion. Experiment! As the Warden, if a prisoner's crimes are heinous enough you can put them in permabrig or the gulag. Make sure to check on them once in a while!