diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm
index 1372e99a8e..1b239f5fc6 100644
--- a/code/__DEFINES/is_helpers.dm
+++ b/code/__DEFINES/is_helpers.dm
@@ -76,6 +76,8 @@
#define isrevenant(A) (istype(A, /mob/living/simple_animal/revenant))
+#define isborer(A) (istype(A, /mob/living/simple_animal/borer))
+
#define isbot(A) (istype(A, /mob/living/simple_animal/bot))
#define iscrab(A) (istype(A, /mob/living/simple_animal/crab))
diff --git a/code/__DEFINES/role_preferences.dm b/code/__DEFINES/role_preferences.dm
index 86fa509e30..cb4d552e5d 100644
--- a/code/__DEFINES/role_preferences.dm
+++ b/code/__DEFINES/role_preferences.dm
@@ -23,6 +23,7 @@
#define ROLE_REVENANT "revenant"
#define ROLE_DEVIL "devil"
#define ROLE_SERVANT_OF_RATVAR "servant of Ratvar"
+#define ROLE_BORER "borer"
//Missing assignment means it's not a gamemode specific role, IT'S NOT A BUG OR ERROR.
//The gamemode specific ones are just so the gamemodes can query whether a player is old enough
@@ -44,6 +45,7 @@ GLOBAL_LIST_INIT(special_roles, list(
ROLE_REVENANT,
ROLE_ABDUCTOR = /datum/game_mode/abduction,
ROLE_DEVIL = /datum/game_mode/devil,
+ ROLE_BORER,
ROLE_SERVANT_OF_RATVAR = /datum/game_mode/clockwork_cult
))
diff --git a/code/datums/mutations.dm b/code/datums/mutations.dm
index 5b44fd966f..df124260fe 100644
--- a/code/datums/mutations.dm
+++ b/code/datums/mutations.dm
@@ -377,6 +377,9 @@ GLOBAL_LIST_EMPTY(mutations_list)
time_coeff = 2
/datum/mutation/human/race/on_acquiring(mob/living/carbon/human/owner)
+ if(owner.has_brain_worms())
+ to_chat(owner, "You feel something strongly clinging to your humanity!")
+ return
if(..())
return
. = owner.monkeyize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_KEEPSE)
diff --git a/code/game/data_huds.dm b/code/game/data_huds.dm
index 2821356db5..2e5854509a 100644
--- a/code/game/data_huds.dm
+++ b/code/game/data_huds.dm
@@ -162,11 +162,14 @@
var/image/holder = hud_list[STATUS_HUD]
var/icon/I = icon(icon, icon_state, dir)
var/virus_state = check_virus()
+ var/mob/living/simple_animal/borer/B = has_brain_worms()
holder.pixel_y = I.Height() - world.icon_size
if(status_flags & XENO_HOST)
holder.icon_state = "hudxeno"
else if(stat == DEAD || (status_flags & FAKEDEATH))
holder.icon_state = "huddead"
+ else if(has_brain_worms() && B != null && B.controlling)
+ holder.icon_state = "hudbrainworm"
else if(virus_state == 2)
holder.icon_state = "hudill"
else if(virus_state == 1)
diff --git a/code/game/gamemodes/antag_spawner_cit.dm b/code/game/gamemodes/antag_spawner_cit.dm
index 1009d9706f..175ad0e8a4 100644
--- a/code/game/gamemodes/antag_spawner_cit.dm
+++ b/code/game/gamemodes/antag_spawner_cit.dm
@@ -4,6 +4,7 @@ obj/item/weapon/antag_spawner/syndi_borer
desc = "Releases a modified cortical borer to assist the user."
icon = 'icons/obj/device.dmi' //Temporary? Doesn't really look like a container for xenofauna... but IDK what else could work.
icon_state = "locator"
+ var/polling = FALSE
obj/item/weapon/antag_spawner/syndi_borer/spawn_antag(client/C, turf/T, mob/owner)
var/mob/living/simple_animal/borer/syndi_borer/B = new /mob/living/simple_animal/borer/syndi_borer(T)
@@ -31,14 +32,18 @@ obj/item/weapon/antag_spawner/syndi_borer/spawn_antag(client/C, turf/T, mob/owne
if(used)
to_chat(user, "[src] appears to be empty!")
return 0
+ if(polling == TRUE)
+ to_chat(user, "[src] is busy activating!")
+ return 0
return 1
/obj/item/weapon/antag_spawner/syndi_borer/attack_self(mob/user)
if(!(check_usability(user)))
return
-
+ polling = TRUE
var/list/borer_candidates = pollCandidatesForMob("Do you want to play as a syndicate cortical borer?", ROLE_BORER, null, ROLE_BORER, 150, src)
if(borer_candidates.len)
+ polling = FALSE
if(!(check_usability(user)))
return
used = 1
@@ -49,4 +54,5 @@ obj/item/weapon/antag_spawner/syndi_borer/spawn_antag(client/C, turf/T, mob/owne
S.start()
qdel(src)
else
+ polling = FALSE
to_chat(user, "Unable to connect to release specimen. Please wait and try again later or use the container on your uplink to get your points refunded.")
\ No newline at end of file
diff --git a/code/game/gamemodes/changeling/powers/panacea.dm b/code/game/gamemodes/changeling/powers/panacea.dm
index a0c9562aa4..40ce63a60e 100644
--- a/code/game/gamemodes/changeling/powers/panacea.dm
+++ b/code/game/gamemodes/changeling/powers/panacea.dm
@@ -10,6 +10,17 @@
/obj/effect/proc_holder/changeling/panacea/sting_action(mob/user)
to_chat(user, "We cleanse impurities from our form.")
+
+ var/mob/living/simple_animal/borer/B = user.has_brain_worms()
+ if(B)
+ if(B.controlling)
+ B.detatch()
+ B.leave_victim()
+ if(iscarbon(user))
+ var/mob/living/carbon/C = user
+ C.vomit(0, toxic = TRUE)
+ to_chat(user, "A parasite exits our form.")
+
var/list/bad_organs = list(
user.getorgan(/obj/item/organ/body_egg),
user.getorgan(/obj/item/organ/zombie_infection))
diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm
index b906386d65..349656d48b 100644
--- a/code/game/gamemodes/game_mode.dm
+++ b/code/game/gamemodes/game_mode.dm
@@ -269,6 +269,42 @@
if(cult.len && !istype(SSticker.mode,/datum/game_mode/cult))
datum_cult_completion()
+
+ if(GLOB.borers.len)
+ var/borerwin = FALSE
+ var/borertext = "
The borers were:"
+ for(var/mob/living/simple_animal/borer/B in GLOB.borers)
+ if((B.key || B.controlling) && B.stat != DEAD)
+ borertext += "
[B.controlling ? B.victim.key : B.key] was [B.truename] ("
+ var/turf/location = get_turf(B)
+ if(location.z == ZLEVEL_CENTCOM && B.victim)
+ borertext += "escaped with host"
+ else
+ borertext += "failed"
+ borertext += ")"
+ to_chat(world, borertext)
+
+ var/total_borers = 0
+ for(var/mob/living/simple_animal/borer/B in GLOB.borers)
+ if((B.key || B.victim) && B.stat != DEAD)
+ total_borers++
+ if(total_borers)
+ var/total_borer_hosts = 0
+ for(var/mob/living/carbon/C in GLOB.mob_list)
+ var/mob/living/simple_animal/borer/D = C.has_brain_worms()
+ var/turf/location = get_turf(C)
+ if(location.z == ZLEVEL_CENTCOM && D && D.stat != DEAD)
+ total_borer_hosts++
+ if(GLOB.total_borer_hosts_needed <= total_borer_hosts)
+ borerwin = TRUE
+ to_chat(world, "There were [total_borers] borers alive at round end!")
+ to_chat(world, "A total of [total_borer_hosts] borers with hosts escaped on the shuttle alive. The borers needed [GLOB.total_borer_hosts_needed] hosts to escape.")
+ if(borerwin)
+ to_chat(world, "The borers were successful!")
+ else
+ to_chat(world, "The borers have failed!")
+
+ CHECK_TICK
return 0
diff --git a/code/game/gamemodes/miniantags/borer/borer.dm b/code/game/gamemodes/miniantags/borer/borer.dm
index 92cff03ec9..7a88a3306c 100644
--- a/code/game/gamemodes/miniantags/borer/borer.dm
+++ b/code/game/gamemodes/miniantags/borer/borer.dm
@@ -59,6 +59,7 @@ GLOBAL_VAR_INIT(total_borer_hosts_needed, 10)
name = "cortical borer"
real_name = "cortical borer"
desc = "A small, quivering, slug-like creature."
+ icon = 'icons/mob/borer.dmi'
icon_state = "brainslug"
icon_living = "brainslug"
icon_dead = "brainslug_dead"
@@ -512,7 +513,7 @@ GLOBAL_VAR_INIT(total_borer_hosts_needed, 10)
to_chat(src, "You focus your psychic lance on [M] and freeze their limbs with a wave of terrible dread.")
to_chat(M, "You feel a creeping, horrible sense of dread come over you, freezing your limbs and setting your heart racing.")
- M.Stun(3)
+ M.Stun(60)
used_dominate = world.time
@@ -613,9 +614,9 @@ GLOBAL_VAR_INIT(total_borer_hosts_needed, 10)
victim.setToxLoss(0)
victim.setOxyLoss(0)
victim.setCloneLoss(0)
- victim.SetParalysis(0)
- victim.SetStunned(0)
- victim.SetWeakened(0)
+ victim.SetUnconscious(0)
+ victim.SetStun(0)
+ victim.SetKnockdown(0)
victim.radiation = 0
victim.heal_overall_damage(victim.getBruteLoss(), victim.getFireLoss())
victim.reagents.clear_reagents()
@@ -768,11 +769,11 @@ GLOBAL_VAR_INIT(total_borer_hosts_needed, 10)
switch(punishment) //Hardcoding this stuff.
if("Blindness")
- victim.blind_eyes(2)
+ victim.blind_eyes(4)
if("Deafness")
- victim.minimumDeafTicks(20)
+ victim.minimumDeafTicks(40)
if("Stun")
- victim.Weaken(10)
+ victim.Knockdown(100)
log_game("[src]/([src.ckey]) punished [victim]/([victim.ckey] with [punishment]")
diff --git a/code/game/gamemodes/miniantags/readme.txt b/code/game/gamemodes/miniantags/readme.txt
index 8ade34bf2e..dc7bd5a66f 100644
--- a/code/game/gamemodes/miniantags/readme.txt
+++ b/code/game/gamemodes/miniantags/readme.txt
@@ -1,6 +1,7 @@
This folder contains all "mini-antagonists" - antagonists that can still spice up the round but aren't enough to be a roundtype in their own right.
Currently, that list consists of:
-Abductors
+ -Borers
-Swarmers
-Prophets of sin
-The Jungle Fever virus (infected monkey bites human, human becomes another infected monkey)
diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm
index 5b3dfbb994..70b6d54f73 100644
--- a/code/game/objects/items/devices/scanners.dm
+++ b/code/game/objects/items/devices/scanners.dm
@@ -120,6 +120,11 @@ MASS SPECTROMETER
if(H.undergoing_cardiac_arrest() && H.stat != DEAD)
to_chat(user, "Subject suffering from heart attack: Apply defibrillator immediately!")
+ if(iscarbon(M))
+ var/mob/living/carbon/C = M
+ if(C.has_brain_worms())
+ to_chat(user, "Foreign organism detected in subject's cranium. Recommended treatment: Dosage of sucrose solution and removal of object via surgery.")
+
to_chat(user, "Analyzing results for [M]:\n\tOverall status: [mob_status]")
// Damage descriptions
diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm
index 66b17af462..ae37d0f9a1 100644
--- a/code/modules/admin/topic.dm
+++ b/code/modules/admin/topic.dm
@@ -835,6 +835,12 @@
else
dat += "