diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index 5ab16b5a5ff591..7f007e5b30ec49 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -954,6 +954,9 @@ GLOBAL_LIST_INIT(layers_to_offset, list( /// Types of bullets that mining mobs take full damage from #define MINING_MOB_PROJECTILE_VULNERABILITY list(BRUTE) +/// Helper macro that determines if the mob is at the threshold to start vomitting due to high toxin levels +#define AT_TOXIN_VOMIT_THRESHOLD(mob) (mob.getToxLoss() > 45 && mob.nutrition > 20) + /// The duration of the flip emote animation #define FLIP_EMOTE_DURATION 0.7 SECONDS diff --git a/code/__DEFINES/role_preferences.dm b/code/__DEFINES/role_preferences.dm index ee7e5dfee0d125..88e64164acd4ba 100644 --- a/code/__DEFINES/role_preferences.dm +++ b/code/__DEFINES/role_preferences.dm @@ -33,7 +33,6 @@ #define ROLE_OPERATIVE_MIDROUND "Operative (Midround)" #define ROLE_PARADOX_CLONE "Paradox Clone" #define ROLE_REV_HEAD "Head Revolutionary" -#define ROLE_SENTIENT_DISEASE "Sentient Disease" #define ROLE_SLEEPER_AGENT "Syndicate Sleeper Agent" #define ROLE_SPACE_DRAGON "Space Dragon" #define ROLE_SPIDER "Spider" @@ -150,7 +149,6 @@ GLOBAL_LIST_INIT(special_roles, list( ROLE_OPERATIVE_MIDROUND = 14, ROLE_PARADOX_CLONE = 0, ROLE_REVENANT = 0, - ROLE_SENTIENT_DISEASE = 0, ROLE_SLEEPER_AGENT = 0, ROLE_SPACE_DRAGON = 0, ROLE_SPIDER = 0, diff --git a/code/controllers/subsystem/dynamic/dynamic_rulesets_midround.dm b/code/controllers/subsystem/dynamic/dynamic_rulesets_midround.dm index 539e6d234c00e0..8ac5f27c4c9b9b 100644 --- a/code/controllers/subsystem/dynamic/dynamic_rulesets_midround.dm +++ b/code/controllers/subsystem/dynamic/dynamic_rulesets_midround.dm @@ -756,26 +756,6 @@ log_game("[key_name(revenant)] was spawned as a revenant by the midround ruleset.") return revenant -/// Midround Sentient Disease Ruleset (From Ghosts) -/datum/dynamic_ruleset/midround/from_ghosts/sentient_disease - name = "Sentient Disease" - midround_ruleset_style = MIDROUND_RULESET_STYLE_HEAVY - antag_datum = /datum/antagonist/disease - antag_flag = ROLE_SENTIENT_DISEASE - required_candidates = 1 - minimum_players = 25 - weight = 4 - cost = 8 - repeatable = TRUE - -/datum/dynamic_ruleset/midround/from_ghosts/sentient_disease/generate_ruleset_body(mob/applicant) - var/mob/camera/disease/virus = new /mob/camera/disease(SSmapping.get_station_center()) - virus.key = applicant.key - INVOKE_ASYNC(virus, TYPE_PROC_REF(/mob/camera/disease, pick_name)) - message_admins("[ADMIN_LOOKUPFLW(virus)] has been made into a sentient disease by the midround ruleset.") - log_game("[key_name(virus)] was spawned as a sentient disease by the midround ruleset.") - return virus - /// Midround Space Pirates Ruleset (From Ghosts) /datum/dynamic_ruleset/midround/pirates name = "Space Pirates" diff --git a/code/datums/components/infective.dm b/code/datums/components/infective.dm index fc2081481d937c..0e5341eabbfe5f 100644 --- a/code/datums/components/infective.dm +++ b/code/datums/components/infective.dm @@ -45,8 +45,6 @@ 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 @@ -180,6 +178,5 @@ COMSIG_ITEM_EQUIPPED, COMSIG_GLASS_DRANK, COMSIG_ORGAN_IMPLANTED, - COMSIG_GIBS_STREAK, )) qdel(GetComponent(/datum/component/connect_loc_behalf)) diff --git a/code/datums/status_effects/debuffs/tox_vomit.dm b/code/datums/status_effects/debuffs/tox_vomit.dm new file mode 100644 index 00000000000000..c1f5aa651efb46 --- /dev/null +++ b/code/datums/status_effects/debuffs/tox_vomit.dm @@ -0,0 +1,23 @@ +/// Simple status effect applied when a mob has high toxins and starts to vomit regularly +/datum/status_effect/tox_vomit + id = "vomitting_from_toxins" + tick_interval = 2 SECONDS + alert_type = null + /// Has a chance to count up every tick, until it reaches a threshold, which causes the mob to vomit and resets + VAR_PRIVATE/puke_counter = 0 + +/datum/status_effect/tox_vomit/tick(seconds_between_ticks) + if(!AT_TOXIN_VOMIT_THRESHOLD(owner)) + qdel(src) + return + + if(owner.stat == DEAD || HAS_TRAIT(owner, TRAIT_STASIS)) + return + + puke_counter += SPT_PROB(30, seconds_between_ticks) + if(puke_counter < 50) // This is like 150 seconds apparently according to old comments + return + + var/mob/living/carbon/human/sick_guy = owner + sick_guy.vomit(VOMIT_CATEGORY_DEFAULT, lost_nutrition = 20) + puke_counter = 0 diff --git a/code/game/objects/effects/decals/cleanable/humans.dm b/code/game/objects/effects/decals/cleanable/humans.dm index 064f3d0f5d0b07..c95bffdc626761 100644 --- a/code/game/objects/effects/decals/cleanable/humans.dm +++ b/code/game/objects/effects/decals/cleanable/humans.dm @@ -111,8 +111,6 @@ drydesc = "They look bloody and gruesome while some terrible smell fills the air." decal_reagent = /datum/reagent/consumable/liquidgibs reagent_amount = 5 - ///Information about the diseases our streaking spawns - var/list/streak_diseases /obj/effect/decal/cleanable/blood/gibs/Initialize(mapload, list/datum/disease/diseases) . = ..() @@ -120,7 +118,6 @@ RegisterSignal(src, COMSIG_MOVABLE_PIPE_EJECTING, PROC_REF(on_pipe_eject)) /obj/effect/decal/cleanable/blood/gibs/Destroy() - LAZYNULL(streak_diseases) return ..() /obj/effect/decal/cleanable/blood/gibs/replace_decal(obj/effect/decal/cleanable/C) @@ -147,8 +144,7 @@ streak(dirs) /obj/effect/decal/cleanable/blood/gibs/proc/streak(list/directions, mapload=FALSE) - LAZYINITLIST(streak_diseases) - SEND_SIGNAL(src, COMSIG_GIBS_STREAK, directions, streak_diseases) + SEND_SIGNAL(src, COMSIG_GIBS_STREAK, directions) var/direction = pick(directions) var/delay = 2 var/range = pick(0, 200; 1, 150; 2, 50; 3, 17; 50) //the 3% chance of 50 steps is intentional and played for laughs. @@ -170,7 +166,7 @@ SIGNAL_HANDLER if(NeverShouldHaveComeHere(loc)) return - new /obj/effect/decal/cleanable/blood/splatter(loc, streak_diseases) + new /obj/effect/decal/cleanable/blood/splatter(loc) /obj/effect/decal/cleanable/blood/gibs/up icon_state = "gibup1" diff --git a/code/modules/admin/sql_ban_system.dm b/code/modules/admin/sql_ban_system.dm index c39706795acd01..9a713588abd6d3 100644 --- a/code/modules/admin/sql_ban_system.dm +++ b/code/modules/admin/sql_ban_system.dm @@ -391,7 +391,6 @@ ROLE_REV, ROLE_REVENANT, ROLE_REV_HEAD, - ROLE_SENTIENT_DISEASE, ROLE_SPIDER, ROLE_SPY, ROLE_SYNDICATE, diff --git a/code/modules/antagonists/disease/disease_abilities.dm b/code/modules/antagonists/disease/disease_abilities.dm deleted file mode 100644 index 3267944e05c62d..00000000000000 --- a/code/modules/antagonists/disease/disease_abilities.dm +++ /dev/null @@ -1,465 +0,0 @@ -/* -Abilities that can be purchased by disease mobs. Most are just passive symptoms that will be -added to their disease, but some are active abilites that affect only the target the overmind -is currently following. -*/ - -GLOBAL_LIST_INIT(disease_ability_singletons, list( -new /datum/disease_ability/action/cough, -new /datum/disease_ability/action/sneeze, -new /datum/disease_ability/action/infect, -new /datum/disease_ability/symptom/mild/cough, -new /datum/disease_ability/symptom/mild/sneeze, -new /datum/disease_ability/symptom/medium/shedding, -new /datum/disease_ability/symptom/medium/beard, -new /datum/disease_ability/symptom/medium/hallucigen, -new /datum/disease_ability/symptom/medium/choking, -new /datum/disease_ability/symptom/medium/confusion, -new /datum/disease_ability/symptom/medium/vomit, -new /datum/disease_ability/symptom/medium/voice_change, -new /datum/disease_ability/symptom/medium/visionloss, -new /datum/disease_ability/symptom/medium/deafness, -new /datum/disease_ability/symptom/powerful/narcolepsy, -new /datum/disease_ability/symptom/medium/fever, -new /datum/disease_ability/symptom/medium/chills, -new /datum/disease_ability/symptom/medium/headache, -new /datum/disease_ability/symptom/medium/viraladaptation, -new /datum/disease_ability/symptom/medium/viralevolution, -new /datum/disease_ability/symptom/medium/disfiguration, -new /datum/disease_ability/symptom/medium/polyvitiligo, -new /datum/disease_ability/symptom/medium/itching, -new /datum/disease_ability/symptom/medium/heal/weight_loss, -new /datum/disease_ability/symptom/medium/heal/sensory_restoration, -new /datum/disease_ability/symptom/medium/heal/mind_restoration, -new /datum/disease_ability/symptom/powerful/fire, -new /datum/disease_ability/symptom/powerful/flesh_eating, -new /datum/disease_ability/symptom/powerful/genetic_mutation, -new /datum/disease_ability/symptom/powerful/inorganic_adaptation, -new /datum/disease_ability/symptom/powerful/heal/starlight, -new /datum/disease_ability/symptom/powerful/heal/oxygen, -new /datum/disease_ability/symptom/powerful/heal/chem, -new /datum/disease_ability/symptom/powerful/heal/metabolism, -new /datum/disease_ability/symptom/powerful/heal/dark, -new /datum/disease_ability/symptom/powerful/heal/water, -new /datum/disease_ability/symptom/powerful/heal/plasma, -new /datum/disease_ability/symptom/powerful/heal/radiation, -new /datum/disease_ability/symptom/powerful/heal/coma, -new /datum/disease_ability/symptom/powerful/youth -)) - -/datum/disease_ability - var/name - var/cost = 0 - var/required_total_points = 0 - var/start_with = FALSE - var/short_desc = "" - var/long_desc = "" - var/stat_block = "" - var/threshold_block = list() - var/category = "" - - var/list/symptoms - var/list/actions - -/datum/disease_ability/New() - ..() - if(symptoms) - var/stealth = 0 - var/resistance = 0 - var/stage_speed = 0 - var/transmittable = 0 - for(var/T in symptoms) - var/datum/symptom/S = T - stealth += initial(S.stealth) - resistance += initial(S.resistance) - stage_speed += initial(S.stage_speed) - transmittable += initial(S.transmittable) - threshold_block += initial(S.threshold_descs) - stat_block = "Resistance: [resistance]
Stealth: [stealth]
Stage Speed: [stage_speed]
Transmissibility: [transmittable]

" - if(symptoms.len == 1) //lazy boy's dream - name = initial(S.name) - if(short_desc == "") - short_desc = initial(S.desc) - if(long_desc == "") - long_desc = initial(S.desc) - -/datum/disease_ability/proc/CanBuy(mob/camera/disease/D) - if(world.time < D.next_adaptation_time) - return FALSE - if(!D.unpurchased_abilities[src]) - return FALSE - return (D.points >= cost) && (D.total_points >= required_total_points) - -/datum/disease_ability/proc/Buy(mob/camera/disease/D, silent = FALSE, trigger_cooldown = TRUE) - if(!silent) - to_chat(D, span_notice("Purchased [name].")) - D.points -= cost - D.unpurchased_abilities -= src - if(trigger_cooldown) - D.adapt_cooldown() - D.purchased_abilities[src] = TRUE - for(var/V in (D.disease_instances+D.disease_template)) - var/datum/disease/advance/sentient_disease/SD = V - if(symptoms) - for(var/T in symptoms) - var/datum/symptom/S = new T() - SD.symptoms += S - S.OnAdd(SD) - if(SD.processing) - if(S.Start(SD)) - S.next_activation = world.time + rand(S.symptom_delay_min * 10, S.symptom_delay_max * 10) - SD.Refresh() - for(var/T in actions) - var/datum/action/A = new T() - A.Grant(D) - - -/datum/disease_ability/proc/CanRefund(mob/camera/disease/D) - if(world.time < D.next_adaptation_time) - return FALSE - return D.purchased_abilities[src] - -/datum/disease_ability/proc/Refund(mob/camera/disease/D, silent = FALSE, trigger_cooldown = TRUE) - if(!silent) - to_chat(D, span_notice("Refunded [name].")) - D.points += cost - D.unpurchased_abilities[src] = TRUE - if(trigger_cooldown) - D.adapt_cooldown() - D.purchased_abilities -= src - for(var/V in (D.disease_instances+D.disease_template)) - var/datum/disease/advance/sentient_disease/SD = V - if(symptoms) - for(var/T in symptoms) - var/datum/symptom/S = locate(T) in SD.symptoms - if(S) - SD.symptoms -= S - S.OnRemove(SD) - if(SD.processing) - S.End(SD) - qdel(S) - SD.Refresh() - for(var/T in actions) - var/datum/action/A = locate(T) in D.actions - qdel(A) - -//these sybtypes are for conveniently separating the different categories, they have no unique code. - -/datum/disease_ability/action - category = "Active" - -/datum/disease_ability/symptom - category = "Symptom" - -//active abilities and their associated actions - -/datum/disease_ability/action/cough - name = "Voluntary Coughing" - actions = list(/datum/action/cooldown/disease_cough) - cost = 0 - required_total_points = 0 - start_with = TRUE - short_desc = "Force the host you are following to cough, spreading your infection to those nearby." - long_desc = "Force the host you are following to cough with extra force, spreading your infection to those within two meters of your host even if your transmissibility is low.
Cooldown: 10 seconds" - - -/datum/action/cooldown/disease_cough - name = "Cough" - button_icon = 'icons/mob/actions/actions_minor_antag.dmi' - button_icon_state = "cough" - desc = "Force the host you are following to cough with extra force, spreading your infection to those within two meters of your host even if your transmissibility is low.
Cooldown: 10 seconds" - cooldown_time = 100 - -/datum/action/cooldown/disease_cough/Activate(atom/target) - StartCooldown(10 SECONDS) - trigger_cough() - StartCooldown() - return TRUE - -/* - * Cause a cough to happen from the host. - */ -/datum/action/cooldown/disease_cough/proc/trigger_cough() - var/mob/camera/disease/our_disease = owner - var/mob/living/host = our_disease.following_host - if(!host) - return FALSE - if(host.stat != CONSCIOUS) - to_chat(our_disease, span_warning("Your host must be conscious to cough.")) - return FALSE - to_chat(our_disease, span_notice("You force [host.real_name] to cough.")) - host.emote("cough") - if(host.CanSpreadAirborneDisease()) //don't spread germs if they covered their mouth - var/datum/disease/advance/sentient_disease/disease_datum = our_disease.hosts[host] - disease_datum.spread(2) - return TRUE - -/datum/disease_ability/action/sneeze - name = "Voluntary Sneezing" - actions = list(/datum/action/cooldown/disease_sneeze) - cost = 2 - required_total_points = 3 - short_desc = "Force the host you are following to sneeze, spreading your infection to those in front of them." - long_desc = "Force the host you are following to sneeze with extra force, spreading your infection to any victims in a 4 meter cone in front of your host.
Cooldown: 20 seconds" - -/datum/action/cooldown/disease_sneeze - name = "Sneeze" - button_icon = 'icons/mob/actions/actions_minor_antag.dmi' - button_icon_state = "sneeze" - desc = "Force the host you are following to sneeze with extra force, spreading your infection to any victims in a 4 meter cone in front of your host even if your transmissibility is low.
Cooldown: 20 seconds" - cooldown_time = 200 - -/datum/action/cooldown/disease_sneeze/Activate(atom/target) - StartCooldown(10 SECONDS) - trigger_sneeze() - StartCooldown() - return TRUE - -/* - * Cause a sneeze to happen from the host. - */ -/datum/action/cooldown/disease_sneeze/proc/trigger_sneeze() - var/mob/camera/disease/our_disease = owner - var/mob/living/host = our_disease.following_host - if(!host) - return FALSE - if(host.stat != CONSCIOUS) - to_chat(our_disease, span_warning("Your host must be conscious to sneeze.")) - return FALSE - to_chat(our_disease, span_notice("You force [host.real_name] to sneeze.")) - host.emote("sneeze") - if(host.CanSpreadAirborneDisease()) //don't spread germs if they covered their mouth - var/datum/disease/advance/sentient_disease/disease_datum = our_disease.hosts[host] - for(var/mob/living/nearby_mob in oview(4, disease_datum.affected_mob)) - if(!is_source_facing_target(disease_datum.affected_mob, nearby_mob)) - continue - if(!disease_air_spread_walk(get_turf(disease_datum.affected_mob), get_turf(nearby_mob))) - continue - nearby_mob.AirborneContractDisease(disease_datum, TRUE) - - return TRUE - -/datum/disease_ability/action/infect - name = "Secrete Infection" - actions = list(/datum/action/cooldown/disease_infect) - cost = 2 - required_total_points = 3 - short_desc = "Cause all objects your host is touching to become infectious for a limited time, spreading your infection to anyone who touches them." - long_desc = "Cause the host you are following to excrete an infective substance from their pores, causing all objects touching their skin to transmit your infection to anyone who touches them for the next 30 seconds. This includes the floor, if they are not wearing shoes, and any items they are holding, if they are not wearing gloves.
Cooldown: 40 seconds" - -/datum/action/cooldown/disease_infect - name = "Secrete Infection" - button_icon = 'icons/mob/actions/actions_minor_antag.dmi' - button_icon_state = "infect" - desc = "Cause the host you are following to excrete an infective substance from their pores, causing all objects touching their skin to transmit your infection to anyone who touches them for the next 30 seconds.
Cooldown: 40 seconds" - cooldown_time = 400 - -/datum/action/cooldown/disease_infect/Activate(atom/target) - StartCooldown(10 SECONDS) - trigger_infection() - StartCooldown() - return TRUE - -/* - * Trigger the infection action. - */ -/datum/action/cooldown/disease_infect/proc/trigger_infection() - var/mob/camera/disease/our_disease = owner - var/mob/living/carbon/human/host = our_disease.following_host - if(!host) - return FALSE - for(var/obj/thing as anything in host.get_equipped_items(include_accessories = TRUE)) - thing.AddComponent(/datum/component/infective, our_disease.disease_template, 300) - //no shoes? infect the floor. - if(!host.shoes) - var/turf/host_turf = get_turf(host) - if(host_turf && !isspaceturf(host_turf)) - host_turf.AddComponent(/datum/component/infective, our_disease.disease_template, 300) - //no gloves? infect whatever we are holding. - if(!host.gloves) - for(var/obj/held_thing as anything in host.held_items) - if(isnull(held_thing)) - continue - held_thing.AddComponent(/datum/component/infective, our_disease.disease_template, 300) - return TRUE - -/*******************BASE SYMPTOM TYPES*******************/ -// cost is for convenience and can be changed. If you're changing req_tot_points then don't use the subtype... -//healing costs more so you have to techswitch from naughty disease otherwise we'd have friendly disease for easy greentext (no fun!) - -/datum/disease_ability/symptom/mild - cost = 2 - required_total_points = 4 - category = "Symptom (Weak)" - -/datum/disease_ability/symptom/medium - cost = 4 - required_total_points = 8 - category = "Symptom" - -/datum/disease_ability/symptom/medium/heal - cost = 5 - category = "Symptom (+)" - -/datum/disease_ability/symptom/powerful - cost = 4 - required_total_points = 16 - category = "Symptom (Strong)" - -/datum/disease_ability/symptom/powerful/heal - cost = 8 - category = "Symptom (Strong+)" - -/******MILD******/ - -/datum/disease_ability/symptom/mild/cough - name = "Involuntary Coughing" - symptoms = list(/datum/symptom/cough) - short_desc = "Cause victims to cough intermittently." - long_desc = "Cause victims to cough intermittently, spreading your infection." - -/datum/disease_ability/symptom/mild/sneeze - name = "Involuntary Sneezing" - symptoms = list(/datum/symptom/sneeze) - short_desc = "Cause victims to sneeze intermittently." - long_desc = "Cause victims to sneeze intermittently, spreading your infection and also increasing transmissibility and resistance, at the cost of stealth." - -/******MEDIUM******/ - -/datum/disease_ability/symptom/medium/shedding - symptoms = list(/datum/symptom/shedding) - -/datum/disease_ability/symptom/medium/beard - symptoms = list(/datum/symptom/beard) - short_desc = "Cause all victims to grow a luscious beard." - long_desc = "Cause all victims to grow a luscious beard. Ineffective against Santa Claus." - -/datum/disease_ability/symptom/medium/hallucigen - symptoms = list(/datum/symptom/hallucigen) - short_desc = "Cause victims to hallucinate." - long_desc = "Cause victims to hallucinate. Decreases stats, especially resistance." - -/datum/disease_ability/symptom/medium/choking - symptoms = list(/datum/symptom/choking) - short_desc = "Cause victims to choke." - long_desc = "Cause victims to choke, threatening asphyxiation. Decreases stats, especially transmissibility." - -/datum/disease_ability/symptom/medium/confusion - symptoms = list(/datum/symptom/confusion) - short_desc = "Cause victims to become confused." - long_desc = "Cause victims to become confused intermittently." - -/datum/disease_ability/symptom/medium/vomit - symptoms = list(/datum/symptom/vomit) - short_desc = "Cause victims to vomit." - long_desc = "Cause victims to vomit. Slightly increases transmissibility. Vomiting also also causes the victims to lose nutrition and removes some toxin damage." - -/datum/disease_ability/symptom/medium/voice_change - symptoms = list(/datum/symptom/voice_change) - short_desc = "Change the voice of victims." - long_desc = "Change the voice of victims, causing confusion in communications." - -/datum/disease_ability/symptom/medium/visionloss - symptoms = list(/datum/symptom/visionloss) - short_desc = "Damage the eyes of victims, eventually causing blindness." - long_desc = "Damage the eyes of victims, eventually causing blindness. Decreases all stats." - -/datum/disease_ability/symptom/medium/deafness - symptoms = list(/datum/symptom/deafness) - -/datum/disease_ability/symptom/medium/fever - symptoms = list(/datum/symptom/fever) - -/datum/disease_ability/symptom/medium/chills - symptoms = list(/datum/symptom/chills) - -/datum/disease_ability/symptom/medium/headache - symptoms = list(/datum/symptom/headache) - -/datum/disease_ability/symptom/medium/viraladaptation - symptoms = list(/datum/symptom/viraladaptation) - short_desc = "Cause your infection to become more resistant to detection and eradication." - long_desc = "Cause your infection to mimic the function of normal body cells, becoming much harder to spot and to eradicate, but reducing its speed." - -/datum/disease_ability/symptom/medium/viralevolution - symptoms = list(/datum/symptom/viralevolution) - -/datum/disease_ability/symptom/medium/polyvitiligo - symptoms = list(/datum/symptom/polyvitiligo) - -/datum/disease_ability/symptom/medium/disfiguration - symptoms = list(/datum/symptom/disfiguration) - -/datum/disease_ability/symptom/medium/itching - symptoms = list(/datum/symptom/itching) - short_desc = "Cause victims to itch." - long_desc = "Cause victims to itch, increasing all stats except stealth." - -/datum/disease_ability/symptom/medium/heal/weight_loss - symptoms = list(/datum/symptom/weight_loss) - short_desc = "Cause victims to lose weight." - long_desc = "Cause victims to lose weight, and make it almost impossible for them to gain nutrition from food. Reduced nutrition allows your infection to spread more easily from hosts, especially by sneezing." - -/datum/disease_ability/symptom/medium/heal/sensory_restoration - symptoms = list(/datum/symptom/sensory_restoration) - short_desc = "Regenerate eye and ear damage of victims." - long_desc = "Regenerate eye and ear damage of victims." - -/datum/disease_ability/symptom/medium/heal/mind_restoration - symptoms = list(/datum/symptom/mind_restoration) - -/******POWERFUL******/ - -/datum/disease_ability/symptom/powerful/fire - symptoms = list(/datum/symptom/fire) - -/datum/disease_ability/symptom/powerful/flesh_eating - symptoms = list(/datum/symptom/flesh_eating) - -/datum/disease_ability/symptom/powerful/genetic_mutation - symptoms = list(/datum/symptom/genetic_mutation) - cost = 8 - -/datum/disease_ability/symptom/powerful/inorganic_adaptation - symptoms = list(/datum/symptom/inorganic_adaptation) - -/datum/disease_ability/symptom/powerful/narcolepsy - symptoms = list(/datum/symptom/narcolepsy) - -/datum/disease_ability/symptom/powerful/youth - symptoms = list(/datum/symptom/youth) - short_desc = "Cause victims to become eternally young." - long_desc = "Cause victims to become eternally young. Provides boosts to all stats except transmissibility." - -/****HEALING SUBTYPE****/ - -/datum/disease_ability/symptom/powerful/heal/starlight - symptoms = list(/datum/symptom/heal/starlight) - -/datum/disease_ability/symptom/powerful/heal/oxygen - symptoms = list(/datum/symptom/oxygen) - -/datum/disease_ability/symptom/powerful/heal/chem - symptoms = list(/datum/symptom/heal/chem) - -/datum/disease_ability/symptom/powerful/heal/metabolism - symptoms = list(/datum/symptom/heal/metabolism) - short_desc = "Increase the metabolism of victims, causing them to process chemicals and grow hungry faster." - long_desc = "Increase the metabolism of victims, causing them to process chemicals twice as fast and grow hungry more quickly." - -/datum/disease_ability/symptom/powerful/heal/dark - symptoms = list(/datum/symptom/heal/darkness) - -/datum/disease_ability/symptom/powerful/heal/water - symptoms = list(/datum/symptom/heal/water) - -/datum/disease_ability/symptom/powerful/heal/plasma - symptoms = list(/datum/symptom/heal/plasma) - -/datum/disease_ability/symptom/powerful/heal/radiation - symptoms = list(/datum/symptom/heal/radiation) - -/datum/disease_ability/symptom/powerful/heal/coma - symptoms = list(/datum/symptom/heal/coma) - short_desc = "Cause victims to fall into a healing coma when hurt." - long_desc = "Cause victims to fall into a healing coma when hurt." diff --git a/code/modules/antagonists/disease/disease_datum.dm b/code/modules/antagonists/disease/disease_datum.dm deleted file mode 100644 index 17364feec55977..00000000000000 --- a/code/modules/antagonists/disease/disease_datum.dm +++ /dev/null @@ -1,103 +0,0 @@ -/datum/antagonist/disease - name = "Sentient Disease" - roundend_category = "diseases" - antagpanel_category = ANTAG_GROUP_BIOHAZARDS - show_to_ghosts = TRUE - var/disease_name = "" - -/datum/antagonist/disease/on_gain() - owner.set_assigned_role(SSjob.GetJobType(/datum/job/sentient_disease)) - owner.special_role = ROLE_SENTIENT_DISEASE - var/datum/objective/O = new /datum/objective/disease_infect() - O.owner = owner - objectives += O - - O = new /datum/objective/disease_infect_centcom() - O.owner = owner - objectives += O - - . = ..() - -/datum/antagonist/disease/greet() - . = ..() - to_chat(owner.current, span_notice("Infect members of the crew to gain adaptation points, and spread your infection further.")) - owner.announce_objectives() - -/datum/antagonist/disease/apply_innate_effects(mob/living/mob_override) - if(!istype(owner.current, /mob/camera/disease)) - var/turf/T = get_turf(owner.current) - T = T ? T : SSmapping.get_station_center() - var/mob/camera/disease/D = new /mob/camera/disease(T) - owner.transfer_to(D) - -/datum/antagonist/disease/admin_add(datum/mind/new_owner,mob/admin) - ..() - var/mob/camera/disease/D = new_owner.current - D.pick_name() - -/datum/antagonist/disease/roundend_report() - var/list/result = list() - - result += "Disease name: [disease_name]" - result += printplayer(owner) - - var/win = TRUE - var/objectives_text = "" - var/count = 1 - for(var/datum/objective/objective in objectives) - if(objective.check_completion()) - objectives_text += "
Objective #[count]: [objective.explanation_text] [span_greentext("Success!")]" - else - objectives_text += "
Objective #[count]: [objective.explanation_text] [span_redtext("Fail.")]" - win = FALSE - count++ - - result += objectives_text - - var/special_role_text = LOWER_TEXT(name) - - if(win) - result += span_greentext("The [special_role_text] was successful!") - else - result += span_redtext("The [special_role_text] has failed!") - - if(istype(owner.current, /mob/camera/disease)) - var/mob/camera/disease/D = owner.current - result += "[disease_name] completed the round with [D.hosts.len] infected hosts, and reached a maximum of [D.total_points] concurrent infections." - result += "[disease_name] completed the round with the following adaptations:" - var/list/adaptations = list() - for(var/V in D.purchased_abilities) - var/datum/disease_ability/A = V - adaptations += A.name - result += adaptations.Join(", ") - - return result.Join("
") - -/datum/antagonist/disease/get_preview_icon() - var/icon/icon = icon('icons/mob/huds/antag_hud.dmi', "virus_infected") - icon.Blend(COLOR_GREEN_GRAY, ICON_MULTIPLY) - icon.Scale(ANTAGONIST_PREVIEW_ICON_SIZE, ANTAGONIST_PREVIEW_ICON_SIZE) - return icon - -/datum/objective/disease_infect - explanation_text = "Survive and infect as many people as possible." - -/datum/objective/disease_infect/check_completion() - var/mob/camera/disease/D = owner.current - if(istype(D) && D.hosts.len) //theoretically it should not exist if it has no hosts, but better safe than sorry. - return TRUE - return FALSE - - -/datum/objective/disease_infect_centcom - explanation_text = "Ensure that at least one infected host escapes on the shuttle or an escape pod." - -/datum/objective/disease_infect_centcom/check_completion() - var/mob/camera/disease/D = owner.current - if(!istype(D)) - return FALSE - for(var/V in D.hosts) - var/mob/living/L = V - if(L.onCentCom() || L.onSyndieBase()) - return TRUE - return FALSE diff --git a/code/modules/antagonists/disease/disease_disease.dm b/code/modules/antagonists/disease/disease_disease.dm deleted file mode 100644 index 8960ac27689939..00000000000000 --- a/code/modules/antagonists/disease/disease_disease.dm +++ /dev/null @@ -1,69 +0,0 @@ -/datum/disease/advance/sentient_disease - form = "Virus" - name = "Sentient Virus" - desc = "An apparently sentient virus, extremely adaptable and resistant to outside sources of mutation." - viable_mobtypes = list(/mob/living/carbon/human) - mutable = FALSE - bypasses_immunity = TRUE - var/mob/camera/disease/overmind - var/disease_id - -/datum/disease/advance/sentient_disease/New() - ..() - GLOB.sentient_disease_instances += src - -/datum/disease/advance/sentient_disease/Destroy() - . = ..() - overmind = null - GLOB.sentient_disease_instances -= src - -/datum/disease/advance/sentient_disease/remove_disease() - if(overmind) - overmind.remove_infection(src) - ..() - -/datum/disease/advance/sentient_disease/infect(mob/living/infectee, make_copy = TRUE) - if(make_copy && overmind && (overmind.disease_template != src)) - overmind.disease_template.infect(infectee, TRUE) //get an updated version of the virus - else - ..() - - -/datum/disease/advance/sentient_disease/IsSame(datum/disease/D) - if(istype(D, /datum/disease/advance/sentient_disease)) - var/datum/disease/advance/sentient_disease/V = D - if(V.overmind == overmind) - return TRUE - return FALSE - - -/datum/disease/advance/sentient_disease/Copy() - var/datum/disease/advance/sentient_disease/D = ..() - D.overmind = overmind - D.disease_id = disease_id - return D - -/datum/disease/advance/sentient_disease/after_add() - if(overmind) - overmind.add_infection(src) - -/datum/disease/advance/sentient_disease/GenerateProperties() - ..() - src.properties["stealth"] += 6 //SD gets an extra bit of stealth, as a treat, to avoid getting caught out so early - -/datum/disease/advance/sentient_disease/GetDiseaseID() - if (!disease_id) //if we don't set this here it can reinfect people after the disease dies, since overmind.tag won't be null when the disease is alive, but will be null afterwards, thus the disease ID changes - disease_id = "[type]|[overmind?.tag]" - return disease_id - -/datum/disease/advance/sentient_disease/generate_cure() - if(cures.len) - return - var/list/not_used = advance_cures.Copy() - not_used.Cut(1, 6) // Removes the first five tiers of cures. - cures = list(pick(pick_n_take(not_used)), pick(pick_n_take(not_used))) - - // Get the cure name from the cure_id - var/datum/reagent/D1 = GLOB.chemical_reagents_list[cures[1]] - var/datum/reagent/D2 = GLOB.chemical_reagents_list[cures[2]] - cure_text = "[D1.name] and [D2.name]" diff --git a/code/modules/antagonists/disease/disease_mob.dm b/code/modules/antagonists/disease/disease_mob.dm deleted file mode 100644 index acefd0e37173cf..00000000000000 --- a/code/modules/antagonists/disease/disease_mob.dm +++ /dev/null @@ -1,450 +0,0 @@ -#define FREEMOVE_TIME (2 MINUTES) - -/* -A mob of type /mob/camera/disease is an overmind coordinating at least one instance of /datum/disease/advance/sentient_disease -that has infected a host. All instances in a host will be synchronized with the stats of the overmind's disease_template. Any -samples outside of a host will retain the stats they had when they left the host, but infecting a new host will cause -the new instance inside the host to be updated to the template's stats. -*/ - -/mob/camera/disease - name = "Sentient Disease" - real_name = "Sentient Disease" - desc = "" - icon = 'icons/mob/silicon/cameramob.dmi' - icon_state = "marker" - mouse_opacity = MOUSE_OPACITY_ICON - move_on_shuttle = FALSE - invisibility = INVISIBILITY_OBSERVER - see_invisible = SEE_INVISIBLE_LIVING - layer = BELOW_MOB_LAYER - // Pale green, bright enough to have good vision - lighting_cutoff_red = 5 - lighting_cutoff_green = 35 - lighting_cutoff_blue = 20 - sight = SEE_SELF|SEE_THRU - initial_language_holder = /datum/language_holder/universal - - var/freemove = TRUE - var/freemove_end = 0 - var/freemove_end_timerid - - var/datum/action/innate/disease_adapt/adaptation_menu_action - var/datum/disease_ability/examining_ability - var/datum/browser/browser - var/browser_open = FALSE - - var/mob/living/following_host - var/list/disease_instances - var/list/hosts //this list is associative, affected_mob -> disease_instance - var/datum/disease/advance/sentient_disease/disease_template - - var/total_points = 0 - var/points = 0 - - var/last_move_tick = 0 - var/move_delay = 1 - - var/next_adaptation_time = 0 - var/adaptation_cooldown = 600 - - var/list/purchased_abilities - var/list/unpurchased_abilities - -/mob/camera/disease/Initialize(mapload) - .= ..() - - ADD_TRAIT(src, TRAIT_SIXTHSENSE, INNATE_TRAIT) //at least they'll have SOMEONE to talk to - - disease_instances = list() - hosts = list() - - purchased_abilities = list() - unpurchased_abilities = list() - - disease_template = new /datum/disease/advance/sentient_disease() - disease_template.overmind = src - qdel(SSdisease.archive_diseases[disease_template.GetDiseaseID()]) - SSdisease.archive_diseases[disease_template.GetDiseaseID()] = disease_template //important for stuff that uses disease IDs - - var/datum/atom_hud/my_hud = GLOB.huds[DATA_HUD_SENTIENT_DISEASE] - my_hud.show_to(src) - - browser = new /datum/browser(src, "disease_menu", "Adaptation Menu", 1000, 770, src) - - freemove_end = world.time + FREEMOVE_TIME - freemove_end_timerid = addtimer(CALLBACK(src, PROC_REF(infect_random_patient_zero)), FREEMOVE_TIME, TIMER_STOPPABLE) - -/mob/camera/disease/Destroy() - . = ..() - QDEL_NULL(adaptation_menu_action) - disease_template = null - for(var/V in GLOB.sentient_disease_instances) - var/datum/disease/advance/sentient_disease/S = V - if(S.overmind == src) - S.overmind = null - browser = null - -/mob/camera/disease/Login() - . = ..() - if(!. || !client) - return FALSE - if(freemove) - to_chat(src, span_warning("You have [DisplayTimeText(freemove_end - world.time)] to select your first host. Click on a human to select your host.")) - - -/mob/camera/disease/get_status_tab_items() - . = ..() - if(freemove) - . += "Host Selection Time: [round((freemove_end - world.time)/10)]s" - else - . += "Adaptation Points: [points]/[total_points]" - . += "Hosts: [disease_instances.len]" - var/adapt_ready = next_adaptation_time - world.time - if(adapt_ready > 0) - . += "Adaptation Ready: [round(adapt_ready/10, 0.1)]s" - - -/mob/camera/disease/examine(mob/user) - . = ..() - if(isobserver(user)) - . += {"[span_notice("[src] has [points]/[total_points] adaptation points.")] - [span_notice("[src] has the following unlocked:")]"} - for(var/datum/disease_ability/ability in purchased_abilities) - . += span_notice("[ability.name]") - -/mob/camera/disease/say( - message, - bubble_type, - list/spans = list(), - sanitize = TRUE, - datum/language/language, - ignore_spam = FALSE, - forced, - filterproof = FALSE, - message_range = 7, - datum/saymode/saymode, - list/message_mods = list(), -) - if(!message) - return - if(sanitize) - message = trim(copytext_char(sanitize(message), 1, MAX_MESSAGE_LEN)) - log_talk(message, LOG_SAY) - var/rendered = "[src] says, \"[message]\"" - for(var/mob/listener in GLOB.mob_list) - if(issentientdisease(listener)) - to_chat(listener, rendered) - else if(isobserver(listener)) - var/link = FOLLOW_LINK(listener, src) - to_chat(listener, "[link] [rendered]") - return - -/mob/camera/disease/Move(NewLoc, Dir = 0) - if(freemove) - forceMove(NewLoc) - else - if(world.time > (last_move_tick + move_delay)) - follow_next(Dir & NORTHWEST) - last_move_tick = world.time - -/mob/camera/disease/can_z_move(direction, turf/start, turf/destination, z_move_flags = NONE, mob/living/rider) - if(freemove) - return ..() - return FALSE - -/mob/camera/disease/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, list/message_mods = list(), message_range) - . = ..() - var/atom/movable/to_follow = speaker - if(radio_freq) - var/atom/movable/virtualspeaker/V = speaker - to_follow = V.source - var/link - if(to_follow in hosts) - link = FOLLOW_LINK(src, to_follow) - else - link = "" - // Create map text prior to modifying message for goonchat - if (client?.prefs.read_preference(/datum/preference/toggle/enable_runechat) && (client.prefs.read_preference(/datum/preference/toggle/enable_runechat_non_mobs) || ismob(speaker))) - create_chat_message(speaker, message_language, raw_message, spans) - // Recompose the message, because it's scrambled by default - message = compose_message(speaker, message_language, raw_message, radio_freq, spans, message_mods) - to_chat(src, "[link] [message]") - - -/mob/camera/disease/mind_initialize() - . = ..() - if(!mind.has_antag_datum(/datum/antagonist/disease)) - mind.add_antag_datum(/datum/antagonist/disease) - var/datum/atom_hud/medsensor = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED] - medsensor.show_to(src) - -/mob/camera/disease/proc/pick_name() - var/static/list/taken_names - if(!taken_names) - taken_names = list("Unknown" = TRUE) - for(var/T in (subtypesof(/datum/disease) - /datum/disease/advance)) - var/datum/disease/D = T - taken_names[initial(D.name)] = TRUE - var/set_name - while(!set_name) - var/input = sanitize_name(tgui_input_text(src, "Select a name for your disease", "Select Name", max_length = MAX_NAME_LEN)) - if(!input) - set_name = "Sentient Virus" - break - if(taken_names[input]) - to_chat(src, span_warning("You cannot use the name of such a well-known disease!")) - else - set_name = input - real_name = "[set_name] (Sentient Disease)" - name = "[set_name] (Sentient Disease)" - disease_template.AssignName(set_name) - var/datum/antagonist/disease/A = mind.has_antag_datum(/datum/antagonist/disease) - if(A) - A.disease_name = set_name - -/mob/camera/disease/proc/infect_random_patient_zero(del_on_fail = TRUE) - if(!freemove) - return FALSE - var/list/possible_hosts = list() - var/list/afk_possible_hosts = list() - for(var/i in GLOB.human_list) - var/mob/living/carbon/human/H = i - var/turf/T = get_turf(H) - if((H.stat != DEAD) && T && is_station_level(T.z) && H.CanContractDisease(disease_template)) - if(H.client && !H.client.is_afk()) - possible_hosts += H - else - afk_possible_hosts += H - - shuffle_inplace(possible_hosts) - shuffle_inplace(afk_possible_hosts) - possible_hosts += afk_possible_hosts //ideally we want a not-afk person, but we will settle for an afk one if there are no others (mostly for testing) - - while(possible_hosts.len) - var/mob/living/carbon/human/target = possible_hosts[1] - if(force_infect(target)) - return TRUE - possible_hosts.Cut(1, 2) - - if(del_on_fail) - to_chat(src, span_warning("No hosts were available for your disease to infect.")) - qdel(src) - return FALSE - -/mob/camera/disease/proc/force_infect(mob/living/L) - var/datum/disease/advance/sentient_disease/V = disease_template.Copy() - var/result = L.ForceContractDisease(V, FALSE, TRUE) - if(result && freemove) - end_freemove() - return result - -/mob/camera/disease/proc/end_freemove() - if(!freemove) - return - freemove = FALSE - move_on_shuttle = TRUE - adaptation_menu_action = new /datum/action/innate/disease_adapt() - adaptation_menu_action.Grant(src) - for(var/V in GLOB.disease_ability_singletons) - unpurchased_abilities[V] = TRUE - var/datum/disease_ability/A = V - if(A.start_with && A.CanBuy(src)) - A.Buy(src, TRUE, FALSE) - if(freemove_end_timerid) - deltimer(freemove_end_timerid) - set_sight(SEE_SELF) - -/mob/camera/disease/proc/add_infection(datum/disease/advance/sentient_disease/V) - disease_instances += V - hosts[V.affected_mob] = V - total_points = max(total_points, disease_instances.len) - points += 1 - - var/image/holder = V.affected_mob.hud_list[SENTIENT_DISEASE_HUD] - var/mutable_appearance/MA = new /mutable_appearance(holder) - MA.icon_state = "virus_infected" - MA.layer = BELOW_MOB_LAYER - MA.color = COLOR_GREEN_GRAY - MA.alpha = 200 - holder.appearance = MA - var/datum/atom_hud/my_hud = GLOB.huds[DATA_HUD_SENTIENT_DISEASE] - my_hud.add_atom_to_hud(V.affected_mob) - - to_chat(src, span_notice("A new host, [V.affected_mob.real_name], has been infected.")) - - if(!following_host) - set_following(V.affected_mob) - refresh_adaptation_menu() - -/mob/camera/disease/proc/remove_infection(datum/disease/advance/sentient_disease/V) - if(QDELETED(src)) - disease_instances -= V - hosts -= V.affected_mob - else - to_chat(src, span_notice("One of your hosts, [V.affected_mob.real_name], has been purged of your infection.")) - - var/datum/atom_hud/my_hud = GLOB.huds[DATA_HUD_SENTIENT_DISEASE] - my_hud.remove_atom_from_hud(V.affected_mob) - - if(following_host == V.affected_mob) - follow_next() - - disease_instances -= V - hosts -= V.affected_mob - - if(!disease_instances.len) - to_chat(src, span_userdanger("The last of your infection has disappeared.")) - set_following(null) - qdel(src) - refresh_adaptation_menu() - -/mob/camera/disease/proc/set_following(mob/living/L) - if(following_host) - UnregisterSignal(following_host, COMSIG_MOVABLE_MOVED) - RegisterSignal(L, COMSIG_MOVABLE_MOVED, PROC_REF(follow_mob)) - following_host = L - follow_mob() - -/mob/camera/disease/proc/follow_next(reverse = FALSE) - var/index = hosts.Find(following_host) - if(index) - if(reverse) - index = index == 1 ? hosts.len : index - 1 - else - index = index == hosts.len ? 1 : index + 1 - set_following(hosts[index]) - -/mob/camera/disease/proc/follow_mob(datum/source, newloc, dir) - SIGNAL_HANDLER - - var/turf/T = get_turf(following_host) - if(T) - forceMove(T) - -/mob/camera/disease/DblClickOn(atom/A, params) - if(hosts[A]) - set_following(A) - else - ..() - -/mob/camera/disease/ClickOn(atom/A, params) - if(freemove && ishuman(A)) - var/mob/living/carbon/human/H = A - if(tgui_alert(usr, "Select [H.name] as your initial host?", "Select Host", list("Yes", "No")) != "Yes") - return - if(!freemove) - return - if(QDELETED(H) || !force_infect(H)) - to_chat(src, span_warning("[H ? H.name : "Host"] cannot be infected.")) - else - ..() - -/mob/camera/disease/proc/adapt_cooldown() - to_chat(src, span_notice("You have altered your genetic structure. You will be unable to adapt again for [DisplayTimeText(adaptation_cooldown)].")) - next_adaptation_time = world.time + adaptation_cooldown - addtimer(CALLBACK(src, PROC_REF(notify_adapt_ready)), adaptation_cooldown) - -/mob/camera/disease/proc/notify_adapt_ready() - to_chat(src, span_notice("You are now ready to adapt again.")) - refresh_adaptation_menu() - -/mob/camera/disease/proc/refresh_adaptation_menu() - if(browser_open) - adaptation_menu() - -/mob/camera/disease/proc/adaptation_menu() - var/datum/disease/advance/sentient_disease/DT = disease_template - if(!DT) - return - var/list/dat = list() - - if(examining_ability) - dat += "Back
" - dat += "

[examining_ability.name]

" - dat += "[examining_ability.stat_block][examining_ability.long_desc][examining_ability.threshold_block]" - for(var/entry in examining_ability.threshold_block) - dat += "[entry]: [examining_ability.threshold_block[entry]]
" - else - dat += "

Disease Statistics


\ - Resistance: [DT.totalResistance()]
\ - Stealth: [DT.totalStealth()]
\ - Stage Speed: [DT.totalStageSpeed()]
\ - Transmissibility: [DT.totalTransmittable()]
\ - Cure: [DT.cure_text]" - dat += "

Adaptations

\ - Points: [points] / [total_points]\ - \ - " - for(var/V in GLOB.disease_ability_singletons) - var/datum/disease_ability/A = V - var/purchase_text - if(unpurchased_abilities[A]) - if(A.CanBuy(src)) - purchase_text = "Purchase" - else - purchase_text = "Purchase" - else - if(A.CanRefund(src)) - purchase_text = "Refund" - else - purchase_text = "Refund" - dat += "" - - dat += "
CostUnlockNameTypeDescription
[A.cost][purchase_text][A.required_total_points][A.name][A.category][A.short_desc]

Infect many hosts at once to gain adaptation points.

Infected Hosts

" - for(var/V in hosts) - var/mob/living/L = V - dat += "
[L.real_name]" - - browser.set_content(dat.Join()) - browser.open() - browser_open = TRUE - -/mob/camera/disease/Topic(href, list/href_list) - ..() - if(href_list["close"]) - browser_open = FALSE - if(usr != src) - return - if(href_list["follow_instance"]) - var/mob/living/L = locate(href_list["follow_instance"]) in hosts - set_following(L) - - if(href_list["buy_ability"]) - var/datum/disease_ability/A = locate(href_list["buy_ability"]) in unpurchased_abilities - if(!istype(A)) - return - if(A.CanBuy(src)) - A.Buy(src) - adaptation_menu() - - if(href_list["refund_ability"]) - var/datum/disease_ability/A = locate(href_list["refund_ability"]) in purchased_abilities - if(!istype(A)) - return - if(A.CanRefund(src)) - A.Refund(src) - adaptation_menu() - - if(href_list["examine_ability"]) - var/datum/disease_ability/A = locate(href_list["examine_ability"]) in GLOB.disease_ability_singletons - if(!istype(A)) - return - examining_ability = A - adaptation_menu() - - if(href_list["main_menu"]) - examining_ability = null - adaptation_menu() - - -/datum/action/innate/disease_adapt - name = "Adaptation Menu" - button_icon = 'icons/mob/actions/actions_minor_antag.dmi' - button_icon_state = "disease_menu" - -/datum/action/innate/disease_adapt/Activate() - var/mob/camera/disease/D = owner - D.adaptation_menu() - -#undef FREEMOVE_TIME diff --git a/code/modules/events/ghost_role/sentient_disease.dm b/code/modules/events/ghost_role/sentient_disease.dm deleted file mode 100644 index 156988d4b20d2f..00000000000000 --- a/code/modules/events/ghost_role/sentient_disease.dm +++ /dev/null @@ -1,25 +0,0 @@ -/datum/round_event_control/sentient_disease - name = "Spawn Sentient Disease" - typepath = /datum/round_event/ghost_role/sentient_disease - weight = 7 - max_occurrences = 1 - min_players = 25 - category = EVENT_CATEGORY_HEALTH - description = "Spawns a sentient disease, who wants to infect as many people as possible." - min_wizard_trigger_potency = 4 - max_wizard_trigger_potency = 7 - -/datum/round_event/ghost_role/sentient_disease - role_name = "sentient disease" - -/datum/round_event/ghost_role/sentient_disease/spawn_role() - var/mob/chosen_one = SSpolling.poll_ghost_candidates(check_jobban = ROLE_ALIEN, role = ROLE_ALIEN, alert_pic = /obj/structure/sign/warning/biohazard, role_name_text = role_name, amount_to_pick = 1) - if(isnull(chosen_one)) - return NOT_ENOUGH_PLAYERS - var/mob/camera/disease/virus = new /mob/camera/disease(SSmapping.get_station_center()) - virus.key = chosen_one.key - INVOKE_ASYNC(virus, TYPE_PROC_REF(/mob/camera/disease, pick_name)) - message_admins("[ADMIN_LOOKUPFLW(virus)] has been made into a sentient disease by an event.") - virus.log_message("was spawned as a sentient disease by an event.", LOG_GAME) - spawned_mobs += virus - return SUCCESSFUL_SPAWN diff --git a/code/modules/jobs/job_types/antagonists/sentient_disease.dm b/code/modules/jobs/job_types/antagonists/sentient_disease.dm deleted file mode 100644 index 4c91ae4ffa1010..00000000000000 --- a/code/modules/jobs/job_types/antagonists/sentient_disease.dm +++ /dev/null @@ -1,2 +0,0 @@ -/datum/job/sentient_disease - title = ROLE_SENTIENT_DISEASE diff --git a/code/modules/mob/living/carbon/damage_procs.dm b/code/modules/mob/living/carbon/damage_procs.dm index 30ff21ccc39894..aeba381703b101 100644 --- a/code/modules/mob/living/carbon/damage_procs.dm +++ b/code/modules/mob/living/carbon/damage_procs.dm @@ -128,20 +128,21 @@ return FALSE return adjustFireLoss(diff, updating_health, forced, required_bodytype) -/mob/living/carbon/adjustToxLoss(amount, updating_health = TRUE, forced = FALSE, required_biotype = ALL) - if(!can_adjust_tox_loss(amount, forced, required_biotype)) - return 0 - if(!forced && HAS_TRAIT(src, TRAIT_TOXINLOVER)) //damage becomes healing and healing becomes damage - amount = -amount - if(HAS_TRAIT(src, TRAIT_TOXIMMUNE)) //Prevents toxin damage, but not healing - amount = min(amount, 0) - if(amount > 0) - blood_volume = max(blood_volume - (5*amount), 0) - else - blood_volume = max(blood_volume - amount, 0) - else if(!forced && HAS_TRAIT(src, TRAIT_TOXIMMUNE)) //Prevents toxin damage, but not healing - amount = min(amount, 0) - return ..() +/mob/living/carbon/human/adjustToxLoss(amount, updating_health = TRUE, forced = FALSE, required_biotype = ALL) + . = ..() + if(. >= 0) // 0 = no damage, + values = healed damage + return . + + if(AT_TOXIN_VOMIT_THRESHOLD(src)) + apply_status_effect(/datum/status_effect/tox_vomit) + +/mob/living/carbon/human/setToxLoss(amount, updating_health, forced, required_biotype) + . = ..() + if(. >= 0) + return . + + if(AT_TOXIN_VOMIT_THRESHOLD(src)) + apply_status_effect(/datum/status_effect/tox_vomit) /mob/living/carbon/adjustStaminaLoss(amount, updating_stamina, forced, required_biotype = ALL) . = ..() diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index 84d1c45466873e..5ee91f88d1bcee 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -71,7 +71,7 @@ /mob/living/carbon/human, /mob/living/basic/slime, )) - var/lastpuke = 0 + var/account_id var/hardcore_survival_score = 0 diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index be355bddbea281..d8119c6a5279a5 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -270,19 +270,6 @@ return min(1, thermal_protection) -/mob/living/carbon/human/handle_random_events(seconds_per_tick, times_fired) - //Puke if toxloss is too high - if(stat) - return - if(getToxLoss() < 45 || nutrition <= 20) - return - - lastpuke += SPT_PROB(30, seconds_per_tick) - if(lastpuke >= 50) // about 25 second delay I guess // This is actually closer to 150 seconds - vomit(VOMIT_CATEGORY_DEFAULT, lost_nutrition = 20) - lastpuke = 0 - - /mob/living/carbon/human/has_smoke_protection() if(isclothing(wear_mask)) if(wear_mask.clothing_flags & BLOCK_GAS_SMOKE_EFFECT) diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm index e5f91b1b1b81aa..e5aa87a94228d0 100644 --- a/code/modules/mob/living/carbon/life.dm +++ b/code/modules/mob/living/carbon/life.dm @@ -317,11 +317,6 @@ // Clear moodlet if no miasma at all. clear_mood_event("smell") else - // Miasma sickness - if(prob(1 * miasma_pp)) - var/datum/disease/advance/miasma_disease = new /datum/disease/advance/random(max_symptoms = 2, max_level = 3) - miasma_disease.name = "Unknown" - ForceContractDisease(miasma_disease, make_copy = TRUE, del_on_fail = TRUE) // Miasma side-effects. if (HAS_TRAIT(src, TRAIT_ANOSMIA)) //We can't feel miasma without sense of smell return diff --git a/code/modules/mob/living/damage_procs.dm b/code/modules/mob/living/damage_procs.dm index 286a3b30ed8432..49f7a7d7701b67 100644 --- a/code/modules/mob/living/damage_procs.dm +++ b/code/modules/mob/living/damage_procs.dm @@ -359,14 +359,31 @@ /mob/living/proc/adjustToxLoss(amount, updating_health = TRUE, forced = FALSE, required_biotype = ALL) if(!can_adjust_tox_loss(amount, forced, required_biotype)) return 0 + + if(!forced && HAS_TRAIT(src, TRAIT_TOXINLOVER)) //damage becomes healing and healing becomes damage + amount = -amount + if(HAS_TRAIT(src, TRAIT_TOXIMMUNE)) //Prevents toxin damage, but not healing + amount = min(amount, 0) + if(blood_volume) + if(amount > 0) + blood_volume = max(blood_volume - (5 * amount), 0) + else + blood_volume = max(blood_volume - amount, 0) + + else if(!forced && HAS_TRAIT(src, TRAIT_TOXIMMUNE)) //Prevents toxin damage, but not healing + amount = min(amount, 0) + . = toxloss toxloss = clamp((toxloss + (amount * CONFIG_GET(number/damage_multiplier))), 0, maxHealth * 2) . -= toxloss + if(!.) // no change, no need to update return FALSE + if(updating_health) updatehealth() + /mob/living/proc/setToxLoss(amount, updating_health = TRUE, forced = FALSE, required_biotype = ALL) if(!forced && (status_flags & GODMODE)) return FALSE diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm index dd7e8a17c9bf2d..7c2af9a15724e9 100644 --- a/code/modules/mob/living/life.dm +++ b/code/modules/mob/living/life.dm @@ -53,10 +53,6 @@ if (QDELETED(src)) // diseases can qdel the mob via transformations return - if(stat != DEAD) - //Random events (vomiting etc) - handle_random_events(seconds_per_tick, times_fired) - //Handle temperature/pressure differences between body and environment var/datum/gas_mixture/environment = loc.return_air() if(environment) @@ -82,9 +78,6 @@ /mob/living/proc/handle_wounds(seconds_per_tick, times_fired) return -/mob/living/proc/handle_random_events(seconds_per_tick, times_fired) - return - // Base mob environment handler for body temperature /mob/living/proc/handle_environment(datum/gas_mixture/environment, seconds_per_tick, times_fired) var/loc_temp = get_temperature(environment) diff --git a/code/modules/surgery/organs/internal/lungs/_lungs.dm b/code/modules/surgery/organs/internal/lungs/_lungs.dm index a60cc243756178..6be62d7b2a20f5 100644 --- a/code/modules/surgery/organs/internal/lungs/_lungs.dm +++ b/code/modules/surgery/organs/internal/lungs/_lungs.dm @@ -462,14 +462,7 @@ /obj/item/organ/internal/lungs/proc/too_much_miasma(mob/living/carbon/breather, datum/gas_mixture/breath, miasma_pp, old_miasma_pp) // Inhale Miasma. Exhale nothing. breathe_gas_volume(breath, /datum/gas/miasma) - // Miasma sickness - if(prob(0.5 * miasma_pp)) - var/datum/disease/advance/miasma_disease = new /datum/disease/advance/random(max_symptoms = min(round(max(miasma_pp / 2, 1), 1), 6), max_level = min(round(max(miasma_pp, 1), 1), 8)) - // tl;dr the first argument chooses the smaller of miasma_pp/2 or 6(typical max virus symptoms), the second chooses the smaller of miasma_pp or 8(max virus symptom level) - // Each argument has a minimum of 1 and rounds to the nearest value. Feel free to change the pp scaling I couldn't decide on good numbers for it. - if(breather.CanContractDisease(miasma_disease)) - miasma_disease.name = "Unknown" - breather.AirborneContractDisease(miasma_disease, TRUE) + // Miasma side effects if (HAS_TRAIT(breather, TRAIT_ANOSMIA)) //Anosmia quirk holder cannot smell miasma, but can get diseases from it. return diff --git a/code/modules/unit_tests/mob_damage.dm b/code/modules/unit_tests/mob_damage.dm index c27bc31ffe0f27..64b12b8f477e85 100644 --- a/code/modules/unit_tests/mob_damage.dm +++ b/code/modules/unit_tests/mob_damage.dm @@ -580,3 +580,22 @@ if(!verify_damage(gusgus, 0, included_types = BRUTELOSS)) TEST_FAIL("heal_overall_damage did not apply its healing correctly on the mouse!") + +/// Tests that humans get the tox_vomit status effect when heavily poisoned +/datum/unit_test/human_tox_damage + +/datum/unit_test/human_tox_damage/Run() + // Spawn a dummy, give it a bunch of tox damage. It should get the status effect. + var/mob/living/carbon/human/dummy = allocate(/mob/living/carbon/human/consistent) + dummy.setToxLoss(75) + var/datum/status_effect/tox_effect = dummy.has_status_effect(/datum/status_effect/tox_vomit) + TEST_ASSERT_NOTNULL(tox_effect, "Dummy didn't get tox_vomit status effect despite at [dummy.getToxLoss()] toxin damage (Method: SET)!") + // Clear the toxin damage away, and force a status effect tick: It should delete itself + dummy.setToxLoss(0) + tox_effect.tick(initial(tox_effect.tick_interval)) + TEST_ASSERT(QDELETED(tox_effect), "Dummy still has tox_vomit status effect despite at [dummy.getToxLoss()] toxin damage (Method: SET)!") + // Test another method of gaining tox damage, use an entirely clean slate just to be sure + var/mob/living/carbon/human/dummy_two = allocate(/mob/living/carbon/human/consistent) + dummy_two.adjustToxLoss(75) + var/datum/status_effect/tox_effect_two = dummy_two.has_status_effect(/datum/status_effect/tox_vomit) + TEST_ASSERT_NOTNULL(tox_effect_two, "Dummy didn't get tox_vomit status effect at [dummy_two.getToxLoss()] toxin damage (METHOD: ADJUST)!") diff --git a/html/changelogs/AutoChangeLog-pr-83421.yml b/html/changelogs/AutoChangeLog-pr-83421.yml new file mode 100644 index 00000000000000..9a03244707dcd9 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-83421.yml @@ -0,0 +1,4 @@ +author: "Melbert" +delete-after: True +changes: + - refactor: "Refactored the way high toxins cause you to vomit." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-83432.yml b/html/changelogs/AutoChangeLog-pr-83432.yml new file mode 100644 index 00000000000000..53ebc367238745 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-83432.yml @@ -0,0 +1,4 @@ +author: "by INFRARED_BARON" +delete-after: True +changes: + - image: "Changes the sprites of bone and ash drake armor (suit + helmet mob/objs)" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-83453.yml b/html/changelogs/AutoChangeLog-pr-83453.yml new file mode 100644 index 00000000000000..cc036ce9d14982 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-83453.yml @@ -0,0 +1,4 @@ +author: "Time-Green" +delete-after: True +changes: + - rscdel: "Removes sentient disease from the game" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-83455.yml b/html/changelogs/AutoChangeLog-pr-83455.yml new file mode 100644 index 00000000000000..d7f9b7d0dd1b6c --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-83455.yml @@ -0,0 +1,4 @@ +author: "Time-Green" +delete-after: True +changes: + - rscdel: "Miasma and gibs no longer generates random diseases" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-83486.yml b/html/changelogs/AutoChangeLog-pr-83486.yml new file mode 100644 index 00000000000000..1ae1044efe1038 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-83486.yml @@ -0,0 +1,4 @@ +author: "necromanceranne" +delete-after: True +changes: + - bugfix: "Material floor tiles once again have their improved sprite." \ No newline at end of file diff --git a/icons/mob/clothing/head/helmet.dmi b/icons/mob/clothing/head/helmet.dmi index 523a306749d3d2..ad489609d983b3 100644 Binary files a/icons/mob/clothing/head/helmet.dmi and b/icons/mob/clothing/head/helmet.dmi differ diff --git a/icons/mob/clothing/suits/armor.dmi b/icons/mob/clothing/suits/armor.dmi index c96fb14268367b..744609ac7793df 100644 Binary files a/icons/mob/clothing/suits/armor.dmi and b/icons/mob/clothing/suits/armor.dmi differ diff --git a/icons/obj/clothing/head/helmet.dmi b/icons/obj/clothing/head/helmet.dmi index 3cf561103a0a70..47dd36c382ef98 100644 Binary files a/icons/obj/clothing/head/helmet.dmi and b/icons/obj/clothing/head/helmet.dmi differ diff --git a/icons/obj/clothing/suits/armor.dmi b/icons/obj/clothing/suits/armor.dmi index f68ebc31a47637..39317e13685359 100644 Binary files a/icons/obj/clothing/suits/armor.dmi and b/icons/obj/clothing/suits/armor.dmi differ diff --git a/icons/turf/floors.dmi b/icons/turf/floors.dmi index 29eb7d3eaeccc2..28ad938775d3c4 100644 Binary files a/icons/turf/floors.dmi and b/icons/turf/floors.dmi differ diff --git a/tgstation.dme b/tgstation.dme index 663beb369bbf2d..d35ffe575fabd9 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -1843,6 +1843,7 @@ #include "code\datums\status_effects\debuffs\strandling.dm" #include "code\datums\status_effects\debuffs\terrified.dm" #include "code\datums\status_effects\debuffs\tower_of_babel.dm" +#include "code\datums\status_effects\debuffs\tox_vomit.dm" #include "code\datums\status_effects\debuffs\slime\slime_food.dm" #include "code\datums\status_effects\debuffs\slime\slime_leech.dm" #include "code\datums\status_effects\debuffs\slime\slimed.dm" @@ -3050,10 +3051,6 @@ #include "code\modules\antagonists\cult\cult_turf_overlay.dm" #include "code\modules\antagonists\cult\rune_spawn_action.dm" #include "code\modules\antagonists\cult\runes.dm" -#include "code\modules\antagonists\disease\disease_abilities.dm" -#include "code\modules\antagonists\disease\disease_datum.dm" -#include "code\modules\antagonists\disease\disease_disease.dm" -#include "code\modules\antagonists\disease\disease_mob.dm" #include "code\modules\antagonists\ert\ert.dm" #include "code\modules\antagonists\fugitive\fugitive.dm" #include "code\modules\antagonists\fugitive\fugitive_equipment.dm" @@ -3981,7 +3978,6 @@ #include "code\modules\events\ghost_role\operative.dm" #include "code\modules\events\ghost_role\revenant_event.dm" #include "code\modules\events\ghost_role\sentience.dm" -#include "code\modules\events\ghost_role\sentient_disease.dm" #include "code\modules\events\ghost_role\slaughter_event.dm" #include "code\modules\events\ghost_role\space_dragon.dm" #include "code\modules\events\ghost_role\space_ninja.dm" @@ -4288,7 +4284,6 @@ #include "code\modules\jobs\job_types\antagonists\nuclear_operative.dm" #include "code\modules\jobs\job_types\antagonists\paradox_clone.dm" #include "code\modules\jobs\job_types\antagonists\revenant.dm" -#include "code\modules\jobs\job_types\antagonists\sentient_disease.dm" #include "code\modules\jobs\job_types\antagonists\slaughter_demon.dm" #include "code\modules\jobs\job_types\antagonists\space_dragon.dm" #include "code\modules\jobs\job_types\antagonists\space_ninja.dm"