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