Files
Bubberstation/code/datums/components/infective.dm
Zergspower 88bf87fa4e [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

🆑
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
/🆑

---------

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 <timothymtorres@gmail.com>
Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com>
Co-authored-by: GoldenAlpharex <58045821+GoldenAlpharex@users.noreply.github.com>
2023-08-04 15:07:07 -04:00

164 lines
5.6 KiB
Plaintext

/datum/component/infective
var/list/datum/disease/diseases //make sure these are the static, non-processing versions!
var/expire_time
var/required_clean_types = CLEAN_TYPE_DISEASE
/// The infection is weak and can only infect on consumption with small chance
var/is_weak = FALSE
/// Chance of weak infection on consumption
var/weak_infection_chance = 10
/datum/component/infective/Initialize(list/datum/disease/_diseases, expire_in, weak = FALSE)
if(islist(_diseases))
diseases = _diseases
else
diseases = list(_diseases)
if(expire_in)
expire_time = world.time + expire_in
QDEL_IN(src, expire_in)
if(!ismovable(parent))
return COMPONENT_INCOMPATIBLE
is_weak = weak
if(is_weak && isitem(parent))
RegisterSignal(parent, COMSIG_FOOD_EATEN, PROC_REF(try_infect_eat))
RegisterSignal(parent, COMSIG_PILL_CONSUMED, PROC_REF(try_infect_eat))
else
var/static/list/disease_connections = list(
COMSIG_ATOM_ENTERED = PROC_REF(try_infect_crossed),
)
AddComponent(/datum/component/connect_loc_behalf, parent, disease_connections)
RegisterSignal(parent, COMSIG_COMPONENT_CLEAN_ACT, PROC_REF(clean))
RegisterSignal(parent, COMSIG_MOVABLE_BUCKLE, PROC_REF(try_infect_buckle))
RegisterSignal(parent, COMSIG_MOVABLE_BUMP, PROC_REF(try_infect_collide))
RegisterSignal(parent, COMSIG_MOVABLE_IMPACT_ZONE, PROC_REF(try_infect_impact_zone))
if(isitem(parent))
RegisterSignal(parent, COMSIG_ITEM_ATTACK_ZONE, PROC_REF(try_infect_attack_zone))
RegisterSignal(parent, COMSIG_ITEM_ATTACK, PROC_REF(try_infect_attack))
RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, PROC_REF(try_infect_equipped))
RegisterSignal(parent, COMSIG_FOOD_EATEN, PROC_REF(try_infect_eat))
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
if(!eater.has_quirk(/datum/quirk/deviant_tastes))
eater.add_mood_event("disgust", /datum/mood_event/disgust/dirty_food)
if(is_weak && !prob(weak_infection_chance))
return
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
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
. = NONE
if(clean_types & required_clean_types)
qdel(src)
return COMPONENT_CLEANED
/datum/component/infective/proc/try_infect_buckle(datum/source, mob/M, force)
SIGNAL_HANDLER
if(isliving(M))
try_infect(M)
/datum/component/infective/proc/try_infect_collide(datum/source, atom/A)
SIGNAL_HANDLER
var/atom/movable/P = parent
if(P.throwing)
//this will be handled by try_infect_impact_zone()
return
if(isliving(A))
try_infect(A)
/datum/component/infective/proc/try_infect_impact_zone(datum/source, mob/living/target, hit_zone)
SIGNAL_HANDLER
try_infect(target, hit_zone)
/datum/component/infective/proc/try_infect_attack_zone(datum/source, mob/living/carbon/target, mob/living/user, hit_zone)
SIGNAL_HANDLER
try_infect(user, BODY_ZONE_L_ARM)
try_infect(target, hit_zone)
/datum/component/infective/proc/try_infect_attack(datum/source, mob/living/target, mob/living/user)
SIGNAL_HANDLER
if(!iscarbon(target)) //this case will be handled by try_infect_attack_zone
try_infect(target)
try_infect(user, BODY_ZONE_L_ARM)
/datum/component/infective/proc/try_infect_equipped(datum/source, mob/living/L, slot)
SIGNAL_HANDLER
var/old_bio_armor
if(isitem(parent))
//if you are putting an infective item on, it obviously will not protect you, so set its bio armor low enough that it will never block ContactContractDisease()
var/obj/item/equipped_item = parent
old_bio_armor = equipped_item.get_armor_rating(BIO)
equipped_item.set_armor_rating(BIO, 0)
try_infect(L, slot2body_zone(slot))
if(isitem(parent))
var/obj/item/equipped_item = parent
equipped_item.set_armor_rating(BIO, old_bio_armor)
/datum/component/infective/proc/try_infect_crossed(datum/source, atom/movable/arrived, atom/old_loc, list/atom/old_locs)
SIGNAL_HANDLER
if(isliving(arrived))
try_infect(arrived, BODY_ZONE_PRECISE_L_FOOT)
/datum/component/infective/proc/try_infect_streak(datum/source, list/directions, list/output_diseases)
SIGNAL_HANDLER
// This blood is not infectable / does not have a diseases list
if(!islist(output_diseases))
return
output_diseases |= diseases
/datum/component/infective/proc/try_infect(mob/living/L, target_zone)
for(var/V in diseases)
L.ContactContractDisease(V, target_zone)