diff --git a/code/__DEFINES/colors.dm b/code/__DEFINES/colors.dm index 59af9d98210..13c70231a5f 100644 --- a/code/__DEFINES/colors.dm +++ b/code/__DEFINES/colors.dm @@ -486,8 +486,9 @@ GLOBAL_LIST_INIT(heretic_path_to_color, list( #define EYE_COLOR_ATOM_COLOR_PRIORITY 2 #define EYE_COLOR_SPECIES_PRIORITY 10 #define EYE_COLOR_WEED_PRIORITY 20 -#define EYE_COLOR_LUMINESCENT_PRIORITY 30 -#define EYE_COLOR_CULT_PRIORITY 40 +#define EYE_COLOR_HUD_PRIORITY 30 +#define EYE_COLOR_LUMINESCENT_PRIORITY 40 +#define EYE_COLOR_CULT_PRIORITY 50 // Client color priorities diff --git a/code/datums/dna.dm b/code/datums/dna.dm index 9afc1b57da8..0614dea442d 100644 --- a/code/datums/dna.dm +++ b/code/datums/dna.dm @@ -640,8 +640,7 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) ..() var/structure = dna.unique_identity skin_tone = GLOB.skin_tones[deconstruct_block(get_uni_identity_block(structure, DNA_SKIN_TONE_BLOCK), GLOB.skin_tones.len)] - eye_color_left = sanitize_hexcolor(get_uni_identity_block(structure, DNA_EYE_COLOR_LEFT_BLOCK)) - eye_color_right = sanitize_hexcolor(get_uni_identity_block(structure, DNA_EYE_COLOR_RIGHT_BLOCK)) + set_eye_color(sanitize_hexcolor(get_uni_identity_block(structure, DNA_EYE_COLOR_LEFT_BLOCK)), sanitize_hexcolor(get_uni_identity_block(structure, DNA_EYE_COLOR_RIGHT_BLOCK))) set_haircolor(sanitize_hexcolor(get_uni_identity_block(structure, DNA_HAIR_COLOR_BLOCK)), update = FALSE) set_facial_haircolor(sanitize_hexcolor(get_uni_identity_block(structure, DNA_FACIAL_HAIR_COLOR_BLOCK)), update = FALSE) set_hair_gradient_color(sanitize_hexcolor(get_uni_identity_block(structure, DNA_HAIR_COLOR_GRADIENT_BLOCK)), update = FALSE) diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm index 4e6d3d5634d..268f1aa3fae 100644 --- a/code/game/objects/structures/mirror.dm +++ b/code/game/objects/structures/mirror.dm @@ -250,8 +250,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/mirror/broken, 28) var/new_eye_color = input(user, "Choose your eye color", "Eye Color", user.eye_color_left) as color|null if(isnull(new_eye_color)) return TRUE - user.eye_color_left = sanitize_hexcolor(new_eye_color) - user.eye_color_right = sanitize_hexcolor(new_eye_color) + user.set_eye_color(sanitize_hexcolor(new_eye_color)) user.dna.update_ui_block(DNA_EYE_COLOR_LEFT_BLOCK) user.dna.update_ui_block(DNA_EYE_COLOR_RIGHT_BLOCK) user.update_body() diff --git a/code/modules/admin/create_mob.dm b/code/modules/admin/create_mob.dm index 944e230acd1..ec06fba0b5d 100644 --- a/code/modules/admin/create_mob.dm +++ b/code/modules/admin/create_mob.dm @@ -22,8 +22,7 @@ human.set_facial_hairstyle(random_facial_hairstyle(human.gender), update = FALSE) human.set_haircolor("#[random_color()]", update = FALSE) human.set_facial_haircolor(human.hair_color, update = FALSE) - human.eye_color_left = random_eye_color() - human.eye_color_right = human.eye_color_left + human.set_eye_color(random_eye_color()) human.skin_tone = pick(GLOB.skin_tones) human.dna.species.randomize_active_underwear_only(human) // Needs to be called towards the end to update all the UIs just set above @@ -43,8 +42,7 @@ human.physique = human.gender human.real_name = human.generate_random_mob_name() human.name = human.get_visible_name() - human.eye_color_left = random_eye_color() - human.eye_color_right = human.eye_color_left + human.set_eye_color(random_eye_color()) human.skin_tone = pick(GLOB.skin_tones) // No underwear generation handled here var/picked_color = random_hair_color() diff --git a/code/modules/antagonists/cult/cult_other.dm b/code/modules/antagonists/cult/cult_other.dm index bbeec10ce17..0e286d75e81 100644 --- a/code/modules/antagonists/cult/cult_other.dm +++ b/code/modules/antagonists/cult/cult_other.dm @@ -8,8 +8,7 @@ r_hand = /obj/item/melee/blood_magic/stun /datum/outfit/cultist/post_equip(mob/living/carbon/human/equipped, visuals_only) - equipped.eye_color_left = BLOODCULT_EYE - equipped.eye_color_right = BLOODCULT_EYE + equipped.set_eye_color(BLOODCULT_EYE) equipped.update_body() ///Returns whether the given mob is convertable to the blood cult diff --git a/code/modules/antagonists/fugitive/fugitive_outfits.dm b/code/modules/antagonists/fugitive/fugitive_outfits.dm index 5b73476a3af..a7a45fba7a1 100644 --- a/code/modules/antagonists/fugitive/fugitive_outfits.dm +++ b/code/modules/antagonists/fugitive/fugitive_outfits.dm @@ -36,8 +36,7 @@ if(visuals_only) return equipped_on.fully_replace_character_name(null, "Waldo") - equipped_on.eye_color_left = COLOR_BLACK - equipped_on.eye_color_right = COLOR_BLACK + equipped_on.set_eye_color(COLOR_BLACK) equipped_on.gender = MALE equipped_on.skin_tone = "caucasian3" equipped_on.hairstyle = "Business Hair 3" diff --git a/code/modules/mining/lavaland/mining_loot/megafauna/ash_drake.dm b/code/modules/mining/lavaland/mining_loot/megafauna/ash_drake.dm index 8251ed395af..c54f2d7152f 100644 --- a/code/modules/mining/lavaland/mining_loot/megafauna/ash_drake.dm +++ b/code/modules/mining/lavaland/mining_loot/megafauna/ash_drake.dm @@ -183,8 +183,7 @@ "lizard_markings" = "Dark Tiger Body", "legs" = DIGITIGRADE_LEGS, ) - consumer.eye_color_left = "#FEE5A3" - consumer.eye_color_right = "#FEE5A3" + consumer.set_eye_color("#FEE5A3") consumer.set_species(/datum/species/lizard) if(2) to_chat(user, span_danger("Your flesh begins to melt! Miraculously, you seem fine otherwise.")) diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm index 66a2377aedc..db0d725b85a 100644 --- a/code/modules/mob/living/carbon/human/emote.dm +++ b/code/modules/mob/living/carbon/human/emote.dm @@ -186,8 +186,8 @@ /datum/emote/living/carbon/human/blink/run_emote(mob/living/carbon/human/user, params, type_override, intentional) . = ..() - // Set to update_body until update_body_parts_head_only is fixed - user.update_body() // Refreshing instantly makes the user blink + var/obj/item/organ/eyes/eyes = user.get_organ_slot(ORGAN_SLOT_EYES) + eyes.blink() /datum/emote/living/carbon/human/blink_r key = "blink_r" @@ -204,9 +204,10 @@ /datum/emote/living/carbon/human/blink_r/run_emote(mob/user, params, type_override, intentional) . = ..() - // Set to update_body until update_body_parts_head_only is fixed + var/obj/item/organ/eyes/eyes = user.get_organ_slot(ORGAN_SLOT_EYES) for (var/i in 1 to 3) - addtimer(CALLBACK(user, TYPE_PROC_REF(/mob, update_body)), i * 0.3 SECONDS) + addtimer(CALLBACK(eyes, TYPE_PROC_REF(/obj/item/organ/eyes, blink), 0.1 SECONDS, FALSE), i * 0.2 SECONDS) + eyes.animate_eyelids(user) ///Snowflake emotes only for le epic chimp /datum/emote/living/carbon/human/monkey diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm index 8166612a873..91b001dff5b 100644 --- a/code/modules/mob/living/carbon/human/human_helpers.dm +++ b/code/modules/mob/living/carbon/human/human_helpers.dm @@ -370,3 +370,17 @@ user.visible_message(span_notice("[user] fixes some of the [message] [src]'s [affecting.name]."), \ span_notice("You fix some of the [message] [src == user ? "your" : "[src]'s"] [affecting.name].")) return TRUE + +/// Sets both mob's and eye organ's eye color values +/// If color_right is not passed, its assumed to be the same as color_left +/mob/living/carbon/human/proc/set_eye_color(color_left, color_right) + if (!color_right) + color_right = color_left + eye_color_left = color_left + eye_color_right = color_right + // Doesn't assign eye color if they already have one from their type + var/obj/item/organ/eyes/eyes = get_organ_by_type(/obj/item/organ/eyes) + if (istype(eyes) && !initial(eyes.eye_color_left) && !initial(eyes.eye_color_right)) + eyes.eye_color_left = color_left + eyes.eye_color_right = color_right + eyes.refresh(src, FALSE) diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index 74def434a31..562ad5d8190 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -3279,6 +3279,7 @@ if (eyes && !IS_ROBOTIC_ORGAN(eyes)) eyes.eye_color_left = color eyes.eye_color_right = color + affected_human.update_body() /datum/reagent/luminescent_fluid/red name = "Red Luminiscent Fluid" diff --git a/code/modules/surgery/organs/internal/cyberimp/augments_arms.dm b/code/modules/surgery/organs/internal/cyberimp/augments_arms.dm index 41fa9babe7a..4df1873c001 100644 --- a/code/modules/surgery/organs/internal/cyberimp/augments_arms.dm +++ b/code/modules/surgery/organs/internal/cyberimp/augments_arms.dm @@ -22,6 +22,8 @@ var/extend_sound = 'sound/vehicles/mecha/mechmove03.ogg' /// Sound played when retracting var/retract_sound = 'sound/vehicles/mecha/mechmove03.ogg' + /// Do we have a separate icon_state for the hand overlay? + var/hand_state = TRUE /obj/item/organ/cyberimp/arm/Initialize(mapload) . = ..() @@ -89,6 +91,25 @@ // give the owner an idea about why his implant is glitching Retract() +/obj/item/organ/cyberimp/arm/get_overlay_state(image_layer, obj/item/bodypart/limb) + return "[aug_overlay][zone == BODY_ZONE_L_ARM ? "_left" : "_right"]" + +/obj/item/organ/cyberimp/arm/get_overlay(image_layer, obj/item/bodypart/limb) + if (!hand_state) + return ..() + + var/mutable_appearance/arm_overlay = mutable_appearance( + icon = aug_icon, + icon_state = get_overlay_state(), + layer = image_layer, + ) + var/mutable_appearance/hand_overlay = mutable_appearance( + icon = aug_icon, + icon_state = "[get_overlay_state()]_hand", + layer = -BODYPARTS_HIGH_LAYER, + ) + return list(arm_overlay, hand_overlay) + /** * Called when the mob uses the "drop item" hotkey * @@ -223,6 +244,7 @@ name = "integrated toolset implant" desc = "A stripped-down version of the engineering cyborg toolset, designed to be installed on subject's arm. Contain advanced versions of every tool." icon_state = "toolkit_engineering" + aug_overlay = "toolkit_engi" actions_types = list(/datum/action/item_action/organ_action/toggle/toolkit) items_to_create = list( /obj/item/screwdriver/cyborg, @@ -238,6 +260,7 @@ name = "integrated paperwork implant" desc = "A highly sought out implant among heads of personnel, and other high up command staff in Nanotrasen. This implant allows the user to always have the tools necessary for paperwork handy" icon_state = "toolkit_engineering" + aug_overlay = "toolkit_engi" actions_types = list(/datum/action/item_action/organ_action/toggle/toolkit) items_to_create = list( /obj/item/pen/fountain, @@ -277,11 +300,14 @@ /obj/item/organ/cyberimp/arm/medibeam name = "integrated medical beamgun" desc = "A cybernetic implant that allows the user to project a healing beam from their hand." + icon_state = "toolkit_surgical" + aug_overlay = "toolkit_med" items_to_create = list(/obj/item/gun/medbeam) /obj/item/organ/cyberimp/arm/flash name = "integrated high-intensity photon projector" //Why not desc = "An integrated projector mounted onto a user's arm that is able to be used as a powerful flash." + aug_overlay = "toolkit" items_to_create = list(/obj/item/assembly/flash/armimplant) /obj/item/organ/cyberimp/arm/flash/Initialize(mapload) @@ -306,11 +332,13 @@ /obj/item/organ/cyberimp/arm/baton name = "arm electrification implant" desc = "An illegal combat implant that allows the user to administer disabling shocks from their arm." + aug_overlay = "toolkit" items_to_create = list(/obj/item/borg/stun) /obj/item/organ/cyberimp/arm/combat name = "combat cybernetics implant" desc = "A powerful cybernetic implant that contains combat modules built into the user's arm." + aug_overlay = "toolkit" items_to_create = list( /obj/item/melee/energy/blade/hardlight, /obj/item/gun/medbeam, @@ -331,6 +359,7 @@ name = "surgical toolset implant" desc = "A set of surgical tools hidden behind a concealed panel on the user's arm." icon_state = "toolkit_surgical" + aug_overlay = "toolkit_med" actions_types = list(/datum/action/item_action/organ_action/toggle/toolkit) items_to_create = list( /obj/item/retractor/augment, @@ -345,6 +374,7 @@ /obj/item/organ/cyberimp/arm/surgery/emagged name = "hacked surgical toolset implant" desc = "A set of surgical tools hidden behind a concealed panel on the user's arm. This one seems to have been tampered with." + aug_overlay = "toolkit_med" items_to_create = list( /obj/item/retractor/augment, /obj/item/hemostat/augment, @@ -374,6 +404,8 @@ ) actions_types = list() + aug_overlay = "strongarm" + hand_state = FALSE ///The amount of damage the implant adds to our unarmed attacks. var/punch_damage = 5 diff --git a/code/modules/surgery/organs/internal/cyberimp/augments_chest.dm b/code/modules/surgery/organs/internal/cyberimp/augments_chest.dm index a26bc7b7de0..c5dedb71fab 100644 --- a/code/modules/surgery/organs/internal/cyberimp/augments_chest.dm +++ b/code/modules/surgery/organs/internal/cyberimp/augments_chest.dm @@ -7,6 +7,7 @@ name = "nutriment pump implant" desc = "This implant will synthesize and pump into your bloodstream a small amount of nutriment when you are starving." icon_state = "nutriment_implant" + aug_overlay = "nutripump" var/hunger_threshold = NUTRITION_LEVEL_STARVING var/synthesizing = 0 var/poison_amount = 5 @@ -37,6 +38,7 @@ name = "nutriment pump implant PLUS" desc = "This implant will synthesize and pump into your bloodstream a small amount of nutriment when you are hungry." icon_state = "adv_nutriment_implant" + aug_overlay = "nutripump_adv" hunger_threshold = NUTRITION_LEVEL_HUNGRY poison_amount = 10 @@ -44,6 +46,8 @@ name = "reviver implant" desc = "This implant will attempt to revive and heal you if you lose consciousness. For the faint of heart!" icon_state = "reviver_implant" + aug_overlay = "reviver" + emissive_overlay = TRUE slot = ORGAN_SLOT_HEART_AID var/revive_cost = 0 var/reviving = FALSE @@ -159,7 +163,8 @@ slot = ORGAN_SLOT_THRUSTERS icon_state = "imp_jetpack" base_icon_state = "imp_jetpack" - implant_color = null + aug_overlay = "imp_jetpack" + emissive_overlay = TRUE actions_types = list(/datum/action/item_action/organ_action/toggle) w_class = WEIGHT_CLASS_NORMAL var/on = FALSE @@ -208,6 +213,7 @@ if(!silent) to_chat(owner, span_notice("You turn your thrusters set on.")) update_appearance() + owner.update_body_parts() /obj/item/organ/cyberimp/chest/thrusters/proc/deactivate(silent = FALSE) if(!on) @@ -218,6 +224,7 @@ to_chat(owner, span_notice("You turn your thrusters set off.")) on = FALSE update_appearance() + owner.update_body_parts() /obj/item/organ/cyberimp/chest/thrusters/update_icon_state() icon_state = "[base_icon_state][on ? "-on" : null]" @@ -258,6 +265,14 @@ deactivate(silent = TRUE) return FALSE +/obj/item/organ/cyberimp/chest/thrusters/get_overlay_state(image_layer, obj/item/bodypart/limb) + return "[aug_overlay][on ? "_on" : ""]" + +/obj/item/organ/cyberimp/chest/thrusters/get_overlay(image_layer, obj/item/bodypart/limb) + . = ..() + for (var/image/overlay as anything in .) + overlay.layer = -BODYPARTS_HIGH_LAYER // makes absolutely zero sense why it would layer ontop of jumpsuits but it looks cool + /obj/item/organ/cyberimp/chest/spine name = "\improper Herculean gravitronic spinal implant" desc = "This gravitronic spinal interface is able to improve the athletics of a user, allowing them greater physical ability. \ @@ -304,23 +319,24 @@ remove_organ_trait(TRAIT_STURDY_FRAME) /obj/item/organ/cyberimp/chest/spine/item_interaction(mob/living/user, obj/item/tool, list/modifiers) - . = ..() + if(!istype(tool, /obj/item/assembly/signaler/anomaly/grav)) + return NONE + if(core_applied) user.balloon_alert(user, "core already installed!") return ITEM_INTERACT_BLOCKING - if(istype(tool, /obj/item/assembly/signaler/anomaly/grav)) - user.balloon_alert(user, "core installed.") - name = /obj/item/organ/cyberimp/chest/spine/atlas::name - desc = /obj/item/organ/cyberimp/chest/spine/atlas::desc - athletics_boost_multiplier = /obj/item/organ/cyberimp/chest/spine/atlas::athletics_boost_multiplier - added_throw_range = /obj/item/organ/cyberimp/chest/spine/atlas::added_throw_range - added_throw_speed = /obj/item/organ/cyberimp/chest/spine/atlas::added_throw_speed - strength_bonus = /obj/item/organ/cyberimp/chest/spine/atlas::strength_bonus - core_applied = TRUE - update_appearance() - qdel(tool) - return ITEM_INTERACT_SUCCESS + user.balloon_alert(user, "core installed") + name = /obj/item/organ/cyberimp/chest/spine/atlas::name + desc = /obj/item/organ/cyberimp/chest/spine/atlas::desc + athletics_boost_multiplier = /obj/item/organ/cyberimp/chest/spine/atlas::athletics_boost_multiplier + added_throw_range = /obj/item/organ/cyberimp/chest/spine/atlas::added_throw_range + added_throw_speed = /obj/item/organ/cyberimp/chest/spine/atlas::added_throw_speed + strength_bonus = /obj/item/organ/cyberimp/chest/spine/atlas::strength_bonus + core_applied = TRUE + update_appearance() + qdel(tool) + return ITEM_INTERACT_SUCCESS /obj/item/organ/cyberimp/chest/spine/atlas name = "\improper Atlas gravitonic spinal implant" diff --git a/code/modules/surgery/organs/internal/cyberimp/augments_eyes.dm b/code/modules/surgery/organs/internal/cyberimp/augments_eyes.dm index 525400b5419..9763b22e4b0 100644 --- a/code/modules/surgery/organs/internal/cyberimp/augments_eyes.dm +++ b/code/modules/surgery/organs/internal/cyberimp/augments_eyes.dm @@ -15,48 +15,61 @@ var/HUD_traits = list() /// Whether the HUD implant is on or off var/toggled_on = TRUE + /// Eyecolor from the HUD + var/hud_color = "#3CB8A5" -/obj/item/organ/cyberimp/eyes/hud/proc/toggle_hud(mob/living/carbon/eye_owner) +/obj/item/organ/cyberimp/eyes/hud/proc/toggle_hud(mob/living/carbon/human/eye_owner) if(toggled_on) toggled_on = FALSE eye_owner.remove_traits(HUD_traits, ORGAN_TRAIT) balloon_alert(eye_owner, "hud disabled") + if(hud_color) + eye_owner.remove_eye_color(EYE_COLOR_HUD_PRIORITY) return toggled_on = TRUE eye_owner.add_traits(HUD_traits, ORGAN_TRAIT) balloon_alert(eye_owner, "hud enabled") + if(hud_color) + eye_owner.add_eye_color_right(hud_color, EYE_COLOR_HUD_PRIORITY) -/obj/item/organ/cyberimp/eyes/hud/on_mob_insert(mob/living/carbon/eye_owner, special = FALSE, movement_flags) +/obj/item/organ/cyberimp/eyes/hud/on_mob_insert(mob/living/carbon/human/eye_owner, special = FALSE, movement_flags) . = ..() - eye_owner.add_traits(HUD_traits, ORGAN_TRAIT) toggled_on = TRUE + if(hud_color) + eye_owner.add_eye_color_right(hud_color, EYE_COLOR_HUD_PRIORITY, !special) -/obj/item/organ/cyberimp/eyes/hud/on_mob_remove(mob/living/carbon/eye_owner, special, movement_flags) +/obj/item/organ/cyberimp/eyes/hud/on_mob_remove(mob/living/carbon/human/eye_owner, special, movement_flags) . = ..() eye_owner.remove_traits(HUD_traits, ORGAN_TRAIT) toggled_on = FALSE + if(hud_color) + eye_owner.remove_eye_color(EYE_COLOR_HUD_PRIORITY, !special) /obj/item/organ/cyberimp/eyes/hud/medical name = "medical HUD implant" desc = "These cybernetic eye implants will display a medical HUD over everything you see." icon_state = "eye_implant_medical" HUD_traits = list(TRAIT_MEDICAL_HUD) + hud_color = "#1D8FEC" /obj/item/organ/cyberimp/eyes/hud/security name = "security HUD implant" desc = "These cybernetic eye implants will display a security HUD over everything you see." icon_state = "eye_implant_security" HUD_traits = list(TRAIT_SECURITY_HUD) + hud_color = "#9A151E" /obj/item/organ/cyberimp/eyes/hud/diagnostic name = "diagnostic HUD implant" desc = "These cybernetic eye implants will display a diagnostic HUD over everything you see." icon_state = "eye_implant_diagnostic" HUD_traits = list(TRAIT_DIAGNOSTIC_HUD, TRAIT_BOT_PATH_HUD) + hud_color = "#CC6E33" /obj/item/organ/cyberimp/eyes/hud/security/syndicate name = "contraband security HUD implant" desc = "A Cybersun Industries brand Security HUD Implant. These illicit cybernetic eye implants will display a security HUD over everything you see." icon_state = "eye_implant_syndicate" organ_flags = ORGAN_ROBOTIC | ORGAN_HIDDEN + hud_color = null diff --git a/code/modules/surgery/organs/internal/cyberimp/augments_internal.dm b/code/modules/surgery/organs/internal/cyberimp/augments_internal.dm index fc358e2c5f6..d604344ba98 100644 --- a/code/modules/surgery/organs/internal/cyberimp/augments_internal.dm +++ b/code/modules/surgery/organs/internal/cyberimp/augments_internal.dm @@ -5,7 +5,72 @@ organ_flags = ORGAN_ROBOTIC failing_desc = "seems to be broken." - var/implant_color = COLOR_WHITE + /// icon of the bodypart overlay we're going to be applying to our owner + var/aug_icon = 'icons/mob/human/species/misc/bodypart_overlay_augmentations.dmi' + /// icon_state of the bodypart overlay we're going to be applying to our owner + var/aug_overlay = null + /// Does the implant have an emissive overlay too? + var/emissive_overlay = FALSE + /// Bodypart overlay we're going to apply to whoever we're implanted into + var/datum/bodypart_overlay/augment/bodypart_aug = null + +/obj/item/organ/cyberimp/Initialize(mapload) + . = ..() + if (aug_overlay) + bodypart_aug = new(src) + +/obj/item/organ/cyberimp/Destroy() + QDEL_NULL(bodypart_aug) + return ..() + +/obj/item/organ/cyberimp/proc/get_overlay_state() + return aug_overlay + +/obj/item/organ/cyberimp/proc/get_overlay(image_layer, obj/item/bodypart/limb) + . = list() + . += image(icon = aug_icon, icon_state = get_overlay_state(), layer = image_layer) + if (emissive_overlay) + . += emissive_appearance(aug_icon, "[get_overlay_state()]_e", limb.owner || limb, image_layer) + +/obj/item/organ/cyberimp/on_bodypart_insert(obj/item/bodypart/limb) + . = ..() + if (bodypart_aug) + limb.add_bodypart_overlay(bodypart_aug) + +/obj/item/organ/cyberimp/on_bodypart_remove(obj/item/bodypart/limb) + . = ..() + if (bodypart_aug) + limb.remove_bodypart_overlay(bodypart_aug) + +/datum/bodypart_overlay/augment + layers = EXTERNAL_ADJACENT + /// Implant that owns this overlay + var/obj/item/organ/cyberimp/implant + +/datum/bodypart_overlay/augment/New(obj/item/organ/cyberimp/implant) + . = ..() + src.implant = implant + +/datum/bodypart_overlay/augment/Destroy(force) + implant = null + return ..() + +/datum/bodypart_overlay/augment/generate_icon_cache() + . = ..() + . += implant.get_overlay_state() + +/datum/bodypart_overlay/augment/get_overlay(layer, obj/item/bodypart/limb) + layer = bitflag_to_layer(layer) + var/list/imageset = implant.get_overlay(layer, limb) + if(blocks_emissive == EMISSIVE_BLOCK_NONE || !limb) + return imageset + + var/list/all_images = list() + for(var/image/overlay as anything in imageset) + all_images += overlay + all_images += emissive_blocker(overlay.icon, overlay.icon_state, limb, layer = overlay.layer, alpha = overlay.alpha) + + return all_images /obj/item/organ/cyberimp/feel_for_damage(self_aware) // No feeling in implants (yet?) @@ -284,6 +349,7 @@ icon_state = "implant_mask" slot = ORGAN_SLOT_BREATHING_TUBE w_class = WEIGHT_CLASS_TINY + aug_overlay = "breathing_tube" /obj/item/organ/cyberimp/mouth/breathing_tube/emp_act(severity) . = ..() diff --git a/code/modules/surgery/organs/internal/eyes/_eyes.dm b/code/modules/surgery/organs/internal/eyes/_eyes.dm index f8d66ede5a5..5ff3aa14a9b 100644 --- a/code/modules/surgery/organs/internal/eyes/_eyes.dm +++ b/code/modules/surgery/organs/internal/eyes/_eyes.dm @@ -37,8 +37,8 @@ /// Are these eyes immune to pepperspray? var/pepperspray_protect = FALSE - var/eye_color_left = "" //set to a hex code to override a mob's left eye color - var/eye_color_right = "" //set to a hex code to override a mob's right eye color + var/eye_color_left = null // set to a hex code to override a mob's left eye color + var/eye_color_right = null // set to a hex code to override a mob's right eye color var/eye_icon_state = "eyes" /// Do these eyes have blinking animations var/blink_animation = TRUE @@ -74,6 +74,13 @@ . = ..() receiver.cure_blind(NO_EYES) apply_damaged_eye_effects() + // Ensures that non-player mobs get their eye colors assigned, as players get them from prefs + if (ishuman(receiver)) + var/mob/living/carbon/human/as_human = receiver + if (!eye_color_left) + eye_color_left = as_human.eye_color_left + if (!eye_color_right) + eye_color_right = as_human.eye_color_right refresh(receiver, call_update = !special) RegisterSignal(receiver, COMSIG_ATOM_BULLET_ACT, PROC_REF(on_bullet_act)) RegisterSignal(receiver, COMSIG_COMPONENT_CLEAN_FACE_ACT, PROC_REF(on_face_wash)) @@ -90,9 +97,9 @@ return var/mob/living/carbon/human/affected_human = eye_owner - if(length(eye_color_left)) + if(eye_color_left) affected_human.add_eye_color_left(eye_color_left, EYE_COLOR_ORGAN_PRIORITY, update_body = FALSE) - if(length(eye_color_right)) + if(eye_color_right) affected_human.add_eye_color_right(eye_color_right, EYE_COLOR_ORGAN_PRIORITY, update_body = FALSE) refresh_atom_color_overrides() @@ -152,9 +159,9 @@ var/left_color = COLOR_WHITE var/right_color = COLOR_WHITE - if (length(eye_color_left)) + if (eye_color_left) left_color = eye_color_left - if (length(eye_color_right)) + if (eye_color_right) right_color = eye_color_right if (checked_color[ATOM_COLOR_TYPE_INDEX] == ATOM_COLOR_TYPE_FILTER) @@ -295,7 +302,7 @@ left_scar.blend_mode = BLEND_INSET_OVERLAY . += left_scar - if (iris_overlay && length(eye_color_left) && length(eye_color_right)) + if (iris_overlay && eye_color_left && eye_color_right) var/mutable_appearance/left_iris = mutable_appearance(icon, "[iris_overlay]_l") var/mutable_appearance/right_iris = mutable_appearance(icon, "[iris_overlay]_r") var/list/color_left = rgb2num(eye_color_left, COLORSPACE_HSL) @@ -427,15 +434,7 @@ eyelid_right.render_target = "*[REF(parent)]_eyelid_right" parent.vis_contents += eyelid_left parent.vis_contents += eyelid_right - var/sync_blinking = synchronized_blinking && (parent.get_organ_loss(ORGAN_SLOT_BRAIN) < ASYNC_BLINKING_BRAIN_DAMAGE) - // Randomize order for unsynched animations - if (sync_blinking || prob(50)) - var/list/anim_times = animate_eyelid(eyelid_left, parent, sync_blinking) - animate_eyelid(eyelid_right, parent, sync_blinking, anim_times) - else - var/list/anim_times = animate_eyelid(eyelid_right, parent, sync_blinking) - animate_eyelid(eyelid_left, parent, sync_blinking, anim_times) - + animate_eyelids(parent) var/mutable_appearance/left_eyelid_overlay = mutable_appearance(layer = -BODY_LAYER, offset_spokesman = parent) var/mutable_appearance/right_eyelid_overlay = mutable_appearance(layer = -BODY_LAYER, offset_spokesman = parent) left_eyelid_overlay.render_source = "*[REF(parent)]_eyelid_left" @@ -447,14 +446,28 @@ . = list() var/prevent_loops = HAS_TRAIT(parent, TRAIT_PREVENT_BLINK_LOOPS) animate(eyelid, alpha = 0, time = 0, loop = (prevent_loops ? 0 : -1)) - for (var/i in 1 to (prevent_loops ? 1 : BLINK_LOOPS)) - var/wait_time = rand(BASE_BLINKING_DELAY - RAND_BLINKING_DELAY, BASE_BLINKING_DELAY + RAND_BLINKING_DELAY) + + var/wait_time = rand(BASE_BLINKING_DELAY - RAND_BLINKING_DELAY, BASE_BLINKING_DELAY + RAND_BLINKING_DELAY) + if (anim_times) + if (sync_blinking) + wait_time = anim_times[1] + anim_times.Cut(1, 2) + else + wait_time = rand(max(BASE_BLINKING_DELAY - RAND_BLINKING_DELAY, anim_times[1] - RAND_BLINKING_DELAY), anim_times[1]) + + animate(time = wait_time) + . += wait_time + + var/cycles = (prevent_loops ? 1 : BLINK_LOOPS) + for (var/i in 1 to cycles) if (anim_times) if (sync_blinking) wait_time = anim_times[1] anim_times.Cut(1, 2) else wait_time = rand(max(BASE_BLINKING_DELAY - RAND_BLINKING_DELAY, anim_times[1] - RAND_BLINKING_DELAY), anim_times[1]) + else + wait_time = rand(BASE_BLINKING_DELAY - RAND_BLINKING_DELAY, BASE_BLINKING_DELAY + RAND_BLINKING_DELAY) . += wait_time if (anim_times && !sync_blinking) // Make sure that we're somewhat in sync with the other eye @@ -462,8 +475,38 @@ anim_times.Cut(1, 2) animate(alpha = 255, time = 0) animate(time = BLINK_DURATION) - animate(alpha = 0, time = 0) - animate(time = wait_time) + if (i != cycles) + animate(alpha = 0, time = 0) + animate(time = wait_time) + +/obj/item/organ/eyes/proc/blink(duration = BLINK_DURATION, restart_animation = TRUE) + var/left_delayed = rand(50) + // Storing blink delay so mistimed blinks of lizards don't get cut short + var/blink_delay = synchronized_blinking ? rand(0, RAND_BLINKING_DELAY) : 0 + animate(eyelid_left, alpha = 0, time = 0) + if (!synchronized_blinking && left_delayed) + animate(time = blink_delay) + animate(alpha = 255, time = 0) + animate(time = duration) + animate(alpha = 0, time = 0) + animate(eyelid_right, alpha = 0, time = 0) + if (!synchronized_blinking && !left_delayed) + animate(time = blink_delay) + animate(alpha = 255, time = 0) + animate(time = duration) + animate(alpha = 0, time = 0) + if (restart_animation) + addtimer(CALLBACK(src, PROC_REF(animate_eyelids), owner), blink_delay + duration) + +/obj/item/organ/eyes/proc/animate_eyelids(mob/living/carbon/human/parent) + var/sync_blinking = synchronized_blinking && (parent.get_organ_loss(ORGAN_SLOT_BRAIN) < ASYNC_BLINKING_BRAIN_DAMAGE) + // Randomize order for unsynched animations + if (sync_blinking || prob(50)) + var/list/anim_times = animate_eyelid(eyelid_left, parent, sync_blinking) + animate_eyelid(eyelid_right, parent, sync_blinking, anim_times) + else + var/list/anim_times = animate_eyelid(eyelid_right, parent, sync_blinking) + animate_eyelid(eyelid_left, parent, sync_blinking, anim_times) /obj/effect/abstract/eyelid_effect name = "eyelid" @@ -640,8 +683,8 @@ /obj/item/organ/eyes/robotic/flashlight name = "flashlight eyes" desc = "It's two flashlights rigged together with some wire. Why would you put these in someone's head?" - eye_color_left ="fee5a3" - eye_color_right ="fee5a3" + eye_color_left ="#fee5a3" + eye_color_right ="#fee5a3" icon = 'icons/obj/lighting.dmi' icon_state = "flashlight_eyes" flash_protect = FLASH_PROTECTION_WELDER diff --git a/code/modules/unit_tests/changeling.dm b/code/modules/unit_tests/changeling.dm index 7f86510fd62..cc39b471d09 100644 --- a/code/modules/unit_tests/changeling.dm +++ b/code/modules/unit_tests/changeling.dm @@ -82,8 +82,7 @@ ling.dna.features["spines"] = "Long + Membrane" ling.dna.features["lizard_markings"] = "Light Belly" ling.dna.features["legs"] = DIGITIGRADE_LEGS - ling.eye_color_left = COLOR_WHITE - ling.eye_color_right = COLOR_WHITE + ling.set_eye_color(COLOR_WHITE) ling.dna.update_ui_block(DNA_EYE_COLOR_LEFT_BLOCK) ling.dna.update_ui_block(DNA_EYE_COLOR_RIGHT_BLOCK) ling.set_species(/datum/species/lizard) diff --git a/icons/mob/human/species/misc/bodypart_overlay_augmentations.dmi b/icons/mob/human/species/misc/bodypart_overlay_augmentations.dmi new file mode 100644 index 00000000000..a8e122dfe52 Binary files /dev/null and b/icons/mob/human/species/misc/bodypart_overlay_augmentations.dmi differ diff --git a/icons/mob/human/species/misc/bodypart_overlay_simple.dmi b/icons/mob/human/species/misc/bodypart_overlay_simple.dmi index e17934a6cdb..f6cbf72ff9d 100644 Binary files a/icons/mob/human/species/misc/bodypart_overlay_simple.dmi and b/icons/mob/human/species/misc/bodypart_overlay_simple.dmi differ