diff --git a/code/__DEFINES/logging.dm b/code/__DEFINES/logging.dm
index 8548b2be..6549dd75 100644
--- a/code/__DEFINES/logging.dm
+++ b/code/__DEFINES/logging.dm
@@ -35,6 +35,7 @@
#define LOG_GAME (1 << 12)
#define LOG_ADMIN_PRIVATE (1 << 13)
#define LOG_ASAY (1 << 14)
+#define LOG_VIRUS (1 << 15)
//Individual logging panel pages
#define INDIVIDUAL_ATTACK_LOG (LOG_ATTACK)
diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm
index 657cfdae..a38aaeaa 100644
--- a/code/__DEFINES/traits.dm
+++ b/code/__DEFINES/traits.dm
@@ -184,6 +184,7 @@
#define OBESITY "obesity"
#define MAGIC_TRAIT "magic"
#define TRAUMA_TRAIT "trauma"
+#define DISEASE_TRAIT "disease"
#define SPECIES_TRAIT "species"
#define ORGAN_TRAIT "organ"
#define JOB_TRAIT "job"
diff --git a/code/__HELPERS/_logging.dm b/code/__HELPERS/_logging.dm
index 8deb1f9f..774b8768 100644
--- a/code/__HELPERS/_logging.dm
+++ b/code/__HELPERS/_logging.dm
@@ -61,6 +61,10 @@
if (CONFIG_GET(flag/log_game))
WRITE_LOG(GLOB.world_game_log, "GAME: [text]")
+/proc/log_virus(text)
+ if (CONFIG_GET(flag/log_virus))
+ WRITE_LOG(GLOB.world_virus_log, "VIRUS: [text]")
+
/proc/log_access(text)
if (CONFIG_GET(flag/log_access))
WRITE_LOG(GLOB.world_game_log, "ACCESS: [text]")
diff --git a/code/_globalvars/logging.dm b/code/_globalvars/logging.dm
index deffd25b..485e67e2 100644
--- a/code/_globalvars/logging.dm
+++ b/code/_globalvars/logging.dm
@@ -26,6 +26,8 @@ GLOBAL_VAR(query_debug_log)
GLOBAL_PROTECT(query_debug_log)
GLOBAL_VAR(world_job_debug_log)
GLOBAL_PROTECT(world_job_debug_log)
+GLOBAL_VAR(world_virus_log)
+GLOBAL_PROTECT(world_virus_log)
GLOBAL_LIST_EMPTY(bombers)
GLOBAL_PROTECT(bombers)
diff --git a/code/controllers/configuration/entries/general.dm b/code/controllers/configuration/entries/general.dm
index ceb879d5..03d52cd9 100644
--- a/code/controllers/configuration/entries/general.dm
+++ b/code/controllers/configuration/entries/general.dm
@@ -39,6 +39,8 @@
/datum/config_entry/flag/log_game // log game events
+/datum/config_entry/flag/log_virus // log virology data
+
/datum/config_entry/flag/log_vote // log voting
/datum/config_entry/flag/log_whisper // log client whisper
diff --git a/code/datums/components/storage/storage.dm b/code/datums/components/storage/storage.dm
index 98af707e..8a58f112 100644
--- a/code/datums/components/storage/storage.dm
+++ b/code/datums/components/storage/storage.dm
@@ -234,7 +234,7 @@
/datum/component/storage/proc/quick_empty(mob/M)
var/atom/A = parent
- if((!ishuman(M) && (A.loc != M)) || (M.stat != CONSCIOUS) || M.restrained() || !M.canmove)
+ if(!M.canUseStorage() || !A.Adjacent(M) || M.incapacitated())
return
if(check_locked(null, M, TRUE))
return FALSE
diff --git a/code/datums/diseases/_MobProcs.dm b/code/datums/diseases/_MobProcs.dm
index e1432bf9..c125a9b7 100644
--- a/code/datums/diseases/_MobProcs.dm
+++ b/code/datums/diseases/_MobProcs.dm
@@ -144,3 +144,9 @@
if(!((locate(thing) in bodyparts) || (locate(thing) in internal_organs)))
return FALSE
return ..()
+
+/mob/living/proc/CanSpreadAirborneDisease()
+ return !is_mouth_covered()
+
+/mob/living/carbon/CanSpreadAirborneDisease()
+ return !((head && (head.flags_cover & HEADCOVERSMOUTH) && (head.armor.getRating("bio") >= 25)) || (wear_mask && (wear_mask.flags_cover & MASKCOVERSMOUTH) && (wear_mask.armor.getRating("bio") >= 25)))
\ No newline at end of file
diff --git a/code/datums/diseases/_disease.dm b/code/datums/diseases/_disease.dm
index 0af4eea8..8a696666 100644
--- a/code/datums/diseases/_disease.dm
+++ b/code/datums/diseases/_disease.dm
@@ -55,6 +55,13 @@
D.after_add()
infectee.med_hud_set_status()
+ var/turf/source_turf = get_turf(infectee)
+ log_virus("[key_name(infectee)] was infected by virus: [src.admin_details()] at [loc_name(source_turf)]")
+
+//Return a string for admin logging uses, should describe the disease in detail
+/datum/disease/proc/admin_details()
+ return "[src.name] : [src.type]"
+
/datum/disease/proc/stage_act()
var/cure = has_cure()
@@ -65,15 +72,17 @@
if(!cure)
if(prob(stage_prob))
- stage = min(stage + 1,max_stages)
+ update_stage(min(stage + 1,max_stages))
else
if(prob(cure_chance))
- stage = max(stage - 1, 1)
+ update_stage(max(stage - 1, 1))
if(disease_flags & CURABLE)
if(cure && prob(cure_chance))
cure()
+/datum/disease/proc/update_stage(new_stage)
+ stage = new_stage
/datum/disease/proc/has_cure()
if(!(disease_flags & CURABLE))
diff --git a/code/datums/diseases/advance/advance.dm b/code/datums/diseases/advance/advance.dm
index 6a41b710..b70f44fd 100644
--- a/code/datums/diseases/advance/advance.dm
+++ b/code/datums/diseases/advance/advance.dm
@@ -31,9 +31,9 @@
var/id = ""
var/processing = FALSE
var/mutable = TRUE //set to FALSE to prevent most in-game methods of altering the disease via virology
- var/oldres
+ var/oldres //To prevent setting new cures unless resistance changes.
- // The order goes from easy to cure to hard to cure.
+ // The order goes from easy to cure to hard to cure. Keep in mind that sentient diseases pick two cures from tier 6 and up, ensure they wont react away in bodies.
var/static/list/advance_cures = list(
list( // level 1
"copper", "silver", "iodine", "iron", "carbon"
@@ -110,15 +110,22 @@
return
if(symptoms && symptoms.len)
-
if(!processing)
processing = TRUE
for(var/datum/symptom/S in symptoms)
- S.Start(src)
+ if(S.Start(src)) //this will return FALSE if the symptom is neutered
+ S.next_activation = world.time + rand(S.symptom_delay_min * 10, S.symptom_delay_max * 10)
+ S.on_stage_change(src)
for(var/datum/symptom/S in symptoms)
S.Activate(src)
+// Tell symptoms stage changed
+/datum/disease/advance/update_stage(new_stage)
+ ..()
+ for(var/datum/symptom/S in symptoms)
+ S.on_stage_change(src)
+
// Compares type then ID.
/datum/disease/advance/IsSame(datum/disease/advance/D)
@@ -137,10 +144,16 @@
A.symptoms += S.Copy()
A.properties = properties.Copy()
A.id = id
- A.mutable = mutable
+ A.oldres = oldres
//this is a new disease starting over at stage 1, so processing is not copied
return A
+//Describe this disease to an admin in detail (for logging)
+/datum/disease/advance/admin_details()
+ var/list/name_symptoms = list()
+ for(var/datum/symptom/S in symptoms)
+ name_symptoms += S.name
+ return "[name] sym:[english_list(name_symptoms)] r:[totalResistance()] s:[totalStealth()] ss:[totalStageSpeed()] t:[totalTransmittable()]"
/*
NEW PROCS
@@ -191,6 +204,10 @@
/datum/disease/advance/proc/Refresh(new_name = FALSE)
GenerateProperties()
AssignProperties()
+ if(processing && symptoms && symptoms.len)
+ for(var/datum/symptom/S in symptoms)
+ S.Start(src)
+ S.on_stage_change(src)
id = null
var/the_id = GetDiseaseID()
@@ -342,28 +359,28 @@
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.
+// Add a symptom, if it is over the limit 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 < (VIRUS_SYMPTOM_LIMIT - 1) + rand(-1, 1))
- symptoms += S
- else
+ if(!(symptoms.len < (VIRUS_SYMPTOM_LIMIT - 1) + rand(-1, 1)))
RemoveSymptom(pick(symptoms))
- symptoms += S
+ symptoms += S
+ S.OnAdd(src)
// Simply removes the symptom.
/datum/disease/advance/proc/RemoveSymptom(datum/symptom/S)
symptoms -= S
+ S.OnRemove(src)
// Neuter a symptom, so it will only affect stats
/datum/disease/advance/proc/NeuterSymptom(datum/symptom/S)
if(!S.neutered)
S.neutered = TRUE
S.name += " (neutered)"
+ S.OnRemove(src)
/*
@@ -417,7 +434,7 @@
var/i = VIRUS_SYMPTOM_LIMIT
- var/datum/disease/advance/D = new(0, null)
+ var/datum/disease/advance/D = new()
D.symptoms = list()
var/list/symptoms = list()
@@ -444,10 +461,6 @@
return
D.AssignName(new_name)
D.Refresh()
-
- for(var/datum/disease/advance/AD in SSdisease.active_diseases)
- AD.Refresh()
-
for(var/mob/living/carbon/human/H in shuffle(GLOB.alive_mob_list))
if(!is_station_level(H.z))
continue
@@ -458,7 +471,8 @@
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)]")
+ message_admins("[key_name_admin(user)] has triggered a custom virus outbreak of [D.admin_details()]")
+ log_virus("[key_name(user)] has triggered a custom virus outbreak of [D.admin_details()]!")
/datum/disease/advance/proc/totalStageSpeed()
diff --git a/code/datums/diseases/advance/symptoms/cough.dm b/code/datums/diseases/advance/symptoms/cough.dm
index 23c332ec..b1767d7c 100644
--- a/code/datums/diseases/advance/symptoms/cough.dm
+++ b/code/datums/diseases/advance/symptoms/cough.dm
@@ -70,6 +70,6 @@ BONUS
addtimer(CALLBACK(M, /mob/.proc/emote, "cough"), 6)
addtimer(CALLBACK(M, /mob/.proc/emote, "cough"), 12)
addtimer(CALLBACK(M, /mob/.proc/emote, "cough"), 18)
- if(infective)
+ if(infective && M.CanSpreadAirborneDisease())
A.spread(1)
diff --git a/code/datums/diseases/advance/symptoms/heal.dm b/code/datums/diseases/advance/symptoms/heal.dm
index e666c7ac..1ab3456c 100644
--- a/code/datums/diseases/advance/symptoms/heal.dm
+++ b/code/datums/diseases/advance/symptoms/heal.dm
@@ -219,8 +219,10 @@
level = 8
passive_message = "The pain from your wounds makes you feel oddly sleepy..."
var/deathgasp = FALSE
+ var/stabilize = FALSE
var/active_coma = FALSE //to prevent multiple coma procs
threshold_desc = "Stealth 2: Host appears to die when falling into a coma.
\
+ Resistance 4: The virus also stabilizes the host while they are in critical condition.
\
Stage Speed 7: Increases healing speed."
/datum/symptom/heal/coma/Start(datum/disease/advance/A)
@@ -228,9 +230,25 @@
return
if(A.properties["stage_rate"] >= 7)
power = 1.5
+ if(A.properties["resistance"] >= 4)
+ stabilize = TRUE
if(A.properties["stealth"] >= 2)
deathgasp = TRUE
+/datum/symptom/heal/coma/on_stage_change(datum/disease/advance/A) //mostly copy+pasted from the code for self-respiration's TRAIT_NOBREATH stuff
+ if(!..())
+ return FALSE
+ if(A.stage >= 4 && stabilize)
+ ADD_TRAIT(A.affected_mob, TRAIT_NOCRITDAMAGE, DISEASE_TRAIT)
+ else
+ REMOVE_TRAIT(A.affected_mob, TRAIT_NOCRITDAMAGE, DISEASE_TRAIT)
+ return TRUE
+
+/datum/symptom/heal/coma/End(datum/disease/advance/A)
+ if(!..())
+ return
+ REMOVE_TRAIT(A.affected_mob, TRAIT_NOCRITDAMAGE, DISEASE_TRAIT)
+
/datum/symptom/heal/coma/CanHeal(datum/disease/advance/A)
var/mob/living/M = A.affected_mob
if(HAS_TRAIT(M, TRAIT_DEATHCOMA))
diff --git a/code/datums/diseases/advance/symptoms/oxygen.dm b/code/datums/diseases/advance/symptoms/oxygen.dm
index cb7d1a6d..65f83071 100644
--- a/code/datums/diseases/advance/symptoms/oxygen.dm
+++ b/code/datums/diseases/advance/symptoms/oxygen.dm
@@ -50,3 +50,19 @@ Bonus
if(prob(base_message_chance))
to_chat(M, "[pick("Your lungs feel great.", "You realize you haven't been breathing.", "You don't feel the need to breathe.")]")
return
+
+/datum/symptom/oxygen/on_stage_change(datum/disease/advance/A)
+ if(!..())
+ return FALSE
+ var/mob/living/carbon/M = A.affected_mob
+ if(A.stage >= 4)
+ ADD_TRAIT(M, TRAIT_NOBREATH, DISEASE_TRAIT)
+ else
+ REMOVE_TRAIT(M, TRAIT_NOBREATH, DISEASE_TRAIT)
+ return TRUE
+
+/datum/symptom/oxygen/End(datum/disease/advance/A)
+ if(!..())
+ return
+ if(A.stage >= 4)
+ REMOVE_TRAIT(A.affected_mob, TRAIT_NOBREATH, DISEASE_TRAIT)
\ No newline at end of file
diff --git a/code/datums/diseases/advance/symptoms/sneeze.dm b/code/datums/diseases/advance/symptoms/sneeze.dm
index 8fe70c54..5e21fb3d 100644
--- a/code/datums/diseases/advance/symptoms/sneeze.dm
+++ b/code/datums/diseases/advance/symptoms/sneeze.dm
@@ -48,4 +48,5 @@ Bonus
M.emote("sniff")
else
M.emote("sneeze")
- A.spread(4 + power)
\ No newline at end of file
+ if(M.CanSpreadAirborneDisease()) //don't spread germs if they covered their mouth
+ A.spread(4 + power)
\ No newline at end of file
diff --git a/code/datums/diseases/advance/symptoms/species.dm b/code/datums/diseases/advance/symptoms/species.dm
index b609529a..1e3df649 100644
--- a/code/datums/diseases/advance/symptoms/species.dm
+++ b/code/datums/diseases/advance/symptoms/species.dm
@@ -8,12 +8,14 @@
level = 5
severity = 0
-/datum/symptom/undead_adaptation/Start(datum/disease/advance/A)
- if(!..())
- return
+/datum/symptom/undead_adaptation/OnAdd(datum/disease/advance/A)
A.process_dead = TRUE
A.infectable_biotypes |= MOB_UNDEAD
+/datum/symptom/undead_adaptation/OnRemove(datum/disease/advance/A)
+ A.process_dead = FALSE
+ A.infectable_biotypes -= MOB_UNDEAD
+
/datum/symptom/inorganic_adaptation
name = "Inorganic Biology"
desc = "The virus can survive and replicate even in an inorganic environment, increasing its resistance and infection rate."
@@ -24,8 +26,8 @@
level = 5
severity = 0
-/datum/symptom/inorganic_adaptation/Start(datum/disease/advance/A)
- if(!..())
- return
+/datum/symptom/inorganic_adaptation/OnAdd(datum/disease/advance/A)
A.infectable_biotypes |= MOB_INORGANIC
-
\ No newline at end of file
+
+/datum/symptom/inorganic_adaptation/OnRemove(datum/disease/advance/A)
+ A.infectable_biotypes -= MOB_INORGANIC
diff --git a/code/datums/diseases/advance/symptoms/symptoms.dm b/code/datums/diseases/advance/symptoms/symptoms.dm
index 04fbf334..76bce9d7 100644
--- a/code/datums/diseases/advance/symptoms/symptoms.dm
+++ b/code/datums/diseases/advance/symptoms/symptoms.dm
@@ -38,11 +38,10 @@
return
CRASH("We couldn't assign an ID!")
-// Called when processing of the advance disease, which holds this symptom, starts.
+// Called when processing of the advance disease that holds this symptom infects a host and upon each Refresh() of that advance disease.
/datum/symptom/proc/Start(datum/disease/advance/A)
if(neutered)
return FALSE
- next_activation = world.time + rand(symptom_delay_min * 10, symptom_delay_max * 10) //so it doesn't instantly activate on infection
return TRUE
// Called when the advance disease is going to be deleted or when the advance disease stops processing.
@@ -60,6 +59,11 @@
next_activation = world.time + rand(symptom_delay_min * 10, symptom_delay_max * 10)
return TRUE
+/datum/symptom/proc/on_stage_change(datum/disease/advance/A)
+ if(neutered)
+ return FALSE
+ return TRUE
+
/datum/symptom/proc/Copy()
var/datum/symptom/new_symp = new type
new_symp.name = name
@@ -69,3 +73,9 @@
/datum/symptom/proc/generate_threshold_desc()
return
+
+/datum/symptom/proc/OnAdd(datum/disease/advance/A) //Overload when a symptom needs to be active before processing, like changing biotypes.
+ return
+
+/datum/symptom/proc/OnRemove(datum/disease/advance/A) //But dont forget to remove them too.
+ return
diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm
index 13b24b23..5eea5703 100644
--- a/code/game/objects/items/devices/flashlight.dm
+++ b/code/game/objects/items/devices/flashlight.dm
@@ -96,7 +96,7 @@
if(BODY_ZONE_PRECISE_MOUTH)
- if((M.head && M.head.flags_cover & HEADCOVERSMOUTH) || (M.wear_mask && M.wear_mask.flags_cover & MASKCOVERSMOUTH))
+ if(M.is_mouth_covered())
to_chat(user, "You're going to need to remove that [(M.head && M.head.flags_cover & HEADCOVERSMOUTH) ? "helmet" : "mask"] first.")
return
diff --git a/code/game/objects/items/storage/firstaid.dm b/code/game/objects/items/storage/firstaid.dm
index dc048e3e..5321b5ef 100644
--- a/code/game/objects/items/storage/firstaid.dm
+++ b/code/game/objects/items/storage/firstaid.dm
@@ -30,7 +30,6 @@
/obj/item/storage/firstaid/regular/PopulateContents()
if(empty)
return
- new /obj/item/stack/medical/plaster_gauze(src)
new /obj/item/stack/medical/gauze(src)
new /obj/item/stack/medical/bruise_pack(src)
new /obj/item/stack/medical/bruise_pack(src)
diff --git a/code/game/world.dm b/code/game/world.dm
index 3d01218b..64ebce37 100644
--- a/code/game/world.dm
+++ b/code/game/world.dm
@@ -107,6 +107,7 @@ GLOBAL_VAR(restart_counter)
GLOB.picture_log_directory = "data/picture_logs/[override_dir]"
GLOB.world_game_log = "[GLOB.log_directory]/game.log"
+ GLOB.world_virus_log = "[GLOB.log_directory]/virus.log"
GLOB.world_attack_log = "[GLOB.log_directory]/attack.log"
GLOB.world_pda_log = "[GLOB.log_directory]/pda.log"
GLOB.world_telecomms_log = "[GLOB.log_directory]/telecomms.log"
diff --git a/code/modules/antagonists/disease/disease_abilities.dm b/code/modules/antagonists/disease/disease_abilities.dm
index 77e0e976..dc224900 100644
--- a/code/modules/antagonists/disease/disease_abilities.dm
+++ b/code/modules/antagonists/disease/disease_abilities.dm
@@ -5,25 +5,48 @@ 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/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()
+ 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/shivering,
+ new /datum/disease_ability/symptom/medium/headache,
+ new /datum/disease_ability/symptom/medium/nano_boost,
+ new /datum/disease_ability/symptom/medium/nano_destroy,
+ new /datum/disease_ability/symptom/medium/viraladaptation,
+ new /datum/disease_ability/symptom/medium/viralevolution,
+ new /datum/disease_ability/symptom/medium/vitiligo,
+ new /datum/disease_ability/symptom/medium/revitiligo,
+ 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
@@ -54,7 +77,13 @@ GLOBAL_LIST_INIT(disease_ability_singletons, list(
stage_speed += initial(S.stage_speed)
transmittable += initial(S.transmittable)
threshold_block += "
[initial(S.threshold_desc)]"
- stat_block = "Resistance: [resistance]
Stealth: [stealth]
Stage Speed: [stage_speed]
Transmissibility: [transmittable]
"
+ 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)
@@ -77,8 +106,10 @@ GLOBAL_LIST_INIT(disease_ability_singletons, list(
for(var/T in symptoms)
var/datum/symptom/S = new T()
SD.symptoms += S
+ S.OnAdd(SD)
if(SD.processing)
- S.Start(SD)
+ 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()
@@ -105,6 +136,7 @@ GLOBAL_LIST_INIT(disease_ability_singletons, list(
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)
@@ -152,8 +184,9 @@ GLOBAL_LIST_INIT(disease_ability_singletons, list(
return FALSE
to_chat(D, "You force [L.real_name] to cough.")
L.emote("cough")
- var/datum/disease/advance/sentient_disease/SD = D.hosts[L]
- SD.spread(2)
+ if(L.CanSpreadAirborneDisease()) //don't spread germs if they covered their mouth
+ var/datum/disease/advance/sentient_disease/SD = D.hosts[L]
+ SD.spread(2)
StartCooldown()
return TRUE
@@ -185,11 +218,12 @@ GLOBAL_LIST_INIT(disease_ability_singletons, list(
return FALSE
to_chat(D, "You force [L.real_name] to sneeze.")
L.emote("sneeze")
- var/datum/disease/advance/sentient_disease/SD = D.hosts[L]
+ if(L.CanSpreadAirborneDisease()) //don't spread germs if they covered their mouth
+ 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)
+ 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
@@ -235,143 +269,192 @@ GLOBAL_LIST_INIT(disease_ability_singletons, list(
StartCooldown()
return TRUE
-//passive symptom abilities
+/*******************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/cough
- name = "Involuntary Coughing"
- symptoms = list(/datum/symptom/cough)
+/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 if your transmissibility is high."
-/datum/disease_ability/symptom/sneeze
+/datum/disease_ability/symptom/mild/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 transmissibility 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."
+/******MEDIUM******/
-/datum/disease_ability/symptom/hallucigen
- name = "Hallucinations"
+/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)
- 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"
+/datum/disease_ability/symptom/medium/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 transmissibility."
-
-/datum/disease_ability/symptom/confusion
- name = "Confusion"
+/datum/disease_ability/symptom/medium/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 transmissibility."
-
-
-/datum/disease_ability/symptom/vomit
- name = "Vomiting"
+/datum/disease_ability/symptom/medium/vomit
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 transmissibility. Vomiting also also causes the victims to lose nutrition and removes some toxin damage."
-/datum/disease_ability/symptom/voice_change
- name = "Voice Changing"
+/datum/disease_ability/symptom/medium/voice_change
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"
+/datum/disease_ability/symptom/medium/visionloss
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"
+/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/shivering
+ symptoms = list(/datum/symptom/shivering)
+
+/datum/disease_ability/symptom/medium/headache
+ symptoms = list(/datum/symptom/headache)
+
+/datum/disease_ability/symptom/medium/nano_boost
+ symptoms = list(/datum/symptom/nano_boost)
+
+/datum/disease_ability/symptom/medium/nano_destroy
+ symptoms = list(/datum/symptom/nano_destroy)
+
+/datum/disease_ability/symptom/medium/viraladaptation
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"
+/datum/disease_ability/symptom/medium/viralevolution
+ symptoms = list(/datum/symptom/viralevolution)
+
+/datum/disease_ability/symptom/medium/vitiligo
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/medium/revitiligo
+ symptoms = list(/datum/symptom/revitiligo)
-/datum/disease_ability/symptom/itching
- name = "Itching"
+/datum/disease_ability/symptom/medium/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"
+/datum/disease_ability/symptom/medium/heal/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 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/metabolism_heal
- name = "Metabolic Boost"
+/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)
- 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"
+/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)
- 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."
diff --git a/code/modules/antagonists/disease/disease_disease.dm b/code/modules/antagonists/disease/disease_disease.dm
index b4b8ac09..c37abefa 100644
--- a/code/modules/antagonists/disease/disease_disease.dm
+++ b/code/modules/antagonists/disease/disease_disease.dm
@@ -51,6 +51,7 @@
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
diff --git a/code/modules/antagonists/disease/disease_mob.dm b/code/modules/antagonists/disease/disease_mob.dm
index 434ecabf..adb448d2 100644
--- a/code/modules/antagonists/disease/disease_mob.dm
+++ b/code/modules/antagonists/disease/disease_mob.dm
@@ -18,7 +18,7 @@ the new instance inside the host to be updated to the template's stats.
layer = BELOW_MOB_LAYER
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
sight = SEE_SELF|SEE_THRU
- initial_language_holder = /datum/language_holder/empty
+ initial_language_holder = /datum/language_holder/universal
var/freemove = TRUE
var/freemove_end = 0
@@ -43,7 +43,7 @@ the new instance inside the host to be updated to the template's stats.
var/move_delay = 1
var/next_adaptation_time = 0
- var/adaptation_cooldown = 1200
+ var/adaptation_cooldown = 600
var/list/purchased_abilities
var/list/unpurchased_abilities
@@ -118,10 +118,28 @@ the new instance inside the host to be updated to the template's stats.
follow_next(Dir & NORTHWEST)
last_move_tick = world.time
+/mob/camera/disease/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode)
+ . = ..()
+ 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 = ""
+ // Recompose the message, because it's scrambled by default
+ message = compose_message(speaker, message_language, raw_message, radio_freq, spans, message_mode)
+ 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.add_hud_to(src)
/mob/camera/disease/proc/pick_name()
var/static/list/taken_names
@@ -247,9 +265,12 @@ the new instance inside the host to be updated to the template's stats.
if(!move_listener)
move_listener = L.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/follow_mob)))
else
- L.TakeComponent(move_listener)
- if(QDELING(move_listener))
- move_listener = null
+ if(L)
+ L.TakeComponent(move_listener)
+ if(QDELING(move_listener))
+ move_listener = null
+ else
+ QDEL_NULL(move_listener)
follow_mob()
/mob/camera/disease/proc/follow_next(reverse = FALSE)
diff --git a/code/modules/jobs/job_types/job_alt_titles.dm b/code/modules/jobs/job_types/job_alt_titles.dm
index fd080223..68e79dd5 100644
--- a/code/modules/jobs/job_types/job_alt_titles.dm
+++ b/code/modules/jobs/job_types/job_alt_titles.dm
@@ -54,7 +54,7 @@
alt_titles = list("Medical Director")
/datum/job/doctor
- alt_titles = list("Nurse", "Surgeon", "Physician")
+ alt_titles = list("Nurse", "Surgeon", "Physician", "Paramedic")
/datum/job/chemist
alt_titles = list("Pharmacist", "Pharmacologist")
diff --git a/code/modules/mob/camera/camera.dm b/code/modules/mob/camera/camera.dm
index de4f2c5a..ff1d9231 100644
--- a/code/modules/mob/camera/camera.dm
+++ b/code/modules/mob/camera/camera.dm
@@ -31,5 +31,8 @@
loc = destination
Moved(oldloc, NONE, TRUE)
+/mob/camera/canUseStorage()
+ return FALSE
+
/mob/camera/emote(act, m_type=1, message = null, intentional = FALSE)
return
diff --git a/code/modules/mob/dead/dead.dm b/code/modules/mob/dead/dead.dm
index 288ca6b3..0c50cb04 100644
--- a/code/modules/mob/dead/dead.dm
+++ b/code/modules/mob/dead/dead.dm
@@ -21,6 +21,9 @@ INITIALIZE_IMMEDIATE(/mob/dead)
set_focus(src)
return INITIALIZE_HINT_NORMAL
+/mob/dead/canUseStorage()
+ return FALSE
+
/mob/dead/dust(just_ash, drop_items, force) //ghosts can't be vaporised.
return
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index bd88a3c8..b315428a 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -373,6 +373,11 @@
if(stat || IsUnconscious() || IsStun() || IsKnockdown() || recoveringstam || (!ignore_restraints && restrained(ignore_grab))) // CIT CHANGE - adds recoveringstam check here
return TRUE
+/mob/living/canUseStorage()
+ if (get_num_arms() <= 0)
+ return FALSE
+ return TRUE
+
/mob/living/proc/InCritical()
return (health <= crit_threshold && (stat == SOFT_CRIT || stat == UNCONSCIOUS))
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index c7ce6577..1d14e084 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -830,6 +830,9 @@
/mob/proc/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE)
return
+/mob/proc/canUseStorage()
+ return FALSE
+
/mob/proc/faction_check_mob(mob/target, exact_match)
if(exact_match) //if we need an exact match, we need to do some bullfuckery.
var/list/faction_src = faction.Copy()
diff --git a/code/modules/reagents/chemistry/machinery/pandemic.dm b/code/modules/reagents/chemistry/machinery/pandemic.dm
index 5e80c42a..e0cbaef6 100644
--- a/code/modules/reagents/chemistry/machinery/pandemic.dm
+++ b/code/modules/reagents/chemistry/machinery/pandemic.dm
@@ -195,6 +195,8 @@
B.reagents.add_reagent("blood", 20, data)
wait = TRUE
update_icon()
+ var/turf/source_turf = get_turf(src)
+ log_virus("A culture bottle was printed for the virus [A.admin_details()] at [loc_name(source_turf)] by [key_name(usr)]")
addtimer(CALLBACK(src, .proc/reset_replicator_cooldown), 50)
. = TRUE
if("create_vaccine_bottle")
diff --git a/code/modules/reagents/chemistry/recipes/others.dm b/code/modules/reagents/chemistry/recipes/others.dm
index d40b1a5b..ea7f86c5 100644
--- a/code/modules/reagents/chemistry/recipes/others.dm
+++ b/code/modules/reagents/chemistry/recipes/others.dm
@@ -702,3 +702,11 @@
id = "royalbluecarpet"
results = list("royalbluecarpet" = 2)
required_reagents = list("carpet" = 1, "clonexadone" = 1)
+
+/datum/chemical_reaction/synth_blood
+ name = "Synthetic Blood"
+ id = "syntheticblood"
+ results = list("syntheticblood" = 3)
+ required_reagents = list("salglu_solution" = 1, "iron" = 1, "stable_plasma" = 1)
+ mix_message = "The mixture congeals and gives off a faint copper scent."
+ required_temp = 350
diff --git a/code/modules/reagents/reagent_containers/pill.dm b/code/modules/reagents/reagent_containers/pill.dm
index 38880f66..c40df151 100644
--- a/code/modules/reagents/reagent_containers/pill.dm
+++ b/code/modules/reagents/reagent_containers/pill.dm
@@ -47,7 +47,7 @@
"[user] forces [M] to [apply_method] [src].")
var/makes_me_think = pick(strings("redpill.json", "redpill_questions"))
- if(icon_state == "pill4" && prob(5)) //you take the red pill - you stay in Wonderland, and I show you how deep the rabbit hole goes
+ if(icon_state == "pill4" && prob(10)) //you take the red pill - you stay in Wonderland, and I show you how deep the rabbit hole goes
addtimer(CALLBACK(GLOBAL_PROC, /proc/to_chat, M, "[makes_me_think]"), 50)
log_combat(user, M, "fed", reagents.log_list())
diff --git a/code/modules/research/designs/autolathe_desings/autolathe_designs_medical_and_dinnerware.dm b/code/modules/research/designs/autolathe_desings/autolathe_designs_medical_and_dinnerware.dm
index 6f6fb0c8..be55ed17 100644
--- a/code/modules/research/designs/autolathe_desings/autolathe_designs_medical_and_dinnerware.dm
+++ b/code/modules/research/designs/autolathe_desings/autolathe_designs_medical_and_dinnerware.dm
@@ -159,10 +159,11 @@
/datum/design/large_beaker
name = "Large Beaker"
id = "large_beaker"
- build_type = AUTOLATHE
+ build_type = AUTOLATHE | PROTOLATHE
materials = list(MAT_GLASS = 2500)
build_path = /obj/item/reagent_containers/glass/beaker/large
category = list("initial", "Medical")
+ departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE
/datum/design/healthanalyzer
name = "Health Analyzer"
@@ -208,7 +209,8 @@
/datum/design/hypoviallarge
name = "Large Hypovial"
id = "large_hypovial"
- build_type = AUTOLATHE
+ build_type = AUTOLATHE | PROTOLATHE
materials = list(MAT_METAL = 2500)
build_path = /obj/item/reagent_containers/glass/bottle/vial/large
category = list("initial","Medical")
+ departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE
diff --git a/code/modules/research/designs/medical_designs.dm b/code/modules/research/designs/medical_designs.dm
index 2a79d48b..abf7f37a 100644
--- a/code/modules/research/designs/medical_designs.dm
+++ b/code/modules/research/designs/medical_designs.dm
@@ -960,3 +960,14 @@
build_path = /obj/item/hypospray/mkii/disposable
category = list("Medical Designs")
departmental_flags = DEPARTMENTAL_FLAG_MEDICAL
+
+/datum/design/adv_hypo
+ name = "Hypospray MK.II"
+ desc = "A new development from DeForest Medical, this hypospray takes 30-unit vials as the drug supply for easy swapping."
+ id = "hypo2"
+ build_type = PROTOLATHE
+ materials = list(MAT_METAL = 500, MAT_GLASS = 500, MAT_SILVER = 500)
+ construction_time = 40
+ build_path = /obj/item/hypospray/mkii
+ category = list("Medical Designs")
+ departmental_flags = DEPARTMENTAL_FLAG_MEDICAL
diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm
index 1d221480..4701bf2b 100644
--- a/code/modules/research/techweb/all_nodes.dm
+++ b/code/modules/research/techweb/all_nodes.dm
@@ -12,7 +12,7 @@
"destructive_analyzer", "circuit_imprinter", "experimentor", "rdconsole", "design_disk", "tech_disk", "rdserver", "rdservercontrol", "mechfab",
"space_heater", "xlarge_beaker", "sec_rshot", "sec_bshot", "sec_slug", "sec_Islug", "sec_dart", "sec_38", "sec_38lethal",
"rglass","plasteel","plastitanium","plasmaglass","plasmareinforcedglass","titaniumglass","plastitaniumglass","chem_pack","medkit_cabinet",
- "disposable_hypospray","plastic_knife","plastic_fork","plastic_spoon")
+ "disposable_hypospray","plastic_knife","plastic_fork","plastic_spoon","large_beaker")
/datum/techweb_node/mmi
id = "mmi"
@@ -81,7 +81,7 @@
display_name = "Advanced Biotechnology"
description = "Advanced Biotechnology"
prereq_ids = list("biotech")
- design_ids = list("piercesyringe", "crewpinpointer", "smoke_machine", "plasmarefiller", "limbgrower", "defibrillator", "meta_beaker", "healthanalyzer_advanced","harvester","holobarrier_med","smartdartgun","medicinalsmartdart", "pHmeter")
+ design_ids = list("piercesyringe", "crewpinpointer", "smoke_machine", "plasmarefiller", "limbgrower", "defibrillator", "meta_beaker", "healthanalyzer_advanced","harvester","holobarrier_med","smartdartgun","medicinalsmartdart", "pHmeter", "large_hypovial")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
export_price = 5000
@@ -673,7 +673,7 @@
display_name = "Medical Weaponry"
description = "Weapons using medical technology."
prereq_ids = list("adv_biotech", "adv_weaponry")
- design_ids = list("rapidsyringe", "shotgundartcryostatis")
+ design_ids = list("rapidsyringe", "shotgundartcryostatis", "hypo2")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000)
export_price = 5000
diff --git a/config/config.txt b/config/config.txt
index 1d7b9ce1..f548b087 100644
--- a/config/config.txt
+++ b/config/config.txt
@@ -146,6 +146,9 @@ LOG_MANIFEST
## Enable logging pictures
# LOG_PICTURES
+## log virus and actions
+LOG_VIRUS
+
##Log camera pictures - Must have picture logging enabled
PICTURE_LOGGING_CAMERA
diff --git a/strings/redpill.json b/strings/redpill.json
index 3f65db73..2526d254 100644
--- a/strings/redpill.json
+++ b/strings/redpill.json
@@ -4,7 +4,7 @@
"Why is it called the emergency shuttle if it arrives every single shift?",
"Where does the Cook get all this meat from?",
"Space wind? How does that even make sense?",
- "Why does Nanotrasen hire Clowns and Mimes for every single station?",
+ "Why does Kinaris hire Clowns and Mimes for every single station?",
"Why is the station's air supply connected to the plasma tank?",
"Why are there fire alarms everywhere but no sprinklers?",
"Why is this a plasma research station if we know everything about plasma already?",
@@ -16,16 +16,16 @@
"How come a hole in the floor doesn't suck you out into space?",
"Why is space cold?",
"Why does space circle around on itself?",
- "Nanotrasen just clones us every shift.",
+ "Kinaris just clones us every shift.",
"There's no biological difference between lizards and humans.",
"Why is there a floor, but no roof?",
- "The universe always ends after we reach Centcomm.",
+ "The universe always ends after we reach CentCom.",
"Everyone is controlled by strings behind a glowing screen",
"Seperation is absolute.",
"It doesn't take much for people to murder their friends.",
"All the crew are just greytiders with different paint.",
- "What the fuck is CO2?",
- "2008 was 550 years ago.",
+ "What the fuck is carbon dioxide?",
+ "2010 was 550 years ago.",
"This is all an endless looping nightmare of misery.",
"The ultimate god is really really stoned.",
"Space stations are no substitute for healthy social interaction.",
@@ -33,11 +33,14 @@
"How do mirrors give people haircuts?",
"Why is this station so poorly designed?",
"How can an escape pod only take two people normally, but an infinite number of people if they're lying down?",
- "Why do only lizards get their own native language?",
"Why do people just randomly murder all their friends some shifts?",
"If magic is real, why aren't we researching that?",
"How is everyone a complete expert in every threat in the universe?",
"If suit sensors are so important, why don't they always start maximized?",
- "If we can wash clothes in a sink, why do we need washing machines?"
+ "If we can wash clothes in a sink, why do we need washing machines?",
+ "Why are the dormitories protected from radiation storms but the rest of the station isn't?",
+ "If people can have a dick that's twice their size, how come they don't die of bloodloss when they get hard?",
+ "How come immovable rods never get vaporized by the supermatter, but everything else does?",
+ "Why do I never have to use the bathroom?"
]
}