Skip to content

Commit

Permalink
The Enlightening: Selectable Night Vision color tint and mechanical r…
Browse files Browse the repository at this point in the history
…ebalancing (it's better now... usually) (#1709)

* Night vision uses eye color to determine overlay hue + photophobia scaling

* Use correct restoration proc for eye sensitivity

* Allow direct selection of night vision color tinting, default to left eye color if not available

* Modularization formatting improvements



* Further modularization & readability improvements, and refresh eyes after photophobia flash_protect adjustment

* Use correct var name

* Apply suggestions from code review



* Apply suggestions from code review



* Apply suggestions from code review



---------

Co-authored-by: Ephemeralis <[email protected]>
Co-authored-by: Bloop <[email protected]>
  • Loading branch information
3 people authored Jan 26, 2024
1 parent d8ca22c commit 599761f
Show file tree
Hide file tree
Showing 9 changed files with 135 additions and 4 deletions.
7 changes: 7 additions & 0 deletions code/__DEFINES/~nova_defines/quirks.dm
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,10 @@
#define DEATH_CONSEQUENCES_SHOW_HEALTH_ANALYZER_DATA "dc_show_health_analyzer_data"

#define DEATH_CONSEQUENCES_TIME_BETWEEN_REMINDERS 5 MINUTES

/// the minimum percentage of RGB darkness reduction that Nova's NV will always give. for base reference, the old NV quirk was equal to 4.5. note: some wide variance in min/max is needed to ensure hue has some chance to linear convert across
#define NOVA_NIGHT_VISION_POWER_MIN 4.5
/// the maximum percentage. for reference, low-light adapted eyes (icecats and ashwalkers) have 30.
#define NOVA_NIGHT_VISION_POWER_MAX 9
/// percentage of the NIGHT_VISION_POWER_MAX increase that is applied for eyes with low innate flash protection (photophobia quirk/moth eyes). At 0.75, this raises NV to 22.5 at hypersensitive flash_protect.
#define NOVA_NIGHT_VISION_SENSITIVITY_MULT 0.75
4 changes: 3 additions & 1 deletion code/datums/quirks/negative_quirks/photophobia.dm
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,15 @@
/datum/quirk/photophobia/proc/update_eyes(obj/item/organ/internal/eyes/target_eyes)
if(!istype(target_eyes))
return
target_eyes.flash_protect = max(target_eyes.flash_protect - 1, FLASH_PROTECTION_HYPER_SENSITIVE)
target_eyes.flash_protect = max(target_eyes.flash_protect - severity, FLASH_PROTECTION_HYPER_SENSITIVE) // NOVA EDIT CHANGE - ORIGINAL: target_eyes.flash_protect = max(target_eyes.flash_protect - 1, FLASH_PROTECTION_HYPER_SENSITIVE)
target_eyes.refresh() // NOVA EDIT ADDITION

/datum/quirk/photophobia/proc/restore_eyes(obj/item/organ/internal/eyes/normal_eyes)
SIGNAL_HANDLER
if(!istype(normal_eyes))
return
normal_eyes.flash_protect = initial(normal_eyes.flash_protect)
normal_eyes.refresh() // NOVA EDIT ADDITION

/datum/quirk/photophobia/proc/on_holder_moved(mob/living/source, atom/old_loc, dir, forced)
SIGNAL_HANDLER
Expand Down
2 changes: 1 addition & 1 deletion code/datums/quirks/positive_quirks/night_vision.dm
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
/datum/quirk/night_vision/proc/refresh_quirk_holder_eyes()
var/mob/living/carbon/human/human_quirk_holder = quirk_holder
var/obj/item/organ/internal/eyes/eyes = human_quirk_holder.get_organ_by_type(/obj/item/organ/internal/eyes)
if(!eyes || eyes.lighting_cutoff)
if(!eyes) // NOVA EDIT CHANGE - ORIGINAL: if(!eyes || eyes.lighting_cutoff)
return
// We've either added or removed TRAIT_NIGHT_VISION before calling this proc. Just refresh the eyes.
eyes.refresh()
9 changes: 7 additions & 2 deletions code/modules/surgery/organs/internal/eyes/_eyes.dm
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,13 @@
affected_human.eye_color_right = eye_color_right
else
eye_color_right = affected_human.eye_color_right
if(HAS_TRAIT(affected_human, TRAIT_NIGHT_VISION) && !lighting_cutoff)
lighting_cutoff = LIGHTING_CUTOFF_REAL_LOW
if(HAS_TRAIT(affected_human, TRAIT_NIGHT_VISION)) // NOVA EDIT CHANGE - ORIGINAL: if(HAS_TRAIT(affected_human, TRAIT_NIGHT_VISION) && !lighting_cutoff)
//lighting_cutoff = LIGHTING_CUTOFF_REAL_LOW // NOVA EDIT REMOVAL
// NOVA EDIT ADDITION START - NIGHT VISION ADJUSTMENT - adjusts color cutoffs based on chosen quirk color, or left eye colour if not available
var/datum/quirk/night_vision/nv_quirk = affected_human.get_quirk(/datum/quirk/night_vision)
nv_quirk.nv_color_cutoffs = nv_quirk.calculate_color_cutoffs(nv_quirk.nv_color)
color_cutoffs = nv_quirk.nv_color_cutoffs
// NOVA EDIT ADDITION END
if(CONFIG_GET(flag/native_fov) && native_fov)
affected_human.add_fov_trait(type, native_fov)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/datum/quirk/photophobia
desc = "Bright lights are uncomfortable and upsetting to you for whatever reason. Your eyes are also more sensitive to light in general. This shares a unique interaction with Night Vision."
/// how much of a flash_protect deficit the quirk inflicts
var/severity = 1

/datum/quirk/photophobia/add_unique(client/client_source)
var/sensitivity = client_source?.prefs.read_preference(/datum/preference/choiced/photophobia_severity)
switch (sensitivity)
if ("Hypersensitive")
severity = 2
if ("Sensitive")
severity = 1
var/obj/item/organ/internal/eyes/holder_eyes = quirk_holder.get_organ_slot(ORGAN_SLOT_EYES)
restore_eyes(holder_eyes) // add_unique() happens after add() so we need to jank reset this to ensure sensitivity is properly applied at roundstart
check_eyes(holder_eyes)

/datum/quirk_constant_data/photophobia
associated_typepath = /datum/quirk/photophobia
customization_options = list(/datum/preference/choiced/photophobia_severity)

/datum/preference/choiced/photophobia_severity
category = PREFERENCE_CATEGORY_MANUALLY_RENDERED
savefile_key = "photophobia_severity"
savefile_identifier = PREFERENCE_CHARACTER

/datum/preference/choiced/photophobia_severity/is_accessible(datum/preferences/preferences)
if (!..(preferences))
return FALSE

return "Photophobia" in preferences.all_quirks

/datum/preference/choiced/photophobia_severity/init_possible_values()
var/list/values = list("Sensitive", "Hypersensitive")
return values

/datum/preference/choiced/photophobia_severity/apply_to_human(mob/living/carbon/human/target, value)
return
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// This NV quirk variant applies color_offsets night vision to a mob based on its chosen eye color.
// Some eye colors will produce very slightly stronger mechanical night vision effects just by virtue of their RGB values being scaled higher (typically lighter colours).

/datum/quirk/night_vision
desc = "You can see a little better in darkness than most ordinary humanoids. If your eyes are naturally more sensitive to light through other means (such as being photophobic or a mothperson), this effect is significantly stronger."
medical_record_text = "Patient's visual sensory organs demonstrate non-standard performance in low-light conditions."
var/nv_color = null /// Holds the player's selected night vision colour
var/list/nv_color_cutoffs = null /// Contains the color_cutoffs applied to the user's eyes w/ our custom hue (once built)

/datum/quirk/night_vision/add_unique(client/client_source)
. = ..()
nv_color = client_source?.prefs.read_preference(/datum/preference/color/nv_color)
if (isnull(nv_color))
var/mob/living/carbon/human/human_holder = quirk_holder
nv_color = process_chat_color(human_holder.eye_color_left)
nv_color_cutoffs = calculate_color_cutoffs(nv_color)
refresh_quirk_holder_eyes() // make double triple dog sure we apply the overlay

/// Calculate eye organ color_cutoffs used in tinted night vision with a supplied hexcode colour, clamping and scaling appropriately.
/datum/quirk/night_vision/proc/calculate_color_cutoffs(color)
var/mob/living/carbon/human/target = quirk_holder

// if we have more sensitive eyes, increase the power
var/obj/item/organ/internal/eyes/target_eyes = target.get_organ_slot(ORGAN_SLOT_EYES)
if (!istype(target_eyes))
return
var/infravision_multiplier = max(0, (-(target_eyes.flash_protect) * NOVA_NIGHT_VISION_SENSITIVITY_MULT)) + 1

var/list/new_rgb_cutoffs = new /list(3)
for(var/i in 1 to 3)
var/base_color = hex2num(copytext(color, (i*2), (i*2)+2)) //convert their supplied hex colour value to RGB
var/adjusted_color = max(((base_color / 255) * (NOVA_NIGHT_VISION_POWER_MAX * infravision_multiplier)), (NOVA_NIGHT_VISION_POWER_MIN * infravision_multiplier)) //linear convert their eye color into a color_cutoff range, ensuring it is clamped
new_rgb_cutoffs[i] = adjusted_color

return new_rgb_cutoffs

/datum/quirk_constant_data/night_vision
associated_typepath = /datum/quirk/night_vision
customization_options = list(/datum/preference/color/nv_color)

// Client preference for night vision colour
/datum/preference/color/nv_color
savefile_key = "nv_color"
savefile_identifier = PREFERENCE_CHARACTER
category = PREFERENCE_CATEGORY_MANUALLY_RENDERED

/datum/preference/color/nv_color/is_accessible(datum/preferences/preferences)
if (!..(preferences))
return FALSE

return "Night Vision" in preferences.all_quirks

/datum/preference/color/nv_color/apply_to_human(mob/living/carbon/human/target, value)
return

// run the Blessed Runechat Proc since it does most of what we want regarding luminance clamping anyway. could it be better? probably. is it more work? yes, it's a LOT of work.
/datum/preference/color/nv_color/deserialize(input, datum/preferences/preferences)
return process_chat_color(sanitize_hexcolor(input))

/datum/preference/color/nv_color/serialize(input)
return process_chat_color(sanitize_hexcolor(input))

/datum/preference/color/nv_color/create_default_value()
return process_chat_color("#[random_color()]")
2 changes: 2 additions & 0 deletions tgstation.dme
Original file line number Diff line number Diff line change
Expand Up @@ -6221,8 +6221,10 @@
#include "modular_nova\master_files\code\datums\quirks\negative_quirks\heavy_sleeper.dm"
#include "modular_nova\master_files\code\datums\quirks\negative_quirks\narcolepsy.dm"
#include "modular_nova\master_files\code\datums\quirks\negative_quirks\nerve_staple.dm"
#include "modular_nova\master_files\code\datums\quirks\negative_quirks\photophobia.dm"
#include "modular_nova\master_files\code\datums\quirks\neutral_quirks\equipping.dm"
#include "modular_nova\master_files\code\datums\quirks\neutral_quirks\lungs.dm"
#include "modular_nova\master_files\code\datums\quirks\positive_quirks\night_vision.dm"
#include "modular_nova\master_files\code\datums\quirks\positive_quirks\spacer.dm"
#include "modular_nova\master_files\code\datums\records\record.dm"
#include "modular_nova\master_files\code\datums\station_traits\negative_traits.dm"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// THIS IS A NOVA SECTOR UI FILE
import { Feature, FeatureColorInput } from '../../base';

export const nv_color: Feature<string> = {
name: 'Night vision tint',
component: FeatureColorInput,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// THIS IS A NOVA SECTOR UI FILE
import { FeatureChoiced, FeatureDropdownInput } from '../../base';

export const photophobia_severity: FeatureChoiced = {
name: 'Severity',
component: FeatureDropdownInput,
};

0 comments on commit 599761f

Please sign in to comment.