diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 2e228f3d571..e22ad5e66dc 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -1,1143 +1,35 @@ -/* - Global associative list for caching humanoid icons. - Index format m or f, followed by a string of 0 and 1 to represent bodyparts followed by husk fat hulk skeleton 1 or 0. - TODO: Proper documentation - icon_key is [species.race_key][g][husk][fat][hulk][skeleton][s_tone] -*/ -var/global/list/human_icon_cache = list() - - /////////////////////// - //UPDATE_ICONS SYSTEM// - /////////////////////// -/* -Calling this a system is perhaps a bit trumped up. It is essentially update_clothing dismantled into its -core parts. The key difference is that when we generate overlays we do not generate either lying or standing -versions. Instead, we generate both and store them in two fixed-length lists, both using the same list-index -(The indexes are in update_icons.dm): Each list for humans is (at the time of writing) of length 19. -This will hopefully be reduced as the system is refined. - - var/overlays_lying[19] //For the lying down stance - var/overlays_standing[19] //For the standing stance - -When we call update_icons, the 'lying' variable is checked and then the appropriate list is assigned to our overlays! -That in itself uses a tiny bit more memory (no more than all the ridiculous lists the game has already mind you). - -On the other-hand, it should be very CPU cheap in comparison to the old system. -In the old system, we updated all our overlays every life() call, even if we were standing still inside a crate! -or dead!. 25ish overlays, all generated from scratch every second for every xeno/human/monkey and then applied. -More often than not update_clothing was being called a few times in addition to that! CPU was not the only issue, -all those icons had to be sent to every client. So really the cost was extremely cumulative. To the point where -update_clothing would frequently appear in the top 10 most CPU intensive procs during profiling. - -Another feature of this new system is that our lists are indexed. This means we can update specific overlays! -So we only regenerate icons when we need them to be updated! This is the main saving for this system. - -In practice this means that: - everytime you fall over, we just switch between precompiled lists. Which is fast and cheap. - Everytime you do something minor like take a pen out of your pocket, we only update the in-hand overlay - etc... - - -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) ) - You will need to call the relevant update_inv_* proc: - update_inv_head() - update_inv_wear_suit() - update_inv_gloves() - update_inv_shoes() - update_inv_w_uniform() - update_inv_glasse() - update_inv_l_hand() - update_inv_r_hand() - update_inv_belt() - update_inv_wear_id() - update_inv_ears() - update_inv_s_store() - update_inv_pockets() - update_inv_back() - update_inv_handcuffed() - update_inv_wear_mask() - - 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_mutations() //handles updating your appearance for certain mutations. e.g TK head-glows - update_mutantrace() //handles updating your appearance after setting the mutantrace var - UpdateDamageIcon() //handles damage overlays for brute/burn damage //(will rename this when I geta round to it) - update_body() //Handles updating your mob's icon to reflect their gender/race/complexion etc - update_hair() //Handles updating your hair overlay (used to be update_face, but mouth and - ...eyes were merged into update_body) - update_targeted() // Updates the target overlay when someone points a gun at you - -> All of these procs update our overlays_lying and overlays_standing, and then call update_icons() by default. - If you wish to update several overlays at once, you can set the argument to 0 to disable the update and call - it manually: - e.g. - update_inv_head(0) - update_inv_l_hand(0) - update_inv_r_hand() //<---calls update_icons() - - or equivillantly: - update_inv_head(0) - update_inv_l_hand(0) - update_inv_r_hand(0) - update_icons() - -> If you need to update all overlays you can use regenerate_icons(). it works exactly like update_clothing used to. - -> I reimplimented an old unused variable which was in the code called (coincidentally) var/update_icon - It can be used as another method of triggering regenerate_icons(). It's basically a flag that when set to non-zero - will call regenerate_icons() at the next life() call and then reset itself to 0. - The idea behind it is icons are regenerated only once, even if multiple events requested it. - -This system is confusing and is still a WIP. It's primary goal is speeding up the controls of the game whilst -reducing processing costs. So please bear with me while I iron out the kinks. It will be worth it, I promise. -If I can eventually free var/lying stuff from the life() process altogether, stuns/death/status stuff -will become less affected by lag-spikes and will be instantaneous! :3 - -If you have any questions/constructive-comments/bugs-to-report/or have a massivly devestated butt... -Please contact me on #coderbus IRC. ~Carn x -*/ - -//Human Overlays Indexes///////// -#define MUTANTRACE_LAYER 1 -#define MARKINGS_LAYER 2 -#define MUTATIONS_LAYER 3 -#define DAMAGE_LAYER 4 -#define UNIFORM_LAYER 5 -#define ID_LAYER 6 -#define SHOES_LAYER 7 -#define GLOVES_LAYER 8 -#define EARS_LAYER 9 -#define SUIT_LAYER 10 -#define GLASSES_LAYER 11 -#define BELT_LAYER 12 //Possible make this an overlay of somethign required to wear a belt? -#define TAIL_LAYER 13 //bs12 specific. this hack is probably gonna come back to haunt me -#define SUIT_STORE_LAYER 14 -#define BACK_LAYER 15 -#define HAIR_LAYER 16 //TODO: make part of head layer? -#define HEAD_ACCESSORY_LAYER 17 -#define FHAIR_LAYER 18 -#define FACEMASK_LAYER 19 -#define HEAD_LAYER 20 -#define COLLAR_LAYER 21 -#define HANDCUFF_LAYER 22 -#define LEGCUFF_LAYER 23 -#define L_HAND_LAYER 24 -#define R_HAND_LAYER 25 -#define TARGETED_LAYER 26 //BS12: Layer for the target overlay from weapon targeting system -#define FIRE_LAYER 27 //If you're on fire -#define TOTAL_LAYERS 27 - - - -/mob/living/carbon/human - var/list/overlays_standing[TOTAL_LAYERS] - var/previous_damage_appearance // store what the body last looked like, so we only have to update it if something changed - var/icon/skeleton - - -/mob/living/carbon/human/proc/apply_overlay(cache_index) - var/image/I = overlays_standing[cache_index] - if(I) - overlays += I - -/mob/living/carbon/human/proc/remove_overlay(cache_index) - if(overlays_standing[cache_index]) - overlays -= overlays_standing[cache_index] - overlays_standing[cache_index] = null - -//UPDATES OVERLAYS FROM OVERLAYS_LYING/OVERLAYS_STANDING -//this proc is messy as I was forced to include some old laggy cloaking code to it so that I don't break cloakers -//I'll work on removing that stuff by rewriting some of the cloaking stuff at a later date. -/mob/living/carbon/human/update_icons() - - update_hud() //TODO: remove the need for this - - var/stealth = 0 - for(var/obj/item/weapon/cloaking_device/S in list(l_hand,r_hand,belt,l_store,r_store)) - if(S.active) - stealth = 1 - break - - if(stealth) - icon = 'icons/mob/human.dmi' - icon_state = "body_cloaked" - var/image/I = overlays_standing[L_HAND_LAYER] - if(istype(I)) overlays += I - I = overlays_standing[R_HAND_LAYER] - if(istype(I)) overlays += I - else - icon = stand_icon - if(overlays.len != overlays_standing.len) - overlays.Cut() - - for(var/thing in overlays_standing) - if(thing) overlays += thing - - update_transform() - -var/global/list/damage_icon_parts = list() - -//DAMAGE OVERLAYS -//constructs damage icon for each organ from mask * damage field and saves it in our overlays_ lists -/mob/living/carbon/human/UpdateDamageIcon(var/update_icons=1) - // first check whether something actually changed about damage appearance - var/damage_appearance = "" - - for(var/obj/item/organ/external/O in organs) - if(O.is_stump()) - continue - if(O.status & ORGAN_DESTROYED) damage_appearance += "d" - else - damage_appearance += O.damage_state - - if(damage_appearance == previous_damage_appearance) - // nothing to do here - return - - previous_damage_appearance = damage_appearance - - var/icon/standing = new /icon(species.damage_overlays, "00") - - var/image/standing_image = new /image("icon" = standing) - - // blend the individual damage states with our icons - for(var/obj/item/organ/external/O in organs) - if(O.is_stump()) - continue - if(!(O.status & ORGAN_DESTROYED)) - O.update_icon() - if(O.damage_state == "00") continue - var/icon/DI - var/cache_index = "[O.damage_state]/[O.icon_name]/[species.blood_color]/[species.name]" - - if(damage_icon_parts[cache_index] == null) - DI = new /icon(species.damage_overlays, O.damage_state) // the damage icon for whole human - DI.Blend(new /icon(species.damage_mask, O.icon_name), ICON_MULTIPLY) // mask with this organ's pixels - DI.Blend(species.blood_color, ICON_MULTIPLY) - damage_icon_parts[cache_index] = DI - else - DI = damage_icon_parts[cache_index] - standing_image.overlays += DI - - overlays_standing[DAMAGE_LAYER] = standing_image - - if(update_icons) update_icons() - -//BASE MOB SPRITE -/mob/living/carbon/human/proc/update_body(var/update_icons=1) - - var/husk_color_mod = rgb(96,88,80) - var/hulk_color_mod = rgb(48,224,40) - - var/husk = (HUSK in src.mutations) - var/fat = (FAT in src.mutations) - var/hulk = (HULK in src.mutations) - var/skeleton = (SKELETON in src.mutations) - - //CACHING: Generate an index key from visible bodyparts. - //0 = destroyed, 1 = normal, 2 = robotic, 3 = necrotic. - //Create a new, blank icon for our mob to use. - if(stand_icon) - qdel(stand_icon) - stand_icon = new(species.icon_template ? species.icon_template : 'icons/mob/human.dmi',"blank") - var/icon_key = "" - var/obj/item/organ/eyes/eyes = internal_organs_by_name["eyes"] - - if(eyes) - icon_key += "[rgb(eyes.eye_colour[1], eyes.eye_colour[2], eyes.eye_colour[3])]" - else - icon_key += "#000000" - - for(var/organ_tag in species.has_limbs) - var/obj/item/organ/external/part = organs_by_name[organ_tag] - if(isnull(part) || part.is_stump() || (part.status & ORGAN_DESTROYED)) - icon_key += "0" - else if(part.status & ORGAN_ROBOT) - icon_key += "2[part.model ? "-[part.model]": ""]" - else if(part.status & ORGAN_DEAD) - icon_key += "3" - else - icon_key += "1" - - if(part) - icon_key += "[part.species.race_key]" - icon_key += "[part.dna.GetUIState(DNA_UI_GENDER)]" - icon_key += "[part.dna.GetUIValue(DNA_UI_SKIN_TONE)]" - if(part.s_col) - icon_key += "[rgb(part.s_col[1], part.s_col[2], part.s_col[3])]" - - icon_key = "[icon_key][husk ? 1 : 0][fat ? 1 : 0][hulk ? 1 : 0][skeleton ? 1 : 0]" - - var/icon/base_icon - if(human_icon_cache[icon_key]) - base_icon = human_icon_cache[icon_key] - else - //BEGIN CACHED ICON GENERATION. - var/obj/item/organ/external/chest = get_organ("chest") - base_icon = chest.get_icon() - - for(var/obj/item/organ/external/part in organs) - var/icon/temp = part.get_icon(skeleton) - //That part makes left and right legs drawn topmost and lowermost when human looks WEST or EAST - //And no change in rendering for other parts (they icon_position is 0, so goes to 'else' part) - if(part.icon_position&(LEFT|RIGHT)) - var/icon/temp2 = new('icons/mob/human.dmi',"blank") - temp2.Insert(new/icon(temp,dir=NORTH),dir=NORTH) - temp2.Insert(new/icon(temp,dir=SOUTH),dir=SOUTH) - if(!(part.icon_position & LEFT)) - temp2.Insert(new/icon(temp,dir=EAST),dir=EAST) - if(!(part.icon_position & RIGHT)) - temp2.Insert(new/icon(temp,dir=WEST),dir=WEST) - base_icon.Blend(temp2, ICON_OVERLAY) - if(part.icon_position & LEFT) - temp2.Insert(new/icon(temp,dir=EAST),dir=EAST) - if(part.icon_position & RIGHT) - temp2.Insert(new/icon(temp,dir=WEST),dir=WEST) - base_icon.Blend(temp2, ICON_UNDERLAY) - else - base_icon.Blend(temp, ICON_OVERLAY) - - if(!skeleton) - if(husk) - base_icon.ColorTone(husk_color_mod) - else if(hulk) - var/list/tone = ReadRGB(hulk_color_mod) - base_icon.MapColors(rgb(tone[1],0,0),rgb(0,tone[2],0),rgb(0,0,tone[3])) - - //Handle husk overlay. - if(husk && ("overlay_husk" in icon_states(species.icobase))) - var/icon/mask = new(base_icon) - var/icon/husk_over = new(species.icobase,"overlay_husk") - mask.MapColors(0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,0) - husk_over.Blend(mask, ICON_ADD) - base_icon.Blend(husk_over, ICON_OVERLAY) - - human_icon_cache[icon_key] = base_icon - - //END CACHED ICON GENERATION. - stand_icon.Blend(base_icon,ICON_OVERLAY) - - //Underwear - if(underwear && species.clothing_flags & HAS_UNDERWEAR) - var/datum/sprite_accessory/underwear/U = underwear_list[underwear] - if(U) - stand_icon.Blend(new /icon(U.icon, "uw_[U.icon_state]_s"), ICON_OVERLAY) - - if(undershirt && species.clothing_flags & HAS_UNDERSHIRT) - var/datum/sprite_accessory/undershirt/U2 = undershirt_list[undershirt] - if(U2) - stand_icon.Blend(new /icon(U2.icon, "us_[U2.icon_state]_s"), ICON_OVERLAY) - - - if(socks && species.clothing_flags & HAS_SOCKS) - var/datum/sprite_accessory/socks/U3 = socks_list[socks] - if(U3) - stand_icon.Blend(new /icon(U3.icon, "sk_[U3.icon_state]_s"), ICON_OVERLAY) - - - if(update_icons) - update_icons() - - if(lip_style && species && species.flags & HAS_LIPS) - var/icon/lips = icon("icon"='icons/mob/human_face.dmi', "icon_state"="lips_[lip_style]_s") - lips.Blend(lip_color, ICON_ADD) - - stand_icon.Blend(lips, ICON_OVERLAY) - - //tail - update_tail_layer(0) - //head accessory - update_head_accessory(0) - //markings - update_markings(0) - //hair - update_hair(0) - update_fhair(0) - - -//MARKINGS OVERLAY -/mob/living/carbon/human/proc/update_markings(var/update_icons=1) - //Reset our markings - overlays_standing[MARKINGS_LAYER] = null - - var/obj/item/organ/external/chest/chest_organ = get_organ("chest") - if(!chest_organ || chest_organ.is_stump() || (chest_organ.status & ORGAN_DESTROYED) ) - if(update_icons) update_icons() - return - - //base icons - var/icon/markings_standing = new /icon('icons/mob/body_accessory.dmi',"accessory_none_s") - - if(m_style && (src.species.bodyflags & HAS_MARKINGS)) - var/datum/sprite_accessory/marking_style = marking_styles_list[m_style] - if(marking_style && marking_style.species_allowed) - if(src.species.name in marking_style.species_allowed) - var/icon/markings_s = new/icon("icon" = marking_style.icon, "icon_state" = "[marking_style.icon_state]_s") - if(marking_style.do_colouration) - markings_s.Blend(rgb(r_markings, g_markings, b_markings), ICON_ADD) - markings_standing.Blend(markings_s, ICON_OVERLAY) - else - //warning("Invalid m_style for [species.name]: [m_style]") - - overlays_standing[MARKINGS_LAYER] = image(markings_standing) - - if(update_icons) update_icons() - -//HEAD ACCESSORY OVERLAY -/mob/living/carbon/human/proc/update_head_accessory(var/update_icons=1) - //Reset our head accessory - overlays_standing[HEAD_ACCESSORY_LAYER] = null - - var/obj/item/organ/external/head/head_organ = get_organ("head") - if(!head_organ || head_organ.is_stump() || (head_organ.status & ORGAN_DESTROYED) ) - if(update_icons) update_icons() - return - - //masks and helmets can obscure our head accessory - if( (head && (head.flags & BLOCKHAIR)) || (wear_mask && (wear_mask.flags & BLOCKHAIR))) - if(update_icons) update_icons() - return - - //base icons - var/icon/head_accessory_standing = new /icon('icons/mob/body_accessory.dmi',"accessory_none_s") - - if(ha_style && !(head && (head.flags & BLOCKHEADHAIR) && !(isSynthetic()) && (src.species.bodyflags & HAS_HEAD_ACCESSORY))) - var/datum/sprite_accessory/head_accessory_style = head_accessory_styles_list[ha_style] - if(head_accessory_style && head_accessory_style.species_allowed) - if(src.species.name in head_accessory_style.species_allowed) - var/icon/head_accessory_s = new/icon("icon" = head_accessory_style.icon, "icon_state" = "[head_accessory_style.icon_state]_s") - if(head_accessory_style.do_colouration) - head_accessory_s.Blend(rgb(r_headacc, g_headacc, b_headacc), ICON_ADD) - head_accessory_standing.Blend(head_accessory_s, ICON_OVERLAY) - else - //warning("Invalid ha_style for [species.name]: [ha_style]") - - overlays_standing[HEAD_ACCESSORY_LAYER] = image(head_accessory_standing) - - if(update_icons) update_icons() - - -//HAIR OVERLAY -/mob/living/carbon/human/proc/update_hair(var/update_icons=1) - //Reset our hair - overlays_standing[HAIR_LAYER] = null - - var/obj/item/organ/external/head/head_organ = get_organ("head") - if(!head_organ || head_organ.is_stump() || (head_organ.status & ORGAN_DESTROYED) ) - if(update_icons) update_icons() - return - - //masks and helmets can obscure our hair, unless we're a synthetic - if( (head && (head.flags & BLOCKHAIR)) || (wear_mask && (wear_mask.flags & BLOCKHAIR))) - if(update_icons) update_icons() - return - - //base icons - var/icon/hair_standing = new /icon('icons/mob/human_face.dmi',"bald_s") - - if(h_style && !(head && (head.flags & BLOCKHEADHAIR) && !(isSynthetic()))) - var/datum/sprite_accessory/hair_style = hair_styles_list[h_style] - if(hair_style && hair_style.species_allowed) - if(src.species.name in hair_style.species_allowed) - var/icon/hair_s = new/icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s") - if(hair_style.do_colouration) - hair_s.Blend(rgb(r_hair, g_hair, b_hair), ICON_ADD) - - hair_standing.Blend(hair_s, ICON_OVERLAY) - else - //warning("Invalid h_style for [species.name]: [h_style]") - - overlays_standing[HAIR_LAYER] = image(hair_standing) - - if(update_icons) update_icons() - - -//FACIAL HAIR OVERLAY -/mob/living/carbon/human/proc/update_fhair(var/update_icons=1) - //Reset our facial hair - overlays_standing[FHAIR_LAYER] = null - - var/obj/item/organ/external/head/head_organ = get_organ("head") - if(!head_organ || head_organ.is_stump() || (head_organ.status & ORGAN_DESTROYED) ) - if(update_icons) update_icons() - return - - //masks and helmets can obscure our facial hair, unless we're a synthetic - if( (head && (head.flags & BLOCKHAIR)) || (wear_mask && (wear_mask.flags & BLOCKHAIR))) - if(update_icons) update_icons() - return - - //base icons - var/icon/face_standing = new /icon('icons/mob/human_face.dmi',"bald_s") - - if(f_style) - var/datum/sprite_accessory/facial_hair_style = facial_hair_styles_list[f_style] - if(facial_hair_style && facial_hair_style.species_allowed) - if(src.species.name in facial_hair_style.species_allowed) - var/icon/facial_s = new/icon("icon" = facial_hair_style.icon, "icon_state" = "[facial_hair_style.icon_state]_s") - if(facial_hair_style.do_colouration) - facial_s.Blend(rgb(r_facial, g_facial, b_facial), ICON_ADD) - face_standing.Blend(facial_s, ICON_OVERLAY) - else - //warning("Invalid f_style for [species.name]: [f_style]") - - overlays_standing[FHAIR_LAYER] = image(face_standing) - - if(update_icons) update_icons() - -/mob/living/carbon/human/update_mutations(var/update_icons=1) - var/fat - if(FAT in mutations) - fat = "fat" - - var/image/standing = image("icon" = 'icons/effects/genetics.dmi') - var/add_image = 0 - var/g = "m" - if(gender == FEMALE) g = "f" - // DNA2 - Drawing underlays. - for(var/datum/dna/gene/gene in dna_genes) - if(!gene.block) - continue - if(gene.is_active(src)) - var/underlay=gene.OnDrawUnderlays(src,g,fat) - if(underlay) - standing.underlays += underlay - add_image = 1 - for(var/mut in mutations) - switch(mut) - /* - if(HULK) - if(fat) - standing.underlays += "hulk_[fat]_s" - else - standing.underlays += "hulk_[g]_s" - add_image = 1 - if(RESIST_COLD) - standing.underlays += "fire[fat]_s" - add_image = 1 - if(RESIST_HEAT) - standing.underlays += "cold[fat]_s" - add_image = 1 - if(TK) - standing.underlays += "telekinesishead[fat]_s" - add_image = 1 - */ - if(LASER) - standing.overlays += "lasereyes_s" - add_image = 1 - if((RESIST_COLD in mutations) && (RESIST_HEAT in mutations)) - standing.underlays -= "cold[fat]_s" - standing.underlays -= "fire[fat]_s" - standing.underlays += "coldfire[fat]_s" - if(add_image) - overlays_standing[MUTATIONS_LAYER] = standing - else - overlays_standing[MUTATIONS_LAYER] = null - if(update_icons) update_icons() - - -/mob/living/carbon/human/proc/update_mutantrace(var/update_icons=1) -//BS12 EDIT - var/skel = (SKELETON in src.mutations) - if(skel) - skeleton = 'icons/mob/human_races/r_skeleton.dmi' - else - skeleton = null - - update_hair(0) - update_fhair(0) - if(update_icons) update_icons() - -//Call when target overlay should be added/removed -/mob/living/carbon/human/update_targeted(var/update_icons=1) - if (targeted_by && target_locked) - overlays_standing[TARGETED_LAYER] = target_locked - else if (!targeted_by && target_locked) - qdel(target_locked) - if (!targeted_by) - overlays_standing[TARGETED_LAYER] = null - if(update_icons) update_icons() - -/mob/living/carbon/human/update_fire() - remove_overlay(FIRE_LAYER) - if(on_fire) - overlays_standing[FIRE_LAYER] = image("icon"=fire_dmi, "icon_state"=fire_sprite, "layer"=-FIRE_LAYER) - else - overlays_standing[FIRE_LAYER] = null - apply_overlay(FIRE_LAYER) - -/* --------------------------------------- */ -//For legacy support. -/mob/living/carbon/human/regenerate_icons() - ..() - if(notransform) return - update_mutations(0) - update_body(0) - update_hair(0) - update_head_accessory(0) - update_fhair(0) - update_mutantrace(0) - update_inv_w_uniform(0,0) - update_inv_wear_id(0) - update_inv_gloves(0,0) - update_inv_glasses(0) - update_inv_ears(0) - update_inv_shoes(0,0) - update_inv_s_store(0) - update_inv_wear_mask(0) - update_inv_head(0,0) - update_inv_belt(0) - update_inv_back(0) - update_inv_wear_suit(0) - update_inv_r_hand(0) - update_inv_l_hand(0) - update_inv_handcuffed(0) - update_inv_legcuffed(0) - update_inv_pockets(0) - update_inv_wear_pda(0) - UpdateDamageIcon() - update_icons() - //Hud Stuff - update_hud() - update_fire() -/* --------------------------------------- */ -//vvvvvv UPDATE_INV PROCS vvvvvv - -/mob/living/carbon/human/update_inv_w_uniform(var/update_icons=1) - if(w_uniform && istype(w_uniform, /obj/item/clothing/under) ) - w_uniform.screen_loc = ui_iclothing - var/t_color = w_uniform.item_color - if(!t_color) t_color = icon_state - var/image/standing = image("icon_state" = "[t_color]_s") - - if(FAT in mutations) - if(w_uniform.flags&ONESIZEFITSALL) - standing.icon = 'icons/mob/uniform_fat.dmi' - else - src << "\red You burst out of \the [w_uniform]!" - unEquip(w_uniform) - return - else - standing.icon = 'icons/mob/uniform.dmi' - - if(w_uniform.icon_override) - standing.icon = w_uniform.icon_override - else if(w_uniform.sprite_sheets && w_uniform.sprite_sheets[species.name]) - standing.icon = w_uniform.sprite_sheets[species.name] - - if(w_uniform.blood_DNA) - var/image/bloodsies = image("icon" = species.blood_mask, "icon_state" = "uniformblood") - bloodsies.color = w_uniform.blood_color - standing.overlays += bloodsies - - if(w_uniform:accessories.len) //WE CHECKED THE TYPE ABOVE. THIS REALLY SHOULD BE FINE. - for(var/obj/item/clothing/accessory/A in w_uniform:accessories) - var/tie_color = A.item_color - if(!tie_color) tie_color = A.icon_state - standing.overlays += image("icon" = 'icons/mob/ties.dmi', "icon_state" = "[tie_color]") - - overlays_standing[UNIFORM_LAYER] = standing - else - overlays_standing[UNIFORM_LAYER] = null - // Automatically drop anything in store / id / belt if you're not wearing a uniform. //CHECK IF NECESARRY - for( var/obj/item/thing in list(r_store, l_store, wear_id, wear_pda, belt) ) // - if(thing) // - unEquip(thing) // - if (client) // - client.screen -= thing // - // - if (thing) // - thing.loc = loc // - thing.dropped(src) // - thing.layer = initial(thing.layer) - if(update_icons) update_icons() - -/mob/living/carbon/human/update_inv_wear_id(var/update_icons=1) - if(wear_id) - wear_id.screen_loc = ui_id //TODO - if(w_uniform && w_uniform:displays_id) - overlays_standing[ID_LAYER] = image("icon" = 'icons/mob/mob.dmi', "icon_state" = "id") - else - overlays_standing[ID_LAYER] = null - else - overlays_standing[ID_LAYER] = null - - if(update_icons) update_icons() - -/mob/living/carbon/human/update_inv_gloves(var/update_icons=1) - if(gloves) - var/t_state = gloves.item_state - if(!t_state) t_state = gloves.icon_state - - var/image/standing - if(gloves.icon_override) - standing = image("icon" = gloves.icon_override, "icon_state" = "[t_state]") - else if(gloves.sprite_sheets && gloves.sprite_sheets[species.name]) - standing = image("icon" = gloves.sprite_sheets[species.name], "icon_state" = "[t_state]") - else - standing = image("icon" = 'icons/mob/hands.dmi', "icon_state" = "[t_state]") - - if(gloves.blood_DNA) - var/image/bloodsies = image("icon" = species.blood_mask, "icon_state" = "bloodyhands") - bloodsies.color = gloves.blood_color - standing.overlays += bloodsies - gloves.screen_loc = ui_gloves - overlays_standing[GLOVES_LAYER] = standing - else - if(blood_DNA) - var/image/bloodsies = image("icon" = species.blood_mask, "icon_state" = "bloodyhands") - bloodsies.color = hand_blood_color - overlays_standing[GLOVES_LAYER] = bloodsies - else - overlays_standing[GLOVES_LAYER] = null - if(update_icons) update_icons() - - -/mob/living/carbon/human/update_inv_glasses(var/update_icons=1) - if(glasses) - - if(glasses.icon_override) - overlays_standing[GLASSES_LAYER] = image("icon" = glasses.icon_override, "icon_state" = "[glasses.icon_state]") - else if(glasses.sprite_sheets && glasses.sprite_sheets[species.name]) - overlays_standing[GLASSES_LAYER]= image("icon" = glasses.sprite_sheets[species.name], "icon_state" = "[glasses.icon_state]") - else - overlays_standing[GLASSES_LAYER]= image("icon" = 'icons/mob/eyes.dmi', "icon_state" = "[glasses.icon_state]") - - else - overlays_standing[GLASSES_LAYER] = null - if(update_icons) update_icons() - -/mob/living/carbon/human/update_inv_ears(var/update_icons=1) - if(l_ear || r_ear) - if(l_ear) - - var/t_type = l_ear.icon_state - if(l_ear.icon_override) - t_type = "[t_type]_l" - overlays_standing[EARS_LAYER] = image("icon" = l_ear.icon_override, "icon_state" = "[t_type]") - else if(l_ear.sprite_sheets && l_ear.sprite_sheets[species.name]) - t_type = "[t_type]_l" - overlays_standing[EARS_LAYER] = image("icon" = l_ear.sprite_sheets[species.name], "icon_state" = "[t_type]") - else - overlays_standing[EARS_LAYER] = image("icon" = 'icons/mob/ears.dmi', "icon_state" = "[t_type]") - - if(r_ear) - - var/t_type = r_ear.icon_state - if(r_ear.icon_override) - t_type = "[t_type]_r" - overlays_standing[EARS_LAYER] = image("icon" = r_ear.icon_override, "icon_state" = "[t_type]") - else if(r_ear.sprite_sheets && r_ear.sprite_sheets[species.name]) - t_type = "[t_type]_r" - overlays_standing[EARS_LAYER] = image("icon" = r_ear.sprite_sheets[species.name], "icon_state" = "[t_type]") - else - overlays_standing[EARS_LAYER] = image("icon" = 'icons/mob/ears.dmi', "icon_state" = "[t_type]") - - else - overlays_standing[EARS_LAYER] = null - if(update_icons) update_icons() - -/mob/living/carbon/human/update_inv_shoes(var/update_icons=1) - if(shoes) - - var/image/standing - if(shoes.icon_override) - standing = image("icon" = shoes.icon_override, "icon_state" = "[shoes.icon_state]") - else if(shoes.sprite_sheets && shoes.sprite_sheets[species.name]) - standing = image("icon" = shoes.sprite_sheets[species.name], "icon_state" = "[shoes.icon_state]") - else - standing = image("icon" = 'icons/mob/feet.dmi', "icon_state" = "[shoes.icon_state]") - - - if(shoes.blood_DNA) - var/image/bloodsies = image("icon" = species.blood_mask, "icon_state" = "shoeblood") - bloodsies.color = shoes.blood_color - standing.overlays += bloodsies - overlays_standing[SHOES_LAYER] = standing - else - if(feet_blood_DNA) - var/image/bloodsies = image("icon" = species.blood_mask, "icon_state" = "shoeblood") - bloodsies.color = feet_blood_color - overlays_standing[SHOES_LAYER] = bloodsies - else - overlays_standing[SHOES_LAYER] = null - if(update_icons) update_icons() - -/mob/living/carbon/human/update_inv_s_store(var/update_icons=1) - if(s_store) - var/t_state = s_store.item_state - if(!t_state) - t_state = s_store.icon_state - var/dmi='icons/mob/belt_mirror.dmi' - overlays_standing[SUIT_STORE_LAYER] = image("icon" = dmi, "icon_state" = "[t_state]") - s_store.screen_loc = ui_sstore1 //TODO - else - overlays_standing[SUIT_STORE_LAYER] = null - if(update_icons) update_icons() - - -/mob/living/carbon/human/update_inv_head(var/update_icons=1) - if(head) - head.screen_loc = ui_head //TODO - var/image/standing - if(head.icon_override) - standing = image("icon" = head.icon_override, "icon_state" = "[head.icon_state]") - else if(head.sprite_sheets && head.sprite_sheets[species.name]) - standing = image("icon" = head.sprite_sheets[species.name], "icon_state" = "[head.icon_state]") - else - standing = image("icon" = 'icons/mob/head.dmi', "icon_state" = "[head.icon_state]") - - if(head.blood_DNA) - var/image/bloodsies = image("icon" = species.blood_mask, "icon_state" = "helmetblood") - bloodsies.color = head.blood_color - standing.overlays += bloodsies - overlays_standing[HEAD_LAYER] = standing - - - else - overlays_standing[HEAD_LAYER] = null - if(update_icons) update_icons() - -/mob/living/carbon/human/update_inv_belt(var/update_icons=1) - if(belt) - belt.screen_loc = ui_belt //TODO - var/t_state = belt.item_state - if(!t_state) t_state = belt.icon_state - - if(belt.icon_override) - t_state = "[t_state]_be" - overlays_standing[BELT_LAYER] = image("icon" = belt.icon_override, "icon_state" = "[t_state]") - else if(belt.sprite_sheets && belt.sprite_sheets[species.name]) - overlays_standing[BELT_LAYER] = image("icon" = belt.sprite_sheets[species.name], "icon_state" = "[t_state]") - else - overlays_standing[BELT_LAYER] = image("icon" = 'icons/mob/belt.dmi', "icon_state" = "[t_state]") - else - overlays_standing[BELT_LAYER] = null - if(update_icons) update_icons() - - -/mob/living/carbon/human/update_inv_wear_suit(var/update_icons=1) - if( wear_suit && istype(wear_suit, /obj/item/clothing/suit) ) //TODO check this - wear_suit.screen_loc = ui_oclothing //TODO - - var/image/standing - if(wear_suit.icon_override) - standing = image("icon" = wear_suit.icon_override, "icon_state" = "[wear_suit.icon_state]") - else if(wear_suit.sprite_sheets && wear_suit.sprite_sheets[species.name]) - standing = image("icon" = wear_suit.sprite_sheets[species.name], "icon_state" = "[wear_suit.icon_state]") - else if(FAT in mutations) - if(wear_suit.flags&ONESIZEFITSALL) - standing = image("icon" = 'icons/mob/suit_fat.dmi', "icon_state" = "[wear_suit.icon_state]") - else - src << "\red You burst out of \the [wear_suit]!" - unEquip(wear_suit) - return - else - standing = image("icon" = 'icons/mob/suit.dmi', "icon_state" = "[wear_suit.icon_state]") - - - if( istype(wear_suit, /obj/item/clothing/suit/straight_jacket) ) - unEquip(handcuffed) - drop_l_hand() - drop_r_hand() - - - if(wear_suit.blood_DNA) - var/obj/item/clothing/suit/S = wear_suit - var/image/bloodsies = image("icon" = species.blood_mask, "icon_state" = "[S.blood_overlay_type]blood") - bloodsies.color = wear_suit.blood_color - standing.overlays += bloodsies - - - overlays_standing[SUIT_LAYER] = standing - - update_tail_layer(0) - - else - overlays_standing[SUIT_LAYER] = null - - update_tail_layer(0) - - update_collar(0) - - if(update_icons) update_icons() - -/mob/living/carbon/human/update_inv_pockets(var/update_icons=1) - if(l_store) l_store.screen_loc = ui_storage1 //TODO - if(r_store) r_store.screen_loc = ui_storage2 //TODO - if(update_icons) update_icons() - -/mob/living/carbon/human/update_inv_wear_pda(var/update_icons=1) - if(wear_pda) wear_pda.screen_loc = ui_pda - if(update_icons) update_icons() - -/mob/living/carbon/human/update_inv_wear_mask(var/update_icons=1) - if( wear_mask && ( istype(wear_mask, /obj/item/clothing/mask) || istype(wear_mask, /obj/item/clothing/accessory) ) ) - wear_mask.screen_loc = ui_mask //TODO - - var/image/standing - if(wear_mask.icon_override) - standing = image("icon" = wear_mask.icon_override, "icon_state" = "[wear_mask.icon_state]") - else if(wear_mask.sprite_sheets && wear_mask.sprite_sheets[species.name]) - standing = image("icon" = wear_mask.sprite_sheets[species.name], "icon_state" = "[wear_mask.icon_state]") - else - standing = image("icon" = 'icons/mob/mask.dmi', "icon_state" = "[wear_mask.icon_state]") - - if( !istype(wear_mask, /obj/item/clothing/mask/cigarette) && wear_mask.blood_DNA ) - var/image/bloodsies = image("icon" = species.blood_mask, "icon_state" = "maskblood") - bloodsies.color = wear_mask.blood_color - standing.overlays += bloodsies - overlays_standing[FACEMASK_LAYER] = standing - else - overlays_standing[FACEMASK_LAYER] = null - if(update_icons) update_icons() - - -/mob/living/carbon/human/update_inv_back(var/update_icons=1) - if(back) - back.screen_loc = ui_back //TODO - - //determine the icon to use - var/icon/overlay_icon - if(back.icon_override) - overlay_icon = back.icon_override - else if(istype(back, /obj/item/weapon/rig)) - //If this is a rig and a mob_icon is set, it will take species into account in the rig update_icon() proc. - var/obj/item/weapon/rig/rig = back - overlay_icon = rig.mob_icon - else if(back.sprite_sheets && back.sprite_sheets[species.name]) - overlay_icon = back.sprite_sheets[species.name] - else - overlay_icon = icon('icons/mob/back.dmi', "[back.icon_state]") - - //determine state to use - var/overlay_state - if(back.item_state) - overlay_state = back.item_state - else - overlay_state = back.icon_state - - //create the image - overlays_standing[BACK_LAYER] = image(icon = overlay_icon, icon_state = overlay_state) - else - overlays_standing[BACK_LAYER] = null - - if(update_icons) update_icons() - - -/mob/living/carbon/human/update_hud() //TODO: do away with this if possible - if(client) - client.screen |= contents - if(hud_used) - hud_used.hidden_inventory_update() //Updates the screenloc of the items on the 'other' inventory bar - - -/mob/living/carbon/human/update_inv_handcuffed(var/update_icons=1) - if(handcuffed) - drop_r_hand() - drop_l_hand() - stop_pulling() //TODO: should be handled elsewhere - if(hud_used) //hud handcuff icons - var/obj/screen/inventory/R = hud_used.adding[7] - var/obj/screen/inventory/L = hud_used.adding[8] - R.overlays += image("icon"='icons/mob/screen_gen.dmi', "icon_state"="markus") - L.overlays += image("icon"='icons/mob/screen_gen.dmi', "icon_state"="gabrielle") - if(istype(handcuffed, /obj/item/weapon/restraints/handcuffs/pinkcuffs)) - overlays_standing[HANDCUFF_LAYER] = image("icon" = 'icons/mob/mob.dmi', "icon_state" = "pinkcuff1") - else - overlays_standing[HANDCUFF_LAYER] = image("icon" = 'icons/mob/mob.dmi', "icon_state" = "handcuff1") - else - overlays_standing[HANDCUFF_LAYER] = null - if(hud_used) - var/obj/screen/inventory/R = hud_used.adding[7] - var/obj/screen/inventory/L = hud_used.adding[8] - R.overlays = null - L.overlays = null - if(update_icons) update_icons() - -/mob/living/carbon/human/update_inv_legcuffed(var/update_icons=1) - if(legcuffed) - overlays_standing[LEGCUFF_LAYER] = image("icon" = 'icons/mob/mob.dmi', "icon_state" = "legcuff1") - if(src.m_intent != "walk") - src.m_intent = "walk" - if(src.hud_used && src.hud_used.move_intent) - src.hud_used.move_intent.icon_state = "walking" - - else - overlays_standing[LEGCUFF_LAYER] = null - if(update_icons) update_icons() - - -/mob/living/carbon/human/update_inv_r_hand(var/update_icons=1) - if(r_hand) - r_hand.screen_loc = ui_rhand //TODO - var/t_state = r_hand.item_state - if(!t_state) t_state = r_hand.icon_state - - var/image/I = image("icon" = r_hand.righthand_file, "icon_state"="[t_state]") - I = center_image(I, r_hand.inhand_x_dimension, r_hand.inhand_y_dimension) - overlays_standing[R_HAND_LAYER] = I - - if (handcuffed) drop_r_hand() - else - overlays_standing[R_HAND_LAYER] = null - if(update_icons) update_icons() - - -/mob/living/carbon/human/update_inv_l_hand(var/update_icons=1) - if(l_hand) - l_hand.screen_loc = ui_lhand //TODO - var/t_state = l_hand.item_state - if(!t_state) t_state = l_hand.icon_state - - var/image/I = image("icon" = l_hand.lefthand_file, "icon_state"="[t_state]") - I = center_image(I, l_hand.inhand_x_dimension, l_hand.inhand_y_dimension) - overlays_standing[L_HAND_LAYER] = I - - if (handcuffed) drop_l_hand() - else - overlays_standing[L_HAND_LAYER] = null - if(update_icons) update_icons() - - - -/mob/living/carbon/human/proc/update_tail_layer(var/update_icons=1) - overlays_standing[TAIL_LAYER] = null - - if(body_accessory) - if(body_accessory.try_restrictions(src)) - var/icon/accessory_s = new/icon("icon" = body_accessory.icon, "icon_state" = body_accessory.icon_state) - accessory_s.Blend(rgb(r_skin, g_skin, b_skin), body_accessory.blend_mode) - - overlays_standing[TAIL_LAYER] = image(accessory_s, "pixel_x" = body_accessory.pixel_x_offset, "pixel_y" = body_accessory.pixel_y_offset) - - - else if(species.tail && species.bodyflags & HAS_TAIL) //no tailless tajaran - if(!wear_suit || !(wear_suit.flags_inv & HIDETAIL) && !istype(wear_suit, /obj/item/clothing/suit/space)) - var/icon/tail_s = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "[species.tail]_s") - tail_s.Blend(rgb(r_skin, g_skin, b_skin), ICON_ADD) - - overlays_standing[TAIL_LAYER] = image(tail_s) - - if(update_icons) - update_icons() - - -/mob/living/carbon/human/proc/start_tail_wagging(var/update_icons=1) - overlays_standing[TAIL_LAYER] = null - - if(body_accessory) - var/icon/accessory_s = new/icon("icon" = body_accessory.get_animated_icon(), "icon_state" = body_accessory.get_animated_icon_state()) - accessory_s.Blend(rgb(r_skin, g_skin, b_skin), body_accessory.blend_mode) - - overlays_standing[TAIL_LAYER] = image(accessory_s, "pixel_x" = body_accessory.pixel_x_offset, "pixel_y" = body_accessory.pixel_y_offset) - - else if(species.tail && species.bodyflags & HAS_TAIL) - var/icon/tailw_s = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "[species.tail]w_s") - tailw_s.Blend(rgb(r_skin, g_skin, b_skin), ICON_ADD) - - overlays_standing[TAIL_LAYER] = image(tailw_s) - - if(update_icons) - update_icons() - -/mob/living/carbon/human/proc/stop_tail_wagging(var/update_icons=1) - overlays_standing[TAIL_LAYER] = null - - update_tail_layer(update_icons) //just trigger a full update for normal stationary sprites - -/mob/living/carbon/human/handle_transform_change() - ..() - update_tail_layer() - -//Adds a collar overlay above the helmet layer if the suit has one -// Suit needs an identically named sprite in icons/mob/collar.dmi -/mob/living/carbon/human/proc/update_collar(var/update_icons=1) - var/icon/C = new('icons/mob/collar.dmi') - var/image/standing = null - - if(wear_suit) - if(wear_suit.icon_state in C.IconStates()) - standing = image("icon" = C, "icon_state" = "[wear_suit.icon_state]") - - overlays_standing[COLLAR_LAYER] = standing - - if(update_icons) update_icons() - - -// Used mostly for creating head items -/mob/living/carbon/human/proc/generate_head_icon() -//gender no longer matters for the mouth, although there should probably be seperate base head icons. -// var/g = "m" -// if (gender == FEMALE) g = "f" - - //base icons - var/icon/face_lying = new /icon('icons/mob/human_face.dmi',"bald_l") - - if(f_style) - var/datum/sprite_accessory/facial_hair_style = facial_hair_styles_list[f_style] - if(facial_hair_style) - var/icon/facial_l = new/icon("icon" = facial_hair_style.icon, "icon_state" = "[facial_hair_style.icon_state]_l") - facial_l.Blend(rgb(r_facial, g_facial, b_facial), ICON_ADD) - face_lying.Blend(facial_l, ICON_OVERLAY) - - if(h_style) - var/datum/sprite_accessory/hair_style = hair_styles_list[h_style] - if(hair_style) - var/icon/hair_l = new/icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_l") - hair_l.Blend(rgb(r_hair, g_hair, b_hair), ICON_ADD) - face_lying.Blend(hair_l, ICON_OVERLAY) - - //Eyes - // Note: These used to be in update_face(), and the fact they're here will make it difficult to create a disembodied head - var/icon/eyes_l = new/icon('icons/mob/human_face.dmi', "eyes_l") - eyes_l.Blend(rgb(r_eyes, g_eyes, b_eyes), ICON_ADD) - face_lying.Blend(eyes_l, ICON_OVERLAY) - - if(lip_style) - face_lying.Blend(new/icon('icons/mob/human_face.dmi', "lips_[lip_style]_l"), ICON_OVERLAY) - - var/image/face_lying_image = new /image(icon = face_lying) - return face_lying_image - -/mob/living/carbon/human/proc/force_update_limbs() - for(var/obj/item/organ/external/O in organs) - O.sync_colour_to_human(src) - update_body(0) - -//Human Overlays Indexes///////// -#undef MUTANTRACE_LAYER -#undef MARKINGS_LAYER -#undef MUTATIONS_LAYER -#undef DAMAGE_LAYER -#undef UNIFORM_LAYER -#undef TAIL_LAYER -#undef ID_LAYER -#undef SHOES_LAYER -#undef GLOVES_LAYER -#undef EARS_LAYER -#undef SUIT_LAYER -#undef GLASSES_LAYER -#undef FACEMASK_LAYER -#undef BELT_LAYER -#undef SUIT_STORE_LAYER -#undef BACK_LAYER -#undef HAIR_LAYER -#undef HEAD_LAYER -#undef HEAD_ACCESSORY_LAYER -#undef FHAIR_LAYER -#undef COLLAR_LAYER -#undef HANDCUFF_LAYER -#undef LEGCUFF_LAYER -#undef L_HAND_LAYER -#undef R_HAND_LAYER -#undef TARGETED_LAYER -#undef FIRE_LAYER -#undef TOTAL_LAYERS +//LOOK G-MA, I'VE JOINED CARBON PROCS THAT ARE IDENTICAL IN ALL CASES INTO ONE PROC, I'M BETTER THAN LIFE() +//I thought about mob/living but silicons and simple_animals don't want this just yet. +//Right now just handles lying down, but could handle other cases later. +//IMPORTANT: Multiple animate() calls do not stack well, so try to do them all at once if you can. +/mob/living/carbon/update_transform() + var/matrix/ntransform = matrix(transform) //aka transform.Copy() + var/final_pixel_y = pixel_y + var/final_dir = dir + var/changed = 0 + if(lying != lying_prev) + changed++ + ntransform.TurnTo(lying_prev,lying) + if(lying == 0) //Lying to standing + final_pixel_y = get_standard_pixel_y_offset() + else //if(lying != 0) + if(lying_prev == 0) //Standing to lying + pixel_y = get_standard_pixel_y_offset() + final_pixel_y = get_standard_pixel_y_offset(lying) + if(dir & (EAST|WEST)) //Facing east or west + final_dir = pick(NORTH, SOUTH) //So you fall on your side rather than your face or ass + + lying_prev = lying //so we don't try to animate until there's been another change. + + if(resize != RESIZE_DEFAULT_SIZE) + changed++ + ntransform.Scale(resize) + resize = RESIZE_DEFAULT_SIZE + + if(changed) + animate(src, transform = ntransform, time = 2, pixel_y = final_pixel_y, dir = final_dir, easing = EASE_IN|EASE_OUT) + handle_transform_change() + floating = 0 // If we were without gravity, the bouncing animation got stopped, so we make sure we restart it in next life(). + +/mob/living/carbon/proc/handle_transform_change() + return \ No newline at end of file