Skip to content

Commit

Permalink
Helmet Visors/Optics and built-in HUDs (#4156)
Browse files Browse the repository at this point in the history
# About the pull request

This PR adds various helmet visors and optics that you can cycle through
for HUDs without goofy eyewear.

Video demonstration:
https://cdn.discordapp.com/attachments/495285245877157906/1139189768597540905/2023-08-10_09-26-38.mp4

On the code side this PR allows for separate sources for HUDs that can
be doubled up without one overriding the other. I'm certain this will
require some testing and jank reduction and frankly my skill with
associated lists and the HUD system is so-so. We'll see if I need to
completely overhaul this.

# Explain why it's good for the game

Movielike

# Testing Photographs and Procedure
<details>
<summary>Screenshots & Videos</summary>

Put screenshots and videos here with an empty line between the
screenshots and the `<details>` tags.

</details>


# Changelog

:cl: Morrow, Frans_Feiffer (beautiful sprites)
add: Added in built HUDs to various helmets
add: Sensormates used by squads without medical skills have been
converted to buyable helmet optics
/:cl:
  • Loading branch information
morrowwolf authored Aug 25, 2023
1 parent d6037d1 commit d0b549f
Show file tree
Hide file tree
Showing 34 changed files with 411 additions and 167 deletions.
3 changes: 3 additions & 0 deletions code/__DEFINES/mob_hud.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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"
42 changes: 30 additions & 12 deletions code/datums/mob_hud.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)

Expand Down Expand Up @@ -229,27 +253,21 @@ 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)



/mob/proc/refresh_huds(mob/source_mob)
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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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),

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down Expand Up @@ -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),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
98 changes: 98 additions & 0 deletions code/game/objects/items/devices/helmet_visors.dm
Original file line number Diff line number Diff line change
@@ -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"
8 changes: 4 additions & 4 deletions code/game/objects/items/devices/radio/headset.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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()
Expand Down Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion code/modules/admin/verbs/mob_verbs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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]."))

Expand Down
10 changes: 5 additions & 5 deletions code/modules/client/preferences_toggles.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand All @@ -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"
Expand Down
8 changes: 4 additions & 4 deletions code/modules/clothing/glasses/glasses.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -95,15 +95,15 @@

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()
..()

/obj/item/clothing/glasses/dropped(mob/living/carbon/human/user)
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()
Expand Down
2 changes: 1 addition & 1 deletion code/modules/clothing/glasses/hud.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading

0 comments on commit d0b549f

Please sign in to comment.