From ee8eb00a857c1d50abe33e471530974072a9b101 Mon Sep 17 00:00:00 2001 From: MistakeNot4892 Date: Tue, 30 Apr 2024 14:18:26 +1000 Subject: [PATCH] Added quadrupedal species handling. --- code/__defines/bodytype.dm | 2 + code/__defines/damage_organs.dm | 6 + code/__defines/flags.dm | 1 + code/__defines/languages.dm | 1 - code/__defines/mobs.dm | 6 +- code/_helpers/unsorted.dm | 1 - code/_onclick/hud/hud.dm | 19 +- code/game/jobs/job/_job.dm | 5 +- code/game/objects/item_mob_overlay.dm | 44 ++++- code/game/objects/items/__item.dm | 6 + code/game/objects/items/weapons/cards_ids.dm | 2 +- .../stool_bed_chair_nest_sofa/bed.dm | 1 + .../stool_bed_chair_nest_sofa/chairs.dm | 2 +- .../stool_bed_chair_nest_sofa/stools.dm | 21 +- code/modules/clothing/_clothing.dm | 9 + code/modules/clothing/head/_head.dm | 2 +- code/modules/clothing/suits/cloaks.dm | 4 +- .../mob/living/carbon/carbon_defines.dm | 1 + .../mob/living/carbon/carbon_organs.dm | 24 ++- code/modules/mob/living/carbon/human/human.dm | 11 +- .../mob/living/carbon/human/human_defines.dm | 2 - .../mob/living/carbon/human/human_movement.dm | 8 +- .../mob/living/carbon/human/human_organs.dm | 168 ---------------- code/modules/mob/living/carbon/human/say.dm | 15 +- .../mob/living/carbon/human/update_icons.dm | 4 +- code/modules/mob/living/life.dm | 187 +++++++++++++++++- code/modules/mob/living/living.dm | 25 ++- code/modules/mob/living/living_defines.dm | 3 + code/modules/mob/living/living_organs.dm | 3 + code/modules/mob/mob.dm | 2 +- code/modules/organs/external/_external.dm | 3 +- .../organs/external/_external_icons.dm | 5 +- code/modules/organs/external/head.dm | 16 +- code/modules/organs/external/quadruped.dm | 51 +++++ code/modules/organs/external/standard.dm | 4 +- code/modules/organs/external/tail.dm | 3 +- code/modules/organs/internal/eyes.dm | 6 +- code/modules/organs/organ.dm | 1 + .../projectiles/targeting/targeting_mob.dm | 4 + code/modules/species/species.dm | 3 +- code/modules/species/species_bodytype.dm | 32 ++- .../species/species_bodytype_offsets.dm | 13 +- .../species/species_bodytype_quadruped.dm | 18 ++ code/modules/sprite_accessories/_accessory.dm | 15 +- .../corporate/clothing/suit/captain.dm | 1 - mods/species/ascent/mobs/nymph/_nymph.dm | 2 +- mods/species/bayliens/tajaran/_tajaran.dm | 2 +- .../bayliens/tajaran/machinery/suit_cycler.dm | 34 ++-- mods/species/neoavians/clothing.dm | 21 +- .../neoavians/machinery/suit_cycler.dm | 36 ++-- mods/species/vox/gear/gear_head.dm | 2 +- mods/species/vox/gear/gear_suit.dm | 2 +- nebula.dme | 2 + 53 files changed, 549 insertions(+), 312 deletions(-) create mode 100644 code/modules/organs/external/quadruped.dm create mode 100644 code/modules/species/species_bodytype_quadruped.dm diff --git a/code/__defines/bodytype.dm b/code/__defines/bodytype.dm index 0fefad2a52b..5a720df0564 100644 --- a/code/__defines/bodytype.dm +++ b/code/__defines/bodytype.dm @@ -1,8 +1,10 @@ #define BODY_FLAG_EXCLUDE BITFLAG(0) #define BODY_FLAG_HUMANOID BITFLAG(1) #define BODY_FLAG_MONKEY BITFLAG(2) +#define BODY_FLAG_QUADRUPED BITFLAG(3) #define BODYTYPE_HUMANOID "humanoid body" +#define BODYTYPE_QUADRUPED "quadruped body" #define BODYTYPE_OTHER "alien body" #define BODYTYPE_MONKEY "small humanoid body" diff --git a/code/__defines/damage_organs.dm b/code/__defines/damage_organs.dm index f585d4a0836..3b786a9c2c9 100644 --- a/code/__defines/damage_organs.dm +++ b/code/__defines/damage_organs.dm @@ -71,6 +71,12 @@ #define ORGAN_FLAG_CAN_DISLOCATE BITFLAG(7) // The organ can be dislocated. #define ORGAN_FLAG_SKELETAL BITFLAG(8) // The organ has been skeletonized. +// Organ category defines. +/// Limb contributes only to stance damage calculation (foot) +#define ORGAN_CATEGORY_STANCE "stance" +/// Limb is considered the 'root' of a given stance limb (leg) - also counted for stance damage a la ORGAN_CATEGORY_STANCE +#define ORGAN_CATEGORY_STANCE_ROOT "stance_root" + // Droplimb types. #define DISMEMBER_METHOD_EDGE 0 #define DISMEMBER_METHOD_BLUNT 1 diff --git a/code/__defines/flags.dm b/code/__defines/flags.dm index cc9efae8d51..925e8fea4d4 100644 --- a/code/__defines/flags.dm +++ b/code/__defines/flags.dm @@ -65,6 +65,7 @@ The latter will result in a linter warning and will not work correctly. #define OBJ_FLAG_NOFALL BITFLAG(3) // Will prevent mobs from falling #define OBJ_FLAG_MOVES_UNSUPPORTED BITFLAG(4) // Object moves with shuttle transition even if turf below is a background turf. #define OBJ_FLAG_HOLLOW BITFLAG(5) // Modifies initial matter values to be lower than w_class normally sets. +#define OBJ_FLAG_SUPPORT_MOB BITFLAG(6) // Object can be used to prop up a mob with stance damage (broken legs) // Item-level flags (/obj/item/item_flags) #define ITEM_FLAG_NO_BLUDGEON BITFLAG(0) // When an item has this it produces no "X has been hit by Y with Z" message with the default handler. diff --git a/code/__defines/languages.dm b/code/__defines/languages.dm index c6ae4185206..58b0a9277e2 100644 --- a/code/__defines/languages.dm +++ b/code/__defines/languages.dm @@ -10,4 +10,3 @@ #define LANG_FLAG_NO_STUTTER BITFLAG(8) // No stuttering, slurring, or other speech problems #define LANG_FLAG_ALT_TRANSMIT BITFLAG(9) // Language is not based on vision or sound (Todo: add this into the say code and use it for the rootspeak languages) #define LANG_FLAG_FORBIDDEN BITFLAG(10) // Language is not to be granted to a mob under any circumstances. - diff --git a/code/__defines/mobs.dm b/code/__defines/mobs.dm index 648edce4f73..140bc68961f 100644 --- a/code/__defines/mobs.dm +++ b/code/__defines/mobs.dm @@ -309,9 +309,9 @@ #define DEXTERITY_KEYBOARDS BITFLAG(4) #define DEXTERITY_TOUCHSCREENS BITFLAG(5) // TODO: actually get grab code to check this one. -#define DEXTERITY_GRAPPLE BITFLAG(6) -#define DEXTERITY_WEAPONS BITFLAG(7) -#define DEXTERITY_COMPLEX_TOOLS BITFLAG(8) +#define DEXTERITY_GRAPPLE BITFLAG(6) // Can the mob grab other mobs? +#define DEXTERITY_WEAPONS BITFLAG(7) // Can the mob use guns? +#define DEXTERITY_COMPLEX_TOOLS BITFLAG(8) // Can the mob use complex items like flashlights, handcuffs, etc? #define DEXTERITY_BASE (DEXTERITY_SIMPLE_MACHINES|DEXTERITY_HOLD_ITEM|DEXTERITY_WIELD_ITEM|DEXTERITY_EQUIP_ITEM) #define DEXTERITY_FULL (DEXTERITY_BASE|DEXTERITY_KEYBOARDS|DEXTERITY_TOUCHSCREENS|DEXTERITY_GRAPPLE|DEXTERITY_WEAPONS|DEXTERITY_COMPLEX_TOOLS) diff --git a/code/_helpers/unsorted.dm b/code/_helpers/unsorted.dm index e92fb83744d..1d1291dfaeb 100644 --- a/code/_helpers/unsorted.dm +++ b/code/_helpers/unsorted.dm @@ -669,7 +669,6 @@ Turf and target are seperate in case you want to teleport some distance from a t mobs += M return mobs - /proc/parse_zone(zone) var/static/list/zone_to_descriptor_mapping = list( BP_R_HAND = "right hand", diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm index c58d371347b..fec45f64dc1 100644 --- a/code/_onclick/hud/hud.dm +++ b/code/_onclick/hud/hud.dm @@ -217,7 +217,7 @@ inv_box = sublist[2] inv_box.screen_loc = "CENTER:[world.icon_size/2],BOTTOM:[hand_y_offset]" hand_y_offset += world.icon_size - if(mymob.client) + if(mymob.client && length(hand_hud_objects)) mymob.client.screen |= hand_hud_objects // Make sure all held items are on the screen and set to the correct screen loc. @@ -232,14 +232,15 @@ if(mymob.client) mymob.client.screen |= held // just to make sure it's visible post-login - var/hand_x_offset = -(world.icon_size/2) - for(var/i = 1 to length(swaphand_hud_objects)) - var/obj/swap_elem = swaphand_hud_objects[i] - swap_elem.screen_loc = "CENTER:[hand_x_offset],BOTTOM:[hand_y_offset]" - if(i > 1) // first two elems share a slot - hand_x_offset += world.icon_size - if(mymob.client) - mymob.client.screen |= swap_elem + if(length(swaphand_hud_objects)) + var/hand_x_offset = -(world.icon_size/2) + for(var/i = 1 to length(swaphand_hud_objects)) + var/obj/swap_elem = swaphand_hud_objects[i] + swap_elem.screen_loc = "CENTER:[hand_x_offset],BOTTOM:[hand_y_offset]" + if(i > 1) // first two elems share a slot + hand_x_offset += world.icon_size + if(mymob.client) + mymob.client.screen |= swap_elem /datum/hud/proc/BuildInventoryUI() diff --git a/code/game/jobs/job/_job.dm b/code/game/jobs/job/_job.dm index 1bbf9d6b13c..b8395bee03e 100644 --- a/code/game/jobs/job/_job.dm +++ b/code/game/jobs/job/_job.dm @@ -89,11 +89,12 @@ return title /datum/job/proc/equip_job(var/mob/living/carbon/human/H, var/alt_title, var/datum/mil_branch/branch, var/datum/mil_rank/grade) + H.add_language(/decl/language/human/common) if (required_language) H.add_language(required_language) H.set_default_language(required_language) - H.add_language(/decl/language/human/common) - H.set_default_language(/decl/language/human/common) + else + H.set_default_language(/decl/language/human/common) var/decl/hierarchy/outfit/outfit = get_outfit(H, alt_title, branch, grade) if(outfit) diff --git a/code/game/objects/item_mob_overlay.dm b/code/game/objects/item_mob_overlay.dm index d86eaaf4d29..990860e2276 100644 --- a/code/game/objects/item_mob_overlay.dm +++ b/code/game/objects/item_mob_overlay.dm @@ -60,38 +60,64 @@ var/global/list/icon_state_cache = list() /obj/item/proc/get_mob_overlay(mob/user_mob, slot, bodypart, use_fallback_if_icon_missing = TRUE, skip_adjustment = FALSE) var/state_modifier = user_mob?.get_overlay_state_modifier() + if(!use_single_icon) var/mob_state = "[item_state || icon_state][state_modifier]" var/mob_icon = global.default_onmob_icons[slot] var/decl/bodytype/root_bodytype = user_mob.get_bodytype() if(istype(root_bodytype)) var/use_slot = (bodypart in root_bodytype.equip_adjust) ? bodypart : slot - return root_bodytype.get_offset_overlay_image(mob_icon, mob_state, color, use_slot) + return root_bodytype.get_offset_overlay_image(user_mob, mob_icon, mob_state, color, use_slot) return overlay_image(mob_icon, mob_state, color, RESET_COLOR) var/bodytype = user_mob?.get_bodytype_category() || BODYTYPE_HUMANOID var/useicon = get_icon_for_bodytype(bodytype) - var/use_state = "[bodytype]-[slot][state_modifier]" + var/use_state = "[bodytype]-[slot]" + if(state_modifier) + use_state = "[use_state][state_modifier]" var/is_not_held_slot = !(slot in global.all_hand_slots) if(bodytype != BODYTYPE_HUMANOID && !check_state_in_icon(use_state, useicon) && use_fallback_if_icon_missing) + var/fallback = is_not_held_slot && get_fallback_slot(slot) - if(fallback && fallback != slot && check_state_in_icon("[bodytype]-[fallback][state_modifier]", useicon)) - slot = fallback + if(fallback && fallback != slot) + if(state_modifier) + if(check_state_in_icon("[bodytype]-[fallback][state_modifier]", useicon)) + slot = fallback + else if(check_state_in_icon("[bodytype]-[fallback]", useicon)) + slot = fallback else bodytype = BODYTYPE_HUMANOID useicon = get_icon_for_bodytype(bodytype) - use_state = "[bodytype]-[slot][state_modifier]" + + if(state_modifier) + use_state = "[bodytype]-[slot][state_modifier]" + if(!check_state_in_icon(use_state, useicon)) + use_state = "[bodytype]-[slot]" + else + use_state = "[bodytype]-[slot]" if(!check_state_in_icon(use_state, useicon) && global.bodypart_to_slot_lookup_table[slot]) - use_state = "[bodytype]-[global.bodypart_to_slot_lookup_table[slot]][state_modifier]" + + var/lookup_slot = global.bodypart_to_slot_lookup_table[slot] + if(state_modifier) + use_state = "[bodytype]-[lookup_slot][state_modifier]" + if(!check_state_in_icon(use_state, useicon)) + use_state = "[bodytype]-[lookup_slot]" + else + use_state = "[bodytype]-[lookup_slot]" if(!check_state_in_icon(use_state, useicon)) var/fallback = use_fallback_if_icon_missing && is_not_held_slot && get_fallback_slot(slot) if(!fallback) return new /image slot = fallback - use_state = "[bodytype]-[slot][state_modifier]" + if(state_modifier) + use_state = "[bodytype]-[slot][state_modifier]" + if(!check_state_in_icon(use_state, useicon)) + use_state = "[bodytype]-[slot]" + else + use_state = "[bodytype]-[slot]" if(!check_state_in_icon(use_state, useicon)) return new /image @@ -115,10 +141,10 @@ var/global/list/icon_state_cache = list() var/decl/bodytype/root_bodytype = user_mob?.get_bodytype() if(root_bodytype && root_bodytype.bodytype_category != bodytype) var/list/overlays_to_offset = overlay.overlays - overlay = root_bodytype.get_offset_overlay_image(overlay.icon, overlay.icon_state, color, (bodypart || slot)) + overlay = root_bodytype.get_offset_overlay_image(user_mob, overlay.icon, overlay.icon_state, color, (bodypart || slot)) for(var/thing in overlays_to_offset) var/image/I = thing // Technically an appearance but don't think we can cast to those - var/image/adjusted_overlay = root_bodytype.get_offset_overlay_image(I.icon, I.icon_state, I.color, (bodypart || slot)) + var/image/adjusted_overlay = root_bodytype.get_offset_overlay_image(user_mob, I.icon, I.icon_state, I.color, (bodypart || slot)) adjusted_overlay.appearance_flags = I.appearance_flags adjusted_overlay.plane = I.plane adjusted_overlay.layer = I.layer diff --git a/code/game/objects/items/__item.dm b/code/game/objects/items/__item.dm index 00484cf0e65..a59f168c170 100644 --- a/code/game/objects/items/__item.dm +++ b/code/game/objects/items/__item.dm @@ -134,6 +134,7 @@ return origin_tech /obj/item/Initialize(var/ml, var/material_key) + if(isnull(current_health)) current_health = max_health //Make sure to propagate max_health to health var before material setup, for consistency if(!ispath(material_key, /decl/material)) @@ -143,6 +144,8 @@ . = ..() + setup_sprite_sheets() + if(islist(armor)) for(var/type in armor) if(armor[type]) // Don't set it if it gives no armor anyway, which is many items. @@ -1109,3 +1112,6 @@ modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out. /obj/item/proc/loadout_setup(mob/wearer, metadata) return + +/obj/item/proc/setup_sprite_sheets() + return diff --git a/code/game/objects/items/weapons/cards_ids.dm b/code/game/objects/items/weapons/cards_ids.dm index f471fd99a37..f69317716b5 100644 --- a/code/game/objects/items/weapons/cards_ids.dm +++ b/code/game/objects/items/weapons/cards_ids.dm @@ -287,7 +287,7 @@ var/global/const/NO_EMAG_ACT = -50 dat += text("Blood Type: []
\n", blood_type) dat += text("DNA Hash: []

\n", dna_hash) if(front && side) - dat +="Photo:
" + dat +="Photo:
" dat += "" return jointext(dat,null) diff --git a/code/game/objects/structures/stool_bed_chair_nest_sofa/bed.dm b/code/game/objects/structures/stool_bed_chair_nest_sofa/bed.dm index 46ae59f4b49..0dac0481e0e 100644 --- a/code/game/objects/structures/stool_bed_chair_nest_sofa/bed.dm +++ b/code/game/objects/structures/stool_bed_chair_nest_sofa/bed.dm @@ -24,6 +24,7 @@ parts_amount = 2 parts_type = /obj/item/stack/material/strut user_comfort = 1 + obj_flags = OBJ_FLAG_SUPPORT_MOB var/base_icon = "bed" var/padding_color diff --git a/code/game/objects/structures/stool_bed_chair_nest_sofa/chairs.dm b/code/game/objects/structures/stool_bed_chair_nest_sofa/chairs.dm index 910e18bdade..7524c9a29aa 100644 --- a/code/game/objects/structures/stool_bed_chair_nest_sofa/chairs.dm +++ b/code/game/objects/structures/stool_bed_chair_nest_sofa/chairs.dm @@ -6,7 +6,7 @@ color = "#666666" buckle_dir = 0 buckle_lying = 0 //force people to sit up in chairs when buckled - obj_flags = OBJ_FLAG_ROTATABLE + obj_flags = OBJ_FLAG_ROTATABLE | OBJ_FLAG_SUPPORT_MOB base_icon = "chair" user_comfort = 0.5 diff --git a/code/game/objects/structures/stool_bed_chair_nest_sofa/stools.dm b/code/game/objects/structures/stool_bed_chair_nest_sofa/stools.dm index 7f55c87c922..4c1bcb3cf12 100644 --- a/code/game/objects/structures/stool_bed_chair_nest_sofa/stools.dm +++ b/code/game/objects/structures/stool_bed_chair_nest_sofa/stools.dm @@ -1,15 +1,16 @@ //Todo: add leather and cloth for arbitrary coloured stools. /obj/item/stool - name = "stool" - desc = "Apply butt." - icon = 'icons/obj/furniture.dmi' - icon_state = "stool_preview" //set for the map - item_state = "stool" - randpixel = 0 - force = 10 - throwforce = 10 - w_class = ITEM_SIZE_HUGE - material = DEFAULT_FURNITURE_MATERIAL + name = "stool" + desc = "Apply butt." + icon = 'icons/obj/furniture.dmi' + icon_state = "stool_preview" //set for the map + item_state = "stool" + randpixel = 0 + force = 10 + throwforce = 10 + w_class = ITEM_SIZE_HUGE + material = DEFAULT_FURNITURE_MATERIAL + obj_flags = OBJ_FLAG_SUPPORT_MOB | OBJ_FLAG_ROTATABLE var/base_icon = "stool" var/padding_color var/decl/material/padding_material diff --git a/code/modules/clothing/_clothing.dm b/code/modules/clothing/_clothing.dm index e2e7cad5224..84328ea6da7 100644 --- a/code/modules/clothing/_clothing.dm +++ b/code/modules/clothing/_clothing.dm @@ -30,6 +30,8 @@ /obj/item/clothing/Initialize() . = ..() + setup_equip_flags() + if(accessory_slot) if(isnull(accessory_removable)) accessory_removable = TRUE @@ -62,6 +64,13 @@ /obj/item/clothing/proc/is_accessory() return istype(loc, /obj/item/clothing) +/obj/item/clothing/proc/setup_equip_flags() + if(!isnull(bodytype_equip_flags)) + if(bodytype_equip_flags & BODY_FLAG_EXCLUDE) + bodytype_equip_flags |= BODY_FLAG_QUADRUPED + else + bodytype_equip_flags &= ~BODY_FLAG_QUADRUPED + /obj/item/clothing/can_contaminate() return TRUE diff --git a/code/modules/clothing/head/_head.dm b/code/modules/clothing/head/_head.dm index 17fa36be7bd..02e9d76f03d 100644 --- a/code/modules/clothing/head/_head.dm +++ b/code/modules/clothing/head/_head.dm @@ -51,7 +51,7 @@ if(overlay && on && check_state_in_icon("[overlay.icon_state]_light", overlay.icon)) var/light_overlay if(user_mob.get_bodytype_category() != bodytype) - light_overlay = user_mob.get_bodytype()?.get_offset_overlay_image(overlay.icon, "[overlay.icon_state]_light", null, slot) + light_overlay = user_mob.get_bodytype()?.get_offset_overlay_image(user_mob, overlay.icon, "[overlay.icon_state]_light", null, slot) if(!light_overlay) light_overlay = image(overlay.icon, "[overlay.icon_state]_light") overlay.overlays += light_overlay diff --git a/code/modules/clothing/suits/cloaks.dm b/code/modules/clothing/suits/cloaks.dm index 20b2dd5d7f6..a1cb8f3d802 100644 --- a/code/modules/clothing/suits/cloaks.dm +++ b/code/modules/clothing/suits/cloaks.dm @@ -35,8 +35,8 @@ var/bodyicon = get_icon_for_bodytype(bodytype) var/decl/bodytype/root_bodytype = user_mob.get_bodytype() if(user_mob && bodytype != root_bodytype.bodytype_category) - underlay = root_bodytype.get_offset_overlay_image(bodyicon, "[bodytype]-underlay", color, slot) - cloverlay = root_bodytype.get_offset_overlay_image(bodyicon, "[bodytype]-overlay", color, slot) + underlay = root_bodytype.get_offset_overlay_image(user_mob, bodyicon, "[bodytype]-underlay", color, slot) + cloverlay = root_bodytype.get_offset_overlay_image(user_mob, bodyicon, "[bodytype]-overlay", color, slot) else underlay = image(bodyicon, "[bodytype]-underlay") cloverlay = image(bodyicon, "[bodytype]-overlay") diff --git a/code/modules/mob/living/carbon/carbon_defines.dm b/code/modules/mob/living/carbon/carbon_defines.dm index 25aef1b9729..90c30e87287 100644 --- a/code/modules/mob/living/carbon/carbon_defines.dm +++ b/code/modules/mob/living/carbon/carbon_defines.dm @@ -26,5 +26,6 @@ var/list/organs_by_tag var/tmp/list/internal_organs var/tmp/list/external_organs + var/list/organs_by_category var/player_triggered_sleeping = 0 diff --git a/code/modules/mob/living/carbon/carbon_organs.dm b/code/modules/mob/living/carbon/carbon_organs.dm index 4fd1c5d27c1..5e7378e8747 100644 --- a/code/modules/mob/living/carbon/carbon_organs.dm +++ b/code/modules/mob/living/carbon/carbon_organs.dm @@ -19,12 +19,18 @@ /mob/living/carbon/has_internal_organs() return LAZYLEN(internal_organs) > 0 +/mob/living/carbon/get_organs_by_categories(var/list/categories) + for(var/organ_cat in categories) + if(organ_cat in organs_by_category) + LAZYDISTINCTADD(., organs_by_category[organ_cat]) + //Deletes all references to organs /mob/living/carbon/delete_organs() ..() - organs_by_tag = null - internal_organs = null - external_organs = null + organs_by_tag = null + internal_organs = null + external_organs = null + organs_by_category = null /mob/living/carbon/add_organ(obj/item/organ/O, obj/item/organ/external/affected, in_place, update_icon, detached, skip_health_update = FALSE) var/obj/item/organ/existing = LAZYACCESS(organs_by_tag, O.organ_tag) @@ -41,6 +47,12 @@ else if(!O.is_internal()) LAZYSET(organs_by_tag, O.organ_tag, O) LAZYDISTINCTADD(external_organs, O) + + // Update our organ category lists, if neeed. + if(O.organ_category) + LAZYINITLIST(organs_by_category) + LAZYDISTINCTADD(organs_by_category[O.organ_category], O) + . = ..() /mob/living/carbon/remove_organ(var/obj/item/organ/O, var/drop_organ = TRUE, var/detach = TRUE, var/ignore_children = FALSE, var/in_place = FALSE, var/update_icon = TRUE, var/skip_health_update = FALSE) @@ -54,6 +66,12 @@ else LAZYREMOVE(external_organs, O) + // Update our organ category lists, if neeed. + if(O.organ_category && islist(organs_by_category)) + organs_by_category[O.organ_category] -= O + if(LAZYLEN(organs_by_category[O.organ_category]) <= 0) + LAZYREMOVE(organs_by_category, O.organ_category) + /mob/living/carbon/get_bodytype() RETURN_TYPE(/decl/bodytype) // If the root organ ever changes/isn't always the chest, this will need to be changed. diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 140ebcf8964..e4f2f3ac462 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -970,14 +970,6 @@ . = global.using_map.default_cultural_info[token] PRINT_STACK_TRACE("get_cultural_value() tried to return a non-instance value for token '[token]' - full culture list: [json_encode(cultural_info)] default species culture list: [json_encode(global.using_map.default_cultural_info)]") -/mob/living/carbon/human/needs_wheelchair() - var/stance_damage = 0 - for(var/limb_tag in list(BP_L_LEG, BP_R_LEG, BP_L_FOOT, BP_R_FOOT)) - var/obj/item/organ/external/E = GET_EXTERNAL_ORGAN(src, limb_tag) - if(!E || !E.is_usable()) - stance_damage += 2 - return stance_damage >= 4 - /mob/living/carbon/human/get_digestion_product() return species.get_digestion_product(src) @@ -1325,3 +1317,6 @@ volume = round(volume) if(volume > 0 && range > 0) playsound(T, footsound, volume, 1, range) + +/mob/living/get_overlay_state_modifier() + return null diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index de81177ac58..709b7616ed5 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -50,8 +50,6 @@ var/list/equipment_overlays = list() var/datum/mil_branch/char_branch = null var/datum/mil_rank/char_rank = null - /// Whether this mob's ability to stand has been affected - var/stance_damage = 0 /// default unarmed attack var/decl/natural_attack/default_attack /// machine that is currently applying visual effects to this mob. Only used for camera monitors currently. diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm index 483589d994b..87fa5de044d 100644 --- a/code/modules/mob/living/carbon/human/human_movement.dm +++ b/code/modules/mob/living/carbon/human/human_movement.dm @@ -59,8 +59,6 @@ if (root_bodytype && bodytemperature < root_bodytype.cold_discomfort_level) tally += (root_bodytype.cold_discomfort_level - bodytemperature) / 10 * 1.75 - tally += max(2 * stance_damage, 0) //damaged/missing feet or legs is slow - if(mRun in mutations) tally = 0 @@ -141,7 +139,6 @@ return (stamina > 0) /mob/living/carbon/human/UpdateLyingBuckledAndVerbStatus() - var/old_buckled_lying = !!buckled?.buckle_lying var/old_lying = lying . = ..() if(!buckled) @@ -150,6 +147,5 @@ var/mob/M = buckled M.unbuckle_mob() var/decl/bodytype/B = get_bodytype() - playsound(loc, B.bodyfall_sounds, 50, TRUE, -1) - else if(!lying && !old_buckled_lying) - handle_stance() // Force an immediate stance update. + if(B) + playsound(loc, B.bodyfall_sounds, 50, TRUE, -1) diff --git a/code/modules/mob/living/carbon/human/human_organs.dm b/code/modules/mob/living/carbon/human/human_organs.dm index 0d09afd17d5..38a0fca364e 100644 --- a/code/modules/mob/living/carbon/human/human_organs.dm +++ b/code/modules/mob/living/carbon/human/human_organs.dm @@ -42,8 +42,6 @@ else vital_organ_missing_time = null - - //processing internal organs is pretty cheap, do that first. for(var/obj/item/organ/I in internal_organs) I.Process() @@ -55,9 +53,6 @@ for(var/obj/item/organ/external/Ex in get_external_organs()) LAZYDISTINCTADD(bad_external_organs, Ex) - handle_stance() - handle_grasp() - if(!force_process && !LAZYLEN(bad_external_organs)) return @@ -82,169 +77,6 @@ if (W.infection_check()) W.germ_level += 1 -/mob/living/carbon/human/proc/Check_Proppable_Object() - for(var/turf/T in RANGE_TURFS(src, 1)) //we only care for non-space turfs - if(T.density && T.simulated) //walls work - return 1 - - for(var/obj/O in orange(1, src)) - if(O && O.density && O.anchored) - return 1 - - return 0 - -/mob/living/carbon/human/proc/handle_stance() - set waitfor = FALSE // Can sleep in emotes. - // Don't need to process any of this if they aren't standing anyways - // unless their stance is damaged, and we want to check if they should stay down - if (!stance_damage && (lying || resting) && (life_tick % 4) != 0) - return - - stance_damage = 0 - - // Buckled to a bed/chair. Stance damage is forced to 0 since they're sitting on something solid - if (istype(buckled, /obj/structure/bed)) - return - - // Can't fall if nothing pulls you down - if(!has_gravity()) - return - - var/limb_pain - for(var/limb_tag in list(BP_L_LEG, BP_R_LEG, BP_L_FOOT, BP_R_FOOT)) - var/obj/item/organ/external/E = GET_EXTERNAL_ORGAN(src, limb_tag) - if(!E || !E.is_usable()) - stance_damage += 2 // let it fail even if just foot&leg - else if (E.is_malfunctioning()) - //malfunctioning only happens intermittently so treat it as a missing limb when it procs - stance_damage += 2 - if(prob(10)) - visible_message("\The [src]'s [E.name] [pick("twitches", "shudders")] and sparks!") - spark_at(src, amount = 5, holder = src) - else if (E.is_broken()) - stance_damage += 1 - else if (E.is_dislocated()) - stance_damage += 0.5 - - if(E) limb_pain = E.can_feel_pain() - - // Canes and crutches help you stand (if the latter is ever added) - // One cane mitigates a broken leg+foot, or a missing foot. - // Two canes are needed for a lost leg. If you are missing both legs, canes aren't gonna help you. - for(var/obj/item/cane/C in get_held_items()) - stance_damage -= 2 - - if(MOVING_DELIBERATELY(src)) //you don't suffer as much if you aren't trying to run - var/working_pair = 2 - var/obj/item/organ/external/LF = GET_EXTERNAL_ORGAN(src, BP_L_FOOT) - var/obj/item/organ/external/LL = GET_EXTERNAL_ORGAN(src, BP_L_LEG) - var/obj/item/organ/external/RF = GET_EXTERNAL_ORGAN(src, BP_R_FOOT) - var/obj/item/organ/external/RL = GET_EXTERNAL_ORGAN(src, BP_R_LEG) - if(!LL || !LF) //are we down a limb? - working_pair -= 1 - else if((!LL.is_usable()) || (!LF.is_usable())) //if not, is it usable? - working_pair -= 1 - if(!RL || !RF) - working_pair -= 1 - else if((!RL.is_usable()) || (!RF.is_usable())) - working_pair -= 1 - if(working_pair >= 1) - stance_damage -= 1 - if(Check_Proppable_Object()) //it helps to lean on something if you've got another leg to stand on - stance_damage -= 1 - - var/list/objects_to_sit_on = list( - /obj/item/stool, - /obj/structure/bed, - ) - - for(var/type in objects_to_sit_on) //things that can't be climbed but can be propped-up-on - if(locate(type) in src.loc) - return - - // standing is poor - if(stance_damage >= 4 || (stance_damage >= 2 && prob(2)) || (stance_damage >= 3 && prob(8))) - if(!(lying || resting)) - if(limb_pain) - emote(/decl/emote/audible/scream) - custom_emote(VISIBLE_MESSAGE, "collapses!") - SET_STATUS_MAX(src, STAT_WEAK, 3) //can't emote while weakened, apparently. - -/mob/living/carbon/human/proc/handle_grasp() - for(var/hand_slot in get_held_item_slots()) - var/datum/inventory_slot/inv_slot = get_inventory_slot_datum(hand_slot) - if(!inv_slot?.requires_organ_tag) - continue - var/holding = inv_slot?.get_equipped_item() - if(holding) - var/obj/item/organ/external/E = GET_EXTERNAL_ORGAN(src, inv_slot.requires_organ_tag) - if((!E || !E.is_usable() || E.is_parent_dislocated()) && try_unequip(holding)) - grasp_damage_disarm(E) - -/mob/living/carbon/human/proc/stance_damage_prone(var/obj/item/organ/external/affected) - - if(affected && (!BP_IS_PROSTHETIC(affected) || affected.is_robotic())) - switch(affected.body_part) - if(SLOT_FOOT_LEFT, SLOT_FOOT_RIGHT) - if(!BP_IS_PROSTHETIC(affected)) - to_chat(src, SPAN_WARNING("You lose your footing as your [affected.name] spasms!")) - else - to_chat(src, SPAN_WARNING("You lose your footing as your [affected.name] [pick("twitches", "shudders")]!")) - if(SLOT_LEG_LEFT, SLOT_LEG_RIGHT) - if(!BP_IS_PROSTHETIC(affected)) - to_chat(src, SPAN_WARNING("Your [affected.name] buckles from the shock!")) - else - to_chat(src, SPAN_WARNING("You lose your balance as [affected.name] [pick("malfunctions", "freezes","shudders")]!")) - else - return - SET_STATUS_MAX(src, STAT_WEAK, 4) - -/mob/living/carbon/human/proc/grasp_damage_disarm(var/obj/item/organ/external/affected) - - var/list/drop_held_item_slots - if(istype(affected)) - for(var/grasp_tag in (list(affected.organ_tag) | affected.children)) - var/datum/inventory_slot/inv_slot = get_inventory_slot_datum(grasp_tag) - if(inv_slot?.get_equipped_item()) - LAZYDISTINCTADD(drop_held_item_slots, inv_slot) - else if(istype(affected, /datum/inventory_slot)) - drop_held_item_slots = list(affected) - - if(!LAZYLEN(drop_held_item_slots)) - return - - for(var/datum/inventory_slot/inv_slot in drop_held_item_slots) - if(!try_unequip(inv_slot.get_equipped_item())) - continue - var/obj/item/organ/external/E = GET_EXTERNAL_ORGAN(src, inv_slot.slot_id) - if(!E) - continue - if(E.is_robotic()) - var/decl/pronouns/G = get_pronouns() - visible_message("\The [src] drops what [G.he] [G.is] holding, [G.his] [E.name] malfunctioning!") - spark_at(src, 5, holder=src) - continue - - var/grasp_name = E.name - if((E.body_part in list(SLOT_ARM_LEFT, SLOT_ARM_RIGHT)) && LAZYLEN(E.children)) - var/obj/item/organ/external/hand = pick(E.children) - grasp_name = hand.name - - if(E.can_feel_pain()) - var/emote_scream = pick("screams in pain", "lets out a sharp cry", "cries out") - var/emote_scream_alt = pick("scream in pain", "let out a sharp cry", "cry out") - visible_message( - "\The [src] [emote_scream] and drops what they were holding in their [grasp_name]!", - null, - "You hear someone [emote_scream_alt]!" - ) - custom_pain("The sharp pain in your [E.name] forces you to drop what you were holding in your [grasp_name]!", 30) - else - visible_message("\The [src] drops what they were holding in their [grasp_name]!") - -/mob/living/proc/is_asystole() - return FALSE - /mob/living/carbon/human/is_asystole() if(isSynthetic()) var/obj/item/organ/internal/cell/C = get_organ(BP_CELL, /obj/item/organ/internal/cell) diff --git a/code/modules/mob/living/carbon/human/say.dm b/code/modules/mob/living/carbon/human/say.dm index b36bf38379a..61ceec9d9c1 100644 --- a/code/modules/mob/living/carbon/human/say.dm +++ b/code/modules/mob/living/carbon/human/say.dm @@ -132,11 +132,16 @@ /mob/living/carbon/human/can_speak(decl/language/speaking) if(ispath(speaking, /decl/language)) speaking = GET_DECL(speaking) - if(species && speaking && (speaking.name in species.assisted_langs)) - for(var/obj/item/organ/internal/voicebox/I in get_internal_organs()) - if(I.is_usable() && I.assists_languages[speaking]) - return TRUE - return FALSE + if(!istype(speaking)) + return ..() + if(species) + if(speaking.type in species.assisted_langs) + for(var/obj/item/organ/internal/voicebox/I in get_internal_organs()) + if(I.is_usable() && I.assists_languages[speaking]) + return TRUE + return FALSE + else if(speaking.type in species.unspeakable_langs) + return FALSE . = ..() /mob/living/carbon/human/parse_language(var/message) diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index c2d87414f96..3e41420a44a 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -211,7 +211,7 @@ Please contact me on #coderbus IRC. ~Carn x var/turn_angle var/matrix/M = matrix() M.Scale(desired_scale_x, desired_scale_y) - if(lying) + if(lying && get_bodytype()?.rotate_on_prone) // This locate is very bad but trying to get it to respect the buckled dir is proving tricky. if((dir & EAST) || (isturf(loc) && (locate(/obj/structure/bed) in loc))) turn_angle = 90 @@ -343,7 +343,7 @@ Please contact me on #coderbus IRC. ~Carn x var/image/I if(UW.slot_offset_str && LAZYACCESS(root_bodytype.equip_adjust, UW.slot_offset_str)) - I = root_bodytype.get_offset_overlay_image(UW.icon, UW.icon_state, UW.color, UW.slot_offset_str) + I = root_bodytype.get_offset_overlay_image(src, UW.icon, UW.icon_state, UW.color, UW.slot_offset_str) else I = image(icon = UW.icon, icon_state = UW.icon_state) I.color = UW.color diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm index dc6dfd29cbb..c4d7649012e 100644 --- a/code/modules/mob/living/life.dm +++ b/code/modules/mob/living/life.dm @@ -37,11 +37,66 @@ handle_fire() handle_actions() UpdateLyingBuckledAndVerbStatus() + handle_grasp() + handle_stance() handle_regular_hud_updates() handle_status_effects() - return 1 +/mob/living/proc/handle_grasp() + for(var/hand_slot in get_held_item_slots()) + var/datum/inventory_slot/inv_slot = get_inventory_slot_datum(hand_slot) + if(!inv_slot?.requires_organ_tag) + continue + var/holding = inv_slot?.get_equipped_item() + if(holding) + var/obj/item/organ/external/E = GET_EXTERNAL_ORGAN(src, inv_slot.requires_organ_tag) + if((!E || !E.is_usable() || E.is_parent_dislocated()) && try_unequip(holding)) + grasp_damage_disarm(E) + +/mob/living/proc/grasp_damage_disarm(var/obj/item/organ/external/affected) + + var/list/drop_held_item_slots + if(istype(affected)) + for(var/grasp_tag in (list(affected.organ_tag) | affected.children)) + var/datum/inventory_slot/inv_slot = get_inventory_slot_datum(grasp_tag) + if(inv_slot?.get_equipped_item()) + LAZYDISTINCTADD(drop_held_item_slots, inv_slot) + else if(istype(affected, /datum/inventory_slot)) + drop_held_item_slots = list(affected) + + if(!LAZYLEN(drop_held_item_slots)) + return + + for(var/datum/inventory_slot/inv_slot in drop_held_item_slots) + if(!try_unequip(inv_slot.get_equipped_item())) + continue + var/obj/item/organ/external/E = GET_EXTERNAL_ORGAN(src, inv_slot.slot_id) + if(!E) + continue + if(E.is_robotic()) + var/decl/pronouns/G = get_pronouns() + visible_message("\The [src] drops what [G.he] [G.is] holding, [G.his] [E.name] malfunctioning!") + spark_at(src, 5, holder=src) + continue + + var/grasp_name = E.name + if((E.body_part in list(SLOT_ARM_LEFT, SLOT_ARM_RIGHT)) && LAZYLEN(E.children)) + var/obj/item/organ/external/hand = pick(E.children) + grasp_name = hand.name + + if(E.can_feel_pain()) + var/emote_scream = pick("screams in pain", "lets out a sharp cry", "cries out") + var/emote_scream_alt = pick("scream in pain", "let out a sharp cry", "cry out") + visible_message( + "\The [src] [emote_scream] and drops what they were holding in their [grasp_name]!", + null, + "You hear someone [emote_scream_alt]!" + ) + custom_pain("The sharp pain in your [E.name] forces you to drop what you were holding in your [grasp_name]!", 30) + else + visible_message("\The [src] drops what they were holding in their [grasp_name]!") + /mob/living/proc/handle_living_non_stasis_processes() SHOULD_CALL_PARENT(TRUE) // hungy @@ -507,3 +562,133 @@ SET_STATUS_MAX(src, STAT_WEAK, current_size) apply_damage(current_size * 3, IRRADIATE, damage_flags = DAM_DISPERSED) return ..() + +#define LIMB_UNUSABLE 2 +#define LIMB_DAMAGED 1 +#define LIMB_IMPAIRED 0.5 + +/mob/living/proc/handle_stance() + set waitfor = FALSE // Can sleep in emotes. + // Don't need to process any of this if they aren't standing anyways + // unless their stance is damaged, and we want to check if they should stay down + if (!stance_damage && (lying || resting) && (life_tick % 4) != 0) + return + + stance_damage = 0 + + // Buckled to a bed/chair. Stance damage is forced to 0 since they're sitting on something solid + if (istype(buckled, /obj/structure/bed)) + return + + // Can't fall if nothing pulls you down + if(!has_gravity()) + return + + // If we don't have a bodytype, all the limb checking below is going to be nonsensical. + var/decl/bodytype/root_bodytype = get_bodytype() + if(!root_bodytype) + return + + var/static/list/all_stance_limbs = list(ORGAN_CATEGORY_STANCE, ORGAN_CATEGORY_STANCE_ROOT) + var/expected_limbs_for_bodytype = root_bodytype.get_expected_organ_count_for_categories(all_stance_limbs) + if(expected_limbs_for_bodytype <= 0) + return // we don't care about stance for whatever reason. + + // Is there something in our loc we can prop ourselves on? + if(length(loc?.contents)) + for(var/obj/thing in loc.contents) + if(thing.obj_flags & OBJ_FLAG_SUPPORT_MOB) + return + + var/found_limbs = 0 + var/had_limb_pain = FALSE + for(var/obj/item/organ/external/limb in get_organs_by_categories(all_stance_limbs)) + found_limbs++ + var/add_stance_damage = 0 + if(limb.is_malfunctioning()) + // malfunctioning only happens intermittently so treat it as a missing limb when it procs + add_stance_damage = LIMB_UNUSABLE + if(prob(10)) + visible_message("\The [src]'s [limb.name] [pick("twitches", "shudders")] and sparks!") + spark_at(src, amount = 5, holder = src) + else if(!limb.is_usable()) + add_stance_damage = LIMB_UNUSABLE + else if (limb.is_broken()) + add_stance_damage = LIMB_DAMAGED + else if (limb.is_dislocated()) + add_stance_damage = LIMB_IMPAIRED + + if(add_stance_damage > 0) + // Keep track of if any of our limbs can feel pain and has failed, + // so we don't scream if it's a prosthetic that has broken. + had_limb_pain = had_limb_pain || limb.can_feel_pain() + stance_damage += add_stance_damage + + // Add missing limbs as unusable. + stance_damage += max(0, expected_limbs_for_bodytype - found_limbs) * LIMB_UNUSABLE + + // Canes and crutches help you stand (if the latter is ever added) + // One cane mitigates a broken leg+foot, or a missing foot. + // Two canes are needed for a lost leg. If you are missing both legs, canes aren't gonna help you. + for(var/obj/item/cane/C in get_held_items()) + stance_damage -= LIMB_UNUSABLE // Counts for a single functional limb. + + // Calculate the expected and actual number of functioning legs we have. + var/has_sufficient_working_legs = TRUE + var/list/root_limb_tags = root_bodytype.organ_tags_by_category[ORGAN_CATEGORY_STANCE_ROOT] + var/minimum_working_legs = CEILING(length(root_limb_tags) * 0.5) + if(minimum_working_legs > 0) + var/leg_count = 0 + has_sufficient_working_legs = FALSE + for(var/organ_tag in root_limb_tags) + var/obj/item/organ/external/stance_root = GET_EXTERNAL_ORGAN(src, organ_tag) + if(!stance_root || !stance_root.is_usable()) + continue + if(!length(stance_root.children)) + continue + // In theory a leg may have multiple children in the future; this + // will need to be revisited for fork-legged insect people or whatever. + var/has_usable_child = FALSE + for(var/child_tag in stance_root.children) + var/obj/item/organ/external/stance_child = GET_EXTERNAL_ORGAN(src, child_tag) + if(stance_child?.is_usable()) + has_usable_child = TRUE + break + if(has_usable_child) + leg_count++ + if(leg_count >= minimum_working_legs) + has_sufficient_working_legs = TRUE + break + + // Having half or more of our expected number of working legs allows us to mitigate some stance damage. + if(has_sufficient_working_legs) + if(find_mob_supporting_object()) //it helps to lean on something if you've got another leg to stand on + stance_damage -= LIMB_UNUSABLE + else + stance_damage -= LIMB_DAMAGED + + // standing is poor + if(stance_damage >= expected_limbs_for_bodytype || (!MOVING_DELIBERATELY(src) && ((stance_damage >= (expected_limbs_for_bodytype*0.75) && prob(8)) || (stance_damage >= (expected_limbs_for_bodytype*0.5) && prob(2))))) + if(!(lying || resting)) + if(had_limb_pain) + emote(/decl/emote/audible/scream) + custom_emote(VISIBLE_MESSAGE, "collapses!") + SET_STATUS_MAX(src, STAT_WEAK, 3) //can't emote while weakened, apparently. + +/mob/living/proc/stance_damage_prone(var/obj/item/organ/external/affected) + + if(affected && (!BP_IS_PROSTHETIC(affected) || affected.is_robotic())) + switch(affected.body_part) + if(SLOT_FOOT_LEFT, SLOT_FOOT_RIGHT) + if(!BP_IS_PROSTHETIC(affected)) + to_chat(src, SPAN_WARNING("You lose your footing as your [affected.name] spasms!")) + else + to_chat(src, SPAN_WARNING("You lose your footing as your [affected.name] [pick("twitches", "shudders")]!")) + if(SLOT_LEG_LEFT, SLOT_LEG_RIGHT) + if(!BP_IS_PROSTHETIC(affected)) + to_chat(src, SPAN_WARNING("Your [affected.name] buckles from the shock!")) + else + to_chat(src, SPAN_WARNING("You lose your balance as [affected.name] [pick("malfunctions", "freezes","shudders")]!")) + else + return + SET_STATUS_MAX(src, STAT_WEAK, 4) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 836017a3baa..9058e3b9c91 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -604,6 +604,7 @@ default behaviour is: resting = !resting UpdateLyingBuckledAndVerbStatus() update_icon() + update_tail_showing() to_chat(src, SPAN_NOTICE("You are now [resting ? "resting" : "getting up"].")) //called when the mob receives a bright flash @@ -772,7 +773,12 @@ default behaviour is: fluids.trans_to_holder(touching_reagents, saturation) /mob/living/proc/needs_wheelchair() - return FALSE + var/tmp_stance_damage = 0 + for(var/limb_tag in list(BP_L_LEG, BP_R_LEG, BP_L_FOOT, BP_R_FOOT)) + var/obj/item/organ/external/E = GET_EXTERNAL_ORGAN(src, limb_tag) + if(!E || !E.is_usable()) + tmp_stance_damage += 2 + return tmp_stance_damage >= 4 /mob/living/proc/seizure() set waitfor = 0 @@ -1448,3 +1454,20 @@ default behaviour is: /mob/living/proc/handle_footsteps() return + +/mob/living/get_movement_delay(var/travel_dir) + . = ..() + if(stance_damage) + . += max(2 * stance_damage, 0) //damaged/missing feet or legs is slow + +/mob/living/proc/find_mob_supporting_object() + for(var/turf/T in RANGE_TURFS(src, 1)) + if(T.density && T.simulated) + return TRUE + for(var/obj/O in orange(1, src)) + if((O.obj_flags & OBJ_FLAG_SUPPORT_MOB) || (O.density && O.anchored)) + return TRUE + return FALSE + +/mob/living/proc/is_asystole() + return FALSE diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index 8339892a1cf..7c98e8264ba 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -72,3 +72,6 @@ // Used to track appearance descriptor datums. // Currently only on humans due to the spaghetti code involved, TODO: generalize. var/list/appearance_descriptors + + /// Whether this mob's ability to stand has been affected + var/stance_damage = 0 diff --git a/code/modules/mob/living/living_organs.dm b/code/modules/mob/living/living_organs.dm index 704e2833f5a..f31461bcb1d 100644 --- a/code/modules/mob/living/living_organs.dm +++ b/code/modules/mob/living/living_organs.dm @@ -10,6 +10,9 @@ /mob/living/proc/get_internal_organs() return +/mob/living/proc/get_organs_by_categories(var/category) + return + //Those are meant to be overriden with optimizations /mob/living/proc/has_organs() return LAZYLEN(get_organs()) > 0 diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 8f29b8589b3..070c658c826 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -1061,6 +1061,7 @@ return gripper.get_dexterity(silent) // If this slot requires an organ, do the appropriate organ checks. + check_slot = gripper.requires_organ_tag var/obj/item/organ/external/active_hand = GET_EXTERNAL_ORGAN(src, check_slot) if(!active_hand) if(!silent) @@ -1078,7 +1079,6 @@ return (active_hand.get_manual_dexterity() & ~dex_malus) return active_hand.get_manual_dexterity() - /mob/proc/check_dexterity(var/dex_level = DEXTERITY_FULL, var/silent = FALSE) . = (get_dexterity(silent) & dex_level) == dex_level if(!. && !silent) diff --git a/code/modules/organs/external/_external.dm b/code/modules/organs/external/_external.dm index cb7e8912473..bf1211d44bf 100644 --- a/code/modules/organs/external/_external.dm +++ b/code/modules/organs/external/_external.dm @@ -36,8 +36,9 @@ var/skin_colour // skin colour var/skin_blend = ICON_ADD // How the skin colour is applied. var/hair_colour // hair colour - var/render_alpha = 255 + var/render_alpha = 255 // Alpha value to use for rendering the icon (slime transparency) var/skip_body_icon_draw = FALSE // Set to true to skip including this organ on the human body sprite. + var/icon_state_modifier // String modifier to icon_state used for prone icons, etc. /// Sprite accessories like hair and markings to apply to the organ icon and owner. VAR_PRIVATE/list/_sprite_accessories diff --git a/code/modules/organs/external/_external_icons.dm b/code/modules/organs/external/_external_icons.dm index a0018a762e3..35a24a3948e 100644 --- a/code/modules/organs/external/_external_icons.dm +++ b/code/modules/organs/external/_external_icons.dm @@ -252,9 +252,10 @@ var/global/list/organ_icon_cache = list() . = ..() // Update our cache key and refresh or create our base icon. + var/next_state = owner ? "[organ_tag][owner.get_overlay_state_modifier()]" : organ_tag update_limb_icon_file() - if(icon_state != organ_tag) - icon_state = organ_tag + if(icon_state != next_state) + icon_state = next_state _icon_cache_key = jointext(get_icon_cache_key_components(), null) var/icon/mob_icon = global.organ_icon_cache[_icon_cache_key] || generate_mob_icon() diff --git a/code/modules/organs/external/head.dm b/code/modules/organs/external/head.dm index fb9684bd260..f2fe70f3fc7 100644 --- a/code/modules/organs/external/head.dm +++ b/code/modules/organs/external/head.dm @@ -102,9 +102,10 @@ /obj/item/organ/external/head/generate_mob_icon() var/icon/ret = ..() - var/icon/eyes_icon = get_eyes_organ()?.get_onhead_icon() - if(eyes_icon) - ret.Blend(eyes_icon, ICON_OVERLAY) + if(ret) + var/icon/eyes_icon = get_eyes_organ()?.get_onhead_icon() + if(eyes_icon) + ret.Blend(eyes_icon, ICON_OVERLAY) return ret /obj/item/organ/external/head/get_mob_overlays() @@ -112,3 +113,12 @@ var/image/eye_glow = get_organ_eyes_overlay() if(eye_glow) LAZYADD(., eye_glow) + +/obj/item/organ/external/head/gripper/do_install(mob/living/carbon/human/target, affected, in_place, update_icon, detached) + . = ..() + if(. && owner) + owner.add_held_item_slot(new /datum/inventory_slot/gripper/mouth) + +/obj/item/organ/external/head/gripper/do_uninstall(in_place, detach, ignore_children, update_icon) + owner?.remove_held_item_slot(BP_MOUTH) + . = ..() diff --git a/code/modules/organs/external/quadruped.dm b/code/modules/organs/external/quadruped.dm new file mode 100644 index 00000000000..1411f8e91e1 --- /dev/null +++ b/code/modules/organs/external/quadruped.dm @@ -0,0 +1,51 @@ +/obj/item/organ/external/leg/quadruped + name = "left hindleg" + joint = "rear left knee" + +/obj/item/organ/external/leg/right/quadruped + name = "right hindleg" + joint = "rear right knee" + +/obj/item/organ/external/foot/quadruped + name = "left hindpaw" + joint = "rear left ankle" + +/obj/item/organ/external/foot/right/quadruped + name = "right hindpaw" + joint = "rear right ankle" + +/obj/item/organ/external/arm/quadruped + name = "left foreleg" + joint = "front left knee" + amputation_point = "front left knee" + tendon_name = "cruciate ligament" + artery_name = "femoral artery" + organ_category = ORGAN_CATEGORY_STANCE_ROOT + limb_flags = ORGAN_FLAG_CAN_AMPUTATE | ORGAN_FLAG_CAN_STAND | ORGAN_FLAG_HAS_TENDON | ORGAN_FLAG_CAN_BREAK | ORGAN_FLAG_CAN_DISLOCATE + +/obj/item/organ/external/arm/right/quadruped + name = "right foreleg" + joint = "front right knee" + amputation_point = "front right knee" + tendon_name = "cruciate ligament" + artery_name = "femoral artery" + organ_category = ORGAN_CATEGORY_STANCE_ROOT + limb_flags = ORGAN_FLAG_CAN_AMPUTATE | ORGAN_FLAG_CAN_STAND | ORGAN_FLAG_HAS_TENDON | ORGAN_FLAG_CAN_BREAK | ORGAN_FLAG_CAN_DISLOCATE + +/obj/item/organ/external/hand/quadruped + name = "left forepaw" + joint = "front left ankle" + amputation_point = "front left ankle" + tendon_name = "Achilles tendon" + limb_flags = ORGAN_FLAG_CAN_AMPUTATE | ORGAN_FLAG_CAN_STAND | ORGAN_FLAG_HAS_TENDON | ORGAN_FLAG_CAN_BREAK | ORGAN_FLAG_CAN_DISLOCATE + organ_category = ORGAN_CATEGORY_STANCE + gripper_type = null + +/obj/item/organ/external/hand/right/quadruped + name = "right forepaw" + joint = "front right ankle" + amputation_point = "front right ankle" + tendon_name = "Achilles tendon" + limb_flags = ORGAN_FLAG_CAN_AMPUTATE | ORGAN_FLAG_CAN_STAND | ORGAN_FLAG_HAS_TENDON | ORGAN_FLAG_CAN_BREAK | ORGAN_FLAG_CAN_DISLOCATE + organ_category = ORGAN_CATEGORY_STANCE + gripper_type = null diff --git a/code/modules/organs/external/standard.dm b/code/modules/organs/external/standard.dm index e86b0ea97a7..8579c7690da 100644 --- a/code/modules/organs/external/standard.dm +++ b/code/modules/organs/external/standard.dm @@ -92,6 +92,7 @@ tendon_name = "cruciate ligament" artery_name = "femoral artery" arterial_bleed_severity = 0.75 + organ_category = ORGAN_CATEGORY_STANCE_ROOT limb_flags = ORGAN_FLAG_CAN_AMPUTATE | ORGAN_FLAG_CAN_STAND | ORGAN_FLAG_HAS_TENDON | ORGAN_FLAG_CAN_BREAK | ORGAN_FLAG_CAN_DISLOCATE /obj/item/organ/external/leg/right @@ -116,6 +117,7 @@ tendon_name = "Achilles tendon" arterial_bleed_severity = 0.5 limb_flags = ORGAN_FLAG_CAN_AMPUTATE | ORGAN_FLAG_CAN_STAND | ORGAN_FLAG_HAS_TENDON | ORGAN_FLAG_CAN_BREAK | ORGAN_FLAG_CAN_DISLOCATE + organ_category = ORGAN_CATEGORY_STANCE /obj/item/organ/external/foot/right organ_tag = BP_R_FOOT @@ -148,7 +150,7 @@ owner.add_held_item_slot(new gripper_type) /obj/item/organ/external/hand/do_uninstall(in_place, detach, ignore_children, update_icon) - if(!in_place) + if(gripper_type) owner?.remove_held_item_slot(organ_tag) . = ..() diff --git a/code/modules/organs/external/tail.dm b/code/modules/organs/external/tail.dm index fc711d6b8c3..55fff675056 100644 --- a/code/modules/organs/external/tail.dm +++ b/code/modules/organs/external/tail.dm @@ -41,7 +41,8 @@ owner.update_tail_showing(FALSE) /obj/item/organ/external/tail/proc/get_tail() - return tail + var/modifier = owner?.get_overlay_state_modifier() + . = modifier ? "[tail][modifier]" : tail /obj/item/organ/external/tail/proc/get_tail_icon() return tail_icon diff --git a/code/modules/organs/internal/eyes.dm b/code/modules/organs/internal/eyes.dm index bdb11a3dd1f..ee53e0c9666 100644 --- a/code/modules/organs/internal/eyes.dm +++ b/code/modules/organs/internal/eyes.dm @@ -37,12 +37,14 @@ verbs |= /obj/item/organ/internal/eyes/proc/toggle_eye_glow /obj/item/organ/internal/eyes/proc/get_onhead_icon() + var/modifier = owner?.get_overlay_state_modifier() + var/eye_state = modifier ? "eyes[modifier]" : "eyes" + last_eye_cache_key = "[type]-[bodytype.eye_icon]-[last_cached_eye_colour]-[bodytype.eye_offset]-[eye_state]" last_cached_eye_colour = eye_colour - last_eye_cache_key = "[type]-[bodytype.eye_icon]-[last_cached_eye_colour]-[bodytype.eye_offset]" if(!bodytype.eye_icon) return if(!global.eye_icon_cache[last_eye_cache_key]) - var/icon/eyes_icon = icon(icon = bodytype.eye_icon, icon_state = "") + var/icon/eyes_icon = icon(icon = bodytype.eye_icon, icon_state = eye_state) if(bodytype.eye_offset) eyes_icon.Shift(NORTH, bodytype.eye_offset) if(bodytype.apply_eye_colour) diff --git a/code/modules/organs/organ.dm b/code/modules/organs/organ.dm index c52d846c819..589b252a7a8 100644 --- a/code/modules/organs/organ.dm +++ b/code/modules/organs/organ.dm @@ -10,6 +10,7 @@ // Strings. var/organ_tag = "organ" // Unique identifier. + var/organ_category // Identifier for use in organ collections, unused if unset. Would be nice to make this a list, but bodytypes rely on initial() with it. var/parent_organ = BP_CHEST // Organ holding this object. // Status tracking. diff --git a/code/modules/projectiles/targeting/targeting_mob.dm b/code/modules/projectiles/targeting/targeting_mob.dm index 1dd13a1aa6d..08cc73e28aa 100644 --- a/code/modules/projectiles/targeting/targeting_mob.dm +++ b/code/modules/projectiles/targeting/targeting_mob.dm @@ -24,6 +24,10 @@ aiming.cancel_aiming(no_message) /mob/living/UpdateLyingBuckledAndVerbStatus() + var/old_lying = lying + var/old_buckled = buckled ..() if(lying) stop_aiming(no_message=1) + else if(old_buckled && !buckled && old_lying) + handle_stance() // Force an immediate stance update. diff --git a/code/modules/species/species.dm b/code/modules/species/species.dm index 9569352c12d..7b4b2c03e64 100644 --- a/code/modules/species/species.dm +++ b/code/modules/species/species.dm @@ -68,7 +68,8 @@ var/global/const/DEFAULT_SPECIES_HEALTH = 200 var/age_descriptor = /datum/appearance_descriptor/age // Speech vars. - var/assisted_langs = list() // The languages the species can't speak without an assisted organ. + var/assisted_langs = list() // The languages the species can't speak without an assisted organ. + var/unspeakable_langs = list() // The languages the species can't speak at all. var/list/speech_sounds // A list of sounds to potentially play when speaking. var/list/speech_chance // The likelihood of a speech sound playing. diff --git a/code/modules/species/species_bodytype.dm b/code/modules/species/species_bodytype.dm index 515795bcc81..206e119561f 100644 --- a/code/modules/species/species_bodytype.dm +++ b/code/modules/species/species_bodytype.dm @@ -44,6 +44,10 @@ var/global/list/bodytypes_by_category = list() var/manual_dexterity = null /// Determines how the limb behaves with regards to manual attachment/detachment. var/modular_limb_tier = MODULAR_BODYPART_INVALID + // Expected organ types per category, used only for stance checking at time of writing. + var/list/organs_by_category = list() + // Expected organ tags per category, used only for stance checking at time of writing. + var/list/organ_tags_by_category = list() var/list/onmob_state_modifiers var/health_hud_intensity = 1 @@ -193,6 +197,9 @@ var/global/list/bodytypes_by_category = list() "Your chilly flesh stands out in goosebumps." ) + /// Set to FALSE if the mob will update prone icon based on state rather than transform. + var/rotate_on_prone = TRUE + /decl/bodytype/Initialize() . = ..() icon_deformed ||= icon_base @@ -222,10 +229,27 @@ var/global/list/bodytypes_by_category = list() has_limbs[ltag] = list("path" = override_limb_types[ltag]) //Build organ descriptors - for(var/limb_type in has_limbs) - var/list/organ_data = has_limbs[limb_type] - var/obj/item/organ/limb_path = organ_data["path"] - organ_data["descriptor"] = initial(limb_path.name) + for(var/organ_tag in has_limbs) + var/list/organ_data = has_limbs[organ_tag] + var/obj/item/organ/organ = organ_data["path"] + organ_data["descriptor"] = initial(organ.name) + var/organ_cat = initial(organ.organ_category) + if(organ_cat) + LAZYADD(organs_by_category[organ_cat], organ) + LAZYADD(organ_tags_by_category[organ_cat], organ_tag) + + for(var/organ_tag in has_organ) + var/obj/item/organ/organ = has_organ[organ_tag] + var/organ_cat = initial(organ.organ_category) + if(organ_cat) + LAZYADD(organs_by_category[organ_cat], organ) + LAZYADD(organ_tags_by_category[organ_cat], organ_tag) + +/decl/bodytype/proc/get_expected_organ_count_for_categories(var/list/categories) + . = 0 + for(var/category in categories) + if(category && (category in organs_by_category)) + . += length(organs_by_category[category]) /decl/bodytype/proc/apply_limb_colouration(var/obj/item/organ/external/E, var/icon/applying) return applying diff --git a/code/modules/species/species_bodytype_offsets.dm b/code/modules/species/species_bodytype_offsets.dm index 2a7505551a7..9e599406f47 100644 --- a/code/modules/species/species_bodytype_offsets.dm +++ b/code/modules/species/species_bodytype_offsets.dm @@ -21,16 +21,21 @@ The slots that you can use are found in items_clothing.dm and are the inventory var/list/equip_adjust = list() var/list/equip_overlays = list() -/decl/bodytype/proc/get_offset_overlay_image(var/mob_icon, var/mob_state, var/color, var/slot) +/decl/bodytype/proc/get_equip_adjust(mob/mob) + return equip_adjust + +/decl/bodytype/proc/get_offset_overlay_image(mob/mob, mob_icon, mob_state, color, slot) // If we don't actually need to offset this, don't bother with any of the generation/caching. - if(length(equip_adjust) && equip_adjust[slot] && length(equip_adjust[slot])) + var/list/use_equip_adjust = get_equip_adjust(mob) + if(length(use_equip_adjust) && use_equip_adjust[slot] && length(use_equip_adjust[slot])) // Check the cache for previously made icons. - var/image_key = "[mob_icon]-[mob_state]-[color]-[slot]" + var/modifier = mob?.get_overlay_state_modifier() + var/image_key = modifier ? "[modifier]-[mob_icon]-[mob_state]-[color]-[slot]" : "generic-[mob_icon]-[mob_state]-[color]-[slot]" if(!equip_overlays[image_key]) var/icon/final_I = new(icon_template) - var/list/shifts = equip_adjust[slot] + var/list/shifts = use_equip_adjust[slot] // Apply all pixel shifts for each direction. for(var/shift_facing in shifts) diff --git a/code/modules/species/species_bodytype_quadruped.dm b/code/modules/species/species_bodytype_quadruped.dm new file mode 100644 index 00000000000..c703ef0991a --- /dev/null +++ b/code/modules/species/species_bodytype_quadruped.dm @@ -0,0 +1,18 @@ +/decl/bodytype/quadruped + abstract_type = /decl/bodytype/quadruped + rotate_on_prone = FALSE + bodytype_category = BODYTYPE_QUADRUPED + bodytype_flag = BODY_FLAG_QUADRUPED + has_limbs = list( + BP_CHEST = list("path" = /obj/item/organ/external/chest), + BP_GROIN = list("path" = /obj/item/organ/external/groin), + BP_HEAD = list("path" = /obj/item/organ/external/head/gripper), + BP_L_ARM = list("path" = /obj/item/organ/external/arm/quadruped), + BP_R_ARM = list("path" = /obj/item/organ/external/arm/right/quadruped), + BP_L_LEG = list("path" = /obj/item/organ/external/leg/quadruped), + BP_R_LEG = list("path" = /obj/item/organ/external/leg/right/quadruped), + BP_L_HAND = list("path" = /obj/item/organ/external/hand/quadruped), + BP_R_HAND = list("path" = /obj/item/organ/external/hand/right/quadruped), + BP_L_FOOT = list("path" = /obj/item/organ/external/foot/quadruped), + BP_R_FOOT = list("path" = /obj/item/organ/external/foot/right/quadruped) + ) diff --git a/code/modules/sprite_accessories/_accessory.dm b/code/modules/sprite_accessories/_accessory.dm index b7aeafd58ad..34f3802ee8a 100644 --- a/code/modules/sprite_accessories/_accessory.dm +++ b/code/modules/sprite_accessories/_accessory.dm @@ -142,16 +142,21 @@ if(!icon_state) return null LAZYINITLIST(cached_icons[organ.bodytype]) - LAZYINITLIST(cached_icons[organ.bodytype][organ.organ_tag]) - var/icon/accessory_icon = cached_icons[organ.bodytype][organ.organ_tag][color] + LAZYINITLIST(cached_icons[organ.bodytype][organ.icon_state]) + var/icon/accessory_icon = cached_icons[organ.bodytype][organ.icon_state][color] if(!accessory_icon) - accessory_icon = icon(get_accessory_icon(organ), icon_state) // make a new one to avoid mutating the base + // make a new one to avoid mutating the base + var/marking_modifier = organ.owner?.get_overlay_state_modifier() + if(marking_modifier) + accessory_icon = icon(get_accessory_icon(organ), "[icon_state][marking_modifier]") + else + accessory_icon = icon(get_accessory_icon(organ), icon_state) if(!accessory_icon) - cached_icons[organ.bodytype][organ.organ_tag][color] = null + cached_icons[organ.bodytype][organ.icon_state][color] = null return null if(mask_to_bodypart) accessory_icon.Blend(get_limb_mask_for(organ), ICON_MULTIPLY) if(!isnull(color) && !isnull(color_blend)) accessory_icon.Blend(color, color_blend) - cached_icons[organ.bodytype][organ.organ_tag][color] = accessory_icon + cached_icons[organ.bodytype][organ.icon_state][color] = accessory_icon return accessory_icon diff --git a/mods/content/corporate/clothing/suit/captain.dm b/mods/content/corporate/clothing/suit/captain.dm index ca9e02c84c2..55150d96b98 100644 --- a/mods/content/corporate/clothing/suit/captain.dm +++ b/mods/content/corporate/clothing/suit/captain.dm @@ -27,4 +27,3 @@ /obj/item/clothing/suit/armor/captain/Initialize() . = ..() LAZYSET(slowdown_per_slot, slot_wear_suit_str, 1.5) - diff --git a/mods/species/ascent/mobs/nymph/_nymph.dm b/mods/species/ascent/mobs/nymph/_nymph.dm index 8bcd4c410bf..da48aabf82e 100644 --- a/mods/species/ascent/mobs/nymph/_nymph.dm +++ b/mods/species/ascent/mobs/nymph/_nymph.dm @@ -50,4 +50,4 @@ set_extension(src, /datum/extension/base_icon_state, icon_state) /mob/living/simple_animal/alien/kharmaan/get_dexterity(var/silent) - return (DEXTERITY_EQUIP_ITEM|DEXTERITY_HOLD_ITEM) + return (DEXTERITY_EQUIP_ITEM) diff --git a/mods/species/bayliens/tajaran/_tajaran.dm b/mods/species/bayliens/tajaran/_tajaran.dm index 78e6c821d4b..6024c4bca0d 100644 --- a/mods/species/bayliens/tajaran/_tajaran.dm +++ b/mods/species/bayliens/tajaran/_tajaran.dm @@ -3,7 +3,7 @@ #define BODYTYPE_FELINE "feline body" #define BODY_FLAG_FELINE BITFLAG(7) -/obj/item/clothing/Initialize() +/obj/item/clothing/setup_equip_flags() . = ..() if(bodytype_equip_flags & BODY_FLAG_EXCLUDE) bodytype_equip_flags |= BODY_FLAG_FELINE diff --git a/mods/species/bayliens/tajaran/machinery/suit_cycler.dm b/mods/species/bayliens/tajaran/machinery/suit_cycler.dm index 58eb45c24c7..af8842c7b19 100644 --- a/mods/species/bayliens/tajaran/machinery/suit_cycler.dm +++ b/mods/species/bayliens/tajaran/machinery/suit_cycler.dm @@ -2,70 +2,70 @@ LAZYDISTINCTADD(available_bodytypes, BODYTYPE_FELINE) . = ..() -/obj/item/clothing/suit/space/void/merc/Initialize() +/obj/item/clothing/suit/space/void/merc/setup_sprite_sheets() . = ..() LAZYSET(sprite_sheets, BODYTYPE_FELINE, 'mods/species/bayliens/tajaran/icons/clothing/merc/suit.dmi') -/obj/item/clothing/suit/space/void/swat/Initialize() +/obj/item/clothing/suit/space/void/swat/setup_sprite_sheets() . = ..() LAZYSET(sprite_sheets, BODYTYPE_FELINE, 'mods/species/bayliens/tajaran/icons/clothing/deathsquad/suit.dmi') -/obj/item/clothing/suit/space/void/engineering/Initialize() +/obj/item/clothing/suit/space/void/engineering/setup_sprite_sheets() . = ..() LAZYSET(sprite_sheets, BODYTYPE_FELINE, 'mods/species/bayliens/tajaran/icons/clothing/engineering/suit.dmi') -/obj/item/clothing/suit/space/void/mining/Initialize() +/obj/item/clothing/suit/space/void/mining/setup_sprite_sheets() . = ..() LAZYSET(sprite_sheets, BODYTYPE_FELINE, 'mods/species/bayliens/tajaran/icons/clothing/mining/suit.dmi') -/obj/item/clothing/suit/space/void/medical/Initialize() +/obj/item/clothing/suit/space/void/medical/setup_sprite_sheets() . = ..() LAZYSET(sprite_sheets, BODYTYPE_FELINE, 'mods/species/bayliens/tajaran/icons/clothing/medical/suit.dmi') -/obj/item/clothing/suit/space/void/security/Initialize() +/obj/item/clothing/suit/space/void/security/setup_sprite_sheets() . = ..() LAZYSET(sprite_sheets, BODYTYPE_FELINE, 'mods/species/bayliens/tajaran/icons/clothing/sec/suit.dmi') -/obj/item/clothing/suit/space/void/atmos/Initialize() +/obj/item/clothing/suit/space/void/atmos/setup_sprite_sheets() . = ..() LAZYSET(sprite_sheets, BODYTYPE_FELINE, 'mods/species/bayliens/tajaran/icons/clothing/atmos/suit.dmi') -/obj/item/clothing/suit/space/void/engineering/alt/Initialize() +/obj/item/clothing/suit/space/void/engineering/alt/setup_sprite_sheets() . = ..() LAZYSET(sprite_sheets, BODYTYPE_FELINE, 'mods/species/bayliens/tajaran/icons/clothing/engineering_alt/suit.dmi') -/obj/item/clothing/suit/space/void/mining/alt/Initialize() +/obj/item/clothing/suit/space/void/mining/alt/setup_sprite_sheets() . = ..() LAZYSET(sprite_sheets, BODYTYPE_FELINE, 'mods/species/bayliens/tajaran/icons/clothing/mining_alt/suit.dmi') -/obj/item/clothing/suit/space/void/medical/alt/Initialize() +/obj/item/clothing/suit/space/void/medical/alt/setup_sprite_sheets() . = ..() LAZYSET(sprite_sheets, BODYTYPE_FELINE, 'mods/species/bayliens/tajaran/icons/clothing/medical_alt/suit.dmi') -/obj/item/clothing/suit/space/void/security/alt/Initialize() +/obj/item/clothing/suit/space/void/security/alt/setup_sprite_sheets() . = ..() LAZYSET(sprite_sheets, BODYTYPE_FELINE, 'mods/species/bayliens/tajaran/icons/clothing/sec_alt/suit.dmi') -/obj/item/clothing/suit/space/void/atmos/alt/Initialize() +/obj/item/clothing/suit/space/void/atmos/alt/setup_sprite_sheets() . = ..() LAZYSET(sprite_sheets, BODYTYPE_FELINE, 'mods/species/bayliens/tajaran/icons/clothing/atmos_alt/suit.dmi') -/obj/item/clothing/suit/space/void/engineering/salvage/Initialize() +/obj/item/clothing/suit/space/void/engineering/salvage/setup_sprite_sheets() . = ..() LAZYSET(sprite_sheets, BODYTYPE_FELINE, 'mods/species/bayliens/tajaran/icons/clothing/salvage/suit.dmi') -/obj/item/clothing/suit/space/void/expedition/Initialize() +/obj/item/clothing/suit/space/void/expedition/setup_sprite_sheets() . = ..() LAZYSET(sprite_sheets, BODYTYPE_FELINE, 'mods/species/bayliens/tajaran/icons/clothing/pilot/suit.dmi') -/obj/item/clothing/suit/space/void/Initialize() +/obj/item/clothing/suit/space/void/setup_sprite_sheets() . = ..() LAZYSET(sprite_sheets, BODYTYPE_FELINE, 'mods/species/bayliens/tajaran/icons/clothing/nasa/suit.dmi') -/obj/item/clothing/suit/space/void/wizard/Initialize() +/obj/item/clothing/suit/space/void/wizard/setup_sprite_sheets() . = ..() LAZYSET(sprite_sheets, BODYTYPE_FELINE, 'mods/species/bayliens/tajaran/icons/clothing/wizard/suit.dmi') -/obj/item/clothing/suit/space/void/excavation/Initialize() +/obj/item/clothing/suit/space/void/excavation/setup_sprite_sheets() . = ..() LAZYSET(sprite_sheets, BODYTYPE_FELINE, 'mods/species/bayliens/tajaran/icons/clothing/excavation/suit.dmi') diff --git a/mods/species/neoavians/clothing.dm b/mods/species/neoavians/clothing.dm index 4d8c7d09df5..4ad16cfebf4 100644 --- a/mods/species/neoavians/clothing.dm +++ b/mods/species/neoavians/clothing.dm @@ -1,21 +1,20 @@ - - //Shoes - -/obj/item/clothing/shoes/magboots/Initialize() +/obj/item/clothing/shoes/magboots/setup_sprite_sheets() . = ..() LAZYSET(sprite_sheets, BODYTYPE_AVIAN, 'mods/species/neoavians/icons/clothing/feet/magboots.dmi') -/obj/item/clothing/shoes/galoshes/Initialize() +/obj/item/clothing/shoes/galoshes/setup_sprite_sheets() . = ..() LAZYSET(sprite_sheets, BODYTYPE_AVIAN, 'mods/species/neoavians/icons/clothing/feet/galoshes.dmi') //Gloves - -/obj/item/clothing/gloves/Initialize() +/obj/item/clothing/gloves/setup_equip_flags() . = ..() if(!isnull(bodytype_equip_flags) && !(bodytype_equip_flags & BODY_FLAG_EXCLUDE)) bodytype_equip_flags |= BODY_FLAG_AVIAN + +/obj/item/clothing/gloves/setup_sprite_sheets() + . = ..() LAZYSET(sprite_sheets, BODYTYPE_AVIAN, 'mods/species/neoavians/icons/clothing/gloves.dmi') //Backpacks & tanks @@ -26,20 +25,20 @@ //Radsuits (theyre essential?) -/obj/item/clothing/head/radiation/Initialize() +/obj/item/clothing/head/radiation/setup_sprite_sheets() . = ..() LAZYSET(sprite_sheets, BODYTYPE_AVIAN, 'mods/species/neoavians/icons/clothing/head/rad_helm.dmi') -/obj/item/clothing/suit/radiation/Initialize() +/obj/item/clothing/suit/radiation/setup_sprite_sheets() . = ..() LAZYSET(sprite_sheets, BODYTYPE_AVIAN, 'mods/species/neoavians/icons/clothing/suit/rad_suit.dmi') //cloaks -/obj/item/clothing/suit/cloak/Initialize() +/obj/item/clothing/suit/cloak/setup_sprite_sheets() . = ..() LAZYSET(sprite_sheets, BODYTYPE_AVIAN, 'mods/species/neoavians/icons/clothing/accessory/cloak.dmi') -/obj/item/clothing/suit/cloak/hide/Initialize() +/obj/item/clothing/suit/cloak/hide/setup_sprite_sheets() . = ..() LAZYSET(sprite_sheets, BODYTYPE_AVIAN, 'mods/species/neoavians/icons/clothing/accessory/cloak_hide.dmi') diff --git a/mods/species/neoavians/machinery/suit_cycler.dm b/mods/species/neoavians/machinery/suit_cycler.dm index 5fa82cf3034..9b368c30577 100644 --- a/mods/species/neoavians/machinery/suit_cycler.dm +++ b/mods/species/neoavians/machinery/suit_cycler.dm @@ -4,86 +4,86 @@ //mining -/obj/item/clothing/suit/space/void/mining/Initialize() +/obj/item/clothing/suit/space/void/mining/setup_sprite_sheets() . = ..() LAZYSET(sprite_sheets, BODYTYPE_AVIAN, 'mods/species/neoavians/icons/clothing/spacesuit/void/mining/suit.dmi') -/obj/item/clothing/head/helmet/space/void/mining/Initialize() +/obj/item/clothing/head/helmet/space/void/mining/setup_sprite_sheets() . = ..() LAZYSET(sprite_sheets, BODYTYPE_AVIAN, 'mods/species/neoavians/icons/clothing/spacesuit/void/mining/helmet.dmi') //excavation -/obj/item/clothing/suit/space/void/excavation/Initialize() +/obj/item/clothing/suit/space/void/excavation/setup_sprite_sheets() . = ..() LAZYSET(sprite_sheets, BODYTYPE_AVIAN, 'mods/species/neoavians/icons/clothing/spacesuit/void/mining/suit.dmi') -/obj/item/clothing/head/helmet/space/void/excavation/Initialize() +/obj/item/clothing/head/helmet/space/void/excavation/setup_sprite_sheets() . = ..() LAZYSET(sprite_sheets, BODYTYPE_AVIAN, 'mods/species/neoavians/icons/clothing/spacesuit/void/mining/helmet.dmi') //engineering -/obj/item/clothing/head/helmet/space/void/engineering/Initialize() +/obj/item/clothing/head/helmet/space/void/engineering/setup_sprite_sheets() . = ..() LAZYSET(sprite_sheets, BODYTYPE_AVIAN, 'mods/species/neoavians/icons/clothing/spacesuit/void/engineering/helmet.dmi') -/obj/item/clothing/suit/space/void/engineering/Initialize() +/obj/item/clothing/suit/space/void/engineering/setup_sprite_sheets() . = ..() LAZYSET(sprite_sheets, BODYTYPE_AVIAN, 'mods/species/neoavians/icons/clothing/spacesuit/void/engineering/suit.dmi') -/obj/item/clothing/head/helmet/space/void/atmos/Initialize() +/obj/item/clothing/head/helmet/space/void/atmos/setup_sprite_sheets() . = ..() LAZYSET(sprite_sheets, BODYTYPE_AVIAN, 'mods/species/neoavians/icons/clothing/spacesuit/void/atmos/helmet.dmi') -/obj/item/clothing/suit/space/void/atmos/Initialize() +/obj/item/clothing/suit/space/void/atmos/setup_sprite_sheets() . = ..() LAZYSET(sprite_sheets, BODYTYPE_AVIAN, 'mods/species/neoavians/icons/clothing/spacesuit/void/atmos/suit.dmi') //medical -/obj/item/clothing/suit/space/void/medical/Initialize() +/obj/item/clothing/suit/space/void/medical/setup_sprite_sheets() . = ..() LAZYSET(sprite_sheets, BODYTYPE_AVIAN, 'mods/species/neoavians/icons/clothing/spacesuit/void/medical/suit.dmi') -/obj/item/clothing/head/helmet/space/void/medical/Initialize() +/obj/item/clothing/head/helmet/space/void/medical/setup_sprite_sheets() . = ..() LAZYSET(sprite_sheets, BODYTYPE_AVIAN, 'mods/species/neoavians/icons/clothing/spacesuit/void/medical/helmet.dmi') //security -/obj/item/clothing/head/helmet/space/void/security/Initialize() +/obj/item/clothing/head/helmet/space/void/security/setup_sprite_sheets() . = ..() LAZYSET(sprite_sheets, BODYTYPE_AVIAN, 'mods/species/neoavians/icons/clothing/spacesuit/void/sec/helmet.dmi') -/obj/item/clothing/suit/space/void/security/Initialize() +/obj/item/clothing/suit/space/void/security/setup_sprite_sheets() . = ..() LAZYSET(sprite_sheets, BODYTYPE_AVIAN, 'mods/species/neoavians/icons/clothing/spacesuit/void/sec/suit.dmi') //salvage -/obj/item/clothing/head/helmet/space/void/engineering/salvage/Initialize() +/obj/item/clothing/head/helmet/space/void/engineering/salvage/setup_sprite_sheets() . = ..() LAZYSET(sprite_sheets, BODYTYPE_AVIAN, 'mods/species/neoavians/icons/clothing/spacesuit/void/salvage/helmet.dmi') -/obj/item/clothing/suit/space/void/engineering/salvage/Initialize() +/obj/item/clothing/suit/space/void/engineering/salvage/setup_sprite_sheets() . = ..() LAZYSET(sprite_sheets, BODYTYPE_AVIAN, 'mods/species/neoavians/icons/clothing/spacesuit/void/salvage/suit.dmi') //pilot -/obj/item/clothing/head/helmet/space/void/expedition/Initialize() +/obj/item/clothing/head/helmet/space/void/expedition/setup_sprite_sheets() . = ..() LAZYSET(sprite_sheets, BODYTYPE_AVIAN, 'mods/species/neoavians/icons/clothing/spacesuit/void/pilot/helmet.dmi') -/obj/item/clothing/suit/space/void/expedition/Initialize() +/obj/item/clothing/suit/space/void/expedition/setup_sprite_sheets() . = ..() LAZYSET(sprite_sheets, BODYTYPE_AVIAN, 'mods/species/neoavians/icons/clothing/spacesuit/void/pilot/suit.dmi') //merc -/obj/item/clothing/head/helmet/space/void/merc/Initialize() +/obj/item/clothing/head/helmet/space/void/merc/setup_sprite_sheets() . = ..() LAZYSET(sprite_sheets, BODYTYPE_AVIAN, 'mods/species/neoavians/icons/clothing/spacesuit/void/merc/helmet.dmi') -/obj/item/clothing/suit/space/void/merc/Initialize() +/obj/item/clothing/suit/space/void/merc/setup_sprite_sheets() . = ..() LAZYSET(sprite_sheets, BODYTYPE_AVIAN, 'mods/species/neoavians/icons/clothing/spacesuit/void/merc/suit.dmi') \ No newline at end of file diff --git a/mods/species/vox/gear/gear_head.dm b/mods/species/vox/gear/gear_head.dm index 24d6676478f..6d96034223a 100644 --- a/mods/species/vox/gear/gear_head.dm +++ b/mods/species/vox/gear/gear_head.dm @@ -1,4 +1,4 @@ -/obj/item/clothing/head/helmet/space/void/Initialize() +/obj/item/clothing/head/helmet/space/void/setup_equip_flags() . = ..() if(bodytype_equip_flags & BODY_FLAG_EXCLUDE) bodytype_equip_flags |= BODY_FLAG_VOX diff --git a/mods/species/vox/gear/gear_suit.dm b/mods/species/vox/gear/gear_suit.dm index 99856c36fad..9760a804b45 100644 --- a/mods/species/vox/gear/gear_suit.dm +++ b/mods/species/vox/gear/gear_suit.dm @@ -1,4 +1,4 @@ -/obj/item/clothing/suit/space/void/Initialize() +/obj/item/clothing/suit/space/void/setup_equip_flags() . = ..() if(bodytype_equip_flags & BODY_FLAG_EXCLUDE) bodytype_equip_flags |= BODY_FLAG_VOX diff --git a/nebula.dme b/nebula.dme index 5ad67597f52..991c94141e2 100644 --- a/nebula.dme +++ b/nebula.dme @@ -3156,6 +3156,7 @@ #include "code\modules\organs\external\diagnostics.dm" #include "code\modules\organs\external\head.dm" #include "code\modules\organs\external\insectoid.dm" +#include "code\modules\organs\external\quadruped.dm" #include "code\modules\organs\external\standard.dm" #include "code\modules\organs\external\tail.dm" #include "code\modules\organs\external\unbreakable.dm" @@ -3579,6 +3580,7 @@ #include "code\modules\species\species_bodytype.dm" #include "code\modules\species\species_bodytype_helpers.dm" #include "code\modules\species\species_bodytype_offsets.dm" +#include "code\modules\species\species_bodytype_quadruped.dm" #include "code\modules\species\species_bodytype_random.dm" #include "code\modules\species\species_crystalline_bodytypes.dm" #include "code\modules\species\species_getters.dm"