Files
vgstation13/code/modules/mob/living/carbon/brain/MMI.dm
Anthony "Shifty Rail 189f77cbb7 Refactors player preferences for modularity + SQLite Unit Test (#37615)
* Pref code refactor

* Empty database reference

* Unit testing SQLite

* Everything else

* Disable unit testing.

* Equivalent

* more robust unit tests
2025-06-07 09:54:09 -04:00

339 lines
12 KiB
Plaintext

/obj/item/device/mmi
name = "\improper Man-Machine Interface"
desc = "The Warrior's bland acronym, MMI, obscures the true horror of this monstrosity."
icon = 'icons/obj/assemblies.dmi'
icon_state = "mmi_empty"
w_class = W_CLASS_MEDIUM
origin_tech = Tc_BIOTECH + "=3"
var/list/mommi_assembly_parts = list(
/obj/item/weapon/cell = 1,
/obj/item/robot_parts/l_leg = 2,
/obj/item/robot_parts/r_leg = 2,
/obj/item/robot_parts/r_arm = 1,
/obj/item/robot_parts/l_arm = 1
)
var/list/sammi_assembly_parts = list(
/obj/item/weapon/cell = 1,
/obj/item/robot_parts/r_arm = 1,
/obj/item/robot_parts/l_arm = 1
)
req_access = list(access_robotics)
//Revised. Brainmob is now contained directly within object of transfer. MMI in this case.
var/locked = 0
var/mob/living/carbon/brain/brainmob = null//The current occupant.
var/mob/living/silicon/robot = null//Appears unused.
var/obj/mecha = null//This does not appear to be used outside of reference in mecha.dm.
/obj/item/device/mmi/Destroy()
if(brainmob)
QDEL_NULL(brainmob)
..()
// Return true if handled
/obj/item/device/mmi/proc/try_handling_mommi_construction(var/obj/item/O as obj, var/mob/user as mob)
if(O.is_screwdriver(user))
for(var/t in mommi_assembly_parts)
var/cc=contents_count(t)
var/req=mommi_assembly_parts[t]
if(cc<req)
var/temppart = new t(src)
to_chat(user, "<span class='warning'>You're short [req-cc] [temppart]\s.</span>")
QDEL_NULL(temppart)
return TRUE
if(!istype(loc,/turf))
to_chat(user, "<span class='warning'>You can't assemble the MoMMI, \the [src] has to be standing on the ground (or a table) to be perfectly precise.</span>")
return TRUE
if(!brainmob)
to_chat(user, "<span class='warning'>What are you doing oh god put the brain back in.</span>")
return TRUE
if(!brainmob.key)
if(!mind_can_reenter(brainmob.mind))
to_chat(user, "<span class='notice'>\The [src] indicates that their mind is completely unresponsive; there's no point.</span>")
return TRUE
if(brainmob.stat == DEAD)
to_chat(user, "<span class='warning'>Yeah, good idea. Give something deader than the pizza in your fridge legs. Mom would be so proud.</span>")
return TRUE
/*if(brainmob.mind in ticker.mode.head_revolutionaries)
to_chat(user, "<span class='warning'>The [src]'s firmware lets out a shrill sound, and flashes 'Abnormal Memory Engram'. It refuses to accept the brain.</span>")
return TRUE
*/
if(jobban_isbanned(brainmob, "Mobile MMI"))
to_chat(user, "<span class='warning'>This brain does not seem to fit.</span>")
return TRUE
//canmove = 0
var/mob/living/silicon/robot/mommi/M = new /mob/living/silicon/robot/mommi/nt(get_turf(loc))
if(!M)
return
M.invisibility = 0
//M.custom_name = created_name
brainmob.mind.transfer_to(M)
M.cell = locate(/obj/item/weapon/cell) in contents
M.cell.forceMove(M)
src.forceMove(M)//Should fix cybros run time erroring when blown up. It got deleted before, along with the frame.
M.mmi = src
if(M.mind && M.mind.special_role)
M.mind.store_memory("In case you look at this after being borged, the objectives are only here until I find a way to make them not show up for you, as I can't simply delete them without screwing up round-end reporting. --NeoFite")
M.job = "MoMMI"
M.Namepick() //this delays the return until after you're done namepicking so it may still cause nervegas further down the line
return TRUE
for(var/t in mommi_assembly_parts)
if(istype(O,t))
var/cc=contents_count(t)
if(cc<mommi_assembly_parts[t])
if(!brainmob)
to_chat(user, "<span class='warning'>Why are you sticking robot legs on an empty [src], you idiot?</span>")
return TRUE
if(!user.drop_item(O, src, failmsg = TRUE))
return FALSE
contents += O
to_chat(user, "<span class='notice'>You successfully add \the [O] to the contraption.</span>")
return TRUE
else if(cc==mommi_assembly_parts[t])
to_chat(user, "<span class='warning'>You have enough of these.</span>")
return TRUE
return FALSE
/obj/item/device/mmi/proc/try_handling_sammi_construction(var/obj/item/O as obj, var/mob/user as mob)
if(O.is_wrench(user))
for(var/t in sammi_assembly_parts)
var/cc=contents_count(t)
var/req=sammi_assembly_parts[t]
if(cc<req)
to_chat(user, "<span class='warning'>You're short [req-cc] [t]\s.</span>")
return TRUE
if(!istype(loc,/turf))
to_chat(user, "<span class='warning'>You can't assemble the SAMMI, \the [src] has to be standing on the ground (or a table) to be perfectly precise.</span>")
return TRUE
new /mob/living/silicon/robot/mommi/sammi(get_turf(loc))
qdel(src)
return TRUE
for(var/t in sammi_assembly_parts)
if(istype(O,t))
var/cc=contents_count(t)
if(cc<sammi_assembly_parts[t])
if(!user.drop_item(O, src, failmsg = TRUE))
return FALSE
contents += O
to_chat(user, "<span class='notice'>You successfully add \the [O] to the contraption,</span>")
return TRUE
else if(cc==sammi_assembly_parts[t])
to_chat(user, "<span class='warning'>You have enough of these.</span>")
return TRUE
return FALSE
/obj/item/device/mmi/attackby(var/obj/item/O as obj, var/mob/user as mob)
if(!brainmob)
if(try_handling_sammi_construction(O,user))
return
else
if(try_handling_mommi_construction(O,user))
return
if(istype(O,/obj/item/organ/internal/brain) && !brainmob) //Time to stick a brain in it --NEO
// MaMIs inherit from brain, but they shouldn't be insertable into a MMI
if (istype(O, /obj/item/organ/internal/brain/mami))
to_chat(user, "<span class='warning'>You are only able to fit organic brains on a MMI. [src] won't work.</span>")
return TRUE
var/obj/item/organ/internal/brain/BO = O
if(!BO.brainmob)
to_chat(user, "<span class='warning'>You aren't sure where this brain came from, but you're pretty sure it's a useless brain.</span>")
return TRUE
// Checking to see if the ghost has been moused/borer'd/etc since death.
var/mob/living/carbon/brain/BM = BO.brainmob
if(!BM.client)
to_chat(user, "<span class='warning'>\The [src] indicates that \the [O] [BM.ghost_reenter_alert("Someone is trying to put your brain in a MMI. Return to your body if you want to be resurrected!") ? "seems slow to respond. Try again in a few seconds" : "is completely unresponsive; there's no point"].</span>")
return TRUE
if(!user.drop_item(O, failmsg = TRUE))
return TRUE
src.visible_message("<span class='notice'>[user] sticks \a [O] into \the [src].</span>")
brainmob = BO.brainmob
BO.brainmob = null
brainmob.forceMove(src)
brainmob.container = src
brainmob.stat = 0
brainmob.resurrect()
QDEL_NULL(O)
name = "[initial(name)]: [brainmob.real_name]"
icon_state = "mmi_full"
if (isrev(brainmob))
var/datum/role/revolutionary/R = brainmob.mind.GetRole(REV)
R.Drop(TRUE)
locked = 1
feedback_inc("cyborg_mmis_filled",1)
return TRUE
if((istype(O,/obj/item/weapon/card/id)||istype(O,/obj/item/device/pda)) && brainmob)
if(allowed(user))
locked = !locked
to_chat(user, "<span class='notice'>You [locked ? "lock" : "unlock"] \the [src].</span>")
else
to_chat(user, "<span class='warning'>Access denied.</span>")
return TRUE
if(istype(O, /obj/item/weapon/implanter))
return//toplel
..()
//TODO: ORGAN REMOVAL UPDATE. Make the brain remain in the MMI so it doesn't lose organ data.
/obj/item/device/mmi/attack_self(mob/user as mob)
if(!brainmob)
to_chat(user, "<span class='warning'>You upend \the [src], but there's nothing in it.")
else if(locked)
to_chat(user, "<span class='warning'>You upend \the [src], but the brain is clamped into place.")
else
to_chat(user, "<span class='notice'>You upend \the [src], spilling the brain onto the floor.</span>")
var/obj/item/organ/internal/brain/brain = new(user.loc)
brain.transfer_identity(brainmob)
QDEL_NULL(brainmob)//Set mmi brainmob var to null
icon_state = "mmi_empty"
name = initial(name)
/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
if(istype(H) && H.dna)
brainmob.dna = H.dna.Clone()
brainmob.container = src
if (isbrain(H))
var/mob/living/carbon/brain/otherbrain = H
brainmob.timeofhostdeath = otherbrain.timeofhostdeath
else if (H.timeofdeath == 0)//happens when the human gets decapitated while still alive
brainmob.timeofhostdeath = world.time
else
brainmob.timeofhostdeath = H.timeofdeath
name = "Man-Machine Interface: [brainmob.real_name]"
icon_state = "mmi_full"
locked = 1
return
/obj/item/device/mmi/proc/create_identity(var/datum/preferences/P)
brainmob = new(src)
brainmob.dna = new()
brainmob.dna.ResetUI()
brainmob.dna.ResetSE()
var/datum/preference_setting/name_pref = P.get_pref_datum(/datum/preference_setting/string/real_name)
var/species = P.get_pref(/datum/preference_setting/string/species)
var/gender = P.get_pref(/datum/preference_setting/enum/gender)
if(P.get_pref(/datum/preference_setting/toggle/be_random_name))
name_pref.setting = random_name(gender, species)
brainmob.name = name_pref.setting
brainmob.real_name = name_pref.setting
brainmob.container = src
name = "Man-Machine Interface: [brainmob.real_name]"
icon_state = "mmi_full"
locked = 1
/obj/item/device/mmi/radio_enabled
name = "Radio-enabled Man-Machine Interface"
desc = "The Warrior's bland acronym, MMI, obscures the true horror of this monstrosity. This one comes with a built-in radio."
origin_tech = Tc_BIOTECH + "=4"
var/obj/item/device/radio/radio = null//Let's give it a radio.
/obj/item/device/mmi/radio_enabled/New()
..()
radio = new(src)//Spawns a radio inside the MMI.
radio.broadcasting = 0//So it's broadcasting from the start.
/obj/item/device/mmi/radio_enabled/Destroy()
..()
QDEL_NULL(radio)
/obj/item/device/mmi/radio_enabled/verb/Toggle_Broadcasting()
set name = "Toggle Broadcasting"
set desc = "Toggle broadcasting channel on or off."
set category = "MMI"
set src = usr.loc//In user location, or in MMI in this case.
set popup_menu = 0//Will not appear when right clicking.
if(brainmob.stat)//Only the brainmob will trigger these so no further check is necessary.
to_chat(brainmob, "Can't do that while incapacitated or dead.")
radio.broadcasting = radio.broadcasting==1 ? 0 : 1
to_chat(brainmob, "<<span class='notice'>Radio is [radio.broadcasting==1 ? "now" : "no longer"] broadcasting.</span>")
/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
if(brainmob.stat)
to_chat(brainmob, "Can't do that while incapacitated or dead.")
radio.listening = radio.listening==1 ? 0 : 1
to_chat(brainmob, "<span class='notice'>Radio is [radio] receiving broadcast.</span>")
/obj/item/device/mmi/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/proc/contents_count(var/type)
var/c=0
for(var/O in contents)
if(istype(O,type))
c++
return c
/obj/item/device/mmi/examine(mob/user)
to_chat(user, "<span class='info'>*---------*</span>")
..()
if(locked!=2)
if(src.brainmob)
if(src.brainmob.stat == DEAD)
to_chat(user, "<span class='deadsay'>It appears the brain has suffered irreversible tissue degeneration</span>")//suicided
else if(!src.brainmob.client)
to_chat(user, "<span class='notice'>It appears to be lost in its own thoughts</span>")//closed game window
else if(!src.brainmob.key)
to_chat(user, "<span class='warning'>It seems to be in a deep dream-state</span>")//ghosted
to_chat(user, "<span class='info'>Its interface is [locked ? "locked" : "unlocked"] </span>")
to_chat(user, "<span class='info'>*---------*</span>")
/obj/item/device/mmi/OnMobDeath(var/mob/living/carbon/brain/B)
if(istype(B))
icon_state = "mmi_dead"
visible_message(message = "<span class='danger'>[B]'s MMI flatlines!</span>", blind_message = "<span class='warning'>You hear something flatline.</span>")