diff --git a/code/modules/mob/living/carbon/brain/MMI.dm b/code/modules/mob/living/carbon/brain/MMI.dm
index 5e6b142038c..2f08993f4f1 100644
--- a/code/modules/mob/living/carbon/brain/MMI.dm
+++ b/code/modules/mob/living/carbon/brain/MMI.dm
@@ -12,91 +12,112 @@
var/alien = 0
var/syndiemmi = 0 //Whether or not this is a Syndicate MMI
var/mob/living/carbon/brain/brainmob = null//The current occupant.
+ var/obj/item/organ/brain/held_brain = null // This is so MMI's aren't brainscrubber 9000's
var/mob/living/silicon/robot/robot = null//Appears unused.
var/obj/mecha/mecha = null//This does not appear to be used outside of reference in mecha.dm.
// I'm using this for mechs giving MMIs HUDs now
- attackby(var/obj/item/O as obj, var/mob/user as mob, params)
- if(istype(O, /obj/item/organ/brain/crystal ))
- user << " This brain is too malformed to be able to use with the [src]."
+/obj/item/device/mmi/attackby(var/obj/item/O as obj, var/mob/user as mob, params)
+ if(istype(O, /obj/item/organ/brain/crystal ))
+ user << " This brain is too malformed to be able to use with the [src]."
+ return
+ if(istype(O,/obj/item/organ/brain) && !brainmob) //Time to stick a brain in it --NEO
+ var/obj/item/organ/brain/B = O
+ if(!B.brainmob)
+ user << "\red You aren't sure where this brain came from, but you're pretty sure it's a useless brain."
return
- if(istype(O,/obj/item/organ/brain) && !brainmob) //Time to stick a brain in it --NEO
- if(!O:brainmob)
- 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]."))
- brainmob = O:brainmob
- O:brainmob = null
- brainmob.loc = src
- brainmob.container = src
- brainmob.stat = 0
- respawnable_list -= brainmob
- dead_mob_list -= brainmob//Update dem lists
- living_mob_list += brainmob
-
- user.drop_item()
- if(istype(O,/obj/item/organ/brain/xeno))
- name = "Man-Machine Interface: Alien - [brainmob.real_name]"
- icon = 'icons/mob/alien.dmi'
- icon_state = "AlienMMI"
- alien = 1
- else
- name = "Man-Machine Interface: [brainmob.real_name]"
- icon_state = "mmi_full"
- alien = 0
- qdel(O)
-
-
-
- feedback_inc("cyborg_mmis_filled",1)
-
+ if(held_brain)
+ user << "Somehow, this MMI still has a brain in it. Report this to the bug tracker."
+ log_to_dd("[user] tried to stick a [O] into [src] in [get_area(src)], but the held brain variable wasn't cleared")
return
-
- if(brainmob)
- O.attack(brainmob, user)//Oh noooeeeee
- // Brainmobs can take damage, but they can't actually die. Maybe should fix.
+ if(B.status & ORGAN_DEAD) // As it stood, a brain would never become unviable for MMI usage. Perhaps we should keep it that way?
+ user << "This [B] is dead"
return
- ..()
+ for(var/mob/V in viewers(src, null))
+ V.show_message(text("\blue [user] sticks \a [O] into \the [src]."))
+ brainmob = B.brainmob
+ B.brainmob = null
+ brainmob.loc = src
+ brainmob.container = src
+ brainmob.stat = CONSCIOUS
+ respawnable_list -= brainmob
+ dead_mob_list -= brainmob//Update dem lists
+ living_mob_list += brainmob
-
-
- attack_self(mob/user as mob)
- if(!brainmob)
- user << "\red You upend the MMI, but there's nothing in it."
+ user.drop_item()
+ B.forceMove(src)
+ held_brain = B
+ if(istype(O,/obj/item/organ/brain/xeno)) // I'm not sure how well this will work now, since I don't think you can actually get xeno brains
+ name = "Man-Machine Interface: Alien - [brainmob.real_name]"
+ icon = 'icons/mob/alien.dmi'
+ icon_state = "AlienMMI"
+ alien = 1
else
- user << "You unlock and upend the MMI, spilling the brain onto the floor."
- if(alien)
- var/obj/item/organ/brain/xeno/brain = new(user.loc)
- dropbrain(brain,get_turf(user))
- else
- var/obj/item/organ/brain/brain = new(user.loc)
- dropbrain(brain,get_turf(user))
- icon = 'icons/obj/assemblies.dmi'
- icon_state = "mmi_empty"
- name = "Man-Machine Interface"
-
- proc
- transfer_identity(var/mob/living/carbon/human/H)//Same deal as the regular brain proc. Used for human-->robot people.
- brainmob = new(src)
- brainmob.name = H.real_name
- brainmob.real_name = H.real_name
- brainmob.dna = H.dna.Clone()
- brainmob.container = src
-
name = "Man-Machine Interface: [brainmob.real_name]"
icon_state = "mmi_full"
- return
+ alien = 0
+ feedback_inc("cyborg_mmis_filled",1)
+
+ return
+
+ if(brainmob)
+ O.attack(brainmob, user)//Oh noooeeeee
+ // Brainmobs can take damage, but they can't actually die. Maybe should fix.
+ return
+ ..()
+
+
+
+/obj/item/device/mmi/attack_self(mob/user as mob)
+ if(!brainmob)
+ user << "You upend the MMI, but there's nothing in it."
+ else
+ user << "You unlock and upend the MMI, spilling the brain onto the floor."
+ dropbrain(get_turf(user))
+ icon = 'icons/obj/assemblies.dmi'
+ icon_state = "mmi_empty"
+ name = "Man-Machine Interface"
+
+/obj/item/device/mmi/proc/transfer_identity(var/mob/living/carbon/human/H)//Same deal as the regular brain proc. Used for human-->robot people.
+ brainmob = new(src)
+ brainmob.name = H.real_name
+ brainmob.real_name = H.real_name
+ brainmob.dna = H.dna.Clone()
+ brainmob.container = src
+
+ if(!istype(H.species) || isnull(H.species.return_organ("brain"))) // Diona/buggy people
+ held_brain = new(src)
+ else // We have a species, and it has a brain
+ var/brain_path = H.species.return_organ("brain")
+ if(!ispath(brain_path, /obj/item/organ/brain))
+ brain_path = /obj/item/organ/brain
+ held_brain = new brain_path(src) // Slime people will keep their slimy brains this way
+ held_brain.dna = brainmob.dna.Clone()
+ held_brain.name = "\the [brainmob.name]'s [initial(held_brain.name)]"
+
+ name = "Man-Machine Interface: [brainmob.real_name]"
+ icon_state = "mmi_full"
+ return
+
//I made this proc as a way to have a brainmob be transferred to any created brain, and to solve the
//problem i was having with alien/nonalien brain drops.
- dropbrain(var/obj/item/organ/brain/brain, var/turf/dropspot)
- brainmob.container = null//Reset brainmob mmi var.
- brainmob.loc = brain//Throw mob into brain.
- respawnable_list += brainmob
- living_mob_list -= brainmob//Get outta here
- brain.brainmob = brainmob//Set the brain to use the brainmob
- brain.brainmob.cancel_camera()
- brainmob = null//Set mmi brainmob var to null
+/obj/item/device/mmi/proc/dropbrain(var/turf/dropspot)
+ if(isnull(held_brain))
+ log_to_dd("[src] at [loc] attempted to drop brain without a contained brain in [get_area(src)].")
+ brainmob << "Your MMI did not contain a brain! We'll make a new one for you, but you'd best report this to the bugtracker!"
+ held_brain = new(dropspot) // Let's not ruin someone's round because of something dumb -- Crazylemon
+ held_brain.dna = brainmob.dna.Clone()
+ held_brain.name = "\the [brainmob.name]'s [initial(held_brain.name)]"
+
+ brainmob.container = null//Reset brainmob mmi var.
+ brainmob.loc = held_brain//Throw mob into brain.
+ respawnable_list += brainmob
+ living_mob_list -= brainmob//Get outta here
+ held_brain.brainmob = brainmob//Set the brain to use the brainmob
+ held_brain.brainmob.cancel_camera()
+ brainmob = null//Set mmi brainmob var to null
+ held_brain.forceMove(dropspot)
+ held_brain = null
/obj/item/device/mmi/radio_enabled
@@ -106,25 +127,23 @@
var/obj/item/device/radio/radio = null//Let's give it a radio.
- New()
- ..()
- radio = new(src)//Spawns a radio inside the MMI.
- radio.broadcasting = 1//So it's broadcasting from the start.
+/obj/item/device/mmi/radio_enabled/New()
+ ..()
+ radio = new(src)//Spawns a radio inside the MMI.
+ radio.broadcasting = 1//So it's broadcasting from the start.
- verb//Allows the brain to toggle the radio functions.
+/obj/item/device/mmi/radio_enabled/verb/Toggle_Listening()
+ set name = "Toggle Listening"
+ set desc = "Toggle listening channel on or off."
+ set category = "MMI"
+ set src = usr.loc
+ set popup_menu = 0
- Toggle_Listening()
- set name = "Toggle Listening"
- set desc = "Toggle listening channel on or off."
- set category = "MMI"
- set src = usr.loc
- set popup_menu = 0
+ if(brainmob.stat)
+ brainmob << "Can't do that while incapacitated or dead."
- if(brainmob.stat)
- brainmob << "Can't do that while incapacitated or dead."
-
- radio.listening = radio.listening==1 ? 0 : 1
- brainmob << "\blue Radio is [radio.listening==1 ? "now" : "no longer"] receiving broadcast."
+ radio.listening = radio.listening==1 ? 0 : 1
+ brainmob << "Radio is [radio.listening==1 ? "now" : "no longer"] receiving broadcast."
/obj/item/device/mmi/emp_act(severity)
if(!brainmob)
@@ -153,6 +172,9 @@
if(brainmob)
qdel(brainmob)
brainmob = null
+ if(held_brain)
+ qdel(held_brain)
+ held_brain = null
return ..()
/obj/item/device/mmi/syndie
diff --git a/code/modules/mob/living/carbon/brain/posibrain.dm b/code/modules/mob/living/carbon/brain/posibrain.dm
index 3cd7e511369..67caeb2788c 100644
--- a/code/modules/mob/living/carbon/brain/posibrain.dm
+++ b/code/modules/mob/living/carbon/brain/posibrain.dm
@@ -54,19 +54,24 @@
else if (response == "Never for this round")
C.prefs.be_special ^= BE_PAI
+// This should not ever happen, but let's be safe
+/obj/item/device/mmi/posibrain/dropbrain(var/turf/dropspot)
+ log_to_dd("[src] at [loc] attempted to drop brain without a contained brain.")
+ return
/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
+ if(isnull(brainmob.dna))
+ brainmob.dna = H.dna.Clone()
+ brainmob.name = brainmob.dna.real_name
+ brainmob.real_name = brainmob.name
brainmob.timeofhostdeath = H.timeofdeath
- brainmob.stat = 0
+ brainmob.stat = CONSCIOUS
if(brainmob.mind)
brainmob.mind.assigned_role = "Positronic Brain"
if(H.mind)
H.mind.transfer_to(brainmob)
- brainmob << "\blue You feel slightly disoriented. That's normal when you're just a metal cube."
+ brainmob << "You feel slightly disoriented. That's normal when you're just a metal cube."
icon_state = "posibrain-occupied"
return
diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm
index 4a83a771149..63f5ac745c8 100644
--- a/code/modules/mob/living/carbon/human/species/species.dm
+++ b/code/modules/mob/living/carbon/human/species/species.dm
@@ -118,6 +118,7 @@
"l_foot" = list("path" = /obj/item/organ/external/foot),
"r_foot" = list("path" = /obj/item/organ/external/foot/right)
)
+ var/cyborg_type = "Cyborg"
/datum/species/New()
//If the species has eyes, they are the default vision organ
@@ -593,3 +594,12 @@
H.bodytemp.icon_state = "temp0"
return 1
+
+/*
+Returns the path corresponding to the corresponding organ
+It'll return null if the organ doesn't correspond, so include null checks when using this!
+*/
+/datum/species/proc/return_organ(var/organ_slot)
+ if(!(organ_slot in has_organ))
+ return null
+ return has_organ[organ_slot]
\ No newline at end of file
diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm
index eb59f6b9aca..88b701d18cb 100644
--- a/code/modules/mob/transform_procs.dm
+++ b/code/modules/mob/transform_procs.dm
@@ -161,7 +161,7 @@
O.job = "Cyborg"
O.notify_ai(1)
- if(O.mind.assigned_role == "Cyborg")
+ if(O.mind && O.mind.assigned_role == "Cyborg")
if(O.mind.role_alt_title == "Android")
O.mmi = new /obj/item/device/mmi/posibrain(O)
else if(O.mind.role_alt_title == "Robot")
@@ -320,7 +320,7 @@
/mob/proc/safe_respawn(var/MP)
if(!MP)
- return 0
+ return 0
if(ispath(MP, /mob/living/simple_animal/pet/cat))
return 1
@@ -347,7 +347,7 @@
if(ispath(MP, /mob/living/simple_animal/borer) && !jobban_isbanned(src, "alien") && !jobban_isbanned(src, "Syndicate"))
return 1
-
+
if(ispath(MP, /mob/living/simple_animal/diona) && !jobban_isbanned(src, "Dionaea"))
return 1