diff --git a/baystation12.dme b/baystation12.dme index 9348f106ce0..b82ce97a578 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -1005,6 +1005,7 @@ #include "code\modules\mob\living\silicon\robot\robot_movement.dm" #include "code\modules\mob\living\silicon\robot\say.dm" #include "code\modules\mob\living\silicon\robot\wires.dm" +#include "code\modules\mob\living\simple_animal\borer.dm" #include "code\modules\mob\living\simple_animal\constructs.dm" #include "code\modules\mob\living\simple_animal\corpse.dm" #include "code\modules\mob\living\simple_animal\parrot.dm" diff --git a/code/game/gamemodes/autotraitor/autotraitor.dm b/code/game/gamemodes/autotraitor/autotraitor.dm index 74bced44214..de795b19222 100644 --- a/code/game/gamemodes/autotraitor/autotraitor.dm +++ b/code/game/gamemodes/autotraitor/autotraitor.dm @@ -4,7 +4,7 @@ /datum/game_mode/traitor/autotraitor name = "AutoTraitor" - config_tag = "Extend-A-Traitormongous" + config_tag = "extend-a-traitormongous" var/list/possible_traitors var/num_players = 0 diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index bb627fd3bcf..a78e8dd8ae0 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -17,7 +17,7 @@ var/config_tag = null var/intercept_hacked = 0 var/votable = 1 - var/probability = 1 + var/probability = 0 var/station_was_nuked = 0 //see nuclearbomb.dm and malfunction.dm var/explosion_in_progress = 0 //sit back and relax var/list/datum/mind/modePlayer = new diff --git a/code/game/gamemodes/heist/heist.dm b/code/game/gamemodes/heist/heist.dm index 878f600e44b..5a1e12a191b 100644 --- a/code/game/gamemodes/heist/heist.dm +++ b/code/game/gamemodes/heist/heist.dm @@ -7,6 +7,9 @@ VOX HEIST ROUNDTYPE var/global/vox_kills = 0 //Used to check the Inviolate. +/datum/game_mode/ + var/list/datum/mind/raiders = list() //Antags. + /datum/game_mode/heist name = "heist" config_tag = "heist" @@ -19,7 +22,6 @@ var/global/vox_kills = 0 //Used to check the Inviolate. var/const/waittime_h = 1800 //upper bound on time before intercept arrives (in tenths of seconds) var/list/raid_objectives = list() //Raid objectives. - var/list/datum/mind/raiders = list() //Antags. var/list/obj/cortical_stacks = list() //Stacks for 'leave nobody behind' objective. /datum/game_mode/heist/announce() diff --git a/code/game/machinery/podmen.dm b/code/game/machinery/podmen.dm index 2fe409dcfb5..1e8eb4e5368 100644 --- a/code/game/machinery/podmen.dm +++ b/code/game/machinery/podmen.dm @@ -12,7 +12,7 @@ Growing it to term with nothing injected will grab a ghost from the observers. * productname = "/mob/living/carbon/human" //verrry special -- Urist lifespan = 50 //no idea what those do endurance = 8 - maturation = 10 + maturation = 5 production = 10 yield = 1 //seeds if there isn't a dna inside oneharvest = 1 diff --git a/code/modules/admin/player_panel.dm b/code/modules/admin/player_panel.dm index e932ab856eb..44f1cfdd820 100644 --- a/code/modules/admin/player_panel.dm +++ b/code/modules/admin/player_panel.dm @@ -469,6 +469,13 @@ dat += "Wizard not found!" dat += "" + if(ticker.mode.raiders.len > 0) + for(var/datum/mind/raider in ticker.mode.raiders) + var/mob/M = raider.current + if(M) + dat += "[M.real_name][M.client ? "" : " (logged out)"][M.stat == 2 ? " (DEAD)" : ""]" + dat += "PM" + dat += "Show Objective" /* if(ticker.mode.ninjas.len > 0) dat += "
" diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm index e20829aab85..095695e23d8 100644 --- a/code/modules/mob/living/carbon/human/death.dm +++ b/code/modules/mob/living/carbon/human/death.dm @@ -54,6 +54,25 @@ dizziness = 0 jitteriness = 0 + //Handle brain slugs. + var/datum/organ/external/head = get_organ("head") + var/mob/living/simple_animal/borer/B + + for(var/I in head.implants) + if(istype(I,/mob/living/simple_animal/borer)) + B = I + if(B) + if(!B.ckey && ckey && B.controlling) + B.ckey = ckey + B.controlling = 0 + if(B.host_brain.ckey) + ckey = B.host_brain.ckey + B.host_brain.ckey = null + B.host_brain.name = "host brain" + B.host_brain.real_name = "host brain" + + verbs -= /mob/living/carbon/human/proc/release_control + //Check for heist mode kill count. if(ticker.mode && ( istype( ticker.mode,/datum/game_mode/heist) ) ) //Check for last assailant's mutantrace. diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index df8dec56156..f70d3956b03 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -1274,3 +1274,83 @@ mob/living/carbon/human/yank_out_object() return 1 else return 0 + +//Brain slug proc for voluntary removal of control. +/mob/living/carbon/human/proc/release_control() + + set category = "Alien" + set name = "Release Control" + set desc = "Release control of your host's body." + + var/datum/organ/external/head = get_organ("head") + var/mob/living/simple_animal/borer/B + + for(var/I in head.implants) + if(istype(I,/mob/living/simple_animal/borer)) + B = I + if(!B) + return + + if(B.controlling) + src << "\red You withdraw your probosci, releasing control of [B.host_brain]" + B.host_brain << "\red Your vision swims as the alien parasite releases control of your body." + B.ckey = ckey + B.controlling = 0 + if(B.host_brain.ckey) + ckey = B.host_brain.ckey + B.host_brain.ckey = null + B.host_brain.name = "host brain" + B.host_brain.real_name = "host brain" + + verbs -= /mob/living/carbon/human/proc/release_control + verbs -= /mob/living/carbon/human/proc/punish_host + verbs -= /mob/living/carbon/human/proc/spawn_larvae + +//Brain slug proc for tormenting the host. +/mob/living/carbon/human/proc/punish_host() + set category = "Alien" + set name = "Torment host" + set desc = "Punish your host with agony." + + var/mob/living/simple_animal/borer/B = has_brain_worms() + + if(!B) + return + + if(B.host_brain.ckey) + src << "\red You send a punishing spike of psychic agony lancing into your host's brain." + B.host_brain << "\red Horrific, burning agony lances through you, ripping a soundless scream from your trapped mind!" + +//Check for brain worms in head. +/mob/living/carbon/human/proc/has_brain_worms() + + var/datum/organ/external/head = get_organ("head") + + for(var/I in head.implants) + if(istype(I,/mob/living/simple_animal/borer)) + return I + + return 0 + +/mob/living/carbon/human/proc/spawn_larvae() + set category = "Alien" + set name = "Reproduce" + set desc = "Spawn several young." + + var/mob/living/simple_animal/borer/B = has_brain_worms() + + if(!B) + return + + if(B.chemicals >= 100) + src << "\red Your host twitches and quivers as you rapdly excrete several larvae from your sluglike body." + visible_message("\red [src] heaves violently, expelling a rush of vomit and a wriggling, sluglike creature!") + B.chemicals -= 100 + + new /obj/effect/decal/cleanable/vomit(get_turf(src)) + playsound(loc, 'sound/effects/splat.ogg', 50, 1) + new /mob/living/simple_animal/borer(get_turf(src)) + + else + src << "You do not have enough chemicals stored to reproduce." + return \ No newline at end of file diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index b7ac6233556..a73e7230bf1 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -384,6 +384,12 @@ var/list/department_radio_keys = list( if(understood || P.universal_speak) //world << "[M] understood [src] (1)." heard_a += M + else if(istype(P,/mob/living/carbon/human)) + var/mob/living/carbon/human/H = P + if(H.has_brain_worms()) // Brain worms act like Babelfish. + heard_a += M + else + heard_b += M else //world << "[M] didn't understand [src]." heard_b += M diff --git a/code/modules/mob/living/simple_animal/borer.dm b/code/modules/mob/living/simple_animal/borer.dm new file mode 100644 index 00000000000..46ff70493c9 --- /dev/null +++ b/code/modules/mob/living/simple_animal/borer.dm @@ -0,0 +1,268 @@ +/mob/living/captive_brain + name = "host brain" + real_name = "host brain" + +/mob/living/captive_brain/say(var/message) + + if (src.client) + if(client.prefs.muted & MUTE_IC) + src << "\red You cannot speak in IC (muted)." + return + if (src.client.handle_spam_prevention(message,MUTE_IC)) + return + + if(istype(src.loc,/mob/living/simple_animal/borer)) + var/mob/living/simple_animal/borer/B = src.loc + src << "You whisper silently, \"[message]\"" + B.host << "The captive mind of [src] whispers, \"[message]\"" + +/mob/living/captive_brain/emote(var/message) + return + +/mob/living/simple_animal/borer + name = "cortical borer" + real_name = "cortical borer" + desc = "A small, quivering sluglike creature." + speak_emote = list("chirrups") + emote_hear = list("chirrups") + response_help = "pokes the" + response_disarm = "prods the" + response_harm = "stomps on the" + icon_state = "brainslug" + icon_living = "brainslug" + icon_dead = "brainslug_dead" + speed = 5 + a_intent = "harm" + stop_automated_movement = 1 + status_flags = CANPUSH + attacktext = "nips" + friendly = "prods" + wander = 0 + + var/chemicals = 10 // Chemicals used for reproduction and spitting neurotoxin. + var/mob/living/carbon/human/host // Human host for the brain worm. + var/truename // Name used for brainworm-speak. + var/bonded // Var for full bonding with the host brain. + var/mob/living/captive_brain/host_brain // Used for swapping control of the body back and forth. + var/controlling // Used in human death check. + +/mob/living/simple_animal/borer/Life() + + ..() + if(host) + if(!stat && !host.stat) + if(chemicals < 250) + chemicals++ + if(controlling) + if(prob(5)) + host.adjustBrainLoss(rand(1,2)) + + if(prob(host.brainloss/20)) + host.say("*[pick(list("blink","blink_r","choke","aflap","drool","twitch","twitch_s","gasp"))]") + + //if(host.brainloss > 100) + +/mob/living/simple_animal/borer/New() + ..() + truename = "[pick("Primary","Secondary","Tertiary","Quaternary")] [rand(1000,9999)]" + host_brain = new/mob/living/captive_brain(src) + + for(var/mob/M in player_list) + if(istype(M,/mob/dead/observer)) + var/mob/dead/observer/O = M + if(O.client) + if(O.client.prefs.be_special & BE_ALIEN) + src.ckey = O.ckey + break + + +/mob/living/simple_animal/borer/say(var/message) + + message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN)) + message = capitalize(message) + + if(!message) + return + + if (stat == 2) + return say_dead(message) + + if (stat) + return + + if (src.client) + if(client.prefs.muted & MUTE_IC) + src << "\red You cannot speak in IC (muted)." + return + if (src.client.handle_spam_prevention(message,MUTE_IC)) + return + + if (copytext(message, 1, 2) == "*") + return emote(copytext(message, 2)) + + if (copytext(message, 1, 2) == ";") //Brain borer hivemind. + return borer_speak(message) + + if(!host) + src << "You have no host to speak to." + return //No host, no audible speech. + + src << "You drop words into [host]'s mind: \"[message]\"" + host << "Your own thoughts speak: \"[message]\"" + +/mob/living/simple_animal/borer/proc/borer_speak(var/message) + if(!message) + return + + for(var/mob/M in mob_list) + if(M.mind && (istype(M, /mob/living/simple_animal/borer) || istype(M, /mob/dead/observer))) + M << "Cortical link, [truename]: [copytext(message, 2)]" + +/mob/living/simple_animal/borer/verb/bond_brain() + set category = "Alien" + set name = "Assume Control" + set desc = "Fully connect to the brain of your host." + + if(!host) + src << "You are not inside a host body." + return + + if(src.stat) + src << "You cannot do that in your current state." + return + + src << "You begin delicately adjusting your connection to the host brain..." + + spawn(300+(host.brainloss*5)) + + if(!host || !src) return + + else + src << "\red You plunge your probosci deep into the cortex of the host brain, interfacing directly with their nervous system." + host << "\red You feel a strange shifting sensation behind your eyes as an alien consciousness displaces yours." + + host_brain.ckey = host.ckey + host.ckey = src.ckey + controlling = 1 + + host.verbs += /mob/living/carbon/human/proc/release_control + host.verbs += /mob/living/carbon/human/proc/punish_host + host.verbs += /mob/living/carbon/human/proc/spawn_larvae + +mob/living/simple_animal/borer/verb/release_host() + set category = "Alien" + set name = "Release Host" + set desc = "Slither out of your host." + + if(!host) + src << "You are not inside a host body." + return + + if(stat) + src << "You cannot leave your host in your current state." + + + if(!host || !src) return + + src << "You begin disconnecting from [host]'s synapses and prodding at their internal ear canal." + bonded = 0 + + if(!host.stat) + host << "An odd, uncomfortable pressure begins to build inside your skull, behind your ear..." + + spawn(200) + + if(!host || !src) return + + if(src.stat) + src << "You cannot infest a target in your current state." + return + + src << "You wiggle out of [host]'s ear and plop to the ground." + if(!host.stat) + host << "Something slimy wiggles out of your ear and plops to the ground!" + + detatch() + +mob/living/simple_animal/borer/proc/detatch() + + if(!host) return + + var/datum/organ/external/head = host.get_organ("head") + head.implants -= src + src.loc = get_turf(host) + controlling = 0 + + host.verbs -= /mob/living/carbon/human/proc/release_control + host.verbs -= /mob/living/carbon/human/proc/punish_host + host.verbs -= /mob/living/carbon/human/proc/spawn_larvae + + if(host_brain.ckey) + src.ckey = host.ckey + host.ckey = host_brain.ckey + host_brain.ckey = null + host_brain.name = "host brain" + host_brain.real_name = "host brain" + + host = null + +/mob/living/simple_animal/borer/verb/infest(var/mob/living/carbon/human/H) + set category = "Alien" + set name = "Infest" + set desc = "Infest a suitable humanoid host." + + if(host) + src << "You are already within a host." + return + + if(stat) + src << "You cannot infest a target in your current state." + return + + var/list/choices = list() + for(var/mob/living/C in view(1,src)) + if(istype(C,/mob/living/carbon/human) && C.stat != 2) + choices += C + + var/mob/living/carbon/human/M = input(src,"Who do you wish to infest?") in null|choices + + if(!M || !src) return + + if(M.has_brain_worms()) + src << "You cannot infest someone who is already infested!" + + M << "Something slimy begins probing at the opening of your ear canal..." + src << "You slither up [M] and begin probing at their ear canal..." + + if(!do_after(src,50)) + src << "As [M] moves away, you are dislodged and fall to the ground." + return + + if(!M || !src) return + + if(src.stat) + src << "You cannot infest a target in your current state." + return + + if(M.stat == 2) + src << "That is not an appropriate target." + return + + if(M in view(1, src)) + src << "You wiggle into [M]'s ear." + if(!M.stat) + M << "Something disgusting and slimy wiggles into your ear!" + + src.host = M + var/datum/organ/external/head = M.get_organ("head") + head.implants += src + src.loc = M + bonded = 0 + + host_brain.name = M.name + host_brain.real_name = M.real_name + + return + else + src << "They are no longer in range!" + return \ No newline at end of file diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index bd27b1d7176..7bb662f91ea 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -106,7 +106,7 @@ if(href_list["observe"]) - if(alert(src,"Are you sure you wish to observe? You will not be able to play this round!","Player Setup","Yes","No") == "Yes") + if(alert(src,"Are you sure you wish to observe? You will have to wait 30 minutes before being able to respawn!","Player Setup","Yes","No") == "Yes") if(!client) return 1 var/mob/dead/observer/observer = new() diff --git a/code/modules/mob/screen.dm b/code/modules/mob/screen.dm index 514872db379..c83ba829a9d 100644 --- a/code/modules/mob/screen.dm +++ b/code/modules/mob/screen.dm @@ -606,6 +606,33 @@ var/mob/living/L = usr + //Resisting control by an alien mind. + if(istype(src.loc,/mob/living/simple_animal/borer)) + var/mob/living/simple_animal/borer/B = src.loc + var/mob/living/captive_brain/H = src + + H << "\red You begin doggedly resisting the parasite's control (this will take approximately sixty seconds)." + B.host << "\red You feel the captive mind of [src] begin to resist your control." + + spawn(rand(350,450)+B.host.brainloss) + + if(!B || !B.controlling) + return + + B.host.adjustBrainLoss(rand(5,10)) + H << "\red With an immense exertion of will, you regain control of your body!" + B.host << "\red You feel control of the host brain ripped from your grasp, and retract your probosci before the wild neural impulses can damage you." + B.controlling = 0 + + B.ckey = B.host.ckey + B.host.ckey = H.ckey + + H.ckey = null + H.name = "host brain" + H.real_name = "host brain" + + return + //resisting grabs (as if it helps anyone...) if ((!( L.stat ) && L.canmove && !( L.restrained() ))) var/resisting = 0 diff --git a/code/modules/surgery/implant.dm b/code/modules/surgery/implant.dm index 0d67881f242..7e240f737e3 100644 --- a/code/modules/surgery/implant.dm +++ b/code/modules/surgery/implant.dm @@ -166,7 +166,7 @@ if (affected.implants.len) - var/obj/item/weapon/obj = affected.implants[1] + var/obj/item/obj = affected.implants[1] if(istype(obj,/obj/item/weapon/implant)) var/obj/item/weapon/implant/imp = obj @@ -181,6 +181,11 @@ user.visible_message("\blue [user] takes something out of incision on [target]'s [affected.display_name] with \the [tool].", \ "\blue You take [obj] out of incision on [target]'s [affected.display_name]s with \the [tool]." ) affected.implants -= obj + + //Handle possessive brain borers. + if(istype(obj,/mob/living/simple_animal/borer)) + target.release_control() + obj.loc = get_turf(target) if(istype(obj,/obj/item/weapon/implant)) var/obj/item/weapon/implant/imp = obj diff --git a/config/config.txt b/config/config.txt index 6538a9edbfb..a0e32f3179e 100644 --- a/config/config.txt +++ b/config/config.txt @@ -74,25 +74,13 @@ LOG_PDA ## ## default probablity is 1, increase to make that mode more likely to be picked ## set to 0 to disable that mode -## Cult mode is in alpha test, enable at your own risk PROBABILITY EXTENDED 1 -PROBABILITY TRAITOR 0 -PROBABILITY METEOR 0 PROBABILITY MALFUNCTION 1 -PROBABILITY BLOB 0 PROBABILITY NUCLEAR 1 -PROBABILITY SANDBOX 0 PROBABILITY WIZARD 1 -PROBABILITY RESTRUCTURING 0 -PROBABILITY REVOLUTION 0 PROBABILITY CHANGELING 1 PROBABILITY CULT 1 -PROBABILITY MONKEY 0 -PROBABILITY TRAITORCHAN 0 PROBABILITY EXTEND-A-TRAITORMONGOUS 6 -PROBABILITY EPIDEMIC 0 -PROBABILITY MEME 0 -PROBABILITY RP-REVOLUTION 0 ## Hash out to disable random events during the round. ALLOW_RANDOM_EVENTS diff --git a/icons/mob/animal.dmi b/icons/mob/animal.dmi index 88fb1e19fcf..e269d169aa7 100644 Binary files a/icons/mob/animal.dmi and b/icons/mob/animal.dmi differ
Ninjas