mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-10 09:42:29 +00:00
Adds blinking and a new Fluoride Stare quirk (#88927)
## About The Pull Request Spessmen now need to blink! If you have non-robotic eyes, you'll automatically blink every once in a while. Lizards have asynchronous blinking, and whenever they blink one of their eyes (chosen at random) will blink slightly sooner. https://github.com/user-attachments/assets/e62020ef-d2f8-4634-9399-a27244326cfe You can also blink manually, as emotes now fire the animations. https://github.com/user-attachments/assets/80d6304f-f3c2-424a-a5aa-96a4aee7acdc Adds a new eye-related quirk, Fluoride Stare! It will spawn you without eyelids, preventing random or manual blinking and forcing you to wet your eyes with some saline solution (of which you get a bottle, and a dropper to apply it) every minute or so. Additionally, eyes now display their color on their organ sprite, instead of always showing up as blue. (Don't tell roleplayers, but Fully Immerse smite now blinds you when you blink, for true full immersion) ## Why It's Good For The Game Spessmen blinking is just soulful, and brings some life into the game. As for the quirk, its just a funny bit/reference that people can use to... torture themselves? ## Changelog 🆑 add: Spessmen now blink. add: Added a new Fluoride Stare quirk, keep those eyeballs wet, lest they crack! image: Eyes now display their color on their organ sprite, instead of always being displayed as blue. /🆑
This commit is contained in:
@@ -265,3 +265,6 @@
|
||||
|
||||
/// from /mob/update_incapacitated(): (old_incap, new_incap)
|
||||
#define COMSIG_MOB_INCAPACITATE_CHANGED "mob_incapacitated"
|
||||
|
||||
/// from /obj/item/reagent_containers/dropper/interact_with_atom(atom/target, mob/living/user, list/modifiers): (mob/living/user, atom/dropper, datum/reagents/reagents, fraction)
|
||||
#define COMSIG_MOB_REAGENTS_DROPPED_INTO_EYES "mob_reagents_drop_into_eyes"
|
||||
|
||||
@@ -1415,4 +1415,13 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
|
||||
/// Apply to movables to say "hey, this movable is technically flat on the floor, so it'd be mopped up by a mop"
|
||||
#define TRAIT_MOPABLE "mopable"
|
||||
|
||||
/// Humans with this trait do not blink
|
||||
#define TRAIT_PREVENT_BLINKING "prevent_blinking"
|
||||
|
||||
/// Prevents animations for blinking from looping
|
||||
#define TRAIT_PREVENT_BLINK_LOOPS "prevent_blink_loops"
|
||||
|
||||
/// Mob doesn't get closed eyelids overlay when it gets knocked out cold or dies
|
||||
#define TRAIT_NO_EYELIDS "no_eyelids"
|
||||
|
||||
// END TRAIT DEFINES
|
||||
|
||||
@@ -585,6 +585,9 @@ GLOBAL_LIST_INIT(traits_by_type, list(
|
||||
"TRAIT_IGNORE_FIRE_PROTECTION" = TRAIT_IGNORE_FIRE_PROTECTION,
|
||||
"TRAIT_LEFT_EYE_SCAR" = TRAIT_LEFT_EYE_SCAR,
|
||||
"TRAIT_RIGHT_EYE_SCAR" = TRAIT_RIGHT_EYE_SCAR,
|
||||
"TRAIT_PREVENT_BLINKING" = TRAIT_PREVENT_BLINKING,
|
||||
"TRAIT_PREVENT_BLINK_LOOPS" = TRAIT_PREVENT_BLINK_LOOPS,
|
||||
"TRAIT_NO_EYELIDS" = TRAIT_NO_EYELIDS,
|
||||
),
|
||||
/obj/item = list(
|
||||
"TRAIT_APC_SHOCKING" = TRAIT_APC_SHOCKING,
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
// Shifted to glob so they are generated at world start instead of risking players doing preference stuff before the subsystem inits
|
||||
GLOBAL_LIST_INIT_TYPED(quirk_blacklist, /list/datum/quirk, list(
|
||||
list(/datum/quirk/item_quirk/blindness, /datum/quirk/item_quirk/nearsighted, /datum/quirk/item_quirk/scarred_eye),
|
||||
list(/datum/quirk/item_quirk/blindness, /datum/quirk/item_quirk/fluoride_stare),
|
||||
list(/datum/quirk/item_quirk/blindness, /datum/quirk/touchy),
|
||||
list(/datum/quirk/jolly, /datum/quirk/depression, /datum/quirk/apathetic, /datum/quirk/hypersensitive),
|
||||
list(/datum/quirk/no_taste, /datum/quirk/vegetarian, /datum/quirk/deviant_tastes, /datum/quirk/gamer),
|
||||
|
||||
@@ -1,31 +1,51 @@
|
||||
/datum/component/manual_blinking
|
||||
dupe_mode = COMPONENT_DUPE_UNIQUE
|
||||
|
||||
var/obj/item/organ/eyes/E
|
||||
var/obj/item/organ/eyes/parent_eyes
|
||||
var/warn_grace = FALSE
|
||||
var/warn_dying = FALSE
|
||||
var/last_blink
|
||||
var/check_every = 20 SECONDS
|
||||
var/grace_period = 6 SECONDS
|
||||
var/damage_rate = 1 // organ damage taken per tick
|
||||
var/list/valid_emotes = list(/datum/emote/living/carbon/blink, /datum/emote/living/carbon/blink_r)
|
||||
/// Organ damage taken per tick
|
||||
var/damage_rate = 1
|
||||
/// How much saline needs to be dropper at once for it to count as "blinking"
|
||||
var/min_saline = 1
|
||||
/// Do we display a message when adding/removing the component
|
||||
var/display_message = TRUE
|
||||
var/list/valid_emotes = list(/datum/emote/living/carbon/human/blink, /datum/emote/living/carbon/human/blink_r)
|
||||
|
||||
/datum/component/manual_blinking/Initialize()
|
||||
/datum/component/manual_blinking/Initialize(damage_rate = 1, check_every = 20 SECONDS, grace_period = 6 SECONDS, display_message = TRUE)
|
||||
if(!iscarbon(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
var/mob/living/carbon/C = parent
|
||||
E = C.get_organ_slot(ORGAN_SLOT_EYES)
|
||||
src.damage_rate = damage_rate
|
||||
src.check_every = check_every
|
||||
src.grace_period = grace_period
|
||||
src.display_message = display_message
|
||||
|
||||
if(E)
|
||||
START_PROCESSING(SSdcs, src)
|
||||
last_blink = world.time
|
||||
to_chat(C, span_notice("You suddenly realize you're blinking manually."))
|
||||
var/mob/living/carbon/carbon_parent = parent
|
||||
ADD_TRAIT(carbon_parent, TRAIT_PREVENT_BLINK_LOOPS, REF(src))
|
||||
carbon_parent.update_body()
|
||||
parent_eyes = carbon_parent.get_organ_slot(ORGAN_SLOT_EYES)
|
||||
|
||||
if(!parent_eyes || IS_ROBOTIC_ORGAN(parent_eyes))
|
||||
return
|
||||
|
||||
START_PROCESSING(SSdcs, src)
|
||||
last_blink = world.time
|
||||
if (display_message)
|
||||
to_chat(carbon_parent, span_notice("You suddenly realize you're blinking manually."))
|
||||
|
||||
/datum/component/manual_blinking/Destroy(force)
|
||||
E = null
|
||||
REMOVE_TRAIT(parent, TRAIT_PREVENT_BLINK_LOOPS, REF(src))
|
||||
parent_eyes = null
|
||||
STOP_PROCESSING(SSdcs, src)
|
||||
to_chat(parent, span_notice("You revert back to automatic blinking."))
|
||||
if (display_message)
|
||||
to_chat(parent, span_notice("You revert back to automatic blinking."))
|
||||
var/mob/living/carbon/carbon_parent = parent
|
||||
carbon_parent.cure_blind(REF(src))
|
||||
carbon_parent.update_body()
|
||||
return ..()
|
||||
|
||||
/datum/component/manual_blinking/RegisterWithParent()
|
||||
@@ -34,13 +54,10 @@
|
||||
RegisterSignal(parent, COMSIG_CARBON_LOSE_ORGAN, PROC_REF(check_removed_organ))
|
||||
RegisterSignal(parent, COMSIG_LIVING_REVIVE, PROC_REF(restart))
|
||||
RegisterSignal(parent, COMSIG_LIVING_DEATH, PROC_REF(pause))
|
||||
RegisterSignal(parent, COMSIG_MOB_REAGENTS_DROPPED_INTO_EYES, PROC_REF(on_dropper))
|
||||
|
||||
/datum/component/manual_blinking/UnregisterFromParent()
|
||||
UnregisterSignal(parent, COMSIG_MOB_EMOTE)
|
||||
UnregisterSignal(parent, COMSIG_CARBON_GAIN_ORGAN)
|
||||
UnregisterSignal(parent, COMSIG_CARBON_LOSE_ORGAN)
|
||||
UnregisterSignal(parent, COMSIG_LIVING_REVIVE)
|
||||
UnregisterSignal(parent, COMSIG_LIVING_DEATH)
|
||||
UnregisterSignal(parent, list(COMSIG_MOB_EMOTE, COMSIG_CARBON_GAIN_ORGAN, COMSIG_CARBON_LOSE_ORGAN, COMSIG_LIVING_REVIVE, COMSIG_LIVING_DEATH, COMSIG_MOB_REAGENTS_DROPPED_INTO_EYES))
|
||||
|
||||
/datum/component/manual_blinking/proc/restart()
|
||||
SIGNAL_HANDLER
|
||||
@@ -53,41 +70,51 @@
|
||||
STOP_PROCESSING(SSdcs, src)
|
||||
|
||||
/datum/component/manual_blinking/process()
|
||||
var/mob/living/carbon/C = parent
|
||||
|
||||
if(world.time > (last_blink + check_every + grace_period))
|
||||
if(!warn_dying)
|
||||
to_chat(C, span_userdanger("Your eyes begin to wither, you need to blink!"))
|
||||
to_chat(parent, span_userdanger("Your eyes begin to wither, you need to blink!"))
|
||||
warn_dying = TRUE
|
||||
|
||||
E.apply_organ_damage(damage_rate)
|
||||
parent_eyes.apply_organ_damage(damage_rate)
|
||||
else if(world.time > (last_blink + check_every))
|
||||
if(!warn_grace)
|
||||
to_chat(C, span_danger("You feel a need to blink!"))
|
||||
to_chat(parent, span_danger("You feel a need to blink!"))
|
||||
warn_grace = TRUE
|
||||
|
||||
/datum/component/manual_blinking/proc/check_added_organ(mob/who_cares, obj/item/organ/O)
|
||||
/datum/component/manual_blinking/proc/check_added_organ(mob/who_cares, obj/item/organ/added_organ)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
var/obj/item/organ/eyes/new_eyes = O
|
||||
|
||||
if(istype(new_eyes,/obj/item/organ/eyes))
|
||||
E = new_eyes
|
||||
if(istype(added_organ, /obj/item/organ/eyes))
|
||||
parent_eyes = added_organ
|
||||
if (IS_ROBOTIC_ORGAN(parent_eyes))
|
||||
parent_eyes = null
|
||||
return
|
||||
last_blink = world.time
|
||||
START_PROCESSING(SSdcs, src)
|
||||
|
||||
/datum/component/manual_blinking/proc/check_removed_organ(mob/who_cares, obj/item/organ/O)
|
||||
/datum/component/manual_blinking/proc/check_removed_organ(mob/who_cares, obj/item/organ/removed_organ)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
var/obj/item/organ/eyes/bye_beyes = O // oh come on, that's pretty good
|
||||
|
||||
if(istype(bye_beyes, /obj/item/organ/eyes))
|
||||
E = null
|
||||
if(removed_organ == parent_eyes)
|
||||
parent_eyes = null
|
||||
STOP_PROCESSING(SSdcs, src)
|
||||
|
||||
/datum/component/manual_blinking/proc/check_emote(mob/living/carbon/user, datum/emote/emote)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(emote.type in valid_emotes)
|
||||
if(!(emote.type in valid_emotes))
|
||||
return
|
||||
|
||||
warn_grace = FALSE
|
||||
warn_dying = FALSE
|
||||
last_blink = world.time
|
||||
user.become_blind(REF(src))
|
||||
addtimer(CALLBACK(user, TYPE_PROC_REF(/mob/living, remove_status_effect), /datum/status_effect/grouped/blindness, REF(src)), 0.15 SECONDS)
|
||||
|
||||
/datum/component/manual_blinking/proc/on_dropper(datum/source, mob/living/user, atom/dropper, datum/reagents/reagents, fraction)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
var/saline_amount = reagents.get_reagent_amount(/datum/reagent/medicine/salglu_solution) * fraction
|
||||
if (saline_amount >= min_saline)
|
||||
warn_grace = FALSE
|
||||
warn_dying = FALSE
|
||||
last_blink = world.time
|
||||
|
||||
36
code/datums/quirks/negative_quirks/fluoride_stare.dm
Normal file
36
code/datums/quirks/negative_quirks/fluoride_stare.dm
Normal file
@@ -0,0 +1,36 @@
|
||||
/datum/quirk/item_quirk/fluoride_stare
|
||||
name = "Fluoride Stare"
|
||||
desc = "You have lost your eyelids in a horrible accident, or so you tell others. You need to manually wet your eyes with a saline solution every once in a while!"
|
||||
icon = FA_ICON_EYE_DROPPER
|
||||
value = -6
|
||||
gain_text = span_danger("Your eyes feel itchy and dry...")
|
||||
lose_text = span_notice("You realize that sudden darkness that has just enveloped you was just your eyelids growing back.")
|
||||
medical_record_text = "Patient has lost their eyelids in a grueling accident."
|
||||
hardcore_value = 6
|
||||
quirk_flags = QUIRK_HUMAN_ONLY
|
||||
mail_goodies = list(/obj/item/reagent_containers/cup/bottle/salglu_solution, /obj/item/light/bulb)
|
||||
|
||||
/datum/quirk/item_quirk/fluoride_stare/add_unique(client/client_source)
|
||||
var/obj/item/reagent_containers/cup/bottle/salglu_solution/saline = new(get_turf(quirk_holder))
|
||||
give_item_to_holder(saline, list(
|
||||
LOCATION_LPOCKET = ITEM_SLOT_LPOCKET,
|
||||
LOCATION_RPOCKET = ITEM_SLOT_RPOCKET,
|
||||
LOCATION_BACKPACK = ITEM_SLOT_BACKPACK,
|
||||
LOCATION_HANDS = ITEM_SLOT_HANDS,
|
||||
))
|
||||
var/obj/item/reagent_containers/dropper/dropper = new(get_turf(quirk_holder))
|
||||
give_item_to_holder(dropper, list(
|
||||
LOCATION_LPOCKET = ITEM_SLOT_LPOCKET,
|
||||
LOCATION_RPOCKET = ITEM_SLOT_RPOCKET,
|
||||
LOCATION_BACKPACK = ITEM_SLOT_BACKPACK,
|
||||
LOCATION_HANDS = ITEM_SLOT_HANDS,
|
||||
))
|
||||
|
||||
/datum/quirk/item_quirk/fluoride_stare/add(client/client_source)
|
||||
ADD_TRAIT(quirk_holder, TRAIT_NO_EYELIDS, QUIRK_TRAIT)
|
||||
quirk_holder.AddComponent(/datum/component/manual_blinking, 1, 30 SECONDS, 10 SECONDS, FALSE)
|
||||
|
||||
/datum/quirk/item_quirk/fluoride_stare/remove()
|
||||
REMOVE_TRAIT(quirk_holder, TRAIT_NO_EYELIDS, QUIRK_TRAIT)
|
||||
if (!HAS_TRAIT(quirk_holder, TRAIT_NO_EYELIDS))
|
||||
qdel(quirk_holder.GetComponent(/datum/component/manual_blinking))
|
||||
@@ -26,6 +26,8 @@
|
||||
icon_state = "eyeballs-fly"
|
||||
flash_protect = FLASH_PROTECTION_HYPER_SENSITIVE
|
||||
native_fov = NONE //flies can see all around themselves.
|
||||
blink_animation = FALSE
|
||||
iris_overlays = FALSE
|
||||
|
||||
/obj/item/organ/eyes/fly/Initialize(mapload)
|
||||
. = ..()
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
icon = 'icons/obj/medical/organs/infuser_organs.dmi'
|
||||
icon_state = "eyes"
|
||||
iris_overlays = FALSE
|
||||
greyscale_config = /datum/greyscale_config/mutant_organ
|
||||
greyscale_colors = GOLIATH_COLORS
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
icon = 'icons/obj/medical/organs/infuser_organs.dmi'
|
||||
icon_state = "eyes"
|
||||
iris_overlays = FALSE
|
||||
greyscale_config = /datum/greyscale_config/mutant_organ
|
||||
greyscale_colors = RAT_COLORS
|
||||
low_light_cutoff = list(16, 11, 0)
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
name = "blackened orbs"
|
||||
desc = "These orbs will withstand the light of the sun, yet still see within the darkest voids."
|
||||
eye_icon_state = null
|
||||
blink_animation = FALSE
|
||||
iris_overlays = FALSE
|
||||
pepperspray_protect = TRUE
|
||||
flash_protect = FLASH_PROTECTION_WELDER
|
||||
color_cutoffs = list(20, 10, 40)
|
||||
|
||||
@@ -6,16 +6,6 @@
|
||||
message = "is strumming the air and headbanging like a safari chimp."
|
||||
hands_use_check = TRUE
|
||||
|
||||
/datum/emote/living/carbon/blink
|
||||
key = "blink"
|
||||
key_third_person = "blinks"
|
||||
message = "blinks."
|
||||
|
||||
/datum/emote/living/carbon/blink_r
|
||||
key = "blink_r"
|
||||
name = "blink (Rapid)"
|
||||
message = "blinks rapidly."
|
||||
|
||||
/datum/emote/living/carbon/clap
|
||||
key = "clap"
|
||||
key_third_person = "claps"
|
||||
|
||||
@@ -171,6 +171,41 @@
|
||||
key_third_person = "clears throat"
|
||||
message = "clears their throat."
|
||||
|
||||
/datum/emote/living/carbon/human/blink
|
||||
key = "blink"
|
||||
key_third_person = "blinks"
|
||||
message = "blinks."
|
||||
|
||||
/datum/emote/living/carbon/human/blink/can_run_emote(mob/living/carbon/human/user, status_check, intentional, params)
|
||||
if (!ishuman(user) || HAS_TRAIT(user, TRAIT_PREVENT_BLINKING) || HAS_TRAIT(user, TRAIT_NO_EYELIDS))
|
||||
return FALSE
|
||||
var/obj/item/organ/eyes/eyes = user.get_organ_slot(ORGAN_SLOT_EYES)
|
||||
if (!eyes)
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/datum/emote/living/carbon/human/blink/run_emote(mob/living/carbon/human/user, params, type_override, intentional)
|
||||
. = ..()
|
||||
user.update_body_parts_head_only() // Refreshing instantly makes the user blink
|
||||
|
||||
/datum/emote/living/carbon/human/blink_r
|
||||
key = "blink_r"
|
||||
name = "blink (Rapid)"
|
||||
message = "blinks rapidly."
|
||||
|
||||
/datum/emote/living/carbon/human/blink_r/can_run_emote(mob/living/carbon/human/user, status_check, intentional, params)
|
||||
if (!ishuman(user) || HAS_TRAIT(user, TRAIT_PREVENT_BLINKING) || HAS_TRAIT(user, TRAIT_NO_EYELIDS))
|
||||
return FALSE
|
||||
var/obj/item/organ/eyes/eyes = user.get_organ_slot(ORGAN_SLOT_EYES)
|
||||
if (!eyes)
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/datum/emote/living/carbon/human/blink_r/run_emote(mob/user, params, type_override, intentional)
|
||||
. = ..()
|
||||
for (var/i in 1 to 3)
|
||||
addtimer(CALLBACK(user, TYPE_PROC_REF(/mob/living/carbon/human, update_body_parts_head_only)), i * 0.3 SECONDS)
|
||||
|
||||
///Snowflake emotes only for le epic chimp
|
||||
/datum/emote/living/carbon/human/monkey
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
/obj/item/organ/tail/lizard = "Smooth",
|
||||
)
|
||||
mutanttongue = /obj/item/organ/tongue/lizard
|
||||
mutanteyes = /obj/item/organ/eyes/lizard
|
||||
coldmod = 1.5
|
||||
heatmod = 0.67
|
||||
payday_modifier = 1.0
|
||||
|
||||
@@ -93,6 +93,7 @@
|
||||
name = "burning red eyes"
|
||||
desc = "Even without their shadowy owner, looking at these eyes gives you a sense of dread."
|
||||
icon = 'icons/obj/medical/organs/shadow_organs.dmi'
|
||||
iris_overlays = FALSE
|
||||
color_cutoffs = list(20, 10, 40)
|
||||
pepperspray_protect = TRUE
|
||||
flash_protect = FLASH_PROTECTION_SENSITIVE
|
||||
|
||||
@@ -41,8 +41,8 @@
|
||||
|
||||
target.visible_message(span_danger("[user] tries to squirt something into [target]'s eyes, but fails!"), \
|
||||
span_userdanger("[user] tries to squirt something into your eyes, but fails!"))
|
||||
|
||||
to_chat(user, span_notice("You transfer [trans] unit\s of the solution."))
|
||||
if(trans)
|
||||
to_chat(user, span_notice("You transfer [trans] unit\s of the solution."))
|
||||
update_appearance()
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
else if(isalien(target)) //hiss-hiss has no eyes!
|
||||
@@ -52,6 +52,7 @@
|
||||
target.visible_message(span_danger("[user] squirts something into [target]'s eyes!"), \
|
||||
span_userdanger("[user] squirts something into your eyes!"))
|
||||
|
||||
SEND_SIGNAL(target, COMSIG_MOB_REAGENTS_DROPPED_INTO_EYES, user, src, reagents, fraction)
|
||||
reagents.expose(target, TOUCH, fraction)
|
||||
var/mob/M = target
|
||||
var/R
|
||||
|
||||
@@ -40,6 +40,15 @@
|
||||
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_icon_state = "eyes"
|
||||
/// Do these eyes have blinking animations
|
||||
var/blink_animation = TRUE
|
||||
/// Do these eyes have iris overlays
|
||||
var/iris_overlays = TRUE
|
||||
/// Should our blinking be synchronized or can separate eyes have (slightly) separate blinking times
|
||||
var/synchronized_blinking = TRUE
|
||||
// A pair of abstract eyelid objects (yes, really) used to animate blinking
|
||||
var/obj/effect/abstract/eyelid_effect/eyelid_left
|
||||
var/obj/effect/abstract/eyelid_effect/eyelid_right
|
||||
|
||||
/// Glasses cannot be worn over these eyes. Currently unused
|
||||
var/no_glasses = FALSE
|
||||
@@ -50,6 +59,17 @@
|
||||
/// Scarring on this organ
|
||||
var/scarring = NONE
|
||||
|
||||
/obj/item/organ/eyes/Initialize(mapload)
|
||||
. = ..()
|
||||
if (blink_animation)
|
||||
eyelid_left = new(src, "[eye_icon_state]_l")
|
||||
eyelid_right = new(src, "[eye_icon_state]_r")
|
||||
|
||||
/obj/item/organ/eyes/Destroy()
|
||||
QDEL_NULL(eyelid_left)
|
||||
QDEL_NULL(eyelid_right)
|
||||
return ..()
|
||||
|
||||
/obj/item/organ/eyes/on_mob_insert(mob/living/carbon/receiver, special, movement_flags)
|
||||
. = ..()
|
||||
receiver.cure_blind(NO_EYES)
|
||||
@@ -226,8 +246,8 @@
|
||||
if(isnull(eye_icon_state))
|
||||
return list()
|
||||
|
||||
var/mutable_appearance/eye_left = mutable_appearance('icons/mob/human/human_face.dmi', "[eye_icon_state]_l", -BODY_LAYER)
|
||||
var/mutable_appearance/eye_right = mutable_appearance('icons/mob/human/human_face.dmi', "[eye_icon_state]_r", -BODY_LAYER)
|
||||
var/mutable_appearance/eye_left = mutable_appearance('icons/mob/human/human_face.dmi', "[eye_icon_state]_l", -BODY_LAYER, parent)
|
||||
var/mutable_appearance/eye_right = mutable_appearance('icons/mob/human/human_face.dmi', "[eye_icon_state]_r", -BODY_LAYER, parent)
|
||||
var/list/overlays = list(eye_left, eye_right)
|
||||
|
||||
var/obscured = parent.check_obscured_slots(TRUE)
|
||||
@@ -241,18 +261,11 @@
|
||||
return overlays
|
||||
|
||||
if(my_head.head_flags & HEAD_EYECOLOR)
|
||||
if(IS_ROBOTIC_ORGAN(src) || !my_head.draw_color || (parent.appears_alive() && !HAS_TRAIT(parent, TRAIT_KNOCKEDOUT)))
|
||||
// show the eyes as open
|
||||
eye_right.color = parent.get_right_eye_color()
|
||||
eye_left.color = parent.get_left_eye_color()
|
||||
else
|
||||
// show the eyes as closed, and as such color them like eyelids wound be colored
|
||||
var/list/base_color = rgb2num(my_head.draw_color, COLORSPACE_HSL)
|
||||
base_color[2] *= 0.85
|
||||
base_color[3] *= 0.85
|
||||
var/eyelid_color = rgb(base_color[1], base_color[2], base_color[3], (length(base_color) >= 4 ? base_color[4] : null), COLORSPACE_HSL)
|
||||
eye_right.color = eyelid_color
|
||||
eye_left.color = eyelid_color
|
||||
eye_right.color = parent.get_right_eye_color()
|
||||
eye_left.color = parent.get_left_eye_color()
|
||||
var/list/eyelids = setup_eyelids(eye_left, eye_right, parent)
|
||||
if (LAZYLEN(eyelids))
|
||||
overlays += eyelids
|
||||
|
||||
if (scarring & RIGHT_EYE_SCAR)
|
||||
var/mutable_appearance/right_scar = mutable_appearance('icons/mob/human/human_face.dmi', "eye_scar_right", -BODY_LAYER)
|
||||
@@ -276,6 +289,18 @@
|
||||
. += mutable_appearance('icons/obj/medical/organs/organs.dmi', "eye_scar_right")
|
||||
if (scarring & LEFT_EYE_SCAR)
|
||||
. += mutable_appearance('icons/obj/medical/organs/organs.dmi', "eye_scar_left")
|
||||
if (iris_overlays && eye_color_left && eye_color_right)
|
||||
var/mutable_appearance/left_iris = mutable_appearance(icon, "[icon_state]_iris_l")
|
||||
var/mutable_appearance/right_iris = mutable_appearance(icon, "[icon_state]_iris_r")
|
||||
var/list/color_left = rgb2num(eye_color_left, COLORSPACE_HSL)
|
||||
var/list/color_right = rgb2num(eye_color_right, COLORSPACE_HSL)
|
||||
// Ugly as sin? Indeed it is! But otherwise eyeballs turn out to be super dark, and this way even lighter colors are mostly preserved
|
||||
color_left[3] /= sqrt(color_left[3] * 0.01)
|
||||
color_right[3] /= sqrt(color_right[3] * 0.01)
|
||||
left_iris.color = rgb(color_left[1], color_left[2], color_left[3], space = COLORSPACE_HSL)
|
||||
right_iris.color = rgb(color_right[1], color_right[2], color_right[3], space = COLORSPACE_HSL)
|
||||
. += left_iris
|
||||
. += right_iris
|
||||
|
||||
/obj/item/organ/eyes/proc/apply_scar(side)
|
||||
if (scarring & side)
|
||||
@@ -368,6 +393,92 @@
|
||||
|
||||
damaged = TRUE
|
||||
|
||||
#define BASE_BLINKING_DELAY 5 SECONDS
|
||||
#define RAND_BLINKING_DELAY 1 SECONDS
|
||||
#define BLINK_DURATION 0.15 SECONDS
|
||||
#define BLINK_LOOPS 5
|
||||
#define ASYNC_BLINKING_BRAIN_DAMAGE 60
|
||||
|
||||
/// Modifies eye overlays to also act as eyelids, both for blinking and for when you're knocked out cold
|
||||
/obj/item/organ/eyes/proc/setup_eyelids(mutable_appearance/eye_left, mutable_appearance/eye_right, mob/living/carbon/human/parent)
|
||||
var/obj/item/bodypart/head/my_head = parent.get_bodypart(BODY_ZONE_HEAD)
|
||||
// Robotic eyes or colorless heads don't get the privelege of having eyelids
|
||||
if (IS_ROBOTIC_ORGAN(src) || !my_head.draw_color || HAS_TRAIT(parent, TRAIT_NO_EYELIDS))
|
||||
return
|
||||
|
||||
var/list/base_color = rgb2num(my_head.draw_color, COLORSPACE_HSL)
|
||||
base_color[2] *= 0.85
|
||||
base_color[3] *= 0.85
|
||||
var/eyelid_color = rgb(base_color[1], base_color[2], base_color[3], (length(base_color) >= 4 ? base_color[4] : null), COLORSPACE_HSL)
|
||||
// If we're knocked out, just color the eyes
|
||||
if (!parent.appears_alive() || HAS_TRAIT(parent, TRAIT_KNOCKEDOUT))
|
||||
eye_right.color = eyelid_color
|
||||
eye_left.color = eyelid_color
|
||||
return
|
||||
|
||||
if (!blink_animation || HAS_TRAIT(parent, TRAIT_PREVENT_BLINKING))
|
||||
return
|
||||
|
||||
eyelid_left.color = eyelid_color
|
||||
eyelid_right.color = eyelid_color
|
||||
eyelid_left.render_target = "*[REF(parent)]_eyelid_left"
|
||||
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)
|
||||
|
||||
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"
|
||||
right_eyelid_overlay.render_source = "*[REF(parent)]_eyelid_right"
|
||||
return list(left_eyelid_overlay, right_eyelid_overlay)
|
||||
|
||||
/// Animates one eyelid at a time, thanks BYOND and thanks animation chains
|
||||
/obj/item/organ/eyes/proc/animate_eyelid(obj/effect/abstract/eyelid_effect/eyelid, mob/living/carbon/human/parent, sync_blinking = TRUE, list/anim_times = null)
|
||||
. = 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)
|
||||
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])
|
||||
. += wait_time
|
||||
if (anim_times && !sync_blinking)
|
||||
// Make sure that we're somewhat in sync with the other eye
|
||||
animate(time = anim_times[1] - wait_time)
|
||||
anim_times.Cut(1, 2)
|
||||
animate(alpha = 255, time = 0)
|
||||
animate(time = BLINK_DURATION)
|
||||
animate(alpha = 0, time = 0)
|
||||
animate(time = wait_time)
|
||||
|
||||
/obj/effect/abstract/eyelid_effect
|
||||
name = "eyelid"
|
||||
icon = 'icons/mob/human/human_face.dmi'
|
||||
layer = -BODY_LAYER
|
||||
vis_flags = VIS_INHERIT_DIR | VIS_INHERIT_PLANE | VIS_INHERIT_ID
|
||||
|
||||
/obj/effect/abstract/eyelid_effect/Initialize(mapload, new_state)
|
||||
. = ..()
|
||||
icon_state = new_state
|
||||
|
||||
#undef BASE_BLINKING_DELAY
|
||||
#undef RAND_BLINKING_DELAY
|
||||
#undef BLINK_DURATION
|
||||
#undef BLINK_LOOPS
|
||||
#undef ASYNC_BLINKING_BRAIN_DAMAGE
|
||||
|
||||
#define NIGHTVISION_LIGHT_OFF 0
|
||||
#define NIGHTVISION_LIGHT_LOW 1
|
||||
#define NIGHTVISION_LIGHT_MID 2
|
||||
@@ -434,9 +545,11 @@
|
||||
|
||||
/obj/item/organ/eyes/golem
|
||||
name = "resonating crystal"
|
||||
desc = "Golems somehow measure external light levels and detect nearby ore using this sensitive mineral lattice."
|
||||
icon_state = "adamantine_cords"
|
||||
eye_icon_state = null
|
||||
desc = "Golems somehow measure external light levels and detect nearby ore using this sensitive mineral lattice."
|
||||
blink_animation = FALSE
|
||||
iris_overlays = FALSE
|
||||
color = COLOR_GOLEM_GRAY
|
||||
visual = FALSE
|
||||
organ_flags = ORGAN_MINERAL
|
||||
@@ -460,8 +573,9 @@
|
||||
|
||||
/obj/item/organ/eyes/robotic
|
||||
name = "robotic eyes"
|
||||
icon_state = "cybernetic_eyeballs"
|
||||
desc = "Your vision is augmented."
|
||||
icon_state = "cybernetic_eyeballs"
|
||||
iris_overlays = FALSE
|
||||
organ_flags = ORGAN_ROBOTIC
|
||||
failing_desc = "seems to be broken."
|
||||
|
||||
@@ -825,59 +939,77 @@
|
||||
/obj/item/organ/eyes/moth
|
||||
name = "moth eyes"
|
||||
desc = "These eyes seem to have increased sensitivity to bright light, with no improvement to low light vision."
|
||||
eye_icon_state = "motheyes"
|
||||
icon_state = "eyeballs-moth"
|
||||
eye_icon_state = "motheyes"
|
||||
blink_animation = FALSE
|
||||
iris_overlays = FALSE
|
||||
flash_protect = FLASH_PROTECTION_SENSITIVE
|
||||
|
||||
/obj/item/organ/eyes/robotic/moth
|
||||
name = "robotic moth eyes"
|
||||
eye_icon_state = "motheyes"
|
||||
icon_state = "eyeballs-cybermoth"
|
||||
desc = "Your vision is augmented. Much like actual moth eyes, very sensitive to bright lights."
|
||||
icon_state = "eyeballs-cybermoth"
|
||||
eye_icon_state = "motheyes"
|
||||
blink_animation = FALSE
|
||||
flash_protect = FLASH_PROTECTION_SENSITIVE
|
||||
|
||||
/obj/item/organ/eyes/robotic/basic/moth
|
||||
name = "basic robotic moth eyes"
|
||||
eye_icon_state = "motheyes"
|
||||
icon_state = "eyeballs-cybermoth"
|
||||
eye_icon_state = "motheyes"
|
||||
blink_animation = FALSE
|
||||
flash_protect = FLASH_PROTECTION_SENSITIVE
|
||||
|
||||
/obj/item/organ/eyes/robotic/xray/moth
|
||||
name = "moth x-ray eyes"
|
||||
eye_icon_state = "motheyes"
|
||||
icon_state = "eyeballs-cybermoth"
|
||||
desc = "These cybernetic imitation moth eyes will give you X-ray vision. Blinking is futile. Much like actual moth eyes, very sensitive to bright lights."
|
||||
icon_state = "eyeballs-cybermoth"
|
||||
eye_icon_state = "motheyes"
|
||||
blink_animation = FALSE
|
||||
flash_protect = FLASH_PROTECTION_SENSITIVE
|
||||
|
||||
/obj/item/organ/eyes/robotic/shield/moth
|
||||
name = "shielded robotic moth eyes"
|
||||
eye_icon_state = "motheyes"
|
||||
icon_state = "eyeballs-cybermoth"
|
||||
eye_icon_state = "motheyes"
|
||||
blink_animation = FALSE
|
||||
|
||||
/obj/item/organ/eyes/robotic/glow/moth
|
||||
name = "high luminosity moth eyes"
|
||||
eye_icon_state = "motheyes"
|
||||
base_eye_state = "eyes_mothglow"
|
||||
icon_state = "eyeballs-cybermoth"
|
||||
desc = "Special glowing eyes, to be one with the lamp. Much like actual moth eyes, very sensitive to bright lights."
|
||||
icon_state = "eyeballs-cybermoth"
|
||||
eye_icon_state = "motheyes"
|
||||
blink_animation = FALSE
|
||||
base_eye_state = "eyes_mothglow"
|
||||
flash_protect = FLASH_PROTECTION_SENSITIVE
|
||||
|
||||
/obj/item/organ/eyes/robotic/thermals/moth //we inherit flash weakness from thermals
|
||||
name = "thermal moth eyes"
|
||||
eye_icon_state = "motheyes"
|
||||
icon_state = "eyeballs-cybermoth"
|
||||
eye_icon_state = "motheyes"
|
||||
blink_animation = FALSE
|
||||
|
||||
/obj/item/organ/eyes/snail
|
||||
name = "snail eyes"
|
||||
desc = "These eyes seem to have a large range, but might be cumbersome with glasses."
|
||||
eye_icon_state = "snail_eyes"
|
||||
icon_state = "snail_eyeballs"
|
||||
eye_icon_state = "snail_eyes"
|
||||
blink_animation = FALSE
|
||||
iris_overlays = FALSE
|
||||
|
||||
/obj/item/organ/eyes/jelly
|
||||
name = "jelly eyes"
|
||||
desc = "These eyes are made of a soft jelly. Unlike all other eyes, though, there are three of them."
|
||||
eye_icon_state = "jelleyes"
|
||||
icon_state = "eyeballs-jelly"
|
||||
eye_icon_state = "jelleyes"
|
||||
blink_animation = FALSE
|
||||
iris_overlays = FALSE
|
||||
|
||||
/obj/item/organ/eyes/lizard
|
||||
name = "reptile eyes"
|
||||
desc = "A pair of reptile eyes with thin vertical slits for pupils."
|
||||
icon_state = "lizard_eyes"
|
||||
synchronized_blinking = FALSE
|
||||
|
||||
/obj/item/organ/eyes/night_vision/maintenance_adapted
|
||||
name = "adapted eyes"
|
||||
@@ -887,6 +1019,7 @@
|
||||
eye_color_right = "f00"
|
||||
icon_state = "adapted_eyes"
|
||||
eye_icon_state = "eyes_glow"
|
||||
iris_overlays = FALSE
|
||||
overlay_ignore_lighting = TRUE
|
||||
low_light_cutoff = list(5, 12, 20)
|
||||
medium_light_cutoff = list(15, 20, 30)
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
@@ -1773,6 +1773,7 @@
|
||||
#include "code\datums\quirks\negative_quirks\deafness.dm"
|
||||
#include "code\datums\quirks\negative_quirks\depression.dm"
|
||||
#include "code\datums\quirks\negative_quirks\family_heirloom.dm"
|
||||
#include "code\datums\quirks\negative_quirks\fluoride_stare.dm"
|
||||
#include "code\datums\quirks\negative_quirks\food_allergy.dm"
|
||||
#include "code\datums\quirks\negative_quirks\frail.dm"
|
||||
#include "code\datums\quirks\negative_quirks\glass_jaw.dm"
|
||||
|
||||
Reference in New Issue
Block a user