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"