diff --git a/NTstation13.dme b/NTstation13.dme
index 1065bbb49b..9e9cbed7e6 100644
--- a/NTstation13.dme
+++ b/NTstation13.dme
@@ -960,6 +960,7 @@
#include "code\modules\mob\living\carbon\brain\emote.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\posibrain.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"
diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm
index ba74450b50..728e11836f 100644
--- a/code/_onclick/hud/hud.dm
+++ b/code/_onclick/hud/hud.dm
@@ -169,9 +169,7 @@ datum/hud/New(mob/owner)
/datum/hud/proc/instantiate()
- if(!ismob(mymob))
- return 0
- if(!mymob.client)
+ if(!ismob(mymob) || !mymob.client || !mymob.client.screen)
return 0
var/ui_style = ui_style2icon(mymob.client.prefs.UI_style)
@@ -200,10 +198,9 @@ datum/hud/New(mob/owner)
//Version denotes which style should be displayed. blank or 0 means "next version"
/datum/hud/proc/show_hud(var/version = 0)
- if(!ismob(mymob))
- return 0
- if(!mymob.client)
+ if(!ismob(mymob) || !mymob.client || !mymob.client.screen)
return 0
+
var/display_hud_version = version
if(!display_hud_version) //If 0 or blank, display the next hud version
display_hud_version = hud_version + 1
@@ -220,18 +217,30 @@ datum/hud/New(mob/owner)
if(hotkeybuttons && !hotkey_ui_hidden)
mymob.client.screen += hotkeybuttons
- action_intent.screen_loc = ui_acti //Restore intent selection to the original position
- mymob.client.screen += mymob.zone_sel //This one is a special snowflake
- mymob.client.screen += mymob.bodytemp //As are the rest of these...
- mymob.client.screen += mymob.fire
- mymob.client.screen += mymob.healths
- mymob.client.screen += mymob.internals
- mymob.client.screen += mymob.nutrition_icon
- mymob.client.screen += mymob.oxygen
- mymob.client.screen += mymob.pressure
- mymob.client.screen += mymob.toxin
- mymob.client.screen += lingstingdisplay
- mymob.client.screen += lingchemdisplay
+ if(action_intent)
+ action_intent.screen_loc = ui_acti //Restore intent selection to the original position
+ if(mymob.zone_sel)
+ mymob.client.screen += mymob.zone_sel //This one is a special snowflake
+ if(mymob.bodytemp)
+ mymob.client.screen += mymob.bodytemp //As are the rest of these...
+ if(mymob.fire)
+ mymob.client.screen += mymob.fire
+ if(mymob.healths)
+ mymob.client.screen += mymob.healths
+ if(mymob.internals)
+ mymob.client.screen += mymob.internals
+ if(mymob.nutrition_icon)
+ mymob.client.screen += mymob.nutrition_icon
+ if(mymob.oxygen)
+ mymob.client.screen += mymob.oxygen
+ if(mymob.pressure)
+ mymob.client.screen += mymob.pressure
+ if(mymob.toxin)
+ mymob.client.screen += mymob.toxin
+ if(lingstingdisplay)
+ mymob.client.screen += lingstingdisplay
+ if(lingchemdisplay)
+ mymob.client.screen += lingchemdisplay
hidden_inventory_update()
persistant_inventory_update()
@@ -248,15 +257,22 @@ datum/hud/New(mob/owner)
mymob.client.screen -= item_action_list
//These ones are not a part of 'adding', 'other' or 'hotkeybuttons' but we want them gone.
- mymob.client.screen -= mymob.zone_sel //zone_sel is a mob variable for some reason.
- mymob.client.screen -= lingstingdisplay
- mymob.client.screen -= lingchemdisplay
+ if(mymob.zone_sel)
+ mymob.client.screen -= mymob.zone_sel //zone_sel is a mob variable for some reason.
+ if(lingstingdisplay)
+ mymob.client.screen -= lingstingdisplay
+ if(lingchemdisplay)
+ mymob.client.screen -= lingchemdisplay
//These ones are a part of 'adding', 'other' or 'hotkeybuttons' but we want them to stay
- mymob.client.screen += l_hand_hud_object //we want the hands to be visible
- mymob.client.screen += r_hand_hud_object //we want the hands to be visible
- mymob.client.screen += action_intent //we want the intent swticher visible
- action_intent.screen_loc = ui_acti_alt //move this to the alternative position, where zone_select usually is.
+ if(l_hand_hud_object)
+ mymob.client.screen += l_hand_hud_object //we want the hands to be visible
+ if(r_hand_hud_object)
+ mymob.client.screen += r_hand_hud_object //we want the hands to be visible
+ if(action_intent)
+ mymob.client.screen += action_intent //we want the intent swticher visible
+ if(ui_acti_alt)
+ action_intent.screen_loc = ui_acti_alt //move this to the alternative position, where zone_select usually is.
hidden_inventory_update()
persistant_inventory_update()
@@ -273,17 +289,28 @@ datum/hud/New(mob/owner)
mymob.client.screen -= item_action_list
//These ones are not a part of 'adding', 'other' or 'hotkeybuttons' but we want them gone.
- mymob.client.screen -= mymob.zone_sel //zone_sel is a mob variable for some reason.
- mymob.client.screen -= mymob.bodytemp
- mymob.client.screen -= mymob.fire
- mymob.client.screen -= mymob.healths
- mymob.client.screen -= mymob.internals
- mymob.client.screen -= mymob.nutrition_icon
- mymob.client.screen -= mymob.oxygen
- mymob.client.screen -= mymob.pressure
- mymob.client.screen -= mymob.toxin
- mymob.client.screen -= lingstingdisplay
- mymob.client.screen -= lingchemdisplay
+ if(mymob.zone_sel)
+ mymob.client.screen -= mymob.zone_sel //zone_sel is a mob variable for some reason.
+ if(mymob.bodytemp)
+ mymob.client.screen -= mymob.bodytemp
+ if(mymob.fire)
+ mymob.client.screen -= mymob.fire
+ if(mymob.healths)
+ mymob.client.screen -= mymob.healths
+ if(mymob.internals)
+ mymob.client.screen -= mymob.internals
+ if(mymob.nutrition_icon)
+ mymob.client.screen -= mymob.nutrition_icon
+ if(mymob.oxygen)
+ mymob.client.screen -= mymob.oxygen
+ if(mymob.pressure)
+ mymob.client.screen -= mymob.pressure
+ if(mymob.toxin)
+ mymob.client.screen -= mymob.toxin
+ if(lingstingdisplay)
+ mymob.client.screen -= lingstingdisplay
+ if(lingchemdisplay)
+ mymob.client.screen -= lingchemdisplay
hidden_inventory_update()
persistant_inventory_update()
diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm
index cd5d0c45fc..83cd5a8cef 100644
--- a/code/game/mecha/mecha.dm
+++ b/code/game/mecha/mecha.dm
@@ -652,10 +652,13 @@
/obj/mecha/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(istype(W, /obj/item/device/mmi))
+ if(istype(src, /obj/mecha/combat)) //Temp fix, Combat mechs cause LOTS of visual errors on MMI/Posibrains - Remie
+ user << "Does that sound like a smart idea to you?"
+ return
if(mmi_move_inside(W,user))
- user << "[src]-MMI interface initialized successfuly"
+ user << "[src]-[W] interface initialized successfuly"
else
- user << "[src]-MMI interface initialization failed."
+ user << "[src]-[W] interface initialization failed."
return
if(istype(W, /obj/item/mecha_parts/mecha_equipment))
@@ -1154,6 +1157,9 @@
if(mmi.brainmob)
occupant.loc = mmi
mmi.mecha = null
+ if(istype(mmi,/obj/item/device/mmi/posibrain))
+ var/obj/item/device/mmi/posibrain/P = mmi
+ P.handle_posibrain_icon()
src.occupant.canmove = 0
src.verbs += /obj/mecha/verb/eject
src.occupant = null
diff --git a/code/game/objects/items/robot/robot_parts.dm b/code/game/objects/items/robot/robot_parts.dm
index 159921e193..e57fe4c8c3 100644
--- a/code/game/objects/items/robot/robot_parts.dm
+++ b/code/game/objects/items/robot/robot_parts.dm
@@ -225,8 +225,9 @@
M.brainmob.mind.transfer_to(O)
- if(O.mind && O.mind.special_role)
- O.mind.remove_all_antag()
+ if(O.mind)
+ if(O.mind.special_role)
+ O.mind.remove_all_antag()
if(!config.borg_remembers)
O.mind.store_memory("All Objectives listed here are considered Failed.")
else
@@ -238,8 +239,9 @@
O.cell = chest.cell
chest.cell.loc = O
chest.cell = null
- W.loc = O//Should fix cybros run time erroring when blown up. It got deleted before, along with the frame.
- O.mmi = W
+ M.loc = O//Should fix cybros run time erroring when blown up. It got deleted before, along with the frame.
+ O.mmi = M
+ O.updatename()
feedback_inc("cyborg_birth",1)
diff --git a/code/modules/mob/living/carbon/brain/MMI.dm b/code/modules/mob/living/carbon/brain/MMI.dm
index 442698859b..7f47e73497 100644
--- a/code/modules/mob/living/carbon/brain/MMI.dm
+++ b/code/modules/mob/living/carbon/brain/MMI.dm
@@ -8,7 +8,7 @@
w_class = 3
origin_tech = "biotech=3"
- var/list/construction_cost = list("metal"=1000,"glass"=500)
+ var/list/construction_cost = list("metal" = 1000, "glass" = 500)
var/construction_time = 75
//these vars are so the mecha fabricator doesn't shit itself anymore. --NEO
@@ -157,4 +157,4 @@
brainmob.emp_damage += rand(10,20)
if(3)
brainmob.emp_damage += rand(0,10)
- ..()
\ No newline at end of file
+ ..()
diff --git a/code/modules/mob/living/carbon/brain/posibrain.dm b/code/modules/mob/living/carbon/brain/posibrain.dm
new file mode 100644
index 0000000000..9271a6b994
--- /dev/null
+++ b/code/modules/mob/living/carbon/brain/posibrain.dm
@@ -0,0 +1,167 @@
+/obj/item/device/mmi/posibrain
+ name = "positronic brain"
+ desc = "A cube of shining metal, four inches to a side and covered in shallow grooves."
+ icon = 'icons/obj/assemblies.dmi'
+ icon_state = "posibrain"
+ w_class = 3
+ origin_tech = "biotech=3;programming=2"
+
+ construction_cost = list("metal" = 700, "glass" = 350)
+ construction_time = 75
+ var/searching = 0
+ var/askDelay = 10 * 60 * 1
+ brainmob = null
+ req_access = list(access_robotics)
+ locked = 0
+ mecha = null//This does not appear to be used outside of reference in mecha.dm.
+
+
+/obj/item/device/mmi/posibrain/attack_self(mob/user as mob)
+ if(brainmob && !brainmob.key && searching == 0)
+ //Start the process of searching for a new user.
+ user << "You carefully locate the manual activation switch and start the positronic brain's boot process."
+ searching = 1
+ handle_posibrain_icon()
+ request_player()
+ spawn(600)
+ reset_search()
+
+/obj/item/device/mmi/posibrain/proc/request_player()
+ for(var/mob/dead/observer/O in player_list)
+ if(jobban_isbanned(O, "pAI"))
+ continue
+ if(O.client)
+ if(O.client.prefs.be_special & BE_PAI)
+ question(O.client)
+
+/obj/item/device/mmi/posibrain/proc/question(var/client/C)
+ spawn(0)
+ if(!C) return
+ var/response = alert(C, "Someone is requesting a personality for a positronic brain. Would you like to play as one?", "Positronic brain request", "Yes", "No", "Never for this round")
+ if(!C || brainmob.key || 0 == searching)
+ return //handle logouts that happen whilst the alert is waiting for a response, and responses issued after a brain has been located.
+ if(response == "Yes")
+ transfer_personality(C.mob)
+ else if (response == "Never for this round")
+ C.prefs.be_special ^= BE_PAI
+
+
+/obj/item/device/mmi/posibrain/transfer_identity(var/mob/living/carbon/H)
+ name = "positronic brain ([H])"
+ brainmob.name = H.real_name
+ brainmob.real_name = H.real_name
+ brainmob.dna = H.dna
+ brainmob.timeofhostdeath = H.timeofdeath
+ brainmob.stat = 0
+ if(brainmob.mind)
+ brainmob.mind.assigned_role = "Positronic Brain"
+ if(H.mind)
+ H.mind.transfer_to(brainmob)
+
+ brainmob.mind.remove_all_antag()
+ brainmob.mind.wipe_memory()
+
+ brainmob << "ALL PAST LIVES ARE FORGOTTEN."
+
+ brainmob << "Hello World!"
+ handle_posibrain_icon()
+ return
+
+/obj/item/device/mmi/posibrain/proc/transfer_personality(var/mob/candidate)
+
+ searching = 0
+ brainmob.mind = candidate.mind
+ brainmob.ckey = candidate.ckey
+ name = "positronic brain ([brainmob.name])"
+
+ brainmob.mind.remove_all_antag()
+ brainmob.mind.wipe_memory()
+
+ brainmob << "ALL PAST LIVES ARE FORGOTTEN."
+
+ brainmob << "You are a positronic brain, brought into existence on [station_name()]."
+ brainmob << "As a synthetic intelligence, you answer to all crewmembers, as well as the AI."
+ brainmob << "Remember, the purpose of your existence is to serve the crew and the station. Above all else, do no harm."
+ brainmob << "Use say :b to speak to other artificial intelligences."
+ brainmob.mind.assigned_role = "Positronic Brain"
+
+ var/turf/T = get_turf()
+ for (var/mob/M in viewers(T))
+ M.show_message("The positronic brain chimes quietly.")
+ handle_posibrain_icon()
+
+/obj/item/device/mmi/posibrain/proc/reset_search() //We give the players sixty seconds to decide, then reset the timer.
+
+ if(brainmob && brainmob.key) return
+
+ searching = 0
+ handle_posibrain_icon()
+
+ var/turf/T = get_turf()
+ for (var/mob/M in viewers(T))
+ M.show_message("The positronic brain buzzes quietly, and the golden lights fade away. Perhaps you could try again?")
+
+/obj/item/device/mmi/posibrain/examine()
+
+ set src in oview()
+
+ if(!usr || !src) return
+ if( (usr.sdisabilities & BLIND || usr.blinded || usr.stat) && !istype(usr,/mob/dead/observer) )
+ usr << "Something is there but you can't see it."
+ return
+
+ var/msg = "*---------*\nThis is \icon[src] \a [src]!\n[desc]\n"
+ msg += ""
+
+ if(brainmob && brainmob.key)
+ switch(brainmob.stat)
+ if(CONSCIOUS)
+ if(!src.brainmob.client) msg += "It appears to be in stand-by mode.\n" //afk
+ if(UNCONSCIOUS) msg += "It doesn't seem to be responsive.\n"
+ if(DEAD) msg += "It appears to be completely inactive.\n"
+ else
+ msg += "It appears to be completely inactive.\n"
+ msg += "*---------*"
+ usr << msg
+ return
+
+/obj/item/device/mmi/posibrain/emp_act(severity)
+ if(!brainmob)
+ return
+ else
+ switch(severity)
+ if(1)
+ brainmob.emp_damage += rand(20,30)
+ if(2)
+ brainmob.emp_damage += rand(10,20)
+ if(3)
+ brainmob.emp_damage += rand(0,10)
+ ..()
+
+/obj/item/device/mmi/posibrain/New()
+
+ brainmob = new(src)
+ brainmob.name = "[pick(list("PBU","HIU","SINA","ARMA","OSI"))]-[rand(100, 999)]"
+ brainmob.real_name = brainmob.name
+ brainmob.loc = src
+ brainmob.container = src
+ brainmob.robot_talk_understand = 1
+ brainmob.stat = 0
+ brainmob.silent = 0
+ dead_mob_list -= brainmob
+
+ ..()
+
+
+/obj/item/device/mmi/posibrain/attackby(var/obj/item/O as obj, var/mob/user as mob)
+ return
+
+
+/obj/item/device/mmi/posibrain/proc/handle_posibrain_icon()
+ if(searching)
+ icon_state = "posibrain-searching"
+ return
+ if(brainmob)
+ icon_state = "posibrain-occupied"
+ else
+ icon_state = "posibrain"
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index 731b0ab36a..ee1ec2d5f4 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -58,6 +58,8 @@
var/obj/item/weapon/tank/internal = null //Hatred. Used if a borg has a jetpack.
var/obj/item/robot_parts/robot_suit/robot_suit = null //Used for deconstruction to remember what the borg was constructed out of..
+ var/braintype = "Cyborg"
+
/mob/living/silicon/robot/New(loc)
@@ -99,18 +101,19 @@
camera.status = 0
..()
- //MMI stuff. Held togheter by magic. ~Miauw
- mmi = new(src)
- mmi.brain = new /obj/item/organ/brain(mmi)
- mmi.brain.name = "[src.real_name]'s brain"
- mmi.locked = 1
- mmi.icon_state = "mmi_full"
- mmi.name = "Man-Machine Interface: [src.real_name]"
- mmi.brainmob = new(src)
- mmi.brainmob.name = src.real_name
- mmi.brainmob.real_name = src.real_name
- mmi.brainmob.container = mmi
- mmi.contents += mmi.brainmob
+ //MMI stuff. Held together by magic. ~Miauw
+ if(!mmi || !mmi.brainmob)
+ mmi = new(src)
+ mmi.brain = new /obj/item/organ/brain(mmi)
+ mmi.brain.name = "[real_name]'s brain"
+ mmi.locked = 1
+ mmi.icon_state = "mmi_full"
+ mmi.name = "Man-Machine Interface: [real_name]"
+ mmi.brainmob = new(src)
+ mmi.brainmob.name = real_name
+ mmi.brainmob.real_name = real_name
+ mmi.brainmob.container = mmi
+ mmi.contents += mmi.brainmob
playsound(loc, 'sound/voice/liveagain.ogg', 75, 1)
@@ -122,6 +125,9 @@
var/turf/T = get_turf(loc)//To hopefully prevent run time errors.
if(T) mmi.loc = T
mind.transfer_to(mmi.brainmob)
+ if(istype(mmi,/obj/item/device/mmi/posibrain))
+ var/obj/item/device/mmi/posibrain/P = mmi
+ P.handle_posibrain_icon()
mmi = null
..()
@@ -229,10 +235,16 @@
/mob/living/silicon/robot/proc/updatename()
var/changed_name = ""
+
if(custom_name)
changed_name = custom_name
else
- changed_name = "[(designation ? "[designation] " : "")]Cyborg-[num2text(ident)]"
+ if(istype(mmi, /obj/item/device/mmi/posibrain))
+ braintype = "Android"
+ else
+ braintype = "Cyborg"
+
+ changed_name = "[(designation ? "[designation] " : "")][braintype]-[num2text(ident)]"
real_name = changed_name
name = real_name
if(camera)
diff --git a/code/modules/research/designs.dm b/code/modules/research/designs.dm
index 7ea38fe1ef..cbc9d5d818 100644
--- a/code/modules/research/designs.dm
+++ b/code/modules/research/designs.dm
@@ -1519,6 +1519,17 @@ datum/design/mmi_radio
build_path = /obj/item/device/mmi/radio_enabled
category = "Misc"
+datum/design/posibrain
+ name = "Positronic Brain"
+ desc = "The latest in Artificial Intelligences."
+ id = "mmi_posi"
+ req_tech = list("programming" = 2, "biotech" = 4)
+ build_type = PROTOLATHE | MECHFAB
+ materials = list("$metal" = 700, "$glass" = 350)
+ reliability = 74
+ build_path = /obj/item/device/mmi/posibrain
+ category = "Misc"
+
datum/design/synthetic_flash
name = "Synthetic Flash"
desc = "When a problem arises, SCIENCE is the solution."
diff --git a/icons/obj/assemblies.dmi b/icons/obj/assemblies.dmi
index 761a77ceb6..de93929d34 100644
Binary files a/icons/obj/assemblies.dmi and b/icons/obj/assemblies.dmi differ