diff --git a/code/__DEFINES/borer_defines.dm b/code/__DEFINES/borer_defines.dm
new file mode 100644
index 000000000000..21db1f9cb127
--- /dev/null
+++ b/code/__DEFINES/borer_defines.dm
@@ -0,0 +1,63 @@
+#define JOB_BRAINWORM "Brainworm"
+
+/// Chemical categories
+#define BORER_CAT_HEAL "Medicines"
+#define BORER_CAT_PUNISH "Motivators"
+#define BORER_CAT_STIM "Stimulants"
+#define BORER_CAT_SELF "Self Protection"
+#define BORER_CAT_REPLICATED "Replicated"
+
+///Amount of chemicals needed for a borer to reproduce, provided reproduction is toggled.
+#define BORER_LARVAE_COST 400
+/// Amount of chemicals needed for a borer to replicate a chemical.
+#define BORER_REPLICATE_COST 350
+
+#define ACTION_SET_HOSTLESS "actions_hostless"
+#define ACTION_SET_HUMANOID "actions_human"
+#define ACTION_SET_XENO "actions_xeno"
+#define ACTION_SET_CONTROL "actions_control"
+
+/// Borer target bitflags
+#define BORER_TARGET_HUMANS (1<<0)
+#define BORER_TARGET_XENOS (1<<1)
+#define BORER_TARGET_YAUTJA (1<<2)
+
+DEFINE_BITFIELD(borer_flags_targets, list(
+ "TARGET_HUMANS" = BORER_TARGET_HUMANS,
+ "TARGET_XENOS" = BORER_TARGET_XENOS,
+ "TARGET_YAUTJA" = BORER_TARGET_YAUTJA,
+))
+
+/// Borer active/toggle-able ability flags.
+/// Middle of crawling into a new host
+#define BORER_PROCESS_INFESTING (1<<0)
+/// Middle of taking control of a host body
+#define BORER_PROCESS_BONDING (1<<1)
+/// Sleeps to purify contaminant
+#define BORER_ABILITY_HIBERNATING (1<<2)
+/// Hiding or not. (Changes layer)
+#define BORER_ABILITY_HIDE (1<<3)
+
+DEFINE_BITFIELD(borer_flags_actives, list(
+ "PROCESS_INFESTING" = BORER_PROCESS_INFESTING,
+ "PROCESS_BONDING" = BORER_PROCESS_BONDING,
+ "ACTIVE_HIBERNATING" = BORER_ABILITY_HIBERNATING,
+ "ACTIVE_HIDING" = BORER_ABILITY_HIDE,
+))
+
+///Borer is in control of their host.
+#define BORER_STATUS_CONTROLLING (1<<0)
+///Anti-Parasite or Anti-Enzyme chemicals can stop borers from acting.
+#define BORER_STATUS_DOCILE (1<<1)
+/// Middle of leaving a host
+#define BORER_STATUS_LEAVING (1<<2)
+
+DEFINE_BITFIELD(borer_flags_status, list(
+ "STATUS_CONTROLLING" = BORER_STATUS_CONTROLLING,
+ "STATUS_DOCILE" = BORER_STATUS_DOCILE,
+ "STATUS_LEAVING" = BORER_STATUS_LEAVING,
+))
+
+
+#define DEATH_CAUSE_PRIMARIES "No living Primaries."
+#define DEATH_CAUSE_UNKNOWN "Unknown"
diff --git a/code/__DEFINES/chemistry.dm b/code/__DEFINES/chemistry.dm
index 35e040654881..7d70f3c4d41a 100644
--- a/code/__DEFINES/chemistry.dm
+++ b/code/__DEFINES/chemistry.dm
@@ -84,6 +84,7 @@
#define CHEM_EFFECT_HYPER_THROTTLE (1<<2) //universal understand but not speech
#define CHEM_EFFECT_ORGAN_STASIS (1<<3) //peri stabiliser
#define CHEM_EFFECT_NO_BLEEDING (1<<4) //replacement for quickclot
+#define CHEM_EFFECT_ANTI_PARASITE (1<<5) //PROPERTY_ANTIPARASITIC
//Blood plasma
diff --git a/code/__DEFINES/language.dm b/code/__DEFINES/language.dm
index e4c4041a3dda..6b438b030879 100644
--- a/code/__DEFINES/language.dm
+++ b/code/__DEFINES/language.dm
@@ -15,6 +15,7 @@
#define LANGUAGE_APOLLO "APOLLO Link"
#define LANGUAGE_TELEPATH "Telepath Implant"
+#define LANGUAGE_BORER "Cortical Link"
#define ALL_HUMAN_LANGUAGES list(LANGUAGE_ENGLISH, LANGUAGE_JAPANESE, LANGUAGE_CHINESE, LANGUAGE_RUSSIAN, LANGUAGE_GERMAN, LANGUAGE_SPANISH)
diff --git a/code/__DEFINES/mob_hud.dm b/code/__DEFINES/mob_hud.dm
index 97cbe0281924..a9fd8dec8285 100644
--- a/code/__DEFINES/mob_hud.dm
+++ b/code/__DEFINES/mob_hud.dm
@@ -27,6 +27,7 @@
#define HUNTER_CLAN "25" //Displays a colored icon to represent ingame Hunter Clans
#define HUNTER_HUD "26" //Displays various statuses on mobs for Hunters to identify targets
#define HOLOCARD_HUD "27" //Displays the holocards set by medical personnel
+#define HUD_BRAINWORM "28" //Displays infested HUD for brainworms.
//data HUD (medhud, sechud) defines
#define MOB_HUD_SECURITY_BASIC 1
@@ -47,6 +48,7 @@
#define MOB_HUD_HUNTER 16
#define MOB_HUD_HUNTER_CLAN 17
#define MOB_HUD_EXECUTE 18
+#define MOB_HUD_BRAINWORM 19
//for SL/FTL/LZ targeting on locator huds
#define TRACKER_SL "track_sl"
diff --git a/code/__DEFINES/typecheck/xenos.dm b/code/__DEFINES/typecheck/xenos.dm
index 34b70ac92f45..ea981a9e02bf 100644
--- a/code/__DEFINES/typecheck/xenos.dm
+++ b/code/__DEFINES/typecheck/xenos.dm
@@ -1,5 +1,7 @@
//Xenomorph Hud Test APOPHIS 22MAY2015
#define isxeno(A) (istype(A, /mob/living/carbon/xenomorph))
+#define isborer(A) (istype(A, /mob/living/carbon/cortical_borer))
+#define iscaptivemind(A) (istype(A, /mob/living/captive_brain))
#define isxeno_human(A) (isxeno(A) || ishuman(A))
//ask walter if i should turn into castechecks
diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm
index d8eebf79bca6..0ee91a4d880c 100644
--- a/code/__HELPERS/unsorted.dm
+++ b/code/__HELPERS/unsorted.dm
@@ -345,6 +345,10 @@
moblist.Add(M)
for(var/mob/living/carbon/xenomorph/M in sortmob)
moblist.Add(M)
+ for(var/mob/living/carbon/cortical_borer/M in sortmob)
+ moblist.Add(M)
+ for(var/mob/living/captive_brain/M in sortmob)
+ moblist.Add(M)
for(var/mob/dead/observer/M in sortmob)
moblist.Add(M)
for(var/mob/new_player/M in sortmob)
diff --git a/code/datums/emergency_calls/custom.dm b/code/datums/emergency_calls/custom.dm
index b62d984f6fe3..fcd1595fa17c 100644
--- a/code/datums/emergency_calls/custom.dm
+++ b/code/datums/emergency_calls/custom.dm
@@ -28,7 +28,7 @@
return
M.transfer_to(H, TRUE)
-
+ to_chat(H, SPAN_ALERT("[objectives]"))
players_to_offer -= H
return
diff --git a/code/datums/entities/player_times.dm b/code/datums/entities/player_times.dm
index 4fc28ba2fa5e..4b83546c801e 100644
--- a/code/datums/entities/player_times.dm
+++ b/code/datums/entities/player_times.dm
@@ -119,7 +119,7 @@ BSQL_PROTECT_DATUM(/datum/entity/player_time)
for(var/datum/view_record/playtime/PT in PTs)
var/isxeno = (PT.role_id in GLOB.RoleAuthority.castes_by_name)
- var/isOther = (PT.role_id == JOB_OBSERVER) // more maybe eventually
+ var/isOther = (PT.role_id in GLOB.RoleAuthority.other_roles) // more maybe eventually
if(PT.role_id == JOB_XENOMORPH)
continue // Snowflake check, will need to be removed in the future
diff --git a/code/datums/mob_hud.dm b/code/datums/mob_hud.dm
index 603f9a05d702..544fe0e7dcb5 100644
--- a/code/datums/mob_hud.dm
+++ b/code/datums/mob_hud.dm
@@ -20,6 +20,7 @@ GLOBAL_LIST_INIT_TYPED(huds, /datum/mob_hud, list(
MOB_HUD_HUNTER = new /datum/mob_hud/hunter_hud(),
MOB_HUD_HUNTER_CLAN = new /datum/mob_hud/hunter_clan(),
MOB_HUD_EXECUTE = new /datum/mob_hud/execute_hud(),
+ MOB_HUD_BRAINWORM = new /datum/mob_hud/brainworm(),
))
/datum/mob_hud
@@ -152,7 +153,7 @@ GLOBAL_LIST_INIT_TYPED(huds, /datum/mob_hud, list(
//medical hud used by ghosts
/datum/mob_hud/medical/observer
- hud_icons = list(HEALTH_HUD, STATUS_HUD_OOC, STATUS_HUD_XENO_CULTIST)
+ hud_icons = list(HEALTH_HUD, STATUS_HUD_OOC, STATUS_HUD_XENO_CULTIST, HUD_BRAINWORM)
//infection status that appears on humans, viewed by xenos only and observers.
@@ -177,6 +178,8 @@ GLOBAL_LIST_INIT_TYPED(huds, /datum/mob_hud, list(
/datum/mob_hud/hunter_hud
hud_icons = list(HUNTER_HUD)
+/datum/mob_hud/brainworm
+ hud_icons = list(HEALTH_HUD_XENO, PLASMA_HUD, PHEROMONE_HUD, QUEEN_OVERWATCH_HUD, ARMOR_HUD_XENO, XENO_STATUS_HUD, XENO_BANISHED_HUD, HEALTH_HUD, STATUS_HUD_OOC, STATUS_HUD_XENO_CULTIST, HUD_BRAINWORM)
//Security
/datum/mob_hud/security
@@ -233,7 +236,7 @@ GLOBAL_LIST_INIT_TYPED(huds, /datum/mob_hud, list(
/mob/living/carbon/xenomorph/add_to_all_mob_huds()
for(var/datum/mob_hud/hud in GLOB.huds)
- if(!istype(hud, /datum/mob_hud/xeno))
+ if(!istype(hud, /datum/mob_hud/xeno) && !istype(hud, /datum/mob_hud/brainworm))
continue
hud.add_to_hud(src)
@@ -253,7 +256,7 @@ GLOBAL_LIST_INIT_TYPED(huds, /datum/mob_hud, list(
/mob/living/carbon/xenomorph/remove_from_all_mob_huds()
for(var/datum/mob_hud/hud in GLOB.huds)
- if(istype(hud, /datum/mob_hud/xeno))
+ if(istype(hud, /datum/mob_hud/xeno) || istype(hud, /datum/mob_hud/brainworm))
hud.remove_from_hud(src)
hud.remove_hud_from(src, src)
else if (istype(hud, /datum/mob_hud/xeno_infection))
@@ -297,6 +300,7 @@ GLOBAL_LIST_INIT_TYPED(huds, /datum/mob_hud, list(
CRASH("hud_list lacks HEALTH_HUD_XENO despite not being deleted in med_hud_set_health()")
var/image/holder = hud_list[HEALTH_HUD_XENO]
+ var/image/holder2 = hud_list[HUD_BRAINWORM]
var/health_hud_type = "xenohealth"
if(stat == DEAD)
@@ -312,6 +316,19 @@ GLOBAL_LIST_INIT_TYPED(huds, /datum/mob_hud, list(
amount = -1 //don't want the 'zero health' icon when we are crit
holder.icon_state = "[health_hud_type][amount]"
+ holder2.icon_state = null
+ if(has_brain_worms())
+ var/worm_icon = "hudbrainwormhost"
+ switch(borer.generation)
+ if(0)
+ worm_icon = "hudbrainwormhostb"
+ if(1)
+ worm_icon = "hudbrainwormhostg"
+ holder2.icon_state = worm_icon
+ holder2.pixel_x = 9
+ holder2.pixel_y = -8
+
+
/mob/living/carbon/xenomorph/proc/overlay_shields()
var/image/holder = hud_list[HEALTH_HUD_XENO]
holder.overlays.Cut()
@@ -374,10 +391,12 @@ GLOBAL_LIST_INIT_TYPED(huds, /datum/mob_hud, list(
holder2.overlays.Cut()
var/image/holder3 = hud_list[STATUS_HUD_XENO_INFECTION]
var/image/holder4 = hud_list[STATUS_HUD_XENO_CULTIST]
+ var/image/holder5 = hud_list[HUD_BRAINWORM]
holder2.color = null
holder3.color = null
holder4.color = null
+ holder5.color = null
holder2.alpha = alpha
holder3.alpha = alpha
@@ -491,6 +510,21 @@ GLOBAL_LIST_INIT_TYPED(huds, /datum/mob_hud, list(
return
+ var/mob/living/carbon/cortical_borer/brainworm = has_brain_worms()
+ holder5.icon_state = null
+ if(brainworm)
+ var/worm_icon = "hudbrainwormhost"
+ switch(brainworm.generation)
+ if(0)
+ worm_icon = "hudbrainwormhostb"
+ if(1)
+ worm_icon = "hudbrainwormhostg"
+ holder5.icon_state = worm_icon
+ if(brainworm.borer_flags_status & BORER_STATUS_CONTROLLING)
+ holder.icon_state = "hudbrainworm"
+ if(!holder2_set)
+ holder2.icon_state = "hudbrainworm"
+ return
for(var/datum/disease/D in viruses)
if(!D.hidden[SCANNER])
diff --git a/code/game/jobs/role_authority.dm b/code/game/jobs/role_authority.dm
index f32860c06d2c..ccd8d2f6ae70 100644
--- a/code/game/jobs/role_authority.dm
+++ b/code/game/jobs/role_authority.dm
@@ -38,6 +38,7 @@ GLOBAL_VAR_INIT(players_preassigned, 0)
var/list/roles_for_mode //Derived list of roles only for the game mode, generated when the round starts.
var/list/castes_by_path //Master list generated when role aithority is created, listing every caste by path.
var/list/castes_by_name //Master list generated when role authority is created, listing every default caste by name.
+ var/list/other_roles = list(JOB_OBSERVER, JOB_BRAINWORM)
/// List of mapped roles that should be used in place of usual ones
var/list/role_mappings
diff --git a/code/game/machinery/medical_pod/bodyscanner.dm b/code/game/machinery/medical_pod/bodyscanner.dm
index 54b454f945a8..b148d23d5197 100644
--- a/code/game/machinery/medical_pod/bodyscanner.dm
+++ b/code/game/machinery/medical_pod/bodyscanner.dm
@@ -386,6 +386,9 @@
if(occ["sdisabilities"] & NEARSIGHTED)
dat += SET_CLASS("Retinal misalignment detected.", INTERFACE_RED)
dat += "
"
+ if(connected.occupant.has_brain_worms())
+ dat += SET_CLASS("Cranial anomoly detected.", INTERFACE_RED)
+ dat += "
"
dat += "