Files
Cameron Lennox 8d1c3f319a Horror modifier adjusments (#19544)
* Horror modifier adjusments

Removes nutrition drain

Makes it so your organs mutate every 200 seconds you've been under it instead of checking life ticks.

Makes it so only 1-2 organs get replaced per 200 seconds instead of 2-3
Makes redspace injection chance much lower (3%->0.5%)
Makes it so you won't repeatedly stab someone with fleshy spread if they already have it.

Makes exiting battle stance while infected a bit better.

Armor now lasts 1 minute. Lowers after 1 minute if health and the such is fixed.

Allows using bruise/ointment on changeling flesh armor...it's flesh and an extension of them.

Makes the fleshy virus chance of organ mutation from 5 to 0.5

Fixes GBS to be actually curable.

Implements COMSIG_ITEM_ATTACK_ZONE and COMSIG_ITEM_ATTACK

* Update redspace_corruption.dm

* Update vorestation.dme

* Update horror.dm
2026-06-25 11:03:17 -04:00

222 lines
7.1 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, weak_infection_chance = 10)
if(!ismovable(parent))
return COMPONENT_INCOMPATIBLE
if(!islist(diseases))
diseases = list(diseases)
///Make sure the diseases list is populated with instances of diseases so that it doesn't have to be for each AddComponent call.
for(var/datum/disease/disease as anything in diseases)
if(!disease) //empty entry, remove.
diseases -= disease
if(ispath(disease, /datum/disease))
var/datum/disease/instance = new disease
diseases -= disease
diseases += instance
else if(!istype(disease))
stack_trace("found [isdatum(disease) ? "an instance of [disease.type]" : disease] inside the diseases list argument for [type]")
diseases -= disease
src.diseases = diseases
if(expire_in)
expire_time = world.time + expire_in
QDEL_IN(src, expire_in)
is_weak = weak
src.weak_infection_chance = weak_infection_chance
/datum/component/infective/Destroy()
QDEL_LIST(diseases)
return ..()
/datum/component/infective/RegisterWithParent()
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))
return
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))
RegisterSignal(parent, COMSIG_ATOM_EXTRAPOLATOR_ACT, PROC_REF(extrapolation))
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/glass))
RegisterSignal(parent, COMSIG_GLASS_DRANK, PROC_REF(try_infect_drink))
if(isorgan(parent))
RegisterSignal(parent, COMSIG_ORGAN_IMPLANTED, PROC_REF(on_organ_insertion))
/datum/component/infective/UnregisterFromParent()
. = ..()
UnregisterSignal(parent, list(
COMSIG_FOOD_EATEN,
COMSIG_PILL_CONSUMED,
COMSIG_COMPONENT_CLEAN_ACT,
COMSIG_MOVABLE_BUMP,
COMSIG_MOVABLE_IMPACT_ZONE,
COMSIG_ITEM_ATTACK_ZONE,
COMSIG_ITEM_ATTACK,
COMSIG_ITEM_EQUIPPED,
COMSIG_GLASS_DRANK,
COMSIG_ORGAN_IMPLANTED,
COMSIG_ATOM_EXTRAPOLATOR_ACT
))
qdel(GetComponent(/datum/component/connect_loc_behalf))
/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(HAS_TRAIT(eater, TRAIT_STRONG_STOMACH))
return
// eater.add_mood_event("disgust", /datum/mood_event/disgust/dirty_food)
for(var/datum/disease/disease as anything in diseases)
if(is_weak && !prob(weak_infection_chance))
continue
// if(!disease.has_required_infectious_organ(eater, ORGAN_SLOT_STOMACH))
// continue
eater.ForceContractDisease(disease)
if(!is_weak)
try_infect(feeder, BP_L_ARM)
/datum/component/infective/proc/try_infect_drink(datum/source, mob/living/drinker, mob/living/feeder)
SIGNAL_HANDLER
if(HAS_TRAIT(drinker, TRAIT_STRONG_STOMACH))
return
if(!is_weak)
var/bodypart_type
if(feeder.l_hand == source)
bodypart_type = BP_R_ARM
else if(feeder.r_hand == source)
bodypart_type = BP_L_ARM
else
bodypart_type = BP_TORSO
try_infect(feeder, bodypart_type)
for(var/datum/disease/disease as anything in diseases)
if(is_weak && !prob(weak_infection_chance))
continue
// 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|COMPONENT_CLEANED_GAIN_XP
/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(obj/item/source, mob/living/carbon/target, mob/living/user, hit_zone)
SIGNAL_HANDLER
try_infect(target, hit_zone)
/datum/component/infective/proc/try_infect_attack(obj/item/source, mob/living/target, mob/living/user)
SIGNAL_HANDLER
if(source.loc == user)
var/obj/item/organ/external/hand = user.get_active_hand()
if(!istype(hand)) //Some fuckery is going on here.
return
if(hand.body_part == HAND_LEFT)
try_infect(user, BP_L_HAND)
else
try_infect(user, BP_R_HAND)
/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.armor["bio"]
equipped_item.armor["bio"] = 0
try_infect(L, slot2body_zone(slot))
if(isitem(parent))
var/obj/item/equipped_item = parent
equipped_item.armor["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, BP_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.ContractDisease(V, target_zone)
/datum/component/infective/proc/extrapolation(datum/source, mob/user, obj/item/extrapolator/extrapolator, dry_run = FALSE, list/result)
SIGNAL_HANDLER
EXTRAPOLATOR_ACT_ADD_DISEASES(result, diseases)