[MIRROR] Disease outbreak fixes/admin options [MDB IGNORE] (#22877)

* Disease outbreak fixes/admin options (#77272)

## About The Pull Request

- Fixes event diseases sometimes remaining invisible even after the
event announcement
- Fixes 'random' disease names favouring certain severities, causing
frequent repetition of selected name
- Adds a bitfield for spread_flags so transmissibility can easily be
modified in game by admins
- Adds option to select spread method when using admin event panel
- Hitting the X or cancel will cancel the event on all admin input
questions

## Why It's Good For The Game

- Being infected with an event disease that remains invisible is a pain
for the player, medbay, and eventually staff
- More admin options when creating an outbreak is good
- Being able to easily edit the transmissibility once the disease is
created is good
- Disease outbreak should fail with ADMIN_CANCEL_EVENT if any explicit
inputs are invalid

## Changelog

🆑 LT3
fix: Fixed disease outbreak viruses sometimes getting stuck invisible
from medHUDs
admin: Added more admin features to create/manange disease outbreaks
admin: Pressing 'cancel' on disease outbreak setup dialogs will actually
cancel the event instead of running it with default settings
/🆑

---------

Co-authored-by: Time-Green <7501474+Time-Green@ users.noreply.github.com>

* Disease outbreak fixes/admin options

---------

Co-authored-by: lessthanthree <83487515+lessthnthree@users.noreply.github.com>
Co-authored-by: Time-Green <7501474+Time-Green@ users.noreply.github.com>
This commit is contained in:
SkyratBot
2023-08-04 14:36:45 -07:00
committed by GitHub
co-authored by Time-Green lessthanthree
parent 84fac53f06
commit 9da281aef7
4 changed files with 110 additions and 54 deletions
+10
View File
@@ -20,6 +20,16 @@
#define DISEASE_SPREAD_CONTACT_SKIN (1<<4)
#define DISEASE_SPREAD_AIRBORNE (1<<5)
//Bitfield for Spread Flags
DEFINE_BITFIELD(spread_flags, list(
"SPREAD_SPECIAL" = DISEASE_SPREAD_SPECIAL,
"SPREAD_NON_CONTAGIOUS" = DISEASE_SPREAD_NON_CONTAGIOUS,
"SPREAD_BLOOD" = DISEASE_SPREAD_BLOOD,
"SPREAD_FLUIDS" = DISEASE_SPREAD_CONTACT_FLUIDS,
"SPREAD_SKIN_CONTACT" = DISEASE_SPREAD_CONTACT_SKIN,
"SPREAD_AIRBORNE" = DISEASE_SPREAD_AIRBORNE,
))
//Severity Defines
/// Diseases that buff, heal, or at least do nothing at all
#define DISEASE_SEVERITY_POSITIVE "Positive"
+5 -3
View File
@@ -1,6 +1,6 @@
/datum/disease
//Flags
var/visibility_flags = 0
var/visibility_flags = NONE
var/disease_flags = CURABLE|CAN_CARRY|CAN_RESIST
var/spread_flags = DISEASE_SPREAD_AIRBORNE | DISEASE_SPREAD_CONTACT_FLUIDS | DISEASE_SPREAD_CONTACT_SKIN
@@ -17,6 +17,8 @@
var/max_stages = 0
/// The probability of this infection advancing a stage every second the cure is not present.
var/stage_prob = 2
/// How long this infection incubates (non-visible) before revealing itself
var/incubation_time = 0
//Other
var/list/viable_mobtypes = list() //typepaths of viable mobs
@@ -62,7 +64,7 @@
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.
///Proc to process the disease and decide on whether to advance, cure or make the symptoms 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%
@@ -152,7 +154,7 @@
/datum/disease/proc/Copy()
//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",
"cure_text", "max_stages", "stage_prob", "incubation_time", "viable_mobtypes", "cures", "infectivity", "cure_chance",
"required_organ", "bypasses_immunity", "spreading_modifier", "severity", "needs_all_cures", "strain_data",
"infectable_biotypes", "process_dead")
+14 -7
View File
@@ -534,15 +534,22 @@
/datum/disease/advance/proc/totalTransmittable()
return properties["transmittable"]
/**
* If the disease has an incubation time (such as event diseases) start the timer
*/
/datum/disease/advance/after_add()
. = ..()
if(incubation_time < world.time)
make_visible()
return
addtimer(CALLBACK(src, PROC_REF(make_visible)), incubation_time - world.time)
/**
* Make virus visible to heath scanners
*/
/datum/disease/advance/proc/make_visible()
visibility_flags &= ~HIDDEN_SCANNER
for(var/datum/disease/advance/virus in SSdisease.active_diseases)
if(!virus.id)
stack_trace("Advanced virus ID is empty or null!")
return
if(virus.id == id)
virus.visibility_flags &= ~HIDDEN_SCANNER
affected_mob.med_hud_set_status()
+81 -44
View File
@@ -14,10 +14,14 @@
#define ADV_RNG_LOW 40
/// Percentile for mid severity advanced virus
#define ADV_RNG_MID 85
/// Percentile for low transmissibility advanced virus
#define ADV_SPREAD_LOW 15
/// Percentile for mid transmissibility advanced virus
#define ADV_SPREAD_MID 85
/// Percentile for high vs. low transmissibility
#define ADV_SPREAD_THRESHOLD 85
/// Admin custom low spread
#define ADV_SPREAD_FORCED_LOW 0
/// Admin custom med spread
#define ADV_SPREAD_FORCED_MID 70
/// Admin custom high spread
#define ADV_SPREAD_FORCED_HIGH 90
/datum/round_event_control/disease_outbreak
name = "Disease Outbreak: Classic"
@@ -149,8 +153,9 @@
max_wizard_trigger_potency = 6
admin_setup = list(
/datum/event_admin_setup/minimum_candidate_requirement/disease_outbreak,
/datum/event_admin_setup/listed_options/disease_outbreak_advanced,
/datum/event_admin_setup/input_number/disease_outbreak_advanced
/datum/event_admin_setup/listed_options/disease_outbreak_advanced/severity,
/datum/event_admin_setup/input_number/disease_outbreak_advanced,
/datum/event_admin_setup/listed_options/disease_outbreak_advanced/transmissibility
)
/**
@@ -159,14 +164,14 @@
* If the admin wishes, give them the opportunity to select the severity and number of symptoms.
*/
/datum/event_admin_setup/listed_options/disease_outbreak_advanced
/datum/event_admin_setup/listed_options/disease_outbreak_advanced/severity
input_text = "Pick a severity!"
normal_run_option = "Random Severity"
normal_run_option = "Random"
/datum/event_admin_setup/listed_options/disease_outbreak_advanced/get_list()
/datum/event_admin_setup/listed_options/disease_outbreak_advanced/severity/get_list()
return list("Medium", "Harmful", "Dangerous")
/datum/event_admin_setup/listed_options/disease_outbreak_advanced/apply_to_event(datum/round_event/disease_outbreak/advanced/event)
/datum/event_admin_setup/listed_options/disease_outbreak_advanced/severity/apply_to_event(datum/round_event/disease_outbreak/advanced/event)
switch(chosen)
if("Medium")
event.requested_severity = ADV_DISEASE_MEDIUM
@@ -174,8 +179,30 @@
event.requested_severity = ADV_DISEASE_HARMFUL
if("Dangerous")
event.requested_severity = ADV_DISEASE_DANGEROUS
else
if("Random")
event.requested_severity = null
else
return ADMIN_CANCEL_EVENT
/datum/event_admin_setup/listed_options/disease_outbreak_advanced/transmissibility
input_text = "Pick a transmissibility!"
normal_run_option = "Random"
/datum/event_admin_setup/listed_options/disease_outbreak_advanced/transmissibility/get_list()
return list("Blood/Fluids", "Skin Contact", "Airborne")
/datum/event_admin_setup/listed_options/disease_outbreak_advanced/transmissibility/apply_to_event(datum/round_event/disease_outbreak/advanced/event)
switch(chosen)
if("Blood/Fluids")
event.requested_transmissibility = ADV_SPREAD_FORCED_LOW
if("Skin Contact")
event.requested_transmissibility = ADV_SPREAD_FORCED_MID
if("Airborne")
event.requested_transmissibility = ADV_SPREAD_FORCED_HIGH
if("Random")
event.requested_transmissibility = null
else
return ADMIN_CANCEL_EVENT
/datum/event_admin_setup/input_number/disease_outbreak_advanced
input_text = "How many symptoms do you want your virus to have?"
@@ -184,23 +211,24 @@
min_value = 1
/datum/event_admin_setup/input_number/disease_outbreak_advanced/prompt_admins()
var/customize_number_of_symptoms = tgui_alert(usr, "Select number of symptoms?", event_control.name, list("Custom", "Random", "Cancel"))
var/customize_number_of_symptoms = tgui_alert(usr, "Select number of symptoms?", event_control.name, list("Default", "Custom"))
switch(customize_number_of_symptoms)
if("Custom")
return ..()
if("Random")
if("Default")
chosen_value = null
else
return ADMIN_CANCEL_EVENT
/datum/event_admin_setup/input_number/disease_outbreak_advanced/apply_to_event(datum/round_event/disease_outbreak/advanced/event)
event.max_symptoms = chosen_value
/datum/round_event/disease_outbreak/advanced
///Number of symptoms for our virus
var/requested_severity
//Maximum symptoms for our virus
///Transmissibility of our virus
var/requested_transmissibility
///Maximum symptoms for our virus
var/max_symptoms
/**
@@ -214,10 +242,10 @@
afflicted += disease_event.disease_candidates
disease_event.disease_candidates.Cut()
if(!max_symptoms)
if(isnull(max_symptoms))
max_symptoms = rand(ADV_MIN_SYMPTOMS, ADV_MAX_SYMPTOMS)
if(!requested_severity)
if(isnull(requested_severity))
var/rng_severity = rand(1, 100)
if(rng_severity < ADV_RNG_LOW)
requested_severity = ADV_DISEASE_MEDIUM
@@ -228,7 +256,7 @@
else
requested_severity = ADV_DISEASE_DANGEROUS
var/datum/disease/advance/advanced_disease = new /datum/disease/advance/random/event(max_symptoms, requested_severity)
var/datum/disease/advance/advanced_disease = new /datum/disease/advance/random/event(max_symptoms, requested_severity, requested_transmissibility)
var/list/name_symptoms = list()
for(var/datum/symptom/new_symptom as anything in advanced_disease.symptoms)
@@ -262,7 +290,7 @@
* Uses the parameters to create a list of symptoms, picking from various severities
* Viral Evolution and Eternal Youth are special modifiers, so we roll separately.
*/
/datum/disease/advance/random/event/New(max_symptoms, requested_severity)
/datum/disease/advance/random/event/New(max_symptoms, requested_severity, requested_transmissibility)
var/list/datum/symptom/possible_symptoms = list(
/datum/symptom/beard,
/datum/symptom/chills,
@@ -319,11 +347,38 @@
symptoms += new_symptom
//Applies the illness name based on the most severe symptom.
if(new_symptom.severity > current_severity)
name = "[new_symptom.illness]"
current_severity = new_symptom.severity
visibility_flags |= HIDDEN_SCANNER
var/transmissibility = requested_transmissibility
if(isnull(transmissibility))
transmissibility = rand(1,100)
if(requested_transmissibility == ADV_SPREAD_FORCED_LOW) // Admin forced
set_spread(DISEASE_SPREAD_CONTACT_FLUIDS)
else if(requested_transmissibility == ADV_SPREAD_FORCED_HIGH) // Admin forced
set_spread(DISEASE_SPREAD_AIRBORNE)
//If severe enough, alert immediately on scanners, limit transmissibility
else if(current_severity >= ADV_DISEASE_DANGEROUS)
visibility_flags &= ~HIDDEN_SCANNER
set_spread(DISEASE_SPREAD_CONTACT_SKIN)
else if(transmissibility < ADV_SPREAD_THRESHOLD)
set_spread(DISEASE_SPREAD_CONTACT_SKIN)
else
visibility_flags &= ~HIDDEN_SCANNER
set_spread(DISEASE_SPREAD_AIRBORNE)
//Illness name from one of the symptoms
var/datum/symptom/picked_name = pick(symptoms)
name = picked_name.illness
//Modifiers to keep the disease base stats above 0 (unless RNG gets a really bad roll.)
//Eternal Youth for +4 to resistance and stage speed.
//Viral modifiers to slow down/resist or go fast and loud.
@@ -353,37 +408,17 @@
stack_trace("Advanced virus properties were empty or null!")
return
addtimer(CALLBACK(src, PROC_REF(make_visible)), ((ADV_ANNOUNCE_DELAY * 2) - 10) SECONDS)
incubation_time = round(world.time + (((ADV_ANNOUNCE_DELAY * 2) - 10) SECONDS))
properties["transmittable"] = rand(4,7)
spreading_modifier = max(CEILING(0.4 * properties["transmittable"], 1), 1)
cure_chance = clamp(7.5 - (0.5 * properties["resistance"]), 5, 10) // Can be between 5 and 10
stage_prob = max(0.4 * properties["stage_rate"], 1)
set_severity(properties["severity"])
visibility_flags |= HIDDEN_SCANNER
//If we have an advanced (high stage) disease, add it to the name.
if(properties["stage_rate"] >= 7)
name = "Advanced [name]"
//If severe enough, alert immediately on scanners
if(severity == "Dangerous" || severity == "BIOHAZARD")
visibility_flags &= ~HIDDEN_SCANNER
set_spread(DISEASE_SPREAD_CONTACT_SKIN)
else
var/transmissibility = rand(1, 100)
if(transmissibility < ADV_SPREAD_LOW)
set_spread(DISEASE_SPREAD_CONTACT_FLUIDS)
else if(transmissibility < ADV_SPREAD_MID)
set_spread(DISEASE_SPREAD_CONTACT_SKIN)
else
set_spread(DISEASE_SPREAD_AIRBORNE)
visibility_flags &= ~HIDDEN_SCANNER
generate_cure(properties)
/**
@@ -428,5 +463,7 @@
#undef ADV_DISEASE_DANGEROUS
#undef ADV_RNG_LOW
#undef ADV_RNG_MID
#undef ADV_SPREAD_LOW
#undef ADV_SPREAD_MID
#undef ADV_SPREAD_THRESHOLD
#undef ADV_SPREAD_FORCED_LOW
#undef ADV_SPREAD_FORCED_MID
#undef ADV_SPREAD_FORCED_HIGH