mirror of
https://github.com/fulpstation/fulpstation.git
synced 2025-12-10 01:57:01 +00:00
* Travis for 510 * Remove json, list2text, text2list, bygex * Change blind and click catcher to a low plane
428 lines
11 KiB
Plaintext
428 lines
11 KiB
Plaintext
/*
|
|
|
|
Advance Disease is a system for Virologist to Engineer their own disease with symptoms that have effects and properties
|
|
which add onto the overall disease.
|
|
|
|
If you need help with creating new symptoms or expanding the advance disease, ask for Giacom on #coderbus.
|
|
|
|
*/
|
|
|
|
var/list/archive_diseases = list()
|
|
|
|
// The order goes from easy to cure to hard to cure.
|
|
var/list/advance_cures = list(
|
|
"sodiumchloride", "sugar", "orangejuice",
|
|
"spaceacillin", "salglu_solution", "ethanol",
|
|
"leporazine", "synaptizine", "lipolicide",
|
|
"silver", "gold"
|
|
)
|
|
|
|
/*
|
|
|
|
PROPERTIES
|
|
|
|
*/
|
|
|
|
/datum/disease/advance
|
|
|
|
name = "Unknown" // We will always let our Virologist name our disease.
|
|
desc = "An engineered disease which can contain a multitude of symptoms."
|
|
form = "Advance Disease" // Will let med-scanners know that this disease was engineered.
|
|
agent = "advance microbes"
|
|
max_stages = 5
|
|
spread_text = "Unknown"
|
|
viable_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
|
|
|
|
// NEW VARS
|
|
|
|
var/list/symptoms = list() // The symptoms of the disease.
|
|
var/id = ""
|
|
var/processing = 0
|
|
|
|
/*
|
|
|
|
OLD PROCS
|
|
|
|
*/
|
|
|
|
/datum/disease/advance/New(var/process = 1, var/datum/disease/advance/D)
|
|
|
|
// Setup our dictionary if it hasn't already.
|
|
if(!dictionary_symptoms.len)
|
|
for(var/symp in list_symptoms)
|
|
var/datum/symptom/S = new symp
|
|
dictionary_symptoms[S.id] = symp
|
|
|
|
if(!istype(D))
|
|
D = null
|
|
// Generate symptoms if we weren't given any.
|
|
|
|
if(!symptoms || !symptoms.len)
|
|
|
|
if(!D || !D.symptoms || !D.symptoms.len)
|
|
symptoms = GenerateSymptoms(0, 2)
|
|
else
|
|
for(var/datum/symptom/S in D.symptoms)
|
|
symptoms += new S.type
|
|
|
|
Refresh()
|
|
..(process, D)
|
|
return
|
|
|
|
/datum/disease/advance/Destroy()
|
|
if(processing)
|
|
for(var/datum/symptom/S in symptoms)
|
|
S.End(src)
|
|
return ..()
|
|
|
|
// Randomly pick a symptom to activate.
|
|
/datum/disease/advance/stage_act()
|
|
..()
|
|
if(symptoms && symptoms.len)
|
|
|
|
if(!processing)
|
|
processing = 1
|
|
for(var/datum/symptom/S in symptoms)
|
|
S.Start(src)
|
|
|
|
for(var/datum/symptom/S in symptoms)
|
|
S.Activate(src)
|
|
else
|
|
CRASH("We do not have any symptoms during stage_act()!")
|
|
|
|
// Compares type then ID.
|
|
/datum/disease/advance/IsSame(datum/disease/advance/D)
|
|
|
|
if(!(istype(D, /datum/disease/advance)))
|
|
return 0
|
|
|
|
if(src.GetDiseaseID() != D.GetDiseaseID())
|
|
return 0
|
|
return 1
|
|
|
|
// To add special resistances.
|
|
/datum/disease/advance/cure(resistance=1)
|
|
if(affected_mob)
|
|
var/id = "[GetDiseaseID()]"
|
|
if(resistance && !(id in affected_mob.resistances))
|
|
affected_mob.resistances[id] = id
|
|
remove_virus()
|
|
qdel(src) //delete the datum to stop it processing
|
|
|
|
// Returns the advance disease with a different reference memory.
|
|
/datum/disease/advance/Copy(process = 0)
|
|
return new /datum/disease/advance(process, src, 1)
|
|
|
|
/*
|
|
|
|
NEW PROCS
|
|
|
|
*/
|
|
|
|
// Mix the symptoms of two diseases (the src and the argument)
|
|
/datum/disease/advance/proc/Mix(datum/disease/advance/D)
|
|
if(!(src.IsSame(D)))
|
|
var/list/possible_symptoms = shuffle(D.symptoms)
|
|
for(var/datum/symptom/S in possible_symptoms)
|
|
AddSymptom(new S.type)
|
|
|
|
/datum/disease/advance/proc/HasSymptom(datum/symptom/S)
|
|
for(var/datum/symptom/symp in symptoms)
|
|
if(symp.id == S.id)
|
|
return 1
|
|
return 0
|
|
|
|
// Will generate new unique symptoms, use this if there are none. Returns a list of symptoms that were generated.
|
|
/datum/disease/advance/proc/GenerateSymptoms(level_min, level_max, amount_get = 0)
|
|
|
|
var/list/generated = list() // Symptoms we generated.
|
|
|
|
// Generate symptoms. By default, we only choose non-deadly symptoms.
|
|
var/list/possible_symptoms = list()
|
|
for(var/symp in list_symptoms)
|
|
var/datum/symptom/S = new symp
|
|
if(S.level >= level_min && S.level <= level_max)
|
|
if(!HasSymptom(S))
|
|
possible_symptoms += S
|
|
|
|
if(!possible_symptoms.len)
|
|
return generated
|
|
|
|
// Random chance to get more than one symptom
|
|
var/number_of = amount_get
|
|
if(!amount_get)
|
|
number_of = 1
|
|
while(prob(20))
|
|
number_of += 1
|
|
|
|
for(var/i = 1; number_of >= i && possible_symptoms.len; i++)
|
|
generated += pick_n_take(possible_symptoms)
|
|
|
|
return generated
|
|
|
|
/datum/disease/advance/proc/Refresh(new_name = 0)
|
|
//world << "[src.name] \ref[src] - REFRESH!"
|
|
var/list/properties = GenerateProperties()
|
|
AssignProperties(properties)
|
|
id = null
|
|
|
|
if(!archive_diseases[GetDiseaseID()])
|
|
if(new_name)
|
|
AssignName()
|
|
archive_diseases[GetDiseaseID()] = src // So we don't infinite loop
|
|
archive_diseases[GetDiseaseID()] = new /datum/disease/advance(0, src, 1)
|
|
|
|
var/datum/disease/advance/A = archive_diseases[GetDiseaseID()]
|
|
AssignName(A.name)
|
|
|
|
//Generate disease properties based on the effects. Returns an associated list.
|
|
/datum/disease/advance/proc/GenerateProperties()
|
|
|
|
if(!symptoms || !symptoms.len)
|
|
CRASH("We did not have any symptoms before generating properties.")
|
|
return
|
|
|
|
var/list/properties = list("resistance" = 1, "stealth" = 1, "stage_rate" = 1, "transmittable" = 1, "severity" = 0)
|
|
|
|
for(var/datum/symptom/S in symptoms)
|
|
|
|
properties["resistance"] += S.resistance
|
|
properties["stealth"] += S.stealth
|
|
properties["stage_rate"] += S.stage_speed
|
|
properties["transmittable"] += S.transmittable
|
|
properties["severity"] = max(properties["severity"], S.severity) // severity is based on the highest severity symptom
|
|
|
|
return properties
|
|
|
|
// Assign the properties that are in the list.
|
|
/datum/disease/advance/proc/AssignProperties(list/properties = list())
|
|
|
|
if(properties && properties.len)
|
|
switch(properties["stealth"])
|
|
if(2 to 3)
|
|
visibility_flags = HIDDEN_SCANNER
|
|
if(3 to INFINITY)
|
|
visibility_flags = HIDDEN_SCANNER|HIDDEN_PANDEMIC
|
|
|
|
// The more symptoms we have, the less transmittable it is but some symptoms can make up for it.
|
|
SetSpread(Clamp(2 ** (properties["transmittable"] - symptoms.len), BLOOD, AIRBORNE))
|
|
permeability_mod = max(Ceiling(0.4 * properties["transmittable"]), 1)
|
|
cure_chance = 15 - Clamp(properties["resistance"], -5, 5) // can be between 10 and 20
|
|
stage_prob = max(properties["stage_rate"], 2)
|
|
SetSeverity(properties["severity"])
|
|
GenerateCure(properties)
|
|
else
|
|
CRASH("Our properties were empty or null!")
|
|
|
|
|
|
// Assign the spread type and give it the correct description.
|
|
/datum/disease/advance/proc/SetSpread(spread_id)
|
|
switch(spread_id)
|
|
if(NON_CONTAGIOUS)
|
|
spread_text = "None"
|
|
if(SPECIAL)
|
|
spread_text = "None"
|
|
if(CONTACT_GENERAL, CONTACT_HANDS, CONTACT_FEET)
|
|
spread_text = "On contact"
|
|
if(AIRBORNE)
|
|
spread_text = "Airborne"
|
|
if(BLOOD)
|
|
spread_text = "Blood"
|
|
|
|
spread_flags = spread_id
|
|
|
|
/datum/disease/advance/proc/SetSeverity(level_sev)
|
|
|
|
switch(level_sev)
|
|
|
|
if(-INFINITY to 0)
|
|
severity = NONTHREAT
|
|
if(1)
|
|
severity = MINOR
|
|
if(2)
|
|
severity = MEDIUM
|
|
if(3)
|
|
severity = HARMFUL
|
|
if(4)
|
|
severity = DANGEROUS
|
|
if(5 to INFINITY)
|
|
severity = BIOHAZARD
|
|
else
|
|
severity = "Unknown"
|
|
|
|
|
|
// Will generate a random cure, the less resistance the symptoms have, the harder the cure.
|
|
/datum/disease/advance/proc/GenerateCure(list/properties = list())
|
|
if(properties && properties.len)
|
|
var/res = Clamp(properties["resistance"] - (symptoms.len / 2), 1, advance_cures.len)
|
|
//world << "Res = [res]"
|
|
cures = list(advance_cures[res])
|
|
|
|
// Get the cure name from the cure_id
|
|
var/datum/reagent/D = chemical_reagents_list[cures[1]]
|
|
cure_text = D.name
|
|
|
|
|
|
return
|
|
|
|
// Randomly generate a symptom, has a chance to lose or gain a symptom.
|
|
/datum/disease/advance/proc/Evolve(min_level, max_level)
|
|
var/s = safepick(GenerateSymptoms(min_level, max_level, 1))
|
|
if(s)
|
|
AddSymptom(s)
|
|
Refresh(1)
|
|
return
|
|
|
|
// Randomly remove a symptom.
|
|
/datum/disease/advance/proc/Devolve()
|
|
if(symptoms.len > 1)
|
|
var/s = safepick(symptoms)
|
|
if(s)
|
|
RemoveSymptom(s)
|
|
Refresh(1)
|
|
return
|
|
|
|
// Name the disease.
|
|
/datum/disease/advance/proc/AssignName(name = "Unknown")
|
|
src.name = name
|
|
return
|
|
|
|
// Return a unique ID of the disease.
|
|
/datum/disease/advance/GetDiseaseID()
|
|
if(!id)
|
|
var/list/L = list()
|
|
for(var/datum/symptom/S in symptoms)
|
|
L += S.id
|
|
L = sortList(L) // Sort the list so it doesn't matter which order the symptoms are in.
|
|
var/result = jointext(L, ":")
|
|
id = result
|
|
return id
|
|
|
|
|
|
// Add a symptom, if it is over the limit (with a small chance to be able to go over)
|
|
// we take a random symptom away and add the new one.
|
|
/datum/disease/advance/proc/AddSymptom(datum/symptom/S)
|
|
|
|
if(HasSymptom(S))
|
|
return
|
|
|
|
if(symptoms.len < 5 + rand(-1, 1))
|
|
symptoms += S
|
|
else
|
|
RemoveSymptom(pick(symptoms))
|
|
symptoms += S
|
|
return
|
|
|
|
// Simply removes the symptom.
|
|
/datum/disease/advance/proc/RemoveSymptom(datum/symptom/S)
|
|
symptoms -= S
|
|
return
|
|
|
|
/*
|
|
|
|
Static Procs
|
|
|
|
*/
|
|
|
|
// Mix a list of advance diseases and return the mixed result.
|
|
/proc/Advance_Mix(var/list/D_list)
|
|
|
|
//world << "Mixing!!!!"
|
|
|
|
var/list/diseases = list()
|
|
|
|
for(var/datum/disease/advance/A in D_list)
|
|
diseases += A.Copy()
|
|
|
|
if(!diseases.len)
|
|
return null
|
|
if(diseases.len <= 1)
|
|
return pick(diseases) // Just return the only entry.
|
|
|
|
var/i = 0
|
|
// Mix our diseases until we are left with only one result.
|
|
while(i < 20 && diseases.len > 1)
|
|
|
|
i++
|
|
|
|
var/datum/disease/advance/D1 = pick(diseases)
|
|
diseases -= D1
|
|
|
|
var/datum/disease/advance/D2 = pick(diseases)
|
|
D2.Mix(D1)
|
|
|
|
// Should be only 1 entry left, but if not let's only return a single entry
|
|
//world << "END MIXING!!!!!"
|
|
var/datum/disease/advance/to_return = pick(diseases)
|
|
to_return.Refresh(1)
|
|
return to_return
|
|
|
|
/proc/SetViruses(datum/reagent/R, list/data)
|
|
if(data)
|
|
var/list/preserve = list()
|
|
if(istype(data) && data["viruses"])
|
|
for(var/datum/disease/A in data["viruses"])
|
|
preserve += A.Copy()
|
|
R.data = data.Copy()
|
|
if(preserve.len)
|
|
R.data["viruses"] = preserve
|
|
|
|
/proc/AdminCreateVirus(client/user)
|
|
|
|
if(!user)
|
|
return
|
|
|
|
var/i = 5
|
|
|
|
var/datum/disease/advance/D = new(0, null)
|
|
D.symptoms = list()
|
|
|
|
var/list/symptoms = list()
|
|
symptoms += "Done"
|
|
symptoms += list_symptoms.Copy()
|
|
do
|
|
if(user)
|
|
var/symptom = input(user, "Choose a symptom to add ([i] remaining)", "Choose a Symptom") in symptoms
|
|
if(isnull(symptom))
|
|
return
|
|
else if(istext(symptom))
|
|
i = 0
|
|
else if(ispath(symptom))
|
|
var/datum/symptom/S = new symptom
|
|
if(!D.HasSymptom(S))
|
|
D.symptoms += S
|
|
i -= 1
|
|
while(i > 0)
|
|
|
|
if(D.symptoms.len > 0)
|
|
|
|
var/new_name = stripped_input(user, "Name your new disease.", "New Name")
|
|
if(!new_name)
|
|
return
|
|
D.AssignName(new_name)
|
|
D.Refresh()
|
|
|
|
for(var/datum/disease/advance/AD in SSdisease.processing)
|
|
AD.Refresh()
|
|
|
|
for(var/mob/living/carbon/human/H in shuffle(living_mob_list))
|
|
if(H.z != 1)
|
|
continue
|
|
if(!H.HasDisease(D))
|
|
H.ForceContractDisease(D)
|
|
break
|
|
|
|
var/list/name_symptoms = list()
|
|
for(var/datum/symptom/S in D.symptoms)
|
|
name_symptoms += S.name
|
|
message_admins("[key_name_admin(user)] has triggered a custom virus outbreak of [D.name]! It has these symptoms: [english_list(name_symptoms)]")
|
|
|
|
/*
|
|
/mob/verb/test()
|
|
|
|
for(var/datum/disease/D in SSdisease.processing)
|
|
src << "<a href='?_src_=vars;Vars=\ref[D]'>[D.name] - [D.holder]</a>"
|
|
*/
|
|
|
|
#undef RANDOM_STARTING_LEVEL
|