Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added quadrupedal species handling. #3952

Merged
merged 1 commit into from
May 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions code/__defines/bodytype.dm
Original file line number Diff line number Diff line change
@@ -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"

Expand Down
6 changes: 6 additions & 0 deletions code/__defines/damage_organs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions code/__defines/flags.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
1 change: 0 additions & 1 deletion code/__defines/languages.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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.

6 changes: 3 additions & 3 deletions code/__defines/mobs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
1 change: 0 additions & 1 deletion code/_helpers/unsorted.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
19 changes: 10 additions & 9 deletions code/_onclick/hud/hud.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this if(length(swaphand_hud_objects)) check isn't strictly necessary because for (var/i in 1 to 0) will skip the loop body.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Length check is technically a microopt over a zero iteration loop so I'm happy to leave it. <_<

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()

Expand Down
5 changes: 3 additions & 2 deletions code/game/jobs/job/_job.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
44 changes: 35 additions & 9 deletions code/game/objects/item_mob_overlay.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
6 changes: 6 additions & 0 deletions code/game/objects/items/__item.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand All @@ -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.
Expand Down Expand Up @@ -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
2 changes: 1 addition & 1 deletion code/game/objects/items/weapons/cards_ids.dm
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ var/global/const/NO_EMAG_ACT = -50
dat += text("Blood Type: []<BR>\n", blood_type)
dat += text("DNA Hash: []<BR><BR>\n", dna_hash)
if(front && side)
dat +="<td align = center valign = top>Photo:<br><img src=front.png height=80 width=80 border=4><img src=side.png height=80 width=80 border=4></td>"
dat +="<td align = center valign = top>Photo:<br><img src=front.png width=80 border=4><img src=side.png width=80 border=4></td>"
dat += "</tr></table>"
return jointext(dat,null)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
21 changes: 11 additions & 10 deletions code/game/objects/structures/stool_bed_chair_nest_sofa/stools.dm
Original file line number Diff line number Diff line change
@@ -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
Expand Down
9 changes: 9 additions & 0 deletions code/modules/clothing/_clothing.dm
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
/obj/item/clothing/Initialize()

. = ..()
setup_equip_flags()

if(accessory_slot)
if(isnull(accessory_removable))
accessory_removable = TRUE
Expand Down Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion code/modules/clothing/head/_head.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions code/modules/clothing/suits/cloaks.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
1 change: 1 addition & 0 deletions code/modules/mob/living/carbon/carbon_defines.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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
24 changes: 21 additions & 3 deletions code/modules/mob/living/carbon/carbon_organs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand All @@ -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.
Expand Down
11 changes: 3 additions & 8 deletions code/modules/mob/living/carbon/human/human.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -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
2 changes: 0 additions & 2 deletions code/modules/mob/living/carbon/human/human_defines.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Loading
Loading