[MIRROR] Disease antagonist (#5815)

* Disease antagonist

* Update mobs.dm

* can I go to sleep yet
This commit is contained in:
CitadelStationBot
2018-03-05 15:20:59 -06:00
committed by Poojawa
parent 766b85908e
commit a2e6253f00
85 changed files with 1483 additions and 505 deletions
@@ -194,15 +194,12 @@
to_chat(owner, "<span class='warning'>You feel sick.</span>")
var/datum/disease/advance/A = random_virus(pick(2,6),6)
A.carrier = TRUE
owner.viruses += A
A.affected_mob = owner
owner.med_hud_set_status()
owner.ForceContractDisease(A, FALSE, TRUE)
/obj/item/organ/heart/gland/viral/proc/random_virus(max_symptoms, max_level)
if(max_symptoms > SYMPTOM_LIMIT)
max_symptoms = SYMPTOM_LIMIT
var/datum/disease/advance/A = new(FALSE, null)
A.symptoms = list()
if(max_symptoms > VIRUS_SYMPTOM_LIMIT)
max_symptoms = VIRUS_SYMPTOM_LIMIT
var/datum/disease/advance/A = new /datum/disease/advance()
var/list/datum/symptom/possible_symptoms = list()
for(var/symptom in subtypesof(/datum/symptom))
var/datum/symptom/S = symptom
@@ -20,6 +20,7 @@ GLOBAL_LIST_EMPTY(blob_nodes)
pass_flags = PASSBLOB
faction = list(ROLE_BLOB)
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
call_life = TRUE
var/obj/structure/blob/core/blob_core = null // The blob overmind's core
var/blob_points = 0
var/max_blob_points = 100
@@ -67,7 +68,7 @@ GLOBAL_LIST_EMPTY(blob_nodes)
if(!T)
CRASH("No blobspawnpoints and blob spawned in nullspace.")
forceMove(T)
/mob/camera/blob/proc/is_valid_turf(turf/T)
var/area/A = get_area(T)
if((A && !A.blob_allowed) || !T || !is_station_level(T.z) || isspaceturf(T))
@@ -217,9 +218,6 @@ GLOBAL_LIST_EMPTY(blob_nodes)
var/link = FOLLOW_LINK(M, src)
to_chat(M, "[link] [rendered]")
/mob/camera/blob/emote(act,m_type=1,message = null)
return
/mob/camera/blob/blob_act(obj/structure/blob/B)
return
@@ -30,9 +30,11 @@
user.reagents.add_reagent("antihol", 10)
user.reagents.add_reagent("mannitol", 25)
for(var/thing in user.viruses)
var/datum/disease/D = thing
if(D.severity == VIRUS_SEVERITY_POSITIVE)
continue
D.cure()
if(isliving(user))
var/mob/living/L = user
for(var/thing in L.diseases)
var/datum/disease/D = thing
if(D.severity == DISEASE_SEVERITY_POSITIVE)
continue
D.cure()
return TRUE
@@ -0,0 +1,347 @@
/*
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/symptom/cough(),
new /datum/disease_ability/symptom/sneeze(),\
new /datum/disease_ability/symptom/hallucigen(),
new /datum/disease_ability/symptom/choking(),
new /datum/disease_ability/symptom/confusion(),
new /datum/disease_ability/symptom/youth(),
new /datum/disease_ability/symptom/vomit(),
new /datum/disease_ability/symptom/voice_change(),
new /datum/disease_ability/symptom/visionloss(),
new /datum/disease_ability/symptom/viraladaptation(),
new /datum/disease_ability/symptom/vitiligo(),
new /datum/disease_ability/symptom/sensory_restoration(),
new /datum/disease_ability/symptom/itching(),
new /datum/disease_ability/symptom/weight_loss(),
new /datum/disease_ability/symptom/metabolism_heal(),
new /datum/disease_ability/symptom/coma_heal()
))
/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 = ""
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 += "<br><br>[initial(S.threshold_desc)]"
stat_block = "Resistance: [resistance]<br>Stealth: [stealth]<br>Stage Speed: [stage_speed]<br>Transmittability: [transmittable]<br><br>"
/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 class='notice'>Purchased [name].</span>")
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
if(SD.processing)
S.Start(SD)
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 class='notice'>Refunded [name].</span>")
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
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 transmitability is low.<br>Cooldown: 10 seconds"
/datum/action/cooldown/disease_cough
name = "Cough"
icon_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 transmitability is low.<br>Cooldown: 10 seconds"
cooldown_time = 100
/datum/action/cooldown/disease_cough/Trigger()
if(!..())
return FALSE
var/mob/camera/disease/D = owner
var/mob/living/L = D.following_host
if(!L)
return FALSE
if(L.stat != CONSCIOUS)
to_chat(D, "<span class='warning'>Your host must be concious to cough.</span>")
return FALSE
to_chat(D, "<span class='notice'>You force [L.real_name] to cough.</span>")
L.emote("cough")
var/datum/disease/advance/sentient_disease/SD = D.hosts[L]
SD.spread(2)
StartCooldown()
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.<br>Cooldown: 20 seconds"
/datum/action/cooldown/disease_sneeze
name = "Sneeze"
icon_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 transmitability is low.<br>Cooldown: 20 seconds"
cooldown_time = 200
/datum/action/cooldown/disease_sneeze/Trigger()
if(!..())
return FALSE
var/mob/camera/disease/D = owner
var/mob/living/L = D.following_host
if(!L)
return FALSE
if(L.stat != CONSCIOUS)
to_chat(D, "<span class='warning'>Your host must be concious to sneeze.</span>")
return FALSE
to_chat(D, "<span class='notice'>You force [L.real_name] to sneeze.</span>")
L.emote("sneeze")
var/datum/disease/advance/sentient_disease/SD = D.hosts[L]
for(var/mob/living/M in oview(4, SD.affected_mob))
if(is_A_facing_B(SD.affected_mob, M) && disease_air_spread_walk(get_turf(SD.affected_mob), get_turf(M)))
M.AirborneContractDisease(SD, TRUE)
StartCooldown()
return TRUE
//passive symptom abilities
/datum/disease_ability/symptom/cough
name = "Involuntary Coughing"
symptoms = list(/datum/symptom/cough)
cost = 2
required_total_points = 4
short_desc = "Cause victims to cough intermittently."
long_desc = "Cause victims to cough intermittently, spreading your infection if your transmitability is high."
/datum/disease_ability/symptom/sneeze
name = "Involuntary Sneezing"
symptoms = list(/datum/symptom/sneeze)
cost = 2
required_total_points = 4
short_desc = "Cause victims to sneeze intermittently."
long_desc = "Cause victims to sneeze intermittently, spreading your infection and also increasing transmitability and resistance, at the cost of stealth."
/datum/disease_ability/symptom/beard
//I don't think I need to justify the fact that this is the best symptom
name = "Beard Growth"
symptoms = list(/datum/symptom/beard)
cost = 1
required_total_points = 8
short_desc = "Cause all victims to grow a luscious beard."
long_desc = "Cause all victims to grow a luscious beard. Decreases stats slightly. Ineffective against Santa Claus."
/datum/disease_ability/symptom/hallucigen
name = "Hallucinations"
symptoms = list(/datum/symptom/hallucigen)
cost = 4
required_total_points = 8
short_desc = "Cause victims to hallucinate."
long_desc = "Cause victims to hallucinate. Decreases stats, especially resistance."
/datum/disease_ability/symptom/choking
name = "Choking"
symptoms = list(/datum/symptom/choking)
cost = 4
required_total_points = 8
short_desc = "Cause victims to choke."
long_desc = "Cause victims to choke, threatening asphyxiation. Decreases stats, especially transmittability."
/datum/disease_ability/symptom/confusion
name = "Confusion"
symptoms = list(/datum/symptom/confusion)
cost = 4
required_total_points = 8
short_desc = "Cause victims to become confused."
long_desc = "Cause victims to become confused intermittently."
/datum/disease_ability/symptom/youth
name = "Eternal Youth"
symptoms = list(/datum/symptom/youth)
cost = 4
required_total_points = 8
short_desc = "Cause victims to become eternally young."
long_desc = "Cause victims to become eternally young. Provides boosts to all stats except transmittability."
/datum/disease_ability/symptom/vomit
name = "Vomiting"
symptoms = list(/datum/symptom/vomit)
cost = 4
required_total_points = 8
short_desc = "Cause victims to vomit."
long_desc = "Cause victims to vomit. Slightly increases transmittability. Vomiting also also causes the victims to lose nutrition and removes some toxin damage."
/datum/disease_ability/symptom/voice_change
name = "Voice Changing"
symptoms = list(/datum/symptom/voice_change)
cost = 4
required_total_points = 8
short_desc = "Change the voice of victims."
long_desc = "Change the voice of victims, causing confusion in communications."
/datum/disease_ability/symptom/visionloss
name = "Vision Loss"
symptoms = list(/datum/symptom/visionloss)
cost = 4
required_total_points = 8
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/viraladaptation
name = "Self-Adaptation"
symptoms = list(/datum/symptom/viraladaptation)
cost = 4
required_total_points = 8
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/vitiligo
name = "Skin Paleness"
symptoms = list(/datum/symptom/vitiligo)
cost = 1
required_total_points = 8
short_desc = "Cause victims to become pale."
long_desc = "Cause victims to become pale. Decreases all stats."
/datum/disease_ability/symptom/sensory_restoration
name = "Sensory Restoration"
symptoms = list(/datum/symptom/sensory_restoration)
cost = 4
required_total_points = 8
short_desc = "Regenerate eye and ear damage of victims."
long_desc = "Regenerate eye and ear damage of victims."
/datum/disease_ability/symptom/itching
name = "Itching"
symptoms = list(/datum/symptom/itching)
cost = 4
required_total_points = 8
short_desc = "Cause victims to itch."
long_desc = "Cause victims to itch, increasing all stats except stealth."
/datum/disease_ability/symptom/weight_loss
name = "Weight Loss"
symptoms = list(/datum/symptom/weight_loss)
cost = 4
required_total_points = 8
short_desc = "Cause victims to lose weight."
long_desc = "Cause victims to lose weight, and make it almost immpossible 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/metabolism_heal
name = "Metabolic Boost"
symptoms = list(/datum/symptom/heal/metabolism)
cost = 4
required_total_points = 16
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/coma_heal
name = "Regenerative Coma"
symptoms = list(/datum/symptom/heal/coma)
cost = 8
required_total_points = 16
short_desc = "Cause victims to fall into a healing coma when hurt."
long_desc = "Cause victims to fall into a healing coma when hurt."
@@ -0,0 +1,100 @@
/datum/antagonist/disease
name = "Sentient Disease"
roundend_category = "diseases"
antagpanel_category = "Disease"
var/disease_name = ""
/datum/antagonist/disease/on_gain()
owner.special_role = "Sentient Disease"
owner.assigned_role = "Sentient Disease"
var/datum/objective/O = new /datum/objective/disease_infect()
O.owner = owner
objectives += O
owner.objectives += O
O = new /datum/objective/disease_infect_centcom()
O.owner = owner
objectives += O
owner.objectives += O
. = ..()
/datum/antagonist/disease/greet()
to_chat(owner.current, "<span class='notice'>You are the [owner.special_role]!</span>")
to_chat(owner.current, "<span class='notice'>Infect members of the crew to gain adaptation points, and spread your infection further.</span>")
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 : locate(1, 1, 1)
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.infect_patient_zero()
D.pick_name()
/datum/antagonist/disease/roundend_report()
var/list/result = list()
result += "<b>Disease name:</b> [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 += "<br><B>Objective #[count]</B>: [objective.explanation_text] <span class='greentext'>Success!</span>"
else
objectives_text += "<br><B>Objective #[count]</B>: [objective.explanation_text] <span class='redtext'>Fail.</span>"
win = FALSE
count++
result += objectives_text
var/special_role_text = lowertext(name)
if(win)
result += "<span class='greentext'>The [special_role_text] was successful!</span>"
else
result += "<span class='redtext'>The [special_role_text] has failed!</span>"
if(istype(owner.current, /mob/camera/disease))
var/mob/camera/disease/D = owner.current
result += "<B>[disease_name] completed the round with [D.hosts.len] infected hosts, and reached a maximum of [D.total_points] concurrent infections.</B>"
result += "<B>[disease_name] completed the round with the following adaptations:</B>"
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("<br>")
/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
@@ -0,0 +1,59 @@
/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
var/mob/camera/disease/overmind
/datum/disease/advance/sentient_disease/New()
..()
GLOB.sentient_disease_instances += src
/datum/disease/advance/sentient_disease/Destroy()
. = ..()
GLOB.sentient_disease_instances -= src
/datum/disease/advance/sentient_disease/remove_disease()
if(overmind)
overmind.remove_infection(src)
..()
/datum/disease/advance/sentient_disease/infect(var/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(src, D.type))
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
return D
/datum/disease/advance/sentient_disease/after_add()
if(overmind)
overmind.add_infection(src)
/datum/disease/advance/sentient_disease/GetDiseaseID()
return "[type]|[overmind ? overmind.tag : null]"
/datum/disease/advance/sentient_disease/GenerateCure()
if(cures.len)
return
var/list/not_used = advance_cures.Copy()
cures = list(pick_n_take(not_used), 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]"
@@ -0,0 +1,30 @@
/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 = 5
/datum/round_event/ghost_role/sentient_disease
role_name = "sentient disease"
/datum/round_event/ghost_role/sentient_disease/spawn_role()
var/list/candidates = get_candidates(ROLE_ALIEN, null, ROLE_ALIEN)
if(!candidates.len)
return NOT_ENOUGH_PLAYERS
var/mob/dead/observer/selected = pick_n_take(candidates)
var/mob/camera/disease/virus = new /mob/camera/disease(locate(1, 1, 1))
if(!virus.infect_patient_zero())
message_admins("Event attempted to spawn a sentient disease, but infection of patient zero failed.")
qdel(virus)
return WAITING_FOR_SOMETHING
virus.key = selected.key
INVOKE_ASYNC(virus, /mob/camera/disease/proc/pick_name)
message_admins("[key_name_admin(virus)] has been made into a sentient disease by an event.")
log_game("[key_name(virus)] was spawned as a sentient disease by an event.")
spawned_mobs += virus
return SUCCESSFUL_SPAWN
@@ -0,0 +1,318 @@
/*
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 = ""
real_name = ""
desc = ""
icon = 'icons/mob/blob.dmi'
icon_state = "marker"
mouse_opacity = MOUSE_OPACITY_ICON
move_on_shuttle = 1
see_in_dark = 8
invisibility = INVISIBILITY_OBSERVER
layer = BELOW_MOB_LAYER
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
sight = SEE_SELF
initial_language_holder = /datum/language_holder/empty
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/datum/component/redirect/move_listener
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 = 1200
var/list/purchased_abilities
var/list/unpurchased_abilities
/mob/camera/disease/Initialize(mapload)
.= ..()
adaptation_menu_action = new /datum/action/innate/disease_adapt()
adaptation_menu_action.Grant(src)
disease_instances = list()
hosts = list()
purchased_abilities = list()
unpurchased_abilities = list()
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)
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.add_hud_to(src)
browser = new /datum/browser(src, "disease_menu", "Adaptation Menu", 1000, 770, src)
/mob/camera/disease/Destroy()
. = ..()
for(var/V in GLOB.sentient_disease_instances)
var/datum/disease/advance/sentient_disease/S = V
if(S.overmind == src)
S.overmind = null
/mob/camera/disease/Stat()
..()
if(statpanel("Status"))
stat("Adaptation Points: [points]/[total_points]")
stat("Hosts: [disease_instances.len]")
var/adapt_ready = next_adaptation_time - world.time
if(adapt_ready > 0)
stat("Adaptation Ready: [round(adapt_ready/10, 0.1)]s")
/mob/camera/disease/say(message)
return
/mob/camera/disease/Move(NewLoc, Dir = 0)
if(world.time > (last_move_tick + move_delay))
follow_next(Dir & NORTHWEST)
last_move_tick = world.time
/mob/camera/disease/mind_initialize()
. = ..()
if(!mind.has_antag_datum(/datum/antagonist/disease))
mind.add_antag_datum(/datum/antagonist/disease)
/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 = stripped_input(src, "Select a name for your disease", "Select Name", "", MAX_NAME_LEN)
if(!input)
set_name = "Sentient Virus"
break
if(taken_names[input])
to_chat(src, "<span class='notice'>You cannot use the name of such a well-known disease!</span>")
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_patient_zero()
var/list/possible_hosts = list()
var/datum/disease/advance/sentient_disease/V = disease_template.Copy()
for(var/mob/living/carbon/human/H in GLOB.carbon_list)
if((H.stat != DEAD) && H.CanContractDisease(V))
possible_hosts += H
if(!possible_hosts.len)
return FALSE
var/mob/living/carbon/human/H = pick(possible_hosts)
if(H.ForceContractDisease(V, FALSE, TRUE))
return TRUE
return FALSE
/mob/camera/disease/proc/force_infect(mob/living/L)
var/datum/disease/advance/sentient_disease/V = disease_template.Copy()
return L.ForceContractDisease(V, FALSE, TRUE)
/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_to_hud(V.affected_mob)
to_chat(src, "<span class='notice'>A new host, <b>[V.affected_mob.real_name]</b>, has been infected.</span>")
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
points -= 1
to_chat(src, "<span class='notice'>One of your hosts, <b>[V.affected_mob.real_name]</b>, has been purged of your infection.</span>")
var/datum/atom_hud/my_hud = GLOB.huds[DATA_HUD_SENTIENT_DISEASE]
my_hud.remove_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 class='userdanger'>The last of your infection has disappeared.</span>")
set_following(null)
qdel(src)
refresh_adaptation_menu()
/mob/camera/disease/proc/set_following(mob/living/L)
following_host = L
if(!move_listener)
move_listener = L.AddComponent(/datum/component/redirect, COMSIG_MOVABLE_MOVED, CALLBACK(src, .proc/follow_mob))
else
L.TakeComponent(move_listener)
if(QDELING(move_listener))
move_listener = null
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(newloc, dir)
var/turf/T = get_turf(following_host)
if(T)
forceMove(T)
/mob/camera/disease/DblClickOn(var/atom/A, params)
if(hosts[A])
set_following(A)
else
..()
/mob/camera/disease/proc/adapt_cooldown()
to_chat(src, "<span class='notice'>You have altered your genetic structure. You will be unable to adapt again for [adaptation_cooldown/10] seconds.</span>")
next_adaptation_time = world.time + adaptation_cooldown
addtimer(CALLBACK(src, .proc/notify_adapt_ready), adaptation_cooldown)
/mob/camera/disease/proc/notify_adapt_ready()
to_chat(src, "<span class='notice'>You are now ready to adapt again.</span>")
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 += "<a href='byond://?src=[REF(src)];main_menu=1'>Back</a><br><h1>[examining_ability.name]</h1>[examining_ability.stat_block][examining_ability.long_desc][examining_ability.threshold_block]"
else
dat += "<h1>Disease Statistics</h1><br>\
Resistance: [DT.totalResistance()]<br>\
Stealth: [DT.totalStealth()]<br>\
Stage Speed: [DT.totalStageSpeed()]<br>\
Transmittability: [DT.totalTransmittable()]<hr>\
Cure: [DT.cure_text]"
dat += "<hr><h1>Adaptations</h1>\
Points: [points] / [total_points]\
<table border=1>\
<tr><td>Cost</td><td></td><td>Unlock</td><td width='180px'>Name</td><td>Type</td><td>Description</td></tr>"
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 = "<a href='byond://?src=[REF(src)];buy_ability=[REF(A)]'>Purchase</a>"
else
purchase_text = "<span class='linkOff'>Purchase</span>"
else
if(A.CanRefund(src))
purchase_text = "<a href='byond://?src=[REF(src)];refund_ability=[REF(A)]'>Refund</a>"
else
purchase_text = "<span class='linkOff'>Refund</span>"
dat += "<tr><td>[A.cost]</td><td>[purchase_text]</td><td>[A.required_total_points]</td><td><a href='byond://?src=[REF(src)];examine_ability=[REF(A)]'>[A.name]</a></td><td>[A.category]</td><td>[A.short_desc]</td></tr>"
dat += "</table><br>Infect many hosts at once to gain adaptation points.<hr><h1>Infected Hosts</h1>"
for(var/V in hosts)
var/mob/living/L = V
dat += "<br><a href='byond://?src=[REF(src)];follow_instance=[REF(L)]'>[L.real_name]</a>"
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"])
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"])
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"])
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"
icon_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()
+2 -3
View File
@@ -40,11 +40,10 @@
owner.special_role = null
SSticker.mode.ape_infectees -= owner
var/datum/disease/transformation/jungle_fever/D = locate() in owner.current.viruses
var/datum/disease/transformation/jungle_fever/D = locate() in owner.current.diseases
if(D)
D.remove_virus()
qdel(D)
. = ..()
/datum/antagonist/monkey/create_team(datum/team/monkey/new_team)
@@ -354,12 +354,12 @@
if(H.dna && H.dna.species)
H.dna.species.handle_hair(H,"#1d2953") //will be reset when blight is cured
var/blightfound = FALSE
for(var/datum/disease/revblight/blight in H.viruses)
for(var/datum/disease/revblight/blight in H.diseases)
blightfound = TRUE
if(blight.stage < 5)
blight.stage++
if(!blightfound)
H.AddDisease(new /datum/disease/revblight)
H.ForceContractDisease(new /datum/disease/revblight(), FALSE, TRUE)
to_chat(H, "<span class='revenminor'>You feel [pick("suddenly sick", "a surge of nausea", "like your skin is <i>wrong</i>")].</span>")
else
if(mob.reagents)
@@ -2,7 +2,7 @@
name = "Unnatural Wasting"
max_stages = 5
stage_prob = 10
spread_flags = VIRUS_SPREAD_NON_CONTAGIOUS
spread_flags = DISEASE_SPREAD_NON_CONTAGIOUS
cure_text = "Holy water or extensive rest."
spread_text = "A burst of unholy energy"
cures = list("holywater")
@@ -11,7 +11,7 @@
viable_mobtypes = list(/mob/living/carbon/human)
disease_flags = CURABLE
permeability_mod = 1
severity = VIRUS_SEVERITY_HARMFUL
severity = DISEASE_SEVERITY_HARMFUL
var/stagedamage = 0 //Highest stage reached.
var/finalstage = 0 //Because we're spawning off the cure in the final stage, we need to check if we've done the final stage's effects.