Eye wounds, scars and a new ~Pirate~ RP quirk (#87209)

## About The Pull Request

Upon getting stabbed in your eyes or having a bullet fly through your
head there's a chance (minor for stabbing, extremely low for headshots)
you'll receive a new "Eye Puncture" wound which causes profuse bleeding
out of your now-empty eye hole. Once healed you'll have to deal with a
scar on your eye which cannot be cured and requires surgical
replacement. Eye scarring will reduce your eyes' max health by 15, give
you a minor screen tint and a fancy visual on your character sprite.
Getting scarring on both eyes will turn you completely blind.


![image](https://github.com/user-attachments/assets/c1ae4ff3-6844-405d-819b-9c390511e321)

This PR also introduces a new quirk which gives you eye scarring on the
eye of your choice and an eyepatch to go alongside it, just make sure
that it sits on the right eye.

Also added medical(white) subtype of eyepatches to loadout for those who
want that version instead. Credits to AnturK on discord for the idea.

## Why It's Good For The Game

Its a neat lil' feature that makes the game more immersive, and unlocks
more roleplay opportunities for players. New quirk gives access to this
feature for players who want to make it a part of their character's
backstory (or maybe as a part of permanent scar roleplaying).

## Changelog
🆑
add: Getting stabbed or shot in the eyes has a chance of giving you a
new wound and a semi-permanent scar, blinding you on one side
add: Added new "Scarred Eye" quirk which blinds you on one eye but gives
you a fancy eyepatch
add: Medical eyepatches have been added to loadout
/🆑

---------

Co-authored-by: Time-Green <7501474+Time-Green@users.noreply.github.com>
This commit is contained in:
SmArtKar
2024-10-19 13:39:19 +02:00
committed by GitHub
co-authored by Time-Green
parent 490e8f9e7b
commit df00d85356
27 changed files with 366 additions and 38 deletions
@@ -39,6 +39,9 @@
/// Called from bodypart changing owner, which could be on attach or detachment. Either argument can be null. (mob/living/carbon/new_owner, mob/living/carbon/old_owner)
#define COMSIG_BODYPART_CHANGED_OWNER "bodypart_changed_owner"
/// Called from /obj/item/bodypart/proc/update_part_wound_overlay()
#define COMSIG_BODYPART_UPDATE_WOUND_OVERLAY "bodypart_update_wound_overlay"
#define COMPONENT_PREVENT_WOUND_OVERLAY_UPDATE (1 << 0)
/// Called from update_health_hud, whenever a bodypart is being updated on the health doll
#define COMSIG_BODYPART_UPDATING_HEALTH_HUD "bodypart_updating_health_hud"
+5
View File
@@ -31,6 +31,11 @@
/// An organ that is ostensibly dangerous when inside a body
#define ORGAN_HAZARDOUS (1<<12)
/// Scarring on the right eye
#define RIGHT_EYE_SCAR (1<<0)
/// Scarring on the left eye
#define LEFT_EYE_SCAR (1<<1)
/// Helper to figure out if a limb is organic
#define IS_ORGANIC_LIMB(limb) (limb.bodytype & BODYTYPE_ORGANIC)
/// Helper to figure out if a limb is robotic
+3
View File
@@ -501,6 +501,9 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
#define TRAIT_USER_SCOPED "user_scoped"
/// Mob is unable to feel pain
#define TRAIT_ANALGESIA "analgesia"
/// Mob has a scar on their left/right eye
#define TRAIT_RIGHT_EYE_SCAR "right_eye_scar"
#define TRAIT_LEFT_EYE_SCAR "left_eye_scar"
/// Trait added when a revenant is visible.
#define TRAIT_REVENANT_REVEALED "revenant_revealed"
+1
View File
@@ -231,6 +231,7 @@
#define SPEED_TRAIT "speed_trait"
/// Trait given to mobs that have been autopsied
#define AUTOPSY_TRAIT "autopsy_trait"
#define EYE_SCARRING_TRAIT "eye_scarring_trait"
///From the market_crash event
#define MARKET_CRASH_EVENT_TRAIT "crashed_market_event"
+5
View File
@@ -25,6 +25,11 @@
/// outright dismemberment of limb
#define WOUND_SEVERITY_LOSS 4
// how much blood the limb needs to be losing per tick (not counting laying down/self grasping modifiers) to get the different bleed icons
#define BLEED_OVERLAY_LOW 0.5
#define BLEED_OVERLAY_MED 1.5
#define BLEED_OVERLAY_GUSH 3.25
/// A "chronological" list of wound severities, starting at the least severe.
GLOBAL_LIST_INIT(wound_severities_chronological, list(
"[WOUND_SEVERITY_TRIVIAL]",
+8
View File
@@ -99,6 +99,14 @@ GLOBAL_LIST_INIT(paraplegic_choice, list(
"Amputee" = TRUE,
))
///Scarred Eye Quirk
GLOBAL_LIST_INIT(scarred_eye_choice, list(
"Random",
"Left Eye",
"Right Eye",
"Double",
))
///chipped Quirk
GLOBAL_LIST_INIT(quirk_chipped_choice, list(
"Basketsoft 3000" = /obj/item/skillchip/basketweaving,
+2
View File
@@ -563,6 +563,8 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_MINING_PARRYING" = TRAIT_MINING_PARRYING,
"TRAIT_ILLUSORY_EFFECT" = TRAIT_ILLUSORY_EFFECT,
"TRAIT_IGNORE_FIRE_PROTECTION" = TRAIT_IGNORE_FIRE_PROTECTION,
"TRAIT_LEFT_EYE_SCAR" = TRAIT_LEFT_EYE_SCAR,
"TRAIT_RIGHT_EYE_SCAR" = TRAIT_RIGHT_EYE_SCAR,
),
/obj/item = list(
"TRAIT_APC_SHOCKING" = TRAIT_APC_SHOCKING,
+2
View File
@@ -326,6 +326,8 @@ GLOBAL_LIST_INIT(admin_visible_traits, list(
"TRAIT_XRAY_VISION" = TRAIT_XRAY_VISION,
"TRAIT_MINING_PARRYING" = TRAIT_MINING_PARRYING,
"TRAIT_IGNORE_FIRE_PROTECTION" = TRAIT_IGNORE_FIRE_PROTECTION,
"TRAIT_LEFT_EYE_SCAR" = TRAIT_LEFT_EYE_SCAR,
"TRAIT_RIGHT_EYE_SCAR" = TRAIT_RIGHT_EYE_SCAR,
),
/obj/item = list(
"TRAIT_APC_SHOCKING" = TRAIT_APC_SHOCKING,
@@ -4,7 +4,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),
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/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),
+25 -3
View File
@@ -2,6 +2,8 @@
#define CLUMSY_ATTACK_SELF_CHANCE 50
/// The damage threshold (of the victim's eyes) after which they start taking more serious effects
#define EYESTAB_BLEEDING_THRESHOLD 10
/// The damage threshold (of the victim's eyes) after which they can go blind
#define EYESTAB_BLINDING_THRESHOLD 30
/// How much blur we can apply
#define EYESTAB_MAX_BLUR (4 MINUTES)
@@ -80,13 +82,14 @@
return
target.adjust_eye_blur_up_to(6 SECONDS, EYESTAB_MAX_BLUR)
var/started_bleeding = eyes.damage < EYESTAB_BLEEDING_THRESHOLD
eyes.apply_organ_damage(rand(2, 4))
if(eyes.damage < EYESTAB_BLEEDING_THRESHOLD)
return
// At over 10 damage we apply a lot of eye blur
target.adjust_eye_blur_up_to(30 SECONDS, EYESTAB_MAX_BLUR)
if (target.stat != DEAD)
if (target.stat != DEAD && started_bleeding)
to_chat(target, span_danger("Your eyes start to bleed profusely!"))
// At over 10 damage, we cause at least enough eye damage to force nearsightedness
@@ -102,8 +105,26 @@
target.Unconscious(2 SECONDS)
target.Paralyze(4 SECONDS)
// At over 10 damage, there is a chance (based on eye damage) of going blind
if (prob(eyes.damage - eyes.low_threshold + 1))
// A solid chance of getting a permanent scar over one of your eyes, if you have at least one unscarred eyeball
if (prob(eyes.damage - EYESTAB_BLEEDING_THRESHOLD + 1))
var/valid_sides = list()
if (!(eyes.scarring & RIGHT_EYE_SCAR))
valid_sides += RIGHT_EYE_SCAR
if (!(eyes.scarring & LEFT_EYE_SCAR))
valid_sides += LEFT_EYE_SCAR
if (length(valid_sides))
var/picked_side = pick(valid_sides)
to_chat(target, span_userdanger("You feel searing pain shoot though your [picked_side == RIGHT_EYE_SCAR ? "right" : "left"] eye!"))
// oof ouch my eyes
var/datum/wound/pierce/bleed/severe/eye/eye_puncture = new
eye_puncture.apply_wound(eyes.bodypart_owner, wound_source = "eye stab", right_side = picked_side)
eyes.apply_scar(picked_side)
if (eyes.damage < EYESTAB_BLINDING_THRESHOLD)
return
// At over 30 damage, there is a chance (based on eye damage) of going blind
if (prob(eyes.damage - EYESTAB_BLINDING_THRESHOLD + 1))
if (!target.is_blind_from(EYE_DAMAGE))
eyes.set_organ_damage(eyes.maxHealth)
// Also cause some temp blindness, so that they're still blind even if they get healed
@@ -111,4 +132,5 @@
#undef CLUMSY_ATTACK_SELF_CHANCE
#undef EYESTAB_BLEEDING_THRESHOLD
#undef EYESTAB_BLINDING_THRESHOLD
#undef EYESTAB_MAX_BLUR
@@ -1,7 +1,7 @@
/datum/quirk/item_quirk/blindness
name = "Blind"
desc = "You are completely blind, nothing can counteract this."
icon = FA_ICON_EYE_SLASH
icon = FA_ICON_BLIND
value = -16
gain_text = span_danger("You can't see anything.")
lose_text = span_notice("You miraculously gain back your vision.")
@@ -0,0 +1,63 @@
/datum/quirk/item_quirk/scarred_eye
name = "Scarred Eye"
desc = "An accident in your past has cost you one of your eyes, but you got a cool eyepatch. Yarr!"
icon = FA_ICON_EYE_SLASH
value = -2
gain_text = span_danger("After all this time, your eye still stings a bit...")
lose_text = span_notice("Your peripherial vision grows by about thirty percent.")
medical_record_text = "Patient has severe scarring on one of their eyes, resulting in partial vision loss."
hardcore_value = 2
quirk_flags = QUIRK_HUMAN_ONLY|QUIRK_CHANGES_APPEARANCE
mail_goodies = list(/obj/item/reagent_containers/cup/glass/bottle/rum, /obj/item/clothing/mask/bandana/red)
/datum/quirk_constant_data/eye_scarring
associated_typepath = /datum/quirk/item_quirk/scarred_eye
customization_options = list(/datum/preference/choiced/scarred_eye)
/datum/quirk/item_quirk/scarred_eye/add_unique(client/client_source)
if (client_source?.prefs.read_preference(/datum/preference/choiced/scarred_eye) == "Double")
give_item_to_holder(new /obj/item/clothing/glasses/blindfold/white(get_turf(quirk_holder)), list(
LOCATION_EYES = ITEM_SLOT_EYES,
LOCATION_BACKPACK = ITEM_SLOT_BACKPACK,
LOCATION_HANDS = ITEM_SLOT_HANDS,
))
return
var/mob/living/carbon/human/human_holder = quirk_holder
var/obj/item/clothing/glasses/eyepatch/eyepatch = new(get_turf(quirk_holder))
if (human_holder.get_eye_scars() & LEFT_EYE_SCAR)
eyepatch.flip_eyepatch()
give_item_to_holder(eyepatch, list(
LOCATION_EYES = ITEM_SLOT_EYES,
LOCATION_BACKPACK = ITEM_SLOT_BACKPACK,
LOCATION_HANDS = ITEM_SLOT_HANDS,
))
/datum/quirk/item_quirk/scarred_eye/add(client/client_source)
var/mob/living/carbon/human/human_owner = quirk_holder
var/obj/item/organ/internal/eyes/eyes = human_owner.get_organ_slot(ORGAN_SLOT_EYES)
if (isnull(eyes))
return
var/eye_side = client_source?.prefs.read_preference(/datum/preference/choiced/scarred_eye) || "Random"
if (eye_side == "Double")
eyes.apply_scar(RIGHT_EYE_SCAR)
eyes.apply_scar(LEFT_EYE_SCAR)
return
switch (eye_side)
if ("Random")
eye_side = pick(RIGHT_EYE_SCAR, LEFT_EYE_SCAR)
if ("Right Eye")
eye_side = RIGHT_EYE_SCAR
if ("Left Eye")
eye_side = LEFT_EYE_SCAR
eyes.apply_scar(eye_side)
/datum/quirk/item_quirk/scarred_eye/remove()
var/mob/living/carbon/human/human_owner = quirk_holder
var/obj/item/organ/internal/eyes/eyes = human_owner.get_organ_slot(ORGAN_SLOT_EYES)
if (!isnull(eyes))
eyes.fix_scar(RIGHT_EYE_SCAR)
eyes.fix_scar(LEFT_EYE_SCAR)
@@ -13,7 +13,7 @@
/// Static list of signals that, when received, we force an update to our nearsighted overlay
var/static/list/update_signals = list(SIGNAL_ADDTRAIT(TRAIT_NEARSIGHTED_CORRECTED), SIGNAL_REMOVETRAIT(TRAIT_NEARSIGHTED_CORRECTED))
/// How severe is our nearsightedness right now
var/overlay_severity = 1
var/overlay_severity = 2
/datum/status_effect/grouped/nearsighted/on_apply()
RegisterSignals(owner, update_signals, PROC_REF(update_nearsightedness))
@@ -33,6 +33,10 @@
/// Checks if we should be nearsighted currently, or if we should clear the overlay
/datum/status_effect/grouped/nearsighted/proc/should_be_nearsighted()
if (ishuman(owner))
var/mob/living/carbon/human/human_owner = owner
if (human_owner.get_eye_scars())
return TRUE
return !HAS_TRAIT(owner, TRAIT_NEARSIGHTED_CORRECTED)
/// Updates our nearsightd overlay, either removing it if we have the trait or adding it if we don't
+43
View File
@@ -256,6 +256,49 @@
if(!limb.can_bleed())
occur_text = "tears a hole open"
/datum/wound/pierce/bleed/severe/eye
name = "Eyeball Puncture"
desc = "Patient's eye has sustained extreme damage, causing severe bleeding from the ocular cavity."
occur_text = "looses a violent spray of blood, revealing a crushed eyeball"
var/right_side = FALSE
/datum/wound/pierce/bleed/severe/eye/apply_wound(obj/item/bodypart/limb, silent, datum/wound/old_wound, smited, attack_direction, wound_source, replacing, right_side)
var/obj/item/organ/internal/eyes/eyes = locate() in limb
if (!istype(eyes))
return FALSE
. = ..()
src.right_side = right_side
examine_desc = "has its [right_side ? "right" : "left"] eye pierced clean through, blood spewing from the cavity"
RegisterSignal(limb, COMSIG_BODYPART_UPDATE_WOUND_OVERLAY, PROC_REF(wound_overlay))
limb.update_part_wound_overlay()
/datum/wound/pierce/bleed/severe/eye/remove_wound(ignore_limb, replaced)
if (!isnull(limb))
UnregisterSignal(limb, COMSIG_BODYPART_UPDATE_WOUND_OVERLAY)
return ..()
/datum/wound/pierce/bleed/severe/eye/proc/wound_overlay(obj/item/bodypart/source, limb_bleed_rate)
SIGNAL_HANDLER
if (limb_bleed_rate <= BLEED_OVERLAY_LOW || limb_bleed_rate > BLEED_OVERLAY_GUSH)
return
if (blood_flow <= BLEED_OVERLAY_LOW)
return
source.bleed_overlay_icon = right_side ? "r_eye" : "l_eye"
return COMPONENT_PREVENT_WOUND_OVERLAY_UPDATE
/datum/wound_pregen_data/flesh_pierce/open_puncture/eye
wound_path_to_generate = /datum/wound/pierce/bleed/severe/eye
viable_zones = list(BODY_ZONE_HEAD)
can_be_randomly_generated = FALSE
/datum/wound_pregen_data/flesh_pierce/open_puncture/eye/can_be_applied_to(obj/item/bodypart/limb, list/suggested_wounding_types, datum/wound/old_wound, random_roll, duplicates_allowed, care_about_existing_wounds)
if (isnull(locate(/obj/item/organ/internal/eyes) in limb))
return FALSE
return ..()
/datum/wound/pierce/bleed/critical
name = "Ruptured Cavity"
desc = "Patient's internal tissue and circulatory system is shredded, causing significant internal bleeding and damage to internal organs."
@@ -0,0 +1,20 @@
/datum/preference/choiced/scarred_eye
category = PREFERENCE_CATEGORY_MANUALLY_RENDERED
savefile_key = "scarred_eye"
savefile_identifier = PREFERENCE_CHARACTER
/datum/preference/choiced/scarred_eye/init_possible_values()
return GLOB.scarred_eye_choice
/datum/preference/choiced/scarred_eye/create_default_value()
return "Random"
/datum/preference/choiced/scarred_eye/is_accessible(datum/preferences/preferences)
. = ..()
if (!.)
return FALSE
return "Scarred Eye" in preferences.all_quirks
/datum/preference/choiced/scarred_eye/apply_to_human(mob/living/carbon/human/target, value)
return
+37 -2
View File
@@ -182,11 +182,46 @@
inhand_icon_state = null
actions_types = list(/datum/action/item_action/flip)
dog_fashion = /datum/dog_fashion/head/eyepatch
var/flipped = FALSE
/obj/item/clothing/glasses/eyepatch/attack_self(mob/user, modifiers)
/obj/item/clothing/glasses/eyepatch/click_alt(mob/user)
. = ..()
icon_state = (icon_state == base_icon_state) ? "[base_icon_state]_flipped" : base_icon_state
flip_eyepatch()
/obj/item/clothing/glasses/eyepatch/attack_self(mob/user)
. = ..()
flip_eyepatch()
/obj/item/clothing/glasses/eyepatch/proc/flip_eyepatch()
flipped = !flipped
icon_state = flipped ? "[base_icon_state]_flipped" : base_icon_state
if (!ismob(loc))
return
var/mob/user = loc
user.update_worn_glasses()
if (!ishuman(user))
return
var/mob/living/carbon/human/human_user = user
if (human_user.get_eye_scars() & (flipped ? RIGHT_EYE_SCAR : LEFT_EYE_SCAR))
tint = INFINITY
else
tint = initial(tint)
human_user.update_tint()
/obj/item/clothing/glasses/eyepatch/equipped(mob/living/user, slot)
if (!ishuman(user))
return ..()
var/mob/living/carbon/human/human_user = user
// lol lmao
if (human_user.get_eye_scars() & (flipped ? RIGHT_EYE_SCAR : LEFT_EYE_SCAR))
tint = INFINITY
else
tint = initial(tint)
return ..()
/obj/item/clothing/glasses/eyepatch/dropped(mob/living/user)
. = ..()
tint = initial(tint)
/obj/item/clothing/glasses/eyepatch/medical
name = "medical eyepatch"
@@ -53,3 +53,7 @@
/datum/loadout_item/glasses/eyepatch
name = "Eyepatch"
item_path = /obj/item/clothing/glasses/eyepatch
/datum/loadout_item/glasses/eyepatch/medical
name = "Medical Eyepatch"
item_path = /obj/item/clothing/glasses/eyepatch/medical
@@ -136,6 +136,11 @@
. = ..()
. += "[dna.species.type]"
/mob/living/carbon/human/proc/get_eye_scars()
var/obj/item/organ/internal/eyes/eyes = get_organ_slot(ORGAN_SLOT_EYES)
if (!isnull(eyes))
return eyes.scarring
/// When we're joining the game in [/mob/dead/new_player/proc/create_character], we increment our scar slot then store the slot in our mind datum.
/mob/living/carbon/human/proc/increment_scar_slot()
var/check_ckey = ckey || client?.ckey
+3 -9
View File
@@ -1210,11 +1210,6 @@
bleed_rate *= 0.7
return bleed_rate
// how much blood the limb needs to be losing per tick (not counting laying down/self grasping modifiers) to get the different bleed icons
#define BLEED_OVERLAY_LOW 0.5
#define BLEED_OVERLAY_MED 1.5
#define BLEED_OVERLAY_GUSH 3.25
/obj/item/bodypart/proc/update_part_wound_overlay()
if(!owner)
return FALSE
@@ -1224,6 +1219,9 @@
owner.update_wound_overlays()
return FALSE
if (SEND_SIGNAL(src, COMSIG_BODYPART_UPDATE_WOUND_OVERLAY, cached_bleed_rate) & COMPONENT_PREVENT_WOUND_OVERLAY_UPDATE)
return
var/bleed_rate = cached_bleed_rate
var/new_bleed_icon = null
@@ -1247,10 +1245,6 @@
bleed_overlay_icon = new_bleed_icon
owner.update_wound_overlays()
#undef BLEED_OVERLAY_LOW
#undef BLEED_OVERLAY_MED
#undef BLEED_OVERLAY_GUSH
/obj/item/bodypart/proc/can_bleed()
SHOULD_BE_PURE(TRUE)
@@ -51,6 +51,8 @@
var/damaged = FALSE
/// Native FOV that will be applied if a config is enabled
var/native_fov = FOV_90_DEGREES
/// Scarring on this organ
var/scarring = NONE
/obj/item/organ/internal/eyes/mob_insert(mob/living/carbon/receiver, special, movement_flags)
// If we don't do this before everything else, heterochromia will be reset leading to eye_color_right no longer being accurate
@@ -64,6 +66,7 @@
receiver.cure_blind(NO_EYES)
apply_damaged_eye_effects()
refresh(receiver, call_update = TRUE)
RegisterSignal(receiver, COMSIG_ATOM_BULLET_ACT, PROC_REF(on_bullet_act))
/// Refreshes the visuals of the eyes
/// If call_update is TRUE, we also will call update_body
@@ -117,6 +120,30 @@
organ_owner.update_tint()
organ_owner.update_sight()
UnregisterSignal(organ_owner, COMSIG_ATOM_BULLET_ACT)
/obj/item/organ/internal/eyes/proc/on_bullet_act(datum/source, obj/projectile/proj, def_zone)
SIGNAL_HANDLER
// Once-a-dozen-rounds level of rare
if (def_zone != BODY_ZONE_HEAD || !prob(proj.damage * 0.1) || !(proj.damage_type == BRUTE || proj.damage_type == BURN))
return
var/valid_sides = list()
if (!(scarring & RIGHT_EYE_SCAR))
valid_sides += RIGHT_EYE_SCAR
if (!(scarring & LEFT_EYE_SCAR))
valid_sides += LEFT_EYE_SCAR
if (!length(valid_sides))
return
var/picked_side = pick(valid_sides)
to_chat(owner, span_userdanger("You feel searing pain shoot though your [picked_side == RIGHT_EYE_SCAR ? "right" : "left"] eye!"))
// oof ouch my eyes
apply_organ_damage(rand((maxHealth - high_threshold) * 0.5, maxHealth - low_threshold))
var/datum/wound/pierce/bleed/severe/eye/eye_puncture = new
eye_puncture.apply_wound(bodypart_owner, wound_source = "bullet impact", right_side = picked_side)
apply_scar(picked_side)
#define OFFSET_X 1
#define OFFSET_Y 2
@@ -129,6 +156,8 @@
if(advanced)
if(owner.is_blind_from(QUIRK_TRAIT))
return conditional_tooltip("Subject is permanently blind.", "Irreparable under normal circumstances.", add_tooltips)
if(owner.is_blind_from(EYE_SCARRING_TRAIT))
return conditional_tooltip("Subject is blind from widespread ocular scarring.", "Surgically replace eyes, irreparable otherwise.", add_tooltips)
if(owner.is_blind_from(TRAUMA_TRAIT))
return conditional_tooltip("Subject is blind from mental trauma.", "Repair via treatment of associated trauma.", add_tooltips)
if(owner.is_blind_from(GENETIC_MUTATION))
@@ -140,6 +169,8 @@
if(advanced)
if(owner.is_nearsighted_from(QUIRK_TRAIT))
return conditional_tooltip("Subject is permanently nearsighted.", "Irreparable under normal circumstances. Prescription glasses will assuage the effects.", add_tooltips)
if(owner.is_nearsighted_from(TRAIT_RIGHT_EYE_SCAR) || owner.is_nearsighted_from(TRAIT_LEFT_EYE_SCAR))
return conditional_tooltip("Subject is nearsighted from severe ocular scarring.", "Surgically replace eyes, irreparable otherwise.", add_tooltips)
if(owner.is_nearsighted_from(GENETIC_MUTATION))
return conditional_tooltip("Subject is genetically nearsighted.", "Use medication such as [/datum/reagent/medicine/mutadone::name]. Prescription glasses will assuage the effects.", add_tooltips)
if(owner.is_nearsighted_from(EYE_DAMAGE))
@@ -167,28 +198,97 @@
if(overlay_ignore_lighting && !(obscured & ITEM_SLOT_EYES))
overlays += emissive_appearance(eye_left.icon, eye_left.icon_state, parent, -BODY_LAYER, alpha = eye_left.alpha)
overlays += emissive_appearance(eye_right.icon, eye_right.icon_state, parent, -BODY_LAYER, alpha = eye_right.alpha)
var/obj/item/bodypart/head/my_head = parent.get_bodypart(BODY_ZONE_HEAD)
if(my_head)
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 = eye_color_right
eye_left.color = eye_color_left
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
if(my_head.worn_face_offset)
my_head.worn_face_offset.apply_offset(eye_left)
my_head.worn_face_offset.apply_offset(eye_right)
var/obj/item/bodypart/head/my_head = parent.get_bodypart(BODY_ZONE_HEAD)
if(!my_head)
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 = eye_color_right
eye_left.color = eye_color_left
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
if (scarring & RIGHT_EYE_SCAR)
var/mutable_appearance/right_scar = mutable_appearance('icons/mob/human/human_face.dmi', "eye_scar_right", -BODY_LAYER)
right_scar.color = my_head.draw_color
overlays += right_scar
if (scarring & LEFT_EYE_SCAR)
var/mutable_appearance/left_scar = mutable_appearance('icons/mob/human/human_face.dmi', "eye_scar_left", -BODY_LAYER)
left_scar.color = my_head.draw_color
overlays += left_scar
if(my_head.worn_face_offset)
my_head.worn_face_offset.apply_offset(eye_left)
my_head.worn_face_offset.apply_offset(eye_right)
return overlays
/obj/item/organ/internal/eyes/update_overlays()
. = ..()
if (scarring & RIGHT_EYE_SCAR)
. += 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")
/obj/item/organ/internal/eyes/proc/apply_scar(side)
if (scarring & side)
return
scarring |= side
maxHealth -= 15
update_appearance()
apply_scarring_effects()
/obj/item/organ/internal/eyes/proc/apply_scarring_effects()
if (!owner)
return
var/datum/status_effect/grouped/nearsighted/nearsightedness = owner.is_nearsighted()
// Even if eyes have enough health, our owner still becomes nearsighted
if (scarring & RIGHT_EYE_SCAR)
owner.become_nearsighted(TRAIT_RIGHT_EYE_SCAR)
if (scarring & LEFT_EYE_SCAR)
owner.become_nearsighted(TRAIT_LEFT_EYE_SCAR)
if (isnull(nearsightedness)) // We aren't nearsighted from any other source
nearsightedness = owner.is_nearsighted()
nearsightedness.set_nearsighted_severity(1)
if ((scarring & RIGHT_EYE_SCAR) && (scarring & LEFT_EYE_SCAR))
owner.become_blind(EYE_SCARRING_TRAIT)
owner.update_body()
/obj/item/organ/internal/eyes/proc/fix_scar(side)
if (!(scarring & side))
return
scarring &= ~side
maxHealth += 15
update_appearance()
if (!owner)
return
owner.cure_nearsighted(side == RIGHT_EYE_SCAR ? TRAIT_RIGHT_EYE_SCAR : TRAIT_LEFT_EYE_SCAR)
owner.cure_blind(EYE_SCARRING_TRAIT)
owner.update_body()
/obj/item/organ/internal/eyes/on_mob_insert(mob/living/carbon/eye_owner)
. = ..()
if (scarring)
apply_scarring_effects()
/obj/item/organ/internal/eyes/on_mob_remove(mob/living/carbon/eye_owner)
. = ..()
if (scarring)
owner.cure_nearsighted(TRAIT_RIGHT_EYE_SCAR)
owner.cure_nearsighted(TRAIT_LEFT_EYE_SCAR)
owner.cure_blind(EYE_SCARRING_TRAIT)
#undef OFFSET_X
#undef OFFSET_Y
@@ -233,7 +333,7 @@
owner.become_nearsighted(EYE_DAMAGE)
// update the severity of our nearsightedness based on our eye damage
var/datum/status_effect/grouped/nearsighted/nearsightedness = owner.is_nearsighted()
nearsightedness.set_nearsighted_severity(damage > high_threshold ? 2 : 1)
nearsightedness.set_nearsighted_severity(damage > high_threshold ? 3 : 2)
damaged = TRUE
+2 -2
View File
@@ -125,7 +125,7 @@
TEST_ASSERT(dummy.is_nearsighted(), "After sustaining minor eye damage ([minor_damage]), the dummy was not nearsighted.")
// Check that the severity is correct
nearsightedness = dummy.is_nearsighted()
TEST_ASSERT_EQUAL(nearsightedness.overlay_severity, 1, "After taking minor eye damage, the dummy's nearsightedness was the incorrect severity.")
TEST_ASSERT_EQUAL(nearsightedness.overlay_severity, 2, "After taking minor eye damage, the dummy's nearsightedness was the incorrect severity.")
nearsightedness = null
// Heal eye damage
eyes.set_organ_damage(0)
@@ -137,7 +137,7 @@
TEST_ASSERT(dummy.is_nearsighted(), "After sustaining major eye damage ([major_damage]), the dummy was not nearsighted.")
// Check that the severity is correct
nearsightedness = dummy.is_nearsighted()
TEST_ASSERT_EQUAL(nearsightedness.overlay_severity, 2, "After taking major eye damage, the dummy's nearsightedness was the incorrect severity.")
TEST_ASSERT_EQUAL(nearsightedness.overlay_severity, 3, "After taking major eye damage, the dummy's nearsightedness was the incorrect severity.")
nearsightedness = null
// Heal eye damage
eyes.set_organ_damage(0)
Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 MiB

After

Width:  |  Height:  |  Size: 6.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 102 KiB

After

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 40 KiB

+2
View File
@@ -1771,6 +1771,7 @@
#include "code\datums\quirks\negative_quirks\prosthetic_organ.dm"
#include "code\datums\quirks\negative_quirks\pushover.dm"
#include "code\datums\quirks\negative_quirks\quadruple_amputee.dm"
#include "code\datums\quirks\negative_quirks\scarred_eye.dm"
#include "code\datums\quirks\negative_quirks\social_anxiety.dm"
#include "code\datums\quirks\negative_quirks\softspoken.dm"
#include "code\datums\quirks\negative_quirks\tin_man.dm"
@@ -3818,6 +3819,7 @@
#include "code\modules\client\preferences\random.dm"
#include "code\modules\client\preferences\runechat.dm"
#include "code\modules\client\preferences\scaling_method.dm"
#include "code\modules\client\preferences\scarred_eye.dm"
#include "code\modules\client\preferences\screentips.dm"
#include "code\modules\client\preferences\security_department.dm"
#include "code\modules\client\preferences\skin_tone.dm"
@@ -0,0 +1,7 @@
import { FeatureChoiced } from '../base';
import { FeatureDropdownInput } from '../dropdowns';
export const scarred_eye: FeatureChoiced = {
name: 'Scarred Eye',
component: FeatureDropdownInput,
};