From 17d894fcba84bdffc5a484c6f2ca4967b56df423 Mon Sep 17 00:00:00 2001 From: ShizCalev Date: Fri, 26 Oct 2018 20:10:55 -0400 Subject: [PATCH] Adds examine messages to disembodied & robot heads (#40999) cl ShizCalev tweak: Added some examine messages to disembodied heads indicating if it's missing eyes, or if it's brain is nonfunctional. tweak: Added some examine messages to cyborg parts to indicate their current construction status. tweak: You can now remove the power cell and cut the wiring out of a cyborg chest during construction. /cl Small indicator to help alleviate some minor wastes of time (such as folks bringing suicider's heads to the roboticist instead of the chef.) Added some missing destroy handling, fixed vars not being set and unset properly, cleaned up some duplicate code in human/examine handling for departed souls. --- code/datums/mind.dm | 8 +- code/modules/mob/living/brain/brain_item.dm | 2 +- .../mob/living/carbon/human/examine.dm | 13 +- code/modules/mob/mob.dm | 4 +- code/modules/surgery/bodyparts/bodyparts.dm | 5 +- .../surgery/bodyparts/dismemberment.dm | 15 ++ code/modules/surgery/bodyparts/head.dm | 61 +++++++- .../surgery/bodyparts/robot_bodyparts.dm | 135 ++++++++++++------ 8 files changed, 180 insertions(+), 63 deletions(-) diff --git a/code/datums/mind.dm b/code/datums/mind.dm index adb7bf3fa23..ea4d656556f 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -433,7 +433,7 @@ if(!GLOB.admin_objective_list) generate_admin_objective_list() - + if(old_objective) if(old_objective.name in GLOB.admin_objective_list) def_value = old_objective.name @@ -451,7 +451,7 @@ target_antag.objectives += new_objective message_admins("[key_name_admin(usr)] added a new objective for [current]: [new_objective.explanation_text]") log_admin("[key_name(usr)] added a new objective for [current]: [new_objective.explanation_text]") - else + else if(old_objective.type == selected_type) //Edit the old old_objective.admin_edit(usr) @@ -652,8 +652,8 @@ S.updateButtonIcon() INVOKE_ASYNC(S, /obj/effect/proc_holder/spell.proc/start_recharge) -/datum/mind/proc/get_ghost(even_if_they_cant_reenter) - for(var/mob/dead/observer/G in GLOB.dead_mob_list) +/datum/mind/proc/get_ghost(even_if_they_cant_reenter, ghosts_with_clients) + for(var/mob/dead/observer/G in (ghosts_with_clients ? GLOB.player_list : GLOB.dead_mob_list)) if(G.mind == src) if(G.can_reenter_corpse || even_if_they_cant_reenter) return G diff --git a/code/modules/mob/living/brain/brain_item.dm b/code/modules/mob/living/brain/brain_item.dm index d18e3daaac3..235cfcf04c8 100644 --- a/code/modules/mob/living/brain/brain_item.dm +++ b/code/modules/mob/living/brain/brain_item.dm @@ -122,7 +122,7 @@ if(suicided) to_chat(user, "It's started turning slightly grey. They must not have been able to handle the stress of it all.") else if(brainmob) - if(brainmob.client) + if(brainmob.get_ghost(FALSE, TRUE)) if(brain_death || brainmob.health <= HEALTH_THRESHOLD_DEAD) to_chat(user, "It's lifeless and severely damaged.") else if(damaged_brain) diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index 4f217a32628..ec13a30ebd9 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -115,17 +115,8 @@ msg += "[t_His] soul seems to have been ripped out of [t_his] body. Revival is impossible.\n" msg += "[t_He] [t_is] limp and unresponsive; there are no signs of life" if(getorgan(/obj/item/organ/brain)) - if(!key) - var/foundghost = 0 - if(mind) - for(var/mob/dead/observer/G in GLOB.player_list) - if(G.mind == mind) - foundghost = 1 - if (G.can_reenter_corpse == 0) - foundghost = 0 - break - if(!foundghost) - msg += " and [t_his] soul has departed" + if(!key && !get_ghost(FALSE, TRUE)) + msg += " and [t_his] soul has departed" msg += "...\n" if(get_bodypart(BODY_ZONE_HEAD) && !getorgan(/obj/item/organ/brain)) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index dc7efd1baa2..e4ea939ea56 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -664,9 +664,9 @@ /mob/proc/assess_threat(judgement_criteria, lasercolor = "", datum/callback/weaponcheck=null) //For sec bot threat assessment return 0 -/mob/proc/get_ghost(even_if_they_cant_reenter = 0) +/mob/proc/get_ghost(even_if_they_cant_reenter, ghosts_with_clients) if(mind) - return mind.get_ghost(even_if_they_cant_reenter) + return mind.get_ghost(even_if_they_cant_reenter, ghosts_with_clients) /mob/proc/grab_ghost(force) if(mind) diff --git a/code/modules/surgery/bodyparts/bodyparts.dm b/code/modules/surgery/bodyparts/bodyparts.dm index 4e9731ce2bf..bc52a8b73bf 100644 --- a/code/modules/surgery/bodyparts/bodyparts.dm +++ b/code/modules/surgery/bodyparts/bodyparts.dm @@ -439,13 +439,12 @@ var/obj/item/cavity_item /obj/item/bodypart/chest/Destroy() - if(cavity_item) - qdel(cavity_item) + QDEL_NULL(cavity_item) return ..() /obj/item/bodypart/chest/drop_organs(mob/user, violent_removal) if(cavity_item) - cavity_item.forceMove(user.loc) + cavity_item.forceMove(drop_location()) cavity_item = null ..() diff --git a/code/modules/surgery/bodyparts/dismemberment.dm b/code/modules/surgery/bodyparts/dismemberment.dm index 69a725d061b..1048c905508 100644 --- a/code/modules/surgery/bodyparts/dismemberment.dm +++ b/code/modules/surgery/bodyparts/dismemberment.dm @@ -158,6 +158,14 @@ LB.eyes = src ..() +/obj/item/organ/ears/transfer_to_limb(obj/item/bodypart/head/LB, mob/living/carbon/human/C) + LB.ears = src + ..() + +/obj/item/organ/tongue/transfer_to_limb(obj/item/bodypart/head/LB, mob/living/carbon/human/C) + LB.tongue = src + ..() + /obj/item/bodypart/chest/drop_limb(special) if(special) ..() @@ -312,6 +320,13 @@ brain.Insert(C) //Now insert the brain proper brain = null //No more brain in the head + if(tongue) + tongue = null + if(ears) + ears = null + if(eyes) + eyes = null + if(ishuman(C)) var/mob/living/carbon/human/H = C H.hair_color = hair_color diff --git a/code/modules/surgery/bodyparts/head.dm b/code/modules/surgery/bodyparts/head.dm index d838e879cbf..358b495ec13 100644 --- a/code/modules/surgery/bodyparts/head.dm +++ b/code/modules/surgery/bodyparts/head.dm @@ -16,6 +16,9 @@ var/mob/living/brain/brainmob = null //The current occupant. var/obj/item/organ/brain/brain = null //The brain organ + var/obj/item/organ/eyes/eyes + var/obj/item/organ/ears/ears + var/obj/item/organ/tongue/tongue //Limb appearance info: var/real_name = "" //Replacement name @@ -28,11 +31,65 @@ var/facial_hair_style = "Shaved" //Eye Colouring - var/obj/item/organ/eyes/eyes = null - var/lip_style = null var/lip_color = "white" + +/obj/item/bodypart/head/Destroy() + QDEL_NULL(brainmob) //order is sensitive, see warning in handle_atom_del() below + QDEL_NULL(brain) + QDEL_NULL(eyes) + QDEL_NULL(ears) + QDEL_NULL(tongue) + return ..() + +/obj/item/bodypart/head/handle_atom_del(atom/A) + if(A == brain) + brain = null + update_icon_dropped() + if(!QDELETED(brainmob)) //this shouldn't happen without badminnery. + message_admins("Brainmob: ([brainmob]) was left stranded in [src] at [ADMIN_VERBOSEJMP(src)] without a brain!") + log_game("Brainmob: ([brainmob]) was left stranded in [src] at [AREACOORD(src)] without a brain!") + if(A == brainmob) + brainmob = null + if(A == eyes) + eyes = null + update_icon_dropped() + if(A == ears) + ears = null + if(A == tongue) + tongue = null + return ..() + +/obj/item/bodypart/head/examine(mob/user) + ..() + if(status == BODYPART_ORGANIC) + if(!brain) + to_chat(user, "The brain has been removed from [src].") + else if(brain.suicided || brainmob?.suiciding) + to_chat(user, "There's a pretty dumb expression on [real_name]'s face; they must have really hated life. There is no hope of recovery.") + else if(brain.brain_death || brainmob?.health <= HEALTH_THRESHOLD_DEAD) + to_chat(user, "It seems to be leaking some kind of... clear fluid? The brain inside must be in pretty bad shape... There is no coming back from that.") + else if(brainmob) + if(brainmob.get_ghost(FALSE, TRUE)) + to_chat(user, "It's muscles are still twitching slightly... It still seems to have a bit of life left to it.") + else + to_chat(user, "It seems seems particularly lifeless. Perhaps there'll be a chance for them later.") + else if(brain?.decoy_override) + to_chat(user, "It seems seems particularly lifeless. Perhaps there'll be a chance for them later.") + else + to_chat(user, "It seems completely devoid of life.") + + if(!eyes) + to_chat(user, "[real_name]'s eyes appear to have been removed.") + + if(!ears) + to_chat(user, "[real_name]'s ears appear to have been removed.") + + if(!tongue) + to_chat(user, "[real_name]'s tongue appears to have been removed.") + + /obj/item/bodypart/head/can_dismember(obj/item/I) if(!((owner.stat == DEAD) || owner.InFullCritical())) return FALSE diff --git a/code/modules/surgery/bodyparts/robot_bodyparts.dm b/code/modules/surgery/bodyparts/robot_bodyparts.dm index 5abafd26b28..ae5cc676d03 100644 --- a/code/modules/surgery/bodyparts/robot_bodyparts.dm +++ b/code/modules/surgery/bodyparts/robot_bodyparts.dm @@ -114,44 +114,82 @@ medium_burn_msg = ROBOTIC_MEDIUM_BURN_MSG heavy_burn_msg = ROBOTIC_HEAVY_BURN_MSG - var/wired = 0 + var/wired = FALSE var/obj/item/stock_parts/cell/cell = null + +/obj/item/bodypart/chest/robot/handle_atom_del(atom/A) + if(A == cell) + cell = null + return ..() + +/obj/item/bodypart/chest/robot/Destroy() + QDEL_NULL(cell) + return ..() + /obj/item/bodypart/chest/robot/attackby(obj/item/W, mob/user, params) if(istype(W, /obj/item/stock_parts/cell)) - if(src.cell) + if(cell) to_chat(user, "You have already inserted a cell!") return else if(!user.transferItemToLoc(W, src)) return - src.cell = W + cell = W to_chat(user, "You insert the cell.") else if(istype(W, /obj/item/stack/cable_coil)) - if(src.wired) + if(wired) to_chat(user, "You have already inserted wire!") return var/obj/item/stack/cable_coil/coil = W if (coil.use(1)) - src.wired = 1 + wired = TRUE to_chat(user, "You insert the wire.") else to_chat(user, "You need one length of coil to wire it!") else return ..() -/obj/item/bodypart/chest/robot/Destroy() - if(cell) - qdel(cell) - cell = null - return ..() +/obj/item/bodypart/chest/robot/wirecutter_act(mob/living/user, obj/item/I) + if(!wired) + return + . = TRUE + I.play_tool_sound(src) + to_chat(user, "You cut the wires out of [src].") + new /obj/item/stack/cable_coil(drop_location(), 1) + wired = FALSE +/obj/item/bodypart/chest/robot/screwdriver_act(mob/living/user, obj/item/I) + ..() + . = TRUE + if(!cell) + to_chat(user, "There's no power cell installed in [src]!") + return + I.play_tool_sound(src) + to_chat(user, "Remove [cell] from [src].") + cell.forceMove(drop_location()) + cell = null + + +/obj/item/bodypart/chest/robot/examine(mob/user) + ..() + if(cell) + to_chat(user, "It has a [cell] inserted.") + to_chat(user, "You can use a screwdriver to remove [cell].") + else + to_chat(user, "It has an empty port for a power cell.") + if(wired) + to_chat(user, "Its all wired up[cell ? " and ready for usage" : ""].") + to_chat(user, "You can use wirecutters to remove the wiring.") + else + to_chat(user, "It has a couple spots that still need to be wired.") /obj/item/bodypart/chest/robot/drop_organs(mob/user, violent_removal) if(wired) - new /obj/item/stack/cable_coil(user.loc, 1) + new /obj/item/stack/cable_coil(drop_location(), 1) + wired = FALSE if(cell) - cell.forceMove(user.loc) + cell.forceMove(drop_location()) cell = null ..() @@ -180,11 +218,36 @@ var/obj/item/assembly/flash/handheld/flash2 = null +/obj/item/bodypart/head/robot/handle_atom_del(atom/A) + if(A == flash1) + flash1 = null + if(A == flash2) + flash2 = null + return ..() + +/obj/item/bodypart/head/robot/Destroy() + QDEL_NULL(flash1) + QDEL_NULL(flash2) + return ..() + +/obj/item/bodypart/head/robot/examine(mob/user) + ..() + if(!flash1 && !flash2) + to_chat(user, "It has two empty eye sockets for flashes.") + else + var/single_flash = FALSE + if(!flash1 || !flash2) + single_flash = TRUE + to_chat(user, "One of it's eye sockets are currently occupied by a flash.") + to_chat(user, "It has an empty eye socket for another flash.") + else + to_chat(user, "It has two eye sockets occupied by flashes.") + to_chat(user, "You can remove the seated flash[single_flash ? "":"es"] with a crowbar.") /obj/item/bodypart/head/robot/attackby(obj/item/W, mob/user, params) if(istype(W, /obj/item/assembly/flash/handheld)) var/obj/item/assembly/flash/handheld/F = W - if(src.flash1 && src.flash2) + if(flash1 && flash2) to_chat(user, "You have already inserted the eyes!") return else if(F.crit_fail) @@ -193,36 +256,28 @@ else if(!user.transferItemToLoc(F, src)) return - if(src.flash1) - src.flash2 = F - else - src.flash1 = F - to_chat(user, "You insert the flash into the eye socket.") - else if(W.tool_behaviour == TOOL_CROWBAR) - if(flash1 || flash2) - W.play_tool_sound(src) - to_chat(user, "You remove the flash from [src].") if(flash1) - flash1.forceMove(user.loc) - flash1 = null - if(flash2) - flash2.forceMove(user.loc) - flash2 = null - else - to_chat(user, "There is no flash to remove from [src].") - - else - return ..() - -/obj/item/bodypart/head/robot/Destroy() - if(flash1) - qdel(flash1) - flash1 = null - if(flash2) - qdel(flash2) - flash2 = null + flash2 = F + else + flash1 = F + to_chat(user, "You insert the flash into the eye socket.") + return return ..() +/obj/item/bodypart/head/robot/crowbar_act(mob/living/user, obj/item/I) + if(flash1 || flash2) + I.play_tool_sound(src) + to_chat(user, "You remove the flash from [src].") + if(flash1) + flash1.forceMove(drop_location()) + flash1 = null + if(flash2) + flash2.forceMove(drop_location()) + flash2 = null + else + to_chat(user, "There is no flash to remove from [src].") + return TRUE + /obj/item/bodypart/head/robot/drop_organs(mob/user, violent_removal) if(flash1)