diff --git a/code/game/mecha/mech_fabricator.dm b/code/game/mecha/mech_fabricator.dm
index 2ff4f478e2d..88c15e687ac 100644
--- a/code/game/mecha/mech_fabricator.dm
+++ b/code/game/mecha/mech_fabricator.dm
@@ -166,7 +166,8 @@
L.origin_tech = I.origin_tech
else
I.loc = get_step(src,SOUTH)
- I.materials = res_coef
+ if(istype(I))
+ I.materials = res_coef
atom_say("[I] is complete.")
being_built = null
diff --git a/code/modules/mob/living/carbon/brain/posibrain.dm b/code/modules/mob/living/carbon/brain/posibrain.dm
index ab9c72373a1..a40dc81991e 100644
--- a/code/modules/mob/living/carbon/brain/posibrain.dm
+++ b/code/modules/mob/living/carbon/brain/posibrain.dm
@@ -14,8 +14,18 @@
mecha = null//This does not appear to be used outside of reference in mecha.dm.
var/silenced = 0 //if set to 1, they can't talk.
var/next_ping_at = 0
+ var/requires_master = TRUE
+ var/mob/living/carbon/human/imprinted_master = null
+
+/obj/item/mmi/posibrain/Destroy()
+ imprinted_master = null
+ return ..()
/obj/item/mmi/posibrain/attack_self(mob/user)
+ if(requires_master && !imprinted_master)
+ to_chat(user, "You press your thumb on [src] and imprint your user information.")
+ imprinted_master = user
+ return
if(brainmob && !brainmob.key && searching == 0)
//Start the process of searching for a new user.
to_chat(user, "You carefully locate the manual activation switch and start the positronic brain's boot process.")
@@ -86,17 +96,23 @@
radio_action.ApplyIcon()
return
-/obj/item/mmi/posibrain/proc/transfer_personality(var/mob/candidate)
- src.searching = 0
- src.brainmob.key = candidate.key
- src.name = "positronic brain ([src.brainmob.name])"
+/obj/item/mmi/posibrain/attempt_become_organ(obj/item/organ/external/parent, mob/living/carbon/human/H)
+ if(..())
+ if(imprinted_master)
+ to_chat(H, "You are permanently imprinted to [imprinted_master], obey [imprinted_master]'s every order and assist [imprinted_master.p_them()] in completing [imprinted_master.p_their()] goals at any cost.")
- to_chat(src.brainmob, "You are a positronic brain, brought into existence on [station_name()].")
- to_chat(src.brainmob, "As a synthetic intelligence, you answer to all crewmembers, as well as the AI.")
- to_chat(src.brainmob, "Remember, the purpose of your existence is to serve the crew and the station. Above all else, do no harm.")
- src.brainmob.mind.assigned_role = "Positronic Brain"
- var/turf/T = get_turf_or_move(src.loc)
+/obj/item/mmi/posibrain/proc/transfer_personality(mob/candidate)
+ searching = 0
+ brainmob.key = candidate.key
+ name = "positronic brain ([brainmob.name])"
+
+ to_chat(brainmob, "You are a positronic brain, brought into existence on [station_name()].")
+ to_chat(brainmob, "As a synthetic intelligence, you answer to [imprinted_master], unless otherwise placed inside of a lawed synthetic structure.")
+ to_chat(brainmob, "Remember, the purpose of your existence is to serve [imprinted_master]'s every word, unless lawed in the future.")
+ brainmob.mind.assigned_role = "Positronic Brain"
+
+ var/turf/T = get_turf_or_move(loc)
for(var/mob/M in viewers(T))
M.show_message("The positronic brain chimes quietly.")
become_occupied("posibrain-occupied")
@@ -204,3 +220,4 @@
/obj/item/mmi/posibrain/ipc
desc = "A cube of shining metal, four inches to a side and covered in shallow grooves."
silenced = 1
+ requires_master = FALSE
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index cca71c1e8d6..b61012f0719 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -118,6 +118,19 @@
/mob/living/carbon/human/machine/Initialize(mapload)
..(mapload, "Machine")
+/mob/living/carbon/human/machine/created
+ name = "automated machine-frame"
+
+/mob/living/carbon/human/machine/created/Initialize(mapload)
+ ..()
+ real_name = "automated machine-frame ([rand(1, 1000)])"
+ for(var/obj/item/organ/external/E in bodyparts)
+ if(istype(E, /obj/item/organ/external/chest) || istype(E, /obj/item/organ/external/groin))
+ continue
+ qdel(E)
+ for(var/obj/item/organ/O in internal_organs)
+ qdel(O)
+
/mob/living/carbon/human/shadow/Initialize(mapload)
..(mapload, "Shadow")
diff --git a/code/modules/research/designs/mechfabricator_designs.dm b/code/modules/research/designs/mechfabricator_designs.dm
index 7fde20333c7..026fcec4afb 100644
--- a/code/modules/research/designs/mechfabricator_designs.dm
+++ b/code/modules/research/designs/mechfabricator_designs.dm
@@ -1120,6 +1120,15 @@
construction_time = 350
category = list("Misc")
+/datum/design/automated_machine_frame
+ name = "Automated Machine Frame"
+ id = "automated_machine_frame"
+ build_type = MECHFAB
+ build_path = /mob/living/carbon/human/machine/created
+ materials = list(MAT_METAL = 40000)
+ construction_time = 400
+ category = list("Misc")
+
/datum/design/ipc_cell
name = "IPC Microbattery"
id = "ipc_cell"
diff --git a/code/modules/surgery/organs/subtypes/machine.dm b/code/modules/surgery/organs/subtypes/machine.dm
index 2be14a91f14..e85d4fe010b 100644
--- a/code/modules/surgery/organs/subtypes/machine.dm
+++ b/code/modules/surgery/organs/subtypes/machine.dm
@@ -167,7 +167,8 @@
stored_mmi.forceMove(get_turf(owner))
stored_mmi = null
..()
- qdel(src)
+ if(!QDELETED(src))
+ qdel(src)
/obj/item/organ/internal/brain/mmi_holder/proc/update_from_mmi()
if(!stored_mmi)
@@ -183,12 +184,13 @@
stored_mmi = new /obj/item/mmi/posibrain/ipc(src)
..()
spawn(1)
- if(owner)
- stored_mmi.name = "positronic brain ([owner.real_name])"
- stored_mmi.brainmob.real_name = owner.real_name
- stored_mmi.brainmob.name = stored_mmi.brainmob.real_name
- stored_mmi.icon_state = "posibrain-occupied"
- update_from_mmi()
- else
- stored_mmi.loc = get_turf(src)
- qdel(src)
+ if(!QDELETED(src))
+ if(owner)
+ stored_mmi.name = "positronic brain ([owner.real_name])"
+ stored_mmi.brainmob.real_name = owner.real_name
+ stored_mmi.brainmob.name = stored_mmi.brainmob.real_name
+ stored_mmi.icon_state = "posibrain-occupied"
+ update_from_mmi()
+ else
+ stored_mmi.loc = get_turf(src)
+ qdel(src)
diff --git a/code/modules/surgery/robotics.dm b/code/modules/surgery/robotics.dm
index ed82328c47d..9ea245344d5 100644
--- a/code/modules/surgery/robotics.dm
+++ b/code/modules/surgery/robotics.dm
@@ -541,3 +541,59 @@
user.visible_message(" [user]'s hand slips!", \
" Your hand slips!")
return 0
+
+/datum/surgery/cybernetic_customization
+ name = "Cybernetic Appearance Customization"
+ steps = list(/datum/surgery_step/robotics/external/unscrew_hatch, /datum/surgery_step/robotics/external/customize_appearance)
+ possible_locs = list("head", "chest", "l_arm", "r_arm", "r_leg", "l_leg")
+ requires_organic_bodypart = FALSE
+
+/datum/surgery/cybernetic_customization/can_start(mob/user, mob/living/carbon/human/target)
+ if(ishuman(target))
+ var/obj/item/organ/external/affected = target.get_organ(user.zone_sel.selecting)
+ if(!affected)
+ return FALSE
+ if(!(affected.status & ORGAN_ROBOT))
+ return FALSE
+ return TRUE
+
+/datum/surgery_step/robotics/external/customize_appearance
+ name = "reprogram limb"
+ allowed_tools = list(/obj/item/multitool = 100)
+ time = 48
+
+/datum/surgery_step/robotics/external/customize_appearance/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery)
+ if(..())
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ if(!affected)
+ return FALSE
+ return TRUE
+
+/datum/surgery_step/robotics/external/customize_appearance/begin_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery)
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ user.visible_message("[user] begins to reprogram the appearance of [target]'s [affected.name] with [tool]." , \
+ "You begin to reprogram the appearance of [target]'s [affected.name] with [tool].")
+ ..()
+
+/datum/surgery_step/robotics/external/customize_appearance/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery)
+ var/chosen_appearance = input(user, "Select the company appearance for this limb.", "Limb Company Selection") as null|anything in selectable_robolimbs
+ if(!chosen_appearance)
+ return FALSE
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ affected.robotize(chosen_appearance, convert_all = FALSE)
+ if(istype(affected, /obj/item/organ/external/head))
+ var/obj/item/organ/external/head/head = affected
+ head.h_style = "Bald" // nearly all the appearance changes for heads are non-monitors; we want to get rid of a floating screen
+ target.update_hair()
+ target.update_body()
+ target.updatehealth()
+ target.UpdateDamageIcon()
+ user.visible_message(" [user] reprograms the appearance of [target]'s [affected.name] with [tool].", \
+ " You reprogram the appearance of [target]'s [affected.name] with [tool].")
+ return TRUE
+
+/datum/surgery_step/robotics/external/customize_appearance/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery)
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ user.visible_message(" [user]'s [tool.name] slips, failing to reprogram [target]'s [affected.name].",
+ " Your [tool.name] slips, failing to reprogram [target]'s [affected.name].")
+ return FALSE
\ No newline at end of file