diff --git a/code/__defines/mobs.dm b/code/__defines/mobs.dm
index cb0ecc37f52..9dc1a586d8d 100644
--- a/code/__defines/mobs.dm
+++ b/code/__defines/mobs.dm
@@ -231,25 +231,26 @@
//Vision flags, for dealing with plane visibility
#define VIS_FULLBRIGHT 1
-#define VIS_GHOSTS 2
-#define VIS_AI_EYE 3
+#define VIS_LIGHTING 2
+#define VIS_GHOSTS 3
+#define VIS_AI_EYE 4
-#define VIS_CH_STATUS 4
-#define VIS_CH_HEALTH 5
-#define VIS_CH_LIFE 6
-#define VIS_CH_ID 7
-#define VIS_CH_WANTED 8
-#define VIS_CH_IMPLOYAL 9
-#define VIS_CH_IMPTRACK 10
-#define VIS_CH_IMPCHEM 11
-#define VIS_CH_SPECIAL 12
-#define VIS_CH_STATUS_OOC 13
+#define VIS_CH_STATUS 5
+#define VIS_CH_HEALTH 6
+#define VIS_CH_LIFE 7
+#define VIS_CH_ID 8
+#define VIS_CH_WANTED 9
+#define VIS_CH_IMPLOYAL 10
+#define VIS_CH_IMPTRACK 11
+#define VIS_CH_IMPCHEM 12
+#define VIS_CH_SPECIAL 13
+#define VIS_CH_STATUS_OOC 14
-#define VIS_D_COLORBLIND 14
-#define VIS_D_COLORBLINDI 15
+#define VIS_D_COLORBLIND 15
+#define VIS_D_COLORBLINDI 16
-#define VIS_ADMIN1 16
-#define VIS_ADMIN2 17
-#define VIS_ADMIN3 18
+#define VIS_ADMIN1 17
+#define VIS_ADMIN2 18
+#define VIS_ADMIN3 19
-#define VIS_COUNT 18 //Must be highest number from above.
\ No newline at end of file
+#define VIS_COUNT 19 //Must be highest number from above.
\ No newline at end of file
diff --git a/code/__defines/mobs_vr.dm b/code/__defines/mobs_vr.dm
index 9209b861590..bc4a2ec8be5 100644
--- a/code/__defines/mobs_vr.dm
+++ b/code/__defines/mobs_vr.dm
@@ -1,10 +1,10 @@
#undef VIS_COUNT
-#define VIS_CH_STATUS_R 18
-#define VIS_CH_HEALTH_VR 19
-#define VIS_CH_BACKUP 20
-#define VIS_CH_VANTAG 21
+#define VIS_CH_STATUS_R 19
+#define VIS_CH_HEALTH_VR 20
+#define VIS_CH_BACKUP 21
+#define VIS_CH_VANTAG 22
-#define VIS_AUGMENTED 22
+#define VIS_AUGMENTED 23
-#define VIS_COUNT 22
\ No newline at end of file
+#define VIS_COUNT 23
\ No newline at end of file
diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm
index 3c6a6a6c56c..6ab4b7627fb 100644
--- a/code/_onclick/hud/hud.dm
+++ b/code/_onclick/hud/hud.dm
@@ -28,6 +28,7 @@ var/list/global_huds = list(
var/obj/screen/whitense
var/list/vimpaired
var/list/darkMask
+ var/obj/screen/darksight
var/obj/screen/nvg
var/obj/screen/thermal
var/obj/screen/meson
@@ -66,6 +67,13 @@ var/list/global_huds = list(
whitense.icon = 'icons/effects/static.dmi'
whitense.icon_state = "1 light"
+ //darksight 'hanger' for attached icons
+ darksight = new /obj/screen()
+ darksight.icon = null
+ darksight.screen_loc = "1,1"
+ darksight.plane = PLANE_LIGHTING
+ darksight.plane = LIGHTING_LAYER + 0.1
+
nvg = setup_overlay("nvg_hud")
thermal = setup_overlay("thermal_hud")
meson = setup_overlay("meson_hud")
diff --git a/code/modules/lighting/lighting_overlay.dm b/code/modules/lighting/lighting_overlay.dm
index 51451e832a0..094d781cf2b 100644
--- a/code/modules/lighting/lighting_overlay.dm
+++ b/code/modules/lighting/lighting_overlay.dm
@@ -11,7 +11,7 @@
color = LIGHTING_BASE_MATRIX
icon_state = "light1"
auto_init = 0 // doesn't need special init
- blend_mode = BLEND_MULTIPLY
+ blend_mode = BLEND_OVERLAY
var/lum_r = 0
var/lum_g = 0
diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm
index 5a3ff2175c1..bd0c6e1870d 100644
--- a/code/modules/mob/living/carbon/human/species/species.dm
+++ b/code/modules/mob/living/carbon/human/species/species.dm
@@ -161,6 +161,7 @@
var/obj/effect/decal/cleanable/blood/tracks/move_trail = /obj/effect/decal/cleanable/blood/tracks/footprints // What marks are left when walking
var/list/skin_overlays = list()
var/has_floating_eyes = 0 // Whether the eyes can be shown above other icons
+ var/has_glowing_eyes = 0 // Whether the eyes are shown above all lighting
var/water_movement = 0 // How much faster or slower the species is in water
var/snow_movement = 0 // How much faster or slower the species is on snow
diff --git a/code/modules/mob/living/carbon/human/species/station/traits_vr/neutral.dm b/code/modules/mob/living/carbon/human/species/station/traits_vr/neutral.dm
index 6eb0d9b6a77..ee849fb7216 100644
--- a/code/modules/mob/living/carbon/human/species/station/traits_vr/neutral.dm
+++ b/code/modules/mob/living/carbon/human/species/station/traits_vr/neutral.dm
@@ -94,3 +94,18 @@
desc = "Allows you to dispose of the snack wrappings on the go instead of having to look for a bin or littering like an animal."
cost = 0
var_changes = list("trashcan" = 1)
+
+/datum/trait/glowing_eyes
+ name = "Glowing Eyes"
+ desc = "Your eyes show up above darkness. SPOOKY! And kinda edgey too."
+ cost = 0
+ var_changes = list("has_glowing_eyes" = 1)
+
+/datum/trait/glowing_body
+ name = "Glowing Body"
+ desc = "Your body glows about as much as a PDA light! Settable color and toggle in Abilities tab ingame."
+ cost = 0
+/datum/trait/glowing_body/apply(var/datum/species/S,var/mob/living/carbon/human/H)
+ ..(S,H)
+ H.verbs |= /mob/living/proc/glow_toggle
+ H.verbs |= /mob/living/proc/glow_color
diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm
index 26c40200571..8dc1a6a4478 100644
--- a/code/modules/mob/living/carbon/human/update_icons.dm
+++ b/code/modules/mob/living/carbon/human/update_icons.dm
@@ -125,19 +125,20 @@ Please contact me on #coderbus IRC. ~Carn x
#define BACK_LAYER 17
#define HAIR_LAYER 18 //TODO: make part of head layer?
#define EARS_LAYER 19
-#define FACEMASK_LAYER 20
-#define HEAD_LAYER 21
-#define COLLAR_LAYER 22
-#define HANDCUFF_LAYER 23
-#define LEGCUFF_LAYER 24
-#define L_HAND_LAYER 25
-#define R_HAND_LAYER 26
-#define MODIFIER_EFFECTS_LAYER 27
-#define FIRE_LAYER 28 //If you're on fire
-#define WATER_LAYER 29 //If you're submerged in water.
-#define TARGETED_LAYER 30 //BS12: Layer for the target overlay from weapon targeting system
-#define WING_LAYER 31 //VOREStation edit. Simply move this up a number if things are added.
-#define TOTAL_LAYERS 31 //VOREStation edit.
+#define EYES_LAYER 20
+#define FACEMASK_LAYER 21
+#define HEAD_LAYER 22
+#define COLLAR_LAYER 23
+#define HANDCUFF_LAYER 24
+#define LEGCUFF_LAYER 25
+#define L_HAND_LAYER 26
+#define R_HAND_LAYER 27
+#define MODIFIER_EFFECTS_LAYER 28
+#define FIRE_LAYER 29 //If you're on fire
+#define WATER_LAYER 30 //If you're submerged in water.
+#define TARGETED_LAYER 31 //BS12: Layer for the target overlay from weapon targeting system
+#define WING_LAYER 32 //VOREStation edit. Simply move this up a number if things are added.
+#define TOTAL_LAYERS 32 //VOREStation edit.
//////////////////////////////////
/mob/living/carbon/human
@@ -483,6 +484,7 @@ var/global/list/damage_icon_parts = list()
//Reset our hair
overlays_standing[HAIR_LAYER] = null
+ update_eyes(0) //Pirated out of here, for glowing eyes.
var/obj/item/organ/external/head/head_organ = get_organ(BP_HEAD)
if(!head_organ || head_organ.is_stump() )
@@ -527,9 +529,50 @@ var/global/list/damage_icon_parts = list()
face_standing += rgb(,,,120)
overlays_standing[HAIR_LAYER] = image(face_standing)
-
if(update_icons) update_icons_layers()
+/mob/living/carbon/human/update_eyes(var/update_icons=1)
+ if(QDESTROYING(src))
+ return
+
+ //Reset our eyes
+ overlays_standing[EYES_LAYER] = null
+
+ //This is ONLY for glowing eyes for now. Boring flat eyes are done by the head's own proc.
+ if(!species.has_glowing_eyes)
+ if(update_icons) update_icons_layers()
+ return
+
+ //Our glowy eyes should be hidden if some equipment hides them.
+ if(!should_have_organ(O_EYES) || (head && (head.flags_inv & BLOCKHAIR)) || (wear_mask && (wear_mask.flags_inv & BLOCKHAIR)))
+ if(update_icons) update_icons_layers()
+ return
+
+ //Get the head, we'll need it later.
+ var/obj/item/organ/external/head/head_organ = get_organ(BP_HEAD)
+ if(!head_organ || head_organ.is_stump() )
+ if(update_icons) update_icons_layers()
+ return
+
+ //The eyes store the color themselves, funny enough.
+ var/obj/item/organ/internal/eyes/eyes = internal_organs_by_name[O_EYES]
+ if(!head_organ.eye_icon)
+ if(update_icons) update_icons_layers()
+ return
+
+ var/icon/eyes_icon = new/icon(head_organ.eye_icon_location, head_organ.eye_icon)
+ if(eyes)
+ eyes_icon.Blend(rgb(eyes.eye_colour[1], eyes.eye_colour[2], eyes.eye_colour[3]), ICON_ADD)
+ else
+ eyes_icon.Blend(rgb(128,0,0), ICON_ADD)
+
+ var/image/eyes_image = image(eyes_icon)
+ eyes_image.plane = PLANE_LIGHTING_ABOVE
+
+ overlays_standing[EYES_LAYER] = eyes_image
+
+ if(update_icons) update_icons_layers()
+
/mob/living/carbon/human/update_mutations(var/update_icons=1)
if(QDESTROYING(src))
return
diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm
index e8ce8080a37..48aec984fb7 100644
--- a/code/modules/mob/living/life.dm
+++ b/code/modules/mob/living/life.dm
@@ -175,6 +175,7 @@
..()
handle_vision()
+ handle_darksight()
handle_hud_icons()
return 1
@@ -207,7 +208,36 @@
set_light(min(round(fire_stacks), 3), round(fire_stacks), l_color = "#FF9933")
return TRUE
+ //VOREStation Add - Glowy trait
+ else if(glow_toggle)
+ set_light(2, l_color = glow_color) //2 is PDA brightness, so neutral in terms of balance
+ //VOREStation Add End
+
else
set_light(0)
return FALSE
+/mob/living/proc/handle_darksight()
+ var/darksightedness = min(see_in_dark/world.view,1.0) //A ratio of how good your darksight is, from 'nada' to 'really darn good'
+ var/current = dsoverlay.alpha/255 //Our current adjustedness
+
+ var/brightness = 0.0 //We'll assume it's superdark if we can't find something else.
+
+ if(isturf(loc))
+ var/turf/T = loc //Will be true 99% of the time, thus avoiding the whole elif chain
+ brightness = T.get_lumcount()
+
+ //Snowflake treatment of potential locations
+ else if(istype(loc,/obj/mecha)) //I imagine there's like displays and junk in there. Use the lights!
+ brightness = 1
+ else if(istype(loc,/obj/item/weapon/holder)) //Poor carried teshari and whatnot should adjust appropriately
+ var/turf/T = get_turf(src)
+ brightness = T.get_lumcount()
+
+ var/darkness = 1-brightness //Silly, I know, but 'alpha' and 'darkness' go the same direction on a number line
+ var/adjust_to = min(darkness,darksightedness)//Capped by how darksighted they are
+ var/distance = abs(current-adjust_to) //Used for how long to animate for
+ if(distance < 0.01) return //We're already all set
+
+ //world << "[src] in B:[round(brightness,0.1)] C:[round(current,0.1)] A2:[round(adjust_to,0.1)] D:[round(distance,0.01)] T:[round(distance*10 SECONDS,0.1)]"
+ animate(dsoverlay, alpha = (adjust_to*255), time = (distance*10 SECONDS))
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index f100d55cbd9..440489f568d 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -1,3 +1,20 @@
+/mob/living/New()
+ ..()
+
+ //I'll just hang my coat up over here
+ dsoverlay = image('icons/mob/darksight.dmi',global_hud.darksight) //This is a secret overlay! Go look at the file, you'll see.
+ var/mutable_appearance/dsma = new(dsoverlay) //Changing like ten things, might as well.
+ dsma.alpha = 0
+ dsma.plane = PLANE_LIGHTING
+ dsma.layer = LIGHTING_LAYER + 0.1
+ dsma.blend_mode = BLEND_ADD
+ dsoverlay.appearance = dsma
+
+/mob/living/Destroy()
+ dsoverlay.loc = null //I'll take my coat with me
+ dsoverlay = null
+ return ..()
+
//mob verbs are faster than object verbs. See mob/verb/examine.
/mob/living/verb/pulled(atom/movable/AM as mob|obj in oview(1))
set name = "Pull"
diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm
index d8913e7b5b8..4226da2cd21 100644
--- a/code/modules/mob/living/living_defines.dm
+++ b/code/modules/mob/living/living_defines.dm
@@ -47,3 +47,4 @@
var/evasion = 0 // Makes attacks harder to land. Each number equals 15% more likely to miss. Negative numbers increase hit chance.
var/force_max_speed = 0 // If 1, the mob runs extremely fast and cannot be slowed.
+ var/image/dsoverlay = null //Overlay used for darksight eye adjustments
\ No newline at end of file
diff --git a/code/modules/mob/living/login.dm b/code/modules/mob/living/login.dm
index b41baabef97..275e88be086 100644
--- a/code/modules/mob/living/login.dm
+++ b/code/modules/mob/living/login.dm
@@ -6,4 +6,6 @@
mind.active = 1 //indicates that the mind is currently synced with a client
//If they're SSD, remove it so they can wake back up.
update_antag_icons(mind)
+ client.screen |= global_hud.darksight
+ client.images |= dsoverlay
return .
diff --git a/code/modules/mob/mob_planes.dm b/code/modules/mob/mob_planes.dm
index 25c494c2e80..a307a291e40 100644
--- a/code/modules/mob/mob_planes.dm
+++ b/code/modules/mob/mob_planes.dm
@@ -12,6 +12,7 @@
//It'd be nice to lazy init these but some of them are important to just EXIST. Like without ghost planemaster, you can see ghosts. Go figure.
plane_masters[VIS_FULLBRIGHT] = new /obj/screen/plane_master/fullbright //Lighting system (lighting_overlay objects)
+ plane_masters[VIS_LIGHTING] = new /obj/screen/plane_master/lighting //Lighting system (but different!)
plane_masters[VIS_GHOSTS] = new /obj/screen/plane_master/ghosts //Ghosts!
plane_masters[VIS_AI_EYE] = new /obj/screen/plane_master{plane = PLANE_AI_EYE} //AI Eye!
@@ -129,12 +130,17 @@
//Lighting is weird and has matrix shenanigans. Think of this as turning on/off darkness.
/obj/screen/plane_master/fullbright
plane = PLANE_LIGHTING
- layer = LIGHTING_LAYER
+ layer = LIGHTING_LAYER+1
color = null //To break lighting when visible (this is sorta backwards)
- alpha = 255 //Starts full opaque
- invisibility = 101 //But invisible
+ alpha = 0 //Starts full opaque
+ invisibility = 101
invis_toggle = TRUE
+/obj/screen/plane_master/lighting
+ plane = PLANE_LIGHTING
+ blend_mode = BLEND_MULTIPLY
+ alpha = 255
+
/////////////////
//Ghosts has a special alpha level
/obj/screen/plane_master/ghosts
diff --git a/code/modules/vore/eating/living_vr.dm b/code/modules/vore/eating/living_vr.dm
index 7c4d5004f1a..53e97793a84 100644
--- a/code/modules/vore/eating/living_vr.dm
+++ b/code/modules/vore/eating/living_vr.dm
@@ -21,6 +21,8 @@
var/absorbing_prey = 0 // Determines if the person is using the succubus drain or not. See station_special_abilities_vr.
var/drain_finalized = 0 // Determines if the succubus drain will be KO'd/absorbed. Can be toggled on at any time.
var/fuzzy = 1 // Preference toggle for sharp/fuzzy icon.
+ var/glow_toggle = 0 // If they're glowing!
+ var/glow_color = "#FFFFFF" // The color they're glowing!
//
// Hook for generic creation of stuff on new creatures
@@ -565,4 +567,25 @@
msg_admin_attack("[key_name(pred)] ate [key_name(prey)] via dropnom/slime feeding!. ([pred ? "JMP" : "null"])")
else
msg_admin_attack("[key_name(user)] forced [key_name(pred)] to eat [key_name(prey)] via dropnoms/slime feeding!! ([pred ? "JMP" : "null"])")
- return 1
\ No newline at end of file
+
+/mob/living/proc/glow_toggle()
+ set name = "Glow (Toggle)"
+ set category = "Abilities"
+ set desc = "Toggle your glowing on/off!"
+
+ //I don't really see a point to any sort of checking here.
+ //If they're passed out, the light won't help them. Same with buckled. Really, I think it's fine to do this whenever.
+ glow_toggle = !glow_toggle
+
+ to_chat(src,"You [glow_toggle ? "en" : "dis"]able your body's glow.")
+
+/mob/living/proc/glow_color()
+ set name = "Glow (Set Color)"
+ set category = "Abilities"
+ set desc = "Pick a color for your body's glow."
+
+ //Again, no real need for a check on this. I'm unsure how it could be somehow abused.
+ //Even if they open the box 900 times, who cares, they get the wrong color and do it again.
+ var/new_color = input(src,"Select a new color","Body Glow",glow_color) as color
+ if(new_color)
+ glow_color = new_color
diff --git a/icons/mob/darksight.dmi b/icons/mob/darksight.dmi
new file mode 100644
index 00000000000..07524534225
Binary files /dev/null and b/icons/mob/darksight.dmi differ