mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-13 17:14:47 +01:00
Organ damage refactor/cleanup (#93436)
## About The Pull Request So, my original goal was just a refactor for the emissive overlays of eyes, as a way to implement the specular emissive introduced by smartkar some time ago, but somehow I found myself dragged into a bigger refactor or cleanup of organ damage, thresholds, failures. One of the main problem was that there were no procs called when a organ suffered enough damage to fail or when recovering from failure. It'd just enable or disable a bitflag, leaving it up to subtypes to decide how to tackle organ failure their own ways: diverse, funky and sometimes incompatible. More often than not relying on their very own "update_thingamajig" kinda procs that run whenever the organ takes damage, rather than just when the threshold is reached (low, high, failure. There are however a couple organs with their own quirky thresholds, I let those slide). There's also a bit of old code, especially for ears, with the `AdjustEarDamage` and temporary deafness both predating the framework for organ damage as far as I know. It really needed a coat of fresh paint. Oh, there were also more than a handful of organs that still heavily relied on some ORGAN_TRAIT source instead of the `organ_traits` list and the two add/remove procs `add_organ_trait` or `remove_organ_trait`. This include organs that lose or gain specific traits when failing et viceversa. ~~Lastly, felinids (and the halloween ghost species) having reflective eyes. It's just a nod to the tapetum lucidum that animals with night vision often have (including cats), which is why their eyes are a bit brighter in the dark. Felinids however, do not have night vision (nor do ghosts). This is merely cosmetic.~~ Cut out for the time being due to issues with the specular emissive... ## Why It's Good For The Game Refactoring / cleaning up old organ code. ## Changelog 🆑 refactor: Refactored organ damage code a little. Hopefully there won't be issues (otherwise report them). /🆑
This commit is contained in:
@@ -117,7 +117,7 @@ INITIALIZE_IMMEDIATE(/obj/item/organ)
|
||||
|
||||
/// Add a Trait to an organ that it will give its owner.
|
||||
/obj/item/organ/proc/add_organ_trait(trait)
|
||||
LAZYADD(organ_traits, trait)
|
||||
LAZYOR(organ_traits, trait)
|
||||
if(isnull(owner))
|
||||
return
|
||||
ADD_TRAIT(owner, trait, REF(src))
|
||||
@@ -251,14 +251,9 @@ INITIALIZE_IMMEDIATE(/obj/item/organ)
|
||||
damage = clamp(damage + damage_amount, 0, maximum)
|
||||
SEND_SIGNAL(src, COMSIG_ORGAN_ADJUST_DAMAGE, damage_amount, maximum, required_organ_flag)
|
||||
. = (prev_damage - damage) // return net damage
|
||||
var/message = check_damage_thresholds(owner)
|
||||
var/message = check_damage_thresholds()
|
||||
prev_damage = damage
|
||||
|
||||
if(damage >= maxHealth)
|
||||
organ_flags |= ORGAN_FAILING
|
||||
else
|
||||
organ_flags &= ~ORGAN_FAILING
|
||||
|
||||
if(message && owner && owner.stat <= SOFT_CRIT)
|
||||
to_chat(owner, message)
|
||||
|
||||
@@ -272,24 +267,66 @@ INITIALIZE_IMMEDIATE(/obj/item/organ)
|
||||
* description: By checking our current damage against our previous damage, we can decide whether we've passed an organ threshold.
|
||||
* If we have, send the corresponding threshold message to the owner, if such a message exists.
|
||||
*/
|
||||
/obj/item/organ/proc/check_damage_thresholds(mob/organ_owner)
|
||||
/obj/item/organ/proc/check_damage_thresholds()
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
if(damage == prev_damage)
|
||||
return
|
||||
var/delta = damage - prev_damage
|
||||
var/message = ""
|
||||
if(delta > 0)
|
||||
if(damage >= maxHealth)
|
||||
return now_failing
|
||||
if(damage > high_threshold && prev_damage <= high_threshold)
|
||||
return high_threshold_passed
|
||||
if(damage > low_threshold && prev_damage <= low_threshold)
|
||||
return low_threshold_passed
|
||||
else
|
||||
if(prev_damage > low_threshold && damage <= low_threshold)
|
||||
return low_threshold_cleared
|
||||
if(prev_damage > high_threshold && damage <= high_threshold)
|
||||
return high_threshold_cleared
|
||||
if(prev_damage == maxHealth)
|
||||
return now_fixed
|
||||
on_low_damage_received()
|
||||
message = low_threshold_passed
|
||||
if(damage > high_threshold && prev_damage <= high_threshold)
|
||||
on_high_damage_received()
|
||||
message = high_threshold_passed
|
||||
if(damage >= maxHealth)
|
||||
organ_flags |= ORGAN_FAILING
|
||||
on_begin_failure()
|
||||
message = now_failing
|
||||
return message
|
||||
|
||||
if(prev_damage == maxHealth)
|
||||
organ_flags &= ~ORGAN_FAILING
|
||||
on_failure_recovery()
|
||||
message = now_fixed
|
||||
if(prev_damage > high_threshold && damage <= high_threshold)
|
||||
on_high_damage_healed()
|
||||
message = high_threshold_cleared
|
||||
if(prev_damage > low_threshold && damage <= low_threshold)
|
||||
on_low_damage_healed()
|
||||
message = low_threshold_cleared
|
||||
return message
|
||||
|
||||
/**
|
||||
* Called when the damage surpasses the low damage threshold.
|
||||
*
|
||||
* This and other procs like this one merely exist to make it easier to keep a standard on
|
||||
* damage thresholds for organs. This doesn't mean you cannot make custom thresholds for various stuff,
|
||||
* and you're more than welcome to improve or refactor any portion of the code around these mechanics
|
||||
*/
|
||||
/obj/item/organ/proc/on_low_damage_received()
|
||||
return
|
||||
|
||||
///Called when the damage goes below the low damage threshold
|
||||
/obj/item/organ/proc/on_low_damage_healed()
|
||||
return
|
||||
|
||||
///Called when the damage surpasses the high damage threshold
|
||||
/obj/item/organ/proc/on_high_damage_received()
|
||||
return
|
||||
|
||||
///Called when the damage goes below the high damage threshold
|
||||
/obj/item/organ/proc/on_high_damage_healed()
|
||||
return
|
||||
|
||||
///Called when the organ enters failing stage
|
||||
/obj/item/organ/proc/on_begin_failure()
|
||||
return
|
||||
|
||||
///Called when the organ recovers from failing stage
|
||||
/obj/item/organ/proc/on_failure_recovery()
|
||||
return
|
||||
|
||||
//Looking for brains?
|
||||
//Try code/modules/mob/living/carbon/brain/brain_item.dm
|
||||
@@ -313,9 +350,9 @@ INITIALIZE_IMMEDIATE(/obj/item/organ)
|
||||
dna.species.regenerate_organs(src, replace_current = FALSE)
|
||||
set_heartattack(FALSE)
|
||||
|
||||
// Ears have aditional vаr "deaf", need to update it too
|
||||
// Ears have aditional var "deaf", need to update it too
|
||||
var/obj/item/organ/ears/ears = get_organ_slot(ORGAN_SLOT_EARS)
|
||||
ears?.adjustEarDamage(0, -INFINITY) // full heal ears deafness
|
||||
ears.adjust_temporary_deafness(-INFINITY)
|
||||
|
||||
return
|
||||
|
||||
@@ -352,7 +389,8 @@ INITIALIZE_IMMEDIATE(/obj/item/organ)
|
||||
if(!ears)
|
||||
ears = new()
|
||||
ears.Insert(src)
|
||||
ears.adjustEarDamage(-INFINITY, -INFINITY) // actually do: set_organ_damage(0) and deaf = 0
|
||||
ears.set_organ_damage(0)
|
||||
ears.adjust_temporary_deafness(-INFINITY)
|
||||
|
||||
///Organs don't die instantly, and neither should you when you get fucked up
|
||||
/obj/item/organ/proc/handle_failing_organs(seconds_per_tick)
|
||||
|
||||
@@ -18,32 +18,36 @@
|
||||
/// Eyecolor from the HUD
|
||||
var/hud_color = "#3CB8A5"
|
||||
|
||||
/obj/item/organ/cyberimp/eyes/hud/Initialize(mapload)
|
||||
. = ..()
|
||||
if(toggled_on)
|
||||
for(var/hud_trait in HUD_traits)
|
||||
add_organ_trait(hud_trait)
|
||||
|
||||
/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)
|
||||
for(var/hud_trait in HUD_traits)
|
||||
remove_organ_trait(hud_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)
|
||||
for(var/hud_trait in HUD_traits)
|
||||
add_organ_trait(hud_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/human/eye_owner, special = FALSE, movement_flags)
|
||||
. = ..()
|
||||
eye_owner.add_traits(HUD_traits, ORGAN_TRAIT)
|
||||
toggled_on = TRUE
|
||||
if(hud_color)
|
||||
if(toggled_on && 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/human/eye_owner, special, movement_flags)
|
||||
. = ..()
|
||||
eye_owner.remove_traits(HUD_traits, ORGAN_TRAIT)
|
||||
toggled_on = FALSE
|
||||
if(hud_color)
|
||||
if(toggled_on && hud_color)
|
||||
eye_owner.remove_eye_color(EYE_COLOR_HUD_PRIORITY, !special)
|
||||
|
||||
/obj/item/organ/cyberimp/eyes/hud/medical
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
now_fixed = span_info("Noise slowly begins filling your ears once more.")
|
||||
low_threshold_cleared = span_info("The ringing in your ears has died down.")
|
||||
|
||||
/// `deaf` measures "ticks" of deafness. While > 0, the person is unable to hear anything.
|
||||
var/deaf = 0
|
||||
/// temporary deafness, measured in seconds. While > 0, the person is unable to hear anything.
|
||||
var/temporary_deafness = 0
|
||||
|
||||
// `damage` in this case measures long term damage to the ears, if too high,
|
||||
// the person will not have either `deaf` or `ear_damage` decrease
|
||||
@@ -39,23 +39,20 @@
|
||||
// no healing if failing
|
||||
if(organ_flags & ORGAN_FAILING)
|
||||
return
|
||||
adjustEarDamage(0, -0.5 * seconds_per_tick)
|
||||
adjust_temporary_deafness(-seconds_per_tick SECONDS)
|
||||
if((damage > low_threshold) && SPT_PROB(damage / 60, seconds_per_tick))
|
||||
adjustEarDamage(0, 4)
|
||||
adjust_temporary_deafness(4 SECONDS)
|
||||
SEND_SOUND(owner, sound('sound/items/weapons/flash_ring.ogg'))
|
||||
|
||||
/obj/item/organ/ears/apply_organ_damage(damage_amount, maximum, required_organ_flag)
|
||||
. = ..()
|
||||
update_temp_deafness()
|
||||
|
||||
/obj/item/organ/ears/on_mob_insert(mob/living/carbon/organ_owner, special, movement_flags)
|
||||
. = ..()
|
||||
update_temp_deafness()
|
||||
if(temporary_deafness)
|
||||
on_deafened()
|
||||
|
||||
/obj/item/organ/ears/on_mob_remove(mob/living/carbon/organ_owner, special, movement_flags)
|
||||
. = ..()
|
||||
UnregisterSignal(organ_owner, COMSIG_MOB_SAY)
|
||||
REMOVE_TRAIT(organ_owner, TRAIT_DEAF, EAR_DAMAGE)
|
||||
if(temporary_deafness)
|
||||
on_undeafened(organ_owner)
|
||||
|
||||
/obj/item/organ/ears/get_status_appendix(advanced, add_tooltips)
|
||||
if(owner.stat == DEAD || !HAS_TRAIT(owner, TRAIT_DEAF))
|
||||
@@ -65,7 +62,7 @@
|
||||
return conditional_tooltip("Subject is permanently deaf.", "Irreparable under normal circumstances.", add_tooltips)
|
||||
if(HAS_TRAIT_FROM(owner, TRAIT_DEAF, GENETIC_MUTATION))
|
||||
return conditional_tooltip("Subject is genetically deaf.", "Use medication such as [/datum/reagent/medicine/mutadone::name].", add_tooltips)
|
||||
if(HAS_TRAIT_FROM(owner, TRAIT_DEAF, EAR_DAMAGE))
|
||||
if((organ_flags & ORGAN_FAILING) || HAS_TRAIT_FROM(owner, TRAIT_DEAF, EAR_DAMAGE))
|
||||
return conditional_tooltip("Subject is [(organ_flags & ORGAN_FAILING) ? "permanently": "temporarily"] deaf from ear damage.", "Repair surgically, use medication such as [/datum/reagent/medicine/inacusiate::name], or protect ears with earmuffs.", add_tooltips)
|
||||
return "Subject is deaf."
|
||||
|
||||
@@ -73,52 +70,43 @@
|
||||
// Always show if we have an appendix
|
||||
return ..() || (owner.stat != DEAD && HAS_TRAIT(owner, TRAIT_DEAF))
|
||||
|
||||
/**
|
||||
* Snowflake proc to handle temporary deafness
|
||||
*
|
||||
* * ddmg: Handles normal organ damage
|
||||
* * ddeaf: Handles temporary deafness, 1 ddeaf = 2 seconds of deafness, by default (with no multiplier)
|
||||
*/
|
||||
/obj/item/organ/ears/proc/adjustEarDamage(ddmg = 0, ddeaf = 0)
|
||||
if(HAS_TRAIT(owner, TRAIT_GODMODE))
|
||||
update_temp_deafness()
|
||||
///Adjust the temporary deafness of the person, up or down
|
||||
/obj/item/organ/ears/proc/adjust_temporary_deafness(amount)
|
||||
// organ failure makes us permanently deafened. Also, doesn't do anything if not in someone or during godmode
|
||||
if(amount <= 0 || (owner && HAS_TRAIT(owner, TRAIT_GODMODE)))
|
||||
return
|
||||
|
||||
var/mod_damage = ddmg > 0 ? (ddmg * damage_multiplier) : ddmg
|
||||
if(mod_damage)
|
||||
apply_organ_damage(mod_damage)
|
||||
var/mod_deaf = ddeaf > 0 ? (ddeaf * damage_multiplier) : ddeaf
|
||||
if(mod_deaf)
|
||||
deaf = max(deaf + mod_deaf, 0)
|
||||
update_temp_deafness()
|
||||
temporary_deafness += max(amount * damage_multiplier, 0)
|
||||
|
||||
/// Updates status of deafness
|
||||
/obj/item/organ/ears/proc/update_temp_deafness()
|
||||
// if we're failing we always have at least some deaf stacks (and thus deafness)
|
||||
if(organ_flags & ORGAN_FAILING)
|
||||
deaf = max(deaf, 1 * damage_multiplier)
|
||||
|
||||
if(isnull(owner))
|
||||
if(!owner)
|
||||
return
|
||||
|
||||
if(HAS_TRAIT(owner, TRAIT_GODMODE))
|
||||
deaf = 0
|
||||
if(temporary_deafness && !HAS_TRAIT_FROM(owner, TRAIT_DEAF, EAR_DAMAGE))
|
||||
on_deafened()
|
||||
else if(!temporary_deafness && HAS_TRAIT_FROM(owner, TRAIT_DEAF, EAR_DAMAGE))
|
||||
on_undeafened()
|
||||
|
||||
if(deaf > 0)
|
||||
if(!HAS_TRAIT_FROM(owner, TRAIT_DEAF, EAR_DAMAGE))
|
||||
RegisterSignal(owner, COMSIG_MOB_SAY, PROC_REF(adjust_speech))
|
||||
ADD_TRAIT(owner, TRAIT_DEAF, EAR_DAMAGE)
|
||||
else
|
||||
REMOVE_TRAIT(owner, TRAIT_DEAF, EAR_DAMAGE)
|
||||
UnregisterSignal(owner, COMSIG_MOB_SAY)
|
||||
///Called when temporary deafness begins
|
||||
/obj/item/organ/ears/proc/on_deafened()
|
||||
RegisterSignal(owner, COMSIG_MOB_SAY, PROC_REF(adjust_speech))
|
||||
ADD_TRAIT(owner, TRAIT_DEAF, EAR_DAMAGE)
|
||||
|
||||
///Called when temporary deafness reaches zero. Has to have an 'organ_owner' arg, because by the time it's called on 'on_mob_remove', owner is already null
|
||||
/obj/item/organ/ears/proc/on_undeafened(mob/living/organ_owner = owner)
|
||||
REMOVE_TRAIT(organ_owner, TRAIT_DEAF, EAR_DAMAGE)
|
||||
UnregisterSignal(organ_owner, COMSIG_MOB_SAY)
|
||||
|
||||
/obj/item/organ/ears/on_begin_failure()
|
||||
add_organ_trait(TRAIT_DEAF)
|
||||
|
||||
/obj/item/organ/ears/on_failure_recovery()
|
||||
remove_organ_trait(TRAIT_DEAF)
|
||||
|
||||
/// Being deafened by loud noises makes you shout
|
||||
/obj/item/organ/ears/proc/adjust_speech(datum/source, list/speech_args)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(HAS_TRAIT_NOT_FROM(source, TRAIT_DEAF, EAR_DAMAGE))
|
||||
return
|
||||
if(HAS_TRAIT(source, TRAIT_SIGN_LANG))
|
||||
if(HAS_TRAIT_NOT_FROM(owner, TRAIT_DEAF, EAR_DAMAGE) || HAS_TRAIT(owner, TRAIT_SIGN_LANG))
|
||||
return
|
||||
|
||||
var/message = speech_args[SPEECH_MESSAGE]
|
||||
@@ -240,16 +228,9 @@
|
||||
desc = "Allows the user to more easily hear whispers. The user becomes extra vulnerable to loud noises, however"
|
||||
// Same sensitivity as felinid ears
|
||||
damage_multiplier = 2
|
||||
|
||||
// The original idea was to use signals to do this not traits. Unfortunately, the star effect used for whispers applies before any relevant signals
|
||||
// This seems like the least invasive solution
|
||||
/obj/item/organ/ears/cybernetic/whisper/on_mob_insert(mob/living/carbon/ear_owner)
|
||||
. = ..()
|
||||
ADD_TRAIT(ear_owner, TRAIT_GOOD_HEARING, ORGAN_TRAIT)
|
||||
|
||||
/obj/item/organ/ears/cybernetic/whisper/on_mob_remove(mob/living/carbon/ear_owner)
|
||||
. = ..()
|
||||
REMOVE_TRAIT(ear_owner, TRAIT_GOOD_HEARING, ORGAN_TRAIT)
|
||||
// The original idea was to use signals to do this not traits. Unfortunately, the star effect used for whispers applies before any relevant signals
|
||||
// This seems like the least invasive solution
|
||||
organ_traits = list(TRAIT_GOOD_HEARING)
|
||||
|
||||
/obj/item/organ/ears/cybernetic/volume
|
||||
name = "volume-adjusting cybernetic ears"
|
||||
@@ -265,14 +246,7 @@
|
||||
desc = "Through the power of modern engineering, allows the user to hear speech through walls. The user becomes extra vulnerable to loud noises, however"
|
||||
// Same sensitivity as felinid ears
|
||||
damage_multiplier = 2
|
||||
|
||||
/obj/item/organ/ears/cybernetic/xray/on_mob_insert(mob/living/carbon/ear_owner)
|
||||
. = ..()
|
||||
ADD_TRAIT(ear_owner, TRAIT_XRAY_HEARING, ORGAN_TRAIT)
|
||||
|
||||
/obj/item/organ/ears/cybernetic/xray/on_mob_remove(mob/living/carbon/ear_owner)
|
||||
. = ..()
|
||||
REMOVE_TRAIT(ear_owner, TRAIT_XRAY_HEARING, ORGAN_TRAIT)
|
||||
organ_traits = list(TRAIT_XRAY_HEARING)
|
||||
|
||||
/obj/item/organ/ears/cybernetic/emp_act(severity)
|
||||
. = ..()
|
||||
|
||||
@@ -22,8 +22,6 @@
|
||||
|
||||
/// Sight flags this eye pair imparts on its user.
|
||||
var/sight_flags = NONE
|
||||
/// changes how the eyes overlay is applied, makes it apply over the lighting layer
|
||||
var/overlay_ignore_lighting = FALSE
|
||||
/// How much innate tint these eyes have
|
||||
var/tint = 0
|
||||
/// How much innare flash protection these eyes have, usually paired with tint
|
||||
@@ -52,8 +50,6 @@
|
||||
|
||||
/// Glasses cannot be worn over these eyes. Currently unused
|
||||
var/no_glasses = FALSE
|
||||
/// indication that the eyes are undergoing some negative effect
|
||||
var/damaged = FALSE
|
||||
/// Native FOV that will be applied if a config is enabled
|
||||
var/native_fov = FOV_90_DEGREES
|
||||
/// Scarring on this organ
|
||||
@@ -82,8 +78,13 @@
|
||||
|
||||
/obj/item/organ/eyes/on_mob_insert(mob/living/carbon/receiver, special, movement_flags)
|
||||
. = ..()
|
||||
if(organ_flags & ORGAN_FAILING)
|
||||
receiver.become_blind(EYE_DAMAGE)
|
||||
if(damage >= low_threshold)
|
||||
receiver.assign_nearsightedness(EYE_DAMAGE, damage >= high_threshold ? 3 : 2, TRUE)
|
||||
|
||||
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
|
||||
@@ -91,9 +92,17 @@
|
||||
eye_color_left = as_human.eye_color_left
|
||||
if (!eye_color_right)
|
||||
eye_color_right = as_human.eye_color_right
|
||||
RegisterSignals(receiver, list(
|
||||
SIGNAL_ADDTRAIT(TRAIT_LUMINESCENT_EYES),
|
||||
SIGNAL_REMOVETRAIT(TRAIT_LUMINESCENT_EYES),
|
||||
SIGNAL_ADDTRAIT(TRAIT_REFLECTIVE_EYES),
|
||||
SIGNAL_REMOVETRAIT(TRAIT_REFLECTIVE_EYES),
|
||||
), PROC_REF(on_shiny_eyes_trait_update))
|
||||
|
||||
refresh(receiver, call_update = TRUE)
|
||||
RegisterSignal(receiver, COMSIG_ATOM_BULLET_ACT, PROC_REF(on_bullet_act))
|
||||
RegisterSignal(receiver, COMSIG_COMPONENT_CLEAN_FACE_ACT, PROC_REF(on_face_wash))
|
||||
|
||||
if (scarring)
|
||||
apply_scarring_effects()
|
||||
|
||||
@@ -134,19 +143,37 @@
|
||||
if(!special)
|
||||
human_owner.update_body()
|
||||
|
||||
// become blind (if not special)
|
||||
if(!special)
|
||||
organ_owner.become_blind(NO_EYES)
|
||||
|
||||
// Cure blindness from eye damage
|
||||
organ_owner.cure_blind(EYE_DAMAGE)
|
||||
organ_owner.cure_nearsighted(EYE_DAMAGE)
|
||||
// Eye blind and temp blind go to, even if this is a bit of cheesy way to clear blindness
|
||||
organ_owner.remove_status_effect(/datum/status_effect/eye_blur)
|
||||
organ_owner.remove_status_effect(/datum/status_effect/temporary_blindness)
|
||||
// Then become blind anyways (if not special)
|
||||
if(!special)
|
||||
organ_owner.become_blind(NO_EYES)
|
||||
|
||||
if (scarring)
|
||||
owner.cure_nearsighted(TRAIT_RIGHT_EYE_SCAR)
|
||||
owner.cure_nearsighted(TRAIT_LEFT_EYE_SCAR)
|
||||
owner.cure_blind(EYE_SCARRING_TRAIT)
|
||||
|
||||
organ_owner.update_tint()
|
||||
organ_owner.update_sight()
|
||||
UnregisterSignal(organ_owner, list(COMSIG_ATOM_BULLET_ACT, COMSIG_COMPONENT_CLEAN_FACE_ACT))
|
||||
UnregisterSignal(organ_owner, list(
|
||||
COMSIG_ATOM_BULLET_ACT,
|
||||
COMSIG_COMPONENT_CLEAN_FACE_ACT,
|
||||
SIGNAL_ADDTRAIT(TRAIT_LUMINESCENT_EYES),
|
||||
SIGNAL_REMOVETRAIT(TRAIT_LUMINESCENT_EYES),
|
||||
SIGNAL_ADDTRAIT(TRAIT_REFLECTIVE_EYES),
|
||||
SIGNAL_REMOVETRAIT(TRAIT_REFLECTIVE_EYES),
|
||||
))
|
||||
|
||||
///Called whenever the luminescent and/or reflective eyes traits are added or removed
|
||||
/obj/item/organ/eyes/proc/on_shiny_eyes_trait_update(mob/living/carbon/human/source)
|
||||
SIGNAL_HANDLER
|
||||
source.update_eyes()
|
||||
|
||||
/obj/item/organ/eyes/update_atom_colour()
|
||||
. = ..()
|
||||
@@ -267,9 +294,8 @@
|
||||
var/mutable_appearance/eye_right = mutable_appearance('icons/mob/human/human_face.dmi', "[eye_icon_state]_r", -EYES_LAYER, parent)
|
||||
var/list/overlays = list(eye_left, eye_right)
|
||||
|
||||
if(overlay_ignore_lighting && !(parent.obscured_slots & HIDEEYES))
|
||||
overlays += emissive_appearance(eye_left.icon, eye_left.icon_state, parent, -EYES_LAYER, alpha = eye_left.alpha)
|
||||
overlays += emissive_appearance(eye_right.icon, eye_right.icon_state, parent, -EYES_LAYER, alpha = eye_right.alpha)
|
||||
if(!(parent.obscured_slots & HIDEEYES))
|
||||
overlays += get_emissive_overlays(eye_left, eye_right, parent)
|
||||
|
||||
var/obj/item/bodypart/head/my_head = parent.get_bodypart(BODY_ZONE_HEAD)
|
||||
|
||||
@@ -299,6 +325,19 @@
|
||||
|
||||
return overlays
|
||||
|
||||
///Returns the two emissive overlays built for the left and right eyes, in order.
|
||||
/obj/item/organ/eyes/proc/get_emissive_overlays(mutable_appearance/eye_left, mutable_appearance/eye_right, atom/spokesman)
|
||||
var/list/return_list = list()
|
||||
var/emissive_effect
|
||||
if((owner && HAS_TRAIT(owner, TRAIT_LUMINESCENT_EYES)) || (TRAIT_LUMINESCENT_EYES in organ_traits))
|
||||
emissive_effect = EMISSIVE_BLOOM
|
||||
else if((owner && HAS_TRAIT(owner, TRAIT_REFLECTIVE_EYES)) || (TRAIT_REFLECTIVE_EYES in organ_traits))
|
||||
emissive_effect = EMISSIVE_SPECULAR
|
||||
if(emissive_effect)
|
||||
return_list += emissive_appearance(eye_left.icon, eye_left.icon_state, spokesman, -EYES_LAYER, alpha = eye_left.alpha, effect_type = emissive_effect)
|
||||
return_list += emissive_appearance(eye_right.icon, eye_right.icon_state, spokesman, -EYES_LAYER, alpha = eye_right.alpha, effect_type = emissive_effect)
|
||||
return return_list
|
||||
|
||||
/obj/item/organ/eyes/update_overlays()
|
||||
. = ..()
|
||||
if (scarring & RIGHT_EYE_SCAR)
|
||||
@@ -358,13 +397,6 @@
|
||||
owner.cure_blind(EYE_SCARRING_TRAIT)
|
||||
owner.update_body()
|
||||
|
||||
/obj/item/organ/eyes/on_mob_remove(mob/living/carbon/eye_owner)
|
||||
. = ..()
|
||||
if (scarring)
|
||||
eye_owner.cure_nearsighted(TRAIT_RIGHT_EYE_SCAR)
|
||||
eye_owner.cure_nearsighted(TRAIT_LEFT_EYE_SCAR)
|
||||
eye_owner.cure_blind(EYE_SCARRING_TRAIT)
|
||||
|
||||
#undef OFFSET_X
|
||||
#undef OFFSET_Y
|
||||
|
||||
@@ -374,38 +406,28 @@
|
||||
eye_color_left = initial(eye_color_left)
|
||||
eye_color_right = initial(eye_color_right)
|
||||
|
||||
/obj/item/organ/eyes/apply_organ_damage(damage_amount, maximum = maxHealth, required_organ_flag)
|
||||
. = ..()
|
||||
if(!owner)
|
||||
return FALSE
|
||||
apply_damaged_eye_effects()
|
||||
|
||||
/// Applies effects to our owner based on how damaged our eyes are
|
||||
/obj/item/organ/eyes/proc/apply_damaged_eye_effects()
|
||||
// we're in healthy threshold, either try to heal (if damaged) or do nothing
|
||||
if(damage <= low_threshold)
|
||||
if(damaged)
|
||||
damaged = FALSE
|
||||
// clear nearsightedness from damage
|
||||
owner.cure_nearsighted(EYE_DAMAGE)
|
||||
// and cure blindness from damage
|
||||
owner.cure_blind(EYE_DAMAGE)
|
||||
/obj/item/organ/eyes/on_low_damage_received()
|
||||
if(damage >= high_threshold)
|
||||
return
|
||||
owner?.assign_nearsightedness(EYE_DAMAGE, 2, TRUE)
|
||||
|
||||
//various degrees of "oh fuck my eyes", from "point a laser at your eye" to "staring at the Sun" intensities
|
||||
// 50 - blind
|
||||
// 49-31 - nearsighted (2 severity)
|
||||
// 30-20 - nearsighted (1 severity)
|
||||
if(organ_flags & ORGAN_FAILING)
|
||||
// become blind from damage
|
||||
owner.become_blind(EYE_DAMAGE)
|
||||
/obj/item/organ/eyes/on_high_damage_received()
|
||||
owner?.assign_nearsightedness(EYE_DAMAGE, 3, TRUE)
|
||||
|
||||
else
|
||||
// become nearsighted from damage
|
||||
var/severity = damage > high_threshold ? 3 : 2
|
||||
owner.assign_nearsightedness(EYE_DAMAGE, severity, TRUE)
|
||||
/obj/item/organ/eyes/on_begin_failure()
|
||||
owner?.become_blind(EYE_DAMAGE)
|
||||
|
||||
damaged = TRUE
|
||||
/obj/item/organ/eyes/on_failure_recovery()
|
||||
owner?.cure_blind(EYE_DAMAGE)
|
||||
|
||||
/obj/item/organ/eyes/on_high_damage_healed()
|
||||
if(damage <= low_threshold)
|
||||
return
|
||||
owner?.assign_nearsightedness(EYE_DAMAGE, 2, TRUE)
|
||||
|
||||
/obj/item/organ/eyes/on_low_damage_healed()
|
||||
// clear nearsightedness from damage
|
||||
owner?.cure_nearsighted(EYE_DAMAGE)
|
||||
|
||||
/obj/item/organ/eyes/feel_for_damage(self_aware)
|
||||
// Eye damage has visual effects, so we don't really need to "feel" it when self-examining
|
||||
@@ -681,16 +703,9 @@
|
||||
eye_color_left = "#3cb8a5"
|
||||
eye_color_right = "#3cb8a5"
|
||||
sight_flags = SEE_MOBS | SEE_OBJS | SEE_TURFS
|
||||
organ_traits = list(TRAIT_XRAY_VISION)
|
||||
penlight_message = "replaced by small radiation emitters and detectors"
|
||||
|
||||
/obj/item/organ/eyes/robotic/xray/on_mob_insert(mob/living/carbon/eye_owner)
|
||||
. = ..()
|
||||
ADD_TRAIT(eye_owner, TRAIT_XRAY_VISION, ORGAN_TRAIT)
|
||||
|
||||
/obj/item/organ/eyes/robotic/xray/on_mob_remove(mob/living/carbon/eye_owner)
|
||||
. = ..()
|
||||
REMOVE_TRAIT(eye_owner, TRAIT_XRAY_VISION, ORGAN_TRAIT)
|
||||
|
||||
/obj/item/organ/eyes/robotic/thermals
|
||||
name = "thermal eyes"
|
||||
desc = "These cybernetic eye implants will give you thermal vision. Vertical slit pupil included."
|
||||
@@ -1004,17 +1019,25 @@
|
||||
if(QDELETED(eye_owner) || !ishuman(eye_owner)) //Other carbon mobs don't have eye color.
|
||||
return
|
||||
|
||||
if(!eye.light_on)
|
||||
eye_icon_state = initial(eye_icon_state)
|
||||
overlay_ignore_lighting = FALSE
|
||||
else
|
||||
overlay_ignore_lighting = TRUE
|
||||
eye_icon_state = base_eye_state
|
||||
|
||||
var/obj/item/bodypart/head/head = eye_owner.get_bodypart(BODY_ZONE_HEAD) //if we have eyes we definently have a head anyway
|
||||
var/previous_flags = head.head_flags
|
||||
head.head_flags = previous_flags | HEAD_EYECOLOR
|
||||
eye_owner.dna.species.handle_body(eye_owner)
|
||||
head.head_flags |= HEAD_EYECOLOR
|
||||
|
||||
///enabling and disabling the TRAIT_LUMINESCENT_EYES trait already calls handle_eyes(), in that case, let's skip that call
|
||||
var/skip_call = FALSE
|
||||
if(!eye.light_on)
|
||||
eye_icon_state = initial(eye_icon_state)
|
||||
skip_call = HAS_TRAIT_FROM_ONLY(eye_owner, TRAIT_LUMINESCENT_EYES, REF(src))
|
||||
remove_organ_trait(TRAIT_LUMINESCENT_EYES)
|
||||
else
|
||||
skip_call = !HAS_TRAIT(eye_owner, TRAIT_LUMINESCENT_EYES)
|
||||
add_organ_trait(TRAIT_LUMINESCENT_EYES)
|
||||
eye_icon_state = base_eye_state
|
||||
|
||||
if(!skip_call && ishuman(eye_owner))
|
||||
var/mob/living/carbon/human/humie = eye_owner
|
||||
humie.update_eyes()
|
||||
|
||||
head.head_flags = previous_flags
|
||||
|
||||
#undef MATCH_LIGHT_COLOR
|
||||
@@ -1140,7 +1163,7 @@
|
||||
eye_color_right = "#f74a4d"
|
||||
eye_icon_state = "eyes_glow"
|
||||
iris_overlay = null
|
||||
overlay_ignore_lighting = TRUE
|
||||
organ_traits = list(TRAIT_UNNATURAL_RED_GLOWY_EYES, TRAIT_LUMINESCENT_EYES)
|
||||
flash_protect = FLASH_PROTECTION_HYPER_SENSITIVE
|
||||
low_light_cutoff = list(5, 12, 20)
|
||||
medium_light_cutoff = list(15, 20, 30)
|
||||
@@ -1153,10 +1176,6 @@
|
||||
apply_organ_damage(20 * examtool.light_power) //that's 0.5 lightpower for a penlight, so one penlight shining is equivalent to two seconds in a lit area
|
||||
return span_danger("[owner.p_Their()] eyes [penlight_message].")
|
||||
|
||||
/obj/item/organ/eyes/night_vision/maintenance_adapted/on_mob_insert(mob/living/carbon/eye_owner)
|
||||
. = ..()
|
||||
ADD_TRAIT(eye_owner, TRAIT_UNNATURAL_RED_GLOWY_EYES, ORGAN_TRAIT)
|
||||
|
||||
/obj/item/organ/eyes/night_vision/maintenance_adapted/on_life(seconds_per_tick, times_fired)
|
||||
if(!owner.is_blind() && isturf(owner.loc) && owner.has_light_nearby(light_amount=0.5)) //we allow a little more than usual so we can produce light from the adapted eyes
|
||||
to_chat(owner, span_danger("Your eyes! They burn in the light!"))
|
||||
@@ -1166,10 +1185,6 @@
|
||||
apply_organ_damage(-10) //heal quickly
|
||||
. = ..()
|
||||
|
||||
/obj/item/organ/eyes/night_vision/maintenance_adapted/on_mob_remove(mob/living/carbon/unadapted, special = FALSE, movement_flags)
|
||||
REMOVE_TRAIT(unadapted, TRAIT_UNNATURAL_RED_GLOWY_EYES, ORGAN_TRAIT)
|
||||
return ..()
|
||||
|
||||
/obj/item/organ/eyes/pod
|
||||
name = "pod eyes"
|
||||
desc = "Strangest salad you've ever seen."
|
||||
@@ -1179,3 +1194,9 @@
|
||||
iris_overlay = null
|
||||
foodtype_flags = PODPERSON_ORGAN_FOODTYPES
|
||||
penlight_message = "are green and plant-like"
|
||||
|
||||
/obj/item/organ/eyes/felinid
|
||||
name = "felinid eyes"
|
||||
desc = "A pair of highly reflective eyes with slit pupils, like those of a cat."
|
||||
pupils_name = "slit pupils"
|
||||
penlight_message = "shine under the pearly light"
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
attack_verb_continuous = list("licks", "slobbers", "slaps", "frenches", "tongues")
|
||||
attack_verb_simple = list("lick", "slobber", "slap", "french", "tongue")
|
||||
voice_filter = ""
|
||||
organ_traits = list(TRAIT_SPEAKS_CLEARLY)
|
||||
/**
|
||||
* A cached list of paths of all the languages this tongue is capable of speaking
|
||||
*
|
||||
@@ -51,6 +52,8 @@
|
||||
// - then we cache it via string list
|
||||
// this results in tongues with identical possible languages sharing a cached list instance
|
||||
languages_possible = string_list(get_possible_languages())
|
||||
if(!sense_of_taste)
|
||||
add_organ_trait(TRAIT_AGEUSIA)
|
||||
|
||||
/obj/item/organ/tongue/examine(mob/user)
|
||||
. = ..()
|
||||
@@ -137,40 +140,24 @@
|
||||
* ageusia from having a non-tasting tongue.
|
||||
*/
|
||||
REMOVE_TRAIT(receiver, TRAIT_AGEUSIA, NO_TONGUE_TRAIT)
|
||||
apply_tongue_effects()
|
||||
|
||||
/obj/item/organ/tongue/on_mob_remove(mob/living/carbon/organ_owner, special, movement_flags)
|
||||
. = ..()
|
||||
|
||||
temp_say_mod = ""
|
||||
UnregisterSignal(organ_owner, COMSIG_MOB_SAY)
|
||||
REMOVE_TRAIT(organ_owner, TRAIT_SPEAKS_CLEARLY, SPEAKING_FROM_TONGUE)
|
||||
REMOVE_TRAIT(organ_owner, TRAIT_AGEUSIA, ORGAN_TRAIT)
|
||||
// Carbons by default start with NO_TONGUE_TRAIT caused TRAIT_AGEUSIA
|
||||
ADD_TRAIT(organ_owner, TRAIT_AGEUSIA, NO_TONGUE_TRAIT)
|
||||
organ_owner.voice_filter = initial(organ_owner.voice_filter)
|
||||
|
||||
/obj/item/organ/tongue/apply_organ_damage(damage_amount, maximum = maxHealth, required_organ_flag)
|
||||
. = ..()
|
||||
if(!owner)
|
||||
return FALSE
|
||||
apply_tongue_effects()
|
||||
/obj/item/organ/tongue/on_begin_failure()
|
||||
remove_organ_trait(TRAIT_SPEAKS_CLEARLY)
|
||||
add_organ_trait(TRAIT_AGEUSIA)
|
||||
|
||||
/// Applies effects to our owner based on how damaged our tongue is
|
||||
/obj/item/organ/tongue/proc/apply_tongue_effects()
|
||||
/obj/item/organ/tongue/on_failure_recovery()
|
||||
add_organ_trait(TRAIT_SPEAKS_CLEARLY)
|
||||
if(sense_of_taste)
|
||||
//tongues can't taste food when they are failing
|
||||
if(organ_flags & ORGAN_FAILING)
|
||||
ADD_TRAIT(owner, TRAIT_AGEUSIA, ORGAN_TRAIT)
|
||||
else
|
||||
REMOVE_TRAIT(owner, TRAIT_AGEUSIA, ORGAN_TRAIT)
|
||||
else
|
||||
//tongues can't taste food when they lack a sense of taste
|
||||
ADD_TRAIT(owner, TRAIT_AGEUSIA, ORGAN_TRAIT)
|
||||
if(organ_flags & ORGAN_FAILING)
|
||||
REMOVE_TRAIT(owner, TRAIT_SPEAKS_CLEARLY, SPEAKING_FROM_TONGUE)
|
||||
else
|
||||
ADD_TRAIT(owner, TRAIT_SPEAKS_CLEARLY, SPEAKING_FROM_TONGUE)
|
||||
remove_organ_trait(TRAIT_AGEUSIA)
|
||||
|
||||
/obj/item/organ/tongue/could_speak_language(datum/language/language_path)
|
||||
return (language_path in languages_possible)
|
||||
|
||||
Reference in New Issue
Block a user