diff --git a/code/defines/mob/living/silicon/robot.dm b/code/defines/mob/living/silicon/robot.dm
index 9cc8ebbfc73..ad8e2375494 100644
--- a/code/defines/mob/living/silicon/robot.dm
+++ b/code/defines/mob/living/silicon/robot.dm
@@ -27,6 +27,8 @@
var/obj/item/weapon/cell/cell = null
var/obj/machinery/camera/camera = null
+ var/obj/item/device/mmi/brain = null
+
var/opened = 0
var/emagged = 0
var/wiresexposed = 0
diff --git a/code/defines/obj.dm b/code/defines/obj.dm
index c5d2b88a22e..5425a8ad5b2 100644
--- a/code/defines/obj.dm
+++ b/code/defines/obj.dm
@@ -794,6 +794,7 @@
origin_tech = "biotech=3"
var/mob/living/carbon/human/owner = null
+ var/mob/living/carbon/brain/brainmob = null
/obj/item/brain/New()
@@ -801,6 +802,25 @@
spawn(5)
if(src.owner)
src.name = "[src.owner]'s brain"
+ //Shifting the brain "mob" over to the brain object so it's easier to keep track of. --NEO
+ brainmob = new /mob/living/carbon/brain
+ brainmob.loc = src
+ brainmob.name = owner.real_name
+ brainmob.real_name = owner.real_name
+ src.owner.mind.transfer_to(brainmob)
+ brainmob.death() //the brain is dead until stuffed into an MMI. In which case it might still be dead if it's been beat up.
+ brainmob.client.screen.len = null //clear the hud
+ brainmob << "\blue You might feel slightly disoriented. That's normal when your brain gets cut out."
+
+/obj/item/brain/Del()
+ if(src.brainmob)
+ if(src.brainmob.client)
+ var/mob/dead/observer/newmob
+ newmob = new/mob/dead/observer
+ newmob.loc = get_turf(src)
+ src.brainmob:client:mob = newmob
+ newmob:client:eye = newmob
+ ..()
/obj/noticeboard
name = "Notice Board"
diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm
index 5bf956e0a9a..587089ac7fc 100644
--- a/code/game/gamemodes/objective.dm
+++ b/code/game/gamemodes/objective.dm
@@ -46,7 +46,7 @@ datum
check_completion()
if(target && target.current)
- if(target.current.stat == 2 || istype(target.current.loc.loc, /area/tdome) || istype(target.current,/mob/living/silicon)) //Assuming this works, people in the thunderdome and borgs now count as dead for traitor objectives. --NeoFite
+ if(target.current.stat == 2 || istype(target.current.loc.loc, /area/tdome) || istype(target.current,/mob/living/silicon) || istype(target.current,/mob/living/carbon/brain)) //Assuming this works, people in the thunderdome and borgs now count as dead for traitor objectives. --NeoFite
return 1
else
return 0
@@ -81,6 +81,8 @@ datum
check_completion()
if(istype(owner.current, /mob/living/silicon))
return 0
+ if(istype(owner.current, /mob/living/carbon/brain))
+ return 0
if(emergency_shuttle.location<2)
return 0
diff --git a/code/game/machinery/computer/AIcore.dm b/code/game/machinery/computer/AIcore.dm
index 950b46c9226..51ed8058f2b 100644
--- a/code/game/machinery/computer/AIcore.dm
+++ b/code/game/machinery/computer/AIcore.dm
@@ -7,7 +7,7 @@
var/state = 0
var/datum/ai_laws/laws = new /datum/ai_laws/asimov
var/obj/item/weapon/circuitboard/circuit = null
- var/obj/item/brain/brain = null
+ var/obj/item/device/mmi/brain = null
/obj/AIcore/attackby(obj/item/P as obj, mob/user as mob)
@@ -105,7 +105,13 @@
src.laws.add_inherent_law(M.newFreeFormLaw)
usr << "Added a freeform law."
- if(istype(P, /obj/item/brain))
+ if(istype(P, /obj/item/device/mmi))
+ if(!P:brain)
+ user << "\red Sticking an empty MMI into the frame would sort of defeat the purpose."
+ return
+ if(P:brain.brainmob.stat == 2)
+ user << "\red Sticking a dead brain into the frame would sort of defeat the purpose."
+ return
user.drop_item()
P.loc = src
src.brain = P
diff --git a/code/game/machinery/microwave.dm b/code/game/machinery/microwave.dm
index 70cc4ebd467..fcdda58aa7f 100644
--- a/code/game/machinery/microwave.dm
+++ b/code/game/machinery/microwave.dm
@@ -571,6 +571,8 @@ Please clean it before use!
src.extra_item = null
else //Otherwise it was empty, so just turn it on then off again with nothing happening
+ for(var/obj/O in src.contents)
+ del(O) //with how brains work now, need to make sure they get deleted so the poor player inside it gets ghosted. --NEO
src.operating = 1
src.icon_state = "mw1"
src.updateUsrDialog()
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index e9467f70d3e..b8fbeebc9f1 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -341,21 +341,23 @@
if(M.client)
M.client.mob = new/mob/dead/observer(M)
//a mob can't have two clients so get rid of one
-
- if(src.owner)
+ //this might actually be outdated since barring badminnery, a debrain'd body will have any client sucked out to the brain's internal mob. Leaving it anyway to be safe. --NEO
+ src.brainmob.mind.transfer_to(M)
+ src.brainmob = null
+// if(src.owner)
//if the brain has an owner corpse
- if(src.owner.client)
+// if(src.owner.client)
//if the player hasn't ghosted
- src.owner.client.mob = M
+// src.owner.client.mob = M
//then put them in M
- else
+// else
//if the player HAS ghosted
- for(var/mob/dead/observer/O in world)
- if(O.corpse == src.owner && O.client)
+// for(var/mob/dead/observer/O in world)
+// if(O.corpse == src.owner && O.client)
//find their ghost
- O.client.mob = M
+// O.client.mob = M
//put their mob in M
- del(O)
+// del(O)
//delete thier ghost
M:brain_op_stage = 3.0
diff --git a/code/game/objects/items/robot_parts.dm b/code/game/objects/items/robot_parts.dm
index d8c87bc60eb..d7ffd56e4d6 100644
--- a/code/game/objects/items/robot_parts.dm
+++ b/code/game/objects/items/robot_parts.dm
@@ -127,27 +127,31 @@
else
user << "\blue You need to attach a flash to it first!"
- if(istype(W, /obj/item/brain))
+ if(istype(W, /obj/item/device/mmi))
if(src.check_completion())
if(!istype(src.loc,/turf))
- user << "\red You can't put the brain in, it has to be standing on the ground to be perfectly precise."
+ user << "\red You can't put the MMI in, the frame has to be standing on the ground to be perfectly precise."
+ return
+ if(!W:brain)
+ user << "\red Sticking an empty MMI into the frame would sort of defeat the purpose."
+ return
+ if(W:brain.brainmob.stat == 2)
+ user << "\red Sticking a dead brain into the frame would sort of defeat the purpose."
return
user.drop_item()
W.loc = src
src.brain = W
var/mob/living/silicon/robot/O = new /mob/living/silicon/robot(get_turf(src.loc))
- if (src.brain.owner)
- O.gender = src.brain.owner.gender
//O.start = 1
O.invisibility = 0
O.name = src.created_name
O.real_name = src.created_name
- if (src.brain.owner.client)
- src.brain.owner.mind.transfer_to(O)
+ if (W:brain.brainmob)
+ W:brain.brainmob.mind.transfer_to(O)
else
for(var/mob/dead/observer/G in world)
- if(G.corpse == src.brain.owner && G.client)
+ if(G.corpse == W:brain.brainmob && G.client)
G.corpse.mind.transfer_to(O)
del(G)
break
@@ -165,10 +169,11 @@
O.cell = src.chest.cell
O.cell.loc = O
+ O.brain = W
del(src)
else
- user << "\blue The brain must go in after everything else!"
+ user << "\blue The MMI must go in after everything else!"
if (istype(W, /obj/item/weapon/pen))
var/t = input(user, "Enter new robot name", src.name, src.created_name) as text
diff --git a/code/game/research/designs.dm b/code/game/research/designs.dm
index 0d800c827c4..3748a569622 100644
--- a/code/game/research/designs.dm
+++ b/code/game/research/designs.dm
@@ -853,6 +853,16 @@ datum
reliability_base = 74
build_path = "/obj/item/device/mass_spectrometer/adv"
+ mmi
+ name = "Man-Machine Interface"
+ desc = "The Warrior's bland acronym, MMI, obscures the true horror of this monstrosity."
+ id = "mmi"
+ req_tech = list("biotech" = 3)
+ build_type = PROTOLATHE | MECHFAB
+ materials = list("$metal" = 1000, "$glass" = 500)
+ reliability_base = 76
+ build_path = "/obj/item/device/mmi"
+
/////////////////////////////////////////
/////////////////Weapons/////////////////
/////////////////////////////////////////
diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index 757cf043e32..e8c289bf4ee 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -1121,7 +1121,7 @@
src.verbs -= /obj/admins/proc/unprison
src.verbs -= /proc/togglebuildmode
src.verbs -= /client/proc/cmd_mass_modify_object_variables
-
+
src.verbs -= /client/proc/triple_ai
src.verbs -= /client/proc/only_one
// Unnecessary commands
@@ -1172,7 +1172,7 @@
src.holder.state = 2
update_admins(rank)
if(!istype(src.mob, /mob/dead/observer))
- src.mob.ghostize()
+ src.mob.ghostize(1)
src << "\blue You are now observing"
/client/proc/admin_play()
diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm
index bda1865c8c3..335737b6d08 100644
--- a/code/modules/mob/dead/observer/observer.dm
+++ b/code/modules/mob/dead/observer/observer.dm
@@ -12,10 +12,13 @@
src.name = corpse.real_name
src.verbs += /mob/dead/observer/proc/reenter_corpse
-/mob/proc/ghostize()
+/mob/proc/ghostize(var/adminoverride = 0)
set category = "Special Verbs"
set name = "Ghost"
set desc = "You cannot be revived as a ghost"
+ if(src.stat != 2 && !adminoverride)
+ src << "Only dead people and admins get to ghost, and admins don't use this verb to ghost while alive."
+ return
if(src.client)
src.client.mob = new/mob/dead/observer(src)
return
diff --git a/code/modules/mob/living/carbon/brain/MMI.dm b/code/modules/mob/living/carbon/brain/MMI.dm
index 0501b18bb3d..317f7b7777a 100644
--- a/code/modules/mob/living/carbon/brain/MMI.dm
+++ b/code/modules/mob/living/carbon/brain/MMI.dm
@@ -4,9 +4,9 @@
icon = 'assemblies.dmi'
icon_state = "mmi_empty"
w_class = 3
+ origin_tech = "biotech=3"
var/obj/item/brain/brain = null
- var/mob/living/carbon/brain/brainmob = null
var/mob/living/silicon/robot = null
var/obj/mecha = null
var/locked = 0
@@ -14,26 +14,21 @@
attackby(var/obj/item/O as obj, var/mob/user as mob)
if(istype(O,/obj/item/brain) && !brain) //Time to stick a brain in it --NEO
-
+ if(!O:owner)
+ user << "\red You aren't sure where this brain came from, but you're pretty sure it's a useless brain."
+ return
for(var/mob/V in viewers(src, null))
V.show_message(text("\blue [user] sticks \a [O] into \the [src]."))
brain = O
user.drop_item()
O.loc = src
-
- //Adding the actual mob the brain's player gets moved to. --NEO
- brainmob = new /mob/living/carbon/brain
- brainmob.loc = src
- brainmob.name = brain.owner.real_name
- brainmob.real_name = brain.owner.real_name
- brainmob.container = src
- brain.owner.mind.transfer_to(brainmob)
- brainmob.client.screen.len = null
-
- name = "Man-Machine Interface:[brainmob.real_name]"
- icon_state = "mmi_full"
+ brain.brainmob.container = src
+ brain.brainmob.stat = 0
locked = 1
+ name = "Man-Machine Interface:[brain.brainmob.real_name]"
+ icon_state = "mmi_full"
return
+
if((istype(O,/obj/item/weapon/card/id)||istype(O,/obj/item/device/pda)) && brain)
if(allowed(user))
locked = !locked
@@ -42,8 +37,24 @@
user << "\red Access denied."
return
if(brain)
- O.attack(brainmob, user)
+ O.attack(brain.brainmob, user)
return
..()
+ attack_self(mob/user as mob)
+ if(!brain)
+ user << "\red You upend the MMI, but there's nothing in it."
+ else if(locked)
+ user << "\red You upend the MMI, but the brain is clamped into place."
+ else
+ user << "\blue You upend the MMI, spilling the brain onto the floor."
+ brain.loc = user.loc
+ brain.brainmob.container = null
+ brain.brainmob.death()
+ brain = null
+ icon_state = "mmi_empty"
+ name = "Man-Machine Interface"
+
+
+
diff --git a/code/modules/mob/living/carbon/brain/brain.dm b/code/modules/mob/living/carbon/brain/brain.dm
index 3ead33ac25e..aee453863bb 100644
--- a/code/modules/mob/living/carbon/brain/brain.dm
+++ b/code/modules/mob/living/carbon/brain/brain.dm
@@ -18,6 +18,12 @@
return 1
return ..()
+// verb
+// body_jump()
+// set category = "Special Verbs"
+// set name = "Check on Original Body"
+
+
/obj/hud/proc/brain_hud(var/ui_style='screen1_old.dmi')
src.station_explosion = new src.h_type( src )
src.station_explosion.icon = 'station_explosion.dmi'
diff --git a/code/modules/mob/living/carbon/brain/death.dm b/code/modules/mob/living/carbon/brain/death.dm
index eeede342a22..8986d162aec 100644
--- a/code/modules/mob/living/carbon/brain/death.dm
+++ b/code/modules/mob/living/carbon/brain/death.dm
@@ -1,9 +1,10 @@
/mob/living/carbon/brain/death(gibbed)
var/cancel
- if (!gibbed)
- for(var/mob/O in viewers(src.container, null))
- O.show_message(text("\red []'s MMI flatlines!", src), 1, "\red You hear something flatline.", 2)
- src.container.icon_state = "mmi_dead"
+ if(src.container)
+ if (!gibbed)
+ for(var/mob/O in viewers(src.container, null))
+ O.show_message(text("\red []'s MMI flatlines!", src), 1, "\red You hear something flatline.", 2)
+ src.container.icon_state = "mmi_dead"
src.stat = 2
if(src.blind)
diff --git a/code/modules/mob/living/carbon/brain/say.dm b/code/modules/mob/living/carbon/brain/say.dm
new file mode 100644
index 00000000000..da7ac7c2da1
--- /dev/null
+++ b/code/modules/mob/living/carbon/brain/say.dm
@@ -0,0 +1,3 @@
+/mob/living/carbon/brain/say(var/message)
+ if(!container && stat != 2) return //In case of some mysterious happenings where a "living" brain is not in an MMI, don't let it speak. --NEO
+ ..()
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/human/say.dm b/code/modules/mob/living/carbon/human/say.dm
index d31d6958a54..3faacd1b5cd 100644
--- a/code/modules/mob/living/carbon/human/say.dm
+++ b/code/modules/mob/living/carbon/human/say.dm
@@ -33,4 +33,6 @@
return 1
if (istype(other, /mob/living/silicon/robot))
return 1
+ if (istype(other, /mob/living/carbon/brain))
+ return 1
return ..()
\ No newline at end of file
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index f3518b009c7..aba5464415c 100644
--- a/code/modules/mob/living/silicon/ai/ai.dm
+++ b/code/modules/mob/living/silicon/ai/ai.dm
@@ -1,4 +1,4 @@
-/mob/living/silicon/ai/New(loc, var/datum/ai_laws/L, var/obj/item/brain/B)
+/mob/living/silicon/ai/New(loc, var/datum/ai_laws/L, var/obj/item/device/mmi/B)
src.anchored = 1
src.canmove = 0
src.loc = loc
@@ -24,8 +24,8 @@
src.real_name = "Inactive AI"
src.icon_state = "ai-empty"
else
- if (B.owner.mind)
- B.owner.mind.transfer_to(src)
+ if (B.brain.brainmob.mind)
+ B.brain.brainmob.mind.transfer_to(src)
src << "You are playing the station's AI. The AI cannot move, but can interact with many objects while viewing them (through cameras)."
src << "To look at other parts of the station, double-click yourself to get a camera menu."
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index ffcb9b30eb0..bb4f00e8037 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -35,6 +35,13 @@
src.cell = C
..()
+/mob/living/silicon/robot/Del()
+ if(brain)
+ brain.loc = loc
+ mind.transfer_to(brain.brain.brainmob)
+ ..()
+ //If there's an MMI in the robot, have it ejected when the mob goes away. --NEO
+
/mob/living/silicon/robot/proc/pick_module()
if(src.module)
return
diff --git a/maps/tgstation.2.0.5.dmm b/maps/tgstation.2.0.5.dmm
index 3e802d2d604..417bc08a672 100644
--- a/maps/tgstation.2.0.5.dmm
+++ b/maps/tgstation.2.0.5.dmm
@@ -3323,7 +3323,7 @@
"blU" = (/obj/cable{d1 = 4; d2 = 8; icon_state = "4-8"; tag = "Streight"},/turf/simulated/floor{icon_state = "white"},/area/medical/surgery)
"blV" = (/obj/cable{d1 = 4; d2 = 8; icon_state = "4-8"; tag = "Streight"},/obj/machinery/atmospherics/pipe/simple{color = "blue"; icon_state = "intact-b-f"; level = 1; name = "pipe"},/obj/machinery/door/firedoor/border_only,/obj/machinery/door/airlock/medical{name = "Operating Theatre"; req_access_txt = "45"},/turf/simulated/floor{icon_state = "white"},/area/medical/surgery)
"blW" = (/obj/cable{d1 = 1; d2 = 8; icon_state = "1-8"; tag = "90Curve"},/turf/simulated/floor{icon_state = "white"},/area/medical/surgery)
-"blX" = (/obj/table{dir = 10; icon_state = "tabledir"},/turf/simulated/floor{icon_state = "white"},/area/medical/surgery)
+"blX" = (/obj/table{dir = 10; icon_state = "tabledir"},/obj/item/device/mmi,/obj/item/device/mmi,/turf/simulated/floor{icon_state = "white"},/area/medical/surgery)
"blY" = (/obj/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = "Streight"},/turf/simulated/floor{icon_state = "dark"},/area/medical/surgery)
"blZ" = (/obj/closet/firecloset,/turf/simulated/floor/plating,/area/maintenance/starboard)
"bma" = (/obj/grille,/obj/window/reinforced,/obj/window/reinforced{dir = 4},/obj/window/reinforced{dir = 8},/turf/simulated/floor/plating,/area/quartermaster/storage)
diff --git a/tgstation.dme b/tgstation.dme
index 52d5a110cfe..d1f7e5779c9 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -655,6 +655,7 @@
#include "code\modules\mob\living\carbon\brain\death.dm"
#include "code\modules\mob\living\carbon\brain\life.dm"
#include "code\modules\mob\living\carbon\brain\MMI.dm"
+#include "code\modules\mob\living\carbon\brain\say.dm"
#include "code\modules\mob\living\carbon\human\death.dm"
#include "code\modules\mob\living\carbon\human\emote.dm"
#include "code\modules\mob\living\carbon\human\examine.dm"