diff --git a/code/game/objects/items/robot/robot_parts.dm b/code/game/objects/items/robot/robot_parts.dm index f10af1c628a..c42145ff2a7 100644 --- a/code/game/objects/items/robot/robot_parts.dm +++ b/code/game/objects/items/robot/robot_parts.dm @@ -316,8 +316,7 @@ chest.cell.forceMove(O) W.forceMove(O)//Should fix cybros run time erroring when blown up. It got deleted before, along with the frame. - if(O.mmi) //we delete the mmi created by robot/New() - qdel(O.mmi) + QDEL_NULL(O.mmi) //we delete the mmi created by robot/New() O.mmi = W //and give the real mmi to the borg. O.updatename(brainmob.client) // This canonizes that MMI'd cyborgs have memories of their previous life diff --git a/code/modules/antagonists/cult/blood_magic.dm b/code/modules/antagonists/cult/blood_magic.dm index da1655f35ac..9b28611e197 100644 --- a/code/modules/antagonists/cult/blood_magic.dm +++ b/code/modules/antagonists/cult/blood_magic.dm @@ -603,7 +603,6 @@ user.visible_message(span_danger("The dark cloud recedes from what was formerly [candidate], revealing a\n [construct_class]!")) make_new_construct_from_class(construct_class, THEME_CULT, candidate, user, FALSE, T) uses-- - candidate.mmi = null qdel(candidate) channeling = FALSE else diff --git a/code/modules/mob/living/brain/MMI.dm b/code/modules/mob/living/brain/MMI.dm index 0de10eda4c9..3dc3d08d399 100644 --- a/code/modules/mob/living/brain/MMI.dm +++ b/code/modules/mob/living/brain/MMI.dm @@ -22,9 +22,6 @@ laws.set_laws_config() /obj/item/mmi/Destroy() - if(iscyborg(loc)) - var/mob/living/silicon/robot/borg = loc - borg.mmi = null set_mecha(null) QDEL_NULL(brainmob) QDEL_NULL(brain) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 53663519ccf..805e48234bb 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -1385,8 +1385,7 @@ // Disconnect AI's in shells if(Robot.connected_ai) Robot.connected_ai.disconnect_shell() - if(Robot.mmi) - qdel(Robot.mmi) + QDEL_NULL(Robot.mmi) Robot.notify_ai(AI_NOTIFICATION_NEW_BORG) else for(var/obj/item/item in src) diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 2a4670d266b..326ed391bb8 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -991,11 +991,6 @@ // I am so sorry SEND_SIGNAL(src, COMSIG_MOB_RESET_PERSPECTIVE) -/mob/living/silicon/ai/death(gibbed) - if(!isnull(deployed_shell)) - disconnect_shell() // farewell my sweet prince; for a shell is nothing without an AI to control it - return ..() - /mob/living/silicon/ai/revive(full_heal_flags = NONE, excess_healing = 0, force_grab_ghost = FALSE) . = ..() if(!.) //successfully ressuscitated from death diff --git a/code/modules/mob/living/silicon/ai/death.dm b/code/modules/mob/living/silicon/ai/death.dm index 7a7e238b296..e064cb3da58 100644 --- a/code/modules/mob/living/silicon/ai/death.dm +++ b/code/modules/mob/living/silicon/ai/death.dm @@ -6,30 +6,30 @@ // Will update all AI status displays with a blue screen of death INVOKE_ASYNC(src, PROC_REF(emote), "bsod") + if(!isnull(deployed_shell)) + disconnect_shell() + . = ..() cut_overlays() //remove portraits - var/old_icon = icon_state - if("[icon_state]_dead" in icon_states(icon)) - icon_state = "[icon_state]_dead" + var/base_icon = icon_state + if(icon_exists(icon, "[base_icon]_dead")) + icon_state = "[base_icon]_dead" else icon_state = "ai_dead" - if("[old_icon]_death_transition" in icon_states(icon)) - flick("[old_icon]_death_transition", src) + + if(icon_exists(icon, "[base_icon]_death_transition")) + flick("[base_icon]_death_transition", src) cameraFollow = null - set_anchored(FALSE) //unbolt floorbolts - status_flags |= CANPUSH //we want it to be pushable when unanchored on death - REMOVE_TRAIT(src, TRAIT_NO_TELEPORT, AI_ANCHOR_TRAIT) //removes the anchor trait, because its not anchored anymore - move_resist = MOVE_FORCE_NORMAL - is_anchored = FALSE + if(is_anchored) + flip_anchored() if(eyeobj) eyeobj.setLoc(get_turf(src)) set_eyeobj_visible(FALSE) - GLOB.shuttle_caller_list -= src SSshuttle.autoEvac() @@ -41,6 +41,8 @@ if(explosive) addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(explosion), loc, 3, 6, 12, null, 15), 1 SECONDS) + SSblackbox.ReportDeath(src) + /mob/living/silicon/ai/proc/ShutOffDoomsdayDevice() if(nuking) nuking = FALSE diff --git a/code/modules/mob/living/silicon/robot/death.dm b/code/modules/mob/living/silicon/robot/death.dm index bf29bf5f771..81026bf11b9 100644 --- a/code/modules/mob/living/silicon/robot/death.dm +++ b/code/modules/mob/living/silicon/robot/death.dm @@ -3,9 +3,9 @@ new /obj/effect/temp_visual/gib_animation(loc, "gibbed-r") /mob/living/silicon/robot/dust(just_ash, drop_items, force) - if(mmi) - qdel(mmi) - ..() + // You do not get MMI'd if you are dusted + QDEL_NULL(mmi) + return ..() /mob/living/silicon/robot/spawn_dust() new /obj/effect/decal/remains/robot(loc) @@ -16,7 +16,9 @@ /mob/living/silicon/robot/death(gibbed) if(stat == DEAD) return - if(!gibbed) + if(gibbed) + dump_into_mmi() + else logevent("FATAL -- SYSTEM HALT") modularInterface.shutdown_computer() . = ..() diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index cada82ec4df..1f2cafbd5cb 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -89,18 +89,6 @@ alert_control.listener.RegisterSignal(src, COMSIG_LIVING_DEATH, TYPE_PROC_REF(/datum/alarm_listener, prevent_alarm_changes)) alert_control.listener.RegisterSignal(src, COMSIG_LIVING_REVIVE, TYPE_PROC_REF(/datum/alarm_listener, allow_alarm_changes)) -/mob/living/silicon/robot/model/syndicate/Initialize(mapload) - . = ..() - laws = new /datum/ai_laws/syndicate_override() - addtimer(CALLBACK(src, PROC_REF(show_playstyle)), 5) - -/mob/living/silicon/robot/model/syndicate/create_modularInterface() - if(!modularInterface) - modularInterface = new /obj/item/modular_computer/pda/silicon/cyborg/syndicate(src) - modularInterface.saved_identification = real_name - modularInterface.saved_job = "Cyborg" - return ..() - /mob/living/silicon/robot/set_suicide(suicide_state) . = ..() if(mmi) @@ -128,30 +116,12 @@ //If there's an MMI in the robot, have it ejected when the mob goes away. --NEO /mob/living/silicon/robot/Destroy() - var/atom/T = drop_location()//To hopefully prevent run time errors. - if(mmi && mind)//Safety for when a cyborg gets dust()ed. Or there is no MMI inside. - if(T) - mmi.forceMove(T) - if(mmi.brainmob) - if(mmi.brainmob.stat == DEAD) - mmi.brainmob.set_stat(CONSCIOUS) - mind.transfer_to(mmi.brainmob) - mmi.update_appearance() - else - to_chat(src, span_boldannounce("Oops! Something went very wrong, your MMI was unable to receive your mind. You have been ghosted. Please make a bug report so we can fix this bug.")) - ghostize() - stack_trace("Borg MMI lacked a brainmob") - mmi = null - if(modularInterface) - QDEL_NULL(modularInterface) if(connected_ai) set_connected_ai(null) if(shell) GLOB.available_ai_shells -= src - else - if(T && istype(radio) && istype(radio.keyslot)) - radio.keyslot.forceMove(T) - radio.keyslot = null + + QDEL_NULL(modularInterface) QDEL_NULL(wires) QDEL_NULL(model) QDEL_NULL(eye_lights) @@ -533,31 +503,62 @@ lampButton?.update_appearance() update_icons() -/mob/living/silicon/robot/proc/deconstruct() +/mob/living/silicon/robot/proc/cyborg_deconstruct() SEND_SIGNAL(src, COMSIG_BORG_SAFE_DECONSTRUCT) if(shell) undeploy() - var/turf/T = get_turf(src) + var/turf/drop_to = drop_location() if (robot_suit) - robot_suit.drop_all_parts(T) + robot_suit.drop_all_parts(drop_to) else - new /obj/item/robot_suit(T) - new /obj/item/bodypart/leg/left/robot(T) - new /obj/item/bodypart/leg/right/robot(T) - new /obj/item/stack/cable_coil(T, 1) - new /obj/item/bodypart/chest/robot(T) - new /obj/item/bodypart/arm/left/robot(T) - new /obj/item/bodypart/arm/right/robot(T) - new /obj/item/bodypart/head/robot(T) - var/b - for(b=0, b != 2, b++) - var/obj/item/assembly/flash/handheld/F = new /obj/item/assembly/flash/handheld(T) - F.burn_out() + new /obj/item/robot_suit(drop_to) + new /obj/item/bodypart/leg/left/robot(drop_to) + new /obj/item/bodypart/leg/right/robot(drop_to) + new /obj/item/stack/cable_coil(drop_to, 1) + new /obj/item/bodypart/chest/robot(drop_to) + new /obj/item/bodypart/arm/left/robot(drop_to) + new /obj/item/bodypart/arm/right/robot(drop_to) + new /obj/item/bodypart/head/robot(drop_to) + for(var/i in 1 to 2) + var/obj/item/assembly/flash/handheld/borgeye = new(drop_to) + borgeye.burn_out() + + cell?.forceMove(drop_to) // Cell can be null, if removed beforehand + radio?.keyslot?.forceMove(drop_to) + radio?.keyslot = null + + dump_into_mmi(drop_to) - cell?.forceMove(T) // Cell can be null, if removed beforehand qdel(src) + +/// Dumps the current occupant of the cyborg into an MMI at the passed location +/// Returns the borg's MMI on success +/mob/living/silicon/robot/proc/dump_into_mmi(atom/at_location = drop_location()) + if(isnull(mmi)) + return + + var/obj/item/mmi/removing = mmi + mmi.forceMove(at_location) // Nulls it out via exited + + if(isnull(mind)) // no one to transfer, just leave the MMI. + return mmi + + if(removing.brainmob) + if(removing.brainmob.stat == DEAD) + removing.brainmob.set_stat(CONSCIOUS) + mind.transfer_to(removing.brainmob) + removing.update_appearance() + + else + to_chat(src, span_boldannounce("Oops! Something went very wrong, your MMI was unable to receive your mind. \ + You have been ghosted. Please make a bug report so we can fix this bug.")) + ghostize() + stack_trace("Borg MMI lacked a brainmob") + + return mmi + /mob/living/silicon/robot/proc/notify_ai(notifytype, oldname, newname) if(!connected_ai) return @@ -736,9 +737,6 @@ return TRUE -/mob/living/silicon/robot/model/syndicate/ResetModel() - return - /mob/living/silicon/robot/proc/has_model() if(!model || model.type == /obj/item/robot_model) . = FALSE @@ -780,6 +778,9 @@ if(gone == cell) cell = null + if(gone == mmi) + mmi = null + ///Use this to add upgrades to robots. It'll register signals for when the upgrade is moved or deleted, if not single use. /mob/living/silicon/robot/proc/add_to_upgrades(obj/item/borg/upgrade/new_upgrade, mob/user) if(new_upgrade in upgrades) diff --git a/code/modules/mob/living/silicon/robot/robot_defense.dm b/code/modules/mob/living/silicon/robot/robot_defense.dm index b4147e76fe1..61cccd35f9b 100644 --- a/code/modules/mob/living/silicon/robot/robot_defense.dm +++ b/code/modules/mob/living/silicon/robot/robot_defense.dm @@ -305,9 +305,9 @@ GLOBAL_LIST_INIT(blacklisted_borg_hats, typecacheof(list( //Hats that don't real spark_system.start() return to_chat(user, span_notice("You start to unfasten [src]'s securing bolts...")) - if(tool.use_tool(src, user, 50, volume=50) && !cell) + if(tool.use_tool(src, user, 5 SECONDS, volume = 50) && !cell) user.visible_message(span_notice("[user] deconstructs [src]!"), span_notice("You unfasten the securing bolts, and [src] falls to pieces!")) - deconstruct() + cyborg_deconstruct() return /mob/living/silicon/robot/fire_act() diff --git a/code/modules/mob/living/silicon/robot/robot_defines.dm b/code/modules/mob/living/silicon/robot/robot_defines.dm index e9b8bbff823..36e000327bf 100644 --- a/code/modules/mob/living/silicon/robot/robot_defines.dm +++ b/code/modules/mob/living/silicon/robot/robot_defines.dm @@ -202,10 +202,26 @@ cell = /obj/item/stock_parts/cell/hyper radio = /obj/item/radio/borg/syndicate +/mob/living/silicon/robot/model/syndicate/Initialize(mapload) + laws = new /datum/ai_laws/syndicate_override() + laws.associate(src) + . = ..() + addtimer(CALLBACK(src, PROC_REF(show_playstyle)), 0.5 SECONDS) + +/mob/living/silicon/robot/model/syndicate/create_modularInterface() + if(!modularInterface) + modularInterface = new /obj/item/modular_computer/pda/silicon/cyborg/syndicate(src) + modularInterface.saved_identification = real_name + modularInterface.saved_job = "Cyborg" + return ..() + /mob/living/silicon/robot/model/syndicate/proc/show_playstyle() if(playstyle_string) to_chat(src, playstyle_string) +/mob/living/silicon/robot/model/syndicate/ResetModel() + return + /mob/living/silicon/robot/model/syndicate/medical icon_state = "synd_medical" playstyle_string = "You are a Syndicate medical cyborg!
\ diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index 8328b3b16dc..c2aaab8fc23 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -106,13 +106,6 @@ modularInterface.saved_job = "Cyborg" return ..() -/mob/living/silicon/robot/model/syndicate/create_modularInterface() - if(!modularInterface) - modularInterface = new /obj/item/modular_computer/pda/silicon/cyborg/syndicate(src) - modularInterface.saved_job = "Cyborg" - return ..() - - /mob/living/silicon/med_hud_set_health() return //we use a different hud