From 611c48be4056de2dc0f25b4f50a1c0db808faa5a Mon Sep 17 00:00:00 2001 From: John Willard <53777086+JohnFulpWillard@users.noreply.github.com> Date: Tue, 9 Apr 2024 07:36:31 +0000 Subject: [PATCH] Monkeys now use height offset (and monkey tail works) (#81598) This PR adds the ability for monkeys to wear any jumpsuit in the game, and adds support for them to wear things like coats, gloves, and shoes (though this cannot be obtained in-game and is solely achieved through admins, which I also improved a bit upon by adding a defined bitfield for no equip flags). This reverts a lot of changes from https://github.com/tgstation/tgstation/pull/73325 - We no longer check height from limbs and such to bring sprites down, instead monkeys now work more similarly to humans, so the entire PR was made irrelevant, and I didn't really want to leave around dead code for the sake of having a human with longer legs. I've now also added support for Dwarfism, which makes monkeys look even smaller. Very minor change but at least now the mutation doesn't feel like it does literally nothing to monkeys (since they can already walk over tables). Here's a few examples of how it can appear in game (purely for demonstration, as it is currently intentionally made impossible to obtain in-game, though if someone wants to change that post-this PR now that support is added, feel free): Tails have been broken for a while now, the only reason you see them in-game is because they are baked into the monkey sprites. This fixes that, which means humans can now get monkey tails implanted into them (hell yeah) and monkeys can have their tails removed (also hell yeah) --- _maps/map_files/Birdshot/birdshot.dmm | 2 +- code/__DEFINES/DNA.dm | 3 +- code/__DEFINES/inventory.dm | 16 ++- code/__DEFINES/mobs.dm | 21 ++-- code/__DEFINES/research/anomalies.dm | 5 - code/__DEFINES/species_clothing_paths.dm | 4 - code/__HELPERS/global_lists.dm | 2 +- code/datums/datum.dm | 10 ++ code/datums/dna.dm | 6 ++ code/datums/sprite_accessories.dm | 16 ++- code/modules/admin/player_panel.dm | 6 +- .../wizard/grand_ritual/finales/clown.dm | 3 +- .../components/unary_devices/vent_scrubber.dm | 15 --- .../preferences/species_features/monkey.dm | 15 +++ code/modules/clothing/under/suits.dm | 1 - code/modules/clothing/under/syndicate.dm | 1 - code/modules/mob/inventory.dm | 7 +- .../mob/living/carbon/carbon_update_icons.dm | 20 +--- .../mob/living/carbon/human/_species.dm | 18 +--- code/modules/mob/living/carbon/human/dummy.dm | 1 + code/modules/mob/living/carbon/human/human.dm | 9 +- .../mob/living/carbon/human/human_helpers.dm | 14 ++- .../living/carbon/human/human_update_icons.dm | 94 +++++++++++++++--- .../human/species_types/abominations.dm | 51 ---------- .../carbon/human/species_types/monkeys.dm | 16 +-- code/modules/mob/transform_procs.dm | 1 + code/modules/surgery/bodyparts/_bodyparts.dm | 2 - code/modules/surgery/bodyparts/parts.dm | 15 --- code/modules/surgery/organs/external/tails.dm | 13 ++- code/modules/transport/tram/tram_doors.dm | 2 +- code/modules/unit_tests/limbsanity.dm | 26 ----- ...humanoids__datum_species_human_tallboy.png | Bin 457 -> 0 bytes ...enshot_humanoids__datum_species_monkey.png | Bin 778 -> 945 bytes ...ids__datum_species_monkey_human_legged.png | Bin 873 -> 0 bytes ...ids__datum_species_monkey_monkey_freak.png | Bin 916 -> 0 bytes icons/mob/human/species/monkey/bodyparts.dmi | Bin 2248 -> 2261 bytes .../mob/human/species/monkey/monkey_tail.dmi | Bin 356 -> 369 bytes icons/mob/human/species/monkey/uniform.dmi | Bin 2222 -> 0 bytes tgstation.dme | 2 +- .../preferences/features/species_features.tsx | 9 ++ 40 files changed, 209 insertions(+), 217 deletions(-) create mode 100644 code/modules/client/preferences/species_features/monkey.dm delete mode 100644 code/modules/mob/living/carbon/human/species_types/abominations.dm delete mode 100644 code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_human_tallboy.png delete mode 100644 code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_monkey_human_legged.png delete mode 100644 code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_monkey_monkey_freak.png delete mode 100644 icons/mob/human/species/monkey/uniform.dmi diff --git a/_maps/map_files/Birdshot/birdshot.dmm b/_maps/map_files/Birdshot/birdshot.dmm index d9fb22def8f..af4e3047c2f 100644 --- a/_maps/map_files/Birdshot/birdshot.dmm +++ b/_maps/map_files/Birdshot/birdshot.dmm @@ -60450,7 +60450,7 @@ desc = "A cold, hard place for your final rest."; name = "Morgue Slab" }, -/mob/living/carbon/human/species/monkey/humand_legged{ +/mob/living/carbon/human/species/monkey{ name = "Charles"; real_name = "Charles" }, diff --git a/code/__DEFINES/DNA.dm b/code/__DEFINES/DNA.dm index a588c3ed4d3..b3cf4b093d4 100644 --- a/code/__DEFINES/DNA.dm +++ b/code/__DEFINES/DNA.dm @@ -56,8 +56,9 @@ #define DNA_MOTH_MARKINGS_BLOCK 13 #define DNA_MUSHROOM_CAPS_BLOCK 14 #define DNA_POD_HAIR_BLOCK 15 +#define DNA_MONKEY_TAIL_BLOCK 16 -#define DNA_FEATURE_BLOCKS 15 +#define DNA_FEATURE_BLOCKS 16 #define DNA_SEQUENCE_LENGTH 4 #define DNA_MUTATION_BLOCKS 8 diff --git a/code/__DEFINES/inventory.dm b/code/__DEFINES/inventory.dm index 46ae692d617..f80316a133f 100644 --- a/code/__DEFINES/inventory.dm +++ b/code/__DEFINES/inventory.dm @@ -67,6 +67,20 @@ /// Total amount of slots #define SLOTS_AMT 20 // Keep this up to date! +///Inventory slots that can be blacklisted by a species from being equipped into +DEFINE_BITFIELD(no_equip_flags, list( + "EXOSUIT" = ITEM_SLOT_OCLOTHING, + "JUMPSUIT" = ITEM_SLOT_ICLOTHING, + "GLOVES" = ITEM_SLOT_GLOVES, + "GLASSES" = ITEM_SLOT_EYES, + "EARPIECES" = ITEM_SLOT_EARS, + "MASKS" = ITEM_SLOT_MASK, + "HATS" = ITEM_SLOT_HEAD, + "SHOES" = ITEM_SLOT_FEET, + "BACKPACKS" = ITEM_SLOT_BACK, + "TIES" = ITEM_SLOT_NECK, +)) + //SLOT GROUP HELPERS #define ITEM_SLOT_POCKETS (ITEM_SLOT_LPOCKET|ITEM_SLOT_RPOCKET) /// Slots that are physically on you @@ -138,8 +152,6 @@ #define CLOTHING_DIGITIGRADE_VARIATION (1<<1) ///The sprite works fine for digitigrade legs as-is. #define CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON (1<<2) -///has a sprite for monkeys -#define CLOTHING_MONKEY_VARIATION (1<<3) //flags for covering body parts #define GLASSESCOVERSEYES (1<<0) diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index 12b0f36b5a6..91955b496ca 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -116,8 +116,6 @@ #define SPECIES_LIZARD_SILVER "silverscale" #define SPECIES_NIGHTMARE "nightmare" #define SPECIES_MONKEY "monkey" -#define SPECIES_MONKEY_FREAK "monkey_freak" -#define SPECIES_MONKEY_HUMAN_LEGGED "monkey_human_legged" #define SPECIES_MOTH "moth" #define SPECIES_MUSHROOM "mush" #define SPECIES_PLASMAMAN "plasmaman" @@ -125,7 +123,6 @@ #define SPECIES_SHADOW "shadow" #define SPECIES_SKELETON "skeleton" #define SPECIES_SNAIL "snail" -#define SPECIES_TALLBOY "tallboy" #define SPECIES_VAMPIRE "vampire" #define SPECIES_ZOMBIE "zombie" #define SPECIES_ZOMBIE_INFECTIOUS "memezombie" @@ -635,18 +632,22 @@ // - They do not start at 0 for futureproofing // - They skip numbers for futureproofing as well // Otherwise they are completely arbitrary -#define HUMAN_HEIGHT_DWARF 2 -#define HUMAN_HEIGHT_SHORTEST 4 -#define HUMAN_HEIGHT_SHORT 6 -#define HUMAN_HEIGHT_MEDIUM 8 -#define HUMAN_HEIGHT_TALL 10 -#define HUMAN_HEIGHT_TALLER 12 -#define HUMAN_HEIGHT_TALLEST 14 +#define MONKEY_HEIGHT_DWARF 2 +#define MONKEY_HEIGHT_MEDIUM 4 +#define HUMAN_HEIGHT_DWARF 6 +#define HUMAN_HEIGHT_SHORTEST 8 +#define HUMAN_HEIGHT_SHORT 10 +#define HUMAN_HEIGHT_MEDIUM 12 +#define HUMAN_HEIGHT_TALL 14 +#define HUMAN_HEIGHT_TALLER 16 +#define HUMAN_HEIGHT_TALLEST 18 /// Assoc list of all heights, cast to strings, to """"tuples""""" /// The first """tuple""" index is the upper body offset /// The second """tuple""" index is the lower body offset GLOBAL_LIST_INIT(human_heights_to_offsets, list( + "[MONKEY_HEIGHT_DWARF]" = list(-9, -3), + "[MONKEY_HEIGHT_MEDIUM]" = list(-7, -4), "[HUMAN_HEIGHT_DWARF]" = list(-5, -4), "[HUMAN_HEIGHT_SHORTEST]" = list(-2, -1), "[HUMAN_HEIGHT_SHORT]" = list(-1, -1), diff --git a/code/__DEFINES/research/anomalies.dm b/code/__DEFINES/research/anomalies.dm index 707b7bd7a02..3389b9e0fe6 100644 --- a/code/__DEFINES/research/anomalies.dm +++ b/code/__DEFINES/research/anomalies.dm @@ -21,11 +21,6 @@ GLOBAL_LIST_INIT(bioscrambler_parts_blacklist, typecacheof(list( /obj/item/bodypart/chest/larva, /obj/item/bodypart/head/larva, - // Re-add the ones below this line when the bug with offset is fixed - /obj/item/bodypart/leg/left/monkey, - /obj/item/bodypart/leg/right/monkey, - /obj/item/bodypart/leg/left/tallboy, - /obj/item/bodypart/leg/right/tallboy, ))) /// Blacklist of organs which should not appear when bioscrambled. diff --git a/code/__DEFINES/species_clothing_paths.dm b/code/__DEFINES/species_clothing_paths.dm index 2582d81b613..99fe7baab1d 100644 --- a/code/__DEFINES/species_clothing_paths.dm +++ b/code/__DEFINES/species_clothing_paths.dm @@ -6,10 +6,6 @@ ///The dmi for humanoid oversuits #define DEFAULT_SUIT_FILE 'icons/mob/clothing/suits/default.dmi' -//MONKEY PATHS -///The dmi for monkey uniforms -#define MONKEY_UNIFORM_FILE 'icons/mob/human/species/monkey/uniform.dmi' - //DIGITIGRADE PATHS ///The dmi containing digitigrade uniforms #define DIGITIGRADE_UNIFORM_FILE 'icons/mob/human/species/misc/digitigrade.dmi' diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm index 8f3ac9744da..83294d26180 100644 --- a/code/__HELPERS/global_lists.dm +++ b/code/__HELPERS/global_lists.dm @@ -17,7 +17,7 @@ init_sprite_accessory_subtypes(/datum/sprite_accessory/body_markings, GLOB.body_markings_list) init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/human, GLOB.tails_list_human, add_blank = TRUE) init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/lizard, GLOB.tails_list_lizard, add_blank = TRUE) - init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/monkey, GLOB.tails_list_monkey, add_blank = TRUE) + init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/monkey, GLOB.tails_list_monkey, add_blank = FALSE) init_sprite_accessory_subtypes(/datum/sprite_accessory/snouts, GLOB.snouts_list) init_sprite_accessory_subtypes(/datum/sprite_accessory/horns,GLOB.horns_list) init_sprite_accessory_subtypes(/datum/sprite_accessory/ears, GLOB.ears_list) diff --git a/code/datums/datum.dm b/code/datums/datum.dm index e98f0941d64..57d2735440e 100644 --- a/code/datums/datum.dm +++ b/code/datums/datum.dm @@ -313,6 +313,16 @@ filter_data[name] = copied_parameters update_filters() +///A version of add_filter that takes a list of filters to add rather than being individual, to limit calls to update_filters(). +/datum/proc/add_filters(list/list/filters) + LAZYINITLIST(filter_data) + for(var/list/individual_filter as anything in filters) + var/list/params = individual_filter["params"] + var/list/copied_parameters = params.Copy() + copied_parameters["priority"] = individual_filter["priority"] + filter_data[individual_filter["name"]] = copied_parameters + update_filters() + /// Reapplies all the filters. /datum/proc/update_filters() ASSERT(isatom(src) || istype(src, /image)) diff --git a/code/datums/dna.dm b/code/datums/dna.dm index 4cc8a37d103..7d69353e02f 100644 --- a/code/datums/dna.dm +++ b/code/datums/dna.dm @@ -208,6 +208,8 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) L[DNA_TAIL_BLOCK] = construct_block(GLOB.tails_list_human.Find(features["tail_cat"]), GLOB.tails_list_human.len) if(features["tail_lizard"]) L[DNA_LIZARD_TAIL_BLOCK] = construct_block(GLOB.tails_list_lizard.Find(features["tail_lizard"]), GLOB.tails_list_lizard.len) + if(features["tail_monkey"]) + L[DNA_MONKEY_TAIL_BLOCK] = construct_block(GLOB.tails_list_monkey.Find(features["tail_monkey"]), GLOB.tails_list_monkey.len) if(features["snout"]) L[DNA_SNOUT_BLOCK] = construct_block(GLOB.snouts_list.Find(features["snout"]), GLOB.snouts_list.len) if(features["horns"]) @@ -344,6 +346,8 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) set_uni_feature_block(blocknumber, construct_block(GLOB.tails_list_human.Find(features["tail_cat"]), GLOB.tails_list_human.len)) if(DNA_LIZARD_TAIL_BLOCK) set_uni_feature_block(blocknumber, construct_block(GLOB.tails_list_lizard.Find(features["tail_lizard"]), GLOB.tails_list_lizard.len)) + if(DNA_MONKEY_TAIL_BLOCK) + set_uni_feature_block(blocknumber, construct_block(GLOB.tails_list_monkey.Find(features["tail_monkey"]), GLOB.tails_list_monkey.len)) if(DNA_SNOUT_BLOCK) set_uni_feature_block(blocknumber, construct_block(GLOB.snouts_list.Find(features["snout"]), GLOB.snouts_list.len)) if(DNA_HORNS_BLOCK) @@ -646,6 +650,8 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) dna.features["tail_cat"] = GLOB.tails_list_human[deconstruct_block(get_uni_feature_block(features, DNA_TAIL_BLOCK), GLOB.tails_list_human.len)] if(dna.features["tail_lizard"]) dna.features["tail_lizard"] = GLOB.tails_list_lizard[deconstruct_block(get_uni_feature_block(features, DNA_LIZARD_TAIL_BLOCK), GLOB.tails_list_lizard.len)] + if(dna.features["tail_monkey"]) + dna.features["tail_monkey"] = GLOB.tails_list_monkey[deconstruct_block(get_uni_feature_block(features, DNA_MONKEY_TAIL_BLOCK), GLOB.tails_list_monkey.len)] if(dna.features["ears"]) dna.features["ears"] = GLOB.ears_list[deconstruct_block(get_uni_feature_block(features, DNA_EARS_BLOCK), GLOB.ears_list.len)] if(dna.features["moth_wings"]) diff --git a/code/datums/sprite_accessories.dm b/code/datums/sprite_accessories.dm index 1584f9c4db8..40c17b774b1 100644 --- a/code/datums/sprite_accessories.dm +++ b/code/datums/sprite_accessories.dm @@ -1739,17 +1739,17 @@ /datum/sprite_accessory/body_markings/dtiger name = "Dark Tiger Body" icon_state = "dtiger" - gender_specific = 1 + gender_specific = TRUE /datum/sprite_accessory/body_markings/ltiger name = "Light Tiger Body" icon_state = "ltiger" - gender_specific = 1 + gender_specific = TRUE /datum/sprite_accessory/body_markings/lbelly name = "Light Belly" icon_state = "lbelly" - gender_specific = 1 + gender_specific = TRUE /datum/sprite_accessory/tails em_block = TRUE @@ -1787,13 +1787,11 @@ icon_state = "default" color_src = HAIR_COLOR -/datum/sprite_accessory/tails/monkey - icon = 'icons/mob/human/species/monkey/monkey_tail.dmi' - color_src = FALSE - -/datum/sprite_accessory/tails/monkey/standard +/datum/sprite_accessory/tails/monkey/default name = "Monkey" - icon_state = "monkey" + icon = 'icons/mob/human/species/monkey/monkey_tail.dmi' + icon_state = "default" + color_src = FALSE /datum/sprite_accessory/pod_hair icon = 'icons/mob/human/species/podperson_hair.dmi' diff --git a/code/modules/admin/player_panel.dm b/code/modules/admin/player_panel.dm index c8c3b660920..31c34957544 100644 --- a/code/modules/admin/player_panel.dm +++ b/code/modules/admin/player_panel.dm @@ -231,10 +231,10 @@ if(isliving(M)) if(iscarbon(M)) //Carbon stuff - if(ismonkey(M)) - M_job = "Monkey" - else if(ishuman(M)) + if(ishuman(M) && M.job) M_job = M.job + else if(ismonkey(M)) + M_job = "Monkey" else if(isalien(M)) //aliens if(islarva(M)) M_job = "Alien larva" diff --git a/code/modules/antagonists/wizard/grand_ritual/finales/clown.dm b/code/modules/antagonists/wizard/grand_ritual/finales/clown.dm index bda79c908c0..d2f4a5a0763 100644 --- a/code/modules/antagonists/wizard/grand_ritual/finales/clown.dm +++ b/code/modules/antagonists/wizard/grand_ritual/finales/clown.dm @@ -24,8 +24,7 @@ var/datum/action/cooldown/spell/conjure_item/clown_pockets/new_spell = new(victim) new_spell.Grant(victim) continue - if (!ismonkey(victim)) // Monkeys cannot yet wear clothes - dress_as_magic_clown(victim) + dress_as_magic_clown(victim) if (prob(15)) create_vendetta(victim.mind, invoker.mind) diff --git a/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm b/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm index c318d78a335..86cbc07a94f 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm @@ -84,21 +84,6 @@ . = ..() disconnect_from_area(area_to_unregister) -///adds a gas or list of gases to our filter_types. used so that the scrubber can check if its supposed to be processing after each change -/obj/machinery/atmospherics/components/unary/vent_scrubber/proc/add_filters(filter_or_filters) - if(!islist(filter_or_filters)) - filter_or_filters = list(filter_or_filters) - - for(var/gas_to_filter in filter_or_filters) - var/translated_gas = istext(gas_to_filter) ? gas_id2path(gas_to_filter) : gas_to_filter - - if(ispath(translated_gas, /datum/gas)) - filter_types |= translated_gas - continue - - atmos_conditions_changed() - return TRUE - ///remove a gas or list of gases from our filter_types.used so that the scrubber can check if its supposed to be processing after each change /obj/machinery/atmospherics/components/unary/vent_scrubber/proc/remove_filters(filter_or_filters) if(!islist(filter_or_filters)) diff --git a/code/modules/client/preferences/species_features/monkey.dm b/code/modules/client/preferences/species_features/monkey.dm new file mode 100644 index 00000000000..b25d2cdfab8 --- /dev/null +++ b/code/modules/client/preferences/species_features/monkey.dm @@ -0,0 +1,15 @@ +/datum/preference/choiced/monkey_tail + savefile_key = "feature_monkey_tail" + savefile_identifier = PREFERENCE_CHARACTER + category = PREFERENCE_CATEGORY_SECONDARY_FEATURES + relevant_external_organ = /obj/item/organ/external/tail/monkey + +/datum/preference/choiced/monkey_tail/init_possible_values() + return assoc_to_keys_features(GLOB.tails_list_monkey) + +/datum/preference/choiced/monkey_tail/apply_to_human(mob/living/carbon/human/target, value) + target.dna.features["tail_monkey"] = value + +/datum/preference/choiced/monkey_tail/create_default_value() + var/datum/sprite_accessory/tails/monkey/default/tail = /datum/sprite_accessory/tails/monkey/default + return initial(tail.name) diff --git a/code/modules/clothing/under/suits.dm b/code/modules/clothing/under/suits.dm index 02f047c2f48..0dbf1880d7d 100644 --- a/code/modules/clothing/under/suits.dm +++ b/code/modules/clothing/under/suits.dm @@ -84,7 +84,6 @@ desc = "It's a very smart uniform with a special pocket for tip." icon_state = "waiter" inhand_icon_state = "waiter" - supports_variations_flags = CLOTHING_MONKEY_VARIATION /obj/item/clothing/under/suit/black_really name = "executive suit" diff --git a/code/modules/clothing/under/syndicate.dm b/code/modules/clothing/under/syndicate.dm index 3a27ee6c1eb..ff3061d3e59 100644 --- a/code/modules/clothing/under/syndicate.dm +++ b/code/modules/clothing/under/syndicate.dm @@ -8,7 +8,6 @@ alt_covers_chest = TRUE icon = 'icons/obj/clothing/under/syndicate.dmi' worn_icon = 'icons/mob/clothing/under/syndicate.dmi' - supports_variations_flags = CLOTHING_MONKEY_VARIATION /datum/armor/clothing_under/syndicate melee = 10 diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm index bc44e651868..382e1da68dc 100644 --- a/code/modules/mob/inventory.dm +++ b/code/modules/mob/inventory.dm @@ -467,7 +467,12 @@ if(M.active_storage?.attempt_insert(src, M)) return TRUE - var/list/obj/item/possible = list(M.get_inactive_held_item(), M.get_item_by_slot(ITEM_SLOT_BELT), M.get_item_by_slot(ITEM_SLOT_DEX_STORAGE), M.get_item_by_slot(ITEM_SLOT_BACK)) + var/list/obj/item/possible = list( + M.get_inactive_held_item(), + M.get_item_by_slot(ITEM_SLOT_BELT), + M.get_item_by_slot(ITEM_SLOT_DEX_STORAGE), + M.get_item_by_slot(ITEM_SLOT_BACK), + ) for(var/i in possible) if(!i) continue diff --git a/code/modules/mob/living/carbon/carbon_update_icons.dm b/code/modules/mob/living/carbon/carbon_update_icons.dm index 8dfa0be5e2b..b637488988c 100644 --- a/code/modules/mob/living/carbon/carbon_update_icons.dm +++ b/code/modules/mob/living/carbon/carbon_update_icons.dm @@ -485,7 +485,7 @@ var/old_key = icon_render_keys?[limb.body_zone] //Checks the mob's icon render key list for the bodypart icon_render_keys[limb.body_zone] = (limb.is_husked) ? limb.generate_husk_key().Join() : limb.generate_icon_key().Join() //Generates a key for the current bodypart - if(icon_render_keys[limb.body_zone] != old_key || get_top_offset() != last_top_offset) //If the keys match, that means the limb doesn't need to be redrawn + if(icon_render_keys[limb.body_zone] != old_key) //If the keys match, that means the limb doesn't need to be redrawn needs_update += limb var/list/missing_bodyparts = get_missing_limbs() @@ -502,15 +502,10 @@ for(var/obj/item/bodypart/limb as anything in bodyparts) if(limb in needs_update) var/bodypart_icon = limb.get_limb_icon() - if(!istype(limb, /obj/item/bodypart/leg)) - var/top_offset = get_top_offset() - for(var/image/image as anything in bodypart_icon) - image.pixel_y += top_offset new_limbs += bodypart_icon limb_icon_cache[icon_render_keys[limb.body_zone]] = bodypart_icon //Caches the icon with the bodypart key, as it is new else new_limbs += limb_icon_cache[icon_render_keys[limb.body_zone]] //Pulls existing sprites from the cache - last_top_offset = get_top_offset() remove_overlay(BODYPARTS_LAYER) @@ -520,19 +515,6 @@ apply_overlay(BODYPARTS_LAYER) -/// This looks at the chest and legs of the mob and decides how much our chest, arms, and head should be adjusted. This is useful for limbs that are larger or smaller than the scope of normal human height while keeping the feet anchored to the bottom of the tile -/mob/living/carbon/proc/get_top_offset() - var/from_chest - var/from_leg - for(var/obj/item/bodypart/leg/leg_checked in bodyparts) - if(leg_checked.top_offset > from_leg || isnull(from_leg)) // We find the tallest leg available - from_leg = leg_checked.top_offset - if(isnull(from_leg)) - from_leg = 0 // If we have no legs, we set this to zero to avoid any math issues that might stem from it being NULL - for(var/obj/item/bodypart/chest/chest_checked in bodyparts) // Take the height from the chest - from_chest = chest_checked.top_offset - return (from_chest + from_leg) // The total hight of the chest and legs together - ///////////////////////// // Limb Icon Cache 2.0 // ///////////////////////// diff --git a/code/modules/mob/living/carbon/human/_species.dm b/code/modules/mob/living/carbon/human/_species.dm index 1f04f01ac24..6489505a70e 100644 --- a/code/modules/mob/living/carbon/human/_species.dm +++ b/code/modules/mob/living/carbon/human/_species.dm @@ -211,6 +211,7 @@ GLOBAL_LIST_EMPTY(features_by_species) GLOB.roundstart_races = generate_selectable_species_and_languages() return GLOB.roundstart_races + /** * Generates species available to choose in character setup at roundstart * @@ -574,7 +575,6 @@ GLOBAL_LIST_EMPTY(features_by_species) */ /datum/species/proc/handle_body(mob/living/carbon/human/species_human) species_human.remove_overlay(BODY_LAYER) - var/height_offset = species_human.get_top_offset() // From high changed by varying limb height if(HAS_TRAIT(species_human, TRAIT_INVISIBLE_MAN)) return handle_mutant_bodyparts(species_human) var/list/standing = list() @@ -586,9 +586,7 @@ GLOBAL_LIST_EMPTY(features_by_species) var/obj/item/organ/internal/eyes/eye_organ = species_human.get_organ_slot(ORGAN_SLOT_EYES) if(eye_organ) eye_organ.refresh(call_update = FALSE) - for(var/mutable_appearance/eye_overlay in eye_organ.generate_body_overlay(species_human)) - eye_overlay.pixel_y += height_offset - standing += eye_overlay + standing += eye_organ.generate_body_overlay(species_human) // organic body markings (oh my god this is terrible please rework this to be done on the limbs themselves i beg you) if(HAS_TRAIT(species_human, TRAIT_HAS_MARKINGS)) @@ -600,22 +598,18 @@ GLOBAL_LIST_EMPTY(features_by_species) var/datum/sprite_accessory/markings = GLOB.moth_markings_list[species_human.dna.features["moth_markings"]] if(noggin && (IS_ORGANIC_LIMB(noggin))) var/mutable_appearance/markings_head_overlay = mutable_appearance(markings.icon, "[markings.icon_state]_head", -BODY_LAYER) - markings_head_overlay.pixel_y += height_offset standing += markings_head_overlay if(chest && (IS_ORGANIC_LIMB(chest))) var/mutable_appearance/markings_chest_overlay = mutable_appearance(markings.icon, "[markings.icon_state]_chest", -BODY_LAYER) - markings_chest_overlay.pixel_y += height_offset standing += markings_chest_overlay if(right_arm && (IS_ORGANIC_LIMB(right_arm))) var/mutable_appearance/markings_r_arm_overlay = mutable_appearance(markings.icon, "[markings.icon_state]_r_arm", -BODY_LAYER) - markings_r_arm_overlay.pixel_y += height_offset standing += markings_r_arm_overlay if(left_arm && (IS_ORGANIC_LIMB(left_arm))) var/mutable_appearance/markings_l_arm_overlay = mutable_appearance(markings.icon, "[markings.icon_state]_l_arm", -BODY_LAYER) - markings_l_arm_overlay.pixel_y += height_offset standing += markings_l_arm_overlay if(right_leg && (IS_ORGANIC_LIMB(right_leg))) @@ -638,7 +632,6 @@ GLOBAL_LIST_EMPTY(features_by_species) underwear_overlay = mutable_appearance(underwear.icon, underwear.icon_state, -BODY_LAYER) if(!underwear.use_static) underwear_overlay.color = species_human.underwear_color - underwear_overlay.pixel_y += height_offset standing += underwear_overlay if(species_human.undershirt) @@ -649,7 +642,6 @@ GLOBAL_LIST_EMPTY(features_by_species) working_shirt = wear_female_version(undershirt.icon_state, undershirt.icon, BODY_LAYER) else working_shirt = mutable_appearance(undershirt.icon, undershirt.icon_state, -BODY_LAYER) - working_shirt.pixel_y += height_offset standing += working_shirt if(species_human.socks && species_human.num_legs >= 2 && !(species_human.bodyshape & BODYSHAPE_DIGITIGRADE)) @@ -892,12 +884,6 @@ GLOBAL_LIST_EMPTY(features_by_species) return FALSE return equip_delay_self_check(I, H, bypass_equip_delay_self) if(ITEM_SLOT_ICLOTHING) - var/obj/item/bodypart/chest = H.get_bodypart(BODY_ZONE_CHEST) - if(chest && (chest.bodyshape & BODYSHAPE_MONKEY)) - if(!(I.supports_variations_flags & CLOTHING_MONKEY_VARIATION)) - if(!disable_warning) - to_chat(H, span_warning("[I] doesn't fit your [chest.name]!")) - return FALSE return equip_delay_self_check(I, H, bypass_equip_delay_self) if(ITEM_SLOT_ID) var/obj/item/bodypart/O = H.get_bodypart(BODY_ZONE_CHEST) diff --git a/code/modules/mob/living/carbon/human/dummy.dm b/code/modules/mob/living/carbon/human/dummy.dm index eabca79d281..329eb4a0246 100644 --- a/code/modules/mob/living/carbon/human/dummy.dm +++ b/code/modules/mob/living/carbon/human/dummy.dm @@ -100,6 +100,7 @@ INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy) target.dna.features["spines"] = get_consistent_feature_entry(GLOB.spines_list) target.dna.features["tail_cat"] = get_consistent_feature_entry(GLOB.tails_list_human) // it's a lie target.dna.features["tail_lizard"] = get_consistent_feature_entry(GLOB.tails_list_lizard) + target.dna.features["tail_monkey"] = get_consistent_feature_entry(GLOB.tails_list_monkey) target.dna.features["pod_hair"] = get_consistent_feature_entry(GLOB.pod_hair_list) target.dna.initialize_dna(create_mutation_blocks = FALSE, randomize_features = FALSE) // UF and UI are nondeterministic, even though the features are the same some blocks will randomize slightly diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 9f1ea960fe5..0794bd99fc2 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -728,6 +728,10 @@ /mob/living/carbon/human/vv_edit_var(var_name, var_value) if(var_name == NAMEOF(src, mob_height)) + var/static/list/monkey_heights = list( + MONKEY_HEIGHT_DWARF, + MONKEY_HEIGHT_MEDIUM, + ) var/static/list/heights = list( HUMAN_HEIGHT_SHORTEST, HUMAN_HEIGHT_SHORT, @@ -736,7 +740,10 @@ HUMAN_HEIGHT_TALLER, HUMAN_HEIGHT_TALLEST ) - if(!(var_value in heights)) + if(ismonkey(src)) + if(!(var_value in monkey_heights)) + return + else if(!(var_value in heights)) return . = set_mob_height(var_value) diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm index ef44318676e..c3809a5e324 100644 --- a/code/modules/mob/living/carbon/human/human_helpers.dm +++ b/code/modules/mob/living/carbon/human/human_helpers.dm @@ -271,8 +271,10 @@ /mob/living/carbon/human/proc/set_mob_height(new_height) if(mob_height == new_height) return FALSE - if(new_height == HUMAN_HEIGHT_DWARF) - CRASH("Don't set height to dwarf height directly, use dwarf trait") + if(new_height == HUMAN_HEIGHT_DWARF || new_height == MONKEY_HEIGHT_DWARF) + CRASH("Don't set height to dwarf height directly, use dwarf trait instead.") + if(new_height == MONKEY_HEIGHT_MEDIUM) + CRASH("Don't set height to monkey height directly, use monkified gene/species instead.") mob_height = new_height regenerate_icons() @@ -287,7 +289,13 @@ */ /mob/living/carbon/human/proc/get_mob_height() if(HAS_TRAIT(src, TRAIT_DWARF)) - return HUMAN_HEIGHT_DWARF + if(ismonkey(src)) + return MONKEY_HEIGHT_DWARF + else + return HUMAN_HEIGHT_DWARF + + else if(ismonkey(src)) + return MONKEY_HEIGHT_MEDIUM return mob_height 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 290fe4ce03b..56d577a18bf 100644 --- a/code/modules/mob/living/carbon/human/human_update_icons.dm +++ b/code/modules/mob/living/carbon/human/human_update_icons.dm @@ -102,9 +102,7 @@ There are several things that need to be remembered: var/icon_file var/woman //BEGIN SPECIES HANDLING - if((bodyshape & BODYSHAPE_MONKEY) && (uniform.supports_variations_flags & CLOTHING_MONKEY_VARIATION)) - icon_file = MONKEY_UNIFORM_FILE - else if((bodyshape & BODYSHAPE_DIGITIGRADE) && (uniform.supports_variations_flags & CLOTHING_DIGITIGRADE_VARIATION)) + if((bodyshape & BODYSHAPE_DIGITIGRADE) && (uniform.supports_variations_flags & CLOTHING_DIGITIGRADE_VARIATION)) icon_file = DIGITIGRADE_UNIFORM_FILE //Female sprites have lower priority than digitigrade sprites else if(dna.species.sexes && (bodyshape & BODYSHAPE_HUMANOID) && physique == FEMALE && !(uniform.female_sprite_flags & NO_FEMALE_UNIFORM)) //Agggggggghhhhh @@ -709,9 +707,6 @@ generate/load female uniform sprites matching all previously decided variables .[2] = offsets["y"] else .[2] = worn_y_offset - if(ishuman(loc) && slot_flags != ITEM_SLOT_FEET) /// we adjust the human body for high given by body parts, execpt shoes, because they are always on the bottom - var/mob/living/carbon/human/human_holder = loc - .[2] += human_holder.get_top_offset() //Can't think of a better way to do this, sadly /mob/proc/get_item_offsets_for_index(i) @@ -820,26 +815,97 @@ generate/load female uniform sprites matching all previously decided variables "Lenghten_Torso", "Gnome_Cut_Torso", "Gnome_Cut_Legs", + "Monkey_Torso", + "Monkey_Legs", + "Monkey_Gnome_Cut_Torso", + "Monkey_Gnome_Cut_Legs", )) switch(get_mob_height()) // Don't set this one directly, use TRAIT_DWARF + if(MONKEY_HEIGHT_DWARF) + appearance.add_filters(list( + list( + "name" = "Monkey_Gnome_Cut_Torso", + "priority" = 1, + "params" = displacement_map_filter(cut_torso_mask, x = 0, y = 0, size = 3), + ), + list( + "name" = "Monkey_Gnome_Cut_Legs", + "priority" = 1, + "params" = displacement_map_filter(cut_legs_mask, x = 0, y = 0, size = 4), + ), + )) + if(MONKEY_HEIGHT_MEDIUM) + appearance.add_filters(list( + list( + "name" = "Monkey_Torso", + "priority" = 1, + "params" = displacement_map_filter(cut_torso_mask, x = 0, y = 0, size = 2), + ), + list( + "name" = "Monkey_Legs", + "priority" = 1, + "params" = displacement_map_filter(cut_legs_mask, x = 0, y = 0, size = 4), + ), + )) + // Don't set this one directly, use TRAIT_DWARF if(HUMAN_HEIGHT_DWARF) - appearance.add_filter("Gnome_Cut_Torso", 1, displacement_map_filter(cut_torso_mask, x = 0, y = 0, size = 2)) - appearance.add_filter("Gnome_Cut_Legs", 1, displacement_map_filter(cut_legs_mask, x = 0, y = 0, size = 3)) + appearance.add_filters(list( + list( + "name" = "Gnome_Cut_Torso", + "priority" = 1, + "params" = displacement_map_filter(cut_torso_mask, x = 0, y = 0, size = 2), + ), + list( + "name" = "Gnome_Cut_Legs", + "priority" = 1, + "params" = displacement_map_filter(cut_legs_mask, x = 0, y = 0, size = 3), + ), + )) if(HUMAN_HEIGHT_SHORTEST) - appearance.add_filter("Cut_Torso", 1, displacement_map_filter(cut_torso_mask, x = 0, y = 0, size = 1)) - appearance.add_filter("Cut_Legs", 1, displacement_map_filter(cut_legs_mask, x = 0, y = 0, size = 1)) + appearance.add_filters(list( + list( + "name" = "Cut_Torso", + "priority" = 1, + "params" = displacement_map_filter(cut_torso_mask, x = 0, y = 0, size = 1), + ), + list( + "name" = "Cut_Legs", + "priority" = 1, + "params" = displacement_map_filter(cut_legs_mask, x = 0, y = 0, size = 1), + ), + )) if(HUMAN_HEIGHT_SHORT) appearance.add_filter("Cut_Legs", 1, displacement_map_filter(cut_legs_mask, x = 0, y = 0, size = 1)) if(HUMAN_HEIGHT_TALL) appearance.add_filter("Lenghten_Legs", 1, displacement_map_filter(lenghten_legs_mask, x = 0, y = 0, size = 1)) if(HUMAN_HEIGHT_TALLER) - appearance.add_filter("Lenghten_Torso", 1, displacement_map_filter(lenghten_torso_mask, x = 0, y = 0, size = 1)) - appearance.add_filter("Lenghten_Legs", 1, displacement_map_filter(lenghten_legs_mask, x = 0, y = 0, size = 1)) + appearance.add_filters(list( + list( + "name" = "Lenghten_Torso", + "priority" = 1, + "params" = displacement_map_filter(lenghten_torso_mask, x = 0, y = 0, size = 1), + ), + list( + "name" = "Lenghten_Legs", + "priority" = 1, + "params" = displacement_map_filter(lenghten_legs_mask, x = 0, y = 0, size = 1), + ), + )) if(HUMAN_HEIGHT_TALLEST) - appearance.add_filter("Lenghten_Torso", 1, displacement_map_filter(lenghten_torso_mask, x = 0, y = 0, size = 1)) - appearance.add_filter("Lenghten_Legs", 1, displacement_map_filter(lenghten_legs_mask, x = 0, y = 0, size = 2)) + appearance.add_filters(list( + list( + "name" = "Lenghten_Torso", + "priority" = 1, + "params" = displacement_map_filter(lenghten_torso_mask, x = 0, y = 0, size = 1), + ), + list( + "name" = "Lenghten_Legs", + "priority" = 1, + "params" = displacement_map_filter(lenghten_legs_mask, x = 0, y = 0, size = 2), + ), + )) return appearance diff --git a/code/modules/mob/living/carbon/human/species_types/abominations.dm b/code/modules/mob/living/carbon/human/species_types/abominations.dm deleted file mode 100644 index 43ca71311c2..00000000000 --- a/code/modules/mob/living/carbon/human/species_types/abominations.dm +++ /dev/null @@ -1,51 +0,0 @@ -/// These won't appear normally in games, they are meant to for debuging the adjustment of limbs based on the height of a humans bodyparts. -/datum/species/human/tallboy - name = "\improper Tall Boy" - id = SPECIES_TALLBOY - examine_limb_id = SPECIES_HUMAN - changesource_flags = MIRROR_BADMIN | WABBAJACK - bodypart_overrides = list( - BODY_ZONE_L_ARM = /obj/item/bodypart/arm/left, - BODY_ZONE_R_ARM = /obj/item/bodypart/arm/right, - BODY_ZONE_HEAD = /obj/item/bodypart/head, - BODY_ZONE_L_LEG = /obj/item/bodypart/leg/left/tallboy, - BODY_ZONE_R_LEG = /obj/item/bodypart/leg/right/tallboy, - BODY_ZONE_CHEST = /obj/item/bodypart/chest, - ) - -/datum/species/monkey/human_legged - name = "human-legged monkey" - id = SPECIES_MONKEY_HUMAN_LEGGED - examine_limb_id = SPECIES_MONKEY - changesource_flags = MIRROR_BADMIN | WABBAJACK - bodypart_overrides = list( - BODY_ZONE_L_ARM = /obj/item/bodypart/arm/left/monkey, - BODY_ZONE_R_ARM = /obj/item/bodypart/arm/right/monkey, - BODY_ZONE_HEAD = /obj/item/bodypart/head/monkey, - BODY_ZONE_L_LEG = /obj/item/bodypart/leg/left, - BODY_ZONE_R_LEG = /obj/item/bodypart/leg/right, - BODY_ZONE_CHEST = /obj/item/bodypart/chest/monkey, - ) - -/datum/species/monkey/monkey_freak - name = "human-armed monkey" - id = SPECIES_MONKEY_FREAK - examine_limb_id = SPECIES_MONKEY - changesource_flags = MIRROR_BADMIN | WABBAJACK - bodypart_overrides = list( - BODY_ZONE_L_ARM = /obj/item/bodypart/arm/left, - BODY_ZONE_R_ARM = /obj/item/bodypart/arm/right, - BODY_ZONE_HEAD = /obj/item/bodypart/head/monkey, - BODY_ZONE_L_LEG = /obj/item/bodypart/leg/left/monkey, - BODY_ZONE_R_LEG = /obj/item/bodypart/leg/right/monkey, - BODY_ZONE_CHEST = /obj/item/bodypart/chest, - ) - -/mob/living/carbon/human/species/monkey/humand_legged - race = /datum/species/monkey/human_legged - -/mob/living/carbon/human/species/monkey/monkey_freak - race = /datum/species/monkey/monkey_freak - -/mob/living/carbon/human/species/tallboy - race = /datum/species/human/tallboy 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 1f371d575ac..159824f2ef3 100644 --- a/code/modules/mob/living/carbon/human/species_types/monkeys.dm +++ b/code/modules/mob/living/carbon/human/species_types/monkeys.dm @@ -4,7 +4,7 @@ name = "Monkey" id = SPECIES_MONKEY external_organs = list( - /obj/item/organ/external/tail/monkey = "Monkey" + /obj/item/organ/external/tail/monkey = "Monkey", ) mutanttongue = /obj/item/organ/internal/tongue/monkey mutantbrain = /obj/item/organ/internal/brain/primate @@ -44,14 +44,14 @@ /datum/species/monkey/random_name(gender,unique,lastname) return "monkey ([rand(1, 999)])" -/datum/species/monkey/on_species_gain(mob/living/carbon/human/H, datum/species/old_species) +/datum/species/monkey/on_species_gain(mob/living/carbon/human/human_who_gained_species, datum/species/old_species, pref_load) . = ..() - passtable_on(H, SPECIES_TRAIT) - H.dna.add_mutation(/datum/mutation/human/race, MUT_NORMAL) - H.dna.activate_mutation(/datum/mutation/human/race) - H.AddElement(/datum/element/human_biter) + passtable_on(human_who_gained_species, SPECIES_TRAIT) + human_who_gained_species.dna.add_mutation(/datum/mutation/human/race, MUT_NORMAL) + human_who_gained_species.dna.activate_mutation(/datum/mutation/human/race) + human_who_gained_species.AddElement(/datum/element/human_biter) -/datum/species/monkey/on_species_loss(mob/living/carbon/C) +/datum/species/monkey/on_species_loss(mob/living/carbon/human/C) . = ..() passtable_off(C, SPECIES_TRAIT) C.dna.remove_mutation(/datum/mutation/human/race) @@ -59,6 +59,7 @@ /datum/species/monkey/check_roundstart_eligible() // STOP ADDING MONKEY SUBTYPES YOU HEATHEN + // ok we killed monkey subtypes but we're keeping this in cause we can't trust you fuckers if(check_holidays(MONKEYDAY) && id == SPECIES_MONKEY) return TRUE return ..() @@ -165,7 +166,6 @@ to_chat(monkey_brain.owner, span_notice("You will now stumble while while colliding with people who are in combat mode.")) build_all_button_icons() - /obj/item/organ/internal/brain/primate/on_mob_insert(mob/living/carbon/primate) . = ..() RegisterSignal(primate, COMSIG_MOVABLE_CROSS, PROC_REF(on_crossed)) diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm index b71a2a46045..895df810cc4 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -35,6 +35,7 @@ RemoveInvisibility(type) set_species(/datum/species/monkey) name = "monkey" + regenerate_icons() set_name() SEND_SIGNAL(src, COMSIG_HUMAN_MONKEYIZE) uncuff() diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm index 445dba9af13..530c4f3aa13 100644 --- a/code/modules/surgery/bodyparts/_bodyparts.dm +++ b/code/modules/surgery/bodyparts/_bodyparts.dm @@ -180,8 +180,6 @@ var/unarmed_damage_high = 1 ///Determines the accuracy bonus, armor penetration and knockdown probability. var/unarmed_effectiveness = 10 - /// How many pixels this bodypart will offset the top half of the mob, used for abnormally sized torsos and legs - var/top_offset = 0 /// Traits that are given to the holder of the part. If you want an effect that changes this, don't add directly to this. Use the add_bodypart_trait() proc var/list/bodypart_traits = list() diff --git a/code/modules/surgery/bodyparts/parts.dm b/code/modules/surgery/bodyparts/parts.dm index 22450ca793d..01b8d93908e 100644 --- a/code/modules/surgery/bodyparts/parts.dm +++ b/code/modules/surgery/bodyparts/parts.dm @@ -83,7 +83,6 @@ icon_static = 'icons/mob/human/species/monkey/bodyparts.dmi' icon_husk = 'icons/mob/human/species/monkey/bodyparts.dmi' husk_type = "monkey" - top_offset = -5 icon_state = "default_monkey_chest" limb_id = SPECIES_MONKEY should_draw_greyscale = FALSE @@ -467,7 +466,6 @@ icon_static = 'icons/mob/human/species/monkey/bodyparts.dmi' icon_husk = 'icons/mob/human/species/monkey/bodyparts.dmi' husk_type = "monkey" - top_offset = -3 icon_state = "default_monkey_l_leg" limb_id = SPECIES_MONKEY should_draw_greyscale = FALSE @@ -558,7 +556,6 @@ icon_static = 'icons/mob/human/species/monkey/bodyparts.dmi' icon_husk = 'icons/mob/human/species/monkey/bodyparts.dmi' husk_type = "monkey" - top_offset = -3 icon_state = "default_monkey_r_leg" limb_id = SPECIES_MONKEY should_draw_greyscale = FALSE @@ -584,15 +581,3 @@ can_be_disabled = FALSE max_damage = LIMB_MAX_HP_ALIEN_LIMBS should_draw_greyscale = FALSE - -/obj/item/bodypart/leg/right/tallboy - limb_id = SPECIES_TALLBOY - top_offset = 23 - unarmed_damage_low = 30 - unarmed_damage_low = 50 - -/obj/item/bodypart/leg/left/tallboy - limb_id = SPECIES_TALLBOY - top_offset = 23 - unarmed_damage_low = 30 - unarmed_damage_low = 50 diff --git a/code/modules/surgery/organs/external/tails.dm b/code/modules/surgery/organs/external/tails.dm index 4234ca9b5ae..ab71e3ac9f3 100644 --- a/code/modules/surgery/organs/external/tails.dm +++ b/code/modules/surgery/organs/external/tails.dm @@ -135,7 +135,7 @@ var/wagging = FALSE /datum/bodypart_overlay/mutant/tail/get_base_icon_state() - return (wagging ? "wagging_" : "") + sprite_datum.icon_state //add the wagging tag if we be wagging + return "[wagging ? "wagging_" : ""][sprite_datum.icon_state]" //add the wagging tag if we be wagging /datum/bodypart_overlay/mutant/tail/can_draw_on_bodypart(mob/living/carbon/human/human) if(human.wear_suit && (human.wear_suit.flags_inv & HIDEJUMPSUIT)) @@ -150,6 +150,9 @@ wag_flags = WAG_ABLE +/datum/bodypart_overlay/mutant/tail/get_global_feature_list() + return GLOB.tails_list_human + /obj/item/organ/external/tail/cat/get_butt_sprite() return BUTT_SPRITE_CAT @@ -158,12 +161,14 @@ feature_key = "tail_cat" color_source = ORGAN_COLOR_HAIR -/datum/bodypart_overlay/mutant/tail/cat/get_global_feature_list() - return GLOB.tails_list_human - /obj/item/organ/external/tail/monkey + name = "monkey tail" + preference = "feature_monkey_tail" + bodypart_overlay = /datum/bodypart_overlay/mutant/tail/monkey + dna_block = DNA_MONKEY_TAIL_BLOCK + ///Monkey tail bodypart overlay /datum/bodypart_overlay/mutant/tail/monkey color_source = NONE diff --git a/code/modules/transport/tram/tram_doors.dm b/code/modules/transport/tram/tram_doors.dm index ea6fe8d32c9..644f45def4a 100644 --- a/code/modules/transport/tram/tram_doors.dm +++ b/code/modules/transport/tram/tram_doors.dm @@ -136,7 +136,7 @@ for(var/mob/living/future_pancake in checked_turf) future_pancake.visible_message(span_warning("[src] beeps angrily and closes on [future_pancake]!"), span_userdanger("[src] beeps angrily and closes on you!")) SEND_SIGNAL(future_pancake, COMSIG_LIVING_DOORCRUSHED, src) - if(ishuman(future_pancake) || ismonkey(future_pancake)) + if(ishuman(future_pancake)) future_pancake.emote("scream") future_pancake.adjustBruteLoss(DOOR_CRUSH_DAMAGE * 2) future_pancake.Paralyze(2 SECONDS) diff --git a/code/modules/unit_tests/limbsanity.dm b/code/modules/unit_tests/limbsanity.dm index a92d481f556..6efec37ab76 100644 --- a/code/modules/unit_tests/limbsanity.dm +++ b/code/modules/unit_tests/limbsanity.dm @@ -10,29 +10,3 @@ TEST_FAIL("[path] does not have a valid icon for female variants") else if(!icon_exists(UNLINT(part::should_draw_greyscale ? part::icon_greyscale : part::icon_static), "[part::limb_id]_[part::body_zone]")) TEST_FAIL("[path] does not have a valid icon") - -/// Tests the height adjustment system which dynamically changes how much the chest, head, and arms of a carbon are adjusted upwards or downwards based on the length of their legs and chest. -/datum/unit_test/limb_height_adjustment - -/datum/unit_test/limb_height_adjustment/Run() - var/mob/living/carbon/human/john_doe = allocate(/mob/living/carbon/human/consistent) - var/mob/living/carbon/human/species/monkey/monkey = allocate(/mob/living/carbon/human/species/monkey) - var/mob/living/carbon/human/tallboy = allocate(/mob/living/carbon/human/consistent) - - tallboy.set_species(/datum/species/human/tallboy) - TEST_ASSERT_EQUAL(john_doe.get_top_offset(), 0, "John Doe found to have a top offset other than zero.") - TEST_ASSERT_EQUAL(monkey.get_top_offset(), -8, "Monkey found to have a top offset other than -8.") - TEST_ASSERT_EQUAL(tallboy.get_top_offset(), 23, "Tallboy human varient found to have a top offset other than 23.") - - - var/obj/item/bodypart/leg/left/monkey/left_monky_leg = allocate(/obj/item/bodypart/leg/left/monkey) - var/obj/item/bodypart/leg/right/monkey/right_monky_leg = allocate(/obj/item/bodypart/leg/right/monkey) - - left_monky_leg.replace_limb(john_doe, TRUE) - - TEST_ASSERT_EQUAL(john_doe.get_top_offset(), 0, "John Doe has a top offset other than 0 with one human leg and one monkey leg.") - - right_monky_leg.replace_limb(john_doe, TRUE) - - TEST_ASSERT_EQUAL(john_doe.get_top_offset(), -3, "John Doe has a top offset other than -3 with two monkey legs.") - diff --git a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_human_tallboy.png b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_human_tallboy.png deleted file mode 100644 index 262353dc0a95afa4307c8c162e9276bb09a17179..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 457 zcmV;)0XF`LP)E#@e2e>c6xkBq}W}Gt14YE62mqS@7!En1VMG7`0MItN#Dr&e)Fap^4yL z#_D|#;e_)L5HG+x_;BdaJrJ&gu5qVv5qR*H04v9z7IX%>0$+0+V;q(cR#-z=2Kf|B z!4yovUkRuUkSgf#IzV-R41vwR7BFucgB(1>eHp*WZbYqJV&aePoOWk!FE^ph-kQR9J=WR@-)?Fbo8g#>DbvO+wQB{~z6vArOjX z&gQ8PQ46GJMibdJ8a2%)w$Vzwk9RF~T}N%F;}R;~oT&T44{6^qGefs1>hG=p>6xVuk6x{Yx#|327%csxMM59PRsW;#6AXpJj?ms{*kc0 ztPt6Uz>!1n9E-U19{Ju|1rHDi$j7t50PdiGu&#tRF|Y?I0rVUS0)efw&f&5Oo&bc1 zB5c|-GVUD;z*ZD+R2XfX1?1CCfFn&Sz#3?eHz}rm5$N&P9>;%Y%0~$sT#lzajF|mz`+WH2E-pUj~(NV$@m|FtUTgFpx8}rsX^38(nYX{qa5CuBChsuj2@f zQ8bpUc?r`kp@M)4ey)Gr2bPG5mXxi4Y@+;@&Y8rDZv|EYFnmkllspA8&T-HPI4n)+ zkSqdNT`HV`UnFoqI21^T>GmFuw%soGcW}H6`9PLmg=4&-*OOU)CcHjAp~b;`aD-0- zLWR**=Lb0>C(H*`fv--VA4K3R1A+=KRA_GEApguo%p-gzXzQUU1nVy<#wThK0J6z|gn1d9<(Rmk+(B(v2+fX3VHc7JFBk2~NIG`E=# zo@PBH8vfSoefIZ((y+Dnr-0a2Eq_*kzYXR2KxU9?epXOA2bhn*EP$3&_XRYhngG1N t>KrWywWcg1fGH2UGn@%Efhqn6{s(ZFEk{}(H532<002ovPDHLkV1j{!VRZli delta 595 zcmV-Z0<8V92Z{!eBmp^*B_$jh8X;C%V|ROl;Nak4VPSxPfOs?TM`0lpM*@~i|&3CwdK&R{@Dw$G^( zfWak@EIH#N4grSOX1I!ZlE{~g7r-d&lV*w6RpT0kt$geqpoeJXQNV+M%>q50jxSFe zpz;0;iEg(WrC@FlwEH$g$pbcU+&}HdLad942LmQ3I>$W>E4M|_jmG~q63~BCYvm2K zwV=x{2*$cW_Opnwy-2i&{5Jm><}>r7;OFCrBaWEG8-MUF-wnc~f~NjK?}`)r!Ia=* z@%@7moYf$>1vK{$h>IG88Nu8?pyD$12hAY(dED5|Kuk6WtpJz1iHCCI)=sk)i4#g7 z@&*I&s@v>n_nn}Xh`|8e%}sxqen9|zDK9QXWeYEeipi8PLlB_JyT0w;Kqz5G?+7r& zq-N)t0RIwb&YD%5_+||Ce{Pf14u|p>{{Xu9JAlepd hq+7wP#U6i2e*?Hh6cE0=ejoq<002ovPDHLkV1g?&A4dQH diff --git a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_monkey_human_legged.png b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_monkey_human_legged.png deleted file mode 100644 index 285c0a660ca896291551e8b6a58063365f8f8455..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 873 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 diff --git a/icons/mob/human/species/monkey/monkey_tail.dmi b/icons/mob/human/species/monkey/monkey_tail.dmi index 2a06af25b797d40bba9f50882900c2cce6944caa..ffebf714f9aa9ae03c3ecbd70ace87c7964ab6b3 100644 GIT binary patch delta 197 zcmV;$06PEV0`UTnOaY3KO;$iYB{eOvG^Zrq$<@Qt&qaxgGbOXA7-SX~XIfEWZYqdv zNJz6=kiTCDF1^YMu6{0HmjVD$el_^)eVaT0004TC+ZlE7KpSc7#l+-4PxkvsPeKF$ zUs9dttU^@6yRi7-v8Mz5A&UjkHY6=Di`94_JiU~s8oysJ006*i^Z$z zWIUMvda_?gZ=VPNzNA{`tU}bnx3Ku-v8N0Dki`Mfu_PT}7VGgsxO_sCr`oF@007`U zeOAG|2&+LUwt_GGmhL8WRs=mo-baRLZVG zM)qAI$&$69Y%|1IhS$5C_ngjo|G4-2$Gv~u^Sz&YV@!>8Az(Nd004--o|gHsI{quT zIF9pNMu6h6+~005??_z|H|hYSFmoBCQBmiKd3F<3((ZD?*32+U5L zpPxC|ID9H!T@G7I)-R8tU8wxXcp*=YiP6VKA8x$ZE42HRm64&tEGA#4rF&*&LCKzR zpVdaxLgh0&_U=fx<4p6Vqr}?(wB5;U7#|1$l<*BoG6N|*)#!#k^uFrmz{+Y9zN4kE zRZCMCY#A_fbW%Fp$%EyrCU-v64rm`@l_Z^0N3lv!9{mM3N_x=Da1}*{-vuqq(NiX{ zs+tQa8!=aRvL1y(#rgxV5{R%G@=E=Wd$!BV!jHP6@_3V01q)rK3Vop71aHy9NIEo- zNxRi>*grU!yjw=39#DE;ugbL?b?4qLT5A~{;oub(e*E1Z33wk;B0xor&S=}(U0eG0 zXNXHLNP1zZp1Cl3K`nW+^P7Z4X?#jFm>Bd)q9cNlNb}30fBVB#Y@~Z84 zV}vqo(n3xbMhV0``nmaI^vr>^&cJXEEH|xbj=E0)W+Q?*9lMsJLPA13UEe5Au0;vd zXKDYM;4M0qpo-jZ^|L zZ)sxcuuoZkeoFqvl4rU}#jyc2H0(P9&%P#&u|N>jYO_kX=n1N>dUZp!nUZ4w^{ z{t&;XJe>cI`(}ZPI_m%R_!)LIRYqaQuox^nlN zq5KEymo^&sX~~!GD=LQGPfMfBS6yi7si{SaacYDo&VpRckVQxw`LvvTbMM5PU{Ylz zDr;WHZ*pWr3lF`6!zGu@%{k%bJ0K>E7Vh}r;o+C~XIHOW;q$gol#NxPDOal&7KGpg zM{^qEJLWnpY`Yh9l->qzmfX(sdm^31vjlf0FU1O6{km%B3UbZK&dL&7TwIL1Ko0Zw zA4yUns>~Q_vy%;{dzVRpzV#lOP8B{SZ|mCPbYE1-K%wvM+P~RK_!;q*kB=`k&qzZX zKmWZ%Nvy0oZObRfnMfZbJ&)Rr8Uxr`offTO*@%Qu_hJmiKb3dmNNPP&V5n`={d~38 z7lLu(n1YjMgO)N|whkkTAcDH-ld~AUD7?_ttuc0=FGkBQuq^5}$>E0-mwkArOxsec zARY4Y9@tPVd)>QGryi3lbhOOVe>`e-{8W~>1EU3dB0=hrxNYcir>UxHE;c?9Yj9Tf zUF}IIvS3Am;tre4U6)4ru5&n0&zf7DLf1K52oq&s@Ar6;Lm$^WFr}>~h*g6XKxnr`x+ViRQ%fR#DNZA|USD(w2}s7kkFs;tOin(n^?Le#Q!_f40lEYXjc0|V97yuO!)DkN z)iQ#?EnS0F2)WS3$^x-x#Tw3kQ~5tz6?e42i7Mq@!i8`DkJrZ)(ONFuLNj#dx+|Q^f(B<;#(x7}g0WOY zo5A7mr-<=~HPPJM;fjIKJSNUNteLsF8l5gjk7@VsGASu7#d6oz)C>i?xDdDd=Xghg z_zI-D;Jb2EU8q=O=IH}A#a$1V&k~(h`M#fgqeR2} zeSqGXSI7?;@#cT|E03Q~W#Pm81I%-SI0kqR)JJ$Y5`7%r2al&2OGowe^t|L+z%aqA zS}K$Z%oA~BTl9GyhWwd$Zg6ARb9P3~WU{Os$S-YdNQy5=%Xg-|;^unIA5BX^F h|9(k-BjLQmrv7(Xd;O;I;|B!L*EZIA^`~RxKLK0zAy@za diff --git a/tgstation.dme b/tgstation.dme index a1c100997c4..36abffbb259 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -3700,6 +3700,7 @@ #include "code\modules\client\preferences\species_features\ethereal.dm" #include "code\modules\client\preferences\species_features\felinid.dm" #include "code\modules\client\preferences\species_features\lizard.dm" +#include "code\modules\client\preferences\species_features\monkey.dm" #include "code\modules\client\preferences\species_features\moth.dm" #include "code\modules\client\preferences\species_features\mushperson.dm" #include "code\modules\client\preferences\species_features\mutants.dm" @@ -4967,7 +4968,6 @@ #include "code\modules\mob\living\carbon\human\status_procs.dm" #include "code\modules\mob\living\carbon\human\suicides.dm" #include "code\modules\mob\living\carbon\human\species_types\abductors.dm" -#include "code\modules\mob\living\carbon\human\species_types\abominations.dm" #include "code\modules\mob\living\carbon\human\species_types\android.dm" #include "code\modules\mob\living\carbon\human\species_types\dullahan.dm" #include "code\modules\mob\living\carbon\human\species_types\ethereal.dm" diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/species_features.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/species_features.tsx index 457e67fd0a6..b7d0d69959f 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/species_features.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/species_features.tsx @@ -68,6 +68,15 @@ export const feature_human_tail: FeatureChoiced = { }, }; +export const feature_monkey_tail: FeatureChoiced = { + name: 'Tail', + component: ( + props: FeatureValueProps, + ) => { + return ; + }, +}; + export const feature_lizard_legs: FeatureChoiced = { name: 'Legs', component: (