diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index 17a51c5b75c..8e6c30f85fd 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -163,10 +163,7 @@ ///The species is forced to have digitigrade legs in generation. #define DIGITIGRADE_FORCED 2 -// Preferences for leg types -/// Legs that are normal -#define NORMAL_LEGS "Normal Legs" -/// Digitgrade legs that are like bended and uhhh no shoes +///Digitigrade's prefs, used in features for legs if you're meant to be a Digitigrade. #define DIGITIGRADE_LEGS "Digitigrade Legs" // Health/damage defines diff --git a/code/__HELPERS/duplicating.dm b/code/__HELPERS/duplicating.dm index f0f3f9a9fce..225dca91fb5 100644 --- a/code/__HELPERS/duplicating.dm +++ b/code/__HELPERS/duplicating.dm @@ -15,6 +15,8 @@ GLOBAL_LIST_INIT(duplicate_forbidden_vars, list( "contents", "cooldowns", "_datum_components", + "external_organs", + "external_organs_slot", "group", "hand_bodyparts", "held_items", diff --git a/code/controllers/subsystem/sprite_accessories.dm b/code/controllers/subsystem/sprite_accessories.dm index 445f8a6d6d1..8d7017648e9 100644 --- a/code/controllers/subsystem/sprite_accessories.dm +++ b/code/controllers/subsystem/sprite_accessories.dm @@ -47,6 +47,7 @@ SUBSYSTEM_DEF(accessories) // just 'accessories' for brevity var/list/horns_list var/list/frills_list var/list/spines_list + var/list/legs_list var/list/tail_spines_list //Mutant Human bits diff --git a/code/datums/bodypart_overlays/mutant_bodypart_overlay.dm b/code/datums/bodypart_overlays/mutant_bodypart_overlay.dm index 0ac3e5c3c1a..158bba5eece 100644 --- a/code/datums/bodypart_overlays/mutant_bodypart_overlay.dm +++ b/code/datums/bodypart_overlays/mutant_bodypart_overlay.dm @@ -13,24 +13,6 @@ ///Take on the dna/preference from whoever we're gonna be inserted in var/imprint_on_next_insertion = TRUE -/datum/bodypart_overlay/mutant/New(obj/item/organ/attached_organ) - . = ..() - - RegisterSignal(attached_organ, COMSIG_ORGAN_IMPLANTED, PROC_REF(on_mob_insert)) - -/datum/bodypart_overlay/mutant/proc/on_mob_insert(obj/item/organ/parent, mob/living/carbon/receiver) - SIGNAL_HANDLER - - if(!should_visual_organ_apply_to(parent.type, receiver)) - stack_trace("adding a [parent.type] to a [receiver.type] when it shouldn't be!") - - if(imprint_on_next_insertion) //We only want this set *once* - var/feature_name = receiver.dna.features[feature_key] - if (isnull(feature_name)) - feature_name = receiver.dna.species.mutant_organs[parent.type] - set_appearance_from_name(feature_name) - imprint_on_next_insertion = FALSE - /datum/bodypart_overlay/mutant/get_overlay(layer, obj/item/bodypart/limb) inherit_color(limb) // If draw_color is not set yet, go ahead and do that return ..() @@ -85,6 +67,7 @@ return appearance /datum/bodypart_overlay/mutant/color_image(image/overlay, layer, obj/item/bodypart/limb) + overlay.color = sprite_datum.color_src ? draw_color : null /datum/bodypart_overlay/mutant/added_to_limb(obj/item/bodypart/limb) diff --git a/code/datums/dna.dm b/code/datums/dna.dm index e06c6849286..43e105dacbd 100644 --- a/code/datums/dna.dm +++ b/code/datums/dna.dm @@ -755,8 +755,9 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) dna.features["caps"] = SSaccessories.caps_list[deconstruct_block(get_uni_feature_block(features, DNA_MUSHROOM_CAPS_BLOCK), length(SSaccessories.caps_list))] if(dna.features["pod_hair"]) dna.features["pod_hair"] = SSaccessories.pod_hair_list[deconstruct_block(get_uni_feature_block(features, DNA_POD_HAIR_BLOCK), length(SSaccessories.pod_hair_list))] - for(var/obj/item/organ/organ in organs) - organ.mutate_feature(features, src) + + for(var/obj/item/organ/external/external_organ in organs) + external_organ.mutate_feature(features, src) if(icon_update) update_body(is_creating = mutcolor_update) diff --git a/code/datums/quirks/neutral_quirks/transhumanist.dm b/code/datums/quirks/neutral_quirks/transhumanist.dm index aa8ae075df3..ea6494a6b32 100644 --- a/code/datums/quirks/neutral_quirks/transhumanist.dm +++ b/code/datums/quirks/neutral_quirks/transhumanist.dm @@ -127,10 +127,10 @@ else if(isorgan(new_part)) var/obj/item/organ/new_organ = new_part old_part = human_holder.get_organ_slot(new_organ.slot) - new_organ.Insert(human_holder, special = TRUE) - old_part.moveToNullspace() - STOP_PROCESSING(SSobj, old_part) - slot_string = new_organ.name + if(new_organ.Insert(human_holder, special = TRUE)) + old_part.moveToNullspace() + STOP_PROCESSING(SSobj, old_part) + slot_string = new_organ.name /datum/quirk/transhumanist/post_add() if(!slot_string) diff --git a/code/datums/sprite_accessories.dm b/code/datums/sprite_accessories.dm index 35fd07ff3bc..3f7f4a5bff0 100644 --- a/code/datums/sprite_accessories.dm +++ b/code/datums/sprite_accessories.dm @@ -34,6 +34,8 @@ * This is the source that this accessory will get its color from. Default is MUTCOLOR, but can also be HAIR, FACEHAIR, EYECOLOR and 0 if none. */ var/color_src = MUTANT_COLOR + /// Decides if this sprite has an "inner" part, such as the fleshy parts on ears. + var/hasinner = FALSE /// Is this part locked from roundstart selection? Used for parts that apply effects. var/locked = FALSE /// Should we center the sprite? @@ -1891,6 +1893,7 @@ /datum/sprite_accessory/ears/cat name = "Cat" icon_state = "cat" + hasinner = TRUE color_src = HAIR_COLOR /datum/sprite_accessory/ears/cat/miqo @@ -1913,6 +1916,7 @@ icon = 'icons/mob/human/fox_features.dmi' name = "Fox" icon_state = "fox" + hasinner = TRUE color_src = HAIR_COLOR locked = TRUE @@ -2075,6 +2079,10 @@ icon = 'icons/mob/human/species/lizard/lizard_spines.dmi' em_block = TRUE +/datum/sprite_accessory/spines/none + name = SPRITE_ACCESSORY_NONE + icon_state = "none" + /datum/sprite_accessory/tail_spines icon = 'icons/mob/human/species/lizard/lizard_spines.dmi' em_block = TRUE @@ -2119,6 +2127,16 @@ name = "Aquatic" icon_state = "aqua" +/datum/sprite_accessory/legs //legs are a special case, they aren't actually sprite_accessories but are updated with them. + icon = null //These datums exist for selecting legs on preference, and little else + em_block = TRUE + +/datum/sprite_accessory/legs/none + name = "Normal Legs" + +/datum/sprite_accessory/legs/digitigrade_lizard + name = DIGITIGRADE_LEGS + /datum/sprite_accessory/caps icon = 'icons/mob/human/species/mush_cap.dmi' color_src = HAIR_COLOR diff --git a/code/game/machinery/dna_infuser/organ_sets/fly_organs.dm b/code/game/machinery/dna_infuser/organ_sets/fly_organs.dm index 3ffad6dcba3..f86a161b1ce 100644 --- a/code/game/machinery/dna_infuser/organ_sets/fly_organs.dm +++ b/code/game/machinery/dna_infuser/organ_sets/fly_organs.dm @@ -137,6 +137,7 @@ //useless organs we throw in just to fuck with surgeons a bit more. they aren't part of a bonus, just the (absolute) state of flies /obj/item/organ/internal/fly desc = FLY_INFUSED_ORGAN_DESC + visual = FALSE /obj/item/organ/internal/fly/Initialize(mapload) . = ..() 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 db12c7fb9ee..60d4465ce72 100644 --- a/code/game/machinery/dna_infuser/organ_sets/fox_organs.dm +++ b/code/game/machinery/dna_infuser/organ_sets/fox_organs.dm @@ -22,7 +22,6 @@ color = ear_owner.hair_color ear_owner.dna.species.mutant_bodyparts -= "ears" ear_owner.update_body() - sprite_accessory_override = /datum/sprite_accessory/ears/fox */ //SKYRAT EDIT REMOVAL END 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 9fcf7e483bb..797c7839b2c 100644 --- a/code/game/machinery/dna_infuser/organ_sets/gondola_organs.dm +++ b/code/game/machinery/dna_infuser/organ_sets/gondola_organs.dm @@ -34,7 +34,7 @@ Fluoride Stare: After someone says 5 words, blah blah blah... AddElement(/datum/element/noticable_organ, "%PRONOUN_They radiate%PRONOUN_s an aura of serenity.") AddElement(/datum/element/update_icon_blocker) -/obj/item/organ/internal/heart/gondola/mob_insert(mob/living/carbon/receiver, special, movement_flags) +/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 @@ -42,7 +42,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/mob_remove(mob/living/carbon/heartless, special, movement_flags) +/obj/item/organ/internal/heart/gondola/Remove(mob/living/carbon/heartless, special, movement_flags) . = ..() for(var/faction in factions_to_remove) heartless.faction -= faction @@ -64,11 +64,11 @@ Fluoride Stare: After someone says 5 words, blah blah blah... AddElement(/datum/element/noticable_organ, "%PRONOUN_Their 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/mob_insert(mob/living/carbon/tongue_owner, special, movement_flags) +/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/mob_remove(mob/living/carbon/tongue_owner, special, movement_flags) +/obj/item/organ/internal/tongue/gondola/Remove(mob/living/carbon/tongue_owner, special, movement_flags) tongue_owner.clear_mood_event("gondola_zen") return ..() @@ -87,7 +87,7 @@ Fluoride Stare: After someone says 5 words, blah blah blah... AddElement(/datum/element/noticable_organ, "%PRONOUN_Their left arm has small needles breaching the skin all over it.", BODY_ZONE_L_ARM) AddElement(/datum/element/noticable_organ, "%PRONOUN_Their right arm has small needles breaching the skin all over it.", BODY_ZONE_R_ARM) -/obj/item/organ/internal/liver/gondola/mob_insert(mob/living/carbon/liver_owner, special, movement_flags) +/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) @@ -102,7 +102,7 @@ Fluoride Stare: After someone says 5 words, blah blah blah... RegisterSignal(liver_owner, COMSIG_LIVING_TRY_PULL, PROC_REF(on_owner_try_pull)) RegisterSignal(liver_owner, COMSIG_CARBON_HELPED, PROC_REF(on_hug)) -/obj/item/organ/internal/liver/gondola/mob_remove(mob/living/carbon/liver_owner, special, movement_flags) +/obj/item/organ/internal/liver/gondola/Remove(mob/living/carbon/liver_owner, special, movement_flags) . = ..() UnregisterSignal(liver_owner, list(COMSIG_HUMAN_EQUIPPING_ITEM, COMSIG_LIVING_TRY_PULL, COMSIG_CARBON_HELPED)) diff --git a/code/game/objects/items/body_egg.dm b/code/game/objects/items/body_egg.dm index d8b48e0789b..d244d8c55cc 100644 --- a/code/game/objects/items/body_egg.dm +++ b/code/game/objects/items/body_egg.dm @@ -15,14 +15,15 @@ if(iscarbon(loc)) Insert(loc) -/obj/item/organ/internal/body_egg/mob_insert(mob/living/carbon/egg_owner, special = FALSE, movement_flags = DELETE_IF_REPLACED) +/obj/item/organ/internal/body_egg/Insert(mob/living/carbon/egg_owner, special = FALSE, movement_flags = DELETE_IF_REPLACED) . = ..() - + if(!.) + return egg_owner.add_traits(list(TRAIT_XENO_HOST, TRAIT_XENO_IMMUNE), ORGAN_TRAIT) egg_owner.med_hud_set_status() INVOKE_ASYNC(src, PROC_REF(AddInfectionImages), egg_owner) -/obj/item/organ/internal/body_egg/mob_remove(mob/living/carbon/egg_owner, special, movement_flags) +/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/modules/admin/verbs/manipulate_organs.dm b/code/modules/admin/verbs/manipulate_organs.dm index 6c0a86126b6..bfb5050dafa 100644 --- a/code/modules/admin/verbs/manipulate_organs.dm +++ b/code/modules/admin/verbs/manipulate_organs.dm @@ -18,7 +18,10 @@ ADMIN_VERB(manipulate_organs, R_DEBUG, "Manipulate Organs", "Manipulate the orga return organ_to_grant = organs[organ_to_grant] organ_to_grant = new organ_to_grant - organ_to_grant.Insert(carbon_victim) + if(!organ_to_grant.Insert(carbon_victim)) + to_chat(user, span_notice("[carbon_victim] is unable to carry this organ!")) + qdel(organ_to_grant) + return log_admin("[key_name(user)] has added organ [organ_to_grant.type] to [key_name(carbon_victim)]") message_admins("[key_name_admin(user)] has added organ [organ_to_grant.type] to [ADMIN_LOOKUPFLW(carbon_victim)]") diff --git a/code/modules/admin/verbs/secrets.dm b/code/modules/admin/verbs/secrets.dm index bcb89379ef4..53ab045e281 100644 --- a/code/modules/admin/verbs/secrets.dm +++ b/code/modules/admin/verbs/secrets.dm @@ -526,7 +526,7 @@ ADMIN_VERB(secrets, R_NONE, "Secrets", "Abuse harder than you ever have before w var/forename = names.len > 1 ? names[2] : names[1] var/newname = "[forename]-[pick(honorifics["[H.gender]"])]" H.fully_replace_character_name(H.real_name,newname) - H.update_body_parts() + H.update_mutant_bodyparts() if(animetype == "Yes") var/seifuku = pick(typesof(/obj/item/clothing/under/costume/schoolgirl)) var/obj/item/clothing/under/costume/schoolgirl/I = new seifuku diff --git a/code/modules/antagonists/abductor/equipment/gland.dm b/code/modules/antagonists/abductor/equipment/gland.dm index f4fe0fb1875..29ea5f1e785 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/mob_remove(mob/living/carbon/gland_owner, special, movement_flags) +/obj/item/organ/internal/heart/gland/Remove(mob/living/carbon/gland_owner, special, movement_flags) . = ..() active = FALSE if(initial(uses) == 1) @@ -93,8 +93,10 @@ hud.remove_atom_from_hud(gland_owner) clear_mind_control() -/obj/item/organ/internal/heart/gland/mob_insert(mob/living/carbon/gland_owner, special = FALSE, movement_flags = DELETE_IF_REPLACED) +/obj/item/organ/internal/heart/gland/Insert(mob/living/carbon/gland_owner, special = FALSE, movement_flags = DELETE_IF_REPLACED) . = ..() + if(!.) + return if(special != 2 && uses) // Special 2 means abductor surgery Start() diff --git a/code/modules/antagonists/changeling/headslug_eggs.dm b/code/modules/antagonists/changeling/headslug_eggs.dm index 75c0881c551..8f861aec2ec 100644 --- a/code/modules/antagonists/changeling/headslug_eggs.dm +++ b/code/modules/antagonists/changeling/headslug_eggs.dm @@ -11,11 +11,11 @@ /// When this egg last got removed from a body. If -1, the egg hasn't been removed from a body. var/removal_time = -1 -/obj/item/organ/internal/body_egg/changeling_egg/mob_insert(mob/living/carbon/egg_owner, special = FALSE, movement_flags = DELETE_IF_REPLACED) +/obj/item/organ/internal/body_egg/changeling_egg/Insert(mob/living/carbon/egg_owner, special = FALSE, movement_flags = DELETE_IF_REPLACED) . = ..() hatch_time = world.time + (removal_time == -1 ? EGG_INCUBATION_TIME : (hatch_time - removal_time)) -/obj/item/organ/internal/body_egg/changeling_egg/mob_remove(mob/living/carbon/egg_owner, special, movement_flags) +/obj/item/organ/internal/body_egg/changeling_egg/Remove(mob/living/carbon/egg_owner, special, movement_flags) . = ..() removal_time = world.time diff --git a/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_knowledge.dm b/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_knowledge.dm index 4b3525c93b0..aff7af7c5fa 100644 --- a/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_knowledge.dm +++ b/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_knowledge.dm @@ -418,13 +418,20 @@ usable_organs -= /obj/item/organ/internal/lungs/corrupt // Their lungs are already more cursed than anything I could give them var/total_implant = rand(2, 4) + var/gave_any = FALSE for (var/i in 1 to total_implant) if (!length(usable_organs)) - return + break var/organ_path = pick_n_take(usable_organs) var/obj/item/organ/internal/to_give = new organ_path - to_give.Insert(sac_target) + if (!to_give.Insert(sac_target)) + qdel(to_give) + else + gave_any = TRUE + + if (!gave_any) + return new /obj/effect/gibspawner/human/bodypartless(get_turf(sac_target)) sac_target.visible_message(span_boldwarning("Several organs force themselves out of [sac_target]!")) diff --git a/code/modules/antagonists/nightmare/nightmare_organs.dm b/code/modules/antagonists/nightmare/nightmare_organs.dm index 19328f20378..a77aaa79b23 100644 --- a/code/modules/antagonists/nightmare/nightmare_organs.dm +++ b/code/modules/antagonists/nightmare/nightmare_organs.dm @@ -65,10 +65,9 @@ /obj/item/organ/internal/heart/nightmare name = "heart of darkness" desc = "An alien organ that twists and writhes when exposed to light." - visual = TRUE icon_state = "demon_heart-on" base_icon_state = "demon_heart" - + visual = TRUE color = COLOR_CRAYON_BLACK decay_factor = 0 // No love is to be found in a heart so twisted. diff --git a/code/modules/antagonists/revenant/revenant_blight.dm b/code/modules/antagonists/revenant/revenant_blight.dm index 13a1ff7e1d6..dcbc9bc8181 100644 --- a/code/modules/antagonists/revenant/revenant_blight.dm +++ b/code/modules/antagonists/revenant/revenant_blight.dm @@ -19,6 +19,7 @@ if(affected_mob) affected_mob.remove_atom_colour(TEMPORARY_COLOUR_PRIORITY, "#1d2953") if(affected_mob.dna && affected_mob.dna.species) + affected_mob.dna.species.handle_mutant_bodyparts(affected_mob) affected_mob.set_haircolor(null, override = TRUE) to_chat(affected_mob, span_notice("You feel better.")) ..() @@ -65,6 +66,7 @@ affected_mob.adjustStaminaLoss(22.5 * seconds_per_tick, updating_stamina = FALSE) new /obj/effect/temp_visual/revenant(affected_mob.loc) if(affected_mob.dna && affected_mob.dna.species) + affected_mob.dna.species.handle_mutant_bodyparts(affected_mob,"#1d2953") affected_mob.set_haircolor("#1d2953", override = TRUE) affected_mob.visible_message(span_warning("[affected_mob] looks terrifyingly gaunt..."), span_revennotice("You suddenly feel like your skin is wrong...")) affected_mob.add_atom_colour("#1d2953", TEMPORARY_COLOUR_PRIORITY) diff --git a/code/modules/client/preferences/_preference.dm b/code/modules/client/preferences/_preference.dm index cf3809ca42a..8eca4652527 100644 --- a/code/modules/client/preferences/_preference.dm +++ b/code/modules/client/preferences/_preference.dm @@ -111,6 +111,10 @@ GLOBAL_LIST_INIT(preference_entries_by_key, init_preference_entries_by_key()) /// DOES have random body on, will this already be randomized? var/randomize_by_default = TRUE + /// If the selected species has this in its /datum/species/mutant_bodyparts, + /// will show the feature as selectable. + var/relevant_mutant_bodypart = null + /// If the selected species has this in its /datum/species/body_markings, /// will show the feature as selectable. var/relevant_body_markings = null @@ -332,7 +336,8 @@ GLOBAL_LIST_INIT(preference_entries_by_key, init_preference_entries_by_key()) SHOULD_NOT_SLEEP(TRUE) if ( \ - !isnull(relevant_inherent_trait) \ + !isnull(relevant_mutant_bodypart) \ + || !isnull(relevant_inherent_trait) \ || !isnull(relevant_external_organ) \ || !isnull(relevant_head_flag) \ || !isnull(relevant_body_markings) \ diff --git a/code/modules/client/preferences/species_features/lizard.dm b/code/modules/client/preferences/species_features/lizard.dm index 2292e3f3e83..2ae38c9ac67 100644 --- a/code/modules/client/preferences/species_features/lizard.dm +++ b/code/modules/client/preferences/species_features/lizard.dm @@ -94,51 +94,13 @@ savefile_key = "feature_lizard_legs" savefile_identifier = PREFERENCE_CHARACTER category = PREFERENCE_CATEGORY_SECONDARY_FEATURES + relevant_mutant_bodypart = "legs" /datum/preference/choiced/lizard_legs/init_possible_values() - return list(NORMAL_LEGS, DIGITIGRADE_LEGS) + return assoc_to_keys_features(SSaccessories.legs_list) /datum/preference/choiced/lizard_legs/apply_to_human(mob/living/carbon/human/target, value) target.dna.features["legs"] = value - // Hack to update the dummy in the preference menu - // (Because digi legs are ONLY handled on species change) - if(!isdummy(target) || target.dna.species.digitigrade_customization == DIGITIGRADE_NEVER) - return - - var/list/correct_legs = target.dna.species.bodypart_overrides.Copy() & list(BODY_ZONE_R_LEG, BODY_ZONE_L_LEG) - - if(value == DIGITIGRADE_LEGS) - correct_legs[BODY_ZONE_R_LEG] = /obj/item/bodypart/leg/right/digitigrade - correct_legs[BODY_ZONE_L_LEG] = /obj/item/bodypart/leg/left/digitigrade - - for(var/obj/item/bodypart/old_part as anything in target.bodyparts) - if(old_part.change_exempt_flags & BP_BLOCK_CHANGE_SPECIES) - continue - - var/path = correct_legs[old_part.body_zone] - if(!path) - continue - var/obj/item/bodypart/new_part = new path() - new_part.replace_limb(target, TRUE) - new_part.update_limb(is_creating = TRUE) - qdel(old_part) - -/datum/preference/choiced/lizard_legs/is_accessible(datum/preferences/preferences) - if(!..()) - return FALSE - var/datum/species/species_type = preferences.read_preference(/datum/preference/choiced/species) - return initial(species_type.digitigrade_customization) == DIGITIGRADE_OPTIONAL - - -/datum/preference/choiced/lizard_legs/is_accessible(datum/preferences/preferences) - . = ..() - - if(!.) - return - - var/datum/species/species_type = preferences.read_preference(/datum/preference/choiced/species) - - return initial(species_type.digitigrade_customization) & DIGITIGRADE_OPTIONAL /datum/preference/choiced/lizard_snout savefile_key = "feature_lizard_snout" @@ -160,7 +122,7 @@ savefile_key = "feature_lizard_spines" savefile_identifier = PREFERENCE_CHARACTER category = PREFERENCE_CATEGORY_SECONDARY_FEATURES - relevant_external_organ = /obj/item/organ/external/spines + relevant_mutant_bodypart = "spines" /datum/preference/choiced/lizard_spines/init_possible_values() return assoc_to_keys_features(SSaccessories.spines_list) diff --git a/code/modules/client/preferences/species_features/mushperson.dm b/code/modules/client/preferences/species_features/mushperson.dm index 42ff286e7d1..2ed58713079 100644 --- a/code/modules/client/preferences/species_features/mushperson.dm +++ b/code/modules/client/preferences/species_features/mushperson.dm @@ -3,7 +3,7 @@ savefile_key = "feature_mushperson_cap" savefile_identifier = PREFERENCE_CHARACTER category = PREFERENCE_CATEGORY_SECONDARY_FEATURES - relevant_external_organ = /obj/item/organ/external/mushroom_cap + relevant_mutant_bodypart = "cap" /datum/preference/choiced/mushroom_cap/init_possible_values() return assoc_to_keys_features(SSaccessories.caps_list) diff --git a/code/modules/experisci/experiment/experiments.dm b/code/modules/experisci/experiment/experiments.dm index c9f4f1b3d1b..1ec229cd1cd 100644 --- a/code/modules/experisci/experiment/experiments.dm +++ b/code/modules/experisci/experiment/experiments.dm @@ -387,7 +387,7 @@ if (organ.type == target_species.get_mutant_organ_type_for_slot(organ.slot)) continue else - if ((organ.type in target_species.mutant_organs)) + if ((organ.type in target_species.mutant_organs) || (organ.type in target_species.external_organs)) continue return TRUE return FALSE 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 4b07baaa058..ec484ebe6eb 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/mob_insert(mob/living/carbon/receiver, special, movement_flags) +/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/mining/equipment/monster_organs/monster_organ.dm b/code/modules/mining/equipment/monster_organs/monster_organ.dm index 3dda7380aef..a854f113740 100644 --- a/code/modules/mining/equipment/monster_organs/monster_organ.dm +++ b/code/modules/mining/equipment/monster_organs/monster_organ.dm @@ -36,6 +36,7 @@ icon = 'icons/obj/medical/organs/mining_organs.dmi' icon_state = "hivelord_core" actions_types = list(/datum/action/cooldown/monster_core_action) + visual = FALSE item_flags = NOBLUDGEON slot = ORGAN_SLOT_MONSTER_CORE organ_flags = ORGAN_ORGANIC @@ -65,9 +66,10 @@ deltimer(decay_timer) return ..() -/obj/item/organ/internal/monster_core/mob_insert(mob/living/carbon/target_carbon, special = FALSE, movement_flags) +/obj/item/organ/internal/monster_core/Insert(mob/living/carbon/target_carbon, special = FALSE, movement_flags) . = ..() - + if(!.) + return if (inert) to_chat(target_carbon, span_notice("[src] breaks down as you try to insert it.")) qdel(src) @@ -78,7 +80,7 @@ target_carbon.visible_message(span_notice("[src] stabilizes as it's inserted.")) return TRUE -/obj/item/organ/internal/monster_core/mob_remove(mob/living/carbon/target_carbon, special, movement_flags) +/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/lavaland/tendril_loot.dm b/code/modules/mining/lavaland/tendril_loot.dm index 8aeceaf6916..92c9059565c 100644 --- a/code/modules/mining/lavaland/tendril_loot.dm +++ b/code/modules/mining/lavaland/tendril_loot.dm @@ -557,6 +557,7 @@ var/obj/item/organ/external/wings/functional/wings = get_wing_choice(exposed_human, chest) wings = new wings() wings.Insert(exposed_human) + exposed_human.dna.species.handle_mutant_bodyparts(exposed_human) playsound(exposed_human.loc, 'sound/items/poster_ripped.ogg', 50, TRUE, -1) exposed_human.apply_damage(20, def_zone = BODY_ZONE_CHEST, forced = TRUE, wound_bonus = CANT_WOUND) exposed_human.emote("scream") diff --git a/code/modules/mob/living/carbon/alien/organs.dm b/code/modules/mob/living/carbon/alien/organs.dm index 3c063aec7e7..9303cd23474 100644 --- a/code/modules/mob/living/carbon/alien/organs.dm +++ b/code/modules/mob/living/carbon/alien/organs.dm @@ -1,5 +1,6 @@ /obj/item/organ/internal/alien icon_state = "acid" + visual = FALSE food_reagents = list(/datum/reagent/consumable/nutriment = 5, /datum/reagent/toxin/acid = 10) /obj/item/organ/internal/alien/plasmavessel @@ -221,11 +222,11 @@ stomach_contents -= source UnregisterSignal(source, list(COMSIG_MOVABLE_MOVED, COMSIG_LIVING_DEATH, COMSIG_QDELETING)) -/obj/item/organ/internal/stomach/alien/mob_insert(mob/living/carbon/stomach_owner, special, movement_flags) +/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/mob_remove(mob/living/carbon/stomach_owner, special, movement_flags) +/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_update_icons.dm b/code/modules/mob/living/carbon/carbon_update_icons.dm index e7a5b097592..05192c8918a 100644 --- a/code/modules/mob/living/carbon/carbon_update_icons.dm +++ b/code/modules/mob/living/carbon/carbon_update_icons.dm @@ -53,8 +53,13 @@ overlays_standing[cache_index] = null SEND_SIGNAL(src, COMSIG_CARBON_REMOVE_OVERLAY, cache_index, I) +//used when putting/removing clothes that hide certain mutant body parts to just update those and not update the whole body. +/mob/living/carbon/human/proc/update_mutant_bodyparts() + dna?.species.handle_mutant_bodyparts(src) + update_body_parts() + /mob/living/carbon/update_body(is_creating = FALSE) - dna?.species.handle_body(src) + dna?.species.handle_body(src) //This calls `handle_mutant_bodyparts` which calls `update_mutant_bodyparts()`. Don't double call! update_body_parts(is_creating) /mob/living/carbon/on_changed_z_level(turf/old_turf, turf/new_turf, same_z_layer, notify_contents) diff --git a/code/modules/mob/living/carbon/human/_species.dm b/code/modules/mob/living/carbon/human/_species.dm index c345696cd05..893df377006 100644 --- a/code/modules/mob/living/carbon/human/_species.dm +++ b/code/modules/mob/living/carbon/human/_species.dm @@ -80,8 +80,10 @@ GLOBAL_LIST_EMPTY(features_by_species) BODY_ZONE_R_LEG = /obj/item/bodypart/leg/right, BODY_ZONE_CHEST = /obj/item/bodypart/chest, ) - ///Internal organs that are unique to this race, like a tail or other cosmetic organs. list(typepath of organ 1, typepath of organ 2 = "Round"). + ///Internal organs that are unique to this race, like a tail. list(typepath of organ 1, typepath of organ 2) var/list/mutant_organs = list() + ///List of external organs to generate like horns, frills, wings, etc. list(typepath of organ = "Round Beautiful BDSM Snout"). Still WIP + var/list/external_organs = list() ///Replaces default brain with a different organ var/obj/item/organ/internal/brain/mutantbrain = /obj/item/organ/internal/brain ///Replaces default heart with a different organ @@ -282,10 +284,7 @@ GLOBAL_LIST_EMPTY(features_by_species) if(ORGAN_SLOT_STOMACH) return mutantstomach else - // Non-standard organs we might have - for(var/obj/item/organ/extra_organ as anything in mutant_organs) - if(initial(extra_organ.slot) == slot) - return extra_organ + CRASH("Invalid organ slot [slot]") /** * Corrects organs in a carbon, removing ones it doesn't need and adding ones it does. @@ -301,33 +300,46 @@ GLOBAL_LIST_EMPTY(features_by_species) * * visual_only - boolean, only load organs that change how the species looks. Do not use for normal gameplay stuff */ /datum/species/proc/regenerate_organs(mob/living/carbon/organ_holder, datum/species/old_species, replace_current = TRUE, list/excluded_zones, visual_only = FALSE) - for(var/slot in get_all_slots()) + //what should be put in if there is no mutantorgan (brains handled separately) + var/list/organ_slots = list( + ORGAN_SLOT_BRAIN, + ORGAN_SLOT_HEART, + ORGAN_SLOT_LUNGS, + ORGAN_SLOT_APPENDIX, + ORGAN_SLOT_EYES, + ORGAN_SLOT_EARS, + ORGAN_SLOT_TONGUE, + ORGAN_SLOT_LIVER, + ORGAN_SLOT_STOMACH, + ) + + for(var/slot in organ_slots) var/obj/item/organ/existing_organ = organ_holder.get_organ_slot(slot) var/obj/item/organ/new_organ = get_mutant_organ_type_for_slot(slot) - var/old_organ_type = old_species?.get_mutant_organ_type_for_slot(slot) - // if we have an extra organ that before changing that the species didnt have, remove it - if(!new_organ) - if(existing_organ && (old_organ_type == existing_organ.type || replace_current)) - existing_organ.Remove(organ_holder) + if(isnull(new_organ)) // if they aren't suppose to have an organ here, remove it + if(existing_organ) + existing_organ.Remove(organ_holder, special = TRUE) qdel(existing_organ) continue - if(existing_organ) - // we dont want to remove organs that were not from the old species (such as from freak surgery or prosthetics) - if(existing_organ.type != old_organ_type && !replace_current && !remove_features) // SKYRAT EDIT - Fixes certain species lacking a tongue (Looks at abductor) + // we don't want to remove organs that are not the default for this species + if(!isnull(existing_organ) && !remove_features) // SKYRAT EDIT - Fixes certain species lacking a tongue (Looks at abductor) + if(!isnull(old_species) && existing_organ.type != old_species.get_mutant_organ_type_for_slot(slot)) + continue + else if(!replace_current && existing_organ.type != get_mutant_organ_type_for_slot(slot)) continue - // we don't want to remove organs that are the same as the new one - if(existing_organ.type == new_organ) - continue + // at this point we already know new_organ is not null + if(existing_organ?.type == new_organ) + continue // we don't want to remove organs that are the same as the new one - if(visual_only && (!initial(new_organ.bodypart_overlay) && !initial(new_organ.visual))) + if(visual_only && !initial(new_organ.visual)) continue var/used_neworgan = FALSE new_organ = SSwardrobe.provide_type(new_organ) - var/should_have = new_organ.get_availability(src, organ_holder) && should_visual_organ_apply_to(new_organ, organ_holder) + var/should_have = new_organ.get_availability(src, organ_holder) // Check for an existing organ, and if there is one check to see if we should remove it var/health_pct = 1 @@ -351,6 +363,46 @@ GLOBAL_LIST_EMPTY(features_by_species) if(!used_neworgan) QDEL_NULL(new_organ) + if(!isnull(old_species)) + for(var/mutant_organ in old_species.mutant_organs) + if(mutant_organ in mutant_organs) + continue // need this mutant organ, but we already have it! + + var/obj/item/organ/current_organ = organ_holder.get_organ_by_type(mutant_organ) + if(current_organ) + current_organ.Remove(organ_holder) + QDEL_NULL(current_organ) + + for(var/obj/item/organ/external/external_organ in organ_holder.organs) + // External organ checking. We need to check the external organs owned by the carbon itself, + // because we want to also remove ones not shared by its species. + // This should be done even if species was not changed. + if(external_organ in external_organs) + continue // Don't remove external organs this species is supposed to have. + + external_organ.Remove(organ_holder) + QDEL_NULL(external_organ) + + var/list/species_organs = mutant_organs + external_organs + for(var/organ_path in species_organs) + var/obj/item/organ/current_organ = organ_holder.get_organ_by_type(organ_path) + if(ispath(organ_path, /obj/item/organ/external) && !should_external_organ_apply_to(organ_path, organ_holder)) + if(!isnull(current_organ) && replace_current) + // if we have an organ here and we're replacing organs, remove it + current_organ.Remove(organ_holder) + QDEL_NULL(current_organ) + continue + + if(!current_organ || replace_current) + var/obj/item/organ/replacement = SSwardrobe.provide_type(organ_path) + // If there's an existing mutant organ, we're technically replacing it. + // Let's abuse the snowflake proc that skillchips added. Basically retains + // feature parity with every other organ too. + 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, 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_equipped_items(INCLUDE_POCKETS)) var/equipped_item_slot = wearer.get_slot_by_item(equipped_item) @@ -392,7 +444,7 @@ GLOBAL_LIST_EMPTY(features_by_species) if(old_species.type != type) replace_body(human_who_gained_species, src) - regenerate_organs(human_who_gained_species, old_species, replace_current = FALSE, visual_only = human_who_gained_species.visual_only_organs) + regenerate_organs(human_who_gained_species, old_species, visual_only = human_who_gained_species.visual_only_organs) // Drop the items the new species can't wear INVOKE_ASYNC(src, PROC_REF(worn_items_fit_body_check), human_who_gained_species, TRUE) @@ -408,6 +460,16 @@ GLOBAL_LIST_EMPTY(features_by_species) //Resets blood if it is excessively high so they don't gib normalize_blood(human_who_gained_species) + if(ishuman(human_who_gained_species)) + var/mob/living/carbon/human/human = human_who_gained_species + for(var/obj/item/organ/external/organ_path as anything in external_organs) + if(!should_external_organ_apply_to(organ_path, human)) + continue + + //Load a persons preferences from DNA + var/obj/item/organ/external/new_organ = SSwardrobe.provide_type(organ_path) + new_organ.Insert(human, special=TRUE, movement_flags = DELETE_IF_REPLACED) + //add_body_markings(human_who_gained_species) // SKYRAT EDIT REMOVAL - We do this differently if(length(inherent_traits)) @@ -448,6 +510,10 @@ GLOBAL_LIST_EMPTY(features_by_species) for(var/X in inherent_traits) REMOVE_TRAIT(C, X, SPECIES_TRAIT) + for(var/obj/item/organ/external/organ in C.organs) + organ.Remove(C) + qdel(organ) + //If their inert mutation is not the same, swap it out if((inert_mutation != new_species.inert_mutation) && LAZYLEN(C.dna.mutation_index) && (inert_mutation in C.dna.mutation_index)) C.dna.remove_mutation(inert_mutation) @@ -481,6 +547,7 @@ GLOBAL_LIST_EMPTY(features_by_species) * Handles the body of a human * * Handles lipstick, having no eyes, eye color, undergarnments like underwear, undershirts, and socks, and body layers. + * Calls [handle_mutant_bodyparts][/datum/species/proc/handle_mutant_bodyparts] * Arguments: * * species_human - Human, whoever we're handling the body for */ @@ -489,7 +556,7 @@ GLOBAL_LIST_EMPTY(features_by_species) /datum/species/proc/handle_body(mob/living/carbon/human/species_human) species_human.remove_overlay(BODY_LAYER) if(HAS_TRAIT(species_human, TRAIT_INVISIBLE_MAN)) - return + return handle_mutant_bodyparts(species_human) var/list/standing = list() if(!HAS_TRAIT(species_human, TRAIT_HUSK)) @@ -534,7 +601,105 @@ GLOBAL_LIST_EMPTY(features_by_species) species_human.overlays_standing[BODY_LAYER] = standing species_human.apply_overlay(BODY_LAYER) - update_body_markings(species_human) + handle_mutant_bodyparts(species_human) + + + +/** + * Handles the mutant bodyparts of a human + * + * Handles the adding and displaying of, layers, colors, and overlays of mutant bodyparts and accessories. + * Handles digitigrade leg displaying and squishing. + * Arguments: + * * H - Human, whoever we're handling the body for + * * forced_colour - The forced color of an accessory. Leave null to use mutant color. + */ +/datum/species/proc/handle_mutant_bodyparts(mob/living/carbon/human/source, forced_colour) + var/list/bodyparts_to_add = mutant_bodyparts.Copy() + var/list/relevent_layers = list(BODY_BEHIND_LAYER, BODY_ADJ_LAYER, BODY_FRONT_LAYER) + var/list/standing = list() + + source.remove_overlay(BODY_BEHIND_LAYER) + source.remove_overlay(BODY_ADJ_LAYER) + source.remove_overlay(BODY_FRONT_LAYER) + + if(!mutant_bodyparts || HAS_TRAIT(source, TRAIT_INVISIBLE_MAN)) + return + + var/obj/item/bodypart/head/noggin = source.get_bodypart(BODY_ZONE_HEAD) + + + if(mutant_bodyparts["ears"]) + if(!source.dna.features["ears"] || source.dna.features["ears"] == "None" || source.head && (source.head.flags_inv & HIDEHAIR) || (source.wear_mask && (source.wear_mask.flags_inv & HIDEHAIR)) || !noggin || IS_ROBOTIC_LIMB(noggin)) + bodyparts_to_add -= "ears" + + if(!bodyparts_to_add) + return + + var/g = (source.physique == FEMALE) ? "f" : "m" + + for(var/layer in relevent_layers) + var/layertext = mutant_bodyparts_layertext(layer) + + for(var/bodypart in bodyparts_to_add) + var/datum/sprite_accessory/accessory + switch(bodypart) + if("ears") + accessory = SSaccessories.ears_list[source.dna.features["ears"]] + if("legs") + accessory = SSaccessories.legs_list[source.dna.features["legs"]] + + if(!accessory || accessory.icon_state == "none") + continue + + var/mutable_appearance/accessory_overlay = mutable_appearance(accessory.icon, layer = -layer) + + if(accessory.gender_specific) + accessory_overlay.icon_state = "[g]_[bodypart]_[accessory.icon_state]_[layertext]" + else + accessory_overlay.icon_state = "m_[bodypart]_[accessory.icon_state]_[layertext]" + + if(accessory.em_block) + accessory_overlay.overlays += emissive_blocker(accessory_overlay.icon, accessory_overlay.icon_state, source, accessory_overlay.alpha) + + if(accessory.center) + accessory_overlay = center_image(accessory_overlay, accessory.dimension_x, accessory.dimension_y) + + if(!(HAS_TRAIT(source, TRAIT_HUSK))) + if(!forced_colour) + switch(accessory.color_src) + if(MUTANT_COLOR) + accessory_overlay.color = fixed_mut_color || source.dna.features["mcolor"] + if(HAIR_COLOR) + accessory_overlay.color = get_fixed_hair_color(source) || source.hair_color + if(FACIAL_HAIR_COLOR) + accessory_overlay.color = get_fixed_hair_color(source) || source.facial_hair_color + if(EYE_COLOR) + accessory_overlay.color = source.eye_color_left + else + accessory_overlay.color = forced_colour + standing += accessory_overlay + + if(accessory.hasinner) + var/mutable_appearance/inner_accessory_overlay = mutable_appearance(accessory.icon, layer = -layer) + if(accessory.gender_specific) + inner_accessory_overlay.icon_state = "[g]_[bodypart]inner_[accessory.icon_state]_[layertext]" + else + inner_accessory_overlay.icon_state = "m_[bodypart]inner_[accessory.icon_state]_[layertext]" + + if(accessory.center) + inner_accessory_overlay = center_image(inner_accessory_overlay, accessory.dimension_x, accessory.dimension_y) + + standing += inner_accessory_overlay + + source.overlays_standing[layer] = standing.Copy() + standing = list() + + source.apply_overlay(BODY_BEHIND_LAYER) + source.apply_overlay(BODY_ADJ_LAYER) + source.apply_overlay(BODY_FRONT_LAYER) + + update_body_markings(source) */ //SKYRAT EDIT REMOVAL END @@ -586,9 +751,7 @@ GLOBAL_LIST_EMPTY(features_by_species) var/list/new_features = list() var/static/list/organs_to_randomize = list() - for(var/obj/item/organ/organ_path as anything in mutant_organs) - if(!organ_path.bodypart_overlay) - continue + for(var/obj/item/organ/external/organ_path as anything in external_organs) var/overlay_path = initial(organ_path.bodypart_overlay) var/datum/bodypart_overlay/mutant/sample_overlay = organs_to_randomize[overlay_path] if(isnull(sample_overlay)) @@ -1443,14 +1606,15 @@ GLOBAL_LIST_EMPTY(features_by_species) var/datum/preference/preference = GLOB.preference_entries[preference_type] if ( \ - (preference.relevant_inherent_trait in inherent_traits) \ - || (preference.relevant_external_organ in mutant_organs) \ + (preference.relevant_mutant_bodypart in mutant_bodyparts) \ + || (preference.relevant_inherent_trait in inherent_traits) \ + || (preference.relevant_external_organ in external_organs) \ || (preference.relevant_head_flag && check_head_flags(preference.relevant_head_flag)) \ || (preference.relevant_body_markings in body_markings) \ ) features += preference.savefile_key - for (var/obj/item/organ/organ_type as anything in mutant_organs) + for (var/obj/item/organ/external/organ_type as anything in external_organs) var/preference = initial(organ_type.preference) if (!isnull(preference)) features += preference @@ -1496,7 +1660,7 @@ GLOBAL_LIST_EMPTY(features_by_species) /datum/species/proc/get_types_to_preload() var/list/to_store = list() to_store += mutant_organs - for(var/obj/item/organ/horny as anything in mutant_organs) + for(var/obj/item/organ/external/horny as anything in external_organs) to_store += horny //Haha get it? //Don't preload brains, cause reuse becomes a horrible headache @@ -2108,10 +2272,6 @@ GLOBAL_LIST_EMPTY(features_by_species) /// Update the overlays if necessary /datum/species/proc/update_body_markings(mob/living/carbon/human/hooman) - if(HAS_TRAIT(hooman, TRAIT_INVISIBLE_MAN)) - remove_body_markings(hooman) - return - var/needs_update = FALSE for(var/datum/bodypart_overlay/simple/body_marking/marking as anything in body_markings) if(initial(marking.dna_feature_key) == body_markings[marking]) // dna is same as our species (sort of mini-cache), so no update needed diff --git a/code/modules/mob/living/carbon/human/human_update_icons.dm b/code/modules/mob/living/carbon/human/human_update_icons.dm index c46d3a26d69..06c0a3f12b2 100644 --- a/code/modules/mob/living/carbon/human/human_update_icons.dm +++ b/code/modules/mob/living/carbon/human/human_update_icons.dm @@ -161,8 +161,7 @@ There are several things that need to be remembered: overlays_standing[UNIFORM_LAYER] = uniform_overlay apply_overlay(UNIFORM_LAYER) - update_body_parts() - apply_overlay(UNIFORM_LAYER) + update_mutant_bodyparts() /mob/living/carbon/human/update_worn_id(update_obscured = TRUE) remove_overlay(ID_LAYER) @@ -591,8 +590,11 @@ There are several things that need to be remembered: // SKYRAT EDIT END overlays_standing[SUIT_LAYER] = suit_overlay update_body_parts() + update_mutant_bodyparts() + apply_overlay(SUIT_LAYER) + /mob/living/carbon/human/update_pockets() if(client && hud_used) var/atom/movable/screen/inventory/inv @@ -660,7 +662,7 @@ There are several things that need to be remembered: overlays_standing[FACEMASK_LAYER] = mask_overlay apply_overlay(FACEMASK_LAYER) - update_body_parts() //e.g. upgate needed because mask now hides lizard snout + update_mutant_bodyparts() //e.g. upgate needed because mask now hides lizard snout /mob/living/carbon/human/update_worn_back(update_obscured = TRUE) remove_overlay(BACK_LAYER) diff --git a/code/modules/mob/living/carbon/human/species_types/dullahan.dm b/code/modules/mob/living/carbon/human/species_types/dullahan.dm index d4dea2abfcc..1d7c328f882 100644 --- a/code/modules/mob/living/carbon/human/species_types/dullahan.dm +++ b/code/modules/mob/living/carbon/human/species_types/dullahan.dm @@ -19,6 +19,7 @@ BODY_ZONE_CHEST = /obj/item/bodypart/chest, ) inherent_biotypes = MOB_UNDEAD|MOB_HUMANOID + mutant_bodyparts = list("wings" = "None") mutantbrain = /obj/item/organ/internal/brain/dullahan mutanteyes = /obj/item/organ/internal/eyes/dullahan mutanttongue = /obj/item/organ/internal/tongue/dullahan 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 e969461ca13..b4ea6c3f2ad 100644 --- a/code/modules/mob/living/carbon/human/species_types/felinid.dm +++ b/code/modules/mob/living/carbon/human/species_types/felinid.dm @@ -161,7 +161,7 @@ // stored_feature_id is only set once (the first time an organ is inserted), so this should be safe. var/obj/item/organ/internal/ears/cat/kitty_ears = new kitty_ears.Insert(soon_to_be_felinid, special = TRUE, movement_flags = DELETE_IF_REPLACED) - if(should_visual_organ_apply_to(/obj/item/organ/external/tail/cat, soon_to_be_felinid)) //only give them a tail if they actually have sprites for it / are a compatible subspecies. + if(should_external_organ_apply_to(/obj/item/organ/external/tail/cat, soon_to_be_felinid)) //only give them a tail if they actually have sprites for it / are a compatible subspecies. var/obj/item/organ/external/tail/cat/kitty_tail = new kitty_tail.Insert(soon_to_be_felinid, special = TRUE, movement_flags = DELETE_IF_REPLACED) @@ -184,8 +184,8 @@ old_tail.Remove(purrbated_human, special = TRUE) qdel(old_tail) // Locate does not work on assoc lists, so we do it by hand - for(var/external_organ in target_species.mutant_organs) - if(!should_visual_organ_apply_to(external_organ, purrbated_human)) + for(var/external_organ in target_species.external_organs) + if(!should_external_organ_apply_to(external_organ, purrbated_human)) continue if(ispath(external_organ, /obj/item/organ/external/tail)) var/obj/item/organ/external/tail/new_tail = new external_organ() 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 1ca2979d3d6..3f2a1752c73 100644 --- a/code/modules/mob/living/carbon/human/species_types/monkeys.dm +++ b/code/modules/mob/living/carbon/human/species_types/monkeys.dm @@ -3,7 +3,7 @@ /datum/species/monkey name = "\improper Monkey" id = SPECIES_MONKEY - mutant_organs = list( + external_organs = list( /obj/item/organ/external/tail/monkey = "Monkey", ) mutanttongue = /obj/item/organ/internal/tongue/monkey diff --git a/code/modules/mob/living/carbon/human/species_types/mothmen.dm b/code/modules/mob/living/carbon/human/species_types/mothmen.dm index 0e4c6679ad5..37bbfd9d5bf 100644 --- a/code/modules/mob/living/carbon/human/species_types/mothmen.dm +++ b/code/modules/mob/living/carbon/human/species_types/mothmen.dm @@ -24,6 +24,12 @@ BODY_ZONE_R_LEG = /obj/item/bodypart/leg/right/moth, ) +/datum/species/moth/regenerate_organs(mob/living/carbon/C, datum/species/old_species, replace_current= TRUE, list/excluded_zones, visual_only) + . = ..() + if(ishuman(C)) + var/mob/living/carbon/human/H = C + handle_mutant_bodyparts(H) + /datum/species/moth/on_species_gain(mob/living/carbon/human/human_who_gained_species, datum/species/old_species, pref_load) . = ..() RegisterSignal(human_who_gained_species, COMSIG_MOB_APPLY_DAMAGE_MODIFIERS, PROC_REF(damage_weakness)) diff --git a/code/modules/mob/living/carbon/human/species_types/mushpeople.dm b/code/modules/mob/living/carbon/human/species_types/mushpeople.dm index 9cf63ea0408..99eb0d756c8 100644 --- a/code/modules/mob/living/carbon/human/species_types/mushpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/mushpeople.dm @@ -6,7 +6,7 @@ fixed_mut_color = "#DBBF92" - mutant_organs = list(/obj/item/organ/external/mushroom_cap = "Round") + external_organs = list(/obj/item/organ/external/mushroom_cap = "Round") inherent_traits = list( TRAIT_MUTANT_COLORS, 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 d3dfb813520..111b35cb7f7 100644 --- a/code/modules/mob/living/carbon/human/species_types/vampire.dm +++ b/code/modules/mob/living/carbon/human/species_types/vampire.dm @@ -17,6 +17,7 @@ TRAIT_NO_MIRROR_REFLECTION, ) inherent_biotypes = MOB_UNDEAD|MOB_HUMANOID + mutant_bodyparts = list("wings" = "None") changesource_flags = MIRROR_BADMIN | WABBAJACK | ERT_SPAWN exotic_bloodtype = "U" blood_deficiency_drain_rate = BLOOD_DEFICIENCY_MODIFIER // vampires already passively lose blood, so this just makes them lose it slightly more quickly when they have blood deficiency. diff --git a/code/modules/mod/modules/modules_medical.dm b/code/modules/mod/modules/modules_medical.dm index 0f445702017..a74a5cfa4ca 100644 --- a/code/modules/mod/modules/modules_medical.dm +++ b/code/modules/mod/modules/modules_medical.dm @@ -225,7 +225,8 @@ organ_evacced.Remove(target, special = TRUE) organ_evacced.forceMove(get_turf(target)) - organ.Insert(target) + if (!organ.Insert(target)) + organ.forceMove(drop_location()) organ = null ///Patrient Transport - Generates hardlight bags you can put people in. diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm index b4f0515359a..25421cd4568 100644 --- a/code/modules/surgery/bodyparts/_bodyparts.dm +++ b/code/modules/surgery/bodyparts/_bodyparts.dm @@ -991,7 +991,7 @@ aux_zone_markings = LAZYCOPY(owner_species.body_markings[aux_zone]) markings_alpha = owner_species.markings_alpha // SKYRAT EDIT END - recolor_bodypart_overlays() + recolor_external_organs() return TRUE //to update the bodypart's icon when not attached to a mob @@ -1369,7 +1369,7 @@ QDEL_NULL(current_gauze) ///Loops through all of the bodypart's external organs and update's their color. -/obj/item/bodypart/proc/recolor_bodypart_overlays() +/obj/item/bodypart/proc/recolor_external_organs() for(var/datum/bodypart_overlay/mutant/overlay in bodypart_overlays) overlay.inherit_color(src, force = TRUE) diff --git a/code/modules/surgery/bodyparts/dismemberment.dm b/code/modules/surgery/bodyparts/dismemberment.dm index 44682189bde..60f564a6603 100644 --- a/code/modules/surgery/bodyparts/dismemberment.dm +++ b/code/modules/surgery/bodyparts/dismemberment.dm @@ -406,12 +406,12 @@ qdel(phantom_loss) //Copied from /datum/species/proc/on_species_gain() - for(var/obj/item/organ/organ_path as anything in dna.species.mutant_organs) + for(var/obj/item/organ/external/organ_path as anything in dna.species.external_organs) //Load a persons preferences from DNA var/zone = initial(organ_path.zone) if(zone != limb_zone) continue - var/obj/item/organ/new_organ = SSwardrobe.provide_type(organ_path) + var/obj/item/organ/external/new_organ = SSwardrobe.provide_type(organ_path) new_organ.Insert(src) update_body_parts() diff --git a/code/modules/surgery/bodyparts/helpers.dm b/code/modules/surgery/bodyparts/helpers.dm index dec8efb154e..8833f87e28e 100644 --- a/code/modules/surgery/bodyparts/helpers.dm +++ b/code/modules/surgery/bodyparts/helpers.dm @@ -182,8 +182,8 @@ /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/organ in limb) - all_limb_flags |= organ.external_bodytypes + for(var/obj/item/organ/external/ext_organ in limb) + all_limb_flags |= ext_organ.external_bodytypes all_limb_flags |= limb.bodytype bodytype = all_limb_flags @@ -192,8 +192,8 @@ /mob/living/carbon/proc/synchronize_bodyshapes() var/all_limb_flags = NONE for(var/obj/item/bodypart/limb as anything in bodyparts) - for(var/obj/item/organ/organ in limb) - all_limb_flags |= organ.external_bodyshapes + for(var/obj/item/organ/external/ext_organ in limb) + all_limb_flags |= ext_organ.external_bodyshapes all_limb_flags |= limb.bodyshape bodyshape = all_limb_flags diff --git a/code/modules/surgery/organ_manipulation.dm b/code/modules/surgery/organ_manipulation.dm index b777a2101d6..59e0ded0a66 100644 --- a/code/modules/surgery/organ_manipulation.dm +++ b/code/modules/surgery/organ_manipulation.dm @@ -239,20 +239,22 @@ tool = tool.contents[1] target_organ = tool user.temporarilyRemoveItemFromInventory(target_organ, TRUE) - target_organ.Insert(target) - if(apparatus) - apparatus.icon_state = initial(apparatus.icon_state) - apparatus.desc = initial(apparatus.desc) - apparatus.cut_overlays() - display_results( - user, - target, - span_notice("You insert [tool] into [target]'s [target.parse_zone_with_bodypart(target_zone)]."), - span_notice("[user] inserts [tool] into [target]'s [target.parse_zone_with_bodypart(target_zone)]!"), - span_notice("[user] inserts something into [target]'s [target.parse_zone_with_bodypart(target_zone)]!"), - ) - display_pain(target, "Your [target.parse_zone_with_bodypart(target_zone)] throbs with pain as your new [tool.name] comes to life!") - target_organ.on_surgical_insertion(user, target, target_zone, tool) + if(target_organ.Insert(target)) + if(apparatus) + apparatus.icon_state = initial(apparatus.icon_state) + apparatus.desc = initial(apparatus.desc) + apparatus.cut_overlays() + display_results( + user, + target, + span_notice("You insert [tool] into [target]'s [target.parse_zone_with_bodypart(target_zone)]."), + span_notice("[user] inserts [tool] into [target]'s [target.parse_zone_with_bodypart(target_zone)]!"), + span_notice("[user] inserts something into [target]'s [target.parse_zone_with_bodypart(target_zone)]!"), + ) + display_pain(target, "Your [target.parse_zone_with_bodypart(target_zone)] throbs with pain as your new [tool.name] comes to life!") + target_organ.on_surgical_insertion(user, target, target_zone, tool) + else + target_organ.forceMove(target.loc) else if(current_type == "extract") if(target_organ && target_organ.owner == target) diff --git a/code/modules/surgery/organs/_organ.dm b/code/modules/surgery/organs/_organ.dm index 4d28b987abc..98d947793ef 100644 --- a/code/modules/surgery/organs/_organ.dm +++ b/code/modules/surgery/organs/_organ.dm @@ -1,3 +1,4 @@ + /obj/item/organ name = "organ" icon = 'icons/obj/medical/organs/organs.dmi' @@ -78,9 +79,6 @@ INITIALIZE_IMMEDIATE(/obj/item/organ) volume = reagent_vol,\ after_eat = CALLBACK(src, PROC_REF(OnEatFrom))) - if(bodypart_overlay) - setup_bodypart_overlay() - /obj/item/organ/Destroy() if(bodypart_owner && !owner && !QDELETED(bodypart_owner)) bodypart_remove(bodypart_owner) @@ -142,7 +140,7 @@ INITIALIZE_IMMEDIATE(/obj/item/organ) return /obj/item/organ/proc/on_life(seconds_per_tick, times_fired) - return + CRASH("Oh god oh fuck something is calling parent organ life") /obj/item/organ/examine(mob/user) . = ..() @@ -344,16 +342,3 @@ 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, movement_flags = DELETE_IF_REPLACED) - - -/// Get all possible organ slots by checking every organ, and then store it and give it whenever needed -/proc/get_all_slots() - var/static/list/all_organ_slots = list() - - if(!all_organ_slots.len) - for(var/obj/item/organ/an_organ as anything in subtypesof(/obj/item/organ)) - if(!initial(an_organ.slot)) - continue - all_organ_slots |= initial(an_organ.slot) - - return all_organ_slots diff --git a/code/modules/surgery/organs/external/_visual_organs.dm b/code/modules/surgery/organs/external/_visual_organs.dm deleted file mode 100644 index 3aa54f27418..00000000000 --- a/code/modules/surgery/organs/external/_visual_organs.dm +++ /dev/null @@ -1,309 +0,0 @@ -/* -System for drawing organs with overlays. These overlays are drawn directly on the bodypart, attached to a person or not -Works in tandem with the /datum/sprite_accessory datum to generate sprites -Unlike normal organs, we're actually inside a persons limbs at all times -*/ -/obj/item/organ - ///The overlay datum that actually draws stuff on the limb - var/datum/bodypart_overlay/mutant/bodypart_overlay - - /// The savefile_key of the preference this relates to. Used for the preferences UI. - var/preference - ///With what DNA block do we mutate in mutate_feature() ? For genetics - var/dna_block - - ///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 its icon with - var/use_mob_sprite_as_obj_sprite = FALSE - - ///Does this organ have any bodytypes to pass to its bodypart_owner? - var/external_bodytypes = NONE - ///Does this organ have any bodyshapes to pass to its bodypart_owner? - var/external_bodyshapes = 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 - - ///If not null, overrides the appearance with this sprite accessory datum - var/sprite_accessory_override - -/**accessory_type is optional if you havent set sprite_datums for the object, and is used mostly to generate sprite_datums from a persons DNA -* For _mob_sprite we make a distinction between "Round Snout" and "round". Round Snout is the name of the sprite datum, while "round" would be part of the sprite -* I'm sorry -*/ -/obj/item/organ/proc/setup_bodypart_overlay(accessory_type) - bodypart_overlay = new bodypart_overlay(src) - - accessory_type = accessory_type ? accessory_type : sprite_accessory_override - var/update_overlays = TRUE - if(accessory_type) - bodypart_overlay.set_appearance(accessory_type) - bodypart_overlay.imprint_on_next_insertion = FALSE - else if(loc) //we've been spawned into the world, and not in nullspace to be added to a limb (yes its fucking scuffed) - bodypart_overlay.randomize_appearance() - else - update_overlays = FALSE - - if(use_mob_sprite_as_obj_sprite && update_overlays) - update_appearance(UPDATE_OVERLAYS) - - if(restyle_flags) - RegisterSignal(src, COMSIG_ATOM_RESTYLE, PROC_REF(on_attempt_feature_restyle)) - -/// Some sanity checks, but mostly to check if the person has their preference/dna set to load -/proc/should_visual_organ_apply_to(obj/item/organ/organpath, mob/living/carbon/target) - if(!initial(organpath.bodypart_overlay)) - return TRUE - - if(isnull(organpath) || isnull(target)) - stack_trace("passed a null path or mob to 'should_visual_organ_apply_to'") - return FALSE - - var/datum/bodypart_overlay/mutant/bodypart_overlay = initial(organpath.bodypart_overlay) - var/feature_key = !isnull(bodypart_overlay) && initial(bodypart_overlay.feature_key) - if(isnull(feature_key)) - return TRUE - - if(target.dna.features[feature_key] != SPRITE_ACCESSORY_NONE) - return TRUE - return FALSE - -///Update our features after something changed our appearance -/obj/item/organ/proc/mutate_feature(features, mob/living/carbon/human/human) - if(!dna_block) - return - - var/list/feature_list = bodypart_overlay.get_global_feature_list() - - bodypart_overlay.set_appearance_from_name(feature_list[deconstruct_block(get_uni_feature_block(features, dna_block), feature_list.len)]) - -///If you need to change an external_organ for simple one-offs, use this. Pass the accessory type : /datum/accessory/something -/obj/item/organ/proc/simple_change_sprite(accessory_type) - var/datum/sprite_accessory/typed_accessory = accessory_type //we only take types for maintainability - - bodypart_overlay.set_appearance(typed_accessory) - - if(owner) //are we in a person? - owner.update_body_parts() - 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/update_overlays() - . = ..() - - if(!use_mob_sprite_as_obj_sprite) - return - - //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, bodypart_owner) - -///The horns of a lizard! -/obj/item/organ/external/horns - name = "horns" - desc = "Why do lizards even have horns? Well, this one obviously doesn't." - icon_state = "horns" - - zone = BODY_ZONE_HEAD - slot = ORGAN_SLOT_EXTERNAL_HORNS - - preference = "feature_lizard_horns" - dna_block = DNA_HORNS_BLOCK - restyle_flags = EXTERNAL_RESTYLE_ENAMEL - - bodypart_overlay = /datum/bodypart_overlay/mutant/horns - -/datum/bodypart_overlay/mutant/horns - layers = EXTERNAL_ADJACENT - feature_key = "horns" - -/datum/bodypart_overlay/mutant/horns/can_draw_on_bodypart(mob/living/carbon/human/human) - if((human.head?.flags_inv & HIDEHAIR) || (human.wear_mask?.flags_inv & HIDEHAIR)) - return FALSE - - return TRUE - -/datum/bodypart_overlay/mutant/horns/get_global_feature_list() - return SSaccessories.horns_list - -///The frills of a lizard (like weird fin ears) -/obj/item/organ/external/frills - name = "frills" - desc = "Ear-like external organs often seen on aquatic reptillians." - icon_state = "frills" - - zone = BODY_ZONE_HEAD - slot = ORGAN_SLOT_EXTERNAL_FRILLS - - preference = "feature_lizard_frills" - dna_block = DNA_FRILLS_BLOCK - restyle_flags = EXTERNAL_RESTYLE_FLESH - - bodypart_overlay = /datum/bodypart_overlay/mutant/frills - -/datum/bodypart_overlay/mutant/frills - layers = EXTERNAL_ADJACENT - feature_key = "frills" - -/datum/bodypart_overlay/mutant/frills/can_draw_on_bodypart(mob/living/carbon/human/human) - if(!(human.head?.flags_inv & HIDEEARS)) - return TRUE - return FALSE - -/datum/bodypart_overlay/mutant/frills/get_global_feature_list() - return SSaccessories.frills_list - -///Guess what part of the lizard this is? -/obj/item/organ/external/snout - name = "lizard snout" - desc = "Take a closer look at that snout!" - icon_state = "snout" - - zone = BODY_ZONE_HEAD - slot = ORGAN_SLOT_EXTERNAL_SNOUT - - preference = "feature_lizard_snout" - external_bodyshapes = BODYSHAPE_SNOUTED - - dna_block = DNA_SNOUT_BLOCK - restyle_flags = EXTERNAL_RESTYLE_FLESH - - bodypart_overlay = /datum/bodypart_overlay/mutant/snout - -/datum/bodypart_overlay/mutant/snout - layers = EXTERNAL_ADJACENT - feature_key = "snout" - -/datum/bodypart_overlay/mutant/snout/can_draw_on_bodypart(mob/living/carbon/human/human) - if(!(human.wear_mask?.flags_inv & HIDESNOUT) && !(human.head?.flags_inv & HIDESNOUT)) - return TRUE - return FALSE - -/datum/bodypart_overlay/mutant/snout/get_global_feature_list() - return SSaccessories.snouts_list - -///A moth's antennae -/obj/item/organ/external/antennae - name = "moth antennae" - desc = "A moths antennae. What is it telling them? What are they sensing?" - icon_state = "antennae" - - zone = BODY_ZONE_HEAD - slot = ORGAN_SLOT_EXTERNAL_ANTENNAE - - preference = "feature_moth_antennae" - dna_block = DNA_MOTH_ANTENNAE_BLOCK - restyle_flags = EXTERNAL_RESTYLE_FLESH - - bodypart_overlay = /datum/bodypart_overlay/mutant/antennae - - ///Are we burned? - var/burnt = FALSE - ///Store our old datum here for if our antennae are healed - var/original_sprite_datum - -/obj/item/organ/external/antennae/mob_insert(mob/living/carbon/receiver, special, movement_flags) - . = ..() - - 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/mob_remove(mob/living/carbon/organ_owner, special, movement_flags) - . = ..() - - 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) - SIGNAL_HANDLER - - if(!burnt && human.bodytemperature >= 800 && human.fire_stacks > 0) //do not go into the extremely hot light. you will not survive - to_chat(human, span_danger("Your precious antennae burn to a crisp!")) - - burn_antennae() - human.update_body_parts() - -///Burn our antennae off ;_; -/obj/item/organ/external/antennae/proc/burn_antennae() - var/datum/bodypart_overlay/mutant/antennae/antennae = bodypart_overlay - antennae.burnt = TRUE - burnt = TRUE - -///heal our antennae back up!! -/obj/item/organ/external/antennae/proc/heal_antennae(datum/source, heal_flags) - SIGNAL_HANDLER - - if(!burnt) - return - - if(heal_flags & (HEAL_LIMBS|HEAL_ORGANS)) - var/datum/bodypart_overlay/mutant/antennae/antennae = bodypart_overlay - antennae.burnt = FALSE - burnt = FALSE - -///Moth antennae datum, with full burning functionality -/datum/bodypart_overlay/mutant/antennae - layers = EXTERNAL_FRONT | EXTERNAL_BEHIND - feature_key = "moth_antennae" - ///Accessory datum of the burn sprite - var/datum/sprite_accessory/burn_datum = /datum/sprite_accessory/moth_antennae/burnt_off - ///Are we burned? If so we draw differently - var/burnt = FALSE - -/datum/bodypart_overlay/mutant/antennae/New() - . = ..() - - burn_datum = fetch_sprite_datum(burn_datum) //turn the path into the singleton instance - -/datum/bodypart_overlay/mutant/antennae/get_global_feature_list() - return SSaccessories.moth_antennae_list - -/datum/bodypart_overlay/mutant/antennae/get_base_icon_state() - return burnt ? burn_datum.icon_state : sprite_datum.icon_state - -///The leafy hair of a podperson -/obj/item/organ/external/pod_hair - name = "podperson hair" - desc = "Base for many-o-salads." - - zone = BODY_ZONE_HEAD - slot = ORGAN_SLOT_EXTERNAL_POD_HAIR - - preference = "feature_pod_hair" - use_mob_sprite_as_obj_sprite = TRUE - - dna_block = DNA_POD_HAIR_BLOCK - restyle_flags = EXTERNAL_RESTYLE_PLANT - - bodypart_overlay = /datum/bodypart_overlay/mutant/pod_hair - -///Podperson bodypart overlay, with special coloring functionality to render the flowers in the inverse color -/datum/bodypart_overlay/mutant/pod_hair - layers = EXTERNAL_FRONT|EXTERNAL_ADJACENT - feature_key = "pod_hair" - - ///This layer will be colored differently than the rest of the organ. So we can get differently colored flowers or something - var/color_swapped_layer = EXTERNAL_FRONT - ///The individual rgb colors are subtracted from this to get the color shifted layer - var/color_inverse_base = 255 - -/datum/bodypart_overlay/mutant/pod_hair/get_global_feature_list() - return SSaccessories.pod_hair_list - -/datum/bodypart_overlay/mutant/pod_hair/color_image(image/overlay, draw_layer, obj/item/bodypart/limb) - if(draw_layer != bitflag_to_layer(color_swapped_layer)) - return ..() - - if(draw_color) // can someone explain to me why draw_color is allowed to EVER BE AN EMPTY STRING - var/list/rgb_list = rgb2num(draw_color) - overlay.color = rgb(color_inverse_base - rgb_list[1], color_inverse_base - rgb_list[2], color_inverse_base - rgb_list[3]) //inversa da color - else - overlay.color = null - -/datum/bodypart_overlay/mutant/pod_hair/can_draw_on_bodypart(mob/living/carbon/human/human) - if((human.head?.flags_inv & HIDEHAIR) || (human.wear_mask?.flags_inv & HIDEHAIR)) - return FALSE - - return TRUE diff --git a/code/modules/surgery/organs/external/restyling.dm b/code/modules/surgery/organs/external/restyling.dm index f862d9e9c08..7d6be1b6d58 100644 --- a/code/modules/surgery/organs/external/restyling.dm +++ b/code/modules/surgery/organs/external/restyling.dm @@ -1,7 +1,7 @@ -//Contains a bunch of procs for different types, but in the end it just lets you restyle the bodypart overlay so thats why its here +//Contains a bunch of procs for different types, but in the end it just lets you restyle external_organs so thats why its here ///Helper proc to fetch a list of styles a player might want to restyle their features into during the round : returns list("Cabbage" = /datum/sprite_accessory/cabbage) -/obj/item/organ/proc/get_valid_restyles() +/obj/item/organ/external/proc/get_valid_restyles() var/list/valid_restyles valid_restyles = list() @@ -31,18 +31,18 @@ ///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/feature in contents) + for(var/obj/item/organ/external/feature in contents) if(feature.restyle_flags & restyle_type) valid_features.Add(feature) - var/obj/item/organ/target_organ + var/obj/item/organ/external/target_organ switch(LAZYLEN(valid_features)) if(1) target_organ = valid_features[1] if(2 to INFINITY) var/choose_options = list() var/name_to_organ = list() //literally so I dont have to loop again after someones made their choice - for(var/obj/item/organ/organ_choice as anything in valid_features) + for(var/obj/item/organ/external/organ_choice as anything in valid_features) choose_options[organ_choice.name] = image(organ_choice) name_to_organ[organ_choice.name] = organ_choice var/picked_option = show_radial_menu(trimmer, original_target, choose_options, radius = 38, require_near = TRUE) @@ -57,7 +57,7 @@ target_organ.attempt_feature_restyle(source, trimmer, original_target, body_zone, restyle_type, style_speed) ///Invoke async so we dont break signals -/obj/item/organ/proc/on_attempt_feature_restyle(atom/source, mob/living/trimmer, atom/movable/original_target, body_zone, restyle_type, style_speed) +/obj/item/organ/external/proc/on_attempt_feature_restyle(atom/source, mob/living/trimmer, atom/movable/original_target, body_zone, restyle_type, style_speed) SIGNAL_HANDLER if(restyle_flags & restyle_type) @@ -66,7 +66,7 @@ to_chat(trimmer, span_warning("This tool is incompatible with the [src.name]!")) ///Restyles the external organ from a list of valid options -/obj/item/organ/proc/attempt_feature_restyle(atom/source, mob/living/trimmer, atom/movable/original_target, body_zone, restyle_type, style_speed) +/obj/item/organ/external/proc/attempt_feature_restyle(atom/source, mob/living/trimmer, atom/movable/original_target, body_zone, restyle_type, style_speed) var/list/restyles = get_valid_restyles() var/new_style = tgui_input_list(trimmer, "Select a new style", "Grooming", restyles) @@ -80,4 +80,5 @@ span_notice("You successfully change [original_target == trimmer ? "your" : original_target.name + "'s"] [name].") ) + simple_change_sprite(restyles[new_style]) //turn name to type and pass it on diff --git a/code/modules/surgery/organs/external/spines.dm b/code/modules/surgery/organs/external/spines.dm index c7b49df959f..ade081030d0 100644 --- a/code/modules/surgery/organs/external/spines.dm +++ b/code/modules/surgery/organs/external/spines.dm @@ -14,13 +14,13 @@ bodypart_overlay = /datum/bodypart_overlay/mutant/spines -/obj/item/organ/external/spines/mob_insert(mob/living/carbon/receiver, special, movement_flags) +/obj/item/organ/external/spines/Insert(mob/living/carbon/receiver, special, movement_flags) // If we have a tail, attempt to add a tail spines overlay var/obj/item/organ/external/tail/our_tail = receiver.get_organ_slot(ORGAN_SLOT_EXTERNAL_TAIL) our_tail?.try_insert_tail_spines(our_tail.bodypart_owner) return ..() -/obj/item/organ/external/spines/mob_remove(mob/living/carbon/organ_owner, special, movement_flags) +/obj/item/organ/external/spines/Remove(mob/living/carbon/organ_owner, special, movement_flags) // If we have a tail, remove any tail spines overlay var/obj/item/organ/external/tail/our_tail = organ_owner.get_organ_slot(ORGAN_SLOT_EXTERNAL_TAIL) our_tail?.remove_tail_spines(our_tail.bodypart_owner) diff --git a/code/modules/surgery/organs/external/tails.dm b/code/modules/surgery/organs/external/tails.dm index 89ef9599d45..8116b200887 100644 --- a/code/modules/surgery/organs/external/tails.dm +++ b/code/modules/surgery/organs/external/tails.dm @@ -20,7 +20,7 @@ ///The overlay for tail spines, if any var/datum/bodypart_overlay/mutant/tail_spines/tail_spines_overlay -/obj/item/organ/external/tail/mob_insert(mob/living/carbon/receiver, special, movement_flags) +/obj/item/organ/external/tail/Insert(mob/living/carbon/receiver, special, movement_flags) . = ..() if(.) receiver.clear_mood_event("tail_lost") @@ -34,7 +34,7 @@ // If it's not your tail AND of different species, we are horrified if(IS_WEAKREF_OF(receiver, original_owner)) receiver.add_mood_event("tail_regained", /datum/mood_event/tail_regained_right) - else if(type in receiver.dna.species.mutant_organs) + else if(type in receiver.dna.species.external_organs) receiver.add_mood_event("tail_regained", /datum/mood_event/tail_regained_species) else receiver.add_mood_event("tail_regained", /datum/mood_event/tail_regained_wrong) @@ -87,7 +87,7 @@ organ_owner.clear_mood_event("tail_regained") - if(type in organ_owner.dna.species.mutant_organs) + if(type in organ_owner.dna.species.external_organs) organ_owner.add_mood_event("tail_lost", /datum/mood_event/tail_lost) organ_owner.add_mood_event("tail_balance_lost", /datum/mood_event/tail_balance_lost) diff --git a/code/modules/surgery/organs/external/wings/functional_wings.dm b/code/modules/surgery/organs/external/wings/functional_wings.dm index 61655be60cd..680226b859b 100644 --- a/code/modules/surgery/organs/external/wings/functional_wings.dm +++ b/code/modules/surgery/organs/external/wings/functional_wings.dm @@ -35,14 +35,15 @@ QDEL_NULL(fly) return ..() -/obj/item/organ/external/wings/functional/mob_insert(mob/living/carbon/receiver, special, movement_flags) +/obj/item/organ/external/wings/functional/Insert(mob/living/carbon/receiver, special, movement_flags) . = ..() - + if(!.) + return if(QDELETED(fly)) fly = new fly.Grant(receiver) -/obj/item/organ/external/wings/functional/mob_remove(mob/living/carbon/organ_owner, special, movement_flags) +/obj/item/organ/external/wings/functional/Remove(mob/living/carbon/organ_owner, special, movement_flags) . = ..() fly?.Remove(organ_owner) if(wings_open) diff --git a/code/modules/surgery/organs/internal/appendix/_appendix.dm b/code/modules/surgery/organs/internal/appendix/_appendix.dm index a75d700e1e5..83ed8da84ac 100644 --- a/code/modules/surgery/organs/internal/appendix/_appendix.dm +++ b/code/modules/surgery/organs/internal/appendix/_appendix.dm @@ -6,6 +6,7 @@ name = "appendix" icon_state = "appendix" base_icon_state = "appendix" + visual = FALSE zone = BODY_ZONE_PRECISE_GROIN slot = ORGAN_SLOT_APPENDIX food_reagents = list(/datum/reagent/consumable/nutriment = 5, /datum/reagent/toxin/bad_food = 5) diff --git a/code/modules/surgery/organs/internal/cyberimp/augments_eyes.dm b/code/modules/surgery/organs/internal/cyberimp/augments_eyes.dm index aa67fe0c08d..d4c4b57d75f 100644 --- a/code/modules/surgery/organs/internal/cyberimp/augments_eyes.dm +++ b/code/modules/surgery/organs/internal/cyberimp/augments_eyes.dm @@ -27,13 +27,14 @@ eye_owner.remove_traits(HUD_traits, ORGAN_TRAIT) balloon_alert(eye_owner, "hud enabled") -/obj/item/organ/internal/cyberimp/eyes/hud/mob_insert(mob/living/carbon/eye_owner, special = FALSE, movement_flags) +/obj/item/organ/internal/cyberimp/eyes/hud/Insert(mob/living/carbon/eye_owner, special = FALSE, movement_flags) . = ..() - + if(!.) + return eye_owner.add_traits(HUD_traits, ORGAN_TRAIT) toggled_on = TRUE -/obj/item/organ/internal/cyberimp/eyes/hud/mob_remove(mob/living/carbon/eye_owner, special, movement_flags) +/obj/item/organ/internal/cyberimp/eyes/hud/Remove(mob/living/carbon/eye_owner, special, movement_flags) . = ..() eye_owner.remove_traits(HUD_traits, ORGAN_TRAIT) toggled_on = FALSE diff --git a/code/modules/surgery/organs/internal/cyberimp/augments_internal.dm b/code/modules/surgery/organs/internal/cyberimp/augments_internal.dm index 6fa9924abc2..f71e29631b3 100644 --- a/code/modules/surgery/organs/internal/cyberimp/augments_internal.dm +++ b/code/modules/surgery/organs/internal/cyberimp/augments_internal.dm @@ -2,6 +2,7 @@ /obj/item/organ/internal/cyberimp name = "cybernetic implant" desc = "A state-of-the-art implant that improves a baseline's functionality." + visual = FALSE organ_flags = ORGAN_ROBOTIC failing_desc = "seems to be broken." var/implant_color = COLOR_WHITE diff --git a/code/modules/surgery/organs/internal/ears/_ears.dm b/code/modules/surgery/organs/internal/ears/_ears.dm index 53b95b54d9b..6bdf093dd47 100644 --- a/code/modules/surgery/organs/internal/ears/_ears.dm +++ b/code/modules/surgery/organs/internal/ears/_ears.dm @@ -4,6 +4,7 @@ desc = "There are three parts to the ear. Inner, middle and outer. Only one of these parts should be normally visible." zone = BODY_ZONE_HEAD slot = ORGAN_SLOT_EARS + visual = FALSE gender = PLURAL healing_factor = STANDARD_ORGAN_HEALING @@ -135,34 +136,32 @@ icon_state = "kitty" visual = TRUE damage_multiplier = 2 + // Keeps track of which cat ears sprite is associated with this. + var/variant = "Cat" - preference = "feature_human_ears" +/obj/item/organ/internal/ears/cat/Initialize(mapload, variant_pref) + . = ..() + if(variant_pref) + variant = variant_pref - dna_block = DNA_EARS_BLOCK +//SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION +/* +/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 + ear_owner.dna.features["ears"] = ear_owner.dna.species.mutant_bodyparts["ears"] = variant + ear_owner.dna.update_uf_block(DNA_EARS_BLOCK) + ear_owner.update_body() - bodypart_overlay = /datum/bodypart_overlay/mutant/cat_ears - -/// Bodypart overlay for the horrible cat ears -/datum/bodypart_overlay/mutant/cat_ears - layers = EXTERNAL_FRONT | EXTERNAL_ADJACENT - color_source = ORGAN_COLOR_HAIR - feature_key = "ears" - - /// We dont color the inner part, which is the front layer - var/colorless_layer = EXTERNAL_FRONT - -/datum/bodypart_overlay/mutant/cat_ears/get_global_feature_list() - return SSaccessories.ears_list - -/datum/bodypart_overlay/mutant/cat_ears/can_draw_on_bodypart(mob/living/carbon/human/human) - if((human.head?.flags_inv & HIDEHAIR) || (human.wear_mask?.flags_inv & HIDEHAIR)) - return FALSE - return TRUE - -/datum/bodypart_overlay/mutant/cat_ears/color_image(image/overlay, draw_layer, obj/item/bodypart/limb) - if(draw_layer != bitflag_to_layer(colorless_layer)) - return ..() - return overlay +/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 + ear_owner.dna.species.mutant_bodyparts -= "ears" + ear_owner.update_body() +*/ +//SKYRAT EDIT REMOVAL END /obj/item/organ/internal/ears/penguin name = "penguin ears" diff --git a/code/modules/surgery/organs/internal/eyes/_eyes.dm b/code/modules/surgery/organs/internal/eyes/_eyes.dm index fe21ba8daa5..5abc296fedb 100644 --- a/code/modules/surgery/organs/internal/eyes/_eyes.dm +++ b/code/modules/surgery/organs/internal/eyes/_eyes.dm @@ -53,18 +53,21 @@ var/native_fov = FOV_180_DEGREES //SKYRAT EDIT CHANGE - Original FOV_90_DEGREES -/obj/item/organ/internal/eyes/mob_insert(mob/living/carbon/receiver, special, movement_flags) +/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(receiver)) - var/mob/living/carbon/human/human_recipient = receiver + if(ishuman(eye_recipient)) + var/mob/living/carbon/human/human_recipient = eye_recipient old_eye_color_left = human_recipient.eye_color_left old_eye_color_right = human_recipient.eye_color_right . = ..() - receiver.cure_blind(NO_EYES) + if(!.) + return + + eye_recipient.cure_blind(NO_EYES) apply_damaged_eye_effects() - refresh(receiver, call_update = TRUE) + refresh(eye_recipient, call_update = TRUE) /// Refreshes the visuals of the eyes /// If call_update is TRUE, we also will call update_body @@ -97,32 +100,31 @@ if(call_update) affected_human.update_body() -/obj/item/organ/internal/eyes/mob_remove(mob/living/carbon/organ_owner, special, movement_flags) +/obj/item/organ/internal/eyes/Remove(mob/living/carbon/eye_owner, special, movement_flags) . = ..() - - if(ishuman(organ_owner)) - var/mob/living/carbon/human/human_owner = organ_owner + if(ishuman(eye_owner)) + var/mob/living/carbon/human/human_owner = eye_owner if(initial(eye_color_left)) human_owner.eye_color_left = old_eye_color_left if(initial(eye_color_right)) human_owner.eye_color_right = old_eye_color_right if(native_fov) - organ_owner.remove_fov_trait(type) + eye_owner.remove_fov_trait(type) if(!special) human_owner.update_body() // Cure blindness from eye damage - organ_owner.cure_blind(EYE_DAMAGE) - organ_owner.cure_nearsighted(EYE_DAMAGE) + eye_owner.cure_blind(EYE_DAMAGE) + eye_owner.cure_nearsighted(EYE_DAMAGE) // Eye blind and temp blind go to, even if this is a bit of cheesy way to clear blindness - organ_owner.remove_status_effect(/datum/status_effect/eye_blur) - organ_owner.remove_status_effect(/datum/status_effect/temporary_blindness) + eye_owner.remove_status_effect(/datum/status_effect/eye_blur) + eye_owner.remove_status_effect(/datum/status_effect/temporary_blindness) // Then become blind anyways (if not special) if(!special) - organ_owner.become_blind(NO_EYES) + eye_owner.become_blind(NO_EYES) - organ_owner.update_tint() - organ_owner.update_sight() + eye_owner.update_tint() + eye_owner.update_sight() is_emissive = FALSE // SKYRAT EDIT ADDITION #define OFFSET_X 1 @@ -449,7 +451,7 @@ 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/mob_insert(mob/living/carbon/eye_recipient, special = FALSE, movement_flags = DELETE_IF_REPLACED) +/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 diff --git a/code/modules/surgery/organs/internal/heart/_heart.dm b/code/modules/surgery/organs/internal/heart/_heart.dm index b0c3ea4840d..b0fac316ad3 100644 --- a/code/modules/surgery/organs/internal/heart/_heart.dm +++ b/code/modules/surgery/organs/internal/heart/_heart.dm @@ -3,6 +3,7 @@ desc = "I feel bad for the heartless bastard who lost this." icon_state = "heart-on" base_icon_state = "heart" + visual = FALSE zone = BODY_ZONE_CHEST slot = ORGAN_SLOT_HEART item_flags = NO_BLOOD_ON_ITEM diff --git a/code/modules/surgery/organs/internal/heart/heart_ethereal.dm b/code/modules/surgery/organs/internal/heart/heart_ethereal.dm index 3e853a965b1..bd30318a722 100644 --- a/code/modules/surgery/organs/internal/heart/heart_ethereal.dm +++ b/code/modules/surgery/organs/internal/heart/heart_ethereal.dm @@ -21,14 +21,15 @@ add_atom_colour(ethereal_color, FIXED_COLOUR_PRIORITY) update_appearance() -/obj/item/organ/internal/heart/ethereal/mob_insert(mob/living/carbon/heart_owner, special = FALSE, movement_flags) +/obj/item/organ/internal/heart/ethereal/Insert(mob/living/carbon/heart_owner, special = FALSE, movement_flags) . = ..() - + if(!.) + return RegisterSignal(heart_owner, COMSIG_MOB_STATCHANGE, PROC_REF(on_stat_change)) 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/mob_remove(mob/living/carbon/heart_owner, special, movement_flags) +/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 06488e5d7b1..9f933b6a2a8 100644 --- a/code/modules/surgery/organs/internal/liver/_liver.dm +++ b/code/modules/surgery/organs/internal/liver/_liver.dm @@ -7,6 +7,7 @@ name = "liver" desc = "Pairing suggestion: chianti and fava beans." icon_state = "liver" + visual = FALSE w_class = WEIGHT_CLASS_SMALL zone = BODY_ZONE_CHEST slot = ORGAN_SLOT_LIVER diff --git a/code/modules/surgery/organs/internal/lungs/_lungs.dm b/code/modules/surgery/organs/internal/lungs/_lungs.dm index 88ce26d66a9..47078bfc803 100644 --- a/code/modules/surgery/organs/internal/lungs/_lungs.dm +++ b/code/modules/surgery/organs/internal/lungs/_lungs.dm @@ -1,6 +1,7 @@ /obj/item/organ/internal/lungs name = "lungs" icon_state = "lungs" + visual = FALSE zone = BODY_ZONE_CHEST slot = ORGAN_SLOT_LUNGS gender = PLURAL @@ -153,16 +154,17 @@ 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/mob_insert(mob/living/carbon/receiver, special = FALSE, movement_flags) +/obj/item/organ/internal/lungs/Insert(mob/living/carbon/receiver, special = FALSE, movement_flags) . = ..() - + if(!.) + return . receiver.clear_alert(ALERT_NOT_ENOUGH_OXYGEN) receiver.clear_alert(ALERT_NOT_ENOUGH_CO2) receiver.clear_alert(ALERT_NOT_ENOUGH_NITRO) receiver.clear_alert(ALERT_NOT_ENOUGH_PLASMA) receiver.clear_alert(ALERT_NOT_ENOUGH_N2O) -/obj/item/organ/internal/lungs/mob_remove(mob/living/carbon/organ_owner, special, movement_flags) +/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 7650f0e20a6..db7134f48e6 100644 --- a/code/modules/surgery/organs/internal/stomach/_stomach.dm +++ b/code/modules/surgery/organs/internal/stomach/_stomach.dm @@ -5,6 +5,7 @@ name = "stomach" desc = "Onaka ga suite imasu." icon_state = "stomach" + visual = FALSE w_class = WEIGHT_CLASS_SMALL zone = BODY_ZONE_CHEST slot = ORGAN_SLOT_STOMACH @@ -246,11 +247,11 @@ disgusted.throw_alert(ALERT_DISGUST, /atom/movable/screen/alert/disgusted) disgusted.add_mood_event("disgust", /datum/mood_event/disgusted) -/obj/item/organ/internal/stomach/mob_insert(mob/living/carbon/receiver, special, movement_flags) +/obj/item/organ/internal/stomach/Insert(mob/living/carbon/receiver, special, movement_flags) . = ..() receiver.hud_used?.hunger?.update_appearance() -/obj/item/organ/internal/stomach/mob_remove(mob/living/carbon/stomach_owner, special, movement_flags) +/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/tongue/_tongue.dm b/code/modules/surgery/organs/internal/tongue/_tongue.dm index 07d030b2b39..18e9de9fb54 100644 --- a/code/modules/surgery/organs/internal/tongue/_tongue.dm +++ b/code/modules/surgery/organs/internal/tongue/_tongue.dm @@ -2,6 +2,7 @@ name = "tongue" desc = "A fleshy muscle mostly used for lying." icon_state = "tongue" + visual = FALSE zone = BODY_ZONE_PRECISE_MOUTH slot = ORGAN_SLOT_TONGUE attack_verb_continuous = list("licks", "slobbers", "slaps", "frenches", "tongues") @@ -123,30 +124,30 @@ food_taste_reaction = FOOD_LIKED return food_taste_reaction -/obj/item/organ/internal/tongue/mob_insert(mob/living/carbon/receiver, special, movement_flags) +/obj/item/organ/internal/tongue/Insert(mob/living/carbon/tongue_owner, special = FALSE, movement_flags) . = ..() - + if(!.) + return if(modifies_speech) - RegisterSignal(receiver, COMSIG_MOB_SAY, PROC_REF(handle_speech)) - receiver.voice_filter = voice_filter + RegisterSignal(tongue_owner, COMSIG_MOB_SAY, PROC_REF(handle_speech)) + tongue_owner.voice_filter = voice_filter /* This could be slightly simpler, by making the removal of the * NO_TONGUE_TRAIT conditional on the tongue's `sense_of_taste`, but * then you can distinguish between ageusia from no tongue, and * ageusia from having a non-tasting tongue. */ - REMOVE_TRAIT(receiver, TRAIT_AGEUSIA, NO_TONGUE_TRAIT) + REMOVE_TRAIT(tongue_owner, TRAIT_AGEUSIA, NO_TONGUE_TRAIT) apply_tongue_effects() -/obj/item/organ/internal/tongue/mob_remove(mob/living/carbon/organ_owner, special, movement_flags) +/obj/item/organ/internal/tongue/Remove(mob/living/carbon/tongue_owner, special, movement_flags) . = ..() - temp_say_mod = "" - UnregisterSignal(organ_owner, COMSIG_MOB_SAY) - REMOVE_TRAIT(organ_owner, TRAIT_SPEAKS_CLEARLY, SPEAKING_FROM_TONGUE) - REMOVE_TRAIT(organ_owner, TRAIT_AGEUSIA, ORGAN_TRAIT) + UnregisterSignal(tongue_owner, COMSIG_MOB_SAY) + REMOVE_TRAIT(tongue_owner, TRAIT_SPEAKS_CLEARLY, SPEAKING_FROM_TONGUE) + REMOVE_TRAIT(tongue_owner, TRAIT_AGEUSIA, ORGAN_TRAIT) // Carbons by default start with NO_TONGUE_TRAIT caused TRAIT_AGEUSIA - ADD_TRAIT(organ_owner, TRAIT_AGEUSIA, NO_TONGUE_TRAIT) - organ_owner.voice_filter = initial(organ_owner.voice_filter) + ADD_TRAIT(tongue_owner, TRAIT_AGEUSIA, NO_TONGUE_TRAIT) + tongue_owner.voice_filter = initial(tongue_owner.voice_filter) /obj/item/organ/internal/tongue/apply_organ_damage(damage_amount, maximum = maxHealth, required_organ_flag) . = ..() diff --git a/code/modules/surgery/organs/internal/vocal_cords/_vocal_cords.dm b/code/modules/surgery/organs/internal/vocal_cords/_vocal_cords.dm index f2d9abae416..9183c7eb809 100644 --- a/code/modules/surgery/organs/internal/vocal_cords/_vocal_cords.dm +++ b/code/modules/surgery/organs/internal/vocal_cords/_vocal_cords.dm @@ -1,6 +1,7 @@ /obj/item/organ/internal/vocal_cords //organs that are activated through speech with the :x/MODE_KEY_VOCALCORDS channel name = "vocal cords" icon_state = "appendix" + visual = FALSE zone = BODY_ZONE_PRECISE_MOUTH slot = ORGAN_SLOT_VOICE gender = PLURAL @@ -86,6 +87,7 @@ next_command = world.time + (cooldown * cooldown_mod) /obj/item/organ/internal/adamantine_resonator + visual = FALSE name = "adamantine resonator" desc = "Fragments of adamantine exist in all golems, stemming from their origins as purely magical constructs. These are used to \"hear\" messages from their leaders." zone = BODY_ZONE_HEAD diff --git a/code/modules/surgery/organs/organ_movement.dm b/code/modules/surgery/organs/organ_movement.dm index 010daa3fd24..ff9f753ce18 100644 --- a/code/modules/surgery/organs/organ_movement.dm +++ b/code/modules/surgery/organs/organ_movement.dm @@ -18,8 +18,7 @@ mob_insert(receiver, special, movement_flags) bodypart_insert(limb_owner = receiver, movement_flags = movement_flags) - if(!special) - receiver.update_body_parts() + return TRUE /* * Remove the organ from the select mob. @@ -33,9 +32,6 @@ mob_remove(organ_owner, special, movement_flags) bodypart_remove(limb_owner = organ_owner, movement_flags = movement_flags) - if(!special) - organ_owner.update_body_parts() - /* * Insert the organ into the select mob. * @@ -69,11 +65,6 @@ wash(CLEAN_TYPE_BLOOD) organ_flags &= ~ORGAN_VIRGIN - if(external_bodytypes) - receiver.synchronize_bodytypes() - if(external_bodyshapes) - receiver.synchronize_bodyshapes() - receiver.organs |= src receiver.organs_slot[slot] = src owner = receiver @@ -129,9 +120,6 @@ ADD_TRAIT(src, TRAIT_NODROP, ORGAN_INSIDE_BODY_TRAIT) interaction_flags_item &= ~INTERACT_ITEM_ATTACK_HAND_PICKUP - if(bodypart_overlay) - limb.add_bodypart_overlay(bodypart_overlay) - /* * Remove the organ from the select mob. * @@ -175,9 +163,6 @@ SEND_SIGNAL(organ_owner, COMSIG_CARBON_LOSE_ORGAN, src, special) ADD_TRAIT(src, TRAIT_USED_ORGAN, ORGAN_TRAIT) - organ_owner.synchronize_bodytypes() - organ_owner.synchronize_bodyshapes() - var/list/diseases = organ_owner.get_static_viruses() if(!LAZYLEN(diseases)) return @@ -226,16 +211,6 @@ REMOVE_TRAIT(src, TRAIT_NODROP, ORGAN_INSIDE_BODY_TRAIT) interaction_flags_item |= INTERACT_ITEM_ATTACK_HAND_PICKUP - if(!bodypart_overlay) - return - - limb.remove_bodypart_overlay(bodypart_overlay) - - if(use_mob_sprite_as_obj_sprite) - update_appearance(UPDATE_OVERLAYS) - - color = bodypart_overlay.draw_color // so a pink felinid doesn't drop a gray tail - /// 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 diff --git a/code/modules/unit_tests/organ_bodypart_shuffle.dm b/code/modules/unit_tests/organ_bodypart_shuffle.dm index 11c0bcd71be..842dd1c6c13 100644 --- a/code/modules/unit_tests/organ_bodypart_shuffle.dm +++ b/code/modules/unit_tests/organ_bodypart_shuffle.dm @@ -2,7 +2,7 @@ /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) //freshly filled with wet insides + 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() @@ -30,3 +30,5 @@ 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 ce425936265..8e2c65270f7 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() - organ.Insert(lab_rat, special = TRUE, movement_flags = DELETE_IF_REPLACED) + 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/wiremod/shell/brain_computer_interface.dm b/code/modules/wiremod/shell/brain_computer_interface.dm index 7adefcaa5ed..67a3a41a488 100644 --- a/code/modules/wiremod/shell/brain_computer_interface.dm +++ b/code/modules/wiremod/shell/brain_computer_interface.dm @@ -3,6 +3,7 @@ desc = "An implant that can be placed in a user's head to control circuits using their brain." icon = 'icons/obj/science/circuits.dmi' icon_state = "bci" + visual = FALSE zone = BODY_ZONE_HEAD w_class = WEIGHT_CLASS_TINY diff --git a/tgstation.dme b/tgstation.dme index e36cae811a8..4646c85e3f7 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -6130,7 +6130,7 @@ #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\_visual_organs.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" #include "code\modules\surgery\organs\external\tails.dm" @@ -7677,6 +7677,7 @@ #include "modular_skyrat\modules\gladiator\code\modules\mob\living\simple_animal\hostile\megafauna\markedone.dm" #include "modular_skyrat\modules\goofsec\code\cellphone.dm" #include "modular_skyrat\modules\goofsec\code\department_guards.dm" +#include "modular_skyrat\modules\goofsec\code\hud.dm" #include "modular_skyrat\modules\goofsec\code\sec_clothing_overrides.dm" #include "modular_skyrat\modules\goofsec\code\sol_fed.dm" #include "modular_skyrat\modules\goofsec\code\solfed_clothing.dm"