From 88bf87fa4e6e1c0b88a5d2735f3716e746606fac Mon Sep 17 00:00:00 2001 From: Zergspower Date: Fri, 4 Aug 2023 14:07:07 -0500 Subject: [PATCH] [MANUAL MIRROR] Robotic organ and disease improvements (#22631) * Robotic organ and disease improvements (#76766) ## About The Pull Request In the code description for the `ORGAN_ROBOTIC` flag, it says that robotic organs are not supposed to decay or regenerate health. I went and fixed this and added some more "robotic" behavior. New changes for robotic organs: - No longer heal damage passively - No longer gain health from revival - No longer heal in the smart organ fridge - No longer heal from pluoxium - Robotic ears no longer heal from ear healing items (earmuffs, etc.) - Robotic eyes are immune to changeling blind stings - Robotic eyes no longer heal from occuline New changes for diseases: - Some diseases now require an organ to work. A robotic organ will give immunity to the disease symptom unless the disease has "Inorganic Biology". - The transmission methods for diseases require organs to work but robotic organs are immune. (except inorganic biology) Airborne disease transmission require lungs. Ingested (drunk or eaten) disease transmission requires a stomach. Blood (inject or patch) disease transmission requires a heart. - Organs removed from a mob that is afflicted with a disease will be infectious while handling or transplanting it. (again, robotic organs are immune unless inorganic biology is present) Certain admin spawned or special diseases are exempt from this transmission method. - A stomach is required for nebula nausea, gastritium, carpellosis, metabolic boost, vomit, weight loss, death sandwich poisoning, - Lungs are required for choking, asphyxiation, cough, cold9, oxygen restoration, sneezing, flu, cold, spanish flu, tuberculosis - A liver is required for tissue hydration, plasma fixation, parasitic infection - Ears are required for deafness, sensory restoration - A heart is required for toxolysis, heart failure - Eyes are required for sensory restoration, hyphema - A tongue is required for voice change, parrot possession, pierrot throat - Wizarditis no longer requires a head (wtf?) to function ## Why It's Good For The Game Robotic organs should behave as intended. Not naturally healing (like organic organs) was supposed to be their downside to counteract their their ability to not decay upon death. ## Changelog :cl: fix: Fix robotic organs to not gain health passively, from revival, smart organ fridge, pluxium, occuline, and earmuffs. add: Some diseases now require the appropriate internal organ to work. A robotic organ will give immunity to the disease symptom unless the disease has "Inorganic Biology". add: Disease transmission methods now require an internal organ to be successful. Robotic organs give immunity. (except inorganic biology) Airborne disease transmission require lungs. Ingested (drunk or eaten) disease transmission requires a stomach. Blood (inject or patch) disease transmission requires a heart. add: Organs removed from a mob that is afflicted with a disease will be infectious while handling or transplanting it. (again, robotic organs are immune unless inorganic biology is present) Certain admin spawned or special diseases are exempt from this transmission method. add: A stomach is required for nebula nausea, gastritium, carpellosis, metabolic boost, vomit, weight loss, death sandwich poisoning add: Lungs are required for choking, asphyxiation, cough, cold9, oxygen restoration, sneezing, flu, cold, spanish flu, tuberculosis add: A liver is required for tissue hydration, plasma fixation, parasitic infection add: Ears are required for deafness, sensory restoration add: A heart is required for toxolysis, heart failure add: Eyes are required for sensory restoration, hyphema add: A tongue is required for voice change, pierrot throat bal: Remove head requirement for wizarditis disease /:cl: --------- Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com> * Modular parts * Printing time * Hah typos * I cant spell * Golden Shower feedback * Posi-Time * Update modular_skyrat/modules/synths/code/bodyparts/brain.dm --------- Co-authored-by: Tim Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com> Co-authored-by: GoldenAlpharex <58045821+GoldenAlpharex@users.noreply.github.com> --- .../~skyrat_defines/synth_defines.dm | 21 +++- code/datums/components/infective.dm | 26 ++++- code/datums/diseases/_MobProcs.dm | 16 +-- code/datums/diseases/_disease.dm | 25 ++++- .../advance/floor_diseases/carpellosis.dm | 2 +- .../advance/floor_diseases/gastritium.dm | 2 +- .../advance/floor_diseases/nebula_nausea.dm | 2 +- .../diseases/advance/symptoms/choking.dm | 29 +++--- .../datums/diseases/advance/symptoms/cough.dm | 3 +- .../diseases/advance/symptoms/deafness.dm | 11 +- .../datums/diseases/advance/symptoms/dizzy.dm | 1 - code/datums/diseases/advance/symptoms/heal.dm | 94 +++++++++--------- .../diseases/advance/symptoms/oxygen.dm | 20 ++-- .../diseases/advance/symptoms/sensory.dm | 34 +++---- .../diseases/advance/symptoms/sneeze.dm | 5 +- .../diseases/advance/symptoms/symptoms.dm | 8 +- .../diseases/advance/symptoms/vision.dm | 33 +++--- .../diseases/advance/symptoms/voice_change.dm | 5 +- .../datums/diseases/advance/symptoms/vomit.dm | 7 +- .../diseases/advance/symptoms/weight.dm | 1 + code/datums/diseases/brainrot.dm | 3 +- code/datums/diseases/cold.dm | 1 + code/datums/diseases/cold9.dm | 2 +- .../diseases/death_sandwich_poisoning.dm | 2 +- code/datums/diseases/flu.dm | 2 +- code/datums/diseases/fluspanish.dm | 2 +- code/datums/diseases/heart_failure.dm | 2 +- code/datums/diseases/parasitic_infection.dm | 3 +- code/datums/diseases/pierrot_throat.dm | 2 +- code/datums/diseases/tuberculosis.dm | 2 +- code/datums/diseases/wizarditis.dm | 1 - code/datums/elements/earhealing.dm | 2 +- .../changeling/powers/tiny_prick.dm | 6 +- .../food_and_drinks/machinery/smartfridge.dm | 7 +- code/modules/mob/living/carbon/carbon.dm | 7 +- .../chemistry/reagents/atmos_gas_reagents.dm | 5 +- .../reagents/drinks/alcohol_reagents.dm | 12 +-- .../chemistry/reagents/medicine_reagents.dm | 2 +- .../chemistry/reagents/other_reagents.dm | 17 +++- code/modules/research/techweb/all_nodes.dm | 7 ++ code/modules/surgery/bodyparts/_bodyparts.dm | 8 +- code/modules/surgery/organs/_organ.dm | 21 ++++ .../organs/internal/_internal_organ.dm | 3 + .../master_files/icons/obj/surgery.dmi | Bin 5860 -> 6077 bytes .../modules/synths/code/bodyparts/brain.dm | 32 +++--- .../modules/synths/code/bodyparts/ears.dm | 37 ++++--- .../modules/synths/code/bodyparts/eyes.dm | 30 ++++-- .../modules/synths/code/bodyparts/heart.dm | 37 +++++++ .../modules/synths/code/bodyparts/limbs.dm | 16 --- .../modules/synths/code/bodyparts/liver.dm | 39 +++++++- .../modules/synths/code/bodyparts/lungs.dm | 33 ++++-- .../modules/synths/code/bodyparts/stomach.dm | 32 ++++-- .../modules/synths/code/bodyparts/tongue.dm | 29 +++++- .../modules/synths/code/species/synthetic.dm | 1 - strings/tips.txt | 1 + 55 files changed, 512 insertions(+), 239 deletions(-) diff --git a/code/__DEFINES/~skyrat_defines/synth_defines.dm b/code/__DEFINES/~skyrat_defines/synth_defines.dm index e863af5e140..654d3b2b009 100644 --- a/code/__DEFINES/~skyrat_defines/synth_defines.dm +++ b/code/__DEFINES/~skyrat_defines/synth_defines.dm @@ -7,5 +7,22 @@ #define DEFAULT_SYNTH_PART_COLOR "#746c6a" #define DEFAULT_SYNTH_SCREEN_COLOR "#b99b3a" -#define SYNTH_ORGAN_LIGHT_EMP_DAMAGE 20 -#define SYNTH_ORGAN_HEAVY_EMP_DAMAGE 30 +// EMP specific Defines +#define SYNTH_ORGAN_LIGHT_EMP_DAMAGE 10 +#define SYNTH_ORGAN_HEAVY_EMP_DAMAGE 20 +#define SYNTH_HEAVY_EMP_MULTIPLIER 2 +#define SYNTH_LIGHT_EMP_TEMPERATURE_POWER 30 +#define SYNTH_HEAVY_EMP_TEMPERATURE_POWER 100 +#define SYNTH_STOMACH_LIGHT_EMP_CHARGE_LOSS 50 +#define SYNTH_STOMACH_HEAVY_EMP_CHARGE_LOSS 150 +#define SYNTH_BRAIN_WAKE_THRESHOLD 50 + +// EMP Damage thresholds from EMP - some organs being insta-killed doesnt really add much to the game +#define SYNTH_EMP_HEART_DAMAGE_MAXIMUM 100 +#define SYNTH_EMP_BRAIN_DAMAGE_MAXIMUM 75 + +// Universal stat defines +#define SYNTH_BAD_EFFECT_DURATION 30 SECONDS +#define SYNTH_HEART_DAMAGE_MESSAGE_INTERVAL 20 SECONDS +#define SYNTH_BRAIN_DAMAGE_MESSAGE_INTERVAL 20 SECONDS +#define SYNTH_DEAF_STACKS 30 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 55ff7d0461e..d9345d0107c 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 538decba24b..14a087da123 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 aad03371626..28ba45f8de4 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 13a506a2f89..412307e33ce 100644 --- a/code/modules/antagonists/changeling/powers/tiny_prick.dm +++ b/code/modules/antagonists/changeling/powers/tiny_prick.dm @@ -200,7 +200,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 @@ -211,6 +211,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 3fdbd3a5f1e..74fce5c4002 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 ef684ed5444..6dc6d98c79e 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -863,8 +863,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 e062ecec54d..69c07deeba6 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 bfd42891eb6..8146aaf8068 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/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm index 6622e3fd5d6..5d1ea2c8570 100644 --- a/code/modules/research/techweb/all_nodes.dm +++ b/code/modules/research/techweb/all_nodes.dm @@ -307,6 +307,13 @@ //SKYRAT EDIT START - RESEARCH DESIGNS "hospital_gown", + "synth_eyes", + "synth_tongue", + "synth_liver", + "synth_lungs", + "synth_stomach", + "synth_ears", + "synth_heart", //SKYRAT EDIT END - RESEARCH DESIGNS ) diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm index 746f7921997..1cbaa170efa 100644 --- a/code/modules/surgery/bodyparts/_bodyparts.dm +++ b/code/modules/surgery/bodyparts/_bodyparts.dm @@ -1332,13 +1332,13 @@ owner.visible_message(span_danger("[owner]'s [src.name] seems to malfunction!")) var/time_needed = 10 SECONDS - var/brute_damage = 5 + 1.5 // Augments reduce brute damage by 5. - var/burn_damage = 4 + 2.5 // As above, but for burn it's 4. + var/brute_damage = 2.5 // SKYRAT EDIT : Balances direct EMP damage for Brute - SR's synth values are multiplied 3x 2.5 * 1.3 * 1.3 + var/burn_damage = 2 // SKYRAT EDIT : Balances direct EMP damage for Burn - SR's synth values are multiplied 3x 2 * 1.3 * 1.3 if(severity == EMP_HEAVY) time_needed *= 2 - brute_damage *= 2 - burn_damage *= 2 + brute_damage *= 1.3 // SKYRAT EDIT : Balance - Lowers total damage from ~125 Brute to ~30 + burn_damage *= 1.3 // SKYRAT EDIT : Balance - Lowers total damage from ~104 Burn to ~24 receive_damage(brute_damage, burn_damage) do_sparks(number = 1, cardinal_only = FALSE, source = owner) 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/modular_skyrat/master_files/icons/obj/surgery.dmi b/modular_skyrat/master_files/icons/obj/surgery.dmi index 4cde615972d68306f3f3d4233b4c71232ef75c1c..5a3aabe223b112817b9ace6924c156949ada8e93 100644 GIT binary patch literal 6077 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 literal 5860 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 Mb SYNTH_BRAIN_WAKE_THRESHOLD) user_human.revive(FALSE) -/obj/item/organ/internal/brain/synth/emp_act(severity) - // This value is the protection value! +/obj/item/organ/internal/brain/synth/emp_act(severity) // EMP act against the posi, keep the cap far below the organ health . = ..() - // If EMP protected, or light EMPed, don't emp_act. - if(. & EMP_PROTECT_SELF || severity != EMP_HEAVY) + if(!owner || . & EMP_PROTECT_SELF) return - apply_organ_damage(SYNTH_EMP_BRAIN_DAMAGE, SYNTH_EMP_BRAIN_DAMAGE_MAXIMUM) + if(!COOLDOWN_FINISHED(src, severe_cooldown)) //So we cant just spam emp to kill people. + COOLDOWN_START(src, severe_cooldown, 10 SECONDS) + + switch(severity) + if(EMP_HEAVY) + to_chat(owner, span_warning("01001001 00100111 01101101 00100000 01100110 01110101 01100011 01101011 01100101 01100100 00101110")) + apply_organ_damage(SYNTH_ORGAN_HEAVY_EMP_DAMAGE, SYNTH_EMP_BRAIN_DAMAGE_MAXIMUM, required_organ_flag = ORGAN_ROBOTIC) + if(EMP_LIGHT) + to_chat(owner, span_warning("Alert: Electromagnetic damage taken in central processing unit. Error Code: 401-YT")) + apply_organ_damage(SYNTH_ORGAN_LIGHT_EMP_DAMAGE, SYNTH_EMP_BRAIN_DAMAGE_MAXIMUM, required_organ_flag = ORGAN_ROBOTIC) /obj/item/organ/internal/brain/synth/apply_organ_damage(damage_amount, maximumm, required_organ_flag) . = ..() @@ -41,11 +44,11 @@ last_message_time = world.time if(damage > BRAIN_DAMAGE_SEVERE) - to_chat(owner, span_warning("Alert: Severe corruption in central processing unit.")) + to_chat(owner, span_warning("Alre: re oumtnin ilir tocorr:pa ni ne:cnrrpiioruloomatt cessingode: P1_1-H")) return if(damage > BRAIN_DAMAGE_MILD) - to_chat(owner, span_warning("Alert: Minor corruption in central processing unit.")) + to_chat(owner, span_warning("Alert: Minor corruption in central processing unit. Error Code: 001-HP")) /obj/item/organ/internal/brain/synth/circuit name = "compact AI circuit" @@ -61,8 +64,3 @@ desc = "A compact man-machine interface, perfectly dimensioned to fit in the same slot as a synthetic-compatible positronic brain. Unfortunately, the brain seems to be permanently attached to the circuitry, and it seems relatively sensitive to it's environment. It is usually slotted into the chest of synthetic crewmembers." icon = 'modular_skyrat/master_files/icons/obj/surgery.dmi' icon_state = "mmi-ipc" - -#undef SYNTH_EMP_BRAIN_DAMAGE -#undef SYNTH_EMP_BRAIN_DAMAGE_MAXIMUM -#undef SYNTH_BRAIN_WAKE_THRESHOLD -#undef SYNTH_BRAIN_DAMAGE_MESSAGE_INTERVAL diff --git a/modular_skyrat/modules/synths/code/bodyparts/ears.dm b/modular_skyrat/modules/synths/code/bodyparts/ears.dm index 93491fa87ea..841a69f9d58 100644 --- a/modular_skyrat/modules/synths/code/bodyparts/ears.dm +++ b/modular_skyrat/modules/synths/code/bodyparts/ears.dm @@ -1,16 +1,12 @@ -#define SYNTH_BAD_EFFECT_DURATION 30 SECONDS -#define SYNTH_DEAF_STACKS 30 -#define SYNTH_KNOCKDOWN_POWER 40 -#define SYNTH_HEAVY_EMP_MULTIPLIER 2 - /obj/item/organ/internal/ears/synth name = "auditory sensors" icon = 'modular_skyrat/master_files/icons/obj/surgery.dmi' icon_state = "ears-ipc" - desc = "A pair of microphones intended to be installed in an IPC head, that grant the ability to hear." + desc = "A pair of microphones intended to be installed in an IPC or Synthetics head, that grant the ability to hear." zone = BODY_ZONE_HEAD slot = ORGAN_SLOT_EARS gender = PLURAL + maxHealth = 1 * STANDARD_ORGAN_THRESHOLD organ_flags = ORGAN_ROBOTIC | ORGAN_SYNTHETIC_FROM_SPECIES /obj/item/organ/internal/ears/synth/emp_act(severity) @@ -19,21 +15,34 @@ if(!owner || . & EMP_PROTECT_SELF) return + if(!COOLDOWN_FINISHED(src, severe_cooldown)) //So we cant just spam emp to kill people. + COOLDOWN_START(src, severe_cooldown, 10 SECONDS) + switch(severity) if(EMP_HEAVY) owner.set_jitter_if_lower(SYNTH_BAD_EFFECT_DURATION * SYNTH_HEAVY_EMP_MULTIPLIER) owner.set_dizzy_if_lower(SYNTH_BAD_EFFECT_DURATION * SYNTH_HEAVY_EMP_MULTIPLIER) - owner.Knockdown(SYNTH_KNOCKDOWN_POWER * SYNTH_HEAVY_EMP_MULTIPLIER) adjustEarDamage(SYNTH_ORGAN_HEAVY_EMP_DAMAGE, SYNTH_DEAF_STACKS) - to_chat(owner, span_warning("Your system reports a complete lack of input from your auditory sensors.")) + to_chat(owner, span_warning("Alert: Null feedback from auditory sensors detected, seek maintenance immediately. Error Code: AS-105")) if(EMP_LIGHT) owner.set_jitter_if_lower(SYNTH_BAD_EFFECT_DURATION) owner.set_dizzy_if_lower(SYNTH_BAD_EFFECT_DURATION) - owner.Knockdown(SYNTH_KNOCKDOWN_POWER) - to_chat(owner, span_warning("Your system reports anomalous feedback from your auditory sensors.")) + adjustEarDamage(SYNTH_ORGAN_LIGHT_EMP_DAMAGE, SYNTH_DEAF_STACKS) + to_chat(owner, span_warning("Alert: Anomalous feedback from auditory sensors detected. Error Code: AS-50")) -#undef SYNTH_BAD_EFFECT_DURATION -#undef SYNTH_DEAF_STACKS -#undef SYNTH_KNOCKDOWN_POWER -#undef SYNTH_HEAVY_EMP_MULTIPLIER +/datum/design/synth_ears + name = "Auditory Sensors" + desc = "A pair of microphones intended to be installed in an IPC or Synthetics head, that grant the ability to hear." + id = "synth_ears" + build_type = PROTOLATHE | AWAY_LATHE | MECHFAB + construction_time = 4 SECONDS + materials = list( + /datum/material/iron = SMALL_MATERIAL_AMOUNT * 5, + /datum/material/glass = SMALL_MATERIAL_AMOUNT * 5, + ) + build_path = /obj/item/organ/internal/ears/synth + category = list( + RND_CATEGORY_CYBERNETICS + RND_SUBCATEGORY_CYBERNETICS_ORGANS_1 + ) + departmental_flags = DEPARTMENT_BITFLAG_MEDICAL | DEPARTMENT_BITFLAG_SCIENCE diff --git a/modular_skyrat/modules/synths/code/bodyparts/eyes.dm b/modular_skyrat/modules/synths/code/bodyparts/eyes.dm index 388103261dd..79dfa299bc0 100644 --- a/modular_skyrat/modules/synths/code/bodyparts/eyes.dm +++ b/modular_skyrat/modules/synths/code/bodyparts/eyes.dm @@ -2,6 +2,9 @@ name = "optical sensors" icon_state = "cybernetic_eyeballs" desc = "A very basic set of optical sensors with no extra vision modes or functions." + zone = BODY_ZONE_HEAD + slot = ORGAN_SLOT_EYES + maxHealth = 1 * STANDARD_ORGAN_THRESHOLD organ_flags = ORGAN_ROBOTIC | ORGAN_SYNTHETIC_FROM_SPECIES /obj/item/organ/internal/eyes/synth/emp_act(severity) @@ -10,11 +13,26 @@ if(!owner || . & EMP_PROTECT_SELF) return - to_chat(owner, span_warning("Electromagnetic interference clouds your optics with static.")) - owner.flash_act(visual = TRUE) - switch(severity) - if(EMP_LIGHT) - owner.adjustOrganLoss(ORGAN_SLOT_EYES, SYNTH_ORGAN_LIGHT_EMP_DAMAGE) if(EMP_HEAVY) - owner.adjustOrganLoss(ORGAN_SLOT_EYES, SYNTH_ORGAN_HEAVY_EMP_DAMAGE) + to_chat(owner, span_warning("Alert:Severe electromagnetic interference clouds your optics with static. Error Code: I-CS6")) + apply_organ_damage(SYNTH_ORGAN_HEAVY_EMP_DAMAGE, maxHealth, required_organ_flag = ORGAN_ROBOTIC) + if(EMP_LIGHT) + to_chat(owner, span_warning("Alert: Mild interference clouds your optics with static. Error Code: I-CS0")) + apply_organ_damage(SYNTH_ORGAN_LIGHT_EMP_DAMAGE, maxHealth, required_organ_flag = ORGAN_ROBOTIC) + +/datum/design/synth_eyes + name = "Optical Sensors" + desc = "A very basic set of optical sensors with no extra vision modes or functions." + id = "synth_eyes" + build_type = PROTOLATHE | AWAY_LATHE | MECHFAB + construction_time = 4 SECONDS + materials = list( + /datum/material/iron = SMALL_MATERIAL_AMOUNT * 5, + /datum/material/glass = SMALL_MATERIAL_AMOUNT * 5, + ) + build_path = /obj/item/organ/internal/eyes/synth + category = list( + RND_CATEGORY_CYBERNETICS + RND_SUBCATEGORY_CYBERNETICS_ORGANS_1 + ) + departmental_flags = DEPARTMENT_BITFLAG_MEDICAL | DEPARTMENT_BITFLAG_SCIENCE diff --git a/modular_skyrat/modules/synths/code/bodyparts/heart.dm b/modular_skyrat/modules/synths/code/bodyparts/heart.dm index aebc9fd85f1..a17d99be2d7 100644 --- a/modular_skyrat/modules/synths/code/bodyparts/heart.dm +++ b/modular_skyrat/modules/synths/code/bodyparts/heart.dm @@ -5,3 +5,40 @@ icon = 'modular_skyrat/master_files/icons/obj/surgery.dmi' icon_state = "heart-ipc-on" base_icon_state = "heart-ipc" + maxHealth = 1.5 * STANDARD_ORGAN_THRESHOLD // 1.5x due to synthcode.tm being weird + zone = BODY_ZONE_CHEST + slot = ORGAN_SLOT_HEART + var/last_message_time = 0 + +/obj/item/organ/internal/heart/synth/emp_act(severity) + . = ..() + + if(!owner || . & EMP_PROTECT_SELF) + return + + if(!COOLDOWN_FINISHED(src, severe_cooldown)) //So we cant just spam emp to kill people. + COOLDOWN_START(src, severe_cooldown, 10 SECONDS) + + switch(severity) + if(EMP_HEAVY) + to_chat(owner, span_warning("Alert: Main hydraulic pump control has taken severe damage, seek maintenance immediately. Error code: HP300-10.")) + apply_organ_damage(SYNTH_ORGAN_HEAVY_EMP_DAMAGE, maxHealth, required_organ_flag = ORGAN_ROBOTIC) + if(EMP_LIGHT) + to_chat(owner, span_warning("Alert: Main hydraulic pump control has taken light damage, seek maintenance immediately. Error code: HP300-05.")) + apply_organ_damage(SYNTH_ORGAN_LIGHT_EMP_DAMAGE, maxHealth, required_organ_flag = ORGAN_ROBOTIC) + +/datum/design/synth_heart + name = "Hydraulic Pump Engine" + desc = "An electronic device that handles the hydraulic pumps, powering one's robotic limbs. Without this, synthetics are unable to move." + id = "synth_heart" + build_type = PROTOLATHE | AWAY_LATHE | MECHFAB + construction_time = 4 SECONDS + materials = list( + /datum/material/iron = SMALL_MATERIAL_AMOUNT * 5, + /datum/material/glass = SMALL_MATERIAL_AMOUNT * 5, + ) + build_path = /obj/item/organ/internal/heart/synth + category = list( + RND_CATEGORY_CYBERNETICS + RND_SUBCATEGORY_CYBERNETICS_ORGANS_1 + ) + departmental_flags = DEPARTMENT_BITFLAG_MEDICAL | DEPARTMENT_BITFLAG_SCIENCE diff --git a/modular_skyrat/modules/synths/code/bodyparts/limbs.dm b/modular_skyrat/modules/synths/code/bodyparts/limbs.dm index b080dfd5828..aba679efaef 100644 --- a/modular_skyrat/modules/synths/code/bodyparts/limbs.dm +++ b/modular_skyrat/modules/synths/code/bodyparts/limbs.dm @@ -8,8 +8,6 @@ should_draw_greyscale = TRUE bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC change_exempt_flags = NONE - brute_modifier = 1 - burn_modifier = 1 brute_modifier = SYNTH_BRUTE_MODIFIER burn_modifier = SYNTH_BURN_MODIFIER head_flags = HEAD_ALL_FEATURES @@ -19,8 +17,6 @@ should_draw_greyscale = TRUE limb_id = SPECIES_SYNTH change_exempt_flags = NONE - brute_modifier = 1 - burn_modifier = 1 brute_modifier = SYNTH_BRUTE_MODIFIER burn_modifier = SYNTH_BURN_MODIFIER @@ -29,8 +25,6 @@ limb_id = SPECIES_SYNTH should_draw_greyscale = TRUE change_exempt_flags = NONE - brute_modifier = 1 - burn_modifier = 1 brute_modifier = SYNTH_BRUTE_MODIFIER burn_modifier = SYNTH_BURN_MODIFIER @@ -39,8 +33,6 @@ limb_id = SPECIES_SYNTH should_draw_greyscale = TRUE change_exempt_flags = NONE - brute_modifier = 1 - burn_modifier = 1 brute_modifier = SYNTH_BRUTE_MODIFIER burn_modifier = SYNTH_BURN_MODIFIER @@ -50,8 +42,6 @@ should_draw_greyscale = TRUE digitigrade_type = /obj/item/bodypart/leg/left/robot/digitigrade change_exempt_flags = NONE - brute_modifier = 1 - burn_modifier = 1 brute_modifier = SYNTH_BRUTE_MODIFIER burn_modifier = SYNTH_BURN_MODIFIER @@ -61,8 +51,6 @@ limb_id = SPECIES_SYNTH digitigrade_type = /obj/item/bodypart/leg/right/robot/digitigrade change_exempt_flags = NONE - brute_modifier = 1 - burn_modifier = 1 brute_modifier = SYNTH_BRUTE_MODIFIER burn_modifier = SYNTH_BURN_MODIFIER @@ -73,8 +61,6 @@ bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC | BODYTYPE_DIGITIGRADE base_limb_id = BODYPART_ID_DIGITIGRADE change_exempt_flags = NONE - brute_modifier = 1 - burn_modifier = 1 brute_modifier = SYNTH_BRUTE_MODIFIER burn_modifier = SYNTH_BURN_MODIFIER @@ -89,8 +75,6 @@ bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC | BODYTYPE_DIGITIGRADE base_limb_id = BODYPART_ID_DIGITIGRADE change_exempt_flags = NONE - brute_modifier = 1 - burn_modifier = 1 brute_modifier = SYNTH_BRUTE_MODIFIER burn_modifier = SYNTH_BURN_MODIFIER diff --git a/modular_skyrat/modules/synths/code/bodyparts/liver.dm b/modular_skyrat/modules/synths/code/bodyparts/liver.dm index 5799b1c35e5..43597e6d422 100644 --- a/modular_skyrat/modules/synths/code/bodyparts/liver.dm +++ b/modular_skyrat/modules/synths/code/bodyparts/liver.dm @@ -1,7 +1,44 @@ /obj/item/organ/internal/liver/synth name = "reagent processing unit" desc = "An electronic device that processes the beneficial chemicals for the synthetic user." - organ_flags = ORGAN_ROBOTIC | ORGAN_SYNTHETIC_FROM_SPECIES icon = 'modular_skyrat/master_files/icons/obj/surgery.dmi' icon_state = "liver-ipc" filterToxins = FALSE //We dont filter them, we're immune to them + zone = BODY_ZONE_CHEST + slot = ORGAN_SLOT_LIVER + maxHealth = 1 * STANDARD_ORGAN_THRESHOLD + organ_flags = ORGAN_ROBOTIC | ORGAN_SYNTHETIC_FROM_SPECIES + +/obj/item/organ/internal/lungs/synth/emp_act(severity) + . = ..() + + if(. & EMP_PROTECT_SELF) + return + + if(!COOLDOWN_FINISHED(src, severe_cooldown)) //So we cant just spam emp to kill people. + COOLDOWN_START(src, severe_cooldown, 10 SECONDS) + + switch(severity) + if(EMP_HEAVY) + to_chat(owner, span_warning("Alert: Critical! Reagent processing unit failure, seek maintenance immediately. Error Code: DR-1k")) + apply_organ_damage(SYNTH_ORGAN_HEAVY_EMP_DAMAGE, maxHealth, required_organ_flag = ORGAN_ROBOTIC) + + if(EMP_LIGHT) + to_chat(owner, span_warning("Alert: Reagent processing unit failure, seek maintenance for diagnostic. Error Code: DR-0k")) + apply_organ_damage(SYNTH_ORGAN_LIGHT_EMP_DAMAGE, maxHealth, required_organ_flag = ORGAN_ROBOTIC) + +/datum/design/synth_liver + name = "Reagent Processing Unit" + desc = "An electronic device that processes the beneficial chemicals for the synthetic user." + id = "synth_liver" + build_type = PROTOLATHE | AWAY_LATHE | MECHFAB + construction_time = 4 SECONDS + materials = list( + /datum/material/iron = SMALL_MATERIAL_AMOUNT * 5, + /datum/material/glass = SMALL_MATERIAL_AMOUNT * 5, + ) + build_path = /obj/item/organ/internal/liver/synth + category = list( + RND_CATEGORY_CYBERNETICS + RND_SUBCATEGORY_CYBERNETICS_ORGANS_1 + ) + departmental_flags = DEPARTMENT_BITFLAG_MEDICAL | DEPARTMENT_BITFLAG_SCIENCE diff --git a/modular_skyrat/modules/synths/code/bodyparts/lungs.dm b/modular_skyrat/modules/synths/code/bodyparts/lungs.dm index fa7f0046b67..69ff9d0dfcf 100644 --- a/modular_skyrat/modules/synths/code/bodyparts/lungs.dm +++ b/modular_skyrat/modules/synths/code/bodyparts/lungs.dm @@ -1,8 +1,5 @@ -#define SYNTH_LIGHT_EMP_TEMPERATURE_POWER 30 -#define SYNTH_HEAVY_EMP_TEMPERATURE_POWER 100 - /obj/item/organ/internal/lungs/synth - name = "heat sink" + name = "heatsink" desc = "A device that transfers generated heat to a fluid medium to cool it down. Required to keep your synthetics cool-headed. It's shape resembles lungs." //Purposefully left the 'fluid medium' ambigious for interpretation of the character, whether it be air or fluid cooling icon = 'modular_skyrat/master_files/icons/obj/surgery.dmi' icon_state = "lungs-ipc" @@ -12,21 +9,41 @@ safe_plasma_max = 0 safe_oxygen_min = 0 //What are you doing man, dont breathe with those! safe_oxygen_max = 0 + zone = BODY_ZONE_CHEST + slot = ORGAN_SLOT_LUNGS + maxHealth = 1.5 * STANDARD_ORGAN_THRESHOLD organ_flags = ORGAN_ROBOTIC | ORGAN_SYNTHETIC_FROM_SPECIES /obj/item/organ/internal/lungs/synth/emp_act(severity) . = ..() - if(. & EMP_PROTECT_SELF) + if(!owner || . & EMP_PROTECT_SELF) return + if(!COOLDOWN_FINISHED(src, severe_cooldown)) //So we cant just spam emp to kill people. + COOLDOWN_START(src, severe_cooldown, 10 SECONDS) + switch(severity) if(EMP_HEAVY) - to_chat(owner, span_warning("Alert: Critical cooling system failure!")) + to_chat(owner, span_warning("Alert: Critical cooling system failure! Seek maintenance immediately. Error Code: 5H-17")) owner.adjust_bodytemperature(SYNTH_HEAVY_EMP_TEMPERATURE_POWER * TEMPERATURE_DAMAGE_COEFFICIENT) if(EMP_LIGHT) + to_chat(owner, span_warning("Alert: Major cooling system failure!")) owner.adjust_bodytemperature(SYNTH_LIGHT_EMP_TEMPERATURE_POWER * TEMPERATURE_DAMAGE_COEFFICIENT) -#undef SYNTH_LIGHT_EMP_TEMPERATURE_POWER -#undef SYNTH_HEAVY_EMP_TEMPERATURE_POWER +/datum/design/synth_heatsink + name = "Heatsink" + desc = "A device that transfers generated heat to a fluid medium to cool it down. Required to keep your synthetics cool-headed. It's shape resembles lungs." + id = "synth_lungs" + build_type = PROTOLATHE | AWAY_LATHE | MECHFAB + construction_time = 4 SECONDS + materials = list( + /datum/material/iron = SMALL_MATERIAL_AMOUNT * 5, + /datum/material/glass = SMALL_MATERIAL_AMOUNT * 5, + ) + build_path = /obj/item/organ/internal/lungs/synth + category = list( + RND_CATEGORY_CYBERNETICS + RND_SUBCATEGORY_CYBERNETICS_ORGANS_1 + ) + departmental_flags = DEPARTMENT_BITFLAG_MEDICAL | DEPARTMENT_BITFLAG_SCIENCE diff --git a/modular_skyrat/modules/synths/code/bodyparts/stomach.dm b/modular_skyrat/modules/synths/code/bodyparts/stomach.dm index 18a72224290..c55f64e2062 100644 --- a/modular_skyrat/modules/synths/code/bodyparts/stomach.dm +++ b/modular_skyrat/modules/synths/code/bodyparts/stomach.dm @@ -1,14 +1,14 @@ -#define SYNTH_STOMACH_LIGHT_EMP_CHARGE_LOSS 50 -#define SYNTH_STOMACH_HEAVY_EMP_CHARGE_LOSS 150 - /obj/item/organ/internal/stomach/synth - name = "synth power cell" + name = "synthetic bio-reactor" icon = 'modular_skyrat/master_files/icons/obj/surgery.dmi' icon_state = "stomach-ipc" w_class = WEIGHT_CLASS_NORMAL + zone = BODY_ZONE_CHEST + slot = ORGAN_SLOT_STOMACH + maxHealth = 1 * STANDARD_ORGAN_THRESHOLD zone = "chest" slot = "stomach" - desc = "A specialised cell, for synthetic use only. Has a low-power mode. Without this, synthetics are unable to stay powered." + desc = "A specialised mini reactor, for synthetic use only. Has a low-power mode to ensure baseline functions. Without this, synthetics are unable to stay powered." organ_flags = ORGAN_ROBOTIC | ORGAN_SYNTHETIC_FROM_SPECIES /obj/item/organ/internal/stomach/synth/emp_act(severity) @@ -17,14 +17,32 @@ if(!owner || . & EMP_PROTECT_SELF) return + if(!COOLDOWN_FINISHED(src, severe_cooldown)) //So we cant just spam emp to kill people. + COOLDOWN_START(src, severe_cooldown, 10 SECONDS) + switch(severity) if(EMP_HEAVY) owner.nutrition = max(0, owner.nutrition - SYNTH_STOMACH_HEAVY_EMP_CHARGE_LOSS) + apply_organ_damage(SYNTH_ORGAN_HEAVY_EMP_DAMAGE, maxHealth, required_organ_flag = ORGAN_ROBOTIC) to_chat(owner, span_warning("Alert: Severe battery discharge!")) if(EMP_LIGHT) owner.nutrition = max(0, owner.nutrition - SYNTH_STOMACH_LIGHT_EMP_CHARGE_LOSS) + apply_organ_damage(SYNTH_ORGAN_LIGHT_EMP_DAMAGE, maxHealth, required_organ_flag = ORGAN_ROBOTIC) to_chat(owner, span_warning("Alert: Minor battery discharge!")) -#undef SYNTH_STOMACH_LIGHT_EMP_CHARGE_LOSS -#undef SYNTH_STOMACH_HEAVY_EMP_CHARGE_LOSS +/datum/design/synth_stomach + name = "Synthetic Bio-Reactor" + desc = "A specialised mini reactor, for synthetic use only. Has a low-power mode to ensure baseline functions. Without this, synthetics are unable to stay powered." + id = "synth_stomach" + build_type = PROTOLATHE | AWAY_LATHE | MECHFAB + construction_time = 4 SECONDS + materials = list( + /datum/material/iron = SMALL_MATERIAL_AMOUNT * 5, + /datum/material/glass = SMALL_MATERIAL_AMOUNT * 5, + ) + build_path = /obj/item/organ/internal/stomach/synth + category = list( + RND_CATEGORY_CYBERNETICS + RND_SUBCATEGORY_CYBERNETICS_ORGANS_1 + ) + departmental_flags = DEPARTMENT_BITFLAG_MEDICAL | DEPARTMENT_BITFLAG_SCIENCE diff --git a/modular_skyrat/modules/synths/code/bodyparts/tongue.dm b/modular_skyrat/modules/synths/code/bodyparts/tongue.dm index e39ff438b85..d5c2564fdb3 100644 --- a/modular_skyrat/modules/synths/code/bodyparts/tongue.dm +++ b/modular_skyrat/modules/synths/code/bodyparts/tongue.dm @@ -1,13 +1,36 @@ /obj/item/organ/internal/tongue/synth name = "synthetic voicebox" - desc = "A voice synthesizer that allows synths to communicate with lifeforms. Tuned to sound less agressive than robotic voiceboxes." - icon = 'modular_skyrat/master_files/icons/obj/surgery.dmi' - icon_state = "tongue-ipc" + desc = "A fully-functional synthetic tongue, encased in soft silicone. Features include high-resolution vocals and taste receptors." + icon = 'modular_skyrat/modules/organs/icons/cyber_tongue.dmi' + icon_state = "cybertongue" say_mod = "beeps" + attack_verb_continuous = list("beeps", "boops") + attack_verb_simple = list("beep", "boop") modifies_speech = TRUE taste_sensitivity = 25 // not as good as an organic tongue maxHealth = 100 //RoboTongue! + zone = BODY_ZONE_HEAD + slot = ORGAN_SLOT_TONGUE organ_flags = ORGAN_ROBOTIC | ORGAN_SYNTHETIC_FROM_SPECIES +/obj/item/organ/internal/tongue/synth/can_speak_language(language) + return TRUE + /obj/item/organ/internal/tongue/synth/handle_speech(datum/source, list/speech_args) speech_args[SPEECH_SPANS] |= SPAN_ROBOT + +/datum/design/synth_tongue + name = "Synthetic Tongue" + desc = "A fully-functional synthetic tongue, encased in soft silicone. Features include high-resolution vocals and taste receptors." + id = "synth_tongue" + build_type = PROTOLATHE | AWAY_LATHE | MECHFAB + construction_time = 4 SECONDS + materials = list( + /datum/material/iron = SMALL_MATERIAL_AMOUNT * 5, + /datum/material/glass = SMALL_MATERIAL_AMOUNT * 5, + ) + build_path = /obj/item/organ/internal/tongue/synth + category = list( + RND_CATEGORY_CYBERNETICS + RND_SUBCATEGORY_CYBERNETICS_ORGANS_1 + ) + departmental_flags = DEPARTMENT_BITFLAG_MEDICAL | DEPARTMENT_BITFLAG_SCIENCE diff --git a/modular_skyrat/modules/synths/code/species/synthetic.dm b/modular_skyrat/modules/synths/code/species/synthetic.dm index 5b98c45a3c0..f8a521fd2e4 100644 --- a/modular_skyrat/modules/synths/code/species/synthetic.dm +++ b/modular_skyrat/modules/synths/code/species/synthetic.dm @@ -8,7 +8,6 @@ TRAIT_CAN_USE_FLIGHT_POTION, TRAIT_ADVANCEDTOOLUSER, TRAIT_RADIMMUNE, - TRAIT_VIRUSIMMUNE, TRAIT_NOBREATH, TRAIT_TOXIMMUNE, TRAIT_NOCLONELOSS, diff --git a/strings/tips.txt b/strings/tips.txt index 12712346bd2..514a9dada7a 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!