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)