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