diff --git a/code/__DEFINES/mob_hud.dm b/code/__DEFINES/mob_hud.dm
index 2704e52d2f85..02f992694832 100644
--- a/code/__DEFINES/mob_hud.dm
+++ b/code/__DEFINES/mob_hud.dm
@@ -65,3 +65,6 @@
#define TRACKER_HIVE "Hive Core"
#define TRACKER_LEADER "Leader"
#define TRACKER_TUNNEL "Tunnel"
+
+//These are used to manage the same HUD having multiple sources
+#define HUD_SOURCE_ADMIN "admin"
diff --git a/code/datums/mob_hud.dm b/code/datums/mob_hud.dm
index aa1bc9b40783..65c5a47896fa 100644
--- a/code/datums/mob_hud.dm
+++ b/code/datums/mob_hud.dm
@@ -30,10 +30,18 @@ var/list/datum/mob_hud/huds = list(
// Stop displaying a HUD to a specific person
// (took off medical glasses)
-/datum/mob_hud/proc/remove_hud_from(mob/user)
+/datum/mob_hud/proc/remove_hud_from(mob/user, source)
+ if(length(hudusers[user]) && (source in hudusers[user]))
+ hudusers[user] -= source
+
+ if(length(hudusers[user]))
+ return FALSE
+
for(var/mob/target in hudmobs)
remove_from_single_hud(user, target)
+
hudusers -= user
+ return TRUE
// Stop rendering a HUD on a target
// "unenroll" them so to speak
@@ -53,8 +61,24 @@ var/list/datum/mob_hud/huds = list(
user.client.images -= target.clone.hud_list[i]
// Allow user to view a HUD (putting on medical glasses)
-/datum/mob_hud/proc/add_hud_to(mob/user)
+/datum/mob_hud/proc/add_hud_to(mob/user, source)
hudusers |= user
+ if(hudusers[user])
+ hudusers[user] |= list(source)
+ else
+ hudusers[user] += list(source)
+
+ for(var/mob/target in hudmobs)
+ add_to_single_hud(user, target)
+
+/// Refreshes the HUD, adding user and sources if missing and then calls to add the HUD
+/datum/mob_hud/proc/refresh_hud(mob/user, list/source)
+ hudusers |= user
+ if(hudusers[user])
+ hudusers[user] |= source
+ else
+ hudusers[user] += source
+
for(var/mob/target in hudmobs)
add_to_single_hud(user, target)
@@ -229,13 +253,13 @@ var/list/datum/mob_hud/huds = list(
for(var/datum/mob_hud/hud in huds)
if(istype(hud, /datum/mob_hud/xeno))
hud.remove_from_hud(src)
- hud.remove_hud_from(src)
+ hud.remove_hud_from(src, src)
else if (istype(hud, /datum/mob_hud/xeno_infection))
- hud.remove_hud_from(src)
+ hud.remove_hud_from(src, src)
if (xeno_hostile_hud)
xeno_hostile_hud = FALSE
var/datum/mob_hud/hostile_hud = huds[MOB_HUD_XENO_HOSTILE]
- hostile_hud.remove_hud_from(src)
+ hostile_hud.remove_hud_from(src, src)
@@ -243,13 +267,7 @@ var/list/datum/mob_hud/huds = list(
var/mob/M = source_mob ? source_mob : src
for(var/datum/mob_hud/hud in huds)
if(M in hud.hudusers)
- readd_hud(hud)
-
-/mob/proc/readd_hud(datum/mob_hud/hud)
- hud.add_hud_to(src)
-
-
-
+ hud.refresh_hud(src, hud.hudusers[M])
//Medical HUDs
diff --git a/code/game/machinery/vending/vendor_types/crew/vehicle_crew.dm b/code/game/machinery/vending/vendor_types/crew/vehicle_crew.dm
index fb9b662be1bc..891a2a907b39 100644
--- a/code/game/machinery/vending/vendor_types/crew/vehicle_crew.dm
+++ b/code/game/machinery/vending/vendor_types/crew/vehicle_crew.dm
@@ -306,7 +306,7 @@ GLOBAL_LIST_INIT(cm_vending_clothing_vehicle_crew, list(
list("Gloves", 0, /obj/item/clothing/gloves/yellow, MARINE_CAN_BUY_GLOVES, VENDOR_ITEM_MANDATORY),
list("Tanker Armor", 0, /obj/item/clothing/suit/storage/marine/tanker, MARINE_CAN_BUY_ARMOR, VENDOR_ITEM_MANDATORY),
list("M50 Tanker Helmet", 0, /obj/item/clothing/head/helmet/marine/tech/tanker, MARINE_CAN_BUY_HELMET, VENDOR_ITEM_MANDATORY),
- list("SensorMate HUD", 0, /obj/item/clothing/glasses/hud/sensor, MARINE_CAN_BUY_GLASSES, VENDOR_ITEM_MANDATORY),
+ list("Medical Helmet Optic", 0, /obj/item/device/helmet_visor/medical, MARINE_CAN_BUY_GLASSES, VENDOR_ITEM_MANDATORY),
list("Welding Kit", 0, /obj/item/tool/weldpack, MARINE_CAN_BUY_BACKPACK, VENDOR_ITEM_MANDATORY),
list("MRE", 0, /obj/item/storage/box/MRE, MARINE_CAN_BUY_MRE, VENDOR_ITEM_MANDATORY),
diff --git a/code/game/machinery/vending/vendor_types/intelligence_officer.dm b/code/game/machinery/vending/vendor_types/intelligence_officer.dm
index a2afe897b495..1f5bb1fda024 100644
--- a/code/game/machinery/vending/vendor_types/intelligence_officer.dm
+++ b/code/game/machinery/vending/vendor_types/intelligence_officer.dm
@@ -15,7 +15,7 @@ GLOBAL_LIST_INIT(cm_vending_gear_intelligence_officer, list(
list("Motion Detector", 15, /obj/item/device/motiondetector, null, VENDOR_ITEM_RECOMMENDED),
list("Plastic Explosive", 10, /obj/item/explosive/plastic, null, VENDOR_ITEM_REGULAR),
list("Welding Goggles", 5, /obj/item/clothing/glasses/welding, null, VENDOR_ITEM_REGULAR),
- list("Sensor Medical HUD", 5, /obj/item/clothing/glasses/hud/sensor, null, VENDOR_ITEM_REGULAR),
+ list("Medical Helmet Optic", 5, /obj/item/device/helmet_visor/medical, null, VENDOR_ITEM_REGULAR),
list("POUCHES", 0, null, null, null),
list("Large Magazine Pouch", 10, /obj/item/storage/pouch/magazine/large, null, VENDOR_ITEM_REGULAR),
diff --git a/code/game/machinery/vending/vendor_types/squad_prep/squad_engineer.dm b/code/game/machinery/vending/vendor_types/squad_prep/squad_engineer.dm
index faff01f7f299..d43e53db4f0d 100644
--- a/code/game/machinery/vending/vendor_types/squad_prep/squad_engineer.dm
+++ b/code/game/machinery/vending/vendor_types/squad_prep/squad_engineer.dm
@@ -54,7 +54,7 @@ GLOBAL_LIST_INIT(cm_vending_gear_engi, list(
list("M56D Heavy Machine Gun", 24, /obj/item/storage/box/guncase/m56d, null, VENDOR_ITEM_REGULAR),
list("UTILITIES", 0, null, null, null),
- list("SensorMate Medical HUD", 12, /obj/item/clothing/glasses/hud/sensor, null, VENDOR_ITEM_REGULAR),
+ list("Medical Helmet Optic", 12, /obj/item/device/helmet_visor/medical, null, VENDOR_ITEM_REGULAR),
list("Roller Bed", 5, /obj/item/roller, null, VENDOR_ITEM_REGULAR),
list("Fulton Device Stack", 5, /obj/item/stack/fulton, null, VENDOR_ITEM_REGULAR),
list("M3 B12 Pattern Armor", 24, /obj/item/clothing/suit/storage/marine/leader, null, VENDOR_ITEM_REGULAR),
diff --git a/code/game/machinery/vending/vendor_types/squad_prep/squad_leader.dm b/code/game/machinery/vending/vendor_types/squad_prep/squad_leader.dm
index 9757576e6d0b..935469b13b47 100644
--- a/code/game/machinery/vending/vendor_types/squad_prep/squad_leader.dm
+++ b/code/game/machinery/vending/vendor_types/squad_prep/squad_leader.dm
@@ -67,7 +67,7 @@ GLOBAL_LIST_INIT(cm_vending_gear_leader, list(
list("Injector (Tricord)", 1, /obj/item/reagent_container/hypospray/autoinjector/tricord, null, VENDOR_ITEM_REGULAR),
list("Health Analyzer", 4, /obj/item/device/healthanalyzer, null, VENDOR_ITEM_REGULAR),
- list("SensorMate Medical HUD", 4, /obj/item/clothing/glasses/hud/sensor, null, VENDOR_ITEM_RECOMMENDED),
+ list("Medical Helmet Optic", 4, /obj/item/device/helmet_visor/medical, null, VENDOR_ITEM_RECOMMENDED),
list("Roller Bed", 2, /obj/item/roller, null, VENDOR_ITEM_REGULAR),
list("SPECIAL AMMUNITION", 0, null, null, null),
diff --git a/code/game/machinery/vending/vendor_types/squad_prep/squad_medic.dm b/code/game/machinery/vending/vendor_types/squad_prep/squad_medic.dm
index 7c9682985298..d2ba88096131 100644
--- a/code/game/machinery/vending/vendor_types/squad_prep/squad_medic.dm
+++ b/code/game/machinery/vending/vendor_types/squad_prep/squad_medic.dm
@@ -42,7 +42,6 @@ GLOBAL_LIST_INIT(cm_vending_gear_medic, list(
list("MEDICAL UTILITIES", 0, null, null, null),
list("Health Analyzer", 4, /obj/item/device/healthanalyzer, null, VENDOR_ITEM_REGULAR),
- list("Medical HUD Glasses", 4, /obj/item/clothing/glasses/hud/health, null, VENDOR_ITEM_REGULAR),
list("Roller Bed", 4, /obj/item/roller, null, VENDOR_ITEM_REGULAR),
list("Stasis Bag", 6, /obj/item/bodybag/cryobag, null, VENDOR_ITEM_REGULAR),
list("Pressurized Reagent Canister Pouch (EMPTY)", 3, /obj/item/storage/pouch/pressurized_reagent_canister, null, VENDOR_ITEM_REGULAR),
@@ -110,7 +109,6 @@ GLOBAL_LIST_INIT(cm_vending_clothing_medic, list(
list("Boots", 0, /obj/item/clothing/shoes/marine/knife, MARINE_CAN_BUY_SHOES, VENDOR_ITEM_MANDATORY),
list("Uniform", 0, /obj/item/clothing/under/marine/medic, MARINE_CAN_BUY_UNIFORM, VENDOR_ITEM_MANDATORY),
list("Gloves", 0, /obj/item/clothing/gloves/marine, MARINE_CAN_BUY_GLOVES, VENDOR_ITEM_MANDATORY),
- list("Medical HUD Glasses", 0, /obj/item/clothing/glasses/hud/health, MARINE_CAN_BUY_GLASSES, VENDOR_ITEM_MANDATORY),
list("Headset", 0, /obj/item/device/radio/headset/almayer/marine, MARINE_CAN_BUY_EAR, VENDOR_ITEM_MANDATORY),
list("Helmet", 0, /obj/item/clothing/head/helmet/marine/medic, MARINE_CAN_BUY_HELMET, VENDOR_ITEM_MANDATORY),
list("MRE", 0, /obj/item/storage/box/MRE, MARINE_CAN_BUY_MRE, VENDOR_ITEM_MANDATORY),
diff --git a/code/game/machinery/vending/vendor_types/squad_prep/squad_rifleman.dm b/code/game/machinery/vending/vendor_types/squad_prep/squad_rifleman.dm
index d92eaabf52c1..09881536901e 100644
--- a/code/game/machinery/vending/vendor_types/squad_prep/squad_rifleman.dm
+++ b/code/game/machinery/vending/vendor_types/squad_prep/squad_rifleman.dm
@@ -76,7 +76,7 @@ GLOBAL_LIST_INIT(cm_vending_clothing_marine, list(
list("Brown Webbing Vest", 15, /obj/item/clothing/accessory/storage/black_vest/brown_vest, null, VENDOR_ITEM_REGULAR),
list("Black Webbing Vest", 15, /obj/item/clothing/accessory/storage/black_vest, null, VENDOR_ITEM_REGULAR),
list("Drop Pouch", 15, /obj/item/clothing/accessory/storage/droppouch, null, VENDOR_ITEM_REGULAR),
- list("SensorMate Medical HUD", 15, /obj/item/clothing/glasses/hud/sensor, null, VENDOR_ITEM_REGULAR),
+ list("Medical Helmet Optic", 15, /obj/item/device/helmet_visor/medical, null, VENDOR_ITEM_REGULAR),
list("Roller Bed", 5, /obj/item/roller, null, VENDOR_ITEM_REGULAR),
list("Fulton Device Stack", 5, /obj/item/stack/fulton, null, VENDOR_ITEM_REGULAR),
list("B12 Pattern Marine Armor", 30, /obj/item/clothing/suit/storage/marine/leader, null, VENDOR_ITEM_REGULAR),
diff --git a/code/game/machinery/vending/vendor_types/squad_prep/squad_smartgunner.dm b/code/game/machinery/vending/vendor_types/squad_prep/squad_smartgunner.dm
index 5560508ca4c1..d3a606ae6b41 100644
--- a/code/game/machinery/vending/vendor_types/squad_prep/squad_smartgunner.dm
+++ b/code/game/machinery/vending/vendor_types/squad_prep/squad_smartgunner.dm
@@ -34,6 +34,7 @@ GLOBAL_LIST_INIT(cm_vending_gear_smartgun, list(
list("Powerloader Certification", 45, /obj/item/pamphlet/skill/powerloader, null, VENDOR_ITEM_REGULAR),
list("Roller Bed", 5, /obj/item/roller, null, VENDOR_ITEM_REGULAR),
list("Fulton Device Stack", 5, /obj/item/stack/fulton, null, VENDOR_ITEM_REGULAR),
+ list("Medical Helmet Optic", 15, /obj/item/device/helmet_visor/medical, null, VENDOR_ITEM_REGULAR),
list("RADIO KEYS", 0, null, null, null),
list("Engineering Radio Encryption Key", 5, /obj/item/device/encryptionkey/engi, null, VENDOR_ITEM_REGULAR),
diff --git a/code/game/machinery/vending/vendor_types/squad_prep/squad_specialist.dm b/code/game/machinery/vending/vendor_types/squad_prep/squad_specialist.dm
index e0900c3fd3c8..b09ae4aa15c5 100644
--- a/code/game/machinery/vending/vendor_types/squad_prep/squad_specialist.dm
+++ b/code/game/machinery/vending/vendor_types/squad_prep/squad_specialist.dm
@@ -38,7 +38,7 @@ GLOBAL_LIST_INIT(cm_vending_gear_spec, list(
list("UTILITIES", 0, null, null, null),
list("Fire Extinguisher (Portable)", 5, /obj/item/tool/extinguisher/mini, null, VENDOR_ITEM_REGULAR),
- list("SensorMate Medical HUD", 15, /obj/item/clothing/glasses/hud/sensor, null, VENDOR_ITEM_REGULAR),
+ list("Medical Helmet Optic", 15, /obj/item/device/helmet_visor/medical, null, VENDOR_ITEM_REGULAR),
list("Roller Bed", 5, /obj/item/roller, null, VENDOR_ITEM_REGULAR),
list("Fulton Device Stack", 5, /obj/item/stack/fulton, null, VENDOR_ITEM_REGULAR),
list("Fuel Tank Strap Pouch", 5, /obj/item/storage/pouch/flamertank, null, VENDOR_ITEM_REGULAR),
diff --git a/code/game/machinery/vending/vendor_types/squad_prep/squad_tl.dm b/code/game/machinery/vending/vendor_types/squad_prep/squad_tl.dm
index ceef80ab6952..7b96b5ee6dcd 100644
--- a/code/game/machinery/vending/vendor_types/squad_prep/squad_tl.dm
+++ b/code/game/machinery/vending/vendor_types/squad_prep/squad_tl.dm
@@ -35,7 +35,7 @@ GLOBAL_LIST_INIT(cm_vending_gear_tl, list(
list("Motion Detector", 15, /obj/item/device/motiondetector, null, VENDOR_ITEM_RECOMMENDED),
list("Plastic Explosive", 10, /obj/item/explosive/plastic, null, VENDOR_ITEM_REGULAR),
list("Breaching Charge", 10, /obj/item/explosive/plastic/breaching_charge, null, VENDOR_ITEM_REGULAR),
- list("SensorMate Medical HUD", 15, /obj/item/clothing/glasses/hud/sensor, null, VENDOR_ITEM_REGULAR),
+ list("Medical Helmet Optic", 15, /obj/item/device/helmet_visor/medical, null, VENDOR_ITEM_REGULAR),
list("M2 Night Vision Goggles", 30, /obj/item/prop/helmetgarb/helmet_nvg, null, VENDOR_ITEM_RECOMMENDED),
list("Roller Bed", 5, /obj/item/roller, null, VENDOR_ITEM_REGULAR),
list("Fulton Device Stack", 5, /obj/item/stack/fulton, null, VENDOR_ITEM_REGULAR),
diff --git a/code/game/objects/items/devices/helmet_visors.dm b/code/game/objects/items/devices/helmet_visors.dm
new file mode 100644
index 000000000000..dd913daf7620
--- /dev/null
+++ b/code/game/objects/items/devices/helmet_visors.dm
@@ -0,0 +1,98 @@
+/obj/item/device/helmet_visor
+ name = "squad optic"
+ desc = "An insertable visor HUD into a standard USCM helmet."
+ icon = 'icons/obj/items/clothing/helmet_visors.dmi'
+ icon_state = "hud_sight"
+ w_class = SIZE_TINY
+
+ ///The type of HUD our visor shows
+ var/hud_type = MOB_HUD_FACTION_USCM
+
+ ///The sound when toggling on the visor
+ var/toggle_on_sound = 'sound/handling/hud_on.ogg'
+
+ ///The sound when toggling off the visor
+ var/toggle_off_sound = 'sound/handling/hud_off.ogg'
+
+ ///The icon name for our helmet's action
+ var/action_icon_string = "hud_sight_down"
+
+ ///The overlay name for when our visor is active
+ var/helmet_overlay = "hud_sight_right"
+
+/// Called to see if the user can even use this visor
+/obj/item/device/helmet_visor/proc/can_toggle(mob/living/carbon/human/user)
+ return TRUE
+
+/// Called to see if this visor is a special non-HUD visor
+/obj/item/device/helmet_visor/proc/visor_function(obj/item/clothing/head/helmet/marine/attached_helmet, mob/living/carbon/human/user, silent = FALSE)
+ if(attached_helmet == user.head && attached_helmet.active_visor == src)
+ var/datum/mob_hud/current_mob_hud = huds[hud_type]
+ current_mob_hud.add_hud_to(user, attached_helmet)
+ if(!silent)
+ to_chat(user, SPAN_NOTICE("You activate [src] on [attached_helmet]."))
+ return TRUE
+
+ var/datum/mob_hud/current_mob_hud = huds[hud_type]
+ current_mob_hud.remove_hud_from(user, attached_helmet)
+ if(!silent)
+ to_chat(user, SPAN_NOTICE("You deactivate [src] on [attached_helmet]."))
+ return TRUE
+
+/obj/item/device/helmet_visor/medical
+ name = "basic medical optic"
+ icon_state = "med_sight"
+ hud_type = MOB_HUD_MEDICAL_ADVANCED
+ action_icon_string = "med_sight_down"
+ helmet_overlay = "med_sight_right"
+
+/obj/item/device/helmet_visor/medical/advanced
+ name = "advanced medical optic"
+ helmet_overlay = "med_sight_left"
+
+/obj/item/device/helmet_visor/medical/advanced/can_toggle(mob/living/carbon/human/user)
+ if(!skillcheck(user, SKILL_MEDICAL, SKILL_MEDICAL_MEDIC))
+ to_chat(user, SPAN_NOTICE("You are not skilled enough to use [src]."))
+ return FALSE
+
+ return TRUE
+
+/obj/item/device/helmet_visor/security
+ name = "security optic"
+ icon_state = "sec_sight"
+ hud_type = MOB_HUD_SECURITY_ADVANCED
+ action_icon_string = "sec_sight_down"
+ helmet_overlay = "sec_sight_right"
+
+/obj/item/device/helmet_visor/welding_visor
+ name = "welding visor"
+ icon_state = "sight_empty"
+ hud_type = null
+ action_icon_string = "blank_hud_sight_down"
+ helmet_overlay = "weld_visor"
+
+/obj/item/device/helmet_visor/welding_visor/visor_function(obj/item/clothing/head/helmet/marine/attached_helmet, mob/living/carbon/human/user, silent = FALSE)
+ if(attached_helmet == user.head && attached_helmet.active_visor == src)
+ attached_helmet.vision_impair = VISION_IMPAIR_MAX
+ attached_helmet.flags_inventory |= COVEREYES|COVERMOUTH
+ attached_helmet.flags_inv_hide |= HIDEEYES|HIDEFACE
+ attached_helmet.eye_protection = EYE_PROTECTION_WELDING
+ user.update_tint()
+ if(!silent)
+ to_chat(user, SPAN_NOTICE("You activate [src] on [attached_helmet]."))
+ return TRUE
+
+ attached_helmet.vision_impair = VISION_IMPAIR_NONE
+ attached_helmet.flags_inventory &= ~(COVEREYES|COVERMOUTH)
+ attached_helmet.flags_inv_hide &= ~(HIDEEYES|HIDEFACE)
+ attached_helmet.eye_protection = EYE_PROTECTION_NONE
+ if(!silent)
+ to_chat(user, SPAN_NOTICE("You deactivate [src] on [attached_helmet]."))
+ user.update_tint()
+ return TRUE
+
+/obj/item/device/helmet_visor/welding_visor/mercenary
+ helmet_overlay = ""
+
+/obj/item/device/helmet_visor/welding_visor/tanker
+ helmet_overlay = "tanker_weld_visor"
diff --git a/code/game/objects/items/devices/radio/headset.dm b/code/game/objects/items/devices/radio/headset.dm
index 7e6b0db056d0..4ab9e19d5ae1 100644
--- a/code/game/objects/items/devices/radio/headset.dm
+++ b/code/game/objects/items/devices/radio/headset.dm
@@ -238,7 +238,7 @@
RegisterSignal(user, COMSIG_HUMAN_SET_UNDEFIBBABLE, PROC_REF(update_minimap_icon))
if(headset_hud_on)
var/datum/mob_hud/H = huds[hud_type]
- H.add_hud_to(user)
+ H.add_hud_to(user, src)
//squad leader locator is no longer invisible on our player HUD.
if(user.mind && (user.assigned_squad || misc_tracking) && user.hud_used && user.hud_used.locate_leader)
user.show_hud_tracker()
@@ -257,7 +257,7 @@
))
if(istype(user) && user.has_item_in_ears(src)) //dropped() is called before the inventory reference is update.
var/datum/mob_hud/H = huds[hud_type]
- H.remove_hud_from(user)
+ H.remove_hud_from(user, src)
//squad leader locator is invisible again
if(user.hud_used && user.hud_used.locate_leader)
user.hide_hud_tracker()
@@ -290,14 +290,14 @@
if(user.has_item_in_ears(src)) //worn
var/datum/mob_hud/H = huds[hud_type]
if(headset_hud_on)
- H.add_hud_to(usr)
+ H.add_hud_to(usr, src)
if(user.mind && (misc_tracking || user.assigned_squad) && user.hud_used?.locate_leader)
user.show_hud_tracker()
if(misc_tracking)
SStracking.start_misc_tracking(user)
update_minimap_icon()
else
- H.remove_hud_from(usr)
+ H.remove_hud_from(usr, src)
if(user.hud_used?.locate_leader)
user.hide_hud_tracker()
if(misc_tracking)
diff --git a/code/modules/admin/verbs/mob_verbs.dm b/code/modules/admin/verbs/mob_verbs.dm
index 376115c0d630..4809d9b2e6ee 100644
--- a/code/modules/admin/verbs/mob_verbs.dm
+++ b/code/modules/admin/verbs/mob_verbs.dm
@@ -81,7 +81,7 @@
H = huds[MOB_HUD_XENO_STATUS]
else return
- H.add_hud_to(M)
+ H.add_hud_to(M, HUD_SOURCE_ADMIN)
to_chat(src, SPAN_INFO("[hud_choice] enabled."))
message_admins(SPAN_INFO("[key_name(usr)] has given a [hud_choice] to [M]."))
diff --git a/code/modules/client/preferences_toggles.dm b/code/modules/client/preferences_toggles.dm
index b81411a26440..b600b39a0018 100644
--- a/code/modules/client/preferences_toggles.dm
+++ b/code/modules/client/preferences_toggles.dm
@@ -623,7 +623,7 @@
if(!isobserver(usr))
return
- var/mob/dead/observer/O = usr
+ var/mob/dead/observer/observer_user = usr
var/datum/mob_hud/H
switch(hud_choice)
if("Medical HUD")
@@ -643,11 +643,11 @@
if("Faction CLF HUD")
H = huds[MOB_HUD_FACTION_CLF]
- O.HUD_toggled[hud_choice] = prefs.observer_huds[hud_choice]
- if(O.HUD_toggled[hud_choice])
- H.add_hud_to(O)
+ observer_user.HUD_toggled[hud_choice] = prefs.observer_huds[hud_choice]
+ if(observer_user.HUD_toggled[hud_choice])
+ H.add_hud_to(observer_user, observer_user)
else
- H.remove_hud_from(O)
+ H.remove_hud_from(observer_user, observer_user)
/client/proc/toggle_ghost_health_scan()
set name = "Toggle Health Scan"
diff --git a/code/modules/clothing/glasses/glasses.dm b/code/modules/clothing/glasses/glasses.dm
index 7bcf1dd6645c..a7844631051e 100644
--- a/code/modules/clothing/glasses/glasses.dm
+++ b/code/modules/clothing/glasses/glasses.dm
@@ -70,10 +70,10 @@
if(hud_type)
var/datum/mob_hud/MH = huds[hud_type]
if(active)
- MH.add_hud_to(H)
+ MH.add_hud_to(H, src)
playsound(H, 'sound/handling/hud_on.ogg', 25, 1)
else
- MH.remove_hud_from(H)
+ MH.remove_hud_from(H, src)
playsound(H, 'sound/handling/hud_off.ogg', 25, 1)
if(active) //turning it on? then add the traits
for(var/trait in clothing_traits)
@@ -95,7 +95,7 @@
else if(hud_type)
var/datum/mob_hud/MH = huds[hud_type]
- MH.add_hud_to(user)
+ MH.add_hud_to(user, src)
user.update_sight()
..()
@@ -103,7 +103,7 @@
if(hud_type && active && istype(user))
if(src == user.glasses) //dropped is called before the inventory reference is updated.
var/datum/mob_hud/H = huds[hud_type]
- H.remove_hud_from(user)
+ H.remove_hud_from(user, src)
user.glasses = null
user.update_inv_glasses()
user.update_sight()
diff --git a/code/modules/clothing/glasses/hud.dm b/code/modules/clothing/glasses/hud.dm
index f5baeb804412..1a133eee0dfe 100644
--- a/code/modules/clothing/glasses/hud.dm
+++ b/code/modules/clothing/glasses/hud.dm
@@ -109,7 +109,7 @@
deactive_state = "sensorhud_d"
flags_armor_protection = 0
toggleable = TRUE
- hud_type = MOB_HUD_MEDICAL_BASIC
+ hud_type = MOB_HUD_MEDICAL_ADVANCED
actions_types = list(/datum/action/item_action/toggle)
req_skill = SKILL_MEDICAL
req_skill_level = SKILL_MEDICAL_DEFAULT
diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm
index 0181d239c574..6fadffd088df 100644
--- a/code/modules/clothing/head/helmet.dm
+++ b/code/modules/clothing/head/helmet.dm
@@ -360,6 +360,7 @@ GLOBAL_LIST_INIT(allowed_helmet_items, list(
var/flags_marine_helmet = HELMET_SQUAD_OVERLAY|HELMET_GARB_OVERLAY|HELMET_DAMAGE_OVERLAY
var/helmet_bash_cooldown = 0
+ //speciality does NOTHING if you have NO_NAME_OVERRIDE
var/specialty = "M10 pattern marine" //Give them a specialty var so that they show up correctly in vendors. speciality does NOTHING if you have NO_NAME_OVERRIDE.
valid_accessory_slots = list(ACCESSORY_SLOT_HELM_C)
restricted_accessory_slots = list(ACCESSORY_SLOT_HELM_C)
@@ -372,11 +373,27 @@ GLOBAL_LIST_INIT(allowed_helmet_items, list(
var/storage_slots_reserved_for_garb = 1
var/storage_max_w_class = SIZE_TINY // can hold tiny items only, EXCEPT for glasses & metal flask.
var/storage_max_storage_space = 4
+
/// The dmi where the grayscale squad overlays are contained
var/helmet_overlay_icon = 'icons/mob/humans/onmob/head_1.dmi'
-/obj/item/clothing/head/helmet/marine/New(loc,
- new_protection[] = list(MAP_ICE_COLONY = ICE_PLANET_MIN_COLD_PROT))
+ ///Any visors built into the helmet
+ var/list/built_in_visors = list(new /obj/item/device/helmet_visor)
+
+ ///Any visors that have been added into the helmet
+ var/list/inserted_visors = list()
+
+ ///Max amount of inserted visors
+ var/max_inserted_visors = 1
+
+ ///The current active visor that is shown
+ var/obj/item/device/helmet_visor/active_visor = null
+
+ ///Designates a visor type that should start down when initialized
+ var/start_down_visor_type
+
+/obj/item/clothing/head/helmet/marine/Initialize(mapload, new_protection[] = list(MAP_ICE_COLONY = ICE_PLANET_MIN_COLD_PROT))
+ . = ..()
if(!(flags_atom & NO_NAME_OVERRIDE))
name = "[specialty]"
if(SSmapping.configs[GROUND_MAP].environment_traits[MAP_COLD])
@@ -385,7 +402,7 @@ GLOBAL_LIST_INIT(allowed_helmet_items, list(
name += " helmet"
if(!(flags_atom & NO_SNOW_TYPE))
- select_gamemode_skin(type,null,new_protection)
+ select_gamemode_skin(type, null, new_protection)
helmet_overlays = list() //To make things simple.
@@ -399,7 +416,24 @@ GLOBAL_LIST_INIT(allowed_helmet_items, list(
camera = new /obj/structure/machinery/camera(src)
camera.network = list(CAMERA_NET_OVERWATCH)
- ..()
+ if(length(inserted_visors) || length(built_in_visors))
+ var/datum/action/item_action/cycle_helmet_huds/new_action = new(src)
+ LAZYADD(actions, new_action)
+ if(ishuman(loc))
+ var/mob/living/carbon/human/holding_human = loc
+ if(holding_human.head == src)
+ new_action.give_to(holding_human)
+
+ if(start_down_visor_type)
+ for(var/obj/item/device/helmet_visor/cycled_visor in (built_in_visors + inserted_visors))
+ if(cycled_visor.type == start_down_visor_type)
+ active_visor = cycled_visor
+ break
+
+ if(active_visor)
+ var/datum/action/item_action/cycle_helmet_huds/cycle_action = locate() in actions
+ if(cycle_action)
+ cycle_action.set_action_overlay(active_visor)
/obj/item/clothing/head/helmet/marine/Destroy(force)
helmet_overlays = null
@@ -421,9 +455,9 @@ GLOBAL_LIST_INIT(allowed_helmet_items, list(
if(pockets.handle_mousedrop(usr, over_object))
..()
-/obj/item/clothing/head/helmet/marine/attackby(obj/item/W, mob/user)
- if(istype(W, /obj/item/ammo_magazine) && world.time > helmet_bash_cooldown && user)
- var/obj/item/ammo_magazine/M = W
+/obj/item/clothing/head/helmet/marine/attackby(obj/item/attacking_item, mob/user)
+ if(istype(attacking_item, /obj/item/ammo_magazine) && world.time > helmet_bash_cooldown && user)
+ var/obj/item/ammo_magazine/M = attacking_item
var/ammo_level = "somewhat"
playsound(user, 'sound/items/trayhit1.ogg', 15, FALSE)
if(M.current_rounds > (M.max_rounds/2))
@@ -436,9 +470,48 @@ GLOBAL_LIST_INIT(allowed_helmet_items, list(
ammo_level = "empty. Uh oh."
user.visible_message("[user] bashes [M] against their helmet", "You bash [M] against your helmet. It is [ammo_level]")
helmet_bash_cooldown = world.time + 20 SECONDS
- else
- ..()
- return pockets.attackby(W, user)
+ return
+
+ if(istype(attacking_item, /obj/item/device/helmet_visor))
+ if(length(inserted_visors) >= max_inserted_visors)
+ to_chat(user, SPAN_NOTICE("[src] has used all of its visor attachment sockets."))
+ return
+
+ var/obj/item/device/helmet_visor/new_visor = attacking_item
+ for(var/obj/item/device/helmet_visor/cycled_visor as anything in (built_in_visors + inserted_visors))
+ if(cycled_visor.type == new_visor.type)
+ to_chat(user, SPAN_NOTICE("[src] already has this type of HUD connected."))
+ return
+ if(!user.drop_held_item())
+ return
+
+ inserted_visors += new_visor
+ to_chat(user, SPAN_NOTICE("You connect [new_visor] to [src]."))
+ new_visor.forceMove(src)
+ if(!(locate(/datum/action/item_action/cycle_helmet_huds) in actions))
+ var/datum/action/item_action/cycle_helmet_huds/new_action = new(src)
+ new_action.give_to(user)
+ return
+
+ if(HAS_TRAIT(attacking_item, TRAIT_TOOL_SCREWDRIVER) && length(inserted_visors))
+ for(var/obj/item/device/visor as anything in inserted_visors)
+ visor.forceMove(get_turf(src))
+
+ inserted_visors = list()
+ to_chat(user, SPAN_NOTICE("You remove the inserted visors."))
+ turn_off_visor(user, active_visor, TRUE)
+
+ var/datum/action/item_action/cycle_helmet_huds/cycle_action = locate() in actions
+ cycle_action.set_default_overlay()
+ if(!length(built_in_visors))
+ cycle_action.remove_from(user)
+
+ active_visor = null
+ recalculate_visors(user)
+ return
+
+ ..()
+ return pockets.attackby(attacking_item, user)
/obj/item/clothing/head/helmet/marine/on_pocket_insertion()
update_icon()
@@ -478,6 +551,9 @@ GLOBAL_LIST_INIT(allowed_helmet_items, list(
else
helmet_overlays = above_band_layer + below_band_layer
+ if(active_visor)
+ helmet_overlays += active_visor.helmet_overlay
+
if(ismob(loc))
var/mob/M = loc
M.update_inv_head()
@@ -485,6 +561,8 @@ GLOBAL_LIST_INIT(allowed_helmet_items, list(
/obj/item/clothing/head/helmet/marine/equipped(mob/living/carbon/human/mob, slot)
if(camera)
camera.c_tag = mob.name
+ if(active_visor)
+ recalculate_visors(mob)
..()
/obj/item/clothing/head/helmet/marine/unequipped(mob/user, slot)
@@ -493,6 +571,8 @@ GLOBAL_LIST_INIT(allowed_helmet_items, list(
for(var/obj/item/attachable/flashlight/F in pockets)
if(F.activated)
F.activate_attachment(src, user, TRUE)
+ if(active_visor)
+ recalculate_visors(user)
/obj/item/clothing/head/helmet/marine/dropped(mob/living/carbon/human/mob)
if(camera)
@@ -501,6 +581,8 @@ GLOBAL_LIST_INIT(allowed_helmet_items, list(
for(var/obj/item/attachable/flashlight/F in pockets)
if(F.activated)
F.activate_attachment(src, mob, TRUE)
+ if(active_visor)
+ recalculate_visors(mob)
..()
/obj/item/clothing/head/helmet/marine/has_garb_overlay()
@@ -518,59 +600,122 @@ GLOBAL_LIST_INIT(allowed_helmet_items, list(
return pockets
return ..()
-/obj/item/clothing/head/helmet/marine/tech
- name = "\improper M10 technician helmet"
- desc = "A modified M10 marine helmet for ComTechs. Features a toggleable welding screen for eye protection."
- icon_state = "tech_helmet"
- specialty = "M10 technician"
- var/protection_on = FALSE
- ///To remember the helmet's map variant-adjusted icon state
- var/base_icon_state
+/// Recalculates and sets the proper visor effects
+/obj/item/clothing/head/helmet/marine/proc/recalculate_visors(mob/user)
+ turn_off_visors(user)
- actions_types = list(/datum/action/item_action/toggle)
- vision_impair = VISION_IMPAIR_NONE
+ if(!active_visor)
+ return
-/obj/item/clothing/head/helmet/marine/tech/Initialize()
- . = ..()
- base_icon_state = icon_state
+ if(user != loc)
+ return
-/obj/item/clothing/head/helmet/marine/tech/attack_self(mob/user)
- ..()
- toggle()
+ var/mob/living/carbon/human/human_user = user
+ if(!human_user || human_user.head != src)
+ return
-/obj/item/clothing/head/helmet/marine/tech/verb/toggle()
- set category = "Object"
- set name = "Toggle Tech Helmet"
- set src in usr
+ turn_on_visor(human_user)
- if(usr.canmove && !usr.stat && !usr.is_mob_restrained())
- if(protection_on)
- vision_impair = VISION_IMPAIR_NONE
- flags_inventory &= ~(COVEREYES|COVERMOUTH)
- flags_inv_hide &= ~(HIDEEYES|HIDEFACE)
- icon_state = base_icon_state
- eye_protection = EYE_PROTECTION_NONE
- to_chat(usr, "You deactivate the [src]'s welding screen.")
- else
- vision_impair = VISION_IMPAIR_MAX
- flags_inventory |= COVEREYES|COVERMOUTH
- flags_inv_hide |= HIDEEYES|HIDEFACE
- icon_state = "[base_icon_state]_on"
- eye_protection = EYE_PROTECTION_WELDING
- to_chat(usr, "You activate the [src]'s welding screen.")
+/// Turns on the current active visor
+/obj/item/clothing/head/helmet/marine/proc/turn_on_visor(mob/user)
+ if(!active_visor)
+ return
- protection_on = !protection_on
+ if(active_visor.can_toggle(user))
+ active_visor.visor_function(src, user)
- if(ishuman(loc))
- var/mob/living/carbon/human/H = loc
- if(H.head == src)
- H.update_tint()
+ playsound_client(user.client, active_visor.toggle_on_sound, null, 75)
+ update_icon()
+
+/// Turns off the specified visor
+/obj/item/clothing/head/helmet/marine/proc/turn_off_visor(mob/user, obj/item/device/helmet_visor/current_visor, sound = FALSE)
+ if(!current_visor)
+ return
+
+ if(current_visor.can_toggle(user))
+ current_visor.visor_function(src, user)
+
+ if(sound)
+ playsound_client(user.client, current_visor.toggle_off_sound, null, 75)
+ update_icon()
+
+/// Attempts to turn off all visors
+/obj/item/clothing/head/helmet/marine/proc/turn_off_visors(mob/user)
+ var/list/total_visors = built_in_visors + inserted_visors
+
+ for(var/obj/item/device/helmet_visor/cycled_helmet_visor in total_visors)
+ if(cycled_helmet_visor.can_toggle(user))
+ cycled_helmet_visor.visor_function(src, user, TRUE)
+
+ update_icon()
+
+///Cycles the active HUD to the next between built_in_visors and inserted_visors, nullifies if at end and removes all HUDs
+/obj/item/clothing/head/helmet/marine/proc/cycle_huds(mob/user)
+ var/list/total_visors = built_in_visors + inserted_visors
+
+ if(!length(total_visors))
+ return FALSE
+
+ if(active_visor)
+ var/iterator = 1
+ for(var/hud_type in total_visors)
+ if(hud_type == active_visor)
+ if(length(total_visors) > iterator)
+ turn_off_visor(user, active_visor, FALSE)
+ active_visor = total_visors[(iterator + 1)]
+ recalculate_visors(user)
+ return active_visor
+ else
+ turn_off_visor(user, active_visor, TRUE)
+ active_visor = null
+ recalculate_visors(user)
+ return FALSE
+ iterator++
+
+ if(total_visors[1])
+ active_visor = total_visors[1]
+ recalculate_visors(user)
+ return active_visor
+
+ active_visor = null
+ recalculate_visors(user)
+ return FALSE
+
+/datum/action/item_action/cycle_helmet_huds/New(Target, obj/item/holder)
+ . = ..()
+ name = "Cycle helmet HUD"
+ button.name = name
+ set_default_overlay()
+
+/datum/action/item_action/cycle_helmet_huds/action_activate()
+ . = ..()
+ var/obj/item/clothing/head/helmet/marine/holder_helmet = holder_item
+ var/cycled_hud = holder_helmet.cycle_huds(usr)
+
+ set_action_overlay(cycled_hud)
- update_clothing_icon() //so our mob-overlays update
+/// Sets the action overlay based on the visor type
+/datum/action/item_action/cycle_helmet_huds/proc/set_action_overlay(obj/item/device/helmet_visor/new_visor)
+ if(!new_visor)
+ set_default_overlay()
+ return
- for(var/X in actions)
- var/datum/action/A = X
- A.update_button_icon()
+ action_icon_state = new_visor.action_icon_string
+ button.overlays.Cut()
+ button.overlays += image('icons/obj/items/clothing/helmet_visors.dmi', button, action_icon_state)
+
+/// Sets the action overlay to default hud sight up
+/datum/action/item_action/cycle_helmet_huds/proc/set_default_overlay()
+ action_icon_state = "hud_sight_up"
+ button.overlays.Cut()
+ button.overlays += image('icons/obj/items/clothing/helmet_visors.dmi', button, action_icon_state)
+
+/obj/item/clothing/head/helmet/marine/tech
+ name = "\improper M10 technician helmet"
+ 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)
/obj/item/clothing/head/helmet/marine/tech/tanker
name = "\improper M50 tanker helmet"
@@ -583,12 +728,15 @@ 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)
/obj/item/clothing/head/helmet/marine/medic
name = "\improper M10 corpsman helmet"
desc = "An M10 marine helmet version worn by marine hospital corpsmen. Has red cross painted on its front."
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)
+ start_down_visor_type = /obj/item/device/helmet_visor/medical/advanced
/obj/item/clothing/head/helmet/marine/covert
name = "\improper M10 covert helmet"
@@ -729,6 +877,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)
/obj/item/clothing/head/helmet/marine/MP
name = "\improper M10 pattern MP helmet"
@@ -737,6 +886,7 @@ GLOBAL_LIST_INIT(allowed_helmet_items, list(
item_state = "mp_helmet"
armor_energy = CLOTHING_ARMOR_MEDIUMLOW
specialty = "M10 pattern military police"
+ built_in_visors = list(new /obj/item/device/helmet_visor/security)
/obj/item/clothing/head/helmet/marine/MP/WO
name = "\improper M3 pattern chief MP helmet"
@@ -751,6 +901,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)
/obj/item/clothing/head/helmet/marine/mp/provost/marshal
name = "\improper Provost Marshal Cap"
@@ -770,6 +921,7 @@ GLOBAL_LIST_INIT(allowed_helmet_items, list(
armor_bio = CLOTHING_ARMOR_MEDIUMHIGH
specialty = "M10 pattern SOF"
flags_atom = NO_SNOW_TYPE
+ built_in_visors = list(new /obj/item/device/helmet_visor, new /obj/item/device/helmet_visor/medical, new /obj/item/device/helmet_visor/security)
//=============================//PMCS\\==================================\\
@@ -777,6 +929,7 @@ GLOBAL_LIST_INIT(allowed_helmet_items, list(
/obj/item/clothing/head/helmet/marine/veteran
flags_atom = NO_SNOW_TYPE|NO_NAME_OVERRIDE //Let's make these keep their name and icon.
+ built_in_visors = list()
/obj/item/clothing/head/helmet/marine/veteran/pmc
name = "\improper PMC tactical cap"
@@ -1137,44 +1290,7 @@ GLOBAL_LIST_INIT(allowed_helmet_items, list(
/obj/item/clothing/head/helmet/marine/veteran/mercenary/support/engineer
desc = "A sturdy helmet worn by an unknown mercenary group. Features a toggleable welding screen for eye protection."
- var/protection_on = FALSE
-
- actions_types = list(/datum/action/item_action/toggle)
- vision_impair = VISION_IMPAIR_NONE
-
-/obj/item/clothing/head/helmet/marine/veteran/mercenary/support/engineer/attack_self(mob/user)
- ..()
- toggle()
-
-/obj/item/clothing/head/helmet/marine/veteran/mercenary/support/engineer/verb/toggle()
- set category = "Object"
- set name = "Toggle Helmet Welding Visor"
- set src in usr
-
- if(usr.canmove && !usr.stat && !usr.is_mob_restrained())
- if(protection_on)
- vision_impair = VISION_IMPAIR_NONE
- flags_inventory &= ~(COVEREYES|COVERMOUTH)
- flags_inv_hide &= ~(HIDEEYES|HIDEFACE)
- eye_protection = EYE_PROTECTION_NONE
- to_chat(usr, "You deactivate the [src]'s welding screen.")
- else
- vision_impair = VISION_IMPAIR_MAX
- flags_inventory |= COVEREYES|COVERMOUTH
- flags_inv_hide |= HIDEEYES|HIDEFACE
- eye_protection = EYE_PROTECTION_WELDING
- to_chat(usr, "You activate the [src]'s welding screen.")
-
- protection_on = !protection_on
-
- if(ishuman(loc))
- var/mob/living/carbon/human/H = loc
- if(H.head == src)
- H.update_tint()
-
- for(var/X in actions)
- var/datum/action/A = X
- A.update_button_icon()
+ built_in_visors = list(new /obj/item/device/helmet_visor/welding_visor/mercenary)
//=============================//MEME\\==================================\\
//=======================================================================\\
@@ -1193,6 +1309,8 @@ GLOBAL_LIST_INIT(allowed_helmet_items, list(
armor_melee = CLOTHING_ARMOR_VERYHIGH
armor_bomb = CLOTHING_ARMOR_GIGAHIGH
+ built_in_visors = list()
+
var/mob/activator = null
var/active = FALSE
var/det_time = 40
@@ -1243,4 +1361,6 @@ GLOBAL_LIST_INIT(allowed_helmet_items, list(
contained_sprite = TRUE
flags_atom = NO_SNOW_TYPE|NO_NAME_OVERRIDE
+ built_in_visors = list()
+
#undef HELMET_GARB_RELAY_ICON_STATE
diff --git a/code/modules/cm_marines/equipment/kit_boxes.dm b/code/modules/cm_marines/equipment/kit_boxes.dm
index a552b8eb0927..be60dce0e783 100644
--- a/code/modules/cm_marines/equipment/kit_boxes.dm
+++ b/code/modules/cm_marines/equipment/kit_boxes.dm
@@ -429,7 +429,7 @@
new /obj/item/pamphlet/skill/medical(src)
new /obj/item/storage/pouch/first_responder/full(src)
new /obj/item/storage/pouch/autoinjector/full(src)
- new /obj/item/clothing/glasses/hud/sensor(src)
+ new /obj/item/device/helmet_visor/medical(src)
new /obj/item/roller(src)
diff --git a/code/modules/cm_preds/yaut_mask.dm b/code/modules/cm_preds/yaut_mask.dm
index be0aa8ed761a..94b244b09f14 100644
--- a/code/modules/cm_preds/yaut_mask.dm
+++ b/code/modules/cm_preds/yaut_mask.dm
@@ -155,7 +155,7 @@
if(istype(user) && user.wear_mask == src) //inventory reference is only cleared after dropped().
for(var/listed_hud in mask_huds)
var/datum/mob_hud/H = huds[listed_hud]
- H.remove_hud_from(user)
+ H.remove_hud_from(user, src)
var/obj/item/visor = user.glasses
if(visor) //make your hud fuck off
if(istype(visor, /obj/item/clothing/glasses/night/yautja))
@@ -170,7 +170,7 @@
START_PROCESSING(SSobj, src)
for(var/listed_hud in mask_huds)
var/datum/mob_hud/H = huds[listed_hud]
- H.add_hud_to(user)
+ H.add_hud_to(user, src)
if(current_goggles)
var/obj/item/clothing/gloves/yautja/bracer = user.gloves
if(!bracer || !istype(bracer))
diff --git a/code/modules/gear_presets/clf.dm b/code/modules/gear_presets/clf.dm
index 901de2c21ca3..81abf8bce550 100644
--- a/code/modules/gear_presets/clf.dm
+++ b/code/modules/gear_presets/clf.dm
@@ -675,7 +675,7 @@
list("Injector (Tricord)", 1, /obj/item/reagent_container/hypospray/autoinjector/tricord, null, VENDOR_ITEM_REGULAR),
list("Health Analyzer", 4, /obj/item/device/healthanalyzer, null, VENDOR_ITEM_REGULAR),
- list("Sensor Medical HUD", 4, /obj/item/clothing/glasses/hud/sensor, null, VENDOR_ITEM_MANDATORY),
+ list("Medical Helmet Optic", 4, /obj/item/device/helmet_visor/medical, null, VENDOR_ITEM_MANDATORY),
list("SPECIAL AMMUNITION", 0, null, null, null),
list("M16 AP Magazine (5.56x45mm)", 10, /obj/item/ammo_magazine/rifle/m16/ap, null, VENDOR_ITEM_REGULAR),
@@ -996,7 +996,7 @@
list("Injector (Tricord)", 1, /obj/item/reagent_container/hypospray/autoinjector/tricord, null, VENDOR_ITEM_REGULAR),
list("Health Analyzer", 4, /obj/item/device/healthanalyzer, null, VENDOR_ITEM_REGULAR),
- list("Sensor Medical HUD", 4, /obj/item/clothing/glasses/hud/sensor, null, VENDOR_ITEM_MANDATORY),
+ list("Medical Helmet Optic", 4, /obj/item/device/helmet_visor/medical, null, VENDOR_ITEM_MANDATORY),
list("SPECIAL AMMUNITION", 0, null, null, null),
list("M16 AP Magazine (5.56x45mm)", 10, /obj/item/ammo_magazine/rifle/m16/ap, null, VENDOR_ITEM_REGULAR),
diff --git a/code/modules/gear_presets/other.dm b/code/modules/gear_presets/other.dm
index 9780b739cf67..b440fe4533b2 100644
--- a/code/modules/gear_presets/other.dm
+++ b/code/modules/gear_presets/other.dm
@@ -807,7 +807,7 @@
for(var/hud_to_add in huds_to_add)
var/datum/mob_hud/hud = huds[hud_to_add]
- hud.add_hud_to(new_human)
+ hud.add_hud_to(new_human, new_human)
var/list/actions_to_add = subtypesof(/datum/action/human_action/activable/cult)
diff --git a/code/modules/mob/camera/imaginary_friend.dm b/code/modules/mob/camera/imaginary_friend.dm
index a78de70a7e15..3d6d5d5a0aa2 100644
--- a/code/modules/mob/camera/imaginary_friend.dm
+++ b/code/modules/mob/camera/imaginary_friend.dm
@@ -168,10 +168,10 @@
hud = huds[MOB_HUD_FACTION_CLF]
if(hud_choice in current_huds)
- hud.remove_hud_from(src)
+ hud.remove_hud_from(src, src)
current_huds -= hud_choice
else
- hud.add_hud_to(src)
+ hud.add_hud_to(src, src)
current_huds += hud_choice
/mob/camera/imaginary_friend/say(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language, ignore_spam = FALSE, forced)
diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm
index ee36d25fc687..405dea1772f0 100644
--- a/code/modules/mob/dead/observer/observer.dm
+++ b/code/modules/mob/dead/observer/observer.dm
@@ -267,28 +267,28 @@
switch(i)
if("Medical HUD")
H = huds[MOB_HUD_MEDICAL_OBSERVER]
- H.add_hud_to(src)
+ H.add_hud_to(src, src)
if("Security HUD")
H = huds[MOB_HUD_SECURITY_ADVANCED]
- H.add_hud_to(src)
+ H.add_hud_to(src, src)
if("Squad HUD")
H = huds[MOB_HUD_FACTION_OBSERVER]
- H.add_hud_to(src)
+ H.add_hud_to(src, src)
if("Xeno Status HUD")
H = huds[MOB_HUD_XENO_STATUS]
- H.add_hud_to(src)
+ H.add_hud_to(src, src)
if("Faction UPP HUD")
H = huds[MOB_HUD_FACTION_UPP]
- H.add_hud_to(src)
+ H.add_hud_to(src, src)
if("Faction Wey-Yu HUD")
H = huds[MOB_HUD_FACTION_WY]
- H.add_hud_to(src)
+ H.add_hud_to(src, src)
if("Faction TWE HUD")
H = huds[MOB_HUD_FACTION_TWE]
- H.add_hud_to(src)
+ H.add_hud_to(src, src)
if("Faction CLF HUD")
H = huds[MOB_HUD_FACTION_CLF]
- H.add_hud_to(src)
+ H.add_hud_to(src, src)
see_invisible = INVISIBILITY_OBSERVER
diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm
index aa0cbba74a5a..6e99ca1e5a15 100644
--- a/code/modules/mob/living/carbon/human/examine.dm
+++ b/code/modules/mob/living/carbon/human/examine.dm
@@ -512,25 +512,30 @@
//Helper procedure. Called by /mob/living/carbon/human/get_examine_text() and /mob/living/carbon/human/Topic() to determine HUD access to security and medical records.
-/proc/hasHUD(mob/M, hudtype)
- if(istype(M, /mob/living/carbon/human))
- var/mob/living/carbon/human/H = M
- if (issynth(H))
+/proc/hasHUD(mob/passed_mob, hudtype)
+ if(istype(passed_mob, /mob/living/carbon/human))
+ var/mob/living/carbon/human/passed_human = passed_mob
+ if (issynth(passed_human))
return 1
switch(hudtype)
if("security")
- //only MPs can use the security HUD glasses's functionalities
- if(skillcheck(H, SKILL_POLICE, SKILL_POLICE_SKILLED))
- return istype(H.glasses, /obj/item/clothing/glasses/hud/security) || istype(H.glasses, /obj/item/clothing/glasses/sunglasses/sechud)
+ if(skillcheck(passed_human, SKILL_POLICE, SKILL_POLICE_SKILLED))
+ var/datum/mob_hud/sec_hud = huds[MOB_HUD_SECURITY_ADVANCED]
+ if(locate(passed_mob) in sec_hud.hudusers)
+ return TRUE
if("medical")
- if(skillcheck(H, SKILL_MEDICAL, SKILL_MEDICAL_MEDIC))
- return istype(H.glasses, /obj/item/clothing/glasses/hud/health)
+ if(skillcheck(passed_human, SKILL_MEDICAL, SKILL_MEDICAL_MEDIC))
+ var/datum/mob_hud/med_hud = huds[MOB_HUD_MEDICAL_ADVANCED]
+ if(locate(passed_mob) in med_hud.hudusers)
+ return TRUE
if("squadleader")
- return H.mind && H.assigned_squad && H.assigned_squad.squad_leader == H && H.get_type_in_ears(/obj/item/device/radio/headset/almayer/marine)
+ var/datum/mob_hud/faction_hud = huds[MOB_HUD_FACTION_USCM]
+ if(passed_human.mind && passed_human.assigned_squad && passed_human.assigned_squad.squad_leader == passed_human && locate(passed_mob) in faction_hud.hudusers)
+ return TRUE
else
return 0
- else if(isrobot(M))
- var/mob/living/silicon/robot/R = M
+ else if(isrobot(passed_mob))
+ var/mob/living/silicon/robot/R = passed_mob
switch(hudtype)
if("security")
return istype(R.module_state_1, /obj/item/robot/sight/hud/sec) || istype(R.module_state_2, /obj/item/robot/sight/hud/sec) || istype(R.module_state_3, /obj/item/robot/sight/hud/sec)
diff --git a/code/modules/mob/living/carbon/human/powers/human_powers.dm b/code/modules/mob/living/carbon/human/powers/human_powers.dm
index 1c8c011f7c71..10b13225b314 100644
--- a/code/modules/mob/living/carbon/human/powers/human_powers.dm
+++ b/code/modules/mob/living/carbon/human/powers/human_powers.dm
@@ -240,9 +240,9 @@
if(synthetic_HUD_toggled[chosen_HUD])
synthetic_HUD_toggled[chosen_HUD] = FALSE
- H.remove_hud_from(src)
+ H.remove_hud_from(src, src)
to_chat(src, SPAN_INFO("[hud_choice] Disabled"))
else
synthetic_HUD_toggled[chosen_HUD] = TRUE
- H.add_hud_to(src)
+ H.add_hud_to(src, src)
to_chat(src, SPAN_INFO("[hud_choice] Enabled"))
diff --git a/code/modules/mob/living/carbon/human/species/zombie.dm b/code/modules/mob/living/carbon/human/species/zombie.dm
index 07fe8f5e1255..5fa928a67f36 100644
--- a/code/modules/mob/living/carbon/human/species/zombie.dm
+++ b/code/modules/mob/living/carbon/human/species/zombie.dm
@@ -68,7 +68,7 @@
D.stage = 5
var/datum/mob_hud/Hu = huds[MOB_HUD_MEDICAL_OBSERVER]
- Hu.add_hud_to(zombie)
+ Hu.add_hud_to(zombie, zombie)
return ..()
@@ -77,7 +77,7 @@
..()
remove_from_revive(zombie)
var/datum/mob_hud/Hu = huds[MOB_HUD_MEDICAL_OBSERVER]
- Hu.remove_hud_from(zombie)
+ Hu.remove_hud_from(zombie, zombie)
/datum/species/zombie/handle_unique_behavior(mob/living/carbon/human/zombie)
diff --git a/code/modules/mob/living/carbon/xenomorph/Xenomorph.dm b/code/modules/mob/living/carbon/xenomorph/Xenomorph.dm
index dd53868caf36..fbf14a9f25f7 100644
--- a/code/modules/mob/living/carbon/xenomorph/Xenomorph.dm
+++ b/code/modules/mob/living/carbon/xenomorph/Xenomorph.dm
@@ -810,7 +810,7 @@
//and display them
add_to_all_mob_huds()
var/datum/mob_hud/MH = huds[MOB_HUD_XENO_INFECTION]
- MH.add_hud_to(src)
+ MH.add_hud_to(src, src)
/mob/living/carbon/xenomorph/check_improved_pointing()
diff --git a/code/modules/mob/living/carbon/xenomorph/xeno_verbs.dm b/code/modules/mob/living/carbon/xenomorph/xeno_verbs.dm
index 583d26de3ee5..94218b224e2d 100644
--- a/code/modules/mob/living/carbon/xenomorph/xeno_verbs.dm
+++ b/code/modules/mob/living/carbon/xenomorph/xeno_verbs.dm
@@ -83,9 +83,9 @@
var/datum/mob_hud/H = huds[MOB_HUD_XENO_STATUS]
if (xeno_mobhud)
- H.remove_hud_from(usr)
+ H.remove_hud_from(usr, usr)
else
- H.add_hud_to(usr)
+ H.add_hud_to(usr, usr)
xeno_mobhud = !xeno_mobhud
@@ -96,9 +96,9 @@
var/datum/mob_hud/H = huds[MOB_HUD_XENO_HOSTILE]
if (xeno_hostile_hud)
- H.remove_hud_from(usr)
+ H.remove_hud_from(usr, usr)
else
- H.add_hud_to(usr)
+ H.add_hud_to(usr, usr)
xeno_hostile_hud = !xeno_hostile_hud
diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm
index 2910da65cb79..b0f08acc33fa 100644
--- a/code/modules/mob/living/silicon/silicon.dm
+++ b/code/modules/mob/living/silicon/silicon.dm
@@ -160,11 +160,11 @@
if(HUD_toggled[HUD_nbr])
HUD_toggled[HUD_nbr] = 0
- H.remove_hud_from(src)
+ H.remove_hud_from(src, src)
to_chat(src, SPAN_NOTICE(" [hud_choice] Disabled"))
else
HUD_toggled[HUD_nbr] = 1
- H.add_hud_to(src)
+ H.add_hud_to(src, src)
to_chat(src, SPAN_NOTICE(" [hud_choice] Enabled"))
/mob/living/silicon/verb/pose()
diff --git a/colonialmarines.dme b/colonialmarines.dme
index 42e7880bd313..0554131e2833 100644
--- a/colonialmarines.dme
+++ b/colonialmarines.dme
@@ -1017,6 +1017,7 @@
#include "code\game\objects\items\devices\flash.dm"
#include "code\game\objects\items\devices\flashlight.dm"
#include "code\game\objects\items\devices\floor_painter.dm"
+#include "code\game\objects\items\devices\helmet_visors.dm"
#include "code\game\objects\items\devices\lightreplacer.dm"
#include "code\game\objects\items\devices\megaphone.dm"
#include "code\game\objects\items\devices\motion_detector.dm"
diff --git a/icons/mob/humans/onmob/head_1.dmi b/icons/mob/humans/onmob/head_1.dmi
index 0fb5700225e3..7f78ce119341 100644
Binary files a/icons/mob/humans/onmob/head_1.dmi and b/icons/mob/humans/onmob/head_1.dmi differ
diff --git a/icons/mob/humans/onmob/helmet_garb.dmi b/icons/mob/humans/onmob/helmet_garb.dmi
index 3bb63088783f..325aed72b155 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
new file mode 100644
index 000000000000..6ba0cfe5623e
Binary files /dev/null and b/icons/obj/items/clothing/helmet_visors.dmi differ