diff --git a/baystation12.dme b/baystation12.dme
index 05c88022914..7703467c4e0 100644
--- a/baystation12.dme
+++ b/baystation12.dme
@@ -217,6 +217,7 @@
#include "code\game\gamemodes\blob\blobs\node.dm"
#include "code\game\gamemodes\blob\blobs\resource.dm"
#include "code\game\gamemodes\blob\blobs\shield.dm"
+#include "code\game\gamemodes\borer\borer.dm"
#include "code\game\gamemodes\changeling\changeling.dm"
#include "code\game\gamemodes\changeling\changeling_powers.dm"
#include "code\game\gamemodes\changeling\modularchangling.dm"
diff --git a/code/game/gamemodes/borer/borer.dm b/code/game/gamemodes/borer/borer.dm
new file mode 100644
index 00000000000..bc09d35808d
--- /dev/null
+++ b/code/game/gamemodes/borer/borer.dm
@@ -0,0 +1,151 @@
+//This file was auto-corrected by findeclaration.exe on 29/05/2012 15:03:04
+// TOTALLY NOT COPY-PASTA FROM meme.dm
+
+/datum/game_mode/var/list/borers = list()
+
+/datum/game_mode/borer
+ name = "Cortical Borers"
+ config_tag = "borer"
+ required_players = 3
+ required_players_secret = 10
+ restricted_jobs = list("AI", "Cyborg", "Mobile MMI")
+ recommended_enemies = 2 // need at least a borer and a host
+ votable = 0 // temporarily disable this mode for voting
+
+ var/var/list/datum/mind/first_hosts = list()
+ var/var/list/assigned_hosts = list()
+
+ var/const/waittime_l = 600 //lower bound on time before intercept arrives (in tenths of seconds)
+ var/const/waittime_h = 1800 //upper bound on time before intercept arrives (in tenths of seconds)
+
+/datum/game_mode/borer/announce()
+ world << "The current game mode is - Cortical Borer!"
+ world << "An unknown creature has infested the mind of a crew member. Find and destroy it by any means necessary."
+
+/datum/game_mode/borer/can_start()
+ if(!..())
+ return 0
+
+ // for every 10 players, get 1 borer, and for each borer, get a host
+ // also make sure that there's at least one borer and one host
+ recommended_enemies = max(src.num_players() / 20 * 2, 2)
+
+ var/list/datum/mind/possible_borers = get_players_for_role(BE_ALIEN)
+
+ if(possible_borers.len < 2)
+ log_admin("MODE FAILURE: BORER. NOT ENOUGH BORER CANDIDATES.")
+ return 0 // not enough candidates for borer
+
+ // for each 2 possible borers, add one borer and one host
+ while(possible_borers.len >= 2)
+ var/datum/mind/borer = pick(possible_borers)
+ possible_borers.Remove(borer)
+
+ var/datum/mind/first_host = pick(possible_borers)
+ possible_borers.Remove(first_host)
+
+ modePlayer += borer
+ modePlayer += first_host
+ borers += borer
+ first_hosts += first_host
+
+ // so that we can later know which host belongs to which borer
+ assigned_hosts[borer.key] = first_host
+
+ borer.assigned_role = "MODE" //So they aren't chosen for other jobs.
+ borer.special_role = "Borer"
+
+ return 1
+
+/datum/game_mode/borer/pre_setup()
+ return 1
+
+
+/datum/game_mode/borer/post_setup()
+ // create a borer and enter it
+ for(var/datum/mind/borer in borers)
+ var/mob/living/simple_animal/borer/M = new(null,1) // loc, by_gamemode=0
+ var/mob/original = borer.current
+ borer.transfer_to(M)
+ //M.clearHUD()
+
+ // get the host for this borer
+ var/datum/mind/first_host = assigned_hosts[borer.key]
+ // this is a redundant check, but I don't think the above works..
+ // if picking hosts works with this method, remove the method above
+ if(!first_host)
+ first_host = pick(first_hosts)
+ first_hosts.Remove(first_host)
+ M.perform_infestation(first_host.current)
+ forge_borer_objectives(borer, first_host)
+
+ del original
+
+ log_admin("Created [borers.len] borers.")
+
+ spawn (rand(waittime_l, waittime_h))
+ send_intercept()
+ ..()
+ return
+
+/datum/game_mode/proc/greet_borer(var/datum/mind/borer, var/you_are=1)
+ if (you_are)
+ borer.current << "\red You are a Cortical Borer!"
+
+ var/obj_count = 1
+ for(var/datum/objective/objective in borer.objectives)
+ borer.current << "Objective #[obj_count]: [objective.explanation_text]"
+ obj_count++
+ return
+
+/datum/game_mode/borer/check_finished()
+ var/borers_alive = 0
+ for(var/datum/mind/borer in borers)
+ if(!istype(borer.current,/mob/living))
+ continue
+ if(borer.current.stat==2)
+ continue
+ borers_alive++
+
+ if (borers_alive)
+ return ..()
+ else
+ return 1
+
+/datum/game_mode/proc/auto_declare_completion_borer()
+ for(var/datum/mind/borer in borers)
+ var/borerwin = 1
+ if((borer.current) && istype(borer.current,/mob/living/simple_animal/borer))
+ world << "The borer was [borer.current.key]."
+ world << "The last host was [borer.current:host.key]."
+
+ var/count = 1
+ for(var/datum/objective/objective in borer.objectives)
+ if(objective.check_completion())
+ world << "Objective #[count]: [objective.explanation_text] \green Success"
+ feedback_add_details("borer_objective","[objective.type]|SUCCESS")
+ else
+ world << "Objective #[count]: [objective.explanation_text] \red Failed"
+ feedback_add_details("borer_objective","[objective.type]|FAIL")
+ borerwin = 0
+ count++
+
+ else
+ borerwin = 0
+
+ if(borerwin)
+ world << "The borer was successful!"
+ feedback_add_details("borer_success","SUCCESS")
+ else
+ world << "The borer has failed!"
+ feedback_add_details("borer_success","FAIL")
+ return 1
+
+/datum/game_mode/proc/forge_borer_objectives(var/datum/mind/borer, var/datum/mind/first_host)
+ var/datum/objective/survive/survive_objective = new
+ survive_objective.owner = borer
+ borer.objectives += survive_objective
+
+ greet_borer(borer)
+
+ return
\ No newline at end of file
diff --git a/code/modules/mob/living/simple_animal/borer.dm b/code/modules/mob/living/simple_animal/borer.dm
index 4bb00a415a7..970ddb27d77 100644
--- a/code/modules/mob/living/simple_animal/borer.dm
+++ b/code/modules/mob/living/simple_animal/borer.dm
@@ -16,11 +16,9 @@
src << "You whisper silently, \"[message]\""
B.host << "The captive mind of [src] whispers, \"[message]\""
- for (var/mob/M in player_list)
- if (istype(M, /mob/new_player))
- continue
- else if(M.stat == 2 && M.client.prefs.toggles & CHAT_GHOSTEARS)
- M << "The captive mind of [src] whispers, \"[message]\""
+ for(var/mob/M in mob_list)
+ if(M.mind && (istype(M, /mob/dead/observer)))
+ M << "Thought-speech, [src] -> [B.truename]: [message]"
/mob/living/captive_brain/emote(var/message)
return
@@ -94,12 +92,13 @@
if(prob(host.brainloss/20))
host.say("*[pick(list("blink","blink_r","choke","aflap","drool","twitch","twitch_s","gasp"))]")
-/mob/living/simple_animal/borer/New()
+/mob/living/simple_animal/borer/New(var/by_gamemode=0)
..()
truename = "[pick("Primary","Secondary","Tertiary","Quaternary")] [rand(1000,9999)]"
host_brain = new/mob/living/captive_brain(src)
- request_player()
+ if(!by_gamemode)
+ request_player()
/mob/living/simple_animal/borer/say(var/message)
@@ -136,11 +135,9 @@
src << "You drop words into [host]'s mind: \"[message]\""
host << "Your own thoughts speak: \"[message]\""
- for (var/mob/M in player_list)
- if (istype(M, /mob/new_player))
- continue
- else if(M.stat == 2 && M.client.prefs.toggles & CHAT_GHOSTEARS)
- M << "[src.truename] whispers to [host], \"[message]\""
+ for(var/mob/M in mob_list)
+ if(M.mind && (istype(M, /mob/dead/observer)))
+ M << "Thought-speech, [truename] -> [host]: [copytext(message, 2)]"
/mob/living/simple_animal/borer/Stat()
@@ -397,22 +394,25 @@ mob/living/simple_animal/borer/proc/detatch()
if(!M.stat)
M << "Something disgusting and slimy wiggles into your ear!"
- src.host = M
- src.loc = M
-
- if(istype(M,/mob/living/carbon/human))
- var/mob/living/carbon/human/H = M
- var/datum/organ/external/head = H.get_organ("head")
- head.implants += src
-
- host_brain.name = M.name
- host_brain.real_name = M.real_name
+ src.perform_infestation(M)
return
else
src << "They are no longer in range!"
return
+/mob/living/simple_animal/borer/proc/perform_infestation(var/mob/living/carbon/M)
+ src.host = M
+ src.loc = M
+
+ if(istype(M,/mob/living/carbon/human))
+ var/mob/living/carbon/human/H = M
+ var/datum/organ/external/head = H.get_organ("head")
+ head.implants += src
+
+ host_brain.name = M.name
+ host_brain.real_name = M.real_name
+
/mob/living/simple_animal/borer/verb/ventcrawl()
set name = "Crawl through Vent"
set desc = "Enter an air vent and crawl through the pipe system."