diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm
index a7e78e2c26..f244d3c64c 100644
--- a/code/__DEFINES/traits.dm
+++ b/code/__DEFINES/traits.dm
@@ -243,6 +243,8 @@
#define TRAIT_SPEC(spec_type) "t_spec_[spec_type]"
/// If the mob won't drop items held in face slot when downed
#define TRAIT_IRON_TEETH "t_iron_teeth"
+/// If the mob won't drop items held in face slot when downed
+#define TRAIT_HUD_SIGHT "t_hud_sight"
// -- ability traits --
/// Xenos with this trait cannot have plasma transfered to them
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index 36dcef935f..0232bdca5b 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -834,3 +834,11 @@ Parameters are passed from New.
var/refid = REF(src)
. += "[VV_HREF_TARGETREF(refid, VV_HK_AUTO_RENAME, "[src]")]"
. += "
<< [dir2text(dir) || dir] >>"
+
+/atom/MouseEntered(location, control, params)
+ if(usr.face_mouse)
+ usr.face_atom(src)
+
+/atom/MouseExited(location, control, params)
+ if(usr.face_mouse)
+ usr.face_atom(src)
diff --git a/code/game/objects/items/devices/helmet_visors.dm b/code/game/objects/items/devices/helmet_visors.dm
index 6987715121..997d65b2a7 100644
--- a/code/game/objects/items/devices/helmet_visors.dm
+++ b/code/game/objects/items/devices/helmet_visors.dm
@@ -61,13 +61,15 @@
/// Called by toggle_visor() to activate the visor's effects
/obj/item/device/helmet_visor/proc/activate_visor(obj/item/clothing/head/helmet/marine/attached_helmet, mob/living/carbon/human/user)
- var/datum/mob_hud/current_mob_hud = GLOB.huds[hud_type]
- current_mob_hud.add_hud_to(user, attached_helmet)
+ if(isnull(GLOB.huds[hud_type]?.hudusers[user]))
+ var/datum/mob_hud/current_mob_hud = GLOB.huds[hud_type]
+ current_mob_hud.add_hud_to(user, attached_helmet)
/// Called by toggle_visor() to deactivate the visor's effects
/obj/item/device/helmet_visor/proc/deactivate_visor(obj/item/clothing/head/helmet/marine/attached_helmet, mob/living/carbon/human/user)
- var/datum/mob_hud/current_mob_hud = GLOB.huds[hud_type]
- current_mob_hud.remove_hud_from(user, attached_helmet)
+ if(!isnull(GLOB.huds[hud_type]?.hudusers[user]))
+ var/datum/mob_hud/current_mob_hud = GLOB.huds[hud_type]
+ current_mob_hud.remove_hud_from(user, attached_helmet)
/// Called by /obj/item/clothing/head/helmet/marine/get_examine_text(mob/user) to get extra examine text for this visor
/obj/item/device/helmet_visor/proc/get_helmet_examine_text()
@@ -333,3 +335,26 @@
/obj/item/device/helmet_visor/night_vision/marine_raider/process(delta_time)
return PROCESS_KILL
+
+/obj/item/device/helmet_visor/sight
+ name = "sight optic"
+ desc = "A standard M10 pattern helmet optic that grants its user point and shoot capabilities and provides tactical squad HUD display."
+
+/obj/item/device/helmet_visor/sight/activate_visor(obj/item/clothing/head/helmet/marine/attached_helmet, mob/living/carbon/human/user)
+ . = ..()
+
+ user.client.mouse_pointer_icon = 'icons/effects/cursors/aim_reticle.dmi'
+ user.client.color = "#FDE8D9"
+ user.overlay_fullscreen("optic", /atom/movable/screen/fullscreen/flash/noise/nvg)
+ ADD_TRAIT(user, TRAIT_HUD_SIGHT, src)
+ user.face_mouse = TRUE
+
+
+/obj/item/device/helmet_visor/sight/deactivate_visor(obj/item/clothing/head/helmet/marine/attached_helmet, mob/living/carbon/human/user)
+ . = ..()
+
+ user.client.mouse_pointer_icon = initial(user.client.mouse_pointer_icon)
+ user.client.color = initial(user.client.color)
+ user.clear_fullscreen("optic", 0.5 SECONDS)
+ REMOVE_TRAIT(user, TRAIT_HUD_SIGHT, src)
+ user.face_mouse = FALSE
diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm
index caa38d8888..f56e8a7dd4 100644
--- a/code/modules/clothing/head/helmet.dm
+++ b/code/modules/clothing/head/helmet.dm
@@ -406,7 +406,7 @@ GLOBAL_LIST_INIT(allowed_helmet_items, list(
var/helmet_overlay_icon = 'icons/mob/humans/onmob/head_1.dmi'
///Any visors built into the helmet
- var/list/built_in_visors = list(new /obj/item/device/helmet_visor)
+ var/list/built_in_visors = list(new /obj/item/device/helmet_visor/sight)
///Any visors that have been added into the helmet
var/list/inserted_visors = list()
@@ -706,11 +706,6 @@ GLOBAL_LIST_INIT(allowed_helmet_items, list(
if(length(total_visors) > iterator)
var/obj/item/device/helmet_visor/next_visor = total_visors[iterator + 1]
- if(!isnull(GLOB.huds[next_visor.hud_type]?.hudusers[user]))
- iterator++
- skipped_hud = TRUE
- continue
-
if(!next_visor.can_toggle(user))
iterator++
skipped_hud = TRUE
@@ -727,8 +722,6 @@ GLOBAL_LIST_INIT(allowed_helmet_items, list(
iterator++
for(var/obj/item/device/helmet_visor/new_visor in total_visors)
- if(!isnull(GLOB.huds[new_visor.hud_type]?.hudusers[user]))
- continue
if(!new_visor.can_toggle(user))
continue
@@ -774,7 +767,7 @@ GLOBAL_LIST_INIT(allowed_helmet_items, list(
desc = "A modified M10 marine helmet for ComTechs. Features a toggleable welding screen for eye protection."
icon_state = "tech_helmet"
specialty = "M10 technician"
- built_in_visors = list(new /obj/item/device/helmet_visor, new /obj/item/device/helmet_visor/welding_visor)
+ built_in_visors = list(new /obj/item/device/helmet_visor/sight, new /obj/item/device/helmet_visor/welding_visor)
/obj/item/clothing/head/helmet/marine/grey
desc = "A standard M10 Pattern Helmet. This one has not had a camouflage pattern applied to it yet. There is a built-in camera on the right side."
@@ -808,14 +801,14 @@ GLOBAL_LIST_INIT(allowed_helmet_items, list(
flags_inventory = BLOCKSHARPOBJ
flags_inv_hide = HIDEEARS|HIDETOPHAIR
specialty = "M50 tanker"
- built_in_visors = list(new /obj/item/device/helmet_visor, new /obj/item/device/helmet_visor/welding_visor/tanker)
+ built_in_visors = list(new /obj/item/device/helmet_visor/sight, new /obj/item/device/helmet_visor/welding_visor/tanker)
/obj/item/clothing/head/helmet/marine/medic
name = "\improper M10 corpsman helmet"
desc = "M10 combat helmet issued to marine hospital corpsmen. Has a red cross painted on its front for attracting the injured and snipers' attentions alike."
icon_state = "med_helmet"
specialty = "M10 pattern medic"
- built_in_visors = list(new /obj/item/device/helmet_visor, new /obj/item/device/helmet_visor/medical/advanced)
+ built_in_visors = list(new /obj/item/device/helmet_visor/sight, new /obj/item/device/helmet_visor/medical/advanced)
start_down_visor_type = /obj/item/device/helmet_visor/medical/advanced
/obj/item/clothing/head/helmet/marine/medic/white
@@ -965,7 +958,7 @@ GLOBAL_LIST_INIT(allowed_helmet_items, list(
armor_bio = CLOTHING_ARMOR_MEDIUMHIGH
specialty = "M10 pattern captain"
flags_atom = NO_SNOW_TYPE
- built_in_visors = list(new /obj/item/device/helmet_visor, new /obj/item/device/helmet_visor/medical/advanced, new /obj/item/device/helmet_visor/security)
+ built_in_visors = list(new /obj/item/device/helmet_visor/sight, new /obj/item/device/helmet_visor/medical/advanced, new /obj/item/device/helmet_visor/security)
/obj/item/clothing/head/helmet/marine/MP
name = "\improper M10 pattern MP helmet"
@@ -989,7 +982,7 @@ GLOBAL_LIST_INIT(allowed_helmet_items, list(
icon_state = "helmet"
item_state = "helmet"
specialty = "M10 pattern officer"
- built_in_visors = list(new /obj/item/device/helmet_visor, new /obj/item/device/helmet_visor/medical/advanced)
+ built_in_visors = list(new /obj/item/device/helmet_visor/sight, new /obj/item/device/helmet_visor/medical/advanced)
/obj/item/clothing/head/helmet/marine/mp/provost/marshal
name = "\improper Provost Marshal Cap"
diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm
index c04a745ea1..b08bcd78e6 100644
--- a/code/modules/mob/mob_defines.dm
+++ b/code/modules/mob/mob_defines.dm
@@ -265,6 +265,8 @@
// contains /atom/movable/screen/alert only
var/list/alerts = list()
+ var/face_mouse = FALSE
+
/mob/vv_get_dropdown()
. = ..()
VV_DROPDOWN_OPTION(VV_HK_EXPLODE, "Trigger Explosion")
diff --git a/code/modules/movement/movement.dm b/code/modules/movement/movement.dm
index 35dbb44481..e72e638992 100644
--- a/code/modules/movement/movement.dm
+++ b/code/modules/movement/movement.dm
@@ -64,8 +64,15 @@
var/old_dir = dir
. = ..()
+
if (flags_atom & DIRLOCK)
setDir(old_dir)
+
+ else if(ismob(src))
+ var/mob/mob = src
+ if(mob.face_mouse)
+ setDir(old_dir)
+
else if(old_dir != direct)
setDir(direct)
l_move_time = world.time
diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm
index 50e735b918..e06e15adec 100644
--- a/code/modules/projectiles/gun.dm
+++ b/code/modules/projectiles/gun.dm
@@ -1706,6 +1706,8 @@ not all weapons use normal magazines etc. load_into_chamber() itself is designed
skill_accuracy = -1
else
skill_accuracy = user.skills.get_skill_level(SKILL_FIREARMS)
+ if(HAS_TRAIT(user, TRAIT_HUD_SIGHT))
+ skill_accuracy += 1
if(skill_accuracy)
gun_accuracy_mult += skill_accuracy * HIT_ACCURACY_MULT_TIER_3 // Accuracy mult increase/decrease per level is equal to attaching/removing a red dot sight
diff --git a/icons/effects/cursors/aim_reticle.dmi b/icons/effects/cursors/aim_reticle.dmi
new file mode 100644
index 0000000000..10f4e3871f
Binary files /dev/null and b/icons/effects/cursors/aim_reticle.dmi differ
diff --git a/icons/mob/humans/onmob/helmet_garb.dmi b/icons/mob/humans/onmob/helmet_garb.dmi
index cd225f4bdb..cc1237a12c 100644
Binary files a/icons/mob/humans/onmob/helmet_garb.dmi and b/icons/mob/humans/onmob/helmet_garb.dmi differ
diff --git a/icons/obj/items/clothing/helmet_visors.dmi b/icons/obj/items/clothing/helmet_visors.dmi
index f47bc9aa26..a36acb79a8 100644
Binary files a/icons/obj/items/clothing/helmet_visors.dmi and b/icons/obj/items/clothing/helmet_visors.dmi differ