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:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user