diff --git a/code/modules/clothing/shoes/_shoes.dm b/code/modules/clothing/shoes/_shoes.dm index b03d71221d..233a529dcf 100644 --- a/code/modules/clothing/shoes/_shoes.dm +++ b/code/modules/clothing/shoes/_shoes.dm @@ -15,6 +15,10 @@ var/offset = 0 var/equipped_before_drop = FALSE + //CITADEL EDIT Enables digitigrade shoe styles + var/adjusted = NORMAL_STYLE + var/mutantrace_variation = MUTANTRACE_VARIATION + /obj/item/clothing/shoes/ComponentInitialize() . = ..() AddComponent(/datum/component/redirect, list(COMSIG_COMPONENT_CLEAN_ACT = CALLBACK(src, .proc/clean_blood))) @@ -54,6 +58,16 @@ /obj/item/clothing/shoes/equipped(mob/user, slot) . = ..() + + if(mutantrace_variation && ishuman(user)) + var/mob/living/carbon/human/H = user + if(DIGITIGRADE in H.dna.species.species_traits) + adjusted = DIGITIGRADE_STYLE + H.update_inv_shoes() + else if(adjusted == DIGITIGRADE_STYLE) + adjusted = NORMAL_STYLE + H.update_inv_shoes() + if(offset && slot_flags & slotdefine2slotbit(slot)) user.pixel_y += offset worn_y_dimension -= (offset * 2) diff --git a/code/modules/mob/dead/new_player/sprite_accessories.dm b/code/modules/mob/dead/new_player/sprite_accessories.dm index ca9119eb43..ba41e1e55d 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories.dm @@ -1516,3 +1516,18 @@ /datum/sprite_accessory/moth_wings/snow name = "Snow" icon_state = "snow" + +//Lunasune +/datum/sprite_accessory/mam_ears/lunasune + name = "lunasune" + icon_state = "lunasune" + hasinner = 1 + extra = TRUE + extra_color_src = MUTCOLORS2 + ckeys_allowed = list("invader4352") + +/datum/sprite_accessory/mam_tails/lunasune + name = "lunasune" + icon_state = "lunasune" + extra = TRUE + ckeys_allowed = list("invader4352") diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index d6999ff5a4..1f68431771 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -922,9 +922,10 @@ GLOBAL_LIST_EMPTY(roundstart_races) if(num_legs < 2) return FALSE if(DIGITIGRADE in species_traits) - if(!disable_warning) - to_chat(H, "The footwear around here isn't compatible with your feet!") - return FALSE + if(!is_species(H, /datum/species/lizard/ashwalker)) + H.update_inv_shoes() + else + return FALSE return equip_delay_self_check(I, H, bypass_equip_delay_self) if(SLOT_BELT) if(H.belt) diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index cdc5259849..5590ce5321 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -1,688 +1,694 @@ - /////////////////////// - //UPDATE_ICONS SYSTEM// - /////////////////////// -/* Keep these comments up-to-date if you -insist- on hurting my code-baby ;_; -This system allows you to update individual mob-overlays, without regenerating them all each time. -When we generate overlays we generate the standing version and then rotate the mob as necessary.. - -As of the time of writing there are 20 layers within this list. Please try to keep this from increasing. //22 and counting, good job guys - var/overlays_standing[20] //For the standing stance - -Most of the time we only wish to update one overlay: - e.g. - we dropped the fireaxe out of our left hand and need to remove its icon from our mob - e.g.2 - our hair colour has changed, so we need to update our hair icons on our mob -In these cases, instead of updating every overlay using the old behaviour (regenerate_icons), we instead call -the appropriate update_X proc. - e.g. - update_l_hand() - e.g.2 - update_hair() - -Note: Recent changes by aranclanos+carn: - update_icons() no longer needs to be called. - the system is easier to use. update_icons() should not be called unless you absolutely -know- you need it. - IN ALL OTHER CASES it's better to just call the specific update_X procs. - -Note: The defines for layer numbers is now kept exclusvely in __DEFINES/misc.dm instead of being defined there, - then redefined and undefiend everywhere else. If you need to change the layering of sprites (or add a new layer) - that's where you should start. - -All of this means that this code is more maintainable, faster and still fairly easy to use. - -There are several things that need to be remembered: -> Whenever we do something that should cause an overlay to update (which doesn't use standard procs - ( i.e. you do something like l_hand = /obj/item/something new(src), rather than using the helper procs) - You will need to call the relevant update_inv_* proc - - All of these are named after the variable they update from. They are defined at the mob/ level like - update_clothing was, so you won't cause undefined proc runtimes with usr.update_inv_wear_id() if the usr is a - slime etc. Instead, it'll just return without doing any work. So no harm in calling it for slimes and such. - - -> There are also these special cases: - update_damage_overlays() //handles damage overlays for brute/burn damage - update_body() //Handles updating your mob's body layer and mutant bodyparts - as well as sprite-accessories that didn't really fit elsewhere (underwear, undershirts, socks, lips, eyes) - //NOTE: update_mutantrace() is now merged into this! - update_hair() //Handles updating your hair overlay (used to be update_face, but mouth and - eyes were merged into update_body()) - - -*/ - -//HAIR OVERLAY -/mob/living/carbon/human/update_hair() - dna.species.handle_hair(src) - -//used when putting/removing clothes that hide certain mutant body parts to just update those and not update the whole body. -/mob/living/carbon/human/proc/update_mutant_bodyparts() - dna.species.handle_mutant_bodyparts(src) - - -/mob/living/carbon/human/update_body() - remove_overlay(BODY_LAYER) - dna.species.handle_body(src) - ..() - -/mob/living/carbon/human/update_fire() - ..((fire_stacks > 3) ? "Standing" : "Generic_mob_burning") - - -/* --------------------------------------- */ -//For legacy support. -/mob/living/carbon/human/regenerate_icons() - - if(!..()) - icon_render_key = null //invalidate bodyparts cache - update_body() - update_hair() - update_inv_w_uniform() - update_inv_wear_id() - update_inv_gloves() - update_inv_glasses() - update_inv_ears() - update_inv_shoes() - update_inv_s_store() - update_inv_wear_mask() - update_inv_head() - update_inv_belt() - update_inv_back() - update_inv_wear_suit() - update_inv_pockets() - update_inv_neck() - update_transform() - //mutations - update_mutations_overlay() - //damage overlays - update_damage_overlays() - -/* --------------------------------------- */ -//vvvvvv UPDATE_INV PROCS vvvvvv - -/mob/living/carbon/human/update_inv_w_uniform() - remove_overlay(UNIFORM_LAYER) - - if(client && hud_used) - var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_W_UNIFORM] - inv.update_icon() - - if(istype(w_uniform, /obj/item/clothing/under)) - var/obj/item/clothing/under/U = w_uniform - U.screen_loc = ui_iclothing - if(client && hud_used && hud_used.hud_shown) - if(hud_used.inventory_shown) - client.screen += w_uniform - update_observer_view(w_uniform,1) - - if(wear_suit && (wear_suit.flags_inv & HIDEJUMPSUIT)) - return - - - var/t_color = U.item_color - if(!t_color) - t_color = U.icon_state - if(U.suit_style == NORMAL_SUIT_STYLE) - if(U.adjusted == ALT_STYLE) - t_color = "[t_color]_d" - - if(U.mutantrace_variation) - if(U.suit_style == DIGITIGRADE_SUIT_STYLE) - U.alternate_worn_icon = 'icons/mob/uniform_digi.dmi' - if(U.adjusted == ALT_STYLE) - t_color = "[t_color]_d_l" - else if(U.adjusted == NORMAL_STYLE) - t_color = "[t_color]_l" - - var/mutable_appearance/uniform_overlay - - if(dna && dna.species.sexes) - var/G = (gender == FEMALE) ? "f" : "m" - if(G == "f" && U.fitted != NO_FEMALE_UNIFORM) - uniform_overlay = U.build_worn_icon(state = "[t_color]", default_layer = UNIFORM_LAYER, default_icon_file = ((w_uniform.alternate_worn_icon) ? w_uniform.alternate_worn_icon : 'icons/mob/uniform.dmi'), isinhands = FALSE, femaleuniform = U.fitted) - - if(!uniform_overlay) - uniform_overlay = U.build_worn_icon(state = "[t_color]", default_layer = UNIFORM_LAYER, default_icon_file = ((w_uniform.alternate_worn_icon) ? w_uniform.alternate_worn_icon : 'icons/mob/uniform.dmi'), isinhands = FALSE) - - - if(OFFSET_UNIFORM in dna.species.offset_features) - uniform_overlay.pixel_x += dna.species.offset_features[OFFSET_UNIFORM][1] - uniform_overlay.pixel_y += dna.species.offset_features[OFFSET_UNIFORM][2] - overlays_standing[UNIFORM_LAYER] = uniform_overlay - - apply_overlay(UNIFORM_LAYER) - update_mutant_bodyparts() - - -/mob/living/carbon/human/update_inv_wear_id() - remove_overlay(ID_LAYER) - - if(client && hud_used) - var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_WEAR_ID] - inv.update_icon() - - var/mutable_appearance/id_overlay = overlays_standing[ID_LAYER] - - if(wear_id) - wear_id.screen_loc = ui_id - if(client && hud_used && hud_used.hud_shown) - client.screen += wear_id - update_observer_view(wear_id) - - //TODO: add an icon file for ID slot stuff, so it's less snowflakey - id_overlay = wear_id.build_worn_icon(state = wear_id.item_state, default_layer = ID_LAYER, default_icon_file = ((wear_id.alternate_worn_icon) ? wear_id.alternate_worn_icon : 'icons/mob/mob.dmi')) - if(OFFSET_ID in dna.species.offset_features) - id_overlay.pixel_x += dna.species.offset_features[OFFSET_ID][1] - id_overlay.pixel_y += dna.species.offset_features[OFFSET_ID][2] - overlays_standing[ID_LAYER] = id_overlay - apply_overlay(ID_LAYER) - - -/mob/living/carbon/human/update_inv_gloves() - remove_overlay(GLOVES_LAYER) - - if(client && hud_used && hud_used.inv_slots[SLOT_GLOVES]) - var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_GLOVES] - inv.update_icon() - - if(!gloves && bloody_hands) - var/mutable_appearance/bloody_overlay = mutable_appearance('icons/effects/blood.dmi', "bloodyhands", -GLOVES_LAYER) - if(get_num_arms() < 2) - if(has_left_hand()) - bloody_overlay.icon_state = "bloodyhands_left" - else if(has_right_hand()) - bloody_overlay.icon_state = "bloodyhands_right" - - overlays_standing[GLOVES_LAYER] = bloody_overlay - - var/mutable_appearance/gloves_overlay = overlays_standing[GLOVES_LAYER] - if(gloves) - gloves.screen_loc = ui_gloves - if(client && hud_used && hud_used.hud_shown) - if(hud_used.inventory_shown) - client.screen += gloves - update_observer_view(gloves,1) - var/t_state = gloves.item_state - if(!t_state) - t_state = gloves.icon_state - overlays_standing[GLOVES_LAYER] = gloves.build_worn_icon(state = t_state, default_layer = GLOVES_LAYER, default_icon_file = ((gloves.alternate_worn_icon) ? gloves.alternate_worn_icon : 'icons/mob/hands.dmi')) - gloves_overlay = overlays_standing[GLOVES_LAYER] - if(OFFSET_GLOVES in dna.species.offset_features) - gloves_overlay.pixel_x += dna.species.offset_features[OFFSET_GLOVES][1] - gloves_overlay.pixel_y += dna.species.offset_features[OFFSET_GLOVES][2] - overlays_standing[GLOVES_LAYER] = gloves_overlay - apply_overlay(GLOVES_LAYER) - - -/mob/living/carbon/human/update_inv_glasses() - remove_overlay(GLASSES_LAYER) - - if(!get_bodypart(BODY_ZONE_HEAD)) //decapitated - return - - if(client && hud_used) - var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_GLASSES] - inv.update_icon() - - if(glasses) - glasses.screen_loc = ui_glasses //...draw the item in the inventory screen - if(client && hud_used && hud_used.hud_shown) - if(hud_used.inventory_shown) //if the inventory is open ... - client.screen += glasses //Either way, add the item to the HUD - update_observer_view(glasses,1) - if(!(head && (head.flags_inv & HIDEEYES)) && !(wear_mask && (wear_mask.flags_inv & HIDEEYES))) - overlays_standing[GLASSES_LAYER] = glasses.build_worn_icon(state = glasses.icon_state, default_layer = GLASSES_LAYER, default_icon_file = ((glasses.alternate_worn_icon) ? glasses.alternate_worn_icon : 'icons/mob/eyes.dmi')) - var/mutable_appearance/glasses_overlay = overlays_standing[GLASSES_LAYER] - if(glasses_overlay) - if(OFFSET_GLASSES in dna.species.offset_features) - glasses_overlay.pixel_x += dna.species.offset_features[OFFSET_GLASSES][1] - glasses_overlay.pixel_y += dna.species.offset_features[OFFSET_GLASSES][2] - overlays_standing[GLASSES_LAYER] = glasses_overlay - apply_overlay(GLASSES_LAYER) - - -/mob/living/carbon/human/update_inv_ears() - remove_overlay(EARS_LAYER) - - if(!get_bodypart(BODY_ZONE_HEAD)) //decapitated - return - - if(client && hud_used) - var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_EARS] - inv.update_icon() - - if(ears) - ears.screen_loc = ui_ears //move the item to the appropriate screen loc - if(client && hud_used && hud_used.hud_shown) - if(hud_used.inventory_shown) //if the inventory is open - client.screen += ears //add it to the client's screen - update_observer_view(ears,1) - - overlays_standing[EARS_LAYER] = ears.build_worn_icon(state = ears.icon_state, default_layer = EARS_LAYER, default_icon_file = ((ears.alternate_worn_icon) ? ears.alternate_worn_icon : 'icons/mob/ears.dmi')) - var/mutable_appearance/ears_overlay = overlays_standing[EARS_LAYER] - if(OFFSET_EARS in dna.species.offset_features) - ears_overlay.pixel_x += dna.species.offset_features[OFFSET_EARS][1] - ears_overlay.pixel_y += dna.species.offset_features[OFFSET_EARS][2] - overlays_standing[EARS_LAYER] = ears_overlay - apply_overlay(EARS_LAYER) - - -/mob/living/carbon/human/update_inv_shoes() - remove_overlay(SHOES_LAYER) - - if(get_num_legs() <2) - return - - if(client && hud_used) - var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_SHOES] - inv.update_icon() - - if(shoes) - shoes.screen_loc = ui_shoes //move the item to the appropriate screen loc - if(client && hud_used && hud_used.hud_shown) - if(hud_used.inventory_shown) //if the inventory is open - client.screen += shoes //add it to client's screen - update_observer_view(shoes,1) - overlays_standing[SHOES_LAYER] = shoes.build_worn_icon(state = shoes.icon_state, default_layer = SHOES_LAYER, default_icon_file = ((shoes.alternate_worn_icon) ? shoes.alternate_worn_icon : 'icons/mob/feet.dmi')) - var/mutable_appearance/shoes_overlay = overlays_standing[SHOES_LAYER] - if(OFFSET_SHOES in dna.species.offset_features) - shoes_overlay.pixel_x += dna.species.offset_features[OFFSET_SHOES][1] - shoes_overlay.pixel_y += dna.species.offset_features[OFFSET_SHOES][2] - overlays_standing[SHOES_LAYER] = shoes_overlay - apply_overlay(SHOES_LAYER) - -/mob/living/carbon/human/update_inv_s_store() - remove_overlay(SUIT_STORE_LAYER) - - if(client && hud_used) - var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_S_STORE] - inv.update_icon() - - if(s_store) - s_store.screen_loc = ui_sstore1 - if(client && hud_used && hud_used.hud_shown) - client.screen += s_store - update_observer_view(s_store) - var/t_state = s_store.item_state - if(!t_state) - t_state = s_store.icon_state - overlays_standing[SUIT_STORE_LAYER] = mutable_appearance(((s_store.alternate_worn_icon) ? s_store.alternate_worn_icon : 'icons/mob/belt_mirror.dmi'), t_state, -SUIT_STORE_LAYER) - var/mutable_appearance/s_store_overlay = overlays_standing[SUIT_LAYER] - if(OFFSET_S_STORE in dna.species.offset_features) - s_store_overlay.pixel_x += dna.species.offset_features[OFFSET_S_STORE][1] - s_store_overlay.pixel_y += dna.species.offset_features[OFFSET_S_STORE][2] - overlays_standing[SUIT_STORE_LAYER] = s_store_overlay - apply_overlay(SUIT_STORE_LAYER) - - -/mob/living/carbon/human/update_inv_head() - ..() - update_mutant_bodyparts() - var/mutable_appearance/head_overlay = overlays_standing[HEAD_LAYER] - if(head_overlay) - remove_overlay(HEAD_LAYER) - if(OFFSET_HEAD in dna.species.offset_features) - head_overlay.pixel_x += dna.species.offset_features[OFFSET_HEAD][1] - head_overlay.pixel_y += dna.species.offset_features[OFFSET_HEAD][2] - overlays_standing[HEAD_LAYER] = head_overlay - apply_overlay(HEAD_LAYER) - -/mob/living/carbon/human/update_inv_belt() - remove_overlay(BELT_LAYER) - - if(client && hud_used) - var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_BELT] - inv.update_icon() - - if(belt) - belt.screen_loc = ui_belt - if(client && hud_used && hud_used.hud_shown) - client.screen += belt - update_observer_view(belt) - - var/t_state = belt.item_state - if(!t_state) - t_state = belt.icon_state - - overlays_standing[BELT_LAYER] = belt.build_worn_icon(state = t_state, default_layer = BELT_LAYER, default_icon_file = ((belt.alternate_worn_icon) ? belt.alternate_worn_icon : 'icons/mob/belt.dmi')) - var/mutable_appearance/belt_overlay = overlays_standing[BELT_LAYER] - if(OFFSET_BELT in dna.species.offset_features) - belt_overlay.pixel_x += dna.species.offset_features[OFFSET_BELT][1] - belt_overlay.pixel_y += dna.species.offset_features[OFFSET_BELT][2] - overlays_standing[BELT_LAYER] = belt_overlay - apply_overlay(BELT_LAYER) - - - -/mob/living/carbon/human/update_inv_wear_suit() - remove_overlay(SUIT_LAYER) - - if(client && hud_used) - var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_WEAR_SUIT] - inv.update_icon() - - if(istype(wear_suit, /obj/item/clothing/suit)) - wear_suit.screen_loc = ui_oclothing - if(client && hud_used && hud_used.hud_shown) - if(hud_used.inventory_shown) - client.screen += wear_suit - update_observer_view(wear_suit,1) - - overlays_standing[SUIT_LAYER] = wear_suit.build_worn_icon(state = wear_suit.icon_state, default_layer = SUIT_LAYER, default_icon_file = ((wear_suit.alternate_worn_icon) ? wear_suit.alternate_worn_icon : 'icons/mob/suit.dmi')) - var/mutable_appearance/suit_overlay = overlays_standing[SUIT_LAYER] - if(OFFSET_SUIT in dna.species.offset_features) - suit_overlay.pixel_x += dna.species.offset_features[OFFSET_SUIT][1] - suit_overlay.pixel_y += dna.species.offset_features[OFFSET_SUIT][2] - overlays_standing[SUIT_LAYER] = suit_overlay - update_hair() - update_mutant_bodyparts() - - apply_overlay(SUIT_LAYER) - - -/mob/living/carbon/human/update_inv_pockets() - if(client && hud_used) - var/obj/screen/inventory/inv - - inv = hud_used.inv_slots[SLOT_L_STORE] - inv.update_icon() - - inv = hud_used.inv_slots[SLOT_R_STORE] - inv.update_icon() - - if(l_store) - l_store.screen_loc = ui_storage1 - if(hud_used.hud_shown) - client.screen += l_store - update_observer_view(l_store) - - if(r_store) - r_store.screen_loc = ui_storage2 - if(hud_used.hud_shown) - client.screen += r_store - update_observer_view(r_store) - - -/mob/living/carbon/human/update_inv_wear_mask() - ..() - var/mutable_appearance/mask_overlay = overlays_standing[FACEMASK_LAYER] - if(mask_overlay) - remove_overlay(FACEMASK_LAYER) - if(OFFSET_FACEMASK in dna.species.offset_features) - mask_overlay.pixel_x += dna.species.offset_features[OFFSET_FACEMASK][1] - mask_overlay.pixel_y += dna.species.offset_features[OFFSET_FACEMASK][2] - overlays_standing[FACEMASK_LAYER] = mask_overlay - apply_overlay(FACEMASK_LAYER) - update_mutant_bodyparts() //e.g. upgate needed because mask now hides lizard snout - -/mob/living/carbon/human/update_inv_back() - ..() - var/mutable_appearance/back_overlay = overlays_standing[BACK_LAYER] - if(back_overlay) - remove_overlay(BACK_LAYER) - if(OFFSET_BACK in dna.species.offset_features) - back_overlay.pixel_x += dna.species.offset_features[OFFSET_BACK][1] - back_overlay.pixel_y += dna.species.offset_features[OFFSET_BACK][2] - overlays_standing[BACK_LAYER] = back_overlay - apply_overlay(BACK_LAYER) - -/mob/living/carbon/human/update_inv_legcuffed() - remove_overlay(LEGCUFF_LAYER) - clear_alert("legcuffed") - if(legcuffed) - overlays_standing[LEGCUFF_LAYER] = mutable_appearance('icons/mob/mob.dmi', "legcuff1", -LEGCUFF_LAYER) - apply_overlay(LEGCUFF_LAYER) - throw_alert("legcuffed", /obj/screen/alert/restrained/legcuffed, new_master = src.legcuffed) - -/proc/wear_female_version(t_color, icon, layer, type) - var/index = t_color - var/icon/female_clothing_icon = GLOB.female_clothing_icons[index] - if(!female_clothing_icon) //Create standing/laying icons if they don't exist - generate_female_clothing(index,t_color,icon,type) - return mutable_appearance(GLOB.female_clothing_icons[t_color], layer = -layer) - -/mob/living/carbon/human/proc/get_overlays_copy(list/unwantedLayers) - var/list/out = new - for(var/i in 1 to TOTAL_LAYERS) - if(overlays_standing[i]) - if(i in unwantedLayers) - continue - out += overlays_standing[i] - return out - - -//human HUD updates for items in our inventory - -//update whether our head item appears on our hud. -/mob/living/carbon/human/update_hud_head(obj/item/I) - I.screen_loc = ui_head - if(client && hud_used && hud_used.hud_shown) - if(hud_used.inventory_shown) - client.screen += I - update_observer_view(I,1) - -//update whether our mask item appears on our hud. -/mob/living/carbon/human/update_hud_wear_mask(obj/item/I) - I.screen_loc = ui_mask - if(client && hud_used && hud_used.hud_shown) - if(hud_used.inventory_shown) - client.screen += I - update_observer_view(I,1) - -//update whether our neck item appears on our hud. -/mob/living/carbon/human/update_hud_neck(obj/item/I) - I.screen_loc = ui_neck - if(client && hud_used && hud_used.hud_shown) - if(hud_used.inventory_shown) - client.screen += I - update_observer_view(I,1) - -//update whether our back item appears on our hud. -/mob/living/carbon/human/update_hud_back(obj/item/I) - I.screen_loc = ui_back - if(client && hud_used && hud_used.hud_shown) - client.screen += I - update_observer_view(I) - - - - -/* -Does everything in relation to building the /mutable_appearance used in the mob's overlays list -covers: - inhands and any other form of worn item - centering large appearances - layering appearances on custom layers - building appearances from custom icon files - -By Remie Richards (yes I'm taking credit because this just removed 90% of the copypaste in update_icons()) - -state: A string to use as the state, this is FAR too complex to solve in this proc thanks to shitty old code -so it's specified as an argument instead. - -default_layer: The layer to draw this on if no other layer is specified - -default_icon_file: The icon file to draw states from if no other icon file is specified - -isinhands: If true then alternate_worn_icon is skipped so that default_icon_file is used, -in this situation default_icon_file is expected to match either the lefthand_ or righthand_ file var - -femalueuniform: A value matching a uniform item's fitted var, if this is anything but NO_FEMALE_UNIFORM, we -generate/load female uniform sprites matching all previously decided variables - - -*/ -/obj/item/proc/build_worn_icon(var/state = "", var/default_layer = 0, var/default_icon_file = null, var/isinhands = FALSE, var/femaleuniform = NO_FEMALE_UNIFORM) - - //Find a valid icon file from variables+arguments - var/file2use - if(!isinhands && alternate_worn_icon) - file2use = alternate_worn_icon - if(!file2use) - file2use = default_icon_file - - //Find a valid layer from variables+arguments - var/layer2use - if(alternate_worn_layer) - layer2use = alternate_worn_layer - if(!layer2use) - layer2use = default_layer - - var/mutable_appearance/standing - if(femaleuniform) - standing = wear_female_version(state,file2use,layer2use,femaleuniform) - if(!standing) - standing = mutable_appearance(file2use, state, -layer2use) - - //Get the overlays for this item when it's being worn - //eg: ammo counters, primed grenade flashes, etc. - var/list/worn_overlays = worn_overlays(isinhands, file2use) - if(worn_overlays && worn_overlays.len) - standing.overlays.Add(worn_overlays) - - standing = center_image(standing, isinhands ? inhand_x_dimension : worn_x_dimension, isinhands ? inhand_y_dimension : worn_y_dimension) - - //Handle held offsets - var/mob/M = loc - if(istype(M)) - var/list/L = get_held_offsets() - if(L) - standing.pixel_x += L["x"] //+= because of center()ing - standing.pixel_y += L["y"] - - standing.alpha = alpha - standing.color = color - - return standing - - -/obj/item/proc/get_held_offsets() - var/list/L - if(ismob(loc)) - var/mob/M = loc - L = M.get_item_offsets_for_index(M.get_held_index_of_item(src)) - return L - - -//Can't think of a better way to do this, sadly -/mob/proc/get_item_offsets_for_index(i) - switch(i) - if(3) //odd = left hands - return list("x" = 0, "y" = 16) - if(4) //even = right hands - return list("x" = 0, "y" = 16) - else //No offsets or Unwritten number of hands - return list("x" = 0, "y" = 0) - - - -//produces a key based on the human's limbs -/mob/living/carbon/human/generate_icon_render_key() - . = "[dna.species.limbs_id]" - - if(dna.check_mutation(HULK)) - . += "-coloured-hulk" - else if(dna.species.use_skintones) - . += "-coloured-[skin_tone]" - else if(dna.species.fixed_mut_color) - . += "-coloured-[dna.species.fixed_mut_color]" - else if(dna.features["mcolor"]) - . += "-coloured-[dna.features["mcolor"]]" - else - . += "-not_coloured" - - . += "-[gender]" - - - var/is_taur = FALSE - var/mob/living/carbon/human/H = src - if(("taur" in H.dna.species.mutant_bodyparts) && (H.dna.features["taur"] != "None")) - is_taur = TRUE - - - for(var/X in bodyparts) - var/obj/item/bodypart/BP = X - - if(istype(BP, /obj/item/bodypart/r_leg) || istype(BP, /obj/item/bodypart/l_leg)) - if(is_taur) - continue - - - . += "-[BP.body_zone]" - if(BP.status == BODYPART_ORGANIC) - . += "-organic" - else - . += "-robotic" - if(BP.use_digitigrade) - . += "-digitigrade[BP.use_digitigrade]" - if(BP.dmg_overlay_type) - . += "-[BP.dmg_overlay_type]" - - if(has_trait(TRAIT_HUSK)) - . += "-husk" - -/mob/living/carbon/human/load_limb_from_cache() - ..() - update_hair() - - - -/mob/living/carbon/human/proc/update_observer_view(obj/item/I, inventory) - if(observers && observers.len) - for(var/M in observers) - var/mob/dead/observe = M - if(observe.client && observe.client.eye == src) - if(observe.hud_used) - if(inventory && !observe.hud_used.inventory_shown) - continue - observe.client.screen += I - else - observers -= observe - if(!observers.len) - observers = null - break - -// Only renders the head of the human -/mob/living/carbon/human/proc/update_body_parts_head_only() - if (!dna) - return - - if (!dna.species) - return - - var/obj/item/bodypart/HD = get_bodypart("head") - - if (!istype(HD)) - return - - HD.update_limb() - - add_overlay(HD.get_limb_icon()) - update_damage_overlays() - - if(HD && !(has_trait(TRAIT_HUSK))) - // lipstick - if(lip_style && (LIPS in dna.species.species_traits)) - var/mutable_appearance/lip_overlay = mutable_appearance('icons/mob/human_face.dmi', "lips_[lip_style]", -BODY_LAYER) - lip_overlay.color = lip_color - if(OFFSET_FACE in dna.species.offset_features) - lip_overlay.pixel_x += dna.species.offset_features[OFFSET_FACE][1] - lip_overlay.pixel_y += dna.species.offset_features[OFFSET_FACE][2] - add_overlay(lip_overlay) - - // eyes - if(!(NOEYES in dna.species.species_traits)) - var/has_eyes = getorganslot(ORGAN_SLOT_EYES) - var/mutable_appearance/eye_overlay - if(!has_eyes) - eye_overlay = mutable_appearance('icons/mob/human_face.dmi', "eyes_missing", -BODY_LAYER) - else - eye_overlay = mutable_appearance('icons/mob/human_face.dmi', "eyes", -BODY_LAYER) - if((EYECOLOR in dna.species.species_traits) && has_eyes) - eye_overlay.color = "#" + eye_color - if(OFFSET_FACE in dna.species.offset_features) - eye_overlay.pixel_x += dna.species.offset_features[OFFSET_FACE][1] - eye_overlay.pixel_y += dna.species.offset_features[OFFSET_FACE][2] - add_overlay(eye_overlay) - - dna.species.handle_hair(src) - - update_inv_head() - update_inv_wear_mask() + /////////////////////// + //UPDATE_ICONS SYSTEM// + /////////////////////// +/* Keep these comments up-to-date if you -insist- on hurting my code-baby ;_; +This system allows you to update individual mob-overlays, without regenerating them all each time. +When we generate overlays we generate the standing version and then rotate the mob as necessary.. + +As of the time of writing there are 20 layers within this list. Please try to keep this from increasing. //22 and counting, good job guys + var/overlays_standing[20] //For the standing stance + +Most of the time we only wish to update one overlay: + e.g. - we dropped the fireaxe out of our left hand and need to remove its icon from our mob + e.g.2 - our hair colour has changed, so we need to update our hair icons on our mob +In these cases, instead of updating every overlay using the old behaviour (regenerate_icons), we instead call +the appropriate update_X proc. + e.g. - update_l_hand() + e.g.2 - update_hair() + +Note: Recent changes by aranclanos+carn: + update_icons() no longer needs to be called. + the system is easier to use. update_icons() should not be called unless you absolutely -know- you need it. + IN ALL OTHER CASES it's better to just call the specific update_X procs. + +Note: The defines for layer numbers is now kept exclusvely in __DEFINES/misc.dm instead of being defined there, + then redefined and undefiend everywhere else. If you need to change the layering of sprites (or add a new layer) + that's where you should start. + +All of this means that this code is more maintainable, faster and still fairly easy to use. + +There are several things that need to be remembered: +> Whenever we do something that should cause an overlay to update (which doesn't use standard procs + ( i.e. you do something like l_hand = /obj/item/something new(src), rather than using the helper procs) + You will need to call the relevant update_inv_* proc + + All of these are named after the variable they update from. They are defined at the mob/ level like + update_clothing was, so you won't cause undefined proc runtimes with usr.update_inv_wear_id() if the usr is a + slime etc. Instead, it'll just return without doing any work. So no harm in calling it for slimes and such. + + +> There are also these special cases: + update_damage_overlays() //handles damage overlays for brute/burn damage + update_body() //Handles updating your mob's body layer and mutant bodyparts + as well as sprite-accessories that didn't really fit elsewhere (underwear, undershirts, socks, lips, eyes) + //NOTE: update_mutantrace() is now merged into this! + update_hair() //Handles updating your hair overlay (used to be update_face, but mouth and + eyes were merged into update_body()) + + +*/ + +//HAIR OVERLAY +/mob/living/carbon/human/update_hair() + dna.species.handle_hair(src) + +//used when putting/removing clothes that hide certain mutant body parts to just update those and not update the whole body. +/mob/living/carbon/human/proc/update_mutant_bodyparts() + dna.species.handle_mutant_bodyparts(src) + + +/mob/living/carbon/human/update_body() + remove_overlay(BODY_LAYER) + dna.species.handle_body(src) + ..() + +/mob/living/carbon/human/update_fire() + ..((fire_stacks > 3) ? "Standing" : "Generic_mob_burning") + + +/* --------------------------------------- */ +//For legacy support. +/mob/living/carbon/human/regenerate_icons() + + if(!..()) + icon_render_key = null //invalidate bodyparts cache + update_body() + update_hair() + update_inv_w_uniform() + update_inv_wear_id() + update_inv_gloves() + update_inv_glasses() + update_inv_ears() + update_inv_shoes() + update_inv_s_store() + update_inv_wear_mask() + update_inv_head() + update_inv_belt() + update_inv_back() + update_inv_wear_suit() + update_inv_pockets() + update_inv_neck() + update_transform() + //mutations + update_mutations_overlay() + //damage overlays + update_damage_overlays() + +/* --------------------------------------- */ +//vvvvvv UPDATE_INV PROCS vvvvvv + +/mob/living/carbon/human/update_inv_w_uniform() + remove_overlay(UNIFORM_LAYER) + + if(client && hud_used) + var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_W_UNIFORM] + inv.update_icon() + + if(istype(w_uniform, /obj/item/clothing/under)) + var/obj/item/clothing/under/U = w_uniform + U.screen_loc = ui_iclothing + if(client && hud_used && hud_used.hud_shown) + if(hud_used.inventory_shown) + client.screen += w_uniform + update_observer_view(w_uniform,1) + + if(wear_suit && (wear_suit.flags_inv & HIDEJUMPSUIT)) + return + + + var/t_color = U.item_color + if(!t_color) + t_color = U.icon_state + if(U.suit_style == NORMAL_SUIT_STYLE) + if(U.adjusted == ALT_STYLE) + t_color = "[t_color]_d" + + if(U.mutantrace_variation) + if(U.suit_style == DIGITIGRADE_SUIT_STYLE) + U.alternate_worn_icon = 'icons/mob/uniform_digi.dmi' + if(U.adjusted == ALT_STYLE) + t_color = "[t_color]_d_l" + else if(U.adjusted == NORMAL_STYLE) + t_color = "[t_color]_l" + + var/mutable_appearance/uniform_overlay + + if(dna && dna.species.sexes) + var/G = (gender == FEMALE) ? "f" : "m" + if(G == "f" && U.fitted != NO_FEMALE_UNIFORM) + uniform_overlay = U.build_worn_icon(state = "[t_color]", default_layer = UNIFORM_LAYER, default_icon_file = ((w_uniform.alternate_worn_icon) ? w_uniform.alternate_worn_icon : 'icons/mob/uniform.dmi'), isinhands = FALSE, femaleuniform = U.fitted) + + if(!uniform_overlay) + uniform_overlay = U.build_worn_icon(state = "[t_color]", default_layer = UNIFORM_LAYER, default_icon_file = ((w_uniform.alternate_worn_icon) ? w_uniform.alternate_worn_icon : 'icons/mob/uniform.dmi'), isinhands = FALSE) + + + if(OFFSET_UNIFORM in dna.species.offset_features) + uniform_overlay.pixel_x += dna.species.offset_features[OFFSET_UNIFORM][1] + uniform_overlay.pixel_y += dna.species.offset_features[OFFSET_UNIFORM][2] + overlays_standing[UNIFORM_LAYER] = uniform_overlay + + apply_overlay(UNIFORM_LAYER) + update_mutant_bodyparts() + + +/mob/living/carbon/human/update_inv_wear_id() + remove_overlay(ID_LAYER) + + if(client && hud_used) + var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_WEAR_ID] + inv.update_icon() + + var/mutable_appearance/id_overlay = overlays_standing[ID_LAYER] + + if(wear_id) + wear_id.screen_loc = ui_id + if(client && hud_used && hud_used.hud_shown) + client.screen += wear_id + update_observer_view(wear_id) + + //TODO: add an icon file for ID slot stuff, so it's less snowflakey + id_overlay = wear_id.build_worn_icon(state = wear_id.item_state, default_layer = ID_LAYER, default_icon_file = ((wear_id.alternate_worn_icon) ? wear_id.alternate_worn_icon : 'icons/mob/mob.dmi')) + if(OFFSET_ID in dna.species.offset_features) + id_overlay.pixel_x += dna.species.offset_features[OFFSET_ID][1] + id_overlay.pixel_y += dna.species.offset_features[OFFSET_ID][2] + overlays_standing[ID_LAYER] = id_overlay + apply_overlay(ID_LAYER) + + +/mob/living/carbon/human/update_inv_gloves() + remove_overlay(GLOVES_LAYER) + + if(client && hud_used && hud_used.inv_slots[SLOT_GLOVES]) + var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_GLOVES] + inv.update_icon() + + if(!gloves && bloody_hands) + var/mutable_appearance/bloody_overlay = mutable_appearance('icons/effects/blood.dmi', "bloodyhands", -GLOVES_LAYER) + if(get_num_arms() < 2) + if(has_left_hand()) + bloody_overlay.icon_state = "bloodyhands_left" + else if(has_right_hand()) + bloody_overlay.icon_state = "bloodyhands_right" + + overlays_standing[GLOVES_LAYER] = bloody_overlay + + var/mutable_appearance/gloves_overlay = overlays_standing[GLOVES_LAYER] + if(gloves) + gloves.screen_loc = ui_gloves + if(client && hud_used && hud_used.hud_shown) + if(hud_used.inventory_shown) + client.screen += gloves + update_observer_view(gloves,1) + var/t_state = gloves.item_state + if(!t_state) + t_state = gloves.icon_state + overlays_standing[GLOVES_LAYER] = gloves.build_worn_icon(state = t_state, default_layer = GLOVES_LAYER, default_icon_file = ((gloves.alternate_worn_icon) ? gloves.alternate_worn_icon : 'icons/mob/hands.dmi')) + gloves_overlay = overlays_standing[GLOVES_LAYER] + if(OFFSET_GLOVES in dna.species.offset_features) + gloves_overlay.pixel_x += dna.species.offset_features[OFFSET_GLOVES][1] + gloves_overlay.pixel_y += dna.species.offset_features[OFFSET_GLOVES][2] + overlays_standing[GLOVES_LAYER] = gloves_overlay + apply_overlay(GLOVES_LAYER) + + +/mob/living/carbon/human/update_inv_glasses() + remove_overlay(GLASSES_LAYER) + + if(!get_bodypart(BODY_ZONE_HEAD)) //decapitated + return + + if(client && hud_used) + var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_GLASSES] + inv.update_icon() + + if(glasses) + glasses.screen_loc = ui_glasses //...draw the item in the inventory screen + if(client && hud_used && hud_used.hud_shown) + if(hud_used.inventory_shown) //if the inventory is open ... + client.screen += glasses //Either way, add the item to the HUD + update_observer_view(glasses,1) + if(!(head && (head.flags_inv & HIDEEYES)) && !(wear_mask && (wear_mask.flags_inv & HIDEEYES))) + overlays_standing[GLASSES_LAYER] = glasses.build_worn_icon(state = glasses.icon_state, default_layer = GLASSES_LAYER, default_icon_file = ((glasses.alternate_worn_icon) ? glasses.alternate_worn_icon : 'icons/mob/eyes.dmi')) + var/mutable_appearance/glasses_overlay = overlays_standing[GLASSES_LAYER] + if(glasses_overlay) + if(OFFSET_GLASSES in dna.species.offset_features) + glasses_overlay.pixel_x += dna.species.offset_features[OFFSET_GLASSES][1] + glasses_overlay.pixel_y += dna.species.offset_features[OFFSET_GLASSES][2] + overlays_standing[GLASSES_LAYER] = glasses_overlay + apply_overlay(GLASSES_LAYER) + + +/mob/living/carbon/human/update_inv_ears() + remove_overlay(EARS_LAYER) + + if(!get_bodypart(BODY_ZONE_HEAD)) //decapitated + return + + if(client && hud_used) + var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_EARS] + inv.update_icon() + + if(ears) + ears.screen_loc = ui_ears //move the item to the appropriate screen loc + if(client && hud_used && hud_used.hud_shown) + if(hud_used.inventory_shown) //if the inventory is open + client.screen += ears //add it to the client's screen + update_observer_view(ears,1) + + overlays_standing[EARS_LAYER] = ears.build_worn_icon(state = ears.icon_state, default_layer = EARS_LAYER, default_icon_file = ((ears.alternate_worn_icon) ? ears.alternate_worn_icon : 'icons/mob/ears.dmi')) + var/mutable_appearance/ears_overlay = overlays_standing[EARS_LAYER] + if(OFFSET_EARS in dna.species.offset_features) + ears_overlay.pixel_x += dna.species.offset_features[OFFSET_EARS][1] + ears_overlay.pixel_y += dna.species.offset_features[OFFSET_EARS][2] + overlays_standing[EARS_LAYER] = ears_overlay + apply_overlay(EARS_LAYER) + + +/mob/living/carbon/human/update_inv_shoes() + remove_overlay(SHOES_LAYER) + + if(get_num_legs() <2) + return + + if(client && hud_used) + var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_SHOES] + inv.update_icon() + + if(shoes) + var/obj/item/clothing/shoes/S = shoes + shoes.screen_loc = ui_shoes //move the item to the appropriate screen loc + if(client && hud_used && hud_used.hud_shown) + if(hud_used.inventory_shown) //if the inventory is open + client.screen += shoes //add it to client's screen + update_observer_view(shoes,1) + if(S.adjusted == DIGITIGRADE_STYLE) + S.icon_override = 'modular_citadel/icons/mob/digishoes.dmi' + else if(S.adjusted == NORMAL_STYLE) + S.icon_override = null + + overlays_standing[SHOES_LAYER] = shoes.build_worn_icon(state = shoes.icon_state, default_layer = SHOES_LAYER, default_icon_file = ((shoes.icon_override) ? shoes.icon_override : 'icons/mob/feet.dmi')) + var/mutable_appearance/shoes_overlay = overlays_standing[SHOES_LAYER] + if(OFFSET_SHOES in dna.species.offset_features) + shoes_overlay.pixel_x += dna.species.offset_features[OFFSET_SHOES][1] + shoes_overlay.pixel_y += dna.species.offset_features[OFFSET_SHOES][2] + overlays_standing[SHOES_LAYER] = shoes_overlay + apply_overlay(SHOES_LAYER) + +/mob/living/carbon/human/update_inv_s_store() + remove_overlay(SUIT_STORE_LAYER) + + if(client && hud_used) + var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_S_STORE] + inv.update_icon() + + if(s_store) + s_store.screen_loc = ui_sstore1 + if(client && hud_used && hud_used.hud_shown) + client.screen += s_store + update_observer_view(s_store) + var/t_state = s_store.item_state + if(!t_state) + t_state = s_store.icon_state + overlays_standing[SUIT_STORE_LAYER] = mutable_appearance(((s_store.alternate_worn_icon) ? s_store.alternate_worn_icon : 'icons/mob/belt_mirror.dmi'), t_state, -SUIT_STORE_LAYER) + var/mutable_appearance/s_store_overlay = overlays_standing[SUIT_LAYER] + if(OFFSET_S_STORE in dna.species.offset_features) + s_store_overlay.pixel_x += dna.species.offset_features[OFFSET_S_STORE][1] + s_store_overlay.pixel_y += dna.species.offset_features[OFFSET_S_STORE][2] + overlays_standing[SUIT_STORE_LAYER] = s_store_overlay + apply_overlay(SUIT_STORE_LAYER) + + +/mob/living/carbon/human/update_inv_head() + ..() + update_mutant_bodyparts() + var/mutable_appearance/head_overlay = overlays_standing[HEAD_LAYER] + if(head_overlay) + remove_overlay(HEAD_LAYER) + if(OFFSET_HEAD in dna.species.offset_features) + head_overlay.pixel_x += dna.species.offset_features[OFFSET_HEAD][1] + head_overlay.pixel_y += dna.species.offset_features[OFFSET_HEAD][2] + overlays_standing[HEAD_LAYER] = head_overlay + apply_overlay(HEAD_LAYER) + +/mob/living/carbon/human/update_inv_belt() + remove_overlay(BELT_LAYER) + + if(client && hud_used) + var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_BELT] + inv.update_icon() + + if(belt) + belt.screen_loc = ui_belt + if(client && hud_used && hud_used.hud_shown) + client.screen += belt + update_observer_view(belt) + + var/t_state = belt.item_state + if(!t_state) + t_state = belt.icon_state + + overlays_standing[BELT_LAYER] = belt.build_worn_icon(state = t_state, default_layer = BELT_LAYER, default_icon_file = ((belt.alternate_worn_icon) ? belt.alternate_worn_icon : 'icons/mob/belt.dmi')) + var/mutable_appearance/belt_overlay = overlays_standing[BELT_LAYER] + if(OFFSET_BELT in dna.species.offset_features) + belt_overlay.pixel_x += dna.species.offset_features[OFFSET_BELT][1] + belt_overlay.pixel_y += dna.species.offset_features[OFFSET_BELT][2] + overlays_standing[BELT_LAYER] = belt_overlay + apply_overlay(BELT_LAYER) + + + +/mob/living/carbon/human/update_inv_wear_suit() + remove_overlay(SUIT_LAYER) + + if(client && hud_used) + var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_WEAR_SUIT] + inv.update_icon() + + if(istype(wear_suit, /obj/item/clothing/suit)) + wear_suit.screen_loc = ui_oclothing + if(client && hud_used && hud_used.hud_shown) + if(hud_used.inventory_shown) + client.screen += wear_suit + update_observer_view(wear_suit,1) + + overlays_standing[SUIT_LAYER] = wear_suit.build_worn_icon(state = wear_suit.icon_state, default_layer = SUIT_LAYER, default_icon_file = ((wear_suit.alternate_worn_icon) ? wear_suit.alternate_worn_icon : 'icons/mob/suit.dmi')) + var/mutable_appearance/suit_overlay = overlays_standing[SUIT_LAYER] + if(OFFSET_SUIT in dna.species.offset_features) + suit_overlay.pixel_x += dna.species.offset_features[OFFSET_SUIT][1] + suit_overlay.pixel_y += dna.species.offset_features[OFFSET_SUIT][2] + overlays_standing[SUIT_LAYER] = suit_overlay + update_hair() + update_mutant_bodyparts() + + apply_overlay(SUIT_LAYER) + + +/mob/living/carbon/human/update_inv_pockets() + if(client && hud_used) + var/obj/screen/inventory/inv + + inv = hud_used.inv_slots[SLOT_L_STORE] + inv.update_icon() + + inv = hud_used.inv_slots[SLOT_R_STORE] + inv.update_icon() + + if(l_store) + l_store.screen_loc = ui_storage1 + if(hud_used.hud_shown) + client.screen += l_store + update_observer_view(l_store) + + if(r_store) + r_store.screen_loc = ui_storage2 + if(hud_used.hud_shown) + client.screen += r_store + update_observer_view(r_store) + + +/mob/living/carbon/human/update_inv_wear_mask() + ..() + var/mutable_appearance/mask_overlay = overlays_standing[FACEMASK_LAYER] + if(mask_overlay) + remove_overlay(FACEMASK_LAYER) + if(OFFSET_FACEMASK in dna.species.offset_features) + mask_overlay.pixel_x += dna.species.offset_features[OFFSET_FACEMASK][1] + mask_overlay.pixel_y += dna.species.offset_features[OFFSET_FACEMASK][2] + overlays_standing[FACEMASK_LAYER] = mask_overlay + apply_overlay(FACEMASK_LAYER) + update_mutant_bodyparts() //e.g. upgate needed because mask now hides lizard snout + +/mob/living/carbon/human/update_inv_back() + ..() + var/mutable_appearance/back_overlay = overlays_standing[BACK_LAYER] + if(back_overlay) + remove_overlay(BACK_LAYER) + if(OFFSET_BACK in dna.species.offset_features) + back_overlay.pixel_x += dna.species.offset_features[OFFSET_BACK][1] + back_overlay.pixel_y += dna.species.offset_features[OFFSET_BACK][2] + overlays_standing[BACK_LAYER] = back_overlay + apply_overlay(BACK_LAYER) + +/mob/living/carbon/human/update_inv_legcuffed() + remove_overlay(LEGCUFF_LAYER) + clear_alert("legcuffed") + if(legcuffed) + overlays_standing[LEGCUFF_LAYER] = mutable_appearance('icons/mob/mob.dmi', "legcuff1", -LEGCUFF_LAYER) + apply_overlay(LEGCUFF_LAYER) + throw_alert("legcuffed", /obj/screen/alert/restrained/legcuffed, new_master = src.legcuffed) + +/proc/wear_female_version(t_color, icon, layer, type) + var/index = t_color + var/icon/female_clothing_icon = GLOB.female_clothing_icons[index] + if(!female_clothing_icon) //Create standing/laying icons if they don't exist + generate_female_clothing(index,t_color,icon,type) + return mutable_appearance(GLOB.female_clothing_icons[t_color], layer = -layer) + +/mob/living/carbon/human/proc/get_overlays_copy(list/unwantedLayers) + var/list/out = new + for(var/i in 1 to TOTAL_LAYERS) + if(overlays_standing[i]) + if(i in unwantedLayers) + continue + out += overlays_standing[i] + return out + + +//human HUD updates for items in our inventory + +//update whether our head item appears on our hud. +/mob/living/carbon/human/update_hud_head(obj/item/I) + I.screen_loc = ui_head + if(client && hud_used && hud_used.hud_shown) + if(hud_used.inventory_shown) + client.screen += I + update_observer_view(I,1) + +//update whether our mask item appears on our hud. +/mob/living/carbon/human/update_hud_wear_mask(obj/item/I) + I.screen_loc = ui_mask + if(client && hud_used && hud_used.hud_shown) + if(hud_used.inventory_shown) + client.screen += I + update_observer_view(I,1) + +//update whether our neck item appears on our hud. +/mob/living/carbon/human/update_hud_neck(obj/item/I) + I.screen_loc = ui_neck + if(client && hud_used && hud_used.hud_shown) + if(hud_used.inventory_shown) + client.screen += I + update_observer_view(I,1) + +//update whether our back item appears on our hud. +/mob/living/carbon/human/update_hud_back(obj/item/I) + I.screen_loc = ui_back + if(client && hud_used && hud_used.hud_shown) + client.screen += I + update_observer_view(I) + + + + +/* +Does everything in relation to building the /mutable_appearance used in the mob's overlays list +covers: + inhands and any other form of worn item + centering large appearances + layering appearances on custom layers + building appearances from custom icon files + +By Remie Richards (yes I'm taking credit because this just removed 90% of the copypaste in update_icons()) + +state: A string to use as the state, this is FAR too complex to solve in this proc thanks to shitty old code +so it's specified as an argument instead. + +default_layer: The layer to draw this on if no other layer is specified + +default_icon_file: The icon file to draw states from if no other icon file is specified + +isinhands: If true then alternate_worn_icon is skipped so that default_icon_file is used, +in this situation default_icon_file is expected to match either the lefthand_ or righthand_ file var + +femalueuniform: A value matching a uniform item's fitted var, if this is anything but NO_FEMALE_UNIFORM, we +generate/load female uniform sprites matching all previously decided variables + + +*/ +/obj/item/proc/build_worn_icon(var/state = "", var/default_layer = 0, var/default_icon_file = null, var/isinhands = FALSE, var/femaleuniform = NO_FEMALE_UNIFORM) + + //Find a valid icon file from variables+arguments + var/file2use + if(!isinhands && alternate_worn_icon) + file2use = alternate_worn_icon + if(!file2use) + file2use = default_icon_file + + //Find a valid layer from variables+arguments + var/layer2use + if(alternate_worn_layer) + layer2use = alternate_worn_layer + if(!layer2use) + layer2use = default_layer + + var/mutable_appearance/standing + if(femaleuniform) + standing = wear_female_version(state,file2use,layer2use,femaleuniform) + if(!standing) + standing = mutable_appearance(file2use, state, -layer2use) + + //Get the overlays for this item when it's being worn + //eg: ammo counters, primed grenade flashes, etc. + var/list/worn_overlays = worn_overlays(isinhands, file2use) + if(worn_overlays && worn_overlays.len) + standing.overlays.Add(worn_overlays) + + standing = center_image(standing, isinhands ? inhand_x_dimension : worn_x_dimension, isinhands ? inhand_y_dimension : worn_y_dimension) + + //Handle held offsets + var/mob/M = loc + if(istype(M)) + var/list/L = get_held_offsets() + if(L) + standing.pixel_x += L["x"] //+= because of center()ing + standing.pixel_y += L["y"] + + standing.alpha = alpha + standing.color = color + + return standing + + +/obj/item/proc/get_held_offsets() + var/list/L + if(ismob(loc)) + var/mob/M = loc + L = M.get_item_offsets_for_index(M.get_held_index_of_item(src)) + return L + + +//Can't think of a better way to do this, sadly +/mob/proc/get_item_offsets_for_index(i) + switch(i) + if(3) //odd = left hands + return list("x" = 0, "y" = 16) + if(4) //even = right hands + return list("x" = 0, "y" = 16) + else //No offsets or Unwritten number of hands + return list("x" = 0, "y" = 0) + + + +//produces a key based on the human's limbs +/mob/living/carbon/human/generate_icon_render_key() + . = "[dna.species.limbs_id]" + + if(dna.check_mutation(HULK)) + . += "-coloured-hulk" + else if(dna.species.use_skintones) + . += "-coloured-[skin_tone]" + else if(dna.species.fixed_mut_color) + . += "-coloured-[dna.species.fixed_mut_color]" + else if(dna.features["mcolor"]) + . += "-coloured-[dna.features["mcolor"]]" + else + . += "-not_coloured" + + . += "-[gender]" + + + var/is_taur = FALSE + var/mob/living/carbon/human/H = src + if(("taur" in H.dna.species.mutant_bodyparts) && (H.dna.features["taur"] != "None")) + is_taur = TRUE + + + for(var/X in bodyparts) + var/obj/item/bodypart/BP = X + + if(istype(BP, /obj/item/bodypart/r_leg) || istype(BP, /obj/item/bodypart/l_leg)) + if(is_taur) + continue + + + . += "-[BP.body_zone]" + if(BP.status == BODYPART_ORGANIC) + . += "-organic" + else + . += "-robotic" + if(BP.use_digitigrade) + . += "-digitigrade[BP.use_digitigrade]" + if(BP.dmg_overlay_type) + . += "-[BP.dmg_overlay_type]" + + if(has_trait(TRAIT_HUSK)) + . += "-husk" + +/mob/living/carbon/human/load_limb_from_cache() + ..() + update_hair() + + + +/mob/living/carbon/human/proc/update_observer_view(obj/item/I, inventory) + if(observers && observers.len) + for(var/M in observers) + var/mob/dead/observe = M + if(observe.client && observe.client.eye == src) + if(observe.hud_used) + if(inventory && !observe.hud_used.inventory_shown) + continue + observe.client.screen += I + else + observers -= observe + if(!observers.len) + observers = null + break + +// Only renders the head of the human +/mob/living/carbon/human/proc/update_body_parts_head_only() + if (!dna) + return + + if (!dna.species) + return + + var/obj/item/bodypart/HD = get_bodypart("head") + + if (!istype(HD)) + return + + HD.update_limb() + + add_overlay(HD.get_limb_icon()) + update_damage_overlays() + + if(HD && !(has_trait(TRAIT_HUSK))) + // lipstick + if(lip_style && (LIPS in dna.species.species_traits)) + var/mutable_appearance/lip_overlay = mutable_appearance('icons/mob/human_face.dmi', "lips_[lip_style]", -BODY_LAYER) + lip_overlay.color = lip_color + if(OFFSET_FACE in dna.species.offset_features) + lip_overlay.pixel_x += dna.species.offset_features[OFFSET_FACE][1] + lip_overlay.pixel_y += dna.species.offset_features[OFFSET_FACE][2] + add_overlay(lip_overlay) + + // eyes + if(!(NOEYES in dna.species.species_traits)) + var/has_eyes = getorganslot(ORGAN_SLOT_EYES) + var/mutable_appearance/eye_overlay + if(!has_eyes) + eye_overlay = mutable_appearance('icons/mob/human_face.dmi', "eyes_missing", -BODY_LAYER) + else + eye_overlay = mutable_appearance('icons/mob/human_face.dmi', "eyes", -BODY_LAYER) + if((EYECOLOR in dna.species.species_traits) && has_eyes) + eye_overlay.color = "#" + eye_color + if(OFFSET_FACE in dna.species.offset_features) + eye_overlay.pixel_x += dna.species.offset_features[OFFSET_FACE][1] + eye_overlay.pixel_y += dna.species.offset_features[OFFSET_FACE][2] + add_overlay(eye_overlay) + + dna.species.handle_hair(src) + + update_inv_head() + update_inv_wear_mask() diff --git a/code/modules/surgery/bodyparts/helpers.dm b/code/modules/surgery/bodyparts/helpers.dm index f7d4d063bc..566157d906 100644 --- a/code/modules/surgery/bodyparts/helpers.dm +++ b/code/modules/surgery/bodyparts/helpers.dm @@ -298,5 +298,10 @@ else U.suit_style = DIGITIGRADE_SUIT_STYLE H.update_inv_w_uniform() - if(H.shoes && !swap_back) - H.dropItemToGround(H.shoes) + if(H.shoes) + var/obj/item/clothing/shoes/S = H.shoes + if(swap_back) + S.adjusted = NORMAL_STYLE + else + S.adjusted = DIGITIGRADE_STYLE + H.update_inv_shoes() diff --git a/html/changelogs/AutoChangeLog-pr-7592.yml b/html/changelogs/AutoChangeLog-pr-7592.yml new file mode 100644 index 0000000000..10ba557d76 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-7592.yml @@ -0,0 +1,5 @@ +author: "Poojawa" +delete-after: True +changes: + - rscadd: "Digitigrade legs are now able to wear shoes and look fancy, Uniforms to come." + - tweak: "Xenos are only digitigrade now, mammals and aquatics have the option." diff --git a/icons/mob/custom_w.dmi b/icons/mob/custom_w.dmi index d1f69fe649..dc79247d48 100644 Binary files a/icons/mob/custom_w.dmi and b/icons/mob/custom_w.dmi differ diff --git a/icons/obj/custom.dmi b/icons/obj/custom.dmi index 75cdf427cd..197b870284 100644 Binary files a/icons/obj/custom.dmi and b/icons/obj/custom.dmi differ diff --git a/modular_citadel/code/modules/client/loadout/__donator.dm b/modular_citadel/code/modules/client/loadout/__donator.dm index be8398ec9a..8135532d85 100644 --- a/modular_citadel/code/modules/client/loadout/__donator.dm +++ b/modular_citadel/code/modules/client/loadout/__donator.dm @@ -326,3 +326,9 @@ datum/gear/darksabresheath category = SLOT_IN_BACKPACK path = /obj/item/toy/gun/m41 ckeywhitelist = list("thalverscholen") + +/datum/gear/Divine_robes + name = "Divine robes" + category = SLOT_W_UNIFORM + path = /obj/item/clothing/under/lunasune + ckeywhitelist = list("invader4352") \ No newline at end of file diff --git a/modular_citadel/code/modules/custom_loadout/custom_items.dm b/modular_citadel/code/modules/custom_loadout/custom_items.dm index 1f59019cc6..807dc064a5 100644 --- a/modular_citadel/code/modules/custom_loadout/custom_items.dm +++ b/modular_citadel/code/modules/custom_loadout/custom_items.dm @@ -397,3 +397,11 @@ desc = "Comfy Lucky Jackboots with the word Luck on them." item_state = "luckyjack" icon_state = "luckyjack" + +/obj/item/clothing/under/lunasune + name = "Divine Robes" + icon = 'icons/obj/custom.dmi' + icon_override = 'icons/mob/custom_w.dmi' + desc = "Heavenly robes of the kitsune Luna Pumpkin,you can feel radiance coming from them." + item_state = "Divine_robes" + icon_state = "Divine_robes" diff --git a/modular_citadel/code/modules/mob/dead/new_player/sprite_accessories.dm b/modular_citadel/code/modules/mob/dead/new_player/sprite_accessories.dm index e769a41491..0b4e744772 100644 --- a/modular_citadel/code/modules/mob/dead/new_player/sprite_accessories.dm +++ b/modular_citadel/code/modules/mob/dead/new_player/sprite_accessories.dm @@ -426,7 +426,7 @@ /datum/sprite_accessory/mam_tails icon = 'modular_citadel/icons/mob/mam_bodyparts.dmi' - + /datum/sprite_accessory/mam_tails/none name = "None" @@ -1432,7 +1432,27 @@ datum/sprite_accessory/mam_tails/tentacle extra2 = FALSE ckeys_allowed = list("poojawa") - + +//Lunasune +/datum/sprite_accessory/mam_ears/lunasune + name = "lunasune" + icon_state = "lunasune" + hasinner = 1 + extra = TRUE + extra_color_src = MUTCOLORS2 + ckeys_allowed = list("invader4352") + +/datum/sprite_accessory/mam_tails/lunasune + name = "lunasune" + icon_state = "lunasune" + extra = TRUE + ckeys_allowed = list("invader4352") + +/datum/sprite_accessory/mam_tails_animated/lunasune + name = "lunasune" + icon_state = "lunasune" + extra = TRUE + /*************** VIRGO PORTED HAIRS ****************************/ #define VHAIR(_name, new_state) /datum/sprite_accessory/hair/##new_state/icon_state=#new_state;/datum/sprite_accessory/hair/##new_state/name = "Virgo - " + #_name //VIRGO PORTED HAIRS @@ -1591,7 +1611,7 @@ VHAIR(Short Hair 4 alt, hair_shorthair4_s) VHAIR(Tressshoulder, hair_tressshoulder_s) //END #undef VHAIR - + #define VFACE(_name, new_state) /datum/sprite_accessory/facial_hair/##new_state/icon_state=#new_state;;/datum/sprite_accessory/facial_hair/##new_state/name="Virgo" + #_name VFACE(Watson, facial_watson_s) VFACE(Chaplin, facial_chaplin_s) diff --git a/modular_citadel/code/modules/mob/living/carbon/human/species_types/furrypeople.dm b/modular_citadel/code/modules/mob/living/carbon/human/species_types/furrypeople.dm index e533829ca1..456478ae63 100644 --- a/modular_citadel/code/modules/mob/living/carbon/human/species_types/furrypeople.dm +++ b/modular_citadel/code/modules/mob/living/carbon/human/species_types/furrypeople.dm @@ -221,10 +221,10 @@ id = "xeno" say_mod = "hisses" default_color = "00FF00" - species_traits = list(MUTCOLORS,EYECOLOR,LIPS) + species_traits = list(MUTCOLORS,EYECOLOR,LIPS,DIGITIGRADE) inherent_biotypes = list(MOB_ORGANIC, MOB_HUMANOID) - mutant_bodyparts = list("xenotail", "xenohead", "xenodorsal", "legs", "taur", "mam_body_markings") - default_features = list("xenotail"="Xenomorph Tail","xenohead"="Standard","xenodorsal"="Standard","mcolor" = "0F0","mcolor2" = "0F0","mcolor3" = "0F0","taur" = "None","mam_body_markings" = "Xeno", "legs" = "Digitigrade Legs") + mutant_bodyparts = list("xenotail", "xenohead", "xenodorsal", "taur", "mam_body_markings") + default_features = list("xenotail"="Xenomorph Tail","xenohead"="Standard","xenodorsal"="Standard","mcolor" = "0F0","mcolor2" = "0F0","mcolor3" = "0F0","taur" = "None","mam_body_markings" = "Xeno") attack_verb = "slash" attack_sound = 'sound/weapons/slash.ogg' miss_sound = 'sound/weapons/slashmiss.ogg' @@ -260,4 +260,4 @@ no_vore = TRUE /mob/living/carbon/human/vore - devourable = TRUE \ No newline at end of file + devourable = TRUE diff --git a/modular_citadel/icons/mob/digishoes.dmi b/modular_citadel/icons/mob/digishoes.dmi new file mode 100644 index 0000000000..49988f88f6 Binary files /dev/null and b/modular_citadel/icons/mob/digishoes.dmi differ diff --git a/modular_citadel/icons/mob/mam_bodyparts.dmi b/modular_citadel/icons/mob/mam_bodyparts.dmi index 268a3b30c2..de8da877f9 100644 Binary files a/modular_citadel/icons/mob/mam_bodyparts.dmi and b/modular_citadel/icons/mob/mam_bodyparts.dmi differ