From 237f8e0c873e0f51f3af76cea15debe573843691 Mon Sep 17 00:00:00 2001 From: Bloop <13398309+vinylspiders@users.noreply.github.com> Date: Tue, 9 Jan 2024 07:49:38 -0500 Subject: [PATCH] Organ movement refactor *Un-nullspaces your organs* [MDB IGNORE] #25530 (#42) * Organ movement refactor *Un-nullspaces your organs* * Fix conflicts I checked the conflicts on the two weird conflicts and no previous TG pr touches them i assume its just github being github because those shoulden't be conflicts *shrug * Fix #1 uhh...this is going to be a long one * Fix #2 Modular Movement Flags * Fix #3 It builds now * Fix #4 Oh god it builds now, I missed some things * Fix #5 No more Runtimesplosion Now time for Synths * Fix #6 Shut up CI Where did you even come from * Fix #7 Didn't I fix you already? * Update language.dm * Fix Opfor jank * Revert "Fix Opfor jank" This reverts commit 6af2fd71d85e6be58890f27f4f32bf92cfcb00fb. * Revert "Revert "Fix Opfor jank"" This reverts commit cbd72277afd05f30a0b6f499a8162412fe3663ea. * Update module_template.md * Revert "Revert "Revert "Fix Opfor jank""" This reverts commit 71ae4c10d8e9876c97f67278c55caa994b26a7dc. * Fixing a runtime with H.A.R.S. (#80772) The brain gets moved into the chest with H.A.R.S. now, but the bodypart insertion and removal procs for it still asume it can only be found in the head. This should fix it. For the sake of preventing similar issues in the future, I've also updated the pretty-much-identical versions for ears, eyes and tongue. I've checked, and the brain var is only used by the head for visuals and examine strings. * Modular updates * Fix synths not dying after being debrained * Update brain.dm * Update cortical_borer.dm * Revert "Fixing a runtime with H.A.R.S. (#80772)" This reverts commit 225035c2101d0e8946f7ef8cb375b68f2d25533a. * Update dismemberment.dm --------- Co-authored-by: Time-Green <7501474+Time-Green@users.noreply.github.com> Co-authored-by: SomeRandomOwl Co-authored-by: SomeRandomOwl <2568378+SomeRandomOwl@users.noreply.github.com> Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com> --- code/__DEFINES/organ_movement.dm | 4 + code/__DEFINES/traits/sources.dm | 2 + code/__HELPERS/mobs.dm | 5 - code/datums/ai/generic/generic_behaviors.dm | 4 + .../mutant_bodypart_overlay.dm | 18 +- code/datums/components/crafting/crafting.dm | 4 + code/datums/diseases/gastrolisis.dm | 2 +- code/datums/dna.dm | 1 - code/datums/mutations/body.dm | 4 +- code/datums/quirks/negative_quirks/junkie.dm | 2 +- .../negative_quirks/prosthetic_organ.dm | 2 +- code/datums/quirks/negative_quirks/tin_man.dm | 2 +- code/datums/station_traits/positive_traits.dm | 2 +- code/datums/status_effects/neutral.dm | 2 +- .../dna_infuser/organ_sets/carp_organs.dm | 23 +- .../dna_infuser/organ_sets/fox_organs.dm | 4 +- .../dna_infuser/organ_sets/goliath_organs.dm | 4 +- .../dna_infuser/organ_sets/gondola_organs.dm | 12 +- .../dna_infuser/organ_sets/rat_organs.dm | 8 +- .../dna_infuser/organ_sets/roach_organs.dm | 23 +- code/game/machinery/recycler.dm | 4 + code/game/objects/items/body_egg.dm | 4 +- code/game/turfs/open/lava.dm | 2 +- code/modules/admin/verbs/admin.dm | 4 + code/modules/admin/verbs/secrets.dm | 4 +- .../antagonists/abductor/equipment/gland.dm | 4 +- .../abductor/equipment/glands/electric.dm | 4 +- .../abductor/equipment/glands/slime.dm | 4 +- .../antagonists/fugitive/fugitive_outfits.dm | 2 +- .../heretic/knowledge/lock_lore.dm | 3 +- .../antagonists/heretic/transmutation_rune.dm | 4 + .../antagonists/nightmare/nightmare_organs.dm | 8 +- code/modules/client/preferences/language.dm | 2 +- .../chaplain/chaplain_vorpal_scythe.dm | 2 +- .../library/skill_learning/skillchip.dm | 2 +- .../equipment/monster_organs/monster_organ.dm | 4 +- .../equipment/monster_organs/rush_gland.dm | 4 +- .../living/basic/lavaland/legion/legion.dm | 2 +- .../basic/lavaland/legion/legion_tumour.dm | 2 +- .../basic/space_fauna/demon/demon_items.dm | 4 +- code/modules/mob/living/blood.dm | 2 +- code/modules/mob/living/brain/brain_item.dm | 48 ++-- .../modules/mob/living/carbon/alien/organs.dm | 18 +- code/modules/mob/living/carbon/carbon.dm | 23 +- code/modules/mob/living/carbon/death.dm | 6 +- .../mob/living/carbon/human/_species.dm | 16 +- .../mob/living/carbon/human/human_defines.dm | 1 + .../carbon/human/species_types/felinid.dm | 12 +- .../carbon/human/species_types/monkeys.dm | 4 +- .../carbon/human/species_types/vampire.dm | 4 +- .../mob_spawn/corpses/mining_corpses.dm | 2 +- code/modules/religion/burdened/psyker.dm | 8 +- .../spells/spell_types/self/summonitem.dm | 12 +- code/modules/surgery/bodyparts/_bodyparts.dm | 213 ++++++++-------- .../surgery/bodyparts/dismemberment.dm | 106 +++----- code/modules/surgery/bodyparts/head.dm | 55 +---- .../surgery/bodyparts/head_hair_and_lips.dm | 4 +- code/modules/surgery/bodyparts/helpers.dm | 3 +- code/modules/surgery/bodyparts/parts.dm | 205 +++++++++------- .../bodyparts/species_parts/misc_bodyparts.dm | 30 ++- code/modules/surgery/organs/_organ.dm | 151 +----------- .../organs/external/_external_organ.dm | 82 ++----- .../surgery/organs/external/restyling.dm | 2 +- .../modules/surgery/organs/external/spines.dm | 4 +- code/modules/surgery/organs/external/tails.dm | 17 +- .../organs/external/wings/functional_wings.dm | 4 +- .../organs/external/wings/moth_wings.dm | 4 +- .../organs/internal/_internal_organ.dm | 25 +- .../organs/internal/appendix/_appendix.dm | 4 +- .../internal/appendix/appendix_golem.dm | 4 +- .../organs/internal/cyberimp/augments_arms.dm | 14 +- .../internal/cyberimp/augments_chest.dm | 2 +- .../organs/internal/cyberimp/augments_eyes.dm | 4 +- .../internal/cyberimp/augments_internal.dm | 6 +- .../surgery/organs/internal/ears/_ears.dm | 16 +- .../surgery/organs/internal/eyes/_eyes.dm | 25 +- .../surgery/organs/internal/heart/_heart.dm | 8 +- .../organs/internal/heart/heart_ethereal.dm | 4 +- .../surgery/organs/internal/liver/_liver.dm | 8 +- .../surgery/organs/internal/lungs/_lungs.dm | 4 +- .../organs/internal/stomach/_stomach.dm | 6 +- .../internal/stomach/stomach_ethereal.dm | 4 +- .../organs/internal/stomach/stomach_golem.dm | 4 +- .../surgery/organs/internal/tongue/_tongue.dm | 4 +- code/modules/surgery/organs/organ_movement.dm | 230 ++++++++++++++++++ code/modules/unit_tests/_unit_tests.dm | 1 + code/modules/unit_tests/heretic_rituals.dm | 9 +- .../unit_tests/human_through_recycler.dm | 7 +- code/modules/unit_tests/ling_decap.dm | 4 +- .../unit_tests/organ_bodypart_shuffle.dm | 34 +++ code/modules/unit_tests/organ_set_bonus.dm | 2 +- code/modules/unit_tests/organs.dm | 10 +- .../unit_tests/species_change_organs.dm | 2 +- code/modules/unit_tests/tail_wag.dm | 4 +- .../wiremod/shell/brain_computer_interface.dm | 5 - code/modules/zombie/organs.dm | 10 +- .../datums/quirks/neutral_quirks/lungs.dm | 2 +- .../code/datums/traits/neutral.dm | 4 +- .../code/modules/client/preferences/brain.dm | 2 +- .../cortical_borer/code/cortical_borer.dm | 4 +- .../evolution_things/empowered_egg.dm | 2 +- .../modules/client/augment/limbs.dm | 2 - .../modules/client/augment/organs.dm | 2 +- .../new_player/sprite_accessories/snout.dm | 2 +- .../mob/living/carbon/human/species.dm | 2 +- .../mob/living/carbon/human/species/ghoul.dm | 12 +- .../species/hemophage/hemophage_tumor.dm | 2 +- .../carbon/human/species/roundstartslime.dm | 2 +- .../modules/surgery/organs/genitals.dm | 2 +- .../modules/surgery/organs/organ.dm | 10 +- .../modules/surgery/organs/tails.dm | 2 +- .../modules/surgery/organs/taur_body.dm | 2 +- .../modules/modular_implants/code/nifs.dm | 2 +- modular_nova/modules/organs/code/heart.dm | 4 +- modular_nova/modules/organs/code/tongue.dm | 4 +- .../modules/synths/code/bodyparts/brain.dm | 10 +- .../modules/synths/code/bodyparts/stomach.dm | 2 +- tgstation.dme | 2 + 118 files changed, 933 insertions(+), 838 deletions(-) create mode 100644 code/__DEFINES/organ_movement.dm create mode 100644 code/modules/surgery/organs/organ_movement.dm create mode 100644 code/modules/unit_tests/organ_bodypart_shuffle.dm 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 19a062bb156..c35c591bc7c 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -707,11 +707,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 b769bc529e2..43e37f66e8c 100644 --- a/code/datums/ai/generic/generic_behaviors.dm +++ b/code/datums/ai/generic/generic_behaviors.dm @@ -360,6 +360,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 f2b82e7a2c8..d64a4e3b57f 100644 --- a/code/datums/bodypart_overlays/mutant_bodypart_overlay.dm +++ b/code/datums/bodypart_overlays/mutant_bodypart_overlay.dm @@ -93,26 +93,26 @@ 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 - alpha = 255 // NOVA EDIT - Mutant bodyparts transparency are based on limb transparency + alpha = 255 // NOVA EDIT ADDITION - Mutant bodyparts transparency are based on limb transparency return TRUE if(draw_color && !force) return FALSE - alpha = ownerlimb.alpha // NOVA EDIT - Mutant bodyparts transparency are based on limb transparency + alpha = bodypart_owner.alpha // NOVA EDIT ADDITION - Mutant bodyparts transparency are based on limb transparency 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 e16ab582b77..832ad22698b 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 0eb811cc8bd..120c69bca1d 100644 --- a/code/datums/dna.dm +++ b/code/datums/dna.dm @@ -604,7 +604,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 92859902137..798628bd040 100644 --- a/code/datums/mutations/body.dm +++ b/code/datums/mutations/body.dm @@ -524,14 +524,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 a1e88288877..e6d411bc772 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 7b3ed0a0b15..c652c55400a 100644 --- a/code/datums/station_traits/positive_traits.dm +++ b/code/datums/station_traits/positive_traits.dm @@ -272,7 +272,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 cb5347c8a51..58494346f62 100644 --- a/code/game/machinery/dna_infuser/organ_sets/fox_organs.dm +++ b/code/game/machinery/dna_infuser/organ_sets/fox_organs.dm @@ -8,7 +8,7 @@ //NOVA EDIT REMOVAL BEGIN - CUSTOMIZATION /* -/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 @@ -16,7 +16,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 f2f5b1b0fec..a4deb63ae21 100644 --- a/code/game/machinery/recycler.dm +++ b/code/game/machinery/recycler.dm @@ -157,6 +157,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 7c7c321f0e2..1a174723d85 100644 --- a/code/game/turfs/open/lava.dm +++ b/code/game/turfs/open/lava.dm @@ -420,7 +420,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 d97ad84273e..838f04995b5 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 d49c7715462..f9879428ddf 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 cf425563c13..fdd7dbbe5fe 100644 --- a/code/modules/antagonists/heretic/knowledge/lock_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/lock_lore.dm @@ -203,8 +203,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 31c252eacf1..2479ec715e0 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 50bfd8e1619..c06f1e322a2 100644 --- a/code/modules/antagonists/nightmare/nightmare_organs.dm +++ b/code/modules/antagonists/nightmare/nightmare_organs.dm @@ -15,7 +15,7 @@ ///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) . = ..() if(brain_owner.dna.species.id != SPECIES_NIGHTMARE) @@ -29,7 +29,7 @@ terrorize_spell = new(src) terrorize_spell.Grant(brain_owner) -/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) @@ -91,13 +91,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/client/preferences/language.dm b/code/modules/client/preferences/language.dm index d26f9a15ffb..7e8e6cb7113 100644 --- a/code/modules/client/preferences/language.dm +++ b/code/modules/client/preferences/language.dm @@ -20,7 +20,7 @@ //we add uncommon as it's foreigner-only. var/datum/language/uncommon/uncommon_language = /datum/language/uncommon values += initial(uncommon_language.name) - values += /datum/language/common::name // NOVA EDIT ADDITION START - Let's you select common + values += /datum/language/common::name // NOVA EDIT ADDITION START - Lets you select common for(var/datum/language/language_type as anything in GLOB.uncommon_roundstart_languages) if(initial(language_type.name) in values) 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 6832e3d66d4..74b1cdcf627 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 61d795c764a..d8e4bfae986 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 ab870461965..a613e2ad839 100644 --- a/code/modules/mob/living/brain/brain_item.dm +++ b/code/modules/mob/living/brain/brain_item.dm @@ -46,7 +46,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 @@ -54,7 +61,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) @@ -101,25 +108,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. @@ -132,10 +125,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)]" @@ -416,11 +410,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) @@ -579,6 +573,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 fb4828e457f..65a40a08805 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -1007,7 +1007,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 @@ -1024,8 +1023,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) @@ -1040,10 +1043,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) @@ -1449,3 +1459,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 7c41119b0c2..0de67ef055d 100644 --- a/code/modules/mob/living/carbon/human/_species.dm +++ b/code/modules/mob/living/carbon/human/_species.dm @@ -375,19 +375,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) @@ -430,7 +428,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()) @@ -497,7 +495,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 d2f3576b6a9..5dffbcd26c0 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 maxHealth = HUMAN_MAXHEALTH //NOVA EDIT ADDITION health = HUMAN_MAXHEALTH //NOVA EDIT ADDITION 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 1db30b11dbe..2ec02dee2b4 100644 --- a/code/modules/mob/living/carbon/human/species_types/felinid.dm +++ b/code/modules/mob/living/carbon/human/species_types/felinid.dm @@ -43,7 +43,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 ..() @@ -95,8 +95,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) @@ -119,16 +119,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 00003a5240b..3c176ff4388 100644 --- a/code/modules/mob/living/carbon/human/species_types/monkeys.dm +++ b/code/modules/mob/living/carbon/human/species_types/monkeys.dm @@ -167,11 +167,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_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 5e9b0f0327b..f43e33aa25a 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 fdeb50114a3..e51d083ddc4 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) @@ -407,31 +414,24 @@ 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) - - 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) + QDEL_NULL(current_gauze) - if(!owner) - return FALSE + 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)) - 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 + if(drop_loc) //can be null during deletion + for(var/atom/movable/movable as anything in src) + movable.forceMove(drop_loc) - return bodypart_organs + update_icon_dropped() //Return TRUE to get whatever mob this is in to update health. /obj/item/bodypart/proc/on_life(seconds_per_tick, times_fired) @@ -760,70 +760,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) - 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)) + SEND_SIGNAL(src, COMSIG_BODYPART_CHANGED_OWNER, new_owner, owner) + + if(owner) + . = 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 34afbd625a6..08d8d018161 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) // NOVA EDIT START - Non-spillable organs if(!organ.drop_when_organ_spilling) continue @@ -79,21 +79,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() @@ -102,16 +94,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) @@ -135,27 +124,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) /** @@ -205,48 +189,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) +/obj/item/organ/internal/eyes/on_bodypart_insert(obj/item/bodypart/head/head) + head.eyes = src + ..() -///Adds the organ to a bodypart, used in transfer_to_limb() -/obj/item/organ/proc/add_to_limb(obj/item/bodypart/bodypart) - forceMove(bodypart) +/obj/item/organ/internal/ears/on_bodypart_insert(obj/item/bodypart/head/head) + head.ears = src + ..() -///Removes the organ from the limb, placing it into nullspace. -/obj/item/organ/proc/remove_from_limb() - moveToNullspace() +/obj/item/organ/internal/tongue/on_bodypart_insert(obj/item/bodypart/head/head) + head.tongue = src + ..() -/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) +/obj/item/organ/internal/brain/on_bodypart_insert(obj/item/bodypart/head/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) - head.eyes = src +/obj/item/organ/internal/eyes/on_bodypart_remove(obj/item/bodypart/head/head) + head.eyes = null ..() -/obj/item/organ/internal/ears/transfer_to_limb(obj/item/bodypart/head/head, mob/living/carbon/human/head_owner) - head.ears = src +/obj/item/organ/internal/ears/on_bodypart_remove(obj/item/bodypart/head/head) + head.ears = null ..() -/obj/item/organ/internal/tongue/transfer_to_limb(obj/item/bodypart/head/head, mob/living/carbon/human/head_owner) - head.tongue = src +/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) +/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) @@ -269,7 +250,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 @@ -280,7 +261,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)) @@ -336,8 +317,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) @@ -350,8 +329,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 @@ -391,15 +372,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 8d4d48bfe6c..e6e805664d3 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/head_hair_and_lips.dm b/code/modules/surgery/bodyparts/head_hair_and_lips.dm index 15d4db296ee..4b23b9cc256 100644 --- a/code/modules/surgery/bodyparts/head_hair_and_lips.dm +++ b/code/modules/surgery/bodyparts/head_hair_and_lips.dm @@ -39,7 +39,7 @@ //HIDDEN CHECKS END if(owner) - if(!hair_hidden && !owner.get_organ_slot(ORGAN_SLOT_BRAIN) && !HAS_TRAIT(owner, TRAIT_NO_DEBRAIN_OVERLAY)) + if(!hair_hidden && !owner.get_organ_slot(ORGAN_SLOT_BRAIN) && !HAS_TRAIT(owner, TRAIT_NO_DEBRAIN_OVERLAY) && !istype(src, /obj/item/bodypart/head/robot/synth)) // NOVA EDIT CHANGE - ORIGINAL: if(!hair_hidden && !owner.get_organ_slot(ORGAN_SLOT_BRAIN) && !HAS_TRAIT(owner, TRAIT_NO_DEBRAIN_OVERLAY)) show_debrained = TRUE else show_debrained = FALSE @@ -49,7 +49,7 @@ else show_eyeless = FALSE else - if(!hair_hidden && !brain) + if(!hair_hidden && !brain && !istype(src, /obj/item/bodypart/head/robot/synth)) // NOVA EDIT CHANGE - ORIGINAL: if(!hair_hidden && !brain) show_debrained = TRUE else show_debrained = FALSE 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/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/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/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)) - - -///Proc to react to the owner gaining the TRAIT_PARALYSIS_L_LEG trait. +/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_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 574ab49987b..7f514ecdaf4 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 dcc713a0991..5b9f9d67347 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 @@ -59,23 +57,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(!.) @@ -91,54 +76,28 @@ // NOVA EDIT CHANGE END 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() + return ..() +/obj/item/organ/external/on_bodypart_insert(obj/item/bodypart/bodypart) + bodypart.add_bodypart_overlay(bodypart_overlay) + return ..() -/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() +/obj/item/organ/external/on_bodypart_remove(obj/item/bodypart/bodypart) + bodypart.remove_bodypart_overlay(bodypart_overlay) - 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 ..() + if(use_mob_sprite_as_obj_sprite) + update_appearance(UPDATE_OVERLAYS) -/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 + 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) @@ -172,8 +131,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) @@ -188,7 +147,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 @@ -294,16 +253,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 600ed619e68..86bc8c800a1 100644 --- a/code/modules/surgery/organs/external/spines.dm +++ b/code/modules/surgery/organs/external/spines.dm @@ -16,13 +16,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 a3105b81b4a..5c620eea161 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) @@ -141,13 +138,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/reciever, 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 58b9a709d87..d1f1eff6fc1 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 88c1d5670fb..db1a14ca05d 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 ecab1c93da9..9f67fb3d899 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 94a4aba90b3..463e34977ee 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) @@ -379,14 +379,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 d97df1d043b..513f0794c31 100644 --- a/code/modules/surgery/organs/internal/cyberimp/augments_chest.dm +++ b/code/modules/surgery/organs/internal/cyberimp/augments_chest.dm @@ -181,7 +181,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 b864e0f5b67..d0255d5a060 100644 --- a/code/modules/surgery/organs/internal/ears/_ears.dm +++ b/code/modules/surgery/organs/internal/ears/_ears.dm @@ -70,7 +70,7 @@ //NOVA EDIT REMOVAL BEGIN - CUSTOMIZATION /* -/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 @@ -78,7 +78,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 @@ -91,13 +91,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.")) @@ -126,11 +126,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) @@ -142,11 +142,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 f8b3286ff22..e52b772479e 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 = NONE //NOVA EDIT CHANGE - ORIGINAL: 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 @@ -99,7 +99,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 @@ -109,7 +109,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) @@ -353,11 +354,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) @@ -385,7 +386,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() @@ -394,7 +395,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) @@ -451,18 +452,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) @@ -750,7 +751,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) @@ -769,7 +770,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 1d3da14fa00..2773f588b24 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 c8515582ac1..d1d0df8f362 100644 --- 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 a1d615041e2..7916606f2df 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 @@ -263,7 +263,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 c0dcf47fbea..50e4e8fa478 100644 --- a/code/modules/surgery/organs/internal/tongue/_tongue.dm +++ b/code/modules/surgery/organs/internal/tongue/_tongue.dm @@ -125,7 +125,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 @@ -144,7 +144,7 @@ ADD_TRAIT(tongue_owner, TRAIT_AGEUSIA, ORGAN_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 84039c9bb66..a97246f908e 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 06d9ba9f2e5..e89769fe7cf 100644 --- a/code/modules/unit_tests/organ_set_bonus.dm +++ b/code/modules/unit_tests/organ_set_bonus.dm @@ -31,7 +31,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 c30c7e629f2..f41d4fa8bf1 100644 --- a/code/modules/wiremod/shell/brain_computer_interface.dm +++ b/code/modules/wiremod/shell/brain_computer_interface.dm @@ -20,11 +20,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 7514b6cdc6b..2ed2bf541d8 100644 --- a/code/modules/zombie/organs.dm +++ b/code/modules/zombie/organs.dm @@ -23,24 +23,24 @@ 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) . = ..() 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/modular_nova/master_files/code/datums/quirks/neutral_quirks/lungs.dm b/modular_nova/master_files/code/datums/quirks/neutral_quirks/lungs.dm index 1e1fa2cc5f8..57247a3aa47 100644 --- a/modular_nova/master_files/code/datums/quirks/neutral_quirks/lungs.dm +++ b/modular_nova/master_files/code/datums/quirks/neutral_quirks/lungs.dm @@ -30,7 +30,7 @@ if (lungs != lungs_added && lungs != lungs_holding) qdel(lungs_holding) return - lungs_holding.Insert(carbon_holder, special = TRUE, drop_if_replaced = FALSE) + lungs_holding.Insert(carbon_holder, special = TRUE, movement_flags = DELETE_IF_REPLACED) lungs_holding.organ_flags &= ~ORGAN_FROZEN /datum/quirk/equipping/lungs/on_equip_item(obj/item/equipped, success) diff --git a/modular_nova/master_files/code/datums/traits/neutral.dm b/modular_nova/master_files/code/datums/traits/neutral.dm index ca1c43a5f39..52adfb141a5 100644 --- a/modular_nova/master_files/code/datums/traits/neutral.dm +++ b/modular_nova/master_files/code/datums/traits/neutral.dm @@ -248,7 +248,7 @@ GLOBAL_VAR_INIT(DNR_trait_overlay, generate_DNR_trait_overlay()) var/obj/item/organ/internal/tongue/dog/new_tongue = new(get_turf(human_holder)) new_tongue.copy_traits_from(human_holder.get_organ_slot(ORGAN_SLOT_TONGUE)) - new_tongue.Insert(human_holder, special = TRUE, drop_if_replaced = FALSE) + new_tongue.Insert(human_holder, special = TRUE, movement_flags = DELETE_IF_REPLACED) /datum/quirk/item_quirk/avian name = "Avian Traits" @@ -263,7 +263,7 @@ GLOBAL_VAR_INIT(DNR_trait_overlay, generate_DNR_trait_overlay()) var/obj/item/organ/internal/tongue/avian/new_tongue = new(get_turf(human_holder)) new_tongue.copy_traits_from(human_holder.get_organ_slot(ORGAN_SLOT_TONGUE)) - new_tongue.Insert(human_holder, special = TRUE, drop_if_replaced = FALSE) + new_tongue.Insert(human_holder, special = TRUE, movement_flags = DELETE_IF_REPLACED) /datum/quirk/sensitivesnout name = "Sensitive Snout" diff --git a/modular_nova/master_files/code/modules/client/preferences/brain.dm b/modular_nova/master_files/code/modules/client/preferences/brain.dm index cdf60e3f59a..1f446e7d893 100644 --- a/modular_nova/master_files/code/modules/client/preferences/brain.dm +++ b/modular_nova/master_files/code/modules/client/preferences/brain.dm @@ -27,7 +27,7 @@ new_brain.modular_persistence = old_brain.modular_persistence old_brain.modular_persistence = null - new_brain.Insert(target, drop_if_replaced = FALSE) + new_brain.mob_insert(target, movement_flags = DELETE_IF_REPLACED) // Prefs can be applied to mindless mobs, let's not try to move the non-existent mind back in! if(!keep_me_safe) diff --git a/modular_nova/modules/cortical_borer/code/cortical_borer.dm b/modular_nova/modules/cortical_borer/code/cortical_borer.dm index 9d5b83fc24a..d77025e6853 100644 --- a/modular_nova/modules/cortical_borer/code/cortical_borer.dm +++ b/modular_nova/modules/cortical_borer/code/cortical_borer.dm @@ -32,7 +32,7 @@ GLOBAL_LIST_EMPTY(cortical_borers) return FALSE //so if a person is debrained, the borer is removed -/obj/item/organ/internal/brain/Remove(mob/living/carbon/target, special = 0, no_id_transfer = FALSE) +/obj/item/organ/internal/brain/Remove(mob/living/carbon/target, special = FALSE, movement_flags) . = ..() var/mob/living/basic/cortical_borer/cb_inside = target.has_borer() if(cb_inside) @@ -50,7 +50,7 @@ GLOBAL_LIST_EMPTY(cortical_borers) borer = null return ..() -/obj/item/organ/internal/borer_body/Insert(mob/living/carbon/carbon_target, special, drop_if_replaced) +/obj/item/organ/internal/borer_body/Insert(mob/living/carbon/carbon_target, special, movement_flags) . = ..() for(var/datum/borer_focus/body_focus as anything in borer.body_focuses) body_focus.on_add() diff --git a/modular_nova/modules/cortical_borer/code/evolution/evolution_things/empowered_egg.dm b/modular_nova/modules/cortical_borer/code/evolution/evolution_things/empowered_egg.dm index d04b31cce56..e1c12846835 100644 --- a/modular_nova/modules/cortical_borer/code/evolution/evolution_things/empowered_egg.dm +++ b/modular_nova/modules/cortical_borer/code/evolution/evolution_things/empowered_egg.dm @@ -19,7 +19,7 @@ if(iscarbon(loc)) Insert(loc) -/obj/item/organ/internal/empowered_borer_egg/Insert(mob/living/carbon/M, special = FALSE, drop_if_replaced = TRUE) +/obj/item/organ/internal/empowered_borer_egg/Insert(mob/living/carbon/M, special = FALSE, movement_flags = DELETE_IF_REPLACED) ..() addtimer(CALLBACK(src, PROC_REF(try_burst)), burst_time) diff --git a/modular_nova/modules/customization/modules/client/augment/limbs.dm b/modular_nova/modules/customization/modules/client/augment/limbs.dm index 8ae5fed1f04..3d855176497 100644 --- a/modular_nova/modules/customization/modules/client/augment/limbs.dm +++ b/modular_nova/modules/customization/modules/client/augment/limbs.dm @@ -31,8 +31,6 @@ var/chosen_style = GLOB.robotic_styles_list[prefs.augment_limb_styles[slot]] new_limb.set_icon_static(chosen_style) new_limb.current_style = prefs.augment_limb_styles[slot] - for (var/obj/item/organ/external/external_organ as anything in old_limb.external_organs) - external_organ.transfer_to_limb(new_limb) new_limb.replace_limb(augmented) qdel(old_limb) diff --git a/modular_nova/modules/customization/modules/client/augment/organs.dm b/modular_nova/modules/customization/modules/client/augment/organs.dm index 091b0414456..0384c3668d9 100644 --- a/modular_nova/modules/customization/modules/client/augment/organs.dm +++ b/modular_nova/modules/customization/modules/client/augment/organs.dm @@ -8,7 +8,7 @@ var/obj/item/organ/organ_path = path // cast this to an organ so we can get the slot from it using initial() var/obj/item/organ/new_organ = new path() new_organ.copy_traits_from(human_holder.get_organ_slot(initial(organ_path.slot))) - new_organ.Insert(human_holder, special = TRUE, drop_if_replaced = FALSE) + new_organ.Insert(human_holder, special = TRUE, movement_flags = DELETE_IF_REPLACED) //HEARTS /datum/augment_item/organ/heart diff --git a/modular_nova/modules/customization/modules/mob/dead/new_player/sprite_accessories/snout.dm b/modular_nova/modules/customization/modules/mob/dead/new_player/sprite_accessories/snout.dm index 159d8c9a652..9eb7da1b4dd 100644 --- a/modular_nova/modules/customization/modules/mob/dead/new_player/sprite_accessories/snout.dm +++ b/modular_nova/modules/customization/modules/mob/dead/new_player/sprite_accessories/snout.dm @@ -30,7 +30,7 @@ return !sprite_datum.is_hidden(human) -/obj/item/organ/external/snout/Insert(mob/living/carbon/reciever, special, drop_if_replaced) +/obj/item/organ/external/snout/Insert(mob/living/carbon/reciever, special, movement_flags) if(sprite_accessory_flags & SPRITE_ACCESSORY_USE_MUZZLED_SPRITE) external_bodytypes |= BODYTYPE_SNOUTED if(sprite_accessory_flags & SPRITE_ACCESSORY_USE_ALT_FACEWEAR_LAYER) diff --git a/modular_nova/modules/customization/modules/mob/living/carbon/human/species.dm b/modular_nova/modules/customization/modules/mob/living/carbon/human/species.dm index 9568aec0bd0..31b0dd14e20 100644 --- a/modular_nova/modules/customization/modules/mob/living/carbon/human/species.dm +++ b/modular_nova/modules/customization/modules/mob/living/carbon/human/species.dm @@ -277,7 +277,7 @@ GLOBAL_LIST_EMPTY(customizable_races) replacement.build_from_dna(target.dna, key) // organ.Insert will qdel any current organs in that slot, so we don't need to. - replacement.Insert(target, special = TRUE, drop_if_replaced = FALSE) + replacement.Insert(target, special = TRUE, movement_flags = DELETE_IF_REPLACED) // var/obj/item/organ/path = new SA.organ_type // var/obj/item/organ/oldorgan = C.get_organ_slot(path.slot) diff --git a/modular_nova/modules/customization/modules/mob/living/carbon/human/species/ghoul.dm b/modular_nova/modules/customization/modules/mob/living/carbon/human/species/ghoul.dm index a1574f895a4..e71c3ed9e50 100644 --- a/modular_nova/modules/customization/modules/mob/living/carbon/human/species/ghoul.dm +++ b/modular_nova/modules/customization/modules/mob/living/carbon/human/species/ghoul.dm @@ -53,39 +53,39 @@ /mob/living/carbon/proc/ReassignForeignBodyparts() var/obj/item/bodypart/head = get_bodypart(BODY_ZONE_HEAD) if (head?.type != part_default_head) - qdel(head) var/obj/item/bodypart/limb = new part_default_head limb.replace_limb(src, TRUE) + qdel(head) var/obj/item/bodypart/chest = get_bodypart(BODY_ZONE_CHEST) if (chest?.type != part_default_chest) - qdel(chest) var/obj/item/bodypart/limb = new part_default_chest limb.replace_limb(src, TRUE) + qdel(chest) var/obj/item/bodypart/arm/left/left_arm = get_bodypart(BODY_ZONE_L_ARM) if (left_arm?.type != part_default_l_arm) - qdel(left_arm) var/obj/item/bodypart/limb = new part_default_l_arm limb.replace_limb(src, TRUE) + qdel(left_arm) var/obj/item/bodypart/arm/right/right_arm = get_bodypart(BODY_ZONE_R_ARM) if (right_arm?.type != part_default_r_arm) - qdel(right_arm) var/obj/item/bodypart/limb = new part_default_r_arm limb.replace_limb(src, TRUE) + qdel(right_arm) var/obj/item/bodypart/leg/left/left_leg = get_bodypart(BODY_ZONE_L_LEG) if (left_leg?.type != part_default_l_leg) - qdel(left_leg) var/obj/item/bodypart/limb = new part_default_l_leg limb.replace_limb(src, TRUE) + qdel(left_leg) var/obj/item/bodypart/leg/right/right_leg = get_bodypart(BODY_ZONE_R_LEG) if (right_leg?.type != part_default_r_leg) - qdel(right_leg) var/obj/item/bodypart/limb = new part_default_r_leg limb.replace_limb(src, TRUE) + qdel(right_leg) /datum/species/ghoul/on_species_gain(mob/living/carbon/new_ghoul, datum/species/old_species, pref_load) // Missing Defaults in DNA? Randomize! diff --git a/modular_nova/modules/customization/modules/mob/living/carbon/human/species/hemophage/hemophage_tumor.dm b/modular_nova/modules/customization/modules/mob/living/carbon/human/species/hemophage/hemophage_tumor.dm index 2f4ee0c3c52..e19afb9734f 100644 --- a/modular_nova/modules/customization/modules/mob/living/carbon/human/species/hemophage/hemophage_tumor.dm +++ b/modular_nova/modules/customization/modules/mob/living/carbon/human/species/hemophage/hemophage_tumor.dm @@ -25,7 +25,7 @@ var/bloodloss_rate = NORMAL_BLOOD_DRAIN -/obj/item/organ/internal/heart/hemophage/Insert(mob/living/carbon/tumorful, special, drop_if_replaced) +/obj/item/organ/internal/heart/hemophage/Insert(mob/living/carbon/tumorful, special, movement_flags) . = ..() if(!. || !owner) return diff --git a/modular_nova/modules/customization/modules/mob/living/carbon/human/species/roundstartslime.dm b/modular_nova/modules/customization/modules/mob/living/carbon/human/species/roundstartslime.dm index ad469037a85..33cd7ff1907 100644 --- a/modular_nova/modules/customization/modules/mob/living/carbon/human/species/roundstartslime.dm +++ b/modular_nova/modules/customization/modules/mob/living/carbon/human/species/roundstartslime.dm @@ -389,7 +389,7 @@ if(robot_organs) replacement_organ.organ_flags |= ORGAN_ROBOTIC replacement_organ.build_from_dna(alterer.dna, chosen_key) - replacement_organ.Insert(alterer, special = TRUE, drop_if_replaced = FALSE) + replacement_organ.Insert(alterer, special = TRUE, movement_flags = DELETE_IF_REPLACED) else var/list/new_acc_list = list() new_acc_list[MUTANT_INDEX_NAME] = selected_sprite_accessory.name diff --git a/modular_nova/modules/customization/modules/surgery/organs/genitals.dm b/modular_nova/modules/customization/modules/surgery/organs/genitals.dm index 4abce60d6e3..17a22786e29 100644 --- a/modular_nova/modules/customization/modules/surgery/organs/genitals.dm +++ b/modular_nova/modules/customization/modules/surgery/organs/genitals.dm @@ -50,7 +50,7 @@ return INITIALIZE_HINT_QDEL //Removes ERP organs depending on config -/obj/item/organ/external/genital/Insert(mob/living/carbon/M, special, drop_if_replaced) +/obj/item/organ/external/genital/Insert(mob/living/carbon/M, special, movement_flags) if(CONFIG_GET(flag/disable_erp_preferences)) return . = ..() diff --git a/modular_nova/modules/customization/modules/surgery/organs/organ.dm b/modular_nova/modules/customization/modules/surgery/organs/organ.dm index ac69342a036..e1892fc5543 100644 --- a/modular_nova/modules/customization/modules/surgery/organs/organ.dm +++ b/modular_nova/modules/customization/modules/surgery/organs/organ.dm @@ -14,21 +14,23 @@ if(mutantpart_key) color = mutantpart_info[MUTANT_INDEX_COLOR_LIST][1] -/obj/item/organ/Insert(mob/living/carbon/M, special = FALSE, drop_if_replaced = TRUE) +/obj/item/organ/Insert(mob/living/carbon/M, special = FALSE, movement_flags = DELETE_IF_REPLACED) var/mob/living/carbon/human/H = M if(mutantpart_key && istype(H)) H.dna.species.mutant_bodyparts[mutantpart_key] = mutantpart_info.Copy() - H.update_body() + if(!special) + H.update_body() . = ..() -/obj/item/organ/Remove(mob/living/carbon/M, special = FALSE) +/obj/item/organ/Remove(mob/living/carbon/M, special = FALSE, movement_flags) var/mob/living/carbon/human/H = M if(mutantpart_key && istype(H)) if(H.dna.species.mutant_bodyparts[mutantpart_key]) mutantpart_info = H.dna.species.mutant_bodyparts[mutantpart_key].Copy() //Update the info in case it was changed on the person color = mutantpart_info[MUTANT_INDEX_COLOR_LIST][1] H.dna.species.mutant_bodyparts -= mutantpart_key - H.update_body() + if(!special) + H.update_body() . = ..() /obj/item/organ/proc/build_from_dna(datum/dna/DNA, associated_key) diff --git a/modular_nova/modules/customization/modules/surgery/organs/tails.dm b/modular_nova/modules/customization/modules/surgery/organs/tails.dm index 007fcb16dfd..3cafd6852a0 100644 --- a/modular_nova/modules/customization/modules/surgery/organs/tails.dm +++ b/modular_nova/modules/customization/modules/surgery/organs/tails.dm @@ -41,7 +41,7 @@ return TRUE -/obj/item/organ/external/tail/Insert(mob/living/carbon/reciever, special, drop_if_replaced) +/obj/item/organ/external/tail/Insert(mob/living/carbon/reciever, special, movement_flags) if(sprite_accessory_flags & SPRITE_ACCESSORY_WAG_ABLE) wag_flags |= WAG_ABLE return ..() diff --git a/modular_nova/modules/customization/modules/surgery/organs/taur_body.dm b/modular_nova/modules/customization/modules/surgery/organs/taur_body.dm index 233b2290b7c..81b842a1af6 100644 --- a/modular_nova/modules/customization/modules/surgery/organs/taur_body.dm +++ b/modular_nova/modules/customization/modules/surgery/organs/taur_body.dm @@ -31,7 +31,7 @@ return GLOB.sprite_accessories["taur"] -/obj/item/organ/external/taur_body/Insert(mob/living/carbon/reciever, special, drop_if_replaced) +/obj/item/organ/external/taur_body/Insert(mob/living/carbon/reciever, special, movement_flags) if(sprite_accessory_flags & SPRITE_ACCESSORY_HIDE_SHOES) external_bodytypes |= BODYTYPE_HIDE_SHOES diff --git a/modular_nova/modules/modular_implants/code/nifs.dm b/modular_nova/modules/modular_implants/code/nifs.dm index 5ec2b9b17fa..35177c8c0cf 100644 --- a/modular_nova/modules/modular_implants/code/nifs.dm +++ b/modular_nova/modules/modular_implants/code/nifs.dm @@ -126,7 +126,7 @@ QDEL_LIST(loaded_nifsofts) return ..() -/obj/item/organ/internal/cyberimp/brain/nif/Insert(mob/living/carbon/human/insertee, special = FALSE, drop_if_replaced = TRUE) +/obj/item/organ/internal/cyberimp/brain/nif/Insert(mob/living/carbon/human/insertee, special = FALSE, movement_flags = DELETE_IF_REPLACED) . = ..() if(linked_mob && stored_ckey != insertee.ckey && theft_protection) diff --git a/modular_nova/modules/organs/code/heart.dm b/modular_nova/modules/organs/code/heart.dm index 857e1f05749..bc2f8ebc59b 100644 --- a/modular_nova/modules/organs/code/heart.dm +++ b/modular_nova/modules/organs/code/heart.dm @@ -9,7 +9,7 @@ COOLDOWN_DECLARE(shell_effect_cd) -/obj/item/organ/internal/heart/snail/on_insert(mob/living/carbon/organ_owner, special) +/obj/item/organ/internal/heart/snail/on_mob_insert(mob/living/carbon/organ_owner, special) . = ..() if(!ishuman(organ_owner)) return @@ -22,7 +22,7 @@ RegisterSignal(human_owner, COMSIG_MOB_APPLY_DAMAGE_MODIFIERS, PROC_REF(modify_damage)) RegisterSignal(human_owner, COMSIG_MOB_AFTER_APPLY_DAMAGE, PROC_REF(do_block_effect)) -/obj/item/organ/internal/heart/snail/on_remove(mob/living/carbon/organ_owner, special) +/obj/item/organ/internal/heart/snail/on_mob_remove(mob/living/carbon/organ_owner, special) . = ..() if(!ishuman(organ_owner) || QDELETED(organ_owner)) return diff --git a/modular_nova/modules/organs/code/tongue.dm b/modular_nova/modules/organs/code/tongue.dm index 957ee29fcda..c803bfc90c9 100644 --- a/modular_nova/modules/organs/code/tongue.dm +++ b/modular_nova/modules/organs/code/tongue.dm @@ -12,7 +12,7 @@ icon_state = "tongue" modifies_speech = TRUE -/obj/item/organ/internal/tongue/dog/Insert(mob/living/carbon/signer, special = FALSE, drop_if_replaced = TRUE) +/obj/item/organ/internal/tongue/dog/Insert(mob/living/carbon/signer, special = FALSE, movement_flags = DELETE_IF_REPLACED) . = ..() signer.verb_ask = "arfs" signer.verb_exclaim = "wans" @@ -34,7 +34,7 @@ icon_state = "tongue" modifies_speech = TRUE -/obj/item/organ/internal/tongue/avian/Insert(mob/living/carbon/signer, special = FALSE, drop_if_replaced = TRUE) +/obj/item/organ/internal/tongue/avian/Insert(mob/living/carbon/signer, special = FALSE, movement_flags = DELETE_IF_REPLACED) . = ..() signer.verb_ask = "peeps" signer.verb_exclaim = "squawks" diff --git a/modular_nova/modules/synths/code/bodyparts/brain.dm b/modular_nova/modules/synths/code/bodyparts/brain.dm index 5638c39269f..bd4564c0886 100644 --- a/modular_nova/modules/synths/code/bodyparts/brain.dm +++ b/modular_nova/modules/synths/code/bodyparts/brain.dm @@ -10,15 +10,15 @@ /// The last time (in ticks) a message about brain damage was sent. Don't touch. var/last_message_time = 0 -/obj/item/organ/internal/brain/synth/Insert(mob/living/carbon/user, special = FALSE, drop_if_replaced = TRUE, no_id_transfer = FALSE) +/obj/item/organ/internal/brain/synth/mob_insert(mob/living/carbon/brain_owner, special = FALSE, movement_flags) . = ..() - if(user.stat != DEAD || !ishuman(user)) + if(brain_owner.stat != DEAD || !ishuman(brain_owner)) return - var/mob/living/carbon/human/user_human = user - if(HAS_TRAIT(user_human, TRAIT_REVIVES_BY_HEALING) && user_human.health > SYNTH_BRAIN_WAKE_THRESHOLD) - user_human.revive(FALSE) + var/mob/living/carbon/human/human_brain_owner = brain_owner + if(HAS_TRAIT(human_brain_owner, TRAIT_REVIVES_BY_HEALING) && human_brain_owner.health > SYNTH_BRAIN_WAKE_THRESHOLD) + human_brain_owner.revive(FALSE) /obj/item/organ/internal/brain/synth/emp_act(severity) // EMP act against the posi, keep the cap far below the organ health . = ..() diff --git a/modular_nova/modules/synths/code/bodyparts/stomach.dm b/modular_nova/modules/synths/code/bodyparts/stomach.dm index 437d9eacff2..686774162ec 100644 --- a/modular_nova/modules/synths/code/bodyparts/stomach.dm +++ b/modular_nova/modules/synths/code/bodyparts/stomach.dm @@ -47,7 +47,7 @@ ) departmental_flags = DEPARTMENT_BITFLAG_MEDICAL | DEPARTMENT_BITFLAG_SCIENCE -/obj/item/organ/internal/stomach/synth/Insert(mob/living/carbon/receiver, special, drop_if_replaced) +/obj/item/organ/internal/stomach/synth/Insert(mob/living/carbon/receiver, special, movement_flags) . = ..() RegisterSignal(receiver, COMSIG_PROCESS_BORGCHARGER_OCCUPANT, PROC_REF(on_borg_charge)) diff --git a/tgstation.dme b/tgstation.dme index 2e12830c4c8..baa50b53c00 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" @@ -5802,6 +5803,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"