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/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index ca43f87ae46..d054c163732 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -1206,6 +1206,10 @@ occupant = brainmob brainmob.forceMove(src) //should allow relaymove brainmob.canmove = 1 + if(istype(mmi_as_oc, /obj/item/mmi/posibrain)) + var/obj/item/mmi/posibrain/P = mmi_as_oc + if(P.imprinted_master) + to_chat(brainmob, "Your imprint to [P.imprinted_master] has been temporarily disabled. You should help the crew and not commit harm.") mmi_as_oc.loc = src mmi_as_oc.mecha = src verbs -= /obj/mecha/verb/eject @@ -1305,6 +1309,10 @@ mmi.mecha = null mmi.update_icon() L.canmove = 0 + if(istype(mmi, /obj/item/mmi/posibrain)) + var/obj/item/mmi/posibrain/P = mmi + if(P.imprinted_master) + to_chat(L, "Imprint re-enabled, you are once again bound to [P.imprinted_master]'s commands.") icon_state = initial(icon_state)+"-open" dir = dir_in diff --git a/code/modules/mob/living/carbon/brain/posibrain.dm b/code/modules/mob/living/carbon/brain/posibrain.dm index ab9c72373a1..9ab4a153f4d 100644 --- a/code/modules/mob/living/carbon/brain/posibrain.dm +++ b/code/modules/mob/living/carbon/brain/posibrain.dm @@ -1,5 +1,5 @@ /obj/item/mmi/posibrain - name = "positronic brain" + name = "robotic 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" @@ -14,11 +14,21 @@ 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.") + to_chat(user, "You carefully locate the manual activation switch and start [src]'s boot process.") icon_state = "posibrain-searching" ghost_volunteers.Cut() searching = 1 @@ -56,7 +66,7 @@ /obj/item/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") + var/response = alert(C, "Someone is requesting a personality for a [src]. Would you like to play as one?", "[src] 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) @@ -69,7 +79,7 @@ return /obj/item/mmi/posibrain/transfer_identity(var/mob/living/carbon/H) - name = "positronic brain ([H])" + name = "[src] ([H])" if(isnull(brainmob.dna)) brainmob.dna = H.dna.Clone() brainmob.name = brainmob.dna.real_name @@ -86,19 +96,25 @@ 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 = "[src] ([brainmob.name])" + + to_chat(brainmob, "You are a [src], 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 or mech.") + to_chat(brainmob, "Remember, the purpose of your existence is to serve [imprinted_master]'s every word, unless lawed or placed into a mech 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.") + M.show_message("[src] chimes quietly.") become_occupied("posibrain-occupied") @@ -110,7 +126,7 @@ var/turf/T = get_turf_or_move(src.loc) 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?") + M.show_message("The [src] buzzes quietly, and the golden lights fade away. Perhaps you could try again?") /obj/item/mmi/posibrain/Topic(href,href_list) if("signup" in href_list) @@ -199,8 +215,10 @@ playsound(get_turf(src), 'sound/items/posiping.ogg', 80, 0) var/turf/T = get_turf_or_move(src.loc) for(var/mob/M in viewers(T)) - M.show_message("The positronic brain pings softly.") + M.show_message("[src] pings softly.") /obj/item/mmi/posibrain/ipc + name = "positronic brain" 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 ad249d8307f..06a287e1645 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 = "Integrated Robotic Chassis" + +/mob/living/carbon/human/machine/created/Initialize(mapload) + ..() + real_name = "Integrated Robotic Chassis ([rand(1, 9999)])" + 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..1589b78438b 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/integrated_robotic_chassis + name = "Integrated Robotic Chassis" + id = "integrated_robotic_chassis" + 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/research/designs/medical_designs.dm b/code/modules/research/designs/medical_designs.dm index c0f9350af51..5782d9f19c8 100644 --- a/code/modules/research/designs/medical_designs.dm +++ b/code/modules/research/designs/medical_designs.dm @@ -104,7 +104,7 @@ category = list("Medical") /datum/design/posibrain - name = "Positronic Brain" + name = "Robotic Brain" desc = "The latest in Artificial Intelligences." id = "mmi_posi" req_tech = list("programming" = 5, "biotech" = 4, "plasmatech" = 3) diff --git a/code/modules/surgery/organs/subtypes/machine.dm b/code/modules/surgery/organs/subtypes/machine.dm index 7c68fc11f28..15f0bc5c118 100644 --- a/code/modules/surgery/organs/subtypes/machine.dm +++ b/code/modules/surgery/organs/subtypes/machine.dm @@ -166,7 +166,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) @@ -182,12 +183,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 0fc8b2852cc..3de2d350ee0 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