diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm
index 5f047e79..7d4dc1ca 100644
--- a/code/__DEFINES/is_helpers.dm
+++ b/code/__DEFINES/is_helpers.dm
@@ -73,7 +73,6 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list(
#define isluminescent(A) (is_species(A, /datum/species/jelly/luminescent))
#define iszombie(A) (is_species(A, /datum/species/zombie))
#define ismoth(A) (is_species(A, /datum/species/moth))
-#define isinsect(A) (is_species(A, /datum/species/insect))
#define ishumanbasic(A) (is_species(A, /datum/species/human))
#define iscatperson(A) (ishumanbasic(A) && istype(A.dna.species, /datum/species/human/felinid) )
#define isvampire(A) (is_species(A,/datum/species/vampire))
diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm
index 624dc971..415218c4 100644
--- a/code/modules/mob/living/carbon/human/examine.dm
+++ b/code/modules/mob/living/carbon/human/examine.dm
@@ -145,8 +145,6 @@
. += "It appears that [t_his] brain is missing..."
var/temp = getBruteLoss() //no need to calculate each of these twice
-
- msg += "" //Everything below gets this span
var/list/msg = list()
diff --git a/code/modules/mob/living/carbon/update_icons.dm b/code/modules/mob/living/carbon/update_icons.dm
index 9c691e1b..3541840a 100644
--- a/code/modules/mob/living/carbon/update_icons.dm
+++ b/code/modules/mob/living/carbon/update_icons.dm
@@ -1,733 +1,357 @@
- ///////////////////////
- //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())
-*/
+//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
-//HAIR OVERLAY
-/mob/living/carbon/human/update_hair()
- dna.species.handle_hair(src)
+ if(lying != lying_prev && rotate_on_lying)
+ changed++
+ ntransform.TurnTo(lying_prev,lying)
+ if(lying == 0) //Lying to standing
+ final_pixel_y = get_standard_pixel_y_offset()
+ if(size_multiplier >= 1) //if its bigger than normal
+ ntransform.Translate(0,16 * (size_multiplier-1))
+ else
+ if(lying_prev == 90)
+ ntransform.Translate(16 * (size_multiplier-1),16 * (size_multiplier-1))
-//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)
+ if(lying_prev == 270)
+ ntransform.Translate(-16 * (size_multiplier-1),16 * (size_multiplier-1))
+
+ 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(lying == 90) //Check the angle of the sprite to offset it accordingly.
+ ntransform.Translate(-16 * (size_multiplier-1),0)
+ if(size_multiplier < 1) //if its smaller than normal
+ ntransform.Translate(0,16 * (size_multiplier-1)) //we additionally offset the sprite downwards
+
+ if(lying == 270) //check the angle of the sprite to offset it accordingly
+ ntransform.Translate(16 * (size_multiplier-1),0)
+ if(size_multiplier < 1) //if its smaller than normal
+ ntransform.Translate(0,16 * (size_multiplier-1)) //we additionally offset the sprite downwards
+
+ 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
+
+ if(resize != RESIZE_DEFAULT_SIZE)
+ changed++
+ ntransform.Scale(resize)
+ resize = RESIZE_DEFAULT_SIZE
+
+ //Apply size multiplier, thank NeverExisted for this
+ if(size_multiplier != previous_size)
+ changed++
+ //now we offset the sprite
+ //Scaling affects offset. There's probably a smarter and easier way to do this, but this way it works for sure (?)
+ //Just to be clear. All this bullshit is needed because someone wanted to store the old transform matrix instead of using a new one each iteration
+ //Winfre is currently doing a great job at coating my nuts in slobber while i code this
+ if(!lying) //when standing. People of all sizes are affected equally
+ ntransform.Translate(0,-16 * (previous_size-1)) //reset the sprite
+ ntransform.Scale(size_multiplier/previous_size) //scale the sprite accordingly.
+ ntransform.Translate(0,16 * (size_multiplier-1)) //apply the new offset
+ else //when lying. Macros dont get an offset, Micros do. We must also check the cases when a micro becomes a macro and viceversa
+ if(previous_size <= 1 && size_multiplier <= 1) //micro stays a micro. We modify the side-offset
+ ntransform.Translate(0,-16 * (previous_size-1)) //reset the sprite
+ ntransform.Scale(size_multiplier/previous_size) //scale the sprite accordingly
+ ntransform.Translate(0,16 * (size_multiplier-1)) //apply the new offset
+
+ if(previous_size <= 1 && size_multiplier > 1) //micro becomes a macro. We remove the side-offset
+ ntransform.Translate(0,-16 * (previous_size-1)) //reset the sprite
+ ntransform.Scale(size_multiplier/previous_size) //scale the sprite accordingly
+
+ if(previous_size > 1 && size_multiplier <= 1) //macro becomes a micro. We add an offset
+ ntransform.Scale(size_multiplier/previous_size) //scale the sprite accordingly.
+ ntransform.Translate(0,16 * (size_multiplier-1)) //apply the new offset
+
+ if(previous_size > 1 && size_multiplier > 1) //macro stays a macro. We just scale the sprite with no offset changes
+ ntransform.Scale(size_multiplier/previous_size) //scale the sprite accordingly
-/mob/living/carbon/human/update_body()
- remove_overlay(BODY_LAYER)
- dna.species.handle_body(src)
- ..()
+ if(changed)
+ animate(src, transform = ntransform, time = 2, pixel_y = final_pixel_y, dir = final_dir, easing = EASE_IN|EASE_OUT)
+ 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/human/update_fire()
- ..((fire_stacks > 3) ? "Standing" : "Generic_mob_burning")
+/mob/living/carbon
+ var/list/overlays_standing[TOTAL_LAYERS]
+
+/mob/living/carbon/proc/apply_overlay(cache_index)
+ if((. = overlays_standing[cache_index]))
+ add_overlay(.)
+
+/mob/living/carbon/proc/remove_overlay(cache_index)
+ var/I = overlays_standing[cache_index]
+ if(I)
+ cut_overlay(I)
+ overlays_standing[cache_index] = null
+
+/mob/living/carbon/regenerate_icons()
+ if(notransform)
+ return 1
+ update_inv_hands()
+ update_inv_handcuffed()
+ update_inv_legcuffed()
+ update_fire()
-/* --------------------------------------- */
-//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"
-
- var/alt_worn = U.alternate_worn_icon
-
- if(!U.force_alternate_icon && U.mutantrace_variation && U.suit_style == DIGITIGRADE_SUIT_STYLE)
- alt_worn = 'modular_citadel/icons/mob/uniform_digi.dmi'
-
- 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 = (alt_worn ? alt_worn : '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 = (alt_worn ? alt_worn : '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, color = blood_DNA_to_color())
- 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
+/mob/living/carbon/update_inv_hands()
+ remove_overlay(HANDS_LAYER)
+ if (handcuffed)
+ drop_all_held_items()
return
- if(client && hud_used)
- var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_GLASSES]
- inv.update_icon()
+ var/list/hands = list()
+ for(var/obj/item/I in held_items)
+ if(client && hud_used && hud_used.hud_version != HUD_STYLE_NOHUD)
+ I.screen_loc = ui_hand_position(get_held_index_of_item(I))
+ client.screen += I
+ if(observers && observers.len)
+ for(var/M in observers)
+ var/mob/dead/observe = M
+ if(observe.client && observe.client.eye == src)
+ observe.client.screen += I
+ else
+ observers -= observe
+ if(!observers.len)
+ observers = null
+ break
- 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 && bloody_feet)
- var/mutable_appearance/bloody_overlay = mutable_appearance('icons/effects/blood.dmi', "bloodyfeet", -SHOES_LAYER, color = blood_DNA_to_color())
- if(dna.features["taur"] != "None")
- if(dna.features["taur"] in GLOB.noodle_taurs)
- bloody_overlay = mutable_appearance('modular_citadel/icons/mob/64x32_effects.dmi', "snekbloodyfeet", -SHOES_LAYER, color = blood_DNA_to_color())
- if(get_num_legs() < 2)
- if(has_left_leg())
- bloody_overlay.icon_state = "snekbloodyfeet_left"
- else if(has_right_leg())
- bloody_overlay.icon_state = "snekbloodyfeet_right"
- else if(dna.features["taur"] in GLOB.paw_taurs)
- bloody_overlay = mutable_appearance('modular_citadel/icons/mob/64x32_effects.dmi', "pawbloodyfeet", -SHOES_LAYER, color = blood_DNA_to_color())
- if(get_num_legs() < 2)
- if(has_left_leg())
- bloody_overlay.icon_state = "pawbloodyfeet_left"
- else if(has_right_leg())
- bloody_overlay.icon_state = "pawbloodyfeet_right"
- else
- if(get_num_legs() < 2)
- if(has_left_leg())
- bloody_overlay.icon_state = "bloodyfeet_left"
- else if(has_right_leg())
- bloody_overlay.icon_state = "bloodyfeet_right"
- overlays_standing[GLOVES_LAYER] = bloody_overlay*/
-
- 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.mutantrace_variation)
- if(S.adjusted == ALT_STYLE)
- S.alternate_worn_icon = 'modular_citadel/icons/mob/digishoes.dmi'
- else
- S.alternate_worn_icon = null
- var/t_state = shoes.item_state
- if (!t_state)
- t_state = shoes.icon_state
- overlays_standing[SHOES_LAYER] = shoes.build_worn_icon(state = t_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
+ var/t_state = I.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)
+ t_state = I.icon_state
+
+ var/icon_file = I.lefthand_file
+ if(get_held_index_of_item(I) % 2 == 0)
+ icon_file = I.righthand_file
+
+ hands += I.build_worn_icon(state = t_state, default_layer = HANDS_LAYER, default_icon_file = icon_file, isinhands = TRUE)
+
+ overlays_standing[HANDS_LAYER] = hands
+ apply_overlay(HANDS_LAYER)
-/mob/living/carbon/human/update_inv_head()
- ..()
- update_mutant_bodyparts()
- if(head)
- remove_overlay(HEAD_LAYER)
- var/obj/item/clothing/head/H = head
- if(H.mutantrace_variation)
- if(H.muzzle_var == ALT_STYLE)
- H.alternate_worn_icon = 'modular_citadel/icons/mob/muzzled_helmet.dmi'
- else
- H.alternate_worn_icon = null
+/mob/living/carbon/update_fire(var/fire_icon = "Generic_mob_burning")
+ remove_overlay(FIRE_LAYER)
+ if(on_fire)
+ var/mutable_appearance/new_fire_overlay = mutable_appearance('icons/mob/OnFire.dmi', fire_icon, -FIRE_LAYER)
+ new_fire_overlay.appearance_flags = RESET_COLOR
+ overlays_standing[FIRE_LAYER] = new_fire_overlay
- overlays_standing[HEAD_LAYER] = H.build_worn_icon(state = H.icon_state, default_layer = HEAD_LAYER, default_icon_file = ((head.alternate_worn_icon) ? H.alternate_worn_icon : 'icons/mob/head.dmi'))
- var/mutable_appearance/head_overlay = overlays_standing[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(wear_suit)
- var/obj/item/clothing/suit/S = wear_suit
- var/no_taur_thanks = FALSE
- if(!istype(S))
- no_taur_thanks = TRUE
- 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)
-
- if(!S.force_alternate_icon)
- if(!no_taur_thanks && S.mutantrace_variation) //Just make sure we've got this checked too
- if(S.taurmode == NOT_TAURIC && S.adjusted == ALT_STYLE) //are we not a taur, but we have Digitigrade legs? Run this check first, then.
- S.alternate_worn_icon = 'modular_citadel/icons/mob/suit_digi.dmi'
- else
- S.alternate_worn_icon = null
-
- if(S.tauric == TRUE) //Are we a suit with tauric mode possible?
- if(S.taurmode == SNEK_TAURIC)
- S.alternate_worn_icon = 'modular_citadel/icons/mob/taur_naga.dmi'
- if(S.taurmode == PAW_TAURIC)
- S.alternate_worn_icon = 'modular_citadel/icons/mob/taur_canine.dmi'
- if(S.taurmode == NOT_TAURIC && S.adjusted == ALT_STYLE)
- S.alternate_worn_icon = 'modular_citadel/icons/mob/suit_digi.dmi'
- else if(S.taurmode == NOT_TAURIC && S.adjusted == NORMAL_STYLE)
- S.alternate_worn_icon = null
-
- overlays_standing[SUIT_LAYER] = S.build_worn_icon(state = wear_suit.icon_state, default_layer = SUIT_LAYER, default_icon_file = ((wear_suit.alternate_worn_icon) ? S.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]
- if(!no_taur_thanks && S.center)
- suit_overlay = center_image(suit_overlay, S.dimension_x, S.dimension_y)
- 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()
- ..()
- if(wear_mask)
- var/obj/item/clothing/mask/M = wear_mask
- remove_overlay(FACEMASK_LAYER)
- if(M.mutantrace_variation)
- if(M.muzzle_var == ALT_STYLE)
- M.alternate_worn_icon = 'modular_citadel/icons/mob/muzzled_mask.dmi'
- else
- M.alternate_worn_icon = null
-
- overlays_standing[FACEMASK_LAYER] = M.build_worn_icon(state = wear_mask.icon_state, default_layer = FACEMASK_LAYER, default_icon_file = ((wear_mask.alternate_worn_icon) ? M.alternate_worn_icon : 'icons/mob/mask.dmi'))
- var/mutable_appearance/mask_overlay = overlays_standing[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)
-
-/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)
+ apply_overlay(FIRE_LAYER)
+/mob/living/carbon/update_damage_overlays()
+ remove_overlay(DAMAGE_LAYER)
+ var/dam_colors = "#E62525"
+ if(ishuman(src))
+ var/mob/living/carbon/human/H = src
+ dam_colors = bloodtype_to_color(H.dna.blood_type)
-/*
-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"]]-[dna.features["mcolor2"]]-[dna.features["mcolor3"]]"
- 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
-
+ var/mutable_appearance/damage_overlay = mutable_appearance('icons/mob/dam_mob.dmi', "blank", -DAMAGE_LAYER, color = dam_colors)
+ overlays_standing[DAMAGE_LAYER] = damage_overlay
for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
+ if(BP.dmg_overlay_type)
+ if(BP.brutestate)
+ damage_overlay.add_overlay("[BP.dmg_overlay_type]_[BP.body_zone]_[BP.brutestate]0") //we're adding icon_states of the base image as overlays
+ if(BP.burnstate)
+ damage_overlay.add_overlay("[BP.dmg_overlay_type]_[BP.body_zone]_0[BP.burnstate]")
- if(istype(BP, /obj/item/bodypart/r_leg) || istype(BP, /obj/item/bodypart/l_leg))
- if(is_taur)
- continue
+ apply_overlay(DAMAGE_LAYER)
+/mob/living/carbon/update_inv_wear_mask()
+ remove_overlay(FACEMASK_LAYER)
+
+ if(!get_bodypart(BODY_ZONE_HEAD)) //Decapitated
+ return
+
+ if(client && hud_used && hud_used.inv_slots[SLOT_WEAR_MASK])
+ var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_WEAR_MASK]
+ inv.update_icon()
+
+ if(wear_mask)
+ if(!(head && (head.flags_inv & HIDEMASK)))
+ overlays_standing[FACEMASK_LAYER] = wear_mask.build_worn_icon(state = wear_mask.icon_state, default_layer = FACEMASK_LAYER, default_icon_file = 'icons/mob/mask.dmi')
+ update_hud_wear_mask(wear_mask)
+
+ apply_overlay(FACEMASK_LAYER)
+
+/mob/living/carbon/update_inv_neck()
+ remove_overlay(NECK_LAYER)
+
+ if(client && hud_used && hud_used.inv_slots[SLOT_NECK])
+ var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_NECK]
+ inv.update_icon()
+
+ if(wear_neck)
+ if(!(head && (head.flags_inv & HIDENECK)))
+ overlays_standing[NECK_LAYER] = wear_neck.build_worn_icon(state = wear_neck.icon_state, default_layer = NECK_LAYER, default_icon_file = 'icons/mob/neck.dmi')
+ update_hud_neck(wear_neck)
+
+ apply_overlay(NECK_LAYER)
+
+/mob/living/carbon/update_inv_back()
+ remove_overlay(BACK_LAYER)
+
+ if(client && hud_used && hud_used.inv_slots[SLOT_BACK])
+ var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_BACK]
+ inv.update_icon()
+
+ if(back)
+ overlays_standing[BACK_LAYER] = back.build_worn_icon(state = back.icon_state, default_layer = BACK_LAYER, default_icon_file = 'icons/mob/back.dmi')
+ update_hud_back(back)
+
+ apply_overlay(BACK_LAYER)
+
+/mob/living/carbon/update_inv_head()
+ remove_overlay(HEAD_LAYER)
+
+ if(!get_bodypart(BODY_ZONE_HEAD)) //Decapitated
+ return
+
+ if(client && hud_used && hud_used.inv_slots[SLOT_BACK])
+ var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_HEAD]
+ inv.update_icon()
+
+ if(head)
+ overlays_standing[HEAD_LAYER] = head.build_worn_icon(state = head.icon_state, default_layer = HEAD_LAYER, default_icon_file = 'icons/mob/head.dmi')
+ update_hud_head(head)
+
+ apply_overlay(HEAD_LAYER)
+
+
+/mob/living/carbon/update_inv_handcuffed()
+ remove_overlay(HANDCUFF_LAYER)
+ if(handcuffed)
+ var/mutable_appearance/cuffs = mutable_appearance('icons/mob/restraints.dmi', handcuffed.item_state, -HANDCUFF_LAYER)
+ cuffs.color = handcuffed.color
+
+ overlays_standing[HANDCUFF_LAYER] = cuffs
+ apply_overlay(HANDCUFF_LAYER)
+
+/mob/living/carbon/update_inv_legcuffed()
+ remove_overlay(LEGCUFF_LAYER)
+ clear_alert("legcuffed")
+ if(legcuffed)
+ var/mutable_appearance/legcuffs = mutable_appearance('icons/mob/restraints.dmi', legcuffed.item_state, -LEGCUFF_LAYER)
+ legcuffs.color = legcuffed.color
+
+ overlays_standing[HANDCUFF_LAYER] = legcuffs
+ apply_overlay(LEGCUFF_LAYER)
+ throw_alert("legcuffed", /obj/screen/alert/restrained/legcuffed, new_master = legcuffed)
+
+//mob HUD updates for items in our inventory
+
+//update whether handcuffs appears on our hud.
+/mob/living/carbon/proc/update_hud_handcuffed()
+ if(hud_used)
+ for(var/hand in hud_used.hand_slots)
+ var/obj/screen/inventory/hand/H = hud_used.hand_slots[hand]
+ if(H)
+ H.update_icon()
+
+//update whether our head item appears on our hud.
+/mob/living/carbon/proc/update_hud_head(obj/item/I)
+ return
+
+//update whether our mask item appears on our hud.
+/mob/living/carbon/proc/update_hud_wear_mask(obj/item/I)
+ return
+
+//update whether our neck item appears on our hud.
+/mob/living/carbon/proc/update_hud_neck(obj/item/I)
+ return
+
+//update whether our back item appears on our hud.
+/mob/living/carbon/proc/update_hud_back(obj/item/I)
+ return
+
+
+
+//Overlays for the worn overlay so you can overlay while you overlay
+//eg: ammo counters, primed grenade flashing, etc.
+//"icon_file" is used automatically for inhands etc. to make sure it gets the right inhand file
+/obj/item/proc/worn_overlays(isinhands = FALSE, icon_file)
+ . = list()
+
+
+/mob/living/carbon/update_body()
+ update_body_parts()
+
+/mob/living/carbon/proc/update_body_parts()
+ //CHECK FOR UPDATE
+ var/oldkey = icon_render_key
+ icon_render_key = generate_icon_render_key()
+ if(oldkey == icon_render_key)
+ return
+
+ remove_overlay(BODYPARTS_LAYER)
+
+ for(var/X in bodyparts)
+ var/obj/item/bodypart/BP = X
+ BP.update_limb()
+
+ //LOAD ICONS
+ if(limb_icon_cache[icon_render_key])
+ load_limb_from_cache()
+ return
+
+ //GENERATE NEW LIMBS
+ var/list/new_limbs = list()
+ for(var/X in bodyparts)
+ var/obj/item/bodypart/BP = X
+ new_limbs += BP.get_limb_icon()
+ if(new_limbs.len)
+ overlays_standing[BODYPARTS_LAYER] = new_limbs
+ limb_icon_cache[icon_render_key] = new_limbs
+
+ apply_overlay(BODYPARTS_LAYER)
+ update_damage_overlays()
+
+
+
+/////////////////////
+// Limb Icon Cache //
+/////////////////////
+/*
+ Called from update_body_parts() these procs handle the limb icon cache.
+ the limb icon cache adds an icon_render_key to a human mob, it represents:
+ - skin_tone (if applicable)
+ - gender
+ - limbs (stores as the limb name and whether it is removed/fine, organic/robotic)
+ These procs only store limbs as to increase the number of matching icon_render_keys
+ This cache exists because drawing 6/7 icons for humans constantly is quite a waste
+ See RemieRichards on irc.rizon.net #coderbus
+*/
+
+//produces a key based on the mob's limbs
+
+/mob/living/carbon/proc/generate_icon_render_key()
+ for(var/X in bodyparts)
+ var/obj/item/bodypart/BP = X
. += "-[BP.body_zone]"
+ if(BP.use_digitigrade)
+ . += "-digitigrade[BP.use_digitigrade]"
+ if(BP.animal_origin)
+ . += "-[BP.animal_origin]"
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(BP.body_markings)
- . += "-[BP.body_markings]"
- else
- . += "-no_marking"
if(HAS_TRAIT(src, 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())
+//change the mob's icon to the one matching its key
+/mob/living/carbon/proc/load_limb_from_cache()
+ if(limb_icon_cache[icon_render_key])
+ remove_overlay(BODYPARTS_LAYER)
+ overlays_standing[BODYPARTS_LAYER] = limb_icon_cache[icon_render_key]
+ apply_overlay(BODYPARTS_LAYER)
update_damage_overlays()
-
- if(HD && !(HAS_TRAIT(src, 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_LIPS in dna.species.offset_features)
- lip_overlay.pixel_x += dna.species.offset_features[OFFSET_LIPS][1]
- lip_overlay.pixel_y += dna.species.offset_features[OFFSET_LIPS][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_EYES in dna.species.offset_features)
- eye_overlay.pixel_x += dna.species.offset_features[OFFSET_EYES][1]
- eye_overlay.pixel_y += dna.species.offset_features[OFFSET_EYES][2]
- add_overlay(eye_overlay)
-
- dna.species.handle_hair(src)
-
- update_inv_head()
- update_inv_wear_mask()
diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm
index 33cca488..f94938b8 100644
--- a/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm
+++ b/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm
@@ -215,7 +215,7 @@
melee_damage_upper = 10
attacktext = "ferociously mauls"
environment_smash = ENVIRONMENT_SMASH_NONE
- loot = list(/obj/item/clothing/mask/gas/clown_hat, /obj/effect/gibspawner/xenobodypartless, /obj/effect/particle_effect/foam, /obj/item/soap)
+ loot = list(/obj/item/clothing/mask/gas/clown_hat, /obj/effect/gibspawner/xeno/bodypartless, /obj/effect/particle_effect/foam, /obj/item/soap)
attack_reagent = /datum/reagent/peaceborg_confuse
/mob/living/simple_animal/hostile/retaliate/clown/clownhulk/destroyer
@@ -259,7 +259,7 @@
melee_damage_lower = 10
melee_damage_upper = 20
attacktext = "awkwardly flails at"
- loot = list(/obj/item/clothing/mask/gas/clown_hat, /obj/effect/gibspawner/xenobodypartless, /obj/item/soap, /obj/effect/gibspawner/generic, /obj/effect/gibspawner/humanbodypartless, /obj/effect/gibspawner/human)
+ loot = list(/obj/item/clothing/mask/gas/clown_hat, /obj/effect/gibspawner/xeno/bodypartless, /obj/item/soap, /obj/effect/gibspawner/generic, /obj/effect/gibspawner/human/bodypartless, /obj/effect/gibspawner/human)
/mob/living/simple_animal/hostile/retaliate/clown/mutant/blob
name = "Something that was once a clown"
@@ -272,5 +272,5 @@
mob_size = MOB_SIZE_LARGE
speed = 20
attacktext = "bounces off of"
- loot = list(/obj/item/clothing/mask/gas/clown_hat, /obj/effect/gibspawner/xenobodypartless, /obj/effect/particle_effect/foam, /obj/item/soap, /obj/effect/gibspawner/generic, /obj/effect/gibspawner/humanbodypartless, /obj/effect/gibspawner/human)
- attack_reagent = /datum/reagent/toxin/mindbreaker
\ No newline at end of file
+ loot = list(/obj/item/clothing/mask/gas/clown_hat, /obj/effect/gibspawner/xeno/bodypartless, /obj/effect/particle_effect/foam, /obj/item/soap, /obj/effect/gibspawner/generic, /obj/effect/gibspawner/human/bodypartless, /obj/effect/gibspawner/human)
+ attack_reagent = /datum/reagent/toxin/mindbreaker
diff --git a/icons/obj/surgery.dmi b/icons/obj/surgery.dmi
index 76ac0c71..d26e7a00 100644
Binary files a/icons/obj/surgery.dmi and b/icons/obj/surgery.dmi differ
diff --git a/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm b/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm
index 9dfc3054..164fa944 100644
--- a/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm
+++ b/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm
@@ -120,7 +120,9 @@
add_blood_DNA(list("Non-human DNA" = "A+"))
/obj/effect/decal/cleanable/milk/replace_decal(obj/effect/decal/cleanable/milk/S)
- S.add_blood_DNA(return_blood_DNA())
+ if(S.blood_DNA)
+ blood_DNA |= S.blood_DNA
+ return ..()
//aphrodisiac & anaphrodisiac