diff --git a/code/__DEFINES/organ_movement.dm b/code/__DEFINES/organ_movement.dm new file mode 100644 index 00000000000..16f003ede81 --- /dev/null +++ b/code/__DEFINES/organ_movement.dm @@ -0,0 +1,4 @@ +/// Delete the organ if replaced +#define DELETE_IF_REPLACED (1<<0) +/// When deleting a brain, we don't delete the identity and the player can keep playing +#define NO_ID_TRANSFER (1<<1) diff --git a/code/__DEFINES/traits/sources.dm b/code/__DEFINES/traits/sources.dm index f0b67a95b92..f9cdbe4326d 100644 --- a/code/__DEFINES/traits/sources.dm +++ b/code/__DEFINES/traits/sources.dm @@ -275,5 +275,7 @@ #define ANALYZER_TRAIT "analyzer_trait" +/// Trait from an organ being inside a bodypart +#define ORGAN_INSIDE_BODY_TRAIT "organ_inside_body" /// Trait when something was labelled by a pen. #define PEN_LABEL_TRAIT "pen_label" diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm index 1c4958a0b03..a8cbdf950be 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -654,11 +654,6 @@ GLOBAL_LIST_EMPTY(species_list) if(isliving(occupant)) mob_occupant = occupant - else if(isbodypart(occupant)) - var/obj/item/bodypart/head/head = occupant - - mob_occupant = head.brainmob - else if(isorgan(occupant)) var/obj/item/organ/internal/brain/brain = occupant mob_occupant = brain.brainmob diff --git a/code/datums/ai/generic/generic_behaviors.dm b/code/datums/ai/generic/generic_behaviors.dm index 962c8d141cd..a5838e1811e 100644 --- a/code/datums/ai/generic/generic_behaviors.dm +++ b/code/datums/ai/generic/generic_behaviors.dm @@ -359,6 +359,10 @@ continue if(thing.IsObscured()) continue + if(isitem(thing)) + var/obj/item/item = thing + if(item.item_flags & ABSTRACT) + continue possible_targets += thing if(!possible_targets.len) finish_action(controller, FALSE) diff --git a/code/datums/bodypart_overlays/mutant_bodypart_overlay.dm b/code/datums/bodypart_overlays/mutant_bodypart_overlay.dm index 10f76317897..57c11814c02 100644 --- a/code/datums/bodypart_overlays/mutant_bodypart_overlay.dm +++ b/code/datums/bodypart_overlays/mutant_bodypart_overlay.dm @@ -93,8 +93,8 @@ CRASH("External organ has no feature list, it will render invisible") ///Give the organ its color. Force will override the existing one. -/datum/bodypart_overlay/mutant/proc/inherit_color(obj/item/bodypart/ownerlimb, force) - if(isnull(ownerlimb)) +/datum/bodypart_overlay/mutant/proc/inherit_color(obj/item/bodypart/bodypart_owner, force) + if(isnull(bodypart_owner)) draw_color = null return TRUE @@ -103,14 +103,14 @@ switch(color_source) if(ORGAN_COLOR_OVERRIDE) - draw_color = override_color(ownerlimb.draw_color) + draw_color = override_color(bodypart_owner.draw_color) if(ORGAN_COLOR_INHERIT) - draw_color = ownerlimb.draw_color + draw_color = bodypart_owner.draw_color if(ORGAN_COLOR_HAIR) - if(!ishuman(ownerlimb.owner)) + if(!ishuman(bodypart_owner.owner)) return - var/mob/living/carbon/human/human_owner = ownerlimb.owner - var/obj/item/bodypart/head/my_head = human_owner.get_bodypart(BODY_ZONE_HEAD) //not always the same as ownerlimb + var/mob/living/carbon/human/human_owner = bodypart_owner.owner + var/obj/item/bodypart/head/my_head = human_owner.get_bodypart(BODY_ZONE_HEAD) //not always the same as bodypart_owner //head hair color takes priority, owner hair color is a backup if we lack a head or something if(my_head) draw_color = my_head.hair_color diff --git a/code/datums/components/crafting/crafting.dm b/code/datums/components/crafting/crafting.dm index 39c53be57d9..7f2753d6771 100644 --- a/code/datums/components/crafting/crafting.dm +++ b/code/datums/components/crafting/crafting.dm @@ -106,6 +106,10 @@ for(var/atom/movable/AM in range(radius_range, a)) if((AM.flags_1 & HOLOGRAM_1) || (blacklist && (AM.type in blacklist))) continue + if(isitem(AM)) + var/obj/item/item = AM + if(item.item_flags & ABSTRACT) //let's not tempt fate, shall we? + continue . += AM /datum/component/personal_crafting/proc/get_surroundings(atom/a, list/blacklist=null) diff --git a/code/datums/diseases/gastrolisis.dm b/code/datums/diseases/gastrolisis.dm index c3a24903b81..aab0fcded1d 100644 --- a/code/datums/diseases/gastrolisis.dm +++ b/code/datums/diseases/gastrolisis.dm @@ -40,7 +40,7 @@ var/obj/item/organ/internal/eyes/eyes = locate(/obj/item/organ/internal/eyes/snail) in affected_mob.organs if(!eyes && SPT_PROB(2.5, seconds_per_tick)) var/obj/item/organ/internal/eyes/snail/new_eyes = new() - new_eyes.Insert(affected_mob, drop_if_replaced = TRUE) + new_eyes.Insert(affected_mob) affected_mob.visible_message(span_warning("[affected_mob]'s eyes fall out, with snail eyes taking its place!"), \ span_userdanger("You scream in pain as your eyes are pushed out by your new snail eyes!")) affected_mob.emote("scream") diff --git a/code/datums/dna.dm b/code/datums/dna.dm index f3a6558ec00..6960a5e28dc 100644 --- a/code/datums/dna.dm +++ b/code/datums/dna.dm @@ -526,7 +526,6 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) update_body(is_creating = TRUE) update_mutations_overlay()// no lizard with human hulk overlay please. - /mob/proc/has_dna() return diff --git a/code/datums/mutations/body.dm b/code/datums/mutations/body.dm index 6c5243ac0ed..a02bf26d747 100644 --- a/code/datums/mutations/body.dm +++ b/code/datums/mutations/body.dm @@ -500,14 +500,16 @@ var/obj/item/organ/internal/brain/brain = owner.get_organ_slot(ORGAN_SLOT_BRAIN) if(brain) + brain.Remove(owner, special = TRUE) brain.zone = BODY_ZONE_CHEST + brain.Insert(owner, special = TRUE) var/obj/item/bodypart/head/head = owner.get_bodypart(BODY_ZONE_HEAD) if(head) owner.visible_message(span_warning("[owner]'s head splatters with a sickening crunch!"), ignored_mobs = list(owner)) new /obj/effect/gibspawner/generic(get_turf(owner), owner) - head.dismember(dam_type = BRUTE, silent = TRUE) head.drop_organs() + head.dismember(dam_type = BRUTE, silent = TRUE) qdel(head) RegisterSignal(owner, COMSIG_ATTEMPT_CARBON_ATTACH_LIMB, PROC_REF(abort_attachment)) diff --git a/code/datums/quirks/negative_quirks/junkie.dm b/code/datums/quirks/negative_quirks/junkie.dm index 269f6d2d96e..2ce29f743c3 100644 --- a/code/datums/quirks/negative_quirks/junkie.dm +++ b/code/datums/quirks/negative_quirks/junkie.dm @@ -134,7 +134,7 @@ smoker_lungs = /obj/item/organ/internal/lungs/smoker_lungs if(!isnull(smoker_lungs)) smoker_lungs = new smoker_lungs - smoker_lungs.Insert(carbon_holder, special = TRUE, drop_if_replaced = FALSE) + smoker_lungs.Insert(carbon_holder, special = TRUE, movement_flags = DELETE_IF_REPLACED) /datum/quirk/item_quirk/junkie/smoker/process(seconds_per_tick) . = ..() diff --git a/code/datums/quirks/negative_quirks/prosthetic_organ.dm b/code/datums/quirks/negative_quirks/prosthetic_organ.dm index 6330035b5a7..0fd5061a787 100644 --- a/code/datums/quirks/negative_quirks/prosthetic_organ.dm +++ b/code/datums/quirks/negative_quirks/prosthetic_organ.dm @@ -49,7 +49,7 @@ medical_record_text = "During physical examination, patient was found to have a low-budget prosthetic [slot_string]. \ Removal of these organs is known to be dangerous to the patient as well as the practitioner." old_organ = human_holder.get_organ_slot(organ_slot) - if(prosthetic.Insert(human_holder, special = TRUE, drop_if_replaced = TRUE)) + if(prosthetic.Insert(human_holder, special = TRUE)) old_organ.moveToNullspace() STOP_PROCESSING(SSobj, old_organ) diff --git a/code/datums/quirks/negative_quirks/tin_man.dm b/code/datums/quirks/negative_quirks/tin_man.dm index 5a4ab4b1357..3fea6893a75 100644 --- a/code/datums/quirks/negative_quirks/tin_man.dm +++ b/code/datums/quirks/negative_quirks/tin_man.dm @@ -30,7 +30,7 @@ for(var/organ_slot in possible_organ_slots) var/organ_path = possible_organ_slots[organ_slot] var/obj/item/organ/new_organ = new organ_path() - new_organ.Insert(human_holder, special = TRUE, drop_if_replaced = FALSE) + new_organ.Insert(human_holder, special = TRUE, movement_flags = DELETE_IF_REPLACED) /datum/quirk/tin_man/post_add() to_chat(quirk_holder, span_boldannounce("Most of your internal organs have been replaced with surplus prosthetics. They are fragile and will easily come apart under duress. \ diff --git a/code/datums/station_traits/positive_traits.dm b/code/datums/station_traits/positive_traits.dm index 2ed8a2e4bee..9b05a146555 100644 --- a/code/datums/station_traits/positive_traits.dm +++ b/code/datums/station_traits/positive_traits.dm @@ -334,7 +334,7 @@ ai.eyeobj.relay_speech = TRUE //surveillance upgrade. the ai gets cybernetics too. return var/obj/item/organ/internal/cybernetic = new cybernetic_type() - cybernetic.Insert(spawned, special = TRUE, drop_if_replaced = FALSE) + cybernetic.Insert(spawned, special = TRUE, movement_flags = DELETE_IF_REPLACED) /datum/station_trait/luxury_escape_pods name = "Luxury Escape Pods" diff --git a/code/datums/status_effects/neutral.dm b/code/datums/status_effects/neutral.dm index 50c93e7db8f..84f30ab7855 100644 --- a/code/datums/status_effects/neutral.dm +++ b/code/datums/status_effects/neutral.dm @@ -522,7 +522,7 @@ return if(prob(1))//low chance of the alternative reality returning to monkey var/obj/item/organ/external/tail/monkey/monkey_tail = new () - monkey_tail.Insert(human_mob, drop_if_replaced = FALSE) + monkey_tail.Insert(human_mob, movement_flags = DELETE_IF_REPLACED) var/datum/species/human_species = human_mob.dna?.species if(human_species) human_species.randomize_active_features(human_mob) diff --git a/code/game/machinery/dna_infuser/organ_sets/carp_organs.dm b/code/game/machinery/dna_infuser/organ_sets/carp_organs.dm index cbe6e1c31c7..afbb8404060 100644 --- a/code/game/machinery/dna_infuser/organ_sets/carp_organs.dm +++ b/code/game/machinery/dna_infuser/organ_sets/carp_organs.dm @@ -48,7 +48,7 @@ AddElement(/datum/element/noticable_organ, "teeth are big and sharp.", BODY_ZONE_PRECISE_MOUTH) AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/carp) -/obj/item/organ/internal/tongue/carp/on_insert(mob/living/carbon/tongue_owner) +/obj/item/organ/internal/tongue/carp/on_mob_insert(mob/living/carbon/tongue_owner, special, movement_flags) . = ..() if(!ishuman(tongue_owner)) return @@ -57,12 +57,14 @@ return var/datum/species/rec_species = human_receiver.dna.species rec_species.update_no_equip_flags(tongue_owner, rec_species.no_equip_flags | ITEM_SLOT_MASK) - var/obj/item/bodypart/head/head = human_receiver.get_bodypart(BODY_ZONE_HEAD) - head.unarmed_damage_low = 10 - head.unarmed_damage_high = 15 - head.unarmed_effectiveness = 15 -/obj/item/organ/internal/tongue/carp/on_remove(mob/living/carbon/tongue_owner) +/obj/item/organ/internal/tongue/carp/on_bodypart_insert(obj/item/bodypart/limb) + . = ..() + limb.unarmed_damage_low = 10 + limb.unarmed_damage_high = 15 + limb.unarmed_effectiveness = 15 + +/obj/item/organ/internal/tongue/carp/on_mob_remove(mob/living/carbon/tongue_owner) . = ..() if(!ishuman(tongue_owner)) return @@ -71,7 +73,10 @@ return var/datum/species/rec_species = human_receiver.dna.species rec_species.update_no_equip_flags(tongue_owner, initial(rec_species.no_equip_flags)) - var/obj/item/bodypart/head/head = human_receiver.get_bodypart(BODY_ZONE_HEAD) + +/obj/item/organ/internal/tongue/carp/on_bodypart_remove(obj/item/bodypart/head) + . = ..() + head.unarmed_damage_low = initial(head.unarmed_damage_low) head.unarmed_damage_high = initial(head.unarmed_damage_high) head.unarmed_effectiveness = initial(head.unarmed_effectiveness) @@ -110,13 +115,13 @@ AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/carp) AddElement(/datum/element/noticable_organ, "seem%PRONOUN_S unable to stay still.") -/obj/item/organ/internal/brain/carp/on_insert(mob/living/carbon/brain_owner) +/obj/item/organ/internal/brain/carp/on_mob_insert(mob/living/carbon/brain_owner) . = ..() cooldown_timer = addtimer(CALLBACK(src, PROC_REF(unsatisfied_nomad)), cooldown_time, TIMER_STOPPABLE|TIMER_OVERRIDE|TIMER_UNIQUE) RegisterSignal(brain_owner, COMSIG_MOVABLE_Z_CHANGED, PROC_REF(satisfied_nomad)) //technically you could get around the mood issue by extracting and reimplanting the brain but it will be far easier to just go one z there and back -/obj/item/organ/internal/brain/carp/on_remove(mob/living/carbon/brain_owner) +/obj/item/organ/internal/brain/carp/on_mob_remove(mob/living/carbon/brain_owner) . = ..() UnregisterSignal(brain_owner, COMSIG_MOVABLE_Z_CHANGED) deltimer(cooldown_timer) diff --git a/code/game/machinery/dna_infuser/organ_sets/fox_organs.dm b/code/game/machinery/dna_infuser/organ_sets/fox_organs.dm index 1b2f69f4ccc..ab33c1ad57e 100644 --- a/code/game/machinery/dna_infuser/organ_sets/fox_organs.dm +++ b/code/game/machinery/dna_infuser/organ_sets/fox_organs.dm @@ -6,7 +6,7 @@ visual = TRUE damage_multiplier = 2 -/obj/item/organ/internal/ears/fox/on_insert(mob/living/carbon/human/ear_owner) +/obj/item/organ/internal/ears/fox/on_mob_insert(mob/living/carbon/human/ear_owner) . = ..() if(istype(ear_owner) && ear_owner.dna) color = ear_owner.hair_color @@ -14,7 +14,7 @@ ear_owner.dna.update_uf_block(DNA_EARS_BLOCK) ear_owner.update_body() -/obj/item/organ/internal/ears/fox/on_remove(mob/living/carbon/human/ear_owner) +/obj/item/organ/internal/ears/fox/on_mob_remove(mob/living/carbon/human/ear_owner) . = ..() if(istype(ear_owner) && ear_owner.dna) color = ear_owner.hair_color diff --git a/code/game/machinery/dna_infuser/organ_sets/goliath_organs.dm b/code/game/machinery/dna_infuser/organ_sets/goliath_organs.dm index 6cd753eb760..477b461bdf3 100644 --- a/code/game/machinery/dna_infuser/organ_sets/goliath_organs.dm +++ b/code/game/machinery/dna_infuser/organ_sets/goliath_organs.dm @@ -66,7 +66,7 @@ AddElement(/datum/element/noticable_organ, "arm is just a mass of plate and tendrils.", BODY_ZONE_CHEST) AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/goliath) -/obj/item/organ/internal/brain/goliath/on_insert(mob/living/carbon/brain_owner) +/obj/item/organ/internal/brain/goliath/on_mob_insert(mob/living/carbon/brain_owner) . = ..() if(!ishuman(brain_owner)) return @@ -78,7 +78,7 @@ hammer = new/obj/item/goliath_infuser_hammer brain_owner.put_in_hands(hammer) -/obj/item/organ/internal/brain/goliath/on_remove(mob/living/carbon/brain_owner) +/obj/item/organ/internal/brain/goliath/on_mob_remove(mob/living/carbon/brain_owner) . = ..() UnregisterSignal(brain_owner) if(!ishuman(brain_owner)) diff --git a/code/game/machinery/dna_infuser/organ_sets/gondola_organs.dm b/code/game/machinery/dna_infuser/organ_sets/gondola_organs.dm index 515c56622c4..2a5c776709c 100644 --- a/code/game/machinery/dna_infuser/organ_sets/gondola_organs.dm +++ b/code/game/machinery/dna_infuser/organ_sets/gondola_organs.dm @@ -33,7 +33,7 @@ Fluoride Stare: After someone says 5 words, blah blah blah... AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/gondola) AddElement(/datum/element/noticable_organ, "radiate%PRONOUN_S an aura of serenity.") -/obj/item/organ/internal/heart/gondola/Insert(mob/living/carbon/receiver, special, drop_if_replaced) +/obj/item/organ/internal/heart/gondola/Insert(mob/living/carbon/receiver, special, movement_flags) . = ..() if(!(FACTION_HOSTILE in receiver.faction)) factions_to_remove += FACTION_HOSTILE @@ -41,7 +41,7 @@ Fluoride Stare: After someone says 5 words, blah blah blah... factions_to_remove += FACTION_MINING receiver.faction |= list(FACTION_HOSTILE, FACTION_MINING) -/obj/item/organ/internal/heart/gondola/Remove(mob/living/carbon/heartless, special) +/obj/item/organ/internal/heart/gondola/Remove(mob/living/carbon/heartless, special, movement_flags) . = ..() for(var/faction in factions_to_remove) heartless.faction -= faction @@ -63,11 +63,11 @@ Fluoride Stare: After someone says 5 words, blah blah blah... AddElement(/datum/element/noticable_organ, "mouth is permanently affixed into a relaxed smile.", BODY_ZONE_PRECISE_MOUTH) AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/gondola) -/obj/item/organ/internal/tongue/gondola/Insert(mob/living/carbon/tongue_owner, special, drop_if_replaced) +/obj/item/organ/internal/tongue/gondola/Insert(mob/living/carbon/tongue_owner, special, movement_flags) . = ..() tongue_owner.add_mood_event("gondola_zen", /datum/mood_event/gondola_serenity) -/obj/item/organ/internal/tongue/gondola/Remove(mob/living/carbon/tongue_owner, special) +/obj/item/organ/internal/tongue/gondola/Remove(mob/living/carbon/tongue_owner, special, movement_flags) tongue_owner.clear_mood_event("gondola_zen") return ..() @@ -89,7 +89,7 @@ Fluoride Stare: After someone says 5 words, blah blah blah... AddElement(/datum/element/noticable_organ, "right arm has small needles breaching the skin all over it.", BODY_ZONE_R_ARM) pax_hugs = new -/obj/item/organ/internal/liver/gondola/Insert(mob/living/carbon/liver_owner, special, drop_if_replaced) +/obj/item/organ/internal/liver/gondola/Insert(mob/living/carbon/liver_owner, special, movement_flags) . = ..() var/has_left = liver_owner.has_left_hand(check_disabled = FALSE) var/has_right = liver_owner.has_right_hand(check_disabled = FALSE) @@ -104,7 +104,7 @@ Fluoride Stare: After someone says 5 words, blah blah blah... RegisterSignal(liver_owner, COMSIG_HUMAN_EQUIPPING_ITEM, PROC_REF(on_owner_equipping_item)) RegisterSignal(liver_owner, COMSIG_LIVING_TRY_PULL, PROC_REF(on_owner_try_pull)) -/obj/item/organ/internal/liver/gondola/Remove(mob/living/carbon/liver_owner, special) +/obj/item/organ/internal/liver/gondola/Remove(mob/living/carbon/liver_owner, special, movement_flags) . = ..() pax_hugs.remove(liver_owner) UnregisterSignal(liver_owner, list(COMSIG_HUMAN_EQUIPPING_ITEM, COMSIG_LIVING_TRY_PULL)) diff --git a/code/game/machinery/dna_infuser/organ_sets/rat_organs.dm b/code/game/machinery/dna_infuser/organ_sets/rat_organs.dm index 96c33871a40..092a4c7889a 100644 --- a/code/game/machinery/dna_infuser/organ_sets/rat_organs.dm +++ b/code/game/machinery/dna_infuser/organ_sets/rat_organs.dm @@ -63,7 +63,7 @@ AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/rat) AddElement(/datum/element/noticable_organ, "hunch%PRONOUN_ES over unnaturally!") -/obj/item/organ/internal/heart/rat/on_insert(mob/living/carbon/receiver) +/obj/item/organ/internal/heart/rat/on_mob_insert(mob/living/carbon/receiver) . = ..() if(!. || !ishuman(receiver)) return @@ -75,7 +75,7 @@ if(human_receiver.physiology) human_receiver.physiology.damage_resistance -= 50 -/obj/item/organ/internal/heart/rat/on_remove(mob/living/carbon/heartless, special) +/obj/item/organ/internal/heart/rat/on_mob_remove(mob/living/carbon/heartless, special) . = ..() if(!ishuman(heartless)) return @@ -113,11 +113,11 @@ if(message == "hi?") speech_args[SPEECH_MESSAGE] = "Um... cheesed to meet you?" -/obj/item/organ/internal/tongue/rat/on_insert(mob/living/carbon/tongue_owner, special, drop_if_replaced) +/obj/item/organ/internal/tongue/rat/on_mob_insert(mob/living/carbon/tongue_owner, special, movement_flags) . = ..() RegisterSignal(tongue_owner, COMSIG_CARBON_ITEM_GIVEN, PROC_REF(its_on_the_mouse)) -/obj/item/organ/internal/tongue/rat/on_remove(mob/living/carbon/tongue_owner) +/obj/item/organ/internal/tongue/rat/on_mob_remove(mob/living/carbon/tongue_owner) . = ..() UnregisterSignal(tongue_owner, COMSIG_CARBON_ITEM_GIVEN) diff --git a/code/game/machinery/dna_infuser/organ_sets/roach_organs.dm b/code/game/machinery/dna_infuser/organ_sets/roach_organs.dm index f10c9b039f2..0644bca0354 100644 --- a/code/game/machinery/dna_infuser/organ_sets/roach_organs.dm +++ b/code/game/machinery/dna_infuser/organ_sets/roach_organs.dm @@ -71,7 +71,7 @@ QDEL_NULL(roach_shell) return ..() -/obj/item/organ/internal/heart/roach/on_insert(mob/living/carbon/organ_owner, special) +/obj/item/organ/internal/heart/roach/on_mob_insert(mob/living/carbon/organ_owner, special) . = ..() if(!ishuman(organ_owner)) return @@ -82,11 +82,11 @@ RegisterSignal(human_owner, COMSIG_MOB_AFTER_APPLY_DAMAGE, PROC_REF(do_block_effect)) human_owner.physiology.knockdown_mod *= 3 - var/obj/item/bodypart/chest/chest = human_owner.get_bodypart(BODY_ZONE_CHEST) - chest.add_bodypart_overlay(roach_shell) - human_owner.update_body_parts() +/obj/item/organ/internal/heart/roach/on_bodypart_insert(obj/item/bodypart/limb) + . = ..() + limb.add_bodypart_overlay(roach_shell) -/obj/item/organ/internal/heart/roach/on_remove(mob/living/carbon/organ_owner, special) +/obj/item/organ/internal/heart/roach/on_mob_remove(mob/living/carbon/organ_owner, special) . = ..() if(!ishuman(organ_owner) || QDELETED(organ_owner)) return @@ -96,9 +96,10 @@ UnregisterSignal(human_owner, list(COMSIG_MOB_APPLY_DAMAGE_MODIFIERS, COMSIG_MOB_AFTER_APPLY_DAMAGE)) human_owner.physiology.knockdown_mod /= 3 - var/obj/item/bodypart/chest/chest = human_owner.get_bodypart(BODY_ZONE_CHEST) - chest.remove_bodypart_overlay(roach_shell) - human_owner.update_body_parts() +/obj/item/organ/internal/heart/roach/on_bodypart_remove(obj/item/bodypart/limb) + . = ..() + + limb.remove_bodypart_overlay(roach_shell) /** * Signal proc for [COMSIG_MOB_APPLY_DAMAGE_MODIFIERS] @@ -193,7 +194,7 @@ . = ..() AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/roach) -/obj/item/organ/internal/liver/roach/on_insert(mob/living/carbon/organ_owner, special) +/obj/item/organ/internal/liver/roach/on_mob_insert(mob/living/carbon/organ_owner, special) . = ..() if(!ishuman(organ_owner)) return @@ -201,13 +202,13 @@ var/mob/living/carbon/human/human_owner = owner human_owner.physiology.tox_mod *= 2 -/obj/item/organ/internal/liver/roach/on_remove(mob/living/carbon/organ_owner, special) +/obj/item/organ/internal/liver/roach/on_mob_remove(mob/living/carbon/organ_owner, special) . = ..() if(!ishuman(organ_owner) || QDELETED(organ_owner)) return var/mob/living/carbon/human/human_owner = organ_owner - human_owner.physiology.tox_mod /= 2 + human_owner.physiology.tox_mod *= 0.5 /// Roach appendix: /// No appendicitus! weee! diff --git a/code/game/machinery/recycler.dm b/code/game/machinery/recycler.dm index a17d9b845b0..50751d95b5f 100644 --- a/code/game/machinery/recycler.dm +++ b/code/game/machinery/recycler.dm @@ -151,6 +151,10 @@ var/obj/item/mmi/as_mmi = thing if(istype(thing, /obj/item/organ/internal/brain) || (istype(as_head) && as_head.brain) || (istype(as_mmi) && as_mmi.brain) || istype(thing, /obj/item/dullahan_relay)) living_detected = TRUE + if(isitem(as_object)) + var/obj/item/as_item = as_object + if(as_item.item_flags & ABSTRACT) //also catches organs and bodyparts *stares* + continue nom += thing else if(isliving(thing)) living_detected = TRUE diff --git a/code/game/objects/items/body_egg.dm b/code/game/objects/items/body_egg.dm index f95b9f2e164..d244d8c55cc 100644 --- a/code/game/objects/items/body_egg.dm +++ b/code/game/objects/items/body_egg.dm @@ -15,7 +15,7 @@ if(iscarbon(loc)) Insert(loc) -/obj/item/organ/internal/body_egg/Insert(mob/living/carbon/egg_owner, special = FALSE, drop_if_replaced = TRUE) +/obj/item/organ/internal/body_egg/Insert(mob/living/carbon/egg_owner, special = FALSE, movement_flags = DELETE_IF_REPLACED) . = ..() if(!.) return @@ -23,7 +23,7 @@ egg_owner.med_hud_set_status() INVOKE_ASYNC(src, PROC_REF(AddInfectionImages), egg_owner) -/obj/item/organ/internal/body_egg/Remove(mob/living/carbon/egg_owner, special = FALSE) +/obj/item/organ/internal/body_egg/Remove(mob/living/carbon/egg_owner, special, movement_flags) . = ..() egg_owner.remove_traits(list(TRAIT_XENO_HOST, TRAIT_XENO_IMMUNE), ORGAN_TRAIT) egg_owner.med_hud_set_status() diff --git a/code/game/turfs/open/lava.dm b/code/game/turfs/open/lava.dm index cce5a49e993..8b3fcb9f00a 100644 --- a/code/game/turfs/open/lava.dm +++ b/code/game/turfs/open/lava.dm @@ -418,7 +418,7 @@ if(BODY_ZONE_HEAD) plasmalimb = new /obj/item/bodypart/head/plasmaman - burn_human.del_and_replace_bodypart(plasmalimb) + burn_human.del_and_replace_bodypart(plasmalimb, special = TRUE) burn_human.update_body_parts() burn_human.emote("scream") burn_human.visible_message(span_warning("[burn_human]'s [burn_limb.plaintext_zone] melts down to the bone!"), \ diff --git a/code/modules/admin/verbs/admin.dm b/code/modules/admin/verbs/admin.dm index e62936ea413..1c0bd7806db 100644 --- a/code/modules/admin/verbs/admin.dm +++ b/code/modules/admin/verbs/admin.dm @@ -176,6 +176,10 @@ for(var/obj/item/W in M) if(!M.dropItemToGround(W)) + // I hate that this is necessary, but the code is literally just dropping or deleting everything otherwise + // people should be allowed to keep their fucking organs + if(istype(W, /obj/item/organ) || istype(W, /obj/item/bodypart)) + continue qdel(W) M.regenerate_icons() diff --git a/code/modules/admin/verbs/secrets.dm b/code/modules/admin/verbs/secrets.dm index 6e26fb9754a..2a355e21714 100644 --- a/code/modules/admin/verbs/secrets.dm +++ b/code/modules/admin/verbs/secrets.dm @@ -506,8 +506,8 @@ GLOBAL_DATUM(everyone_a_traitor, /datum/everyone_is_a_traitor_controller) if(H.dna.features["tail_human"] == "None" || H.dna.features["ears"] == "None") var/obj/item/organ/internal/ears/cat/ears = new var/obj/item/organ/external/tail/cat/tail = new - ears.Insert(H, drop_if_replaced=FALSE) - tail.Insert(H, drop_if_replaced=FALSE) + ears.Insert(H, movement_flags = DELETE_IF_REPLACED) + tail.Insert(H, movement_flags = DELETE_IF_REPLACED) var/list/honorifics = list("[MALE]" = list("kun"), "[FEMALE]" = list("chan","tan"), "[NEUTER]" = list("san"), "[PLURAL]" = list("san")) //John Robust -> Robust-kun var/list/names = splittext(H.real_name," ") var/forename = names.len > 1 ? names[2] : names[1] diff --git a/code/modules/antagonists/abductor/equipment/gland.dm b/code/modules/antagonists/abductor/equipment/gland.dm index e29388c9fd6..960851280e3 100644 --- a/code/modules/antagonists/abductor/equipment/gland.dm +++ b/code/modules/antagonists/abductor/equipment/gland.dm @@ -84,7 +84,7 @@ active_mind_control = FALSE return TRUE -/obj/item/organ/internal/heart/gland/Remove(mob/living/carbon/gland_owner, special = FALSE) +/obj/item/organ/internal/heart/gland/Remove(mob/living/carbon/gland_owner, special, movement_flags) . = ..() active = FALSE if(initial(uses) == 1) @@ -93,7 +93,7 @@ hud.remove_atom_from_hud(gland_owner) clear_mind_control() -/obj/item/organ/internal/heart/gland/Insert(mob/living/carbon/gland_owner, special = FALSE, drop_if_replaced = TRUE) +/obj/item/organ/internal/heart/gland/Insert(mob/living/carbon/gland_owner, special = FALSE, movement_flags = DELETE_IF_REPLACED) . = ..() if(!.) return diff --git a/code/modules/antagonists/abductor/equipment/glands/electric.dm b/code/modules/antagonists/abductor/equipment/glands/electric.dm index a3107af0217..a5ec2cfde21 100644 --- a/code/modules/antagonists/abductor/equipment/glands/electric.dm +++ b/code/modules/antagonists/abductor/equipment/glands/electric.dm @@ -7,11 +7,11 @@ mind_control_uses = 2 mind_control_duration = 900 -/obj/item/organ/internal/heart/gland/electric/on_insert(mob/living/carbon/gland_owner) +/obj/item/organ/internal/heart/gland/electric/on_mob_insert(mob/living/carbon/gland_owner) . = ..() ADD_TRAIT(gland_owner, TRAIT_SHOCKIMMUNE, ABDUCTOR_GLAND_TRAIT) -/obj/item/organ/internal/heart/gland/electric/on_remove(mob/living/carbon/gland_owner) +/obj/item/organ/internal/heart/gland/electric/on_mob_remove(mob/living/carbon/gland_owner) . = ..() REMOVE_TRAIT(gland_owner, TRAIT_SHOCKIMMUNE, ABDUCTOR_GLAND_TRAIT) diff --git a/code/modules/antagonists/abductor/equipment/glands/slime.dm b/code/modules/antagonists/abductor/equipment/glands/slime.dm index 60e680bc2a9..853f0bb6473 100644 --- a/code/modules/antagonists/abductor/equipment/glands/slime.dm +++ b/code/modules/antagonists/abductor/equipment/glands/slime.dm @@ -7,12 +7,12 @@ mind_control_uses = 1 mind_control_duration = 2400 -/obj/item/organ/internal/heart/gland/slime/on_insert(mob/living/carbon/gland_owner) +/obj/item/organ/internal/heart/gland/slime/on_mob_insert(mob/living/carbon/gland_owner) . = ..() gland_owner.faction |= FACTION_SLIME gland_owner.grant_language(/datum/language/slime, source = LANGUAGE_GLAND) -/obj/item/organ/internal/heart/gland/slime/on_remove(mob/living/carbon/gland_owner) +/obj/item/organ/internal/heart/gland/slime/on_mob_remove(mob/living/carbon/gland_owner) . = ..() gland_owner.faction -= FACTION_SLIME gland_owner.remove_language(/datum/language/slime, source = LANGUAGE_GLAND) diff --git a/code/modules/antagonists/fugitive/fugitive_outfits.dm b/code/modules/antagonists/fugitive/fugitive_outfits.dm index ba1fe87bfbb..3efab657101 100644 --- a/code/modules/antagonists/fugitive/fugitive_outfits.dm +++ b/code/modules/antagonists/fugitive/fugitive_outfits.dm @@ -67,7 +67,7 @@ if(visualsOnly) return var/obj/item/organ/internal/eyes/robotic/glow/eyes = new() - eyes.Insert(H, drop_if_replaced = FALSE) + eyes.Insert(H, movement_flags = DELETE_IF_REPLACED) /datum/outfit/invisible_man name = "Invisible Man" diff --git a/code/modules/antagonists/heretic/knowledge/lock_lore.dm b/code/modules/antagonists/heretic/knowledge/lock_lore.dm index 6c6df4c6567..3550e287b6a 100644 --- a/code/modules/antagonists/heretic/knowledge/lock_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/lock_lore.dm @@ -199,8 +199,7 @@ for(var/mob/living/carbon/human/body in atoms) if(body.stat != DEAD) continue - var/obj/item/bodypart/chest = body.get_bodypart(BODY_ZONE_CHEST) - if(LAZYLEN(chest.get_organs())) + if(LAZYLEN(body.get_organs_for_zone(BODY_ZONE_CHEST))) to_chat(user, span_hierophant_warning("[body] has organs in their chest.")) continue diff --git a/code/modules/antagonists/heretic/transmutation_rune.dm b/code/modules/antagonists/heretic/transmutation_rune.dm index 55ca897342f..efd53418a78 100644 --- a/code/modules/antagonists/heretic/transmutation_rune.dm +++ b/code/modules/antagonists/heretic/transmutation_rune.dm @@ -80,6 +80,10 @@ for(var/atom/close_atom as anything in range(1, src)) if(!ismovable(close_atom)) continue + if(isitem(close_atom)) + var/obj/item/close_item = close_atom + if(close_item.item_flags & ABSTRACT) //woops sacrificed your own head + continue if(close_atom.invisibility) continue if(close_atom == user) diff --git a/code/modules/antagonists/nightmare/nightmare_organs.dm b/code/modules/antagonists/nightmare/nightmare_organs.dm index ce5ff427a21..fc3a4c52667 100644 --- a/code/modules/antagonists/nightmare/nightmare_organs.dm +++ b/code/modules/antagonists/nightmare/nightmare_organs.dm @@ -14,8 +14,10 @@ ///Our associated terrorize spell, for antagonist nightmares var/datum/action/cooldown/spell/pointed/terrorize/terrorize_spell -/obj/item/organ/internal/brain/shadow/nightmare/on_insert(mob/living/carbon/brain_owner) +/obj/item/organ/internal/brain/shadow/nightmare/on_mob_insert(mob/living/carbon/brain_owner) . = ..() + RegisterSignal(brain_owner, COMSIG_ATOM_PRE_BULLET_ACT, PROC_REF(dodge_bullets)) + if(brain_owner.dna.species.id != SPECIES_NIGHTMARE) brain_owner.set_species(/datum/species/shadow/nightmare) visible_message(span_warning("[brain_owner] thrashes as [src] takes root in [brain_owner.p_their()] body!")) @@ -27,9 +29,7 @@ terrorize_spell = new(src) terrorize_spell.Grant(brain_owner) - RegisterSignal(brain_owner, COMSIG_ATOM_PRE_BULLET_ACT, PROC_REF(dodge_bullets)) - -/obj/item/organ/internal/brain/shadow/nightmare/on_remove(mob/living/carbon/brain_owner) +/obj/item/organ/internal/brain/shadow/nightmare/on_mob_remove(mob/living/carbon/brain_owner) . = ..() QDEL_NULL(our_jaunt) QDEL_NULL(terrorize_spell) @@ -76,13 +76,13 @@ user.temporarilyRemoveItemFromInventory(src, TRUE) Insert(user) -/obj/item/organ/internal/heart/nightmare/on_insert(mob/living/carbon/heart_owner, special) +/obj/item/organ/internal/heart/nightmare/on_mob_insert(mob/living/carbon/heart_owner, special) . = ..() if(special != HEART_SPECIAL_SHADOWIFY) blade = new/obj/item/light_eater heart_owner.put_in_hands(blade) -/obj/item/organ/internal/heart/nightmare/on_remove(mob/living/carbon/heart_owner, special) +/obj/item/organ/internal/heart/nightmare/on_mob_remove(mob/living/carbon/heart_owner, special) . = ..() respawn_progress = 0 if(blade && special != HEART_SPECIAL_SHADOWIFY) diff --git a/code/modules/jobs/job_types/chaplain/chaplain_vorpal_scythe.dm b/code/modules/jobs/job_types/chaplain/chaplain_vorpal_scythe.dm index 3e752910a29..0dffeda5781 100644 --- a/code/modules/jobs/job_types/chaplain/chaplain_vorpal_scythe.dm +++ b/code/modules/jobs/job_types/chaplain/chaplain_vorpal_scythe.dm @@ -10,7 +10,7 @@ If the scythe isn't empowered when you sheath it, you take a heap of damage and desc = "This shard seems to be directly linked to some sinister entity. It might be your god! It also gives you a really horrible rash when you hold onto it for too long." items_to_create = list(/obj/item/vorpalscythe) -/obj/item/organ/internal/cyberimp/arm/shard/scythe/Insert(mob/living/carbon/receiver, special, drop_if_replaced) +/obj/item/organ/internal/cyberimp/arm/shard/scythe/Insert(mob/living/carbon/receiver, special, movement_flags) . = ..() if(receiver.mind) ADD_TRAIT(receiver.mind, TRAIT_MORBID, ORGAN_TRAIT) diff --git a/code/modules/library/skill_learning/skillchip.dm b/code/modules/library/skill_learning/skillchip.dm index a58fbec7c75..2ef7a20e680 100644 --- a/code/modules/library/skill_learning/skillchip.dm +++ b/code/modules/library/skill_learning/skillchip.dm @@ -106,7 +106,7 @@ return "Skillchip is not active." // Should not happen. Holding brain is destroyed and the chip hasn't had its state set appropriately. - if(QDELETED(holding_brain)) + if(!holding_brain) stack_trace("Skillchip's owner is null or qdeleted brain.") return "Skillchip cannot detect viable brain." diff --git a/code/modules/mining/equipment/monster_organs/monster_organ.dm b/code/modules/mining/equipment/monster_organs/monster_organ.dm index 699564c9ed7..8c1b031171f 100644 --- a/code/modules/mining/equipment/monster_organs/monster_organ.dm +++ b/code/modules/mining/equipment/monster_organs/monster_organ.dm @@ -69,7 +69,7 @@ deltimer(decay_timer) return ..() -/obj/item/organ/internal/monster_core/Insert(mob/living/carbon/target_carbon, special = FALSE, drop_if_replaced = TRUE) +/obj/item/organ/internal/monster_core/Insert(mob/living/carbon/target_carbon, special = FALSE, movement_flags) . = ..() if(!.) return @@ -83,7 +83,7 @@ target_carbon.visible_message(span_notice("[src] stabilizes as it's inserted.")) return TRUE -/obj/item/organ/internal/monster_core/Remove(mob/living/carbon/target_carbon, special = 0) +/obj/item/organ/internal/monster_core/Remove(mob/living/carbon/target_carbon, special, movement_flags) if (!inert && !special) owner.visible_message(span_notice("[src] rapidly decays as it's removed.")) go_inert() diff --git a/code/modules/mining/equipment/monster_organs/rush_gland.dm b/code/modules/mining/equipment/monster_organs/rush_gland.dm index 3554d67b2a6..b3932afdaab 100644 --- a/code/modules/mining/equipment/monster_organs/rush_gland.dm +++ b/code/modules/mining/equipment/monster_organs/rush_gland.dm @@ -21,11 +21,11 @@ if (owner.health <= HEALTH_DANGER_ZONE) trigger_organ_action() -/obj/item/organ/internal/monster_core/rush_gland/on_insert(mob/living/carbon/organ_owner) +/obj/item/organ/internal/monster_core/rush_gland/on_mob_insert(mob/living/carbon/organ_owner) . = ..() RegisterSignal(organ_owner, COMSIG_GOLIATH_TENTACLED_GRABBED, PROC_REF(trigger_organ_action)) -/obj/item/organ/internal/monster_core/rush_gland/on_remove(mob/living/carbon/organ_owner, special) +/obj/item/organ/internal/monster_core/rush_gland/on_mob_remove(mob/living/carbon/organ_owner, special) . = ..() UnregisterSignal(organ_owner, COMSIG_GOLIATH_TENTACLED_GRABBED) diff --git a/code/modules/mob/living/basic/lavaland/legion/legion.dm b/code/modules/mob/living/basic/lavaland/legion/legion.dm index 080f397226e..3a18a0703e6 100644 --- a/code/modules/mob/living/basic/lavaland/legion/legion.dm +++ b/code/modules/mob/living/basic/lavaland/legion/legion.dm @@ -83,7 +83,7 @@ return // Congratulations you have won a special prize: cancer var/obj/item/organ/internal/legion_tumour/cancer = new() - cancer.Insert(consumed, special = TRUE, drop_if_replaced = FALSE) + cancer.Insert(consumed, special = TRUE, movement_flags = DELETE_IF_REPLACED) /// A Legion which only drops skeletons instead of corpses which might have fun loot, so it cannot be farmed diff --git a/code/modules/mob/living/basic/lavaland/legion/legion_tumour.dm b/code/modules/mob/living/basic/lavaland/legion/legion_tumour.dm index 078af57de2a..55c1e6426b3 100644 --- a/code/modules/mob/living/basic/lavaland/legion/legion_tumour.dm +++ b/code/modules/mob/living/basic/lavaland/legion/legion_tumour.dm @@ -50,7 +50,7 @@ animate(transform = matrix(), time = 0.5 SECONDS / speed_divider, easing = SINE_EASING | EASE_IN) animate(transform = matrix(), time = 2 SECONDS / speed_divider) -/obj/item/organ/internal/legion_tumour/Remove(mob/living/carbon/egg_owner, special) +/obj/item/organ/internal/legion_tumour/Remove(mob/living/carbon/egg_owner, special, movement_flags) . = ..() stage = 0 elapsed_time = 0 diff --git a/code/modules/mob/living/basic/space_fauna/demon/demon_items.dm b/code/modules/mob/living/basic/space_fauna/demon/demon_items.dm index 8cdd7a6cf53..1cc7549f0ea 100644 --- a/code/modules/mob/living/basic/space_fauna/demon/demon_items.dm +++ b/code/modules/mob/living/basic/space_fauna/demon/demon_items.dm @@ -33,13 +33,13 @@ user.temporarilyRemoveItemFromInventory(src, TRUE) src.Insert(user) //Consuming the heart literally replaces your heart with a demon heart. H A R D C O R E -/obj/item/organ/internal/heart/demon/on_insert(mob/living/carbon/heart_owner) +/obj/item/organ/internal/heart/demon/on_mob_insert(mob/living/carbon/heart_owner) . = ..() // Gives a non-eat-people crawl to the new owner var/datum/action/cooldown/spell/jaunt/bloodcrawl/crawl = new(heart_owner) crawl.Grant(heart_owner) -/obj/item/organ/internal/heart/demon/on_remove(mob/living/carbon/heart_owner, special = FALSE) +/obj/item/organ/internal/heart/demon/on_mob_remove(mob/living/carbon/heart_owner, special = FALSE) . = ..() var/datum/action/cooldown/spell/jaunt/bloodcrawl/crawl = locate() in heart_owner.actions qdel(crawl) diff --git a/code/modules/mob/living/blood.dm b/code/modules/mob/living/blood.dm index bc0d2e3d8e8..0818532cc4d 100644 --- a/code/modules/mob/living/blood.dm +++ b/code/modules/mob/living/blood.dm @@ -286,7 +286,7 @@ return /datum/reagent/blood /mob/living/carbon/human/get_blood_id() - if(HAS_TRAIT(src, TRAIT_HUSK)) + if(HAS_TRAIT(src, TRAIT_HUSK) || !dna) return if(check_holidays(APRIL_FOOLS) && is_clown_job(mind?.assigned_role)) return /datum/reagent/colorful_reagent diff --git a/code/modules/mob/living/brain/brain_item.dm b/code/modules/mob/living/brain/brain_item.dm index 8f29a7d2be7..b09513c42de 100644 --- a/code/modules/mob/living/brain/brain_item.dm +++ b/code/modules/mob/living/brain/brain_item.dm @@ -47,7 +47,14 @@ // Brain size logic transform = transform.Scale(brain_size) -/obj/item/organ/internal/brain/Insert(mob/living/carbon/brain_owner, special = FALSE, drop_if_replaced = TRUE, no_id_transfer = FALSE) +/obj/item/organ/internal/brain/examine() + . = ..() + if(brain_size < 1) + . += span_notice("It is a bit on the smaller side...") + if(brain_size > 1) + . += span_notice("It is bigger than average...") + +/obj/item/organ/internal/brain/mob_insert(mob/living/carbon/brain_owner, special = FALSE, movement_flags) . = ..() if(!.) return @@ -55,7 +62,7 @@ name = initial(name) // Special check for if you're trapped in a body you can't control because it's owned by a ling. - if(brain_owner?.mind?.has_antag_datum(/datum/antagonist/changeling) && !no_id_transfer) + if(brain_owner?.mind?.has_antag_datum(/datum/antagonist/changeling) && !(movement_flags & NO_ID_TRANSFER)) if(brainmob && !(brain_owner.stat == DEAD || (HAS_TRAIT(brain_owner, TRAIT_DEATHCOMA)))) to_chat(brainmob, span_danger("You can't feel your body! You're still just a brain!")) forceMove(brain_owner) @@ -102,25 +109,11 @@ //Update the body's icon so it doesnt appear debrained anymore brain_owner.update_body_parts() -/obj/item/organ/internal/brain/on_insert(mob/living/carbon/organ_owner, special) - // Are we inserting into a new mob from a head? - // If yes, we want to quickly steal the brainmob from the head before we do anything else. - // This is usually stuff like reattaching dismembered/amputated heads. - if(istype(loc, /obj/item/bodypart/head)) - var/obj/item/bodypart/head/brain_holder = loc - if(brain_holder.brainmob) - brainmob = brain_holder.brainmob - brain_holder.brainmob = null - brainmob.container = null - brainmob.forceMove(src) - - return ..() - -/obj/item/organ/internal/brain/Remove(mob/living/carbon/brain_owner, special = 0, no_id_transfer = FALSE) +/obj/item/organ/internal/brain/mob_remove(mob/living/carbon/organ_owner, special, movement_flags) // Delete skillchips first as parent proc sets owner to null, and skillchips need to know the brain's owner. - if(!QDELETED(brain_owner) && length(skillchips)) + if(!QDELETED(organ_owner) && length(skillchips)) if(!special) - to_chat(brain_owner, span_notice("You feel your skillchips enable emergency power saving mode, deactivating as your brain leaves your body...")) + to_chat(organ_owner, span_notice("You feel your skillchips enable emergency power saving mode, deactivating as your brain leaves your body...")) for(var/chip in skillchips) var/obj/item/skillchip/skillchip = chip // Run the try_ proc with force = TRUE. @@ -133,10 +126,11 @@ BT.on_lose(TRUE) BT.owner = null - if((!gc_destroyed || (owner && !owner.gc_destroyed)) && !no_id_transfer) - transfer_identity(brain_owner) - brain_owner.update_body_parts() - brain_owner.clear_mood_event("brain_damage") + if((!gc_destroyed || (owner && !owner.gc_destroyed)) && !(movement_flags & NO_ID_TRANSFER)) + transfer_identity(organ_owner) + if(!special) + organ_owner.update_body_parts() + organ_owner.clear_mood_event("brain_damage") /obj/item/organ/internal/brain/proc/transfer_identity(mob/living/L) name = "[L.name]'s [initial(name)]" @@ -417,11 +411,11 @@ icon_state = "random_fly_4" organ_traits = list(TRAIT_ADVANCEDTOOLUSER, TRAIT_LITERATE, TRAIT_CAN_STRIP) -/obj/item/organ/internal/brain/lustrous/before_organ_replacement(mob/living/carbon/organ_owner, special) +/obj/item/organ/internal/brain/lustrous/on_mob_remove(mob/living/carbon/organ_owner, special) . = ..() organ_owner.cure_trauma_type(/datum/brain_trauma/special/bluespace_prophet, TRAUMA_RESILIENCE_ABSOLUTE) -/obj/item/organ/internal/brain/lustrous/on_insert(mob/living/carbon/organ_owner, special) +/obj/item/organ/internal/brain/lustrous/on_mob_insert(mob/living/carbon/organ_owner, special) . = ..() organ_owner.gain_trauma(/datum/brain_trauma/special/bluespace_prophet, TRAUMA_RESILIENCE_ABSOLUTE) @@ -580,6 +574,6 @@ /// Brains REALLY like ghosting people. we need special tricks to avoid that, namely removing the old brain with no_id_transfer /obj/item/organ/internal/brain/replace_into(mob/living/carbon/new_owner) var/obj/item/organ/internal/brain/old_brain = new_owner.get_organ_slot(ORGAN_SLOT_BRAIN) - old_brain.Remove(new_owner, special = TRUE, no_id_transfer = TRUE) + old_brain.Remove(new_owner, special = TRUE, movement_flags = NO_ID_TRANSFER) qdel(old_brain) - return Insert(new_owner, special = TRUE, drop_if_replaced = FALSE, no_id_transfer = TRUE) + return Insert(new_owner, special = TRUE, movement_flags = NO_ID_TRANSFER | DELETE_IF_REPLACED) diff --git a/code/modules/mob/living/carbon/alien/organs.dm b/code/modules/mob/living/carbon/alien/organs.dm index a29b126dd8d..66f555b639a 100644 --- a/code/modules/mob/living/carbon/alien/organs.dm +++ b/code/modules/mob/living/carbon/alien/organs.dm @@ -69,14 +69,14 @@ else owner.adjustPlasma(0.1 * plasma_rate * delta_time) -/obj/item/organ/internal/alien/plasmavessel/on_insert(mob/living/carbon/organ_owner) +/obj/item/organ/internal/alien/plasmavessel/on_mob_insert(mob/living/carbon/organ_owner) . = ..() if(isalien(organ_owner)) var/mob/living/carbon/alien/target_alien = organ_owner target_alien.updatePlasmaDisplay() RegisterSignal(organ_owner, COMSIG_MOB_GET_STATUS_TAB_ITEMS, PROC_REF(get_status_tab_item)) -/obj/item/organ/internal/alien/plasmavessel/on_remove(mob/living/carbon/organ_owner) +/obj/item/organ/internal/alien/plasmavessel/on_mob_remove(mob/living/carbon/organ_owner) . = ..() if(isalien(organ_owner)) var/mob/living/carbon/alien/organ_owner_alien = organ_owner @@ -95,18 +95,18 @@ zone = BODY_ZONE_HEAD slot = ORGAN_SLOT_XENO_HIVENODE w_class = WEIGHT_CLASS_TINY + organ_traits = list(TRAIT_XENO_IMMUNE) actions_types = list(/datum/action/cooldown/alien/whisper) /// Indicates if the queen died recently, aliens are heavily weakened while this is active. var/recent_queen_death = FALSE -/obj/item/organ/internal/alien/hivenode/on_insert(mob/living/carbon/organ_owner) +/obj/item/organ/internal/alien/hivenode/on_mob_insert(mob/living/carbon/organ_owner) . = ..() organ_owner.faction |= ROLE_ALIEN - ADD_TRAIT(organ_owner, TRAIT_XENO_IMMUNE, ORGAN_TRAIT) -/obj/item/organ/internal/alien/hivenode/Remove(mob/living/carbon/organ_owner, special = FALSE) - organ_owner.faction -= ROLE_ALIEN - REMOVE_TRAIT(organ_owner, TRAIT_XENO_IMMUNE, ORGAN_TRAIT) +/obj/item/organ/internal/alien/hivenode/on_mob_remove(mob/living/carbon/organ_owner, special = FALSE) + if(organ_owner) + organ_owner.faction -= ROLE_ALIEN return ..() //When the alien queen dies, all aliens suffer a penalty as punishment for failing to protect her. @@ -232,11 +232,11 @@ stomach_contents -= source UnregisterSignal(source, list(COMSIG_MOVABLE_MOVED, COMSIG_LIVING_DEATH, COMSIG_QDELETING)) -/obj/item/organ/internal/stomach/alien/Insert(mob/living/carbon/stomach_owner, special = FALSE, drop_if_replaced = TRUE) +/obj/item/organ/internal/stomach/alien/Insert(mob/living/carbon/stomach_owner, special, movement_flags) RegisterSignal(stomach_owner, COMSIG_ATOM_RELAYMOVE, PROC_REF(something_moved)) return ..() -/obj/item/organ/internal/stomach/alien/Remove(mob/living/carbon/stomach_owner, special = FALSE) +/obj/item/organ/internal/stomach/alien/Remove(mob/living/carbon/stomach_owner, special, movement_flags) UnregisterSignal(stomach_owner, COMSIG_ATOM_RELAYMOVE) return ..() diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 01ef424b00f..a6761f85cbc 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -979,7 +979,6 @@ for(var/obj/item/bodypart/bodypart_path as anything in bodyparts_paths) var/real_body_part_path = overrides?[initial(bodypart_path.body_zone)] || bodypart_path var/obj/item/bodypart/bodypart_instance = new real_body_part_path() - bodypart_instance.set_owner(src) add_bodypart(bodypart_instance) /// Called when a new hand is added @@ -996,8 +995,12 @@ /mob/living/carbon/proc/add_bodypart(obj/item/bodypart/new_bodypart) SHOULD_NOT_OVERRIDE(TRUE) + new_bodypart.on_adding(src) bodyparts += new_bodypart - new_bodypart.set_owner(src) + new_bodypart.update_owner(src) + + for(var/obj/item/organ/organ in new_bodypart) + organ.mob_insert(src) switch(new_bodypart.body_part) if(LEG_LEFT, LEG_RIGHT) @@ -1012,10 +1015,17 @@ synchronize_bodytypes() ///Proc to hook behavior on bodypart removals. Do not directly call. You're looking for [/obj/item/bodypart/proc/drop_limb()]. -/mob/living/carbon/proc/remove_bodypart(obj/item/bodypart/old_bodypart) +/mob/living/carbon/proc/remove_bodypart(obj/item/bodypart/old_bodypart, special) SHOULD_NOT_OVERRIDE(TRUE) - old_bodypart.on_removal() + if(special) + for(var/obj/item/organ/organ in old_bodypart) + organ.bodypart_remove(limb_owner = src, movement_flags = NO_ID_TRANSFER) + else + for(var/obj/item/organ/organ in old_bodypart) + organ.mob_remove(src, special) + + old_bodypart.on_removal(src) bodyparts -= old_bodypart switch(old_bodypart.body_part) @@ -1413,3 +1423,8 @@ our_splatter.blood_dna_info = get_blood_dna_list() var/turf/targ = get_ranged_target_turf(src, splatter_direction, splatter_strength) our_splatter.fly_towards(targ, splatter_strength) + +/mob/living/carbon/dropItemToGround(obj/item/item, force = FALSE, silent = FALSE, invdrop = TRUE) + if(item && ((item in organs) || (item in bodyparts))) //let's not do this, aight? + return FALSE + return ..() diff --git a/code/modules/mob/living/carbon/death.dm b/code/modules/mob/living/carbon/death.dm index 78b8554361b..85a6b06a2d3 100644 --- a/code/modules/mob/living/carbon/death.dm +++ b/code/modules/mob/living/carbon/death.dm @@ -28,9 +28,9 @@ add_memory_in_range(src, 7, /datum/memory/witness_gib, protagonist = src) if(drop_bitflags & DROP_ITEMS) for(var/obj/item/W in src) - dropItemToGround(W) - if(prob(50)) - step(W, pick(GLOB.alldirs)) + if(dropItemToGround(W)) + if(prob(50)) + step(W, pick(GLOB.alldirs)) var/atom/Tsec = drop_location() for(var/mob/M in src) M.forceMove(Tsec) diff --git a/code/modules/mob/living/carbon/human/_species.dm b/code/modules/mob/living/carbon/human/_species.dm index e67651f0ce6..f0d4e644c4d 100644 --- a/code/modules/mob/living/carbon/human/_species.dm +++ b/code/modules/mob/living/carbon/human/_species.dm @@ -370,19 +370,17 @@ GLOBAL_LIST_EMPTY(features_by_species) health_pct = (existing_organ.maxHealth - existing_organ.damage) / existing_organ.maxHealth if(slot == ORGAN_SLOT_BRAIN) var/obj/item/organ/internal/brain/existing_brain = existing_organ - if(!existing_brain.decoy_override) - existing_brain.before_organ_replacement(new_organ) - existing_brain.Remove(organ_holder, special = TRUE, no_id_transfer = TRUE) - QDEL_NULL(existing_organ) + existing_brain.before_organ_replacement(new_organ) + existing_brain.Remove(organ_holder, special = TRUE, movement_flags = NO_ID_TRANSFER) else existing_organ.before_organ_replacement(new_organ) existing_organ.Remove(organ_holder, special = TRUE) - QDEL_NULL(existing_organ) - if(isnull(existing_organ) && should_have && !(new_organ.zone in excluded_zones)) + QDEL_NULL(existing_organ) + if(isnull(existing_organ) && should_have && !(new_organ.zone in excluded_zones) && organ_holder.get_bodypart(deprecise_zone(new_organ.zone))) used_neworgan = TRUE new_organ.set_organ_damage(new_organ.maxHealth * (1 - health_pct)) - new_organ.Insert(organ_holder, special = TRUE, drop_if_replaced = FALSE) + new_organ.Insert(organ_holder, special = TRUE, movement_flags = DELETE_IF_REPLACED) if(!used_neworgan) QDEL_NULL(new_organ) @@ -425,7 +423,7 @@ GLOBAL_LIST_EMPTY(features_by_species) if(current_organ) current_organ.before_organ_replacement(replacement) // organ.Insert will qdel any current organs in that slot, so we don't need to. - replacement.Insert(organ_holder, special=TRUE, drop_if_replaced=FALSE) + replacement.Insert(organ_holder, special=TRUE, movement_flags = DELETE_IF_REPLACED) /datum/species/proc/worn_items_fit_body_check(mob/living/carbon/wearer) for(var/obj/item/equipped_item in wearer.get_all_worn_items()) @@ -492,7 +490,7 @@ GLOBAL_LIST_EMPTY(features_by_species) //Load a persons preferences from DNA var/obj/item/organ/external/new_organ = SSwardrobe.provide_type(organ_path) - new_organ.Insert(human, special=TRUE, drop_if_replaced=FALSE) + new_organ.Insert(human, special=TRUE, movement_flags = DELETE_IF_REPLACED) diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index 48980076f4e..00b59ffe25f 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -13,6 +13,7 @@ mob_biotypes = MOB_ORGANIC|MOB_HUMANOID can_be_shoved_into = TRUE initial_language_holder = /datum/language_holder/empty // We get stuff from our species + flags_1 = PREVENT_CONTENTS_EXPLOSION_1 //Hair colour and style var/hair_color = "#000000" diff --git a/code/modules/mob/living/carbon/human/species_types/felinid.dm b/code/modules/mob/living/carbon/human/species_types/felinid.dm index 161b42fff5b..277bc7d72af 100644 --- a/code/modules/mob/living/carbon/human/species_types/felinid.dm +++ b/code/modules/mob/living/carbon/human/species_types/felinid.dm @@ -41,7 +41,7 @@ target_human.dna.features["ears"] = "Cat" if(target_human.dna.features["ears"] == "Cat") var/obj/item/organ/internal/ears/cat/ears = new - ears.Insert(target_human, drop_if_replaced = FALSE) + ears.Insert(target_human, movement_flags = DELETE_IF_REPLACED) else mutantears = /obj/item/organ/internal/ears return ..() @@ -92,8 +92,8 @@ // Humans get converted directly to felinids, and the key is handled in on_species_gain. // Now when we get mob.dna.features[feature_key], it returns None, which is why the tail is invisible. // stored_feature_id is only set once (the first time an organ is inserted), so this should be safe. - kitty_ears.Insert(soon_to_be_felinid, special = TRUE, drop_if_replaced = FALSE) - kitty_tail.Insert(soon_to_be_felinid, special = TRUE, drop_if_replaced = FALSE) + kitty_ears.Insert(soon_to_be_felinid, special = TRUE, movement_flags = DELETE_IF_REPLACED) + kitty_tail.Insert(soon_to_be_felinid, special = TRUE, movement_flags = DELETE_IF_REPLACED) if(!silent) to_chat(soon_to_be_felinid, span_boldnotice("Something is nya~t right.")) playsound(get_turf(soon_to_be_felinid), 'sound/effects/meow1.ogg', 50, TRUE, -1) @@ -116,16 +116,16 @@ for(var/external_organ in target_species.external_organs) if(ispath(external_organ, /obj/item/organ/external/tail)) var/obj/item/organ/external/tail/new_tail = new external_organ() - new_tail.Insert(purrbated_human, special = TRUE, drop_if_replaced = FALSE) + new_tail.Insert(purrbated_human, special = TRUE, movement_flags = DELETE_IF_REPLACED) // Don't forget the spines we removed earlier else if(ispath(external_organ, /obj/item/organ/external/spines)) var/obj/item/organ/external/spines/new_spines = new external_organ() - new_spines.Insert(purrbated_human, special = TRUE, drop_if_replaced = FALSE) + new_spines.Insert(purrbated_human, special = TRUE, movement_flags = DELETE_IF_REPLACED) var/obj/item/organ/internal/ears/old_ears = purrbated_human.get_organ_slot(ORGAN_SLOT_EARS) if(istype(old_ears, /obj/item/organ/internal/ears/cat)) var/obj/item/organ/new_ears = new target_species.mutantears() - new_ears.Insert(purrbated_human, special = TRUE, drop_if_replaced = FALSE) + new_ears.Insert(purrbated_human, special = TRUE, movement_flags = DELETE_IF_REPLACED) if(!silent) to_chat(purrbated_human, span_boldnotice("You are no longer a cat.")) diff --git a/code/modules/mob/living/carbon/human/species_types/monkeys.dm b/code/modules/mob/living/carbon/human/species_types/monkeys.dm index 8fb36e7c4e2..8d0cbac2e7e 100644 --- a/code/modules/mob/living/carbon/human/species_types/monkeys.dm +++ b/code/modules/mob/living/carbon/human/species_types/monkeys.dm @@ -166,11 +166,11 @@ build_all_button_icons() -/obj/item/organ/internal/brain/primate/on_insert(mob/living/carbon/primate) +/obj/item/organ/internal/brain/primate/on_mob_insert(mob/living/carbon/primate) . = ..() RegisterSignal(primate, COMSIG_MOVABLE_CROSS, PROC_REF(on_crossed), TRUE) -/obj/item/organ/internal/brain/primate/on_remove(mob/living/carbon/primate) +/obj/item/organ/internal/brain/primate/on_mob_remove(mob/living/carbon/primate) . = ..() UnregisterSignal(primate, COMSIG_MOVABLE_CROSS) diff --git a/code/modules/mob/living/carbon/human/species_types/vampire.dm b/code/modules/mob/living/carbon/human/species_types/vampire.dm index 6e56b13055b..427f1f5f71b 100644 --- a/code/modules/mob/living/carbon/human/species_types/vampire.dm +++ b/code/modules/mob/living/carbon/human/species_types/vampire.dm @@ -203,11 +203,11 @@ name = "vampire heart" color = "#1C1C1C" -/obj/item/organ/internal/heart/vampire/on_insert(mob/living/carbon/receiver) +/obj/item/organ/internal/heart/vampire/on_mob_insert(mob/living/carbon/receiver) . = ..() RegisterSignal(receiver, COMSIG_MOB_GET_STATUS_TAB_ITEMS, PROC_REF(get_status_tab_item)) -/obj/item/organ/internal/heart/vampire/on_remove(mob/living/carbon/heartless) +/obj/item/organ/internal/heart/vampire/on_mob_remove(mob/living/carbon/heartless) . = ..() UnregisterSignal(heartless, COMSIG_MOB_GET_STATUS_TAB_ITEMS) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index b6ca0349aed..d11e5d5620b 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -1391,7 +1391,7 @@ Robot.notify_ai(AI_NOTIFICATION_NEW_BORG) else for(var/obj/item/item in src) - if(!dropItemToGround(item)) + if(!dropItemToGround(item) && !(item.item_flags & ABSTRACT)) qdel(item) continue item_contents += item diff --git a/code/modules/mob_spawn/corpses/mining_corpses.dm b/code/modules/mob_spawn/corpses/mining_corpses.dm index 8b7ad474b16..972bb5c3fa5 100644 --- a/code/modules/mob_spawn/corpses/mining_corpses.dm +++ b/code/modules/mob_spawn/corpses/mining_corpses.dm @@ -27,7 +27,7 @@ /obj/effect/mob_spawn/corpse/human/legioninfested/special(mob/living/carbon/human/spawned_human) . = ..() var/obj/item/organ/internal/legion_tumour/cancer = new() - cancer.Insert(spawned_human, special = TRUE, drop_if_replaced = FALSE) + cancer.Insert(spawned_human, special = TRUE, movement_flags = DELETE_IF_REPLACED) /// Returns the outfit worn by our corpse /obj/effect/mob_spawn/corpse/human/legioninfested/proc/select_outfit() diff --git a/code/modules/religion/burdened/psyker.dm b/code/modules/religion/burdened/psyker.dm index 2b2df26a446..1fe730c1f5e 100644 --- a/code/modules/religion/burdened/psyker.dm +++ b/code/modules/religion/burdened/psyker.dm @@ -10,12 +10,12 @@ organ_traits = list(TRAIT_ADVANCEDTOOLUSER, TRAIT_LITERATE, TRAIT_CAN_STRIP, TRAIT_ANTIMAGIC_NO_SELFBLOCK) w_class = WEIGHT_CLASS_NORMAL -/obj/item/organ/internal/brain/psyker/on_insert(mob/living/carbon/inserted_into) +/obj/item/organ/internal/brain/psyker/on_mob_insert(mob/living/carbon/inserted_into) . = ..() inserted_into.AddComponent(/datum/component/echolocation, blocking_trait = TRAIT_DUMB, echo_group = "psyker", echo_icon = "psyker", color_path = /datum/client_colour/psyker) inserted_into.AddComponent(/datum/component/anti_magic, antimagic_flags = MAGIC_RESISTANCE_MIND) -/obj/item/organ/internal/brain/psyker/on_remove(mob/living/carbon/removed_from) +/obj/item/organ/internal/brain/psyker/on_mob_remove(mob/living/carbon/removed_from) . = ..() qdel(removed_from.GetComponent(/datum/component/echolocation)) qdel(removed_from.GetComponent(/datum/component/anti_magic)) @@ -82,9 +82,9 @@ qdel(old_head) var/obj/item/organ/internal/brain/psyker/psyker_brain = new() old_brain.before_organ_replacement(psyker_brain) - old_brain.Remove(src, special = TRUE, no_id_transfer = TRUE) + old_brain.Remove(src, special = TRUE, movement_flags = NO_ID_TRANSFER) qdel(old_brain) - psyker_brain.Insert(src, special = TRUE, drop_if_replaced = FALSE) + psyker_brain.Insert(src, special = TRUE, movement_flags = DELETE_IF_REPLACED) if(old_eyes) qdel(old_eyes) return TRUE diff --git a/code/modules/spells/spell_types/self/summonitem.dm b/code/modules/spells/spell_types/self/summonitem.dm index 62d6b078161..ab99f35271d 100644 --- a/code/modules/spells/spell_types/self/summonitem.dm +++ b/code/modules/spells/spell_types/self/summonitem.dm @@ -138,7 +138,6 @@ item_to_retrieve = null break - SEND_SIGNAL(holding_mark, COMSIG_MAGIC_RECALL, caster, item_to_retrieve) holding_mark.dropItemToGround(item_to_retrieve) else if(isobj(item_to_retrieve.loc)) @@ -157,15 +156,6 @@ infinite_recursion += 1 - else - // Organs are usually stored in nullspace - if(isorgan(item_to_retrieve)) - var/obj/item/organ/organ = item_to_retrieve - if(organ.owner) - // If this code ever runs I will be happy - log_combat(caster, organ.owner, "magically removed [organ.name] from", addition = "COMBAT MODE: [uppertext(caster.combat_mode)]") - organ.Remove(organ.owner) - if(!item_to_retrieve) return @@ -176,6 +166,8 @@ else item_to_retrieve.forceMove(caster.drop_location()) item_to_retrieve.loc.visible_message(span_warning("[item_to_retrieve] suddenly appears!")) + + SEND_SIGNAL(item_to_retrieve, COMSIG_MAGIC_RECALL, caster, item_to_retrieve) playsound(get_turf(item_to_retrieve), 'sound/magic/summonitems_generic.ogg', 50, TRUE) /datum/action/cooldown/spell/summonitem/abductor diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm index 1ff1082b4a4..020e0d36c01 100644 --- a/code/modules/surgery/bodyparts/_bodyparts.dm +++ b/code/modules/surgery/bodyparts/_bodyparts.dm @@ -6,6 +6,7 @@ w_class = WEIGHT_CLASS_SMALL icon = 'icons/mob/human/bodyparts.dmi' icon_state = "" //Leave this blank! Bodyparts are built using overlays + flags_1 = PREVENT_CONTENTS_EXPLOSION_1 //actually mindblowing /// The icon for Organic limbs using greyscale VAR_PROTECTED/icon_greyscale = DEFAULT_BODYPART_ICON_ORGANIC ///The icon for non-greyscale limbs @@ -19,7 +20,7 @@ layer = BELOW_MOB_LAYER //so it isn't hidden behind objects when on the floor grind_results = list(/datum/reagent/bone_dust = 10, /datum/reagent/consumable/liquidgibs = 5) // robotic bodyparts and chests/heads cannot be ground /// The mob that "owns" this limb - /// DO NOT MODIFY DIRECTLY. Use set_owner() + /// DO NOT MODIFY DIRECTLY. Use update_owner() var/mob/living/carbon/owner /// If this limb can be scarred. @@ -155,9 +156,6 @@ /// If something is currently grasping this bodypart and trying to staunch bleeding (see [/obj/item/hand_item/self_grasp]) var/obj/item/hand_item/self_grasp/grasped_by - ///A list of all the external organs we've got stored to draw horns, wings and stuff with (special because we are actually in the limbs unlike normal organs :/ ) - ///If someone ever comes around to making all organs exist in the bodyparts, you can just remove this and use a typed loop - var/list/obj/item/organ/external/external_organs = list() ///A list of all bodypart overlays to draw var/list/bodypart_overlays = list() @@ -232,31 +230,40 @@ refresh_bleed_rate() /obj/item/bodypart/Destroy() - if(owner) - owner.remove_bodypart(src) - set_owner(null) + if(owner && !QDELETED(owner)) + forced_removal(special = FALSE, dismembered = TRUE, move_to_floor = FALSE) + update_owner(null) for(var/wound in wounds) qdel(wound) // wounds is a lazylist, and each wound removes itself from it on deletion. if(length(wounds)) stack_trace("[type] qdeleted with [length(wounds)] uncleared wounds") wounds.Cut() - if(length(external_organs)) - for(var/obj/item/organ/external/external_organ as anything in external_organs) - external_organs -= external_organ - qdel(external_organ) // It handles removing its references to this limb on its own. + owner = null + + for(var/atom/movable/movable in contents) + qdel(movable) - external_organs = list() QDEL_LIST_ASSOC_VAL(feature_offsets) return ..() -/obj/item/bodypart/forceMove(atom/destination) //Please. Never forcemove a limb if its's actually in use. This is only for borgs. - SHOULD_CALL_PARENT(TRUE) +/obj/item/bodypart/ex_act(severity, target) + if(owner) //trust me bro you dont want this + return FALSE + return ..() - . = ..() - if(isturf(destination)) - update_icon_dropped() + +/obj/item/bodypart/proc/on_forced_removal(atom/old_loc, dir, forced, list/old_locs) + SIGNAL_HANDLER + + forced_removal(special = FALSE, dismembered = TRUE, move_to_floor = FALSE) + +/// In-case someone, somehow only teleports someones limb +/obj/item/bodypart/proc/forced_removal(special, dismembered, move_to_floor) + drop_limb(special, dismembered, move_to_floor) + + update_icon_dropped() /obj/item/bodypart/examine(mob/user) SHOULD_CALL_PARENT(TRUE) @@ -403,32 +410,25 @@ var/atom/drop_loc = drop_location() if(IS_ORGANIC_LIMB(src)) playsound(drop_loc, 'sound/misc/splort.ogg', 50, TRUE, -1) + QDEL_NULL(current_gauze) - for(var/obj/item/organ/bodypart_organ as anything in get_organs()) - bodypart_organ.transfer_to_limb(src, owner) - for(var/obj/item/organ/external/external as anything in external_organs) - external.remove_from_limb() - external.forceMove(drop_loc) - for(var/obj/item/item_in_bodypart in src) - item_in_bodypart.forceMove(drop_loc) + + for(var/obj/item/organ/bodypart_organ in contents) + if(bodypart_organ.organ_flags & ORGAN_UNREMOVABLE) + continue + if(owner) + bodypart_organ.Remove(bodypart_organ.owner) + else + if(bodypart_organ.bodypart_remove(src)) + if(drop_loc) //can be null if being deleted + bodypart_organ.forceMove(get_turf(drop_loc)) + + if(drop_loc) //can be null during deletion + for(var/atom/movable/movable as anything in src) + movable.forceMove(drop_loc) update_icon_dropped() -///since organs aren't actually stored in the bodypart themselves while attached to a person, we have to query the owner for what we should have -/obj/item/bodypart/proc/get_organs() - SHOULD_CALL_PARENT(TRUE) - RETURN_TYPE(/list) - - if(!owner) - return FALSE - - var/list/bodypart_organs - for(var/obj/item/organ/organ_check as anything in owner.organs) //internal organs inside the dismembered limb are dropped. - if(check_zone(organ_check.zone) == body_zone) - LAZYADD(bodypart_organs, organ_check) // this way if we don't have any, it'll just return null - - return bodypart_organs - //Return TRUE to get whatever mob this is in to update health. /obj/item/bodypart/proc/on_life(seconds_per_tick, times_fired) SHOULD_CALL_PARENT(TRUE) @@ -737,70 +737,91 @@ owner.update_health_hud() //update the healthdoll owner.update_body() -///Proc to change the value of the `owner` variable and react to the event of its change. -/obj/item/bodypart/proc/set_owner(new_owner) - SHOULD_CALL_PARENT(TRUE) +/// Proc to change the value of the `owner` variable and react to the event of its change. +/obj/item/bodypart/proc/update_owner(new_owner) + SHOULD_NOT_OVERRIDE(TRUE) + if(owner == new_owner) return FALSE //`null` is a valid option, so we need to use a num var to make it clear no change was made. - var/mob/living/carbon/old_owner = owner - owner = new_owner - SEND_SIGNAL(src, COMSIG_BODYPART_CHANGED_OWNER, new_owner, old_owner) - var/needs_update_disabled = FALSE //Only really relevant if there's an owner - if(old_owner) - if(held_index) - old_owner.on_lost_hand(src) - if(old_owner.hud_used) - var/atom/movable/screen/inventory/hand/hand = old_owner.hud_used.hand_slots["[held_index]"] - if(hand) - hand.update_appearance() - old_owner.update_worn_gloves() - if(speed_modifier) - old_owner.update_bodypart_speed_modifier() - if(length(bodypart_traits)) - old_owner.remove_traits(bodypart_traits, bodypart_trait_source) - if(initial(can_be_disabled)) - if(HAS_TRAIT(old_owner, TRAIT_NOLIMBDISABLE)) - if(!owner || !HAS_TRAIT(owner, TRAIT_NOLIMBDISABLE)) - set_can_be_disabled(initial(can_be_disabled)) - needs_update_disabled = TRUE - UnregisterSignal(old_owner, list( - SIGNAL_REMOVETRAIT(TRAIT_NOLIMBDISABLE), - SIGNAL_ADDTRAIT(TRAIT_NOLIMBDISABLE), - SIGNAL_REMOVETRAIT(TRAIT_NOBLOOD), - SIGNAL_ADDTRAIT(TRAIT_NOBLOOD), - )) - UnregisterSignal(old_owner, COMSIG_ATOM_RESTYLE) + + SEND_SIGNAL(src, COMSIG_BODYPART_CHANGED_OWNER, new_owner, owner) + if(owner) - if(held_index) - owner.on_added_hand(src, held_index) - if(owner.hud_used) - var/atom/movable/screen/inventory/hand/hand = owner.hud_used.hand_slots["[held_index]"] - if(hand) - hand.update_appearance() - owner.update_worn_gloves() - if(speed_modifier) - owner.update_bodypart_speed_modifier() - if(length(bodypart_traits)) - owner.add_traits(bodypart_traits, bodypart_trait_source) - if(initial(can_be_disabled)) - if(HAS_TRAIT(owner, TRAIT_NOLIMBDISABLE)) - set_can_be_disabled(FALSE) - needs_update_disabled = FALSE - RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_NOLIMBDISABLE), PROC_REF(on_owner_nolimbdisable_trait_loss)) - RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_NOLIMBDISABLE), PROC_REF(on_owner_nolimbdisable_trait_gain)) - // Bleeding stuff - RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_NOBLOOD), PROC_REF(on_owner_nobleed_loss)) - RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_NOBLOOD), PROC_REF(on_owner_nobleed_gain)) - - if(needs_update_disabled) - update_disabled() - - RegisterSignal(owner, COMSIG_ATOM_RESTYLE, PROC_REF(on_attempt_feature_restyle_mob)) + . = owner //return value is old owner + clear_ownership(owner) + if(new_owner) + apply_ownership(new_owner) refresh_bleed_rate() - return old_owner + return . + +/// Run all necessary procs to remove a limbs ownership and remove the appropriate signals and traits +/obj/item/bodypart/proc/clear_ownership(mob/living/carbon/old_owner) + SHOULD_CALL_PARENT(TRUE) + + owner = null + + if(speed_modifier) + old_owner.update_bodypart_speed_modifier() + if(length(bodypart_traits)) + old_owner.remove_traits(bodypart_traits, bodypart_trait_source) + + UnregisterSignal(old_owner, list( + SIGNAL_REMOVETRAIT(TRAIT_NOLIMBDISABLE), + SIGNAL_ADDTRAIT(TRAIT_NOLIMBDISABLE), + SIGNAL_REMOVETRAIT(TRAIT_NOBLOOD), + SIGNAL_ADDTRAIT(TRAIT_NOBLOOD), + )) + + UnregisterSignal(old_owner, COMSIG_ATOM_RESTYLE) + +/// Apply ownership of a limb to someone, giving the appropriate traits, updates and signals +/obj/item/bodypart/proc/apply_ownership(mob/living/carbon/new_owner) + SHOULD_CALL_PARENT(TRUE) + + owner = new_owner + + if(speed_modifier) + owner.update_bodypart_speed_modifier() + if(length(bodypart_traits)) + owner.add_traits(bodypart_traits, bodypart_trait_source) + + if(initial(can_be_disabled)) + if(HAS_TRAIT(owner, TRAIT_NOLIMBDISABLE)) + set_can_be_disabled(FALSE) + + // Listen to disable traits being added + RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_NOLIMBDISABLE), PROC_REF(on_owner_nolimbdisable_trait_loss)) + RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_NOLIMBDISABLE), PROC_REF(on_owner_nolimbdisable_trait_gain)) + + // Listen to no blood traits being added + RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_NOBLOOD), PROC_REF(on_owner_nobleed_loss)) + RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_NOBLOOD), PROC_REF(on_owner_nobleed_gain)) + + if(can_be_disabled) + update_disabled() + + RegisterSignal(owner, COMSIG_ATOM_RESTYLE, PROC_REF(on_attempt_feature_restyle_mob)) + + forceMove(owner) + RegisterSignal(src, COMSIG_MOVABLE_MOVED, PROC_REF(on_forced_removal)) //this must be set after we moved, or we insta gib + +/// Called on addition of a bodypart +/obj/item/bodypart/proc/on_adding(mob/living/carbon/new_owner) + SHOULD_CALL_PARENT(TRUE) + + item_flags |= ABSTRACT + ADD_TRAIT(src, TRAIT_NODROP, ORGAN_INSIDE_BODY_TRAIT) + +/// Called on removal of a bodypart. +/obj/item/bodypart/proc/on_removal(mob/living/carbon/old_owner) + SHOULD_CALL_PARENT(TRUE) + + UnregisterSignal(src, COMSIG_MOVABLE_MOVED) + + item_flags &= ~ABSTRACT + REMOVE_TRAIT(src, TRAIT_NODROP, ORGAN_INSIDE_BODY_TRAIT) -/obj/item/bodypart/proc/on_removal() if(!length(bodypart_traits)) return diff --git a/code/modules/surgery/bodyparts/dismemberment.dm b/code/modules/surgery/bodyparts/dismemberment.dm index db92a901916..2856b9c23cc 100644 --- a/code/modules/surgery/bodyparts/dismemberment.dm +++ b/code/modules/surgery/bodyparts/dismemberment.dm @@ -67,7 +67,7 @@ if(wounding_type != WOUND_BURN && isturf(chest_owner.loc) && can_bleed()) chest_owner.add_splatter_floor(chest_owner.loc) playsound(get_turf(chest_owner), 'sound/misc/splort.ogg', 80, TRUE) - for(var/obj/item/organ/organ as anything in chest_owner.organs) + for(var/obj/item/organ/organ in contents) var/org_zone = check_zone(organ.zone) if(org_zone != BODY_ZONE_CHEST) continue @@ -75,21 +75,13 @@ organ.forceMove(chest_owner.loc) . += organ - for(var/obj/item/organ/external/ext_organ as anything in src.external_organs) - if(!(ext_organ.organ_flags & ORGAN_UNREMOVABLE)) - ext_organ.Remove(chest_owner) - ext_organ.forceMove(chest_owner.loc) - . += ext_organ - if(cavity_item) cavity_item.forceMove(chest_owner.loc) . += cavity_item cavity_item = null - return . - ///limb removal. The "special" argument is used for swapping a limb with a new one without the effects of losing a limb kicking in. -/obj/item/bodypart/proc/drop_limb(special, dismembered) +/obj/item/bodypart/proc/drop_limb(special, dismembered, move_to_floor = TRUE) if(!owner) return var/atom/drop_loc = owner.drop_location() @@ -98,16 +90,13 @@ SEND_SIGNAL(src, COMSIG_BODYPART_REMOVED, owner, special, dismembered) update_limb(dropping_limb = TRUE) bodypart_flags &= ~BODYPART_IMPLANTED //limb is out and about, it can't really be considered an implant - owner.remove_bodypart(src) + owner.remove_bodypart(src, special) for(var/datum/scar/scar as anything in scars) scar.victim = null LAZYREMOVE(owner.all_scars, scar) - for(var/obj/item/organ/external/ext_organ as anything in external_organs) - ext_organ.transfer_to_limb(src, null) //Null is the second arg because the bodypart is being removed from it's owner. - - var/mob/living/carbon/phantom_owner = set_owner(null) // so we can still refer to the guy who lost their limb after said limb forgets 'em + var/mob/living/carbon/phantom_owner = update_owner(null) // so we can still refer to the guy who lost their limb after said limb forgets 'em for(var/datum/wound/wound as anything in wounds) wound.remove_wound(TRUE) @@ -131,27 +120,22 @@ to_chat(phantom_owner, span_warning("You feel your [mutation] deactivating from the loss of your [body_zone]!")) phantom_owner.dna.force_lose(mutation) - for(var/obj/item/organ/organ as anything in phantom_owner.organs) //internal organs inside the dismembered limb are dropped. - var/org_zone = check_zone(organ.zone) - if(org_zone != body_zone) - continue - organ.transfer_to_limb(src, phantom_owner) - update_icon_dropped() phantom_owner.update_health_hud() //update the healthdoll phantom_owner.update_body() phantom_owner.update_body_parts() - if(!drop_loc) // drop_loc = null happens when a "dummy human" used for rendering icons on prefs screen gets its limbs replaced. - qdel(src) - return - if(bodypart_flags & BODYPART_PSEUDOPART) drop_organs(phantom_owner) //Psuedoparts shouldn't have organs, but just in case qdel(src) return - forceMove(drop_loc) + if(move_to_floor) + if(!drop_loc) // drop_loc = null happens when a "dummy human" used for rendering icons on prefs screen gets its limbs replaced. + qdel(src) + return + forceMove(drop_loc) + SEND_SIGNAL(phantom_owner, COMSIG_CARBON_POST_REMOVE_LIMB, src, special, dismembered) /** @@ -201,48 +185,45 @@ var/datum/wound/loss/dismembering = new return dismembering.apply_dismember(src, wounding_type) -///Transfers the organ to the limb, and to the limb's owner, if it has one. This is done on drop_limb(). -/obj/item/organ/proc/transfer_to_limb(obj/item/bodypart/bodypart, mob/living/carbon/bodypart_owner) - Remove(bodypart_owner) - add_to_limb(bodypart) - -///Adds the organ to a bodypart, used in transfer_to_limb() -/obj/item/organ/proc/add_to_limb(obj/item/bodypart/bodypart) - forceMove(bodypart) - -///Removes the organ from the limb, placing it into nullspace. -/obj/item/organ/proc/remove_from_limb() - moveToNullspace() - -/obj/item/organ/internal/brain/transfer_to_limb(obj/item/bodypart/head/head, mob/living/carbon/human/head_owner) - Remove(head_owner) //Changeling brain concerns are now handled in Remove - forceMove(head) - head.brain = src - if(brainmob) - head.brainmob = brainmob - brainmob = null - head.brainmob.forceMove(head) - head.brainmob.set_stat(DEAD) - -/obj/item/organ/internal/eyes/transfer_to_limb(obj/item/bodypart/head/head, mob/living/carbon/human/head_owner) +/obj/item/organ/internal/eyes/on_bodypart_insert(obj/item/bodypart/head/head) head.eyes = src ..() -/obj/item/organ/internal/ears/transfer_to_limb(obj/item/bodypart/head/head, mob/living/carbon/human/head_owner) +/obj/item/organ/internal/ears/on_bodypart_insert(obj/item/bodypart/head/head) head.ears = src ..() -/obj/item/organ/internal/tongue/transfer_to_limb(obj/item/bodypart/head/head, mob/living/carbon/human/head_owner) +/obj/item/organ/internal/tongue/on_bodypart_insert(obj/item/bodypart/head/head) head.tongue = src ..() -/obj/item/bodypart/chest/drop_limb(special) +/obj/item/organ/internal/brain/on_bodypart_insert(obj/item/bodypart/head/head) + head.brain = src + ..() + +/obj/item/organ/internal/eyes/on_bodypart_remove(obj/item/bodypart/head/head) + head.eyes = null + ..() + +/obj/item/organ/internal/ears/on_bodypart_remove(obj/item/bodypart/head/head) + head.ears = null + ..() + +/obj/item/organ/internal/tongue/on_bodypart_remove(obj/item/bodypart/head/head) + head.tongue = null + ..() + +/obj/item/organ/internal/brain/on_bodypart_remove(obj/item/bodypart/head/head) + head.brain = null + ..() + +/obj/item/bodypart/chest/drop_limb(special, dismembered, move_to_floor = TRUE) if(special) return ..() //if this is not a special drop, this is a mistake return FALSE -/obj/item/bodypart/arm/drop_limb(special) +/obj/item/bodypart/arm/drop_limb(special, dismembered, move_to_floor = TRUE) var/mob/living/carbon/arm_owner = owner if(special || !arm_owner) @@ -265,7 +246,7 @@ arm_owner.update_worn_gloves() //to remove the bloody hands overlay return ..() -/obj/item/bodypart/leg/drop_limb(special) +/obj/item/bodypart/leg/drop_limb(special, dismembered, move_to_floor = TRUE) if(owner && !special) if(owner.legcuffed) owner.legcuffed.forceMove(owner.drop_location()) //At this point bodypart is still in nullspace @@ -276,7 +257,7 @@ owner.dropItemToGround(owner.shoes, TRUE) return ..() -/obj/item/bodypart/head/drop_limb(special) +/obj/item/bodypart/head/drop_limb(special, dismembered, move_to_floor = TRUE) if(!special) //Drop all worn head items for(var/obj/item/head_item as anything in list(owner.glasses, owner.ears, owner.wear_mask, owner.head)) @@ -332,8 +313,6 @@ SEND_SIGNAL(new_limb_owner, COMSIG_CARBON_ATTACH_LIMB, src, special) SEND_SIGNAL(src, COMSIG_BODYPART_ATTACHED, new_limb_owner, special) - moveToNullspace() - set_owner(new_limb_owner) new_limb_owner.add_bodypart(src) LAZYREMOVE(new_limb_owner.body_zone_dismembered_by, body_zone) @@ -346,8 +325,10 @@ qdel(attach_surgery) break - for(var/obj/item/organ/limb_organ in contents) - limb_organ.Insert(new_limb_owner, TRUE) + for(var/obj/item/organ/organ as anything in new_limb_owner.organs) + if(deprecise_zone(organ.zone) != body_zone) + continue + organ.bodypart_insert(src) for(var/datum/wound/wound as anything in wounds) // we have to remove the wound from the limb wound list first, so that we can reapply it fresh with the new person @@ -387,15 +368,6 @@ if(!.) return - if(brain) - brain = null - if(tongue) - tongue = null - if(ears) - ears = null - if(eyes) - eyes = null - if(old_real_name) new_head_owner.real_name = old_real_name real_name = new_head_owner.real_name diff --git a/code/modules/surgery/bodyparts/head.dm b/code/modules/surgery/bodyparts/head.dm index 04c74b91473..e43d6ca05c0 100644 --- a/code/modules/surgery/bodyparts/head.dm +++ b/code/modules/surgery/bodyparts/head.dm @@ -26,7 +26,6 @@ unarmed_effectiveness = 0 bodypart_trait_source = HEAD_TRAIT - var/mob/living/brain/brainmob //The current occupant. var/obj/item/organ/internal/brain/brain //The brain organ var/obj/item/organ/internal/eyes/eyes var/obj/item/organ/internal/ears/ears @@ -93,12 +92,6 @@ var/datum/worn_feature_offset/worn_face_offset /obj/item/bodypart/head/Destroy() - QDEL_NULL(brainmob) //order is sensitive, see warning in Exited() below - QDEL_NULL(brain) - QDEL_NULL(eyes) - QDEL_NULL(ears) - QDEL_NULL(tongue) - QDEL_NULL(worn_ears_offset) QDEL_NULL(worn_glasses_offset) QDEL_NULL(worn_mask_offset) @@ -110,11 +103,6 @@ if(gone == brain) brain = null update_icon_dropped() - if(!QDELETED(brainmob)) //this shouldn't happen without badminnery. - message_admins("Brainmob: ([ADMIN_LOOKUPFLW(brainmob)]) was left stranded in [src] at [ADMIN_VERBOSEJMP(src)] without a brain!") - brainmob.log_message(", brainmob, was left stranded in [src] without a brain", LOG_GAME) - if(gone == brainmob) - brainmob = null if(gone == eyes) eyes = null update_icon_dropped() @@ -129,12 +117,12 @@ if(show_organs_on_examine && IS_ORGANIC_LIMB(src)) if(!brain) . += span_info("The brain has been removed from [src].") - else if(brain.suicided || (brainmob && HAS_TRAIT(brainmob, TRAIT_SUICIDED))) + else if(brain.suicided || (brain.brainmob && HAS_TRAIT(brain.brainmob, TRAIT_SUICIDED))) . += span_info("There's a miserable expression on [real_name]'s face; they must have really hated life. There's no hope of recovery.") - else if(brainmob?.health <= HEALTH_THRESHOLD_DEAD) - . += span_info("It's leaking some kind of... clear fluid? The brain inside must be in pretty bad shape.") - else if(brainmob) - if(brainmob.key || brainmob.get_ghost(FALSE, TRUE)) + else if(brain.brainmob) + if(brain.brainmob?.health <= HEALTH_THRESHOLD_DEAD) + . += span_info("It's leaking some kind of... clear fluid? The brain inside must be in pretty bad shape.") + if(brain.brainmob.key || brain.brainmob.get_ghost(FALSE, TRUE)) . += span_info("Its muscles are twitching slightly... It seems to have some life still in it.") else . += span_info("It's completely lifeless. Perhaps there'll be a chance for them later.") @@ -158,33 +146,12 @@ return ..() /obj/item/bodypart/head/drop_organs(mob/user, violent_removal) - var/atom/drop_loc = drop_location() - for(var/obj/item/head_item in src) - if(head_item == brain) - if(user) - user.visible_message(span_warning("[user] saws [src] open and pulls out a brain!"), span_notice("You saw [src] open and pull out a brain.")) - if(brainmob) - brainmob.container = null - brain.brainmob = brainmob - brainmob = null - if(violent_removal && prob(rand(80, 100))) //ghetto surgery can damage the brain. - to_chat(user, span_warning("[brain] was damaged in the process!")) - brain.set_organ_damage(brain.maxHealth) - brain.forceMove(drop_loc) - brain = null - update_icon_dropped() - else - if(istype(head_item, /obj/item/reagent_containers/pill)) - for(var/datum/action/item_action/hands_free/activate_pill/pill_action in head_item.actions) - qdel(pill_action) - else if(isorgan(head_item)) - var/obj/item/organ/organ = head_item - if(organ.organ_flags & ORGAN_UNREMOVABLE) - continue - head_item.forceMove(drop_loc) - eyes = null - ears = null - tongue = null + if(user) + user.visible_message(span_warning("[user] saws [src] open and pulls out a brain!"), span_notice("You saw [src] open and pull out a brain.")) + if(brain && violent_removal && prob(90)) //ghetto surgery can damage the brain. + to_chat(user, span_warning("[brain] was damaged in the process!")) + brain.set_organ_damage(brain.maxHealth) + update_limb() return ..() diff --git a/code/modules/surgery/bodyparts/helpers.dm b/code/modules/surgery/bodyparts/helpers.dm index c93fdf10b47..52671b5fbc1 100644 --- a/code/modules/surgery/bodyparts/helpers.dm +++ b/code/modules/surgery/bodyparts/helpers.dm @@ -15,6 +15,7 @@ /mob/living/carbon/proc/del_and_replace_bodypart(obj/item/bodypart/new_limb, special) var/obj/item/bodypart/old_limb = get_bodypart(new_limb.body_zone) if(old_limb) + old_limb.drop_limb(special = TRUE) qdel(old_limb) new_limb.try_attach_limb(src, special = special) @@ -172,7 +173,7 @@ /mob/living/carbon/proc/synchronize_bodytypes() var/all_limb_flags = NONE for(var/obj/item/bodypart/limb as anything in bodyparts) - for(var/obj/item/organ/external/ext_organ as anything in limb.external_organs) + for(var/obj/item/organ/external/ext_organ in limb) all_limb_flags |= ext_organ.external_bodytypes all_limb_flags |= limb.bodytype diff --git a/code/modules/surgery/bodyparts/parts.dm b/code/modules/surgery/bodyparts/parts.dm index 25f1ab985b6..5f40b14c02d 100644 --- a/code/modules/surgery/bodyparts/parts.dm +++ b/code/modules/surgery/bodyparts/parts.dm @@ -35,8 +35,18 @@ /// Which functional (i.e. flightpotion) wing types (if any) does this bodypart support? If count is >1 a radial menu is used to choose between all icons in list var/list/wing_types = list(/obj/item/organ/external/wings/functional/angel) +/obj/item/bodypart/chest/forced_removal(dismembered, special, move_to_floor) + var/mob/living/carbon/old_owner = owner + ..(special = TRUE) //special because we're self destructing + + //If someones chest is teleported away, they die pretty hard + if(!old_owner) + return + message_admins("[ADMIN_LOOKUPFLW(old_owner)] was gibbed after their chest teleport to [ADMIN_VERBOSEJMP(loc)].") + old_owner.gib(DROP_ALL_REMAINS) + /obj/item/bodypart/chest/can_dismember(obj/item/item) - if(owner.stat < HARD_CRIT || !get_organs()) + if(owner.stat < HARD_CRIT || !contents.len) return FALSE return ..() @@ -127,6 +137,40 @@ QDEL_NULL(held_hand_offset) return ..() +/// We need to clear out hand hud items and appearance, so do that here +/obj/item/bodypart/arm/clear_ownership(mob/living/carbon/old_owner) + ..() + + old_owner.update_worn_gloves() + + if(!held_index) + return + + old_owner.on_lost_hand(src) + + if(!old_owner.hud_used) + return + + var/atom/movable/screen/inventory/hand/hand = old_owner.hud_used.hand_slots["[held_index]"] + hand?.update_appearance() + +/// We need to add hand hud items and appearance, so do that here +/obj/item/bodypart/arm/apply_ownership(mob/living/carbon/new_owner) + ..() + + new_owner.update_worn_gloves() + + if(!held_index) + return + + new_owner.on_added_hand(src, held_index) + + if(!new_owner.hud_used) + return + + var/atom/movable/screen/inventory/hand/hand = new_owner.hud_used.hand_slots["[held_index]"] + hand.update_appearance() + /obj/item/bodypart/arm/left name = "left arm" desc = "Did you know that the word 'sinister' stems originally from the \ @@ -143,27 +187,22 @@ px_y = 0 bodypart_trait_source = LEFT_ARM_TRAIT +/obj/item/bodypart/arm/left/apply_ownership(mob/living/carbon/new_owner) + if(HAS_TRAIT(new_owner, TRAIT_PARALYSIS_L_ARM)) + ADD_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_ARM) + RegisterSignal(new_owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_L_ARM), PROC_REF(on_owner_paralysis_loss)) + else + REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_ARM) + RegisterSignal(new_owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_L_ARM), PROC_REF(on_owner_paralysis_gain)) + ..() -/obj/item/bodypart/arm/left/set_owner(new_owner) - . = ..() - if(. == FALSE) - return - if(owner) - if(HAS_TRAIT(owner, TRAIT_PARALYSIS_L_ARM)) - ADD_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_ARM) - RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_L_ARM), PROC_REF(on_owner_paralysis_loss)) - else - REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_ARM) - RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_L_ARM), PROC_REF(on_owner_paralysis_gain)) - if(.) - var/mob/living/carbon/old_owner = . - if(HAS_TRAIT(old_owner, TRAIT_PARALYSIS_L_ARM)) - UnregisterSignal(old_owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_L_ARM)) - if(!owner || !HAS_TRAIT(owner, TRAIT_PARALYSIS_L_ARM)) - REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_ARM) - else - UnregisterSignal(old_owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_L_ARM)) - +/obj/item/bodypart/arm/left/clear_ownership(mob/living/carbon/old_owner) + if(HAS_TRAIT(old_owner, TRAIT_PARALYSIS_L_ARM)) + UnregisterSignal(old_owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_L_ARM)) + REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_ARM) + else + UnregisterSignal(old_owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_L_ARM)) + ..() ///Proc to react to the owner gaining the TRAIT_PARALYSIS_L_ARM trait. /obj/item/bodypart/arm/left/proc/on_owner_paralysis_gain(mob/living/carbon/source) @@ -172,7 +211,6 @@ UnregisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_L_ARM)) RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_L_ARM), PROC_REF(on_owner_paralysis_loss)) - ///Proc to react to the owner losing the TRAIT_PARALYSIS_L_ARM trait. /obj/item/bodypart/arm/left/proc/on_owner_paralysis_loss(mob/living/carbon/source) SIGNAL_HANDLER @@ -180,7 +218,6 @@ UnregisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_L_ARM)) RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_L_ARM), PROC_REF(on_owner_paralysis_gain)) - /obj/item/bodypart/arm/left/set_disabled(new_disabled) . = ..() if(isnull(.) || !owner) @@ -200,7 +237,6 @@ var/atom/movable/screen/inventory/hand/hand_screen_object = owner.hud_used.hand_slots["[held_index]"] hand_screen_object?.update_appearance() - /obj/item/bodypart/arm/left/monkey icon = 'icons/mob/human/species/monkey/bodyparts.dmi' icon_static = 'icons/mob/human/species/monkey/bodyparts.dmi' @@ -233,7 +269,6 @@ should_draw_greyscale = FALSE appendage_noun = "scythe-like hand" - /obj/item/bodypart/arm/right name = "right arm" desc = "Over 87% of humans are right handed. That figure is much lower \ @@ -249,26 +284,22 @@ px_y = 0 bodypart_trait_source = RIGHT_ARM_TRAIT -/obj/item/bodypart/arm/right/set_owner(new_owner) - . = ..() - if(. == FALSE) - return - if(owner) - if(HAS_TRAIT(owner, TRAIT_PARALYSIS_R_ARM)) - ADD_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_ARM) - RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_R_ARM), PROC_REF(on_owner_paralysis_loss)) - else - REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_ARM) - RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_R_ARM), PROC_REF(on_owner_paralysis_gain)) - if(.) - var/mob/living/carbon/old_owner = . - if(HAS_TRAIT(old_owner, TRAIT_PARALYSIS_R_ARM)) - UnregisterSignal(old_owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_R_ARM)) - if(!owner || !HAS_TRAIT(owner, TRAIT_PARALYSIS_R_ARM)) - REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_ARM) - else - UnregisterSignal(old_owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_R_ARM)) +/obj/item/bodypart/arm/right/apply_ownership(mob/living/carbon/new_owner) + if(HAS_TRAIT(new_owner, TRAIT_PARALYSIS_R_ARM)) + ADD_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_ARM) + RegisterSignal(new_owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_R_ARM), PROC_REF(on_owner_paralysis_loss)) + else + REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_ARM) + RegisterSignal(new_owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_R_ARM), PROC_REF(on_owner_paralysis_gain)) + ..() +/obj/item/bodypart/arm/right/clear_ownership(mob/living/carbon/old_owner) + if(HAS_TRAIT(old_owner, TRAIT_PARALYSIS_R_ARM)) + UnregisterSignal(old_owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_R_ARM)) + REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_ARM) + else + UnregisterSignal(old_owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_R_ARM)) + ..() ///Proc to react to the owner gaining the TRAIT_PARALYSIS_R_ARM trait. /obj/item/bodypart/arm/right/proc/on_owner_paralysis_gain(mob/living/carbon/source) @@ -277,7 +308,6 @@ UnregisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_R_ARM)) RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_R_ARM), PROC_REF(on_owner_paralysis_loss)) - ///Proc to react to the owner losing the TRAIT_PARALYSIS_R_ARM trait. /obj/item/bodypart/arm/right/proc/on_owner_paralysis_loss(mob/living/carbon/source) SIGNAL_HANDLER @@ -285,7 +315,6 @@ UnregisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_R_ARM)) RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_R_ARM), PROC_REF(on_owner_paralysis_gain)) - /obj/item/bodypart/arm/right/set_disabled(new_disabled) . = ..() if(isnull(.) || !owner) @@ -305,7 +334,6 @@ var/atom/movable/screen/inventory/hand/hand_screen_object = owner.hud_used.hand_slots["[held_index]"] hand_screen_object?.update_appearance() - /obj/item/bodypart/arm/right/monkey icon = 'icons/mob/human/species/monkey/bodyparts.dmi' icon_static = 'icons/mob/human/species/monkey/bodyparts.dmi' @@ -375,35 +403,30 @@ can_be_disabled = TRUE bodypart_trait_source = LEFT_LEG_TRAIT -/obj/item/bodypart/leg/left/set_owner(new_owner) - . = ..() - if(. == FALSE) - return - if(owner) - if(HAS_TRAIT(owner, TRAIT_PARALYSIS_L_LEG)) - ADD_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_LEG) - RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_L_LEG), PROC_REF(on_owner_paralysis_loss)) - else - REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_LEG) - RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_L_LEG), PROC_REF(on_owner_paralysis_gain)) - if(.) - var/mob/living/carbon/old_owner = . - if(HAS_TRAIT(old_owner, TRAIT_PARALYSIS_L_LEG)) - UnregisterSignal(old_owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_L_LEG)) - if(!owner || !HAS_TRAIT(owner, TRAIT_PARALYSIS_L_LEG)) - REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_LEG) - else - UnregisterSignal(old_owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_L_LEG)) +/obj/item/bodypart/leg/left/apply_ownership(mob/living/carbon/new_owner) + if(HAS_TRAIT(new_owner, TRAIT_PARALYSIS_L_LEG)) + ADD_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_LEG) + RegisterSignal(new_owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_L_LEG), PROC_REF(on_owner_paralysis_loss)) + else + REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_LEG) + RegisterSignal(new_owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_L_LEG), PROC_REF(on_owner_paralysis_gain)) + ..() +/obj/item/bodypart/leg/left/clear_ownership(mob/living/carbon/old_owner) + if(HAS_TRAIT(old_owner, TRAIT_PARALYSIS_L_LEG)) + UnregisterSignal(old_owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_L_LEG)) + REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_LEG) + else + UnregisterSignal(old_owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_L_LEG)) + ..() -///Proc to react to the owner gaining the TRAIT_PARALYSIS_L_LEG trait. +///Proc to react to the owner gaining the TRAIT_PARALYSIS_L_ARM trait. /obj/item/bodypart/leg/left/proc/on_owner_paralysis_gain(mob/living/carbon/source) SIGNAL_HANDLER ADD_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_LEG) UnregisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_L_LEG)) RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_L_LEG), PROC_REF(on_owner_paralysis_loss)) - ///Proc to react to the owner losing the TRAIT_PARALYSIS_L_LEG trait. /obj/item/bodypart/leg/left/proc/on_owner_paralysis_loss(mob/living/carbon/source) SIGNAL_HANDLER @@ -411,7 +434,6 @@ UnregisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_L_LEG)) RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_L_LEG), PROC_REF(on_owner_paralysis_gain)) - /obj/item/bodypart/leg/left/set_disabled(new_disabled) . = ..() if(isnull(.) || !owner) @@ -469,26 +491,22 @@ px_y = 12 bodypart_trait_source = RIGHT_LEG_TRAIT -/obj/item/bodypart/leg/right/set_owner(new_owner) - . = ..() - if(. == FALSE) - return - if(owner) - if(HAS_TRAIT(owner, TRAIT_PARALYSIS_R_LEG)) - ADD_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_LEG) - RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_R_LEG), PROC_REF(on_owner_paralysis_loss)) - else - REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_LEG) - RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_R_LEG), PROC_REF(on_owner_paralysis_gain)) - if(.) - var/mob/living/carbon/old_owner = . - if(HAS_TRAIT(old_owner, TRAIT_PARALYSIS_R_LEG)) - UnregisterSignal(old_owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_R_LEG)) - if(!owner || !HAS_TRAIT(owner, TRAIT_PARALYSIS_R_LEG)) - REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_LEG) - else - UnregisterSignal(old_owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_R_LEG)) +/obj/item/bodypart/leg/right/apply_ownership(mob/living/carbon/new_owner) + if(HAS_TRAIT(new_owner, TRAIT_PARALYSIS_R_LEG)) + ADD_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_LEG) + RegisterSignal(new_owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_R_LEG), PROC_REF(on_owner_paralysis_loss)) + else + REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_LEG) + RegisterSignal(new_owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_R_LEG), PROC_REF(on_owner_paralysis_gain)) + ..() +/obj/item/bodypart/leg/right/clear_ownership(mob/living/carbon/old_owner) + if(HAS_TRAIT(old_owner, TRAIT_PARALYSIS_R_LEG)) + UnregisterSignal(old_owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_R_LEG)) + REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_LEG) + else + UnregisterSignal(old_owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_R_LEG)) + ..() ///Proc to react to the owner gaining the TRAIT_PARALYSIS_R_LEG trait. /obj/item/bodypart/leg/right/proc/on_owner_paralysis_gain(mob/living/carbon/source) @@ -497,7 +515,6 @@ UnregisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_R_LEG)) RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_R_LEG), PROC_REF(on_owner_paralysis_loss)) - ///Proc to react to the owner losing the TRAIT_PARALYSIS_R_LEG trait. /obj/item/bodypart/leg/right/proc/on_owner_paralysis_loss(mob/living/carbon/source) SIGNAL_HANDLER diff --git a/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm b/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm index 7cf82552d8f..81a7636c100 100644 --- a/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm +++ b/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm @@ -518,17 +518,16 @@ ) return ..() -/obj/item/bodypart/arm/left/golem/set_owner(new_owner) +/obj/item/bodypart/arm/left/golem/clear_ownership(mob/living/carbon/old_owner) . = ..() - if (. == FALSE) - return - if (owner) - owner.AddComponentFrom(REF(src), /datum/component/shovel_hands) - if (isnull(.)) - return - var/mob/living/carbon/old_owner = . + old_owner.RemoveComponentSource(REF(src), /datum/component/shovel_hands) +/obj/item/bodypart/arm/left/golem/apply_ownership(mob/living/carbon/new_owner) + . = ..() + + new_owner.AddComponentFrom(REF(src), /datum/component/shovel_hands) + /obj/item/bodypart/arm/right/golem icon = 'icons/mob/human/species/golems.dmi' icon_static = 'icons/mob/human/species/golems.dmi' @@ -552,17 +551,16 @@ ) return ..() -/obj/item/bodypart/arm/right/golem/set_owner(new_owner) +/obj/item/bodypart/arm/right/golem/clear_ownership(mob/living/carbon/old_owner) . = ..() - if (. == FALSE) - return - if (owner) - owner.AddComponentFrom(REF(src), /datum/component/shovel_hands) - if (isnull(.)) - return - var/mob/living/carbon/old_owner = . + old_owner.RemoveComponentSource(REF(src), /datum/component/shovel_hands) +/obj/item/bodypart/arm/right/golem/apply_ownership(mob/living/carbon/new_owner) + . = ..() + + new_owner.AddComponentFrom(REF(src), /datum/component/shovel_hands) + /obj/item/bodypart/leg/left/golem icon = 'icons/mob/human/species/golems.dmi' icon_static = 'icons/mob/human/species/golems.dmi' diff --git a/code/modules/surgery/organs/_organ.dm b/code/modules/surgery/organs/_organ.dm index a3feba76fec..d7f08a7be35 100644 --- a/code/modules/surgery/organs/_organ.dm +++ b/code/modules/surgery/organs/_organ.dm @@ -6,6 +6,8 @@ throwforce = 0 /// The mob that owns this organ. var/mob/living/carbon/owner = null + /// Reference to the limb we're inside of + var/obj/item/bodypart/bodypart_owner /// The cached info about the blood this organ belongs to var/list/blood_dna_info = list("Synthetic DNA" = "O+") // not every organ spawns inside a person /// The body zone this organ is supposed to inhabit. @@ -77,134 +79,16 @@ INITIALIZE_IMMEDIATE(/obj/item/organ) volume = reagent_vol,\ after_eat = CALLBACK(src, PROC_REF(OnEatFrom))) - if(!IS_ROBOTIC_ORGAN(src)) - add_blood_DNA(blood_dna_info) - -/* - * Insert the organ into the select mob. - * - * receiver - the mob who will get our organ - * special - "quick swapping" an organ out - when TRUE, the mob will be unaffected by not having that organ for the moment - * drop_if_replaced - if there's an organ in the slot already, whether we drop it afterwards - */ -/obj/item/organ/proc/Insert(mob/living/carbon/receiver, special = FALSE, drop_if_replaced = TRUE) - SHOULD_CALL_PARENT(TRUE) - - if(!iscarbon(receiver) || owner == receiver) - return FALSE - - var/obj/item/organ/replaced = receiver.get_organ_slot(slot) - if(replaced) - replaced.Remove(receiver, special = TRUE) - if(drop_if_replaced) - replaced.forceMove(get_turf(receiver)) - else - qdel(replaced) - - receiver.organs |= src - receiver.organs_slot[slot] = src - owner = receiver - - if(!IS_ROBOTIC_ORGAN(src) && (organ_flags & ORGAN_VIRGIN)) - blood_dna_info = receiver.get_blood_dna_list() - // need to remove the synethic blood DNA that is initialized - // wash also adds the blood dna again - wash(CLEAN_TYPE_BLOOD) - organ_flags &= ~ORGAN_VIRGIN - - - // Apply unique side-effects. Return value does not matter. - on_insert(receiver, special) - - return TRUE - -/// Called after the organ is inserted into a mob. -/// Adds Traits, Actions, and Status Effects on the mob in which the organ is impanted. -/// Override this proc to create unique side-effects for inserting your organ. Must be called by overrides. -/obj/item/organ/proc/on_insert(mob/living/carbon/organ_owner, special) - SHOULD_CALL_PARENT(TRUE) - - moveToNullspace() - - for(var/trait in organ_traits) - ADD_TRAIT(organ_owner, trait, REF(src)) - - for(var/datum/action/action as anything in actions) - action.Grant(organ_owner) - - for(var/datum/status_effect/effect as anything in organ_effects) - organ_owner.apply_status_effect(effect, type) - - RegisterSignal(owner, COMSIG_ATOM_EXAMINE, PROC_REF(on_owner_examine)) - SEND_SIGNAL(src, COMSIG_ORGAN_IMPLANTED, organ_owner) - SEND_SIGNAL(organ_owner, COMSIG_CARBON_GAIN_ORGAN, src, special) - -/* - * Remove the organ from the select mob. - * - * * organ_owner - the mob who owns our organ, that we're removing the organ from. - * * special - "quick swapping" an organ out - when TRUE, the mob will be unaffected by not having that organ for the moment - */ -/obj/item/organ/proc/Remove(mob/living/carbon/organ_owner, special = FALSE) - SHOULD_CALL_PARENT(TRUE) - - organ_owner.organs -= src - if(organ_owner.organs_slot[slot] == src) - organ_owner.organs_slot.Remove(slot) - - owner = null - - // Apply or reset unique side-effects. Return value does not matter. - on_remove(organ_owner, special) - - return TRUE - -/// Called after the organ is removed from a mob. -/// Removes Traits, Actions, and Status Effects on the mob in which the organ was impanted. -/// Override this proc to create unique side-effects for removing your organ. Must be called by overrides. -/obj/item/organ/proc/on_remove(mob/living/carbon/organ_owner, special) - SHOULD_CALL_PARENT(TRUE) - - if(!iscarbon(organ_owner)) - stack_trace("Organ removal should not be happening on non carbon mobs: [organ_owner]") - - for(var/trait in organ_traits) - REMOVE_TRAIT(organ_owner, trait, REF(src)) - - for(var/datum/action/action as anything in actions) - action.Remove(organ_owner) - - for(var/datum/status_effect/effect as anything in organ_effects) - organ_owner.remove_status_effect(effect, type) - - UnregisterSignal(organ_owner, COMSIG_ATOM_EXAMINE) - SEND_SIGNAL(src, COMSIG_ORGAN_REMOVED, organ_owner) - SEND_SIGNAL(organ_owner, COMSIG_CARBON_LOSE_ORGAN, src, special) - - // We don't need to readd things to the organ if it's getting deleted - if(QDELING(src)) - return - - if(!IS_ROBOTIC_ORGAN(src) && !(item_flags & NO_BLOOD_ON_ITEM)) - AddElement(/datum/element/decal/blood) - - var/list/diseases = organ_owner.get_static_viruses() - if(!LAZYLEN(diseases)) - return - - var/list/datum/disease/diseases_to_add = list() - for(var/datum/disease/disease as anything in diseases) - // robotic organs are immune to disease unless 'inorganic biology' symptom is present - if(IS_ROBOTIC_ORGAN(src) && !(disease.infectable_biotypes & MOB_ROBOTIC)) - continue - - // admin or special viruses that should not be reproduced - if(disease.spread_flags & (DISEASE_SPREAD_SPECIAL | DISEASE_SPREAD_NON_CONTAGIOUS)) - continue - - diseases_to_add += disease - if(LAZYLEN(diseases_to_add)) - AddComponent(/datum/component/infective, diseases_to_add) +/obj/item/organ/Destroy() + if(bodypart_owner && !owner && !QDELETED(bodypart_owner)) + bodypart_remove(bodypart_owner) + else if(owner) + // The special flag is important, because otherwise mobs can die + // while undergoing transformation into different mobs. + Remove(owner, special=TRUE) + else + STOP_PROCESSING(SSobj, src) + return ..() /// Add a Trait to an organ that it will give its owner. /obj/item/organ/proc/add_organ_trait(trait) @@ -241,15 +125,6 @@ INITIALIZE_IMMEDIATE(/obj/item/organ) /obj/item/organ/proc/on_find(mob/living/finder) return -/** - * Proc that gets called when the organ is surgically removed by someone, can be used for special effects - * Currently only used so surplus organs can explode when surgically removed. - */ -/obj/item/organ/proc/on_surgical_removal(mob/living/user, mob/living/carbon/old_owner, target_zone, obj/item/tool) - SHOULD_CALL_PARENT(TRUE) - SEND_SIGNAL(src, COMSIG_ORGAN_SURGICALLY_REMOVED, user, old_owner, target_zone, tool) - RemoveElement(/datum/element/decal/blood) - /obj/item/organ/wash(clean_types) . = ..() @@ -452,4 +327,4 @@ INITIALIZE_IMMEDIATE(/obj/item/organ) /// Tries to replace the existing organ on the passed mob with this one, with special handling for replacing a brain without ghosting target /obj/item/organ/proc/replace_into(mob/living/carbon/new_owner) - return Insert(new_owner, special = TRUE, drop_if_replaced = FALSE) + return Insert(new_owner, special = TRUE, movement_flags = DELETE_IF_REPLACED) diff --git a/code/modules/surgery/organs/external/_external_organ.dm b/code/modules/surgery/organs/external/_external_organ.dm index db0d2535640..c75712d06d5 100644 --- a/code/modules/surgery/organs/external/_external_organ.dm +++ b/code/modules/surgery/organs/external/_external_organ.dm @@ -12,8 +12,6 @@ ///The overlay datum that actually draws stuff on the limb var/datum/bodypart_overlay/mutant/bodypart_overlay - ///Reference to the limb we're inside of - var/obj/item/bodypart/ownerlimb ///If not null, overrides the appearance with this sprite accessory datum var/sprite_accessory_override @@ -25,7 +23,7 @@ ///Set to EXTERNAL_BEHIND, EXTERNAL_FRONT or EXTERNAL_ADJACENT if you want to draw one of those layers as the object sprite. FALSE to use your own ///This will not work if it doesn't have a limb to generate it's icon with var/use_mob_sprite_as_obj_sprite = FALSE - ///Does this organ have any bodytypes to pass to it's ownerlimb? + ///Does this organ have any bodytypes to pass to it's bodypart_owner? var/external_bodytypes = NONE ///Which flags does a 'modification tool' need to have to restyle us, if it all possible (located in code/_DEFINES/mobs) var/restyle_flags = NONE @@ -55,23 +53,10 @@ if(restyle_flags) RegisterSignal(src, COMSIG_ATOM_RESTYLE, PROC_REF(on_attempt_feature_restyle)) -/obj/item/organ/external/Destroy() - if(owner) - Remove(owner, special=TRUE) - else if(ownerlimb) - remove_from_limb() - - return ..() - -/obj/item/organ/external/Insert(mob/living/carbon/receiver, special, drop_if_replaced) +/obj/item/organ/external/mob_insert(mob/living/carbon/receiver, special, movement_flags) if(!should_external_organ_apply_to(type, receiver)) stack_trace("adding a [type] to a [receiver.type] when it shouldn't be!") - var/obj/item/bodypart/limb = receiver.get_bodypart(deprecise_zone(zone)) - - if(!limb) - return FALSE - . = ..() if(!.) @@ -84,54 +69,28 @@ bodypart_overlay.set_appearance_from_name(feature_name) bodypart_overlay.imprint_on_next_insertion = FALSE - ownerlimb = limb - add_to_limb(ownerlimb) - if(external_bodytypes) receiver.synchronize_bodytypes() receiver.update_body_parts() -/obj/item/organ/external/Remove(mob/living/carbon/organ_owner, special, moving) - . = ..() - - if(ownerlimb) - remove_from_limb() - if(!moving && use_mob_sprite_as_obj_sprite) //so we're being taken out and dropped - update_appearance(UPDATE_OVERLAYS) - - if(organ_owner) +/obj/item/organ/external/mob_remove(mob/living/carbon/organ_owner, special, moving) + if(!special) + organ_owner.synchronize_bodytypes() organ_owner.update_body_parts() - - -/obj/item/organ/external/on_remove(mob/living/carbon/organ_owner, special) - . = ..() - color = bodypart_overlay.draw_color // so a pink felinid doesn't drop a gray tail - -///Transfers the organ to the limb, and to the limb's owner, if it has one. -/obj/item/organ/external/transfer_to_limb(obj/item/bodypart/bodypart, mob/living/carbon/bodypart_owner) - if(owner) - Remove(owner, moving = TRUE) - else if(ownerlimb) - remove_from_limb() - - if(bodypart_owner) - Insert(bodypart_owner, TRUE) - else - add_to_limb(bodypart) - -/obj/item/organ/external/add_to_limb(obj/item/bodypart/bodypart) - bodypart.external_organs += src - ownerlimb = bodypart - ownerlimb.add_bodypart_overlay(bodypart_overlay) return ..() -/obj/item/organ/external/remove_from_limb() - ownerlimb.external_organs -= src - ownerlimb.remove_bodypart_overlay(bodypart_overlay) - if(ownerlimb.owner && external_bodytypes) - ownerlimb.owner.synchronize_bodytypes() - ownerlimb = null +/obj/item/organ/external/on_bodypart_insert(obj/item/bodypart/bodypart) + bodypart.add_bodypart_overlay(bodypart_overlay) + return ..() + +/obj/item/organ/external/on_bodypart_remove(obj/item/bodypart/bodypart) + bodypart.remove_bodypart_overlay(bodypart_overlay) + + if(use_mob_sprite_as_obj_sprite) + update_appearance(UPDATE_OVERLAYS) + + color = bodypart_overlay.draw_color // so a pink felinid doesn't drop a gray tail return ..() /proc/should_external_organ_apply_to(obj/item/organ/external/organpath, mob/living/carbon/target) @@ -165,8 +124,8 @@ if(owner) //are we in a person? owner.update_body_parts() - else if(ownerlimb) //are we in a limb? - ownerlimb.update_icon_dropped() + else if(bodypart_owner) //are we in a limb? + bodypart_owner.update_icon_dropped() //else if(use_mob_sprite_as_obj_sprite) //are we out in the world, unprotected by flesh? /obj/item/organ/external/on_life(seconds_per_tick, times_fired) @@ -181,7 +140,7 @@ //Build the mob sprite and use it as our overlay for(var/external_layer in bodypart_overlay.all_layers) if(bodypart_overlay.layers & external_layer) - . += bodypart_overlay.get_overlay(external_layer, ownerlimb) + . += bodypart_overlay.get_overlay(external_layer, bodypart_owner) ///The horns of a lizard! /obj/item/organ/external/horns @@ -287,16 +246,17 @@ ///Store our old datum here for if our antennae are healed var/original_sprite_datum -/obj/item/organ/external/antennae/Insert(mob/living/carbon/receiver, special, drop_if_replaced) +/obj/item/organ/external/antennae/Insert(mob/living/carbon/receiver, special, movement_flags) . = ..() if(!.) return RegisterSignal(receiver, COMSIG_HUMAN_BURNING, PROC_REF(try_burn_antennae)) RegisterSignal(receiver, COMSIG_LIVING_POST_FULLY_HEAL, PROC_REF(heal_antennae)) -/obj/item/organ/external/antennae/Remove(mob/living/carbon/organ_owner, special, moving) +/obj/item/organ/external/antennae/Remove(mob/living/carbon/organ_owner, special, movement_flags) . = ..() - UnregisterSignal(organ_owner, list(COMSIG_HUMAN_BURNING, COMSIG_LIVING_POST_FULLY_HEAL)) + if(organ_owner) + UnregisterSignal(organ_owner, list(COMSIG_HUMAN_BURNING, COMSIG_LIVING_POST_FULLY_HEAL)) ///check if our antennae can burn off ;_; /obj/item/organ/external/antennae/proc/try_burn_antennae(mob/living/carbon/human/human) diff --git a/code/modules/surgery/organs/external/restyling.dm b/code/modules/surgery/organs/external/restyling.dm index 454e4395ae6..7d6be1b6d58 100644 --- a/code/modules/surgery/organs/external/restyling.dm +++ b/code/modules/surgery/organs/external/restyling.dm @@ -31,7 +31,7 @@ ///Asks the external organs inside the limb if they can restyle /obj/item/bodypart/proc/attempt_feature_restyle(atom/source, mob/living/trimmer, atom/movable/original_target, body_zone, restyle_type, style_speed) var/list/valid_features = list() - for(var/obj/item/organ/external/feature in external_organs) + for(var/obj/item/organ/external/feature in contents) if(feature.restyle_flags & restyle_type) valid_features.Add(feature) diff --git a/code/modules/surgery/organs/external/spines.dm b/code/modules/surgery/organs/external/spines.dm index d7b9dd785d0..7588e26735e 100644 --- a/code/modules/surgery/organs/external/spines.dm +++ b/code/modules/surgery/organs/external/spines.dm @@ -17,13 +17,13 @@ ///A two-way reference between the tail and the spines because of wagging sprites. Bruh. var/obj/item/organ/external/tail/lizard/paired_tail -/obj/item/organ/external/spines/Insert(mob/living/carbon/receiver, special, drop_if_replaced) +/obj/item/organ/external/spines/Insert(mob/living/carbon/receiver, special, movement_flags) . = ..() if(.) paired_tail = locate(/obj/item/organ/external/tail/lizard) in receiver.organs //We want specifically a lizard tail, so we don't use the slot. paired_tail?.paired_spines = src -/obj/item/organ/external/spines/Remove(mob/living/carbon/organ_owner, special, moving) +/obj/item/organ/external/spines/Remove(mob/living/carbon/organ_owner, special, movement_flags) . = ..() if(paired_tail) paired_tail.paired_spines = null diff --git a/code/modules/surgery/organs/external/tails.dm b/code/modules/surgery/organs/external/tails.dm index 65db70f70b5..9937ee18d10 100644 --- a/code/modules/surgery/organs/external/tails.dm +++ b/code/modules/surgery/organs/external/tails.dm @@ -18,7 +18,7 @@ ///The original owner of this tail var/original_owner //Yay, snowflake code! -/obj/item/organ/external/tail/Insert(mob/living/carbon/receiver, special, drop_if_replaced) +/obj/item/organ/external/tail/Insert(mob/living/carbon/receiver, special, movement_flags) . = ..() if(.) RegisterSignal(receiver, COMSIG_ORGAN_WAG_TAIL, PROC_REF(wag)) @@ -32,15 +32,12 @@ else if(type in receiver.dna.species.external_organs) receiver.add_mood_event("wrong_tail_regained", /datum/mood_event/tail_regained_wrong) -/obj/item/organ/external/tail/Remove(mob/living/carbon/organ_owner, special, moving) +/obj/item/organ/external/tail/on_mob_remove(mob/living/carbon/organ_owner, special) + . = ..() + if(wag_flags & WAG_WAGGING) wag(organ_owner, start = FALSE) - return ..() - -/obj/item/organ/external/tail/on_remove(mob/living/carbon/organ_owner, special) - . = ..() - UnregisterSignal(organ_owner, COMSIG_ORGAN_WAG_TAIL) if(type in organ_owner.dna.species.external_organs) @@ -136,13 +133,13 @@ ///A reference to the paired_spines, since for some fucking reason tail spines are tied to the spines themselves. var/obj/item/organ/external/spines/paired_spines -/obj/item/organ/external/tail/lizard/Insert(mob/living/carbon/receiver, special, drop_if_replaced) +/obj/item/organ/external/tail/lizard/Insert(mob/living/carbon/receiver, special, movement_flags) . = ..() if(.) - paired_spines = ownerlimb.owner.get_organ_slot(ORGAN_SLOT_EXTERNAL_SPINES) + paired_spines = bodypart_owner.owner.get_organ_slot(ORGAN_SLOT_EXTERNAL_SPINES) paired_spines?.paired_tail = src -/obj/item/organ/external/tail/lizard/Remove(mob/living/carbon/organ_owner, special, moving) +/obj/item/organ/external/tail/lizard/Remove(mob/living/carbon/organ_owner, special, movement_flags) . = ..() if(paired_spines) paired_spines.paired_tail = null diff --git a/code/modules/surgery/organs/external/wings/functional_wings.dm b/code/modules/surgery/organs/external/wings/functional_wings.dm index 72f55ea0e34..aacf6f08f6a 100644 --- a/code/modules/surgery/organs/external/wings/functional_wings.dm +++ b/code/modules/surgery/organs/external/wings/functional_wings.dm @@ -29,13 +29,13 @@ // grind_results = list(/datum/reagent/flightpotion = 5) food_reagents = list(/datum/reagent/flightpotion = 5) -/obj/item/organ/external/wings/functional/Insert(mob/living/carbon/receiver, special, drop_if_replaced) +/obj/item/organ/external/wings/functional/Insert(mob/living/carbon/receiver, special, movement_flags) . = ..() if(. && isnull(fly)) fly = new fly.Grant(receiver) -/obj/item/organ/external/wings/functional/Remove(mob/living/carbon/organ_owner, special, moving) +/obj/item/organ/external/wings/functional/Remove(mob/living/carbon/organ_owner, special, movement_flags) . = ..() fly.Remove(organ_owner) diff --git a/code/modules/surgery/organs/external/wings/moth_wings.dm b/code/modules/surgery/organs/external/wings/moth_wings.dm index f13b346ab07..f4e0f156e70 100644 --- a/code/modules/surgery/organs/external/wings/moth_wings.dm +++ b/code/modules/surgery/organs/external/wings/moth_wings.dm @@ -14,13 +14,13 @@ ///Store our old datum here for if our burned wings are healed var/original_sprite_datum -/obj/item/organ/external/wings/moth/on_insert(mob/living/carbon/receiver) +/obj/item/organ/external/wings/moth/on_mob_insert(mob/living/carbon/receiver) . = ..() RegisterSignal(receiver, COMSIG_HUMAN_BURNING, PROC_REF(try_burn_wings)) RegisterSignal(receiver, COMSIG_LIVING_POST_FULLY_HEAL, PROC_REF(heal_wings)) RegisterSignal(receiver, COMSIG_MOVABLE_PRE_MOVE, PROC_REF(update_float_move)) -/obj/item/organ/external/wings/moth/on_remove(mob/living/carbon/organ_owner) +/obj/item/organ/external/wings/moth/on_mob_remove(mob/living/carbon/organ_owner) . = ..() UnregisterSignal(organ_owner, list(COMSIG_HUMAN_BURNING, COMSIG_LIVING_POST_FULLY_HEAL, COMSIG_MOVABLE_PRE_MOVE)) REMOVE_TRAIT(organ_owner, TRAIT_FREE_FLOAT_MOVEMENT, REF(src)) diff --git a/code/modules/surgery/organs/internal/_internal_organ.dm b/code/modules/surgery/organs/internal/_internal_organ.dm index eb8629347e6..ecd6eb2b7d7 100644 --- a/code/modules/surgery/organs/internal/_internal_organ.dm +++ b/code/modules/surgery/organs/internal/_internal_organ.dm @@ -5,19 +5,8 @@ . = ..() START_PROCESSING(SSobj, src) -/obj/item/organ/internal/Destroy() - if(owner) - // The special flag is important, because otherwise mobs can die - // while undergoing transformation into different mobs. - Remove(owner, special=TRUE) - else - STOP_PROCESSING(SSobj, src) - return ..() - -/obj/item/organ/internal/Insert(mob/living/carbon/receiver, special = FALSE, drop_if_replaced = TRUE) +/obj/item/organ/internal/on_mob_insert(mob/living/carbon/organ_owner, special, movement_flags) . = ..() - if(!. || !owner) - return // organs_slot must ALWAYS be ordered in the same way as organ_process_order // Otherwise life processing breaks down @@ -25,18 +14,16 @@ STOP_PROCESSING(SSobj, src) -/obj/item/organ/internal/Remove(mob/living/carbon/organ_owner, special = FALSE) +/obj/item/organ/internal/on_mob_remove(mob/living/carbon/organ_owner, special = FALSE) . = ..() - if(organ_owner) - if((organ_flags & ORGAN_VITAL) && !special && !(organ_owner.status_flags & GODMODE)) - if(organ_owner.stat != DEAD) - organ_owner.investigate_log("has been killed by losing a vital organ ([src]).", INVESTIGATE_DEATHS) - organ_owner.death() + if((organ_flags & ORGAN_VITAL) && !special && !(organ_owner.status_flags & GODMODE)) + if(organ_owner.stat != DEAD) + organ_owner.investigate_log("has been killed by losing a vital organ ([src]).", INVESTIGATE_DEATHS) + organ_owner.death() START_PROCESSING(SSobj, src) - /obj/item/organ/internal/process(seconds_per_tick, times_fired) on_death(seconds_per_tick, times_fired) //Kinda hate doing it like this, but I really don't want to call process directly. diff --git a/code/modules/surgery/organs/internal/appendix/_appendix.dm b/code/modules/surgery/organs/internal/appendix/_appendix.dm index ee87d674dc4..e5190f1282e 100644 --- a/code/modules/surgery/organs/internal/appendix/_appendix.dm +++ b/code/modules/surgery/organs/internal/appendix/_appendix.dm @@ -76,12 +76,12 @@ /obj/item/organ/internal/appendix/get_availability(datum/species/owner_species, mob/living/owner_mob) return owner_species.mutantappendix -/obj/item/organ/internal/appendix/on_remove(mob/living/carbon/organ_owner) +/obj/item/organ/internal/appendix/on_mob_remove(mob/living/carbon/organ_owner) . = ..() REMOVE_TRAIT(organ_owner, TRAIT_DISEASELIKE_SEVERITY_MEDIUM, type) organ_owner.med_hud_set_status() -/obj/item/organ/internal/appendix/on_insert(mob/living/carbon/organ_owner) +/obj/item/organ/internal/appendix/on_mob_insert(mob/living/carbon/organ_owner) . = ..() if(inflamation_stage) ADD_TRAIT(organ_owner, TRAIT_DISEASELIKE_SEVERITY_MEDIUM, type) diff --git a/code/modules/surgery/organs/internal/appendix/appendix_golem.dm b/code/modules/surgery/organs/internal/appendix/appendix_golem.dm index ede8dfa1e6b..5510b4bf967 100644 --- a/code/modules/surgery/organs/internal/appendix/appendix_golem.dm +++ b/code/modules/surgery/organs/internal/appendix/appendix_golem.dm @@ -12,7 +12,7 @@ . = ..() smelter = new(src) -/obj/item/organ/internal/appendix/golem/on_insert(mob/living/carbon/organ_owner) +/obj/item/organ/internal/appendix/golem/on_mob_insert(mob/living/carbon/organ_owner) . = ..() RegisterSignal(owner, COMSIG_MOVABLE_MOVED, PROC_REF(check_for_lava)) @@ -25,7 +25,7 @@ if (smelter.owner != owner) smelter.Grant(owner) -/obj/item/organ/internal/appendix/golem/on_remove(mob/living/carbon/organ_owner) +/obj/item/organ/internal/appendix/golem/on_mob_remove(mob/living/carbon/organ_owner) UnregisterSignal(organ_owner, COMSIG_MOVABLE_MOVED) smelter?.Remove(organ_owner) // Might have been deleted by Destroy already return ..() diff --git a/code/modules/surgery/organs/internal/cyberimp/augments_arms.dm b/code/modules/surgery/organs/internal/cyberimp/augments_arms.dm index 2c14c91dbd5..6f87ad0e8ee 100644 --- a/code/modules/surgery/organs/internal/cyberimp/augments_arms.dm +++ b/code/modules/surgery/organs/internal/cyberimp/augments_arms.dm @@ -76,7 +76,7 @@ to_chat(user, span_notice("You modify [src] to be installed on the [zone == BODY_ZONE_R_ARM ? "right" : "left"] arm.")) update_appearance() -/obj/item/organ/internal/cyberimp/arm/on_insert(mob/living/carbon/arm_owner) +/obj/item/organ/internal/cyberimp/arm/on_mob_insert(mob/living/carbon/arm_owner) . = ..() var/side = zone == BODY_ZONE_R_ARM? RIGHT_HANDS : LEFT_HANDS hand = arm_owner.hand_bodyparts[side] @@ -84,7 +84,7 @@ RegisterSignal(hand, COMSIG_ITEM_ATTACK_SELF, PROC_REF(on_item_attack_self)) //If the limb gets an attack-self, open the menu. Only happens when hand is empty RegisterSignal(arm_owner, COMSIG_KB_MOB_DROPITEM_DOWN, PROC_REF(dropkey)) //We're nodrop, but we'll watch for the drop hotkey anyway and then stow if possible. -/obj/item/organ/internal/cyberimp/arm/on_remove(mob/living/carbon/arm_owner) +/obj/item/organ/internal/cyberimp/arm/on_mob_remove(mob/living/carbon/arm_owner) . = ..() Retract() if(hand) @@ -378,14 +378,14 @@ ///How long will the implant malfunction if it is EMP'd var/emp_base_duration = 9 SECONDS -/obj/item/organ/internal/cyberimp/arm/muscle/Insert(mob/living/carbon/receiver, special = FALSE, drop_if_replaced = TRUE) +/obj/item/organ/internal/cyberimp/arm/muscle/on_mob_insert(mob/living/carbon/arm_owner) . = ..() - if(ishuman(receiver)) //Sorry, only humans - RegisterSignal(receiver, COMSIG_LIVING_EARLY_UNARMED_ATTACK, PROC_REF(on_attack_hand)) + if(ishuman(arm_owner)) //Sorry, only humans + RegisterSignal(arm_owner, COMSIG_LIVING_EARLY_UNARMED_ATTACK, PROC_REF(on_attack_hand)) -/obj/item/organ/internal/cyberimp/arm/muscle/Remove(mob/living/carbon/implant_owner, special = 0) +/obj/item/organ/internal/cyberimp/arm/muscle/on_mob_remove(mob/living/carbon/arm_owner) . = ..() - UnregisterSignal(implant_owner, COMSIG_LIVING_EARLY_UNARMED_ATTACK) + UnregisterSignal(arm_owner, COMSIG_LIVING_EARLY_UNARMED_ATTACK) /obj/item/organ/internal/cyberimp/arm/muscle/emp_act(severity) . = ..() diff --git a/code/modules/surgery/organs/internal/cyberimp/augments_chest.dm b/code/modules/surgery/organs/internal/cyberimp/augments_chest.dm index 3fe5e150288..41860d60b48 100644 --- a/code/modules/surgery/organs/internal/cyberimp/augments_chest.dm +++ b/code/modules/surgery/organs/internal/cyberimp/augments_chest.dm @@ -182,7 +182,7 @@ /datum/effect_system/trail_follow/ion \ ) -/obj/item/organ/internal/cyberimp/chest/thrusters/Remove(mob/living/carbon/thruster_owner, special = 0) +/obj/item/organ/internal/cyberimp/chest/thrusters/Remove(mob/living/carbon/thruster_owner, special, movement_flags) if(on) deactivate(silent = TRUE) ..() diff --git a/code/modules/surgery/organs/internal/cyberimp/augments_eyes.dm b/code/modules/surgery/organs/internal/cyberimp/augments_eyes.dm index 869d4cc1c9e..cec0241ece3 100644 --- a/code/modules/surgery/organs/internal/cyberimp/augments_eyes.dm +++ b/code/modules/surgery/organs/internal/cyberimp/augments_eyes.dm @@ -31,7 +31,7 @@ hud.show_to(eye_owner) toggled_on = TRUE -/obj/item/organ/internal/cyberimp/eyes/hud/Insert(mob/living/carbon/eye_owner, special = FALSE, drop_if_replaced = TRUE) +/obj/item/organ/internal/cyberimp/eyes/hud/Insert(mob/living/carbon/eye_owner, special = FALSE, movement_flags) . = ..() if(!.) return @@ -42,7 +42,7 @@ ADD_TRAIT(eye_owner, HUD_trait, ORGAN_TRAIT) toggled_on = TRUE -/obj/item/organ/internal/cyberimp/eyes/hud/Remove(mob/living/carbon/eye_owner, special = FALSE) +/obj/item/organ/internal/cyberimp/eyes/hud/Remove(mob/living/carbon/eye_owner, special, movement_flags) . = ..() if(HUD_type) var/datum/atom_hud/hud = GLOB.huds[HUD_type] diff --git a/code/modules/surgery/organs/internal/cyberimp/augments_internal.dm b/code/modules/surgery/organs/internal/cyberimp/augments_internal.dm index f0578832969..67a02e71d7e 100644 --- a/code/modules/surgery/organs/internal/cyberimp/augments_internal.dm +++ b/code/modules/surgery/organs/internal/cyberimp/augments_internal.dm @@ -87,7 +87,7 @@ stored_items = list() -/obj/item/organ/internal/cyberimp/brain/anti_drop/Remove(mob/living/carbon/implant_owner, special = 0) +/obj/item/organ/internal/cyberimp/brain/anti_drop/Remove(mob/living/carbon/implant_owner, special, movement_flags) if(active) ui_action_click() ..() @@ -113,11 +113,11 @@ var/stun_cap_amount = 40 -/obj/item/organ/internal/cyberimp/brain/anti_stun/on_remove(mob/living/carbon/implant_owner) +/obj/item/organ/internal/cyberimp/brain/anti_stun/on_mob_remove(mob/living/carbon/implant_owner) . = ..() UnregisterSignal(implant_owner, signalCache) -/obj/item/organ/internal/cyberimp/brain/anti_stun/on_insert(mob/living/carbon/receiver) +/obj/item/organ/internal/cyberimp/brain/anti_stun/on_mob_insert(mob/living/carbon/receiver) . = ..() RegisterSignals(receiver, signalCache, PROC_REF(on_signal)) diff --git a/code/modules/surgery/organs/internal/ears/_ears.dm b/code/modules/surgery/organs/internal/ears/_ears.dm index 7d2b0f3c549..ad48645e893 100644 --- a/code/modules/surgery/organs/internal/ears/_ears.dm +++ b/code/modules/surgery/organs/internal/ears/_ears.dm @@ -68,7 +68,7 @@ visual = TRUE damage_multiplier = 2 -/obj/item/organ/internal/ears/cat/on_insert(mob/living/carbon/human/ear_owner) +/obj/item/organ/internal/ears/cat/on_mob_insert(mob/living/carbon/human/ear_owner) . = ..() if(istype(ear_owner) && ear_owner.dna) color = ear_owner.hair_color @@ -76,7 +76,7 @@ ear_owner.dna.update_uf_block(DNA_EARS_BLOCK) ear_owner.update_body() -/obj/item/organ/internal/ears/cat/on_remove(mob/living/carbon/human/ear_owner) +/obj/item/organ/internal/ears/cat/on_mob_remove(mob/living/carbon/human/ear_owner) . = ..() if(istype(ear_owner) && ear_owner.dna) color = ear_owner.hair_color @@ -87,13 +87,13 @@ name = "penguin ears" desc = "The source of a penguin's happy feet." -/obj/item/organ/internal/ears/penguin/on_insert(mob/living/carbon/human/ear_owner) +/obj/item/organ/internal/ears/penguin/on_mob_insert(mob/living/carbon/human/ear_owner) . = ..() if(istype(ear_owner)) to_chat(ear_owner, span_notice("You suddenly feel like you've lost your balance.")) ear_owner.AddElement(/datum/element/waddling) -/obj/item/organ/internal/ears/penguin/on_remove(mob/living/carbon/human/ear_owner) +/obj/item/organ/internal/ears/penguin/on_mob_remove(mob/living/carbon/human/ear_owner) . = ..() if(istype(ear_owner)) to_chat(ear_owner, span_notice("Your sense of balance comes back to you.")) @@ -122,11 +122,11 @@ // The original idea was to use signals to do this not traits. Unfortunately, the star effect used for whispers applies before any relevant signals // This seems like the least invasive solution -/obj/item/organ/internal/ears/cybernetic/whisper/on_insert(mob/living/carbon/ear_owner) +/obj/item/organ/internal/ears/cybernetic/whisper/on_mob_insert(mob/living/carbon/ear_owner) . = ..() ADD_TRAIT(ear_owner, TRAIT_GOOD_HEARING, ORGAN_TRAIT) -/obj/item/organ/internal/ears/cybernetic/whisper/on_remove(mob/living/carbon/ear_owner) +/obj/item/organ/internal/ears/cybernetic/whisper/on_mob_remove(mob/living/carbon/ear_owner) . = ..() REMOVE_TRAIT(ear_owner, TRAIT_GOOD_HEARING, ORGAN_TRAIT) @@ -138,11 +138,11 @@ // Same sensitivity as felinid ears damage_multiplier = 2 -/obj/item/organ/internal/ears/cybernetic/xray/on_insert(mob/living/carbon/ear_owner) +/obj/item/organ/internal/ears/cybernetic/xray/on_mob_insert(mob/living/carbon/ear_owner) . = ..() ADD_TRAIT(ear_owner, TRAIT_XRAY_HEARING, ORGAN_TRAIT) -/obj/item/organ/internal/ears/cybernetic/xray/on_remove(mob/living/carbon/ear_owner) +/obj/item/organ/internal/ears/cybernetic/xray/on_mob_remove(mob/living/carbon/ear_owner) . = ..() REMOVE_TRAIT(ear_owner, TRAIT_XRAY_HEARING, ORGAN_TRAIT) diff --git a/code/modules/surgery/organs/internal/eyes/_eyes.dm b/code/modules/surgery/organs/internal/eyes/_eyes.dm index 2b6329702f3..d9c0ea86fcf 100644 --- a/code/modules/surgery/organs/internal/eyes/_eyes.dm +++ b/code/modules/surgery/organs/internal/eyes/_eyes.dm @@ -52,7 +52,7 @@ /// Native FOV that will be applied if a config is enabled var/native_fov = FOV_90_DEGREES -/obj/item/organ/internal/eyes/Insert(mob/living/carbon/eye_recipient, special = FALSE, drop_if_replaced = FALSE) +/obj/item/organ/internal/eyes/Insert(mob/living/carbon/eye_recipient, special = FALSE, movement_flags = DELETE_IF_REPLACED) // If we don't do this before everything else, heterochromia will be reset leading to eye_color_right no longer being accurate if(ishuman(eye_recipient)) var/mob/living/carbon/human/human_recipient = eye_recipient @@ -94,7 +94,7 @@ if(call_update) affected_human.update_body() -/obj/item/organ/internal/eyes/Remove(mob/living/carbon/eye_owner, special = FALSE) +/obj/item/organ/internal/eyes/Remove(mob/living/carbon/eye_owner, special, movement_flags) . = ..() if(ishuman(eye_owner)) var/mob/living/carbon/human/human_owner = eye_owner @@ -104,7 +104,8 @@ human_owner.eye_color_right = old_eye_color_right if(native_fov) eye_owner.remove_fov_trait(type) - human_owner.update_body() + if(!special) + human_owner.update_body() // Cure blindness from eye damage eye_owner.cure_blind(EYE_DAMAGE) @@ -327,11 +328,11 @@ eye_color_right = "000" sight_flags = SEE_MOBS | SEE_OBJS | SEE_TURFS -/obj/item/organ/internal/eyes/robotic/xray/on_insert(mob/living/carbon/eye_owner) +/obj/item/organ/internal/eyes/robotic/xray/on_mob_insert(mob/living/carbon/eye_owner) . = ..() ADD_TRAIT(eye_owner, TRAIT_XRAY_VISION, ORGAN_TRAIT) -/obj/item/organ/internal/eyes/robotic/xray/on_remove(mob/living/carbon/eye_owner) +/obj/item/organ/internal/eyes/robotic/xray/on_mob_remove(mob/living/carbon/eye_owner) . = ..() REMOVE_TRAIT(eye_owner, TRAIT_XRAY_VISION, ORGAN_TRAIT) @@ -359,7 +360,7 @@ /obj/item/organ/internal/eyes/robotic/flashlight/emp_act(severity) return -/obj/item/organ/internal/eyes/robotic/flashlight/on_insert(mob/living/carbon/victim) +/obj/item/organ/internal/eyes/robotic/flashlight/on_mob_insert(mob/living/carbon/victim) . = ..() if(!eye) eye = new /obj/item/flashlight/eyelight() @@ -368,7 +369,7 @@ eye.update_brightness(victim) victim.become_blind(FLASHLIGHT_EYES) -/obj/item/organ/internal/eyes/robotic/flashlight/on_remove(mob/living/carbon/victim) +/obj/item/organ/internal/eyes/robotic/flashlight/on_mob_remove(mob/living/carbon/victim) . = ..() eye.set_light_on(FALSE) eye.update_brightness(victim) @@ -425,18 +426,18 @@ deactivate(close_ui = TRUE) /// Set the initial color of the eyes on insert to be the mob's previous eye color. -/obj/item/organ/internal/eyes/robotic/glow/Insert(mob/living/carbon/eye_recipient, special = FALSE, drop_if_replaced = FALSE) +/obj/item/organ/internal/eyes/robotic/glow/Insert(mob/living/carbon/eye_recipient, special = FALSE, movement_flags = DELETE_IF_REPLACED) . = ..() left_eye_color_string = old_eye_color_left right_eye_color_string = old_eye_color_right update_mob_eye_color(eye_recipient) -/obj/item/organ/internal/eyes/robotic/glow/on_insert(mob/living/carbon/eye_recipient) +/obj/item/organ/internal/eyes/robotic/glow/on_mob_insert(mob/living/carbon/eye_recipient) . = ..() deactivate(close_ui = TRUE) eye.forceMove(eye_recipient) -/obj/item/organ/internal/eyes/robotic/glow/on_remove(mob/living/carbon/eye_owner) +/obj/item/organ/internal/eyes/robotic/glow/on_mob_remove(mob/living/carbon/eye_owner) deactivate(eye_owner, close_ui = TRUE) if(!QDELETED(eye)) eye.forceMove(src) @@ -723,7 +724,7 @@ high_light_cutoff = list(30, 35, 50) var/obj/item/flashlight/eyelight/adapted/adapt_light -/obj/item/organ/internal/eyes/night_vision/maintenance_adapted/on_insert(mob/living/carbon/eye_owner) +/obj/item/organ/internal/eyes/night_vision/maintenance_adapted/on_mob_insert(mob/living/carbon/eye_owner) . = ..() //add lighting if(!adapt_light) @@ -742,7 +743,7 @@ apply_organ_damage(-10) //heal quickly . = ..() -/obj/item/organ/internal/eyes/night_vision/maintenance_adapted/Remove(mob/living/carbon/unadapted, special = FALSE) +/obj/item/organ/internal/eyes/night_vision/maintenance_adapted/on_mob_remove(mob/living/carbon/unadapted, special = FALSE) //remove lighting adapt_light.set_light_on(FALSE) adapt_light.update_brightness(unadapted) diff --git a/code/modules/surgery/organs/internal/heart/_heart.dm b/code/modules/surgery/organs/internal/heart/_heart.dm index 8a5646d1814..e2ca8725b9d 100644 --- a/code/modules/surgery/organs/internal/heart/_heart.dm +++ b/code/modules/surgery/organs/internal/heart/_heart.dm @@ -33,7 +33,7 @@ . = ..() icon_state = "[base_icon_state]-[beating ? "on" : "off"]" -/obj/item/organ/internal/heart/Remove(mob/living/carbon/heartless, special = 0) +/obj/item/organ/internal/heart/Remove(mob/living/carbon/heartless, special, movement_flags) . = ..() if(!special) addtimer(CALLBACK(src, PROC_REF(stop_if_unowned)), 12 SECONDS) @@ -146,12 +146,14 @@ else return ..() -/obj/item/organ/internal/heart/cursed/on_insert(mob/living/carbon/accursed) +/obj/item/organ/internal/heart/cursed/on_mob_insert(mob/living/carbon/accursed) . = ..() + accursed.AddComponent(/datum/component/manual_heart, pump_delay = pump_delay, blood_loss = blood_loss, heal_brute = heal_brute, heal_burn = heal_burn, heal_oxy = heal_oxy) -/obj/item/organ/internal/heart/cursed/Remove(mob/living/carbon/accursed, special = FALSE) +/obj/item/organ/internal/heart/cursed/on_mob_remove(mob/living/carbon/accursed, special = FALSE) . = ..() + qdel(accursed.GetComponent(/datum/component/manual_heart)) /obj/item/organ/internal/heart/cybernetic diff --git a/code/modules/surgery/organs/internal/heart/heart_ethereal.dm b/code/modules/surgery/organs/internal/heart/heart_ethereal.dm index 78ee55b0b28..50659115872 100644 --- a/code/modules/surgery/organs/internal/heart/heart_ethereal.dm +++ b/code/modules/surgery/organs/internal/heart/heart_ethereal.dm @@ -21,7 +21,7 @@ add_atom_colour(ethereal_color, FIXED_COLOUR_PRIORITY) update_appearance() -/obj/item/organ/internal/heart/ethereal/Insert(mob/living/carbon/heart_owner, special = FALSE, drop_if_replaced = TRUE) +/obj/item/organ/internal/heart/ethereal/Insert(mob/living/carbon/heart_owner, special = FALSE, movement_flags) . = ..() if(!.) return @@ -29,7 +29,7 @@ RegisterSignal(heart_owner, COMSIG_LIVING_POST_FULLY_HEAL, PROC_REF(on_owner_fully_heal)) RegisterSignal(heart_owner, COMSIG_QDELETING, PROC_REF(owner_deleted)) -/obj/item/organ/internal/heart/ethereal/Remove(mob/living/carbon/heart_owner, special = FALSE) +/obj/item/organ/internal/heart/ethereal/Remove(mob/living/carbon/heart_owner, special, movement_flags) UnregisterSignal(heart_owner, list(COMSIG_MOB_STATCHANGE, COMSIG_LIVING_POST_FULLY_HEAL, COMSIG_QDELETING)) REMOVE_TRAIT(heart_owner, TRAIT_CORPSELOCKED, SPECIES_TRAIT) stop_crystalization_process(heart_owner) diff --git a/code/modules/surgery/organs/internal/liver/_liver.dm b/code/modules/surgery/organs/internal/liver/_liver.dm index c78b071eec0..92e2cb0039f 100755 --- a/code/modules/surgery/organs/internal/liver/_liver.dm +++ b/code/modules/surgery/organs/internal/liver/_liver.dm @@ -61,12 +61,12 @@ qdel(GetComponent(/datum/component/squeak)) /// Registers COMSIG_SPECIES_HANDLE_CHEMICAL from owner -/obj/item/organ/internal/liver/on_insert(mob/living/carbon/organ_owner, special) +/obj/item/organ/internal/liver/on_mob_insert(mob/living/carbon/organ_owner, special) . = ..() RegisterSignal(organ_owner, COMSIG_SPECIES_HANDLE_CHEMICAL, PROC_REF(handle_chemical)) /// Unregisters COMSIG_SPECIES_HANDLE_CHEMICAL from owner -/obj/item/organ/internal/liver/on_remove(mob/living/carbon/organ_owner, special) +/obj/item/organ/internal/liver/on_mob_remove(mob/living/carbon/organ_owner, special) . = ..() UnregisterSignal(organ_owner, COMSIG_SPECIES_HANDLE_CHEMICAL) @@ -134,7 +134,7 @@ return var/obj/belly = owner.get_organ_slot(ORGAN_SLOT_STOMACH) - var/list/cached_reagents = owner.reagents.reagent_list + var/list/cached_reagents = owner.reagents?.reagent_list var/liver_damage = 0 var/provide_pain_message = HAS_NO_TOXIN @@ -152,7 +152,7 @@ if(provide_pain_message != HAS_PAINFUL_TOXIN) provide_pain_message = toxin.silent_toxin ? HAS_SILENT_TOXIN : HAS_PAINFUL_TOXIN - owner.reagents.metabolize(owner, seconds_per_tick, times_fired, can_overdose = TRUE) + owner.reagents?.metabolize(owner, seconds_per_tick, times_fired, can_overdose = TRUE) if(liver_damage) apply_organ_damage(min(liver_damage * seconds_per_tick , MAX_TOXIN_LIVER_DAMAGE * seconds_per_tick)) diff --git a/code/modules/surgery/organs/internal/lungs/_lungs.dm b/code/modules/surgery/organs/internal/lungs/_lungs.dm index 2e99f70d989..874ec320648 100644 --- a/code/modules/surgery/organs/internal/lungs/_lungs.dm +++ b/code/modules/surgery/organs/internal/lungs/_lungs.dm @@ -153,7 +153,7 @@ add_gas_reaction(/datum/gas/zauker, while_present = PROC_REF(too_much_zauker)) ///Simply exists so that you don't keep any alerts from your previous lack of lungs. -/obj/item/organ/internal/lungs/Insert(mob/living/carbon/receiver, special = FALSE, drop_if_replaced = TRUE) +/obj/item/organ/internal/lungs/Insert(mob/living/carbon/receiver, special = FALSE, movement_flags) . = ..() if(!.) return . @@ -163,7 +163,7 @@ receiver.clear_alert(ALERT_NOT_ENOUGH_PLASMA) receiver.clear_alert(ALERT_NOT_ENOUGH_N2O) -/obj/item/organ/internal/lungs/Remove(mob/living/carbon/organ_owner, special) +/obj/item/organ/internal/lungs/Remove(mob/living/carbon/organ_owner, special, movement_flags) . = ..() // This is very "manual" I realize, but it's useful to ensure cleanup for gases we're removing happens // Avoids stuck alerts and such diff --git a/code/modules/surgery/organs/internal/stomach/_stomach.dm b/code/modules/surgery/organs/internal/stomach/_stomach.dm index d97b883817d..6e985e26329 100644 --- a/code/modules/surgery/organs/internal/stomach/_stomach.dm +++ b/code/modules/surgery/organs/internal/stomach/_stomach.dm @@ -55,7 +55,7 @@ var/mob/living/carbon/body = owner // digest food, sent all reagents that can metabolize to the body - for(var/datum/reagent/bit as anything in reagents.reagent_list) + for(var/datum/reagent/bit as anything in reagents?.reagent_list) // If the reagent does not metabolize then it will sit in the stomach // This has an effect on items like plastic causing them to take up space in the stomach @@ -93,7 +93,7 @@ return //We are checking if we have nutriment in a damaged stomach. - var/datum/reagent/nutri = locate(/datum/reagent/consumable/nutriment) in reagents.reagent_list + var/datum/reagent/nutri = locate(/datum/reagent/consumable/nutriment) in reagents?.reagent_list //No nutriment found lets exit out if(!nutri) return @@ -262,7 +262,7 @@ disgusted.throw_alert(ALERT_DISGUST, /atom/movable/screen/alert/disgusted) disgusted.add_mood_event("disgust", /datum/mood_event/disgusted) -/obj/item/organ/internal/stomach/Remove(mob/living/carbon/stomach_owner, special = 0) +/obj/item/organ/internal/stomach/Remove(mob/living/carbon/stomach_owner, special, movement_flags) if(ishuman(stomach_owner)) var/mob/living/carbon/human/human_owner = owner human_owner.clear_alert(ALERT_DISGUST) diff --git a/code/modules/surgery/organs/internal/stomach/stomach_ethereal.dm b/code/modules/surgery/organs/internal/stomach/stomach_ethereal.dm index c1632f33329..68f9d9428a0 100644 --- a/code/modules/surgery/organs/internal/stomach/stomach_ethereal.dm +++ b/code/modules/surgery/organs/internal/stomach/stomach_ethereal.dm @@ -13,12 +13,12 @@ adjust_charge(-ETHEREAL_CHARGE_FACTOR * seconds_per_tick) handle_charge(owner, seconds_per_tick, times_fired) -/obj/item/organ/internal/stomach/ethereal/on_insert(mob/living/carbon/stomach_owner) +/obj/item/organ/internal/stomach/ethereal/on_mob_insert(mob/living/carbon/stomach_owner) . = ..() RegisterSignal(stomach_owner, COMSIG_PROCESS_BORGCHARGER_OCCUPANT, PROC_REF(charge)) RegisterSignal(stomach_owner, COMSIG_LIVING_ELECTROCUTE_ACT, PROC_REF(on_electrocute)) -/obj/item/organ/internal/stomach/ethereal/on_remove(mob/living/carbon/stomach_owner) +/obj/item/organ/internal/stomach/ethereal/on_mob_remove(mob/living/carbon/stomach_owner) . = ..() UnregisterSignal(stomach_owner, COMSIG_PROCESS_BORGCHARGER_OCCUPANT) UnregisterSignal(stomach_owner, COMSIG_LIVING_ELECTROCUTE_ACT) diff --git a/code/modules/surgery/organs/internal/stomach/stomach_golem.dm b/code/modules/surgery/organs/internal/stomach/stomach_golem.dm index 5f721fa52b1..a1f5ce6c70e 100644 --- a/code/modules/surgery/organs/internal/stomach/stomach_golem.dm +++ b/code/modules/surgery/organs/internal/stomach/stomach_golem.dm @@ -11,11 +11,11 @@ /// How slow are you if you have absolutely nothing in the tank? var/max_hunger_slowdown = 4 -/obj/item/organ/internal/stomach/golem/on_insert(mob/living/carbon/organ_owner, special) +/obj/item/organ/internal/stomach/golem/on_mob_insert(mob/living/carbon/organ_owner, special) . = ..() RegisterSignal(owner, COMSIG_CARBON_ATTEMPT_EAT, PROC_REF(try_eating)) -/obj/item/organ/internal/stomach/golem/on_remove(mob/living/carbon/organ_owner, special) +/obj/item/organ/internal/stomach/golem/on_mob_remove(mob/living/carbon/organ_owner, special) . = ..() UnregisterSignal(organ_owner, COMSIG_CARBON_ATTEMPT_EAT) organ_owner.remove_movespeed_modifier(/datum/movespeed_modifier/golem_hunger) diff --git a/code/modules/surgery/organs/internal/tongue/_tongue.dm b/code/modules/surgery/organs/internal/tongue/_tongue.dm index ca5e3873a2b..cbed058a44c 100644 --- a/code/modules/surgery/organs/internal/tongue/_tongue.dm +++ b/code/modules/surgery/organs/internal/tongue/_tongue.dm @@ -120,7 +120,7 @@ food_taste_reaction = FOOD_LIKED return food_taste_reaction -/obj/item/organ/internal/tongue/Insert(mob/living/carbon/tongue_owner, special = FALSE, drop_if_replaced = TRUE) +/obj/item/organ/internal/tongue/Insert(mob/living/carbon/tongue_owner, special = FALSE, movement_flags) . = ..() if(!.) return @@ -135,7 +135,7 @@ REMOVE_TRAIT(tongue_owner, TRAIT_AGEUSIA, NO_TONGUE_TRAIT) apply_tongue_effects() -/obj/item/organ/internal/tongue/Remove(mob/living/carbon/tongue_owner, special = FALSE) +/obj/item/organ/internal/tongue/Remove(mob/living/carbon/tongue_owner, special, movement_flags) . = ..() temp_say_mod = "" UnregisterSignal(tongue_owner, COMSIG_MOB_SAY) diff --git a/code/modules/surgery/organs/organ_movement.dm b/code/modules/surgery/organs/organ_movement.dm new file mode 100644 index 00000000000..98eeb969fac --- /dev/null +++ b/code/modules/surgery/organs/organ_movement.dm @@ -0,0 +1,230 @@ +// There are two kinds of organ movement: mob movement and limb movement +// If you pull someones brain out, you remove it from the mob and the limb +// If you take someones head off, you remove it from the mob but not the limb +// If you remove the brain from an already decapitated head, you remove it from the limb but not the mob + +// Keep the seperation of limb removal and mob removal absolute + +/* + * Insert the organ into the select mob. + * + * receiver - the mob who will get our organ + * special - "quick swapping" an organ out - when TRUE, the mob will be unaffected by not having that organ for the moment + * movement_flags - Flags for how we behave in movement. See DEFINES/organ_movement for flags + */ +/obj/item/organ/proc/Insert(mob/living/carbon/receiver, special = FALSE, movement_flags) + SHOULD_CALL_PARENT(TRUE) + + mob_insert(receiver, special, movement_flags) + bodypart_insert(limb_owner = receiver, movement_flags = movement_flags) + + return TRUE + +/* + * Remove the organ from the select mob. + * + * * organ_owner - the mob who owns our organ, that we're removing the organ from. Can be null + * * special - "quick swapping" an organ out - when TRUE, the mob will be unaffected by not having that organ for the moment + */ +/obj/item/organ/proc/Remove(mob/living/carbon/organ_owner, special = FALSE, movement_flags) + SHOULD_CALL_PARENT(TRUE) + + mob_remove(organ_owner, special, movement_flags) + bodypart_remove(null, organ_owner, movement_flags) + +/* + * Insert the organ into the select mob. + * + * receiver - the mob who will get our organ + * special - "quick swapping" an organ out - when TRUE, the mob will be unaffected by not having that organ for the moment + * movement_flags - Flags for how we behave in movement. See DEFINES/organ_movement for flags + */ +/obj/item/organ/proc/mob_insert(mob/living/carbon/receiver, special, movement_flags) + SHOULD_CALL_PARENT(TRUE) + + if(!iscarbon(receiver)) + stack_trace("Tried to insert organ into non-carbon: [receiver.type]") + return + + if(owner == receiver) + stack_trace("Organ receiver is already organ owner") + return + + var/obj/item/organ/replaced = receiver.get_organ_slot(slot) + if(replaced) + replaced.Remove(receiver, special = TRUE) + if(movement_flags & DELETE_IF_REPLACED) + qdel(replaced) + else + replaced.forceMove(get_turf(receiver)) + + if(!IS_ROBOTIC_ORGAN(src) && (organ_flags & ORGAN_VIRGIN)) + blood_dna_info = receiver.get_blood_dna_list() + // need to remove the synethic blood DNA that is initialized + // wash also adds the blood dna again + wash(CLEAN_TYPE_BLOOD) + organ_flags &= ~ORGAN_VIRGIN + + receiver.organs |= src + receiver.organs_slot[slot] = src + owner = receiver + + on_mob_insert(receiver, special) + + return TRUE + +/// Called after the organ is inserted into a mob. +/// Adds Traits, Actions, and Status Effects on the mob in which the organ is impanted. +/// Override this proc to create unique side-effects for inserting your organ. Must be called by overrides. +/obj/item/organ/proc/on_mob_insert(mob/living/carbon/organ_owner, special = FALSE, movement_flags) + SHOULD_CALL_PARENT(TRUE) + + for(var/trait in organ_traits) + ADD_TRAIT(organ_owner, trait, REF(src)) + + for(var/datum/action/action as anything in actions) + action.Grant(organ_owner) + + for(var/datum/status_effect/effect as anything in organ_effects) + organ_owner.apply_status_effect(effect, type) + + RegisterSignal(owner, COMSIG_ATOM_EXAMINE, PROC_REF(on_owner_examine)) + SEND_SIGNAL(src, COMSIG_ORGAN_IMPLANTED, organ_owner) + SEND_SIGNAL(organ_owner, COMSIG_CARBON_GAIN_ORGAN, src, special) + +/// Insert an organ into a limb, assume the limb as always detached and include no owner operations here (except the get_bodypart helper here I guess) +/// Give EITHER a limb OR a limb owner +/obj/item/organ/proc/bodypart_insert(obj/item/bodypart/bodypart, mob/living/carbon/limb_owner, movement_flags) + SHOULD_CALL_PARENT(TRUE) + + if(limb_owner) + bodypart = limb_owner.get_bodypart(deprecise_zone(zone)) + + // The true movement + forceMove(bodypart) + bodypart.contents |= src + bodypart_owner = bodypart + + RegisterSignal(src, COMSIG_MOVABLE_MOVED, PROC_REF(forced_removal)) + + // Apply unique side-effects. Return value does not matter. + on_bodypart_insert(bodypart) + + return TRUE + +/// Add any limb specific effects you might want here +/obj/item/organ/proc/on_bodypart_insert(obj/item/bodypart/limb, movement_flags) + SHOULD_CALL_PARENT(TRUE) + + item_flags |= ABSTRACT + ADD_TRAIT(src, TRAIT_NODROP, ORGAN_INSIDE_BODY_TRAIT) + +/* + * Remove the organ from the select mob. + * + * * organ_owner - the mob who owns our organ, that we're removing the organ from. Can be null + * * special - "quick swapping" an organ out - when TRUE, the mob will be unaffected by not having that organ for the moment + */ +/obj/item/organ/proc/mob_remove(mob/living/carbon/organ_owner, special = FALSE, movement_flags) + SHOULD_CALL_PARENT(TRUE) + + if(organ_owner) + if(organ_owner.organs_slot[slot] == src) + organ_owner.organs_slot.Remove(slot) + organ_owner.organs -= src + + owner = null + + on_mob_remove(organ_owner, special) + + return TRUE + +/// Called after the organ is removed from a mob. +/// Removes Traits, Actions, and Status Effects on the mob in which the organ was impanted. +/// Override this proc to create unique side-effects for removing your organ. Must be called by overrides. +/obj/item/organ/proc/on_mob_remove(mob/living/carbon/organ_owner, special = FALSE, movement_flags) + SHOULD_CALL_PARENT(TRUE) + + if(!iscarbon(organ_owner)) + stack_trace("Organ removal should not be happening on non carbon mobs: [organ_owner]") + + for(var/trait in organ_traits) + REMOVE_TRAIT(organ_owner, trait, REF(src)) + + for(var/datum/action/action as anything in actions) + action.Remove(organ_owner) + + for(var/datum/status_effect/effect as anything in organ_effects) + organ_owner.remove_status_effect(effect, type) + + UnregisterSignal(organ_owner, COMSIG_ATOM_EXAMINE) + SEND_SIGNAL(src, COMSIG_ORGAN_REMOVED, organ_owner) + SEND_SIGNAL(organ_owner, COMSIG_CARBON_LOSE_ORGAN, src, special) + + var/list/diseases = organ_owner.get_static_viruses() + if(!LAZYLEN(diseases)) + return + + var/list/datum/disease/diseases_to_add = list() + for(var/datum/disease/disease as anything in diseases) + // robotic organs are immune to disease unless 'inorganic biology' symptom is present + if(IS_ROBOTIC_ORGAN(src) && !(disease.infectable_biotypes & MOB_ROBOTIC)) + continue + + // admin or special viruses that should not be reproduced + if(disease.spread_flags & (DISEASE_SPREAD_SPECIAL | DISEASE_SPREAD_NON_CONTAGIOUS)) + continue + + diseases_to_add += disease + + if(LAZYLEN(diseases_to_add)) + AddComponent(/datum/component/infective, diseases_to_add) + +/// Called to remove an organ from a limb. Do not put any mob operations here (except the bodypart_getter at the start) +/// Give EITHER a limb OR a limb_owner +/obj/item/organ/proc/bodypart_remove(obj/item/bodypart/limb, mob/living/carbon/limb_owner, movement_flags) + SHOULD_CALL_PARENT(TRUE) + + if(limb_owner) + limb = limb_owner.get_bodypart(deprecise_zone(zone)) + + UnregisterSignal(src, COMSIG_MOVABLE_MOVED) //DONT MOVE THIS!!!! we moves the organ right after, so we unregister before we move them physically + + // The true movement is here + moveToNullspace() + bodypart_owner.contents -= src + bodypart_owner = null + + on_bodypart_remove(limb) + + return TRUE + +/// Called on limb removal to remove limb specific limb effects or statusses +/obj/item/organ/proc/on_bodypart_remove(obj/item/bodypart/limb, movement_flags) + SHOULD_CALL_PARENT(TRUE) + + if(!IS_ROBOTIC_ORGAN(src) && !(item_flags & NO_BLOOD_ON_ITEM) && !QDELING(src)) + AddElement(/datum/element/decal/blood) + + item_flags &= ~ABSTRACT + REMOVE_TRAIT(src, TRAIT_NODROP, ORGAN_INSIDE_BODY_TRAIT) + +/// In space station videogame, nothing is sacred. If somehow an organ is removed unexpectedly, handle it properly +/obj/item/organ/proc/forced_removal() + SIGNAL_HANDLER + + if(owner) + Remove(owner) + else if(bodypart_owner) + bodypart_remove(limb_owner = owner) + else + stack_trace("Force removed an already removed organ!") + +/** + * Proc that gets called when the organ is surgically removed by someone, can be used for special effects + * Currently only used so surplus organs can explode when surgically removed. + */ +/obj/item/organ/proc/on_surgical_removal(mob/living/user, mob/living/carbon/old_owner, target_zone, obj/item/tool) + SHOULD_CALL_PARENT(TRUE) + SEND_SIGNAL(src, COMSIG_ORGAN_SURGICALLY_REMOVED, user, old_owner, target_zone, tool) + RemoveElement(/datum/element/decal/blood) diff --git a/code/modules/unit_tests/_unit_tests.dm b/code/modules/unit_tests/_unit_tests.dm index 2bce0963b70..61bc9ec6d4e 100644 --- a/code/modules/unit_tests/_unit_tests.dm +++ b/code/modules/unit_tests/_unit_tests.dm @@ -195,6 +195,7 @@ #include "objectives.dm" #include "operating_table.dm" #include "orderable_items.dm" +#include "organ_bodypart_shuffle.dm" #include "organ_set_bonus.dm" #include "organs.dm" #include "outfit_sanity.dm" diff --git a/code/modules/unit_tests/heretic_rituals.dm b/code/modules/unit_tests/heretic_rituals.dm index 4ac5bce8d3d..b55136cface 100644 --- a/code/modules/unit_tests/heretic_rituals.dm +++ b/code/modules/unit_tests/heretic_rituals.dm @@ -66,7 +66,10 @@ if(islist(ritual_item_path)) ritual_item_path = pick(ritual_item_path) for(var/i in 1 to amount_to_create) - created_atoms += new ritual_item_path(get_turf(our_heretic)) + var/obj/item/item = new ritual_item_path(get_turf(our_heretic)) + if(isitem(item)) + item.item_flags &= ~ABSTRACT + created_atoms += item // Now, we can ACTUALLY run the ritual. Let's do it. // Attempt to run the knowledge via the sacrifice rune. @@ -106,6 +109,10 @@ for(var/atom/thing as anything in nearby_atoms) if(!ismovable(thing)) continue + if(isitem(thing)) + var/obj/item/item = thing + if(item.item_flags & ABSTRACT) //bodyparts and stuff will get registered otherwise + continue // There are atoms around the rune still, and there shouldn't be. // All component atoms were consumed, and all resulting atoms were cleaned up. diff --git a/code/modules/unit_tests/human_through_recycler.dm b/code/modules/unit_tests/human_through_recycler.dm index 7d554d72690..c51b9a0e30b 100644 --- a/code/modules/unit_tests/human_through_recycler.dm +++ b/code/modules/unit_tests/human_through_recycler.dm @@ -17,8 +17,13 @@ TEST_ASSERT_EQUAL(damage_incurred, chewer.crush_damage, "Assistant did not take the expected amount of brute damage ([chewer.crush_damage]) from the emagged recycler! Took ([damage_incurred]) instead.") TEST_ASSERT(chewer.bloody, "The emagged recycler did not become bloody after crushing the assistant!") + var/list/bad_contents = assistant.contents + for(var/obj/item/item in assistant.contents) + if(item.item_flags & ABSTRACT) + bad_contents -= item + // Now, let's test to see if all of their clothing got properly deleted. - TEST_ASSERT_EQUAL(length(assistant.contents), 0, "Assistant still has items in its contents after being put through an emagged recycler!") + TEST_ASSERT_EQUAL(length(bad_contents), 0, "Assistant still has items in its contents after being put through an emagged recycler!") // Consistent Assistants will always have the following: ID, PDA, backpack, a uniform, a headset, and a pair of shoes. If any of these are still present, then the recycler did not properly delete the assistant's clothing. // However, let's check for EVERYTHING just in case, because we don't want to miss anything. // This is just what we expect to be deleted. diff --git a/code/modules/unit_tests/ling_decap.dm b/code/modules/unit_tests/ling_decap.dm index 0c964f9a043..5d6f01caf9a 100644 --- a/code/modules/unit_tests/ling_decap.dm +++ b/code/modules/unit_tests/ling_decap.dm @@ -9,7 +9,7 @@ var/obj/item/bodypart/head/noggin = ling.get_bodypart(BODY_ZONE_HEAD) noggin.dismember() TEST_ASSERT_NULL(ling.get_bodypart(BODY_ZONE_HEAD), "Changeling failed to be decapitated.") - TEST_ASSERT_NULL(noggin.brainmob.mind, "Changeling's mind was moved to their head after decapitation, but it should have remained in their body.") + TEST_ASSERT_NULL(noggin.brain.brainmob.mind, "Changeling's mind was moved to their brain after decapitation, but it should have remained in their body.") var/obj/item/organ/internal/brain/oldbrain = noggin.brain noggin.drop_organs() @@ -33,7 +33,7 @@ var/obj/item/bodypart/head/noggin = normal_guy.get_bodypart(BODY_ZONE_HEAD) noggin.dismember() - TEST_ASSERT_EQUAL(noggin.brainmob.mind, my_guys_mind, "Dummy's mind was not moved to their head after decapitation.") + TEST_ASSERT_EQUAL(noggin.brain.brainmob.mind, my_guys_mind, "Dummy's mind was not moved to their brain after decapitation.") var/obj/item/organ/internal/brain/oldbrain = noggin.brain noggin.drop_organs() diff --git a/code/modules/unit_tests/organ_bodypart_shuffle.dm b/code/modules/unit_tests/organ_bodypart_shuffle.dm new file mode 100644 index 00000000000..842dd1c6c13 --- /dev/null +++ b/code/modules/unit_tests/organ_bodypart_shuffle.dm @@ -0,0 +1,34 @@ +/// Moves organs in and out of bodyparts, and moves the bodyparts around to see if someone didn't fuck up their movement +/datum/unit_test/organ_bodypart_shuffle + +/datum/unit_test/organ_bodypart_shuffle/Run() + var/mob/living/carbon/human/hollow_boy = allocate(/mob/living/carbon/human/consistent) + + // Test if organs are all properly updating when forcefully removed + var/list/removed_organs = list() + + for(var/obj/item/organ/organ as anything in hollow_boy.organs) + organ.moveToNullspace() + removed_organs += organ + + for(var/obj/item/organ/organ as anything in removed_organs) + TEST_ASSERT(!(organ in hollow_boy.organs), "Organ '[organ.name] remained inside human after forceMove into nullspace.") + TEST_ASSERT(organ.loc == null, "Organ '[organ.name] did not move to nullspace after being forced to.") + TEST_ASSERT(!(organ.owner), "Organ '[organ.name] kept reference to human after forceMove into nullspace.") + TEST_ASSERT(!(organ.bodypart_owner), "Organ '[organ.name] kept reference to bodypart after forceMove into nullspace.") + + for(var/obj/item/bodypart/bodypart as anything in hollow_boy.bodyparts) + bodypart = new bodypart.type() //fresh, duplice bodypart with no insides + for(var/obj/item/organ/organ as anything in removed_organs) + if(bodypart.body_zone != deprecise_zone(organ.zone)) + continue + organ.bodypart_insert(bodypart) // Put all the old organs back in + bodypart.replace_limb(hollow_boy) //so stick new bodyparts on them with their old organs + // Check if, after we put the old organs in a new limb, and after we put that new limb on the mob, if the organs came with + for(var/obj/item/organ/organ as anything in removed_organs) //technically readded organ now + if(bodypart.body_zone != deprecise_zone(organ.zone)) + continue + TEST_ASSERT(organ in hollow_boy.organs, "Organ '[organ.name] was put in an empty bodypart that replaced a humans, but the organ did not come with.") + + // Test if bodyparts are all properly updating when forcefully removed + hollow_boy = allocate(/mob/living/carbon/human/consistent) //freshly filled with wet insides diff --git a/code/modules/unit_tests/organ_set_bonus.dm b/code/modules/unit_tests/organ_set_bonus.dm index 250433028c1..a9e9a8805f9 100644 --- a/code/modules/unit_tests/organ_set_bonus.dm +++ b/code/modules/unit_tests/organ_set_bonus.dm @@ -30,7 +30,7 @@ // Attempt to insert entire list of mutant organs for the given infusion_entry. for(var/obj/item/organ/organ as anything in output_organs) organ = new organ() - TEST_ASSERT(organ.Insert(lab_rat, special = TRUE, drop_if_replaced = FALSE), "The organ `[organ.type]` for `[infuser_entry.type]` was not inserted in the mob when expected, Insert() returned falsy when TRUE was expected.") + TEST_ASSERT(organ.Insert(lab_rat, special = TRUE, movement_flags = DELETE_IF_REPLACED), "The organ `[organ.type]` for `[infuser_entry.type]` was not inserted in the mob when expected, Insert() returned falsy when TRUE was expected.") inserted_organs += organ // Search for added Status Effect. diff --git a/code/modules/unit_tests/organs.dm b/code/modules/unit_tests/organs.dm index 4ba51e0870c..1da3808ba39 100644 --- a/code/modules/unit_tests/organs.dm +++ b/code/modules/unit_tests/organs.dm @@ -25,14 +25,10 @@ )) /datum/unit_test/organ_sanity/Run() - for(var/obj/item/organ/organ_type as anything in subtypesof(/obj/item/organ)) + for(var/obj/item/organ/organ_type as anything in subtypesof(/obj/item/organ) - test_organ_blacklist) organ_test_insert(organ_type) /datum/unit_test/organ_sanity/proc/organ_test_insert(obj/item/organ/organ_type) - // Skip prototypes. - if(test_organ_blacklist[organ_type]) - return - // Appropriate mob (Human) which will receive organ. var/mob/living/carbon/human/lab_rat = allocate(/mob/living/carbon/human/consistent) var/obj/item/organ/test_organ = new organ_type() @@ -41,8 +37,8 @@ var/mob/living/basic/pet/dog/lab_dog = allocate(/mob/living/basic/pet/dog/corgi) var/obj/item/organ/reject_organ = new organ_type() - TEST_ASSERT(test_organ.Insert(lab_rat, special = TRUE, drop_if_replaced = FALSE), TEST_ORGAN_INSERT_MESSAGE(test_organ, "should return TRUE to indicate success.")) - TEST_ASSERT(!reject_organ.Insert(lab_dog, special = TRUE, drop_if_replaced = FALSE), TEST_ORGAN_INSERT_MESSAGE(test_organ, "shouldn't return TRUE when inserting into a basic mob (Corgi).")) + TEST_ASSERT(test_organ.Insert(lab_rat, special = TRUE, movement_flags = DELETE_IF_REPLACED), TEST_ORGAN_INSERT_MESSAGE(test_organ, "should return TRUE to indicate success.")) + TEST_ASSERT(!reject_organ.Insert(lab_dog, special = TRUE, movement_flags = DELETE_IF_REPLACED), TEST_ORGAN_INSERT_MESSAGE(test_organ, "shouldn't return TRUE when inserting into a basic mob (Corgi).")) // Species change swaps out all the organs, making test_organ un-usable by this point. if(species_changing_organs[test_organ.type]) diff --git a/code/modules/unit_tests/species_change_organs.dm b/code/modules/unit_tests/species_change_organs.dm index e0555aa89bc..41d55047f03 100644 --- a/code/modules/unit_tests/species_change_organs.dm +++ b/code/modules/unit_tests/species_change_organs.dm @@ -12,7 +12,7 @@ dummy.gain_trauma(/datum/brain_trauma/severe/blindness) // Give a cyber heart var/obj/item/organ/internal/heart/cybernetic/cyber_heart = allocate(/obj/item/organ/internal/heart/cybernetic) - cyber_heart.Insert(dummy, special = TRUE, drop_if_replaced = FALSE) + cyber_heart.Insert(dummy, special = TRUE, movement_flags = DELETE_IF_REPLACED) // Give one of their organs a bit of damage var/obj/item/organ/internal/appendix/existing_appendix = dummy.get_organ_slot(ORGAN_SLOT_APPENDIX) existing_appendix.set_organ_damage(25) diff --git a/code/modules/unit_tests/tail_wag.dm b/code/modules/unit_tests/tail_wag.dm index 0d828557953..ceb82e98c0d 100644 --- a/code/modules/unit_tests/tail_wag.dm +++ b/code/modules/unit_tests/tail_wag.dm @@ -6,7 +6,7 @@ /datum/unit_test/tail_wag/Run() var/mob/living/carbon/human/dummy = allocate(/mob/living/carbon/human/consistent) var/obj/item/organ/external/tail/cat/dummy_tail = allocate(/obj/item/organ/external/tail/cat) - dummy_tail.Insert(dummy, special = TRUE, drop_if_replaced = FALSE) + dummy_tail.Insert(dummy, special = TRUE, movement_flags = DELETE_IF_REPLACED) // SANITY TEST @@ -74,7 +74,7 @@ // TESTING MOB DEATH // put it back and start wagging again - dummy_tail.Insert(dummy, special = TRUE, drop_if_replaced = FALSE) + dummy_tail.Insert(dummy, special = TRUE, movement_flags = DELETE_IF_REPLACED) SEND_SIGNAL(dummy, COMSIG_ORGAN_WAG_TAIL, TRUE) if(!(dummy_tail.wag_flags & WAG_WAGGING)) TEST_FAIL("Tail did not start wagging when it should have!") diff --git a/code/modules/wiremod/shell/brain_computer_interface.dm b/code/modules/wiremod/shell/brain_computer_interface.dm index c3ac3154d2d..1d71bfa0c25 100644 --- a/code/modules/wiremod/shell/brain_computer_interface.dm +++ b/code/modules/wiremod/shell/brain_computer_interface.dm @@ -17,11 +17,6 @@ new /obj/item/circuit_component/bci_core, ), SHELL_CAPACITY_SMALL, starting_circuit = circuit) -/obj/item/organ/internal/cyberimp/bci/on_insert(mob/living/carbon/receiver) - . = ..() - // Organs are put in nullspace, but this breaks circuit interactions - forceMove(receiver) - /obj/item/organ/internal/cyberimp/bci/say(message, bubble_type, list/spans, sanitize, datum/language/language, ignore_spam, forced = null, filterproof = null, message_range = 7, datum/saymode/saymode = null) if (owner) // Otherwise say_dead will be called. diff --git a/code/modules/zombie/organs.dm b/code/modules/zombie/organs.dm index 94ace7e6c7f..73149fc8d76 100644 --- a/code/modules/zombie/organs.dm +++ b/code/modules/zombie/organs.dm @@ -23,25 +23,25 @@ GLOB.zombie_infection_list -= src . = ..() -/obj/item/organ/internal/zombie_infection/Insert(mob/living/carbon/M, special = FALSE, drop_if_replaced = TRUE) +/obj/item/organ/internal/zombie_infection/on_mob_insert(mob/living/carbon/M, special = FALSE, movement_flags) . = ..() if(!.) return . START_PROCESSING(SSobj, src) -/obj/item/organ/internal/zombie_infection/Remove(mob/living/carbon/M, special = FALSE) +/obj/item/organ/internal/zombie_infection/on_mob_remove(mob/living/carbon/M, special = FALSE) . = ..() STOP_PROCESSING(SSobj, src) - if(iszombie(M) && old_species && !special && !QDELETED(src)) + if(iszombie(M) && old_species && !special) M.set_species(old_species) if(timer_id) deltimer(timer_id) -/obj/item/organ/internal/zombie_infection/on_insert(mob/living/carbon/organ_owner, special) +/obj/item/organ/internal/zombie_infection/on_mob_insert(mob/living/carbon/organ_owner, special) . = ..() RegisterSignal(organ_owner, COMSIG_LIVING_DEATH, PROC_REF(organ_owner_died)) -/obj/item/organ/internal/zombie_infection/on_remove(mob/living/carbon/organ_owner, special) +/obj/item/organ/internal/zombie_infection/on_mob_remove(mob/living/carbon/organ_owner, special) . = ..() UnregisterSignal(organ_owner, COMSIG_LIVING_DEATH) diff --git a/tgstation.dme b/tgstation.dme index a40e405951a..c4a89286782 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -159,6 +159,7 @@ #include "code\__DEFINES\nuclear_bomb.dm" #include "code\__DEFINES\obj_flags.dm" #include "code\__DEFINES\observers.dm" +#include "code\__DEFINES\organ_movement.dm" #include "code\__DEFINES\overlays.dm" #include "code\__DEFINES\pai.dm" #include "code\__DEFINES\paintings.dm" @@ -5670,6 +5671,7 @@ #include "code\modules\surgery\organs\_organ.dm" #include "code\modules\surgery\organs\autosurgeon.dm" #include "code\modules\surgery\organs\helpers.dm" +#include "code\modules\surgery\organs\organ_movement.dm" #include "code\modules\surgery\organs\external\_external_organ.dm" #include "code\modules\surgery\organs\external\restyling.dm" #include "code\modules\surgery\organs\external\spines.dm"