REC_Hud
Stracture
Installation, configuration, and usage for REC_Hud.
- Added
- Updated
The following configuration files and manifest are taken from the current source.
config/sh_config.lua
---@class REC_Hud.Shared.Config
local config = {}
---[[
--- Debug Mode
---]]
---@type boolean
config.debugMode = true
---[[
--- Layout of every element the HUD draws
---
--- Every element has a default position here (a corner plus the distance from the screen edge).
--- Players can drag the elements anywhere from the layout editor (/rechudlayout, or the button in
--- the settings panel), that position is saved on their computer and wins over the one below.
---]]
config.ui = {
---[[
--- Hide the whole HUD while the pause menu is open
---]]
---@type boolean
hideInPauseMenu = true,
---[[
--- Nothing is drawn until the player really stands in the world (loading screen gone, screen
--- faded in, no switch camera). This is how often that is checked (ms)
---]]
---@type integer
spawnPoll = 250,
---[[
--- Chat commands
---]]
command = {
---@type string # settings panel (shape, size, display mode, which gauges to show, ...)
settings = "hud",
---@type string # layout editor (drag the elements around)
layout = "layout",
---@type string # cinematic mode on / off (black bars, no HUD, no radar)
cinematic = "cinematic",
},
---[[
--- Key that opens the settings panel (the same panel as the command)
---]]
settingsKeybind = {
---@type boolean
enabled = true,
---@type string
name = "rec_hud_settings",
---@type string # empty leaves it unbound, the player sets it in the key settings
defaultKey = "I",
},
---[[
--- Status gauges (health, hunger, ...)
---]]
gauges = {
---[[
--- false hides the gauges entirely (keep it off when another HUD resource draws them)
---]]
---@type boolean
enabled = true,
---[[
--- Corner the gauges sit in and the distance from the screen edge (CSS units)
---]]
---@type REC_Hud.Shared.Enum.Position
position = "bottom-left",
offset = {
---@type string
x = "1.6vw",
---@type string
y = "3vh",
},
---@type string
gap = "8px",
---[[
--- Default shape, players can pick another one from the settings panel
--- see enum.gaugeShape in shared/sh_enum.lua for the whole list
--- ("bar" / "thick" / "segment" / "ring" / "dial" / "needle" / "arc" / "column" / "columnSegment" /
--- "square" / "hex" / "diamond" / "minimal" / "number")
---]]
---@type REC_Hud.Shared.Enum.GaugeShape
shape = "bar",
---[[
--- false locks the shape above (the settings panel hides the shape picker)
---]]
---@type boolean
allowShapeChange = true,
---[[
--- Size multiplier (1.0 is the native size, players can change it from the settings panel)
---]]
---@type number
scale = 1.5,
---[[
--- Default display mode, players can switch it from the settings panel
--- "always": the gauges stay on screen
--- "onChange": a gauge is on screen while its value differs from its resting value
--- (the item's "default" below) and hides again once it is back to it
---]]
---@type REC_Hud.Shared.Enum.DisplayMode
displayMode = "always",
---@type number # below this percent the gauge blinks
lowPercent = 20,
---[[
--- How often the values are read (ms)
--- only the values that changed are sent to the NUI
---]]
---@type integer
tick = 300,
---[[
--- The gauges, drawn in this order
--- key: unique name (also what exports.REC_Hud:setGaugeValue refers to)
--- icon: an icon from shared/sh_enum.lua or a custom SVG path ("path:M12 2L...")
--- source: where the value comes from
--- a name from enum.gaugeSource (health / armor / stamina / oxygen come from natives,
--- hunger / thirst / stress come from the framework through REC_Utils)
--- or a function returning the value (nil hides the gauge until it returns one)
--- omit it to push the value from another resource with exports.REC_Hud:setGaugeValue
--- min / max: value range (defaults 0 to 100)
--- default: resting value the "onChange" mode compares against
--- (defaults to min when hideWhenEmpty is true, max otherwise)
--- hideWhenFull: hide the gauge while the value is at max (stamina, oxygen)
--- hideWhenEmpty: hide the gauge while the value is at min (armor, stress)
--- (both are ignored by the "always" mode, a gauge set to it stays on screen)
--- showValue: draw the number next to the gauge
--- label: name in the settings panel (defaults to locales.gauge[key], then the key)
---]]
---@type REC_Hud.Shared.Gauge.Payload[]
items = {
{ key = "health", icon = "heart", color = "#f87171", source = "health", },
{ key = "armor", icon = "shield", color = "#60a5fa", source = "armor", hideWhenEmpty = true, },
{ key = "hunger", icon = "utensils", color = "#fbbf24", source = "hunger", },
{ key = "thirst", icon = "droplet", color = "#38bdf8", source = "thirst", },
{ key = "stress", icon = "brain", color = "#c084fc", source = "stress", hideWhenEmpty = true, },
{ key = "stamina", icon = "activity", color = "#4ade80", source = "stamina", hideWhenFull = true, },
{ key = "oxygen", icon = "waves", color = "#22d3ee", source = "oxygen", hideWhenFull = true, },
-- a gauge fed by another resource, here the gas mask filter of REC_BetterMask
-- {
-- key = "maskFilter",
-- icon = "mask",
-- color = "#a3e635",
-- hideWhenEmpty = true,
-- source = function ()
-- if GetResourceState("REC_BetterMask") ~= "started" then
-- return nil
-- end
-- local state = exports.REC_BetterMask:getMaskState()
-- if state == nil or state.wearing == false then
-- return nil
-- end
-- return state.filter
-- end,
-- },
},
},
---[[
--- Vehicle panel, shown while the player sits in a vehicle
--- (a speed readout plus gauges read from the vehicle)
---]]
vehicle = {
---@type boolean
enabled = true,
---@type boolean # true shows the panel to the driver only
driverOnly = false,
---@type REC_Hud.Shared.Enum.Position
position = "bottom-right",
offset = {
---@type string
x = "1.6vw",
---@type string
y = "3vh",
},
---@type string
gap = "8px",
---[[
--- Shape of the vehicle gauges, nil follows the status gauges
---]]
---@type REC_Hud.Shared.Enum.GaugeShape|nil
shape = nil,
---@type integer # how often the vehicle is read (ms), the speed needs a quick tick
tick = 100,
---[[
--- Speed readout
---]]
speed = {
---@type boolean
enabled = true,
---@type REC_Hud.Shared.Enum.SpeedUnit # default unit, players can switch it from the settings panel
unit = "kmh",
---@type REC_Hud.Shared.Enum.SpeedStyle # "digital" is the number, "analog" a meter with a needle (players can switch)
style = "digital",
---@type number # where the analog meter ends (in the unit above)
max = 240,
---@type boolean # the needles kick when the gearbox shifts (analog meter and needle shaped gauges)
shiftShake = true,
},
---[[
--- Seatbelt: a warning icon while the belt is off, a soft chime once the vehicle moves
--- The belt itself lives here too (keybind, no ejection through the windscreen, no exit while buckled)
--- and is published as LocalPlayer.state[stateBag] for other resources
---]]
seatbelt = {
---@type boolean
enabled = true,
---@type string # LocalPlayer.state key, true while buckled
stateBag = "seatbelt",
keybind = {
---@type boolean # false leaves the toggling to exports.REC_Hud:setSeatbelt
enabled = true,
---@type string
name = "rec_hud_seatbelt",
---@type string
defaultKey = "B",
},
---@type boolean # the exit key does nothing while buckled
blockExit = true,
---@type table<integer, boolean> # vehicle classes without a belt (no icon, no chime, no toggle)
excludedClasses = {
[8] = true, -- motorcycles
[13] = true, -- cycles
},
---[[
--- The reminder chime (players can mute it from the settings panel)
---]]
sound = {
---@type boolean
enabled = true,
---@type number # km/h, no chime below this speed
minSpeed = 15,
---@type integer # ms between two chimes
interval = 1800,
---@type number # 0 to 1
volume = 0.05,
},
},
---[[
--- Aircraft (planes and helicopters) get an airspeed, altitude, climb and heading readout
--- on top of the gauges below
---]]
aircraft = {
---@type boolean # false draws the plain vehicle panel in aircraft too
enabled = true,
---@type REC_Hud.Shared.Enum.SpeedUnit # "kmh" / "mph" / "knots" (players can switch)
speedUnit = "knots",
---@type number # where the analog airspeed meter ends (in the unit above)
speedMax = 300,
---@type REC_Hud.Shared.Enum.AltitudeUnit # "m" / "ft" (players can switch)
altitudeUnit = "ft",
},
---[[
--- The gauges read from the vehicle, same fields as config.ui.gauges.items
--- source: a name from enum.vehicleSource (fuel / engine / body / rpm)
--- or a function (vehicle) returning the value
---]]
---@type REC_Hud.Shared.Gauge.Payload[]
items = {
{ key = "fuel", icon = "fuel", color = "#f59e0b", source = "fuel", showValue = false, unit = "%", }, -- players can turn the percent readout on from the settings panel
{ key = "engine", icon = "engine", color = "#ef4444", source = "engine", },
-- { key = "body", icon = "wrench", color = "#a3a3a3", source = "body", },
-- { key = "rpm", icon = "gauge", color = "#38bdf8", source = "rpm", },
},
},
---[[
--- Clock (players can turn it off, switch 12h / 24h, seconds and the date from the settings panel)
---]]
clock = {
---@type boolean
enabled = true,
---@type REC_Hud.Shared.Enum.Position
position = "top-right",
offset = {
---@type string
x = "1.6vw",
---@type string
y = "2vh",
},
---@type REC_Hud.Shared.Enum.ClockSource # "real" is the player's computer, "game" the in-game time
source = "real",
---@type boolean # 12 hour clock with AM / PM
hour12 = false,
---@type boolean
showSeconds = false,
---@type boolean # the date under the time ("real" only)
showDate = false,
},
---[[
--- Server ID of the player
--- the number the staff asks for, it never changes while the player is connected
---
--- While it shares its corner with the clock it is drawn right under it whatever the clock
--- shows, so the offset below is only used when they sit in different corners
---]]
serverId = {
---@type boolean
enabled = true,
---@type REC_Hud.Shared.Enum.Position
position = "top-right",
offset = {
---@type string
x = "1.6vw",
---@type string
y = "7vh",
},
---@type boolean # draw the "ID" label in front of the number
showLabel = true,
},
---[[
--- FiveM player name, stacked below the server ID or clock while sharing their corner
---]]
playerName = {
---@type boolean
enabled = true,
---@type boolean # false prevents players from hiding the name; layout editing stays available
allowHide = false,
---@type REC_Hud.Shared.Enum.Position
position = "top-right",
offset = {
---@type string
x = "1.6vw",
---@type string
y = "11vh",
},
},
---[[
--- Compass
--- a bar with the cardinals and the ticks, the heading in degrees and the street names under it
---]]
compass = {
---@type boolean
enabled = true,
---@type REC_Hud.Shared.Enum.Position
position = "top-center",
offset = {
---@type string
x = "0px",
---@type string
y = "1.5vh",
},
---@type string # CSS width of the bar
width = "340px",
---@type boolean # only while in a vehicle (the settings panel can change it)
inVehicleOnly = true,
---@type boolean # follow the camera heading, false follows the ped
followCamera = true,
---@type boolean # the heading in degrees under the bar
showDegrees = true,
---@type boolean # the marker in the middle of the bar
showPointer = true,
---@type boolean # the street names under the bar
showStreets = true,
---@type integer # how often the heading is read (ms)
tick = 50,
---@type integer # how often the street names are read (ms)
streetTick = 1000,
},
---[[
--- Server logo
--- image: a file inside this resource (listed under files in fxmanifest.lua) or a full URL,
--- nil draws the text instead
---]]
logo = {
---@type boolean
enabled = false,
---@type REC_Hud.Shared.Enum.Position
position = "top-left",
offset = {
---@type string
x = "1.6vw",
---@type string
y = "2vh",
},
---@type string|nil
image = "images/logo.svg",
---@type string # drawn when image is nil (or fails to load)
text = "RE:CORD",
---@type string # CSS width of the image
width = "140px",
---@type number # 0 to 1
opacity = 0.9,
},
---[[
--- Minimap
--- the map itself is drawn by the game, REC_Hud only moves it (SetMinimapComponentPosition)
--- to where the player dragged its outline in the layout editor
---]]
minimap = {
---@type boolean # false leaves the minimap alone (no outline in the layout editor)
movable = true,
---[[
--- Shape of the minimap: the radar mask is swapped for the one streamed from stream/
--- (squaremap.ytd / circlemap.ytd, the minimap.gfx there drops the vanilla frame and bars)
--- nil keeps the vanilla minimap, players can pick a shape from the settings panel
---]]
---@type REC_Hud.Shared.Enum.MinimapShape|nil
shape = "square",
---@type number # size of the minimap, 1.0 is the vanilla size (players can change it, min / max below)
scale = 1.0,
---@type number
scaleMin = 0.6,
---@type number
scaleMax = 1.8,
---@type boolean # hide the north blip on the radar
hideNorthBlip = true,
---@type boolean # draw the radar on foot too, false shows it in vehicles only (players can switch)
showOnFoot = true,
---@type integer # ms, the shape / size is applied a second time this long after a spawn (the game resets the minimap while spawning)
reapplyDelay = 2000,
---[[
--- Radar keep-alive
--- other resources set the radar zoom and can leave the bigmap on after this resource
--- has applied its own state (map_code adds its minimap overlay from the end of the
--- resource list), and none of them announce it, so the state is set again when a
--- resource starts after this one, and on a slow interval as a fallback.
--- ps-hud did the same every 500 ms.
---]]
---@type integer # ms between each fallback re-assert (a resource starting after this one re-asserts right away), 0 disables the keep-alive
keepAliveInterval = 2000,
---@type integer|nil # radar zoom the keep-alive forces, nil leaves the zoom alone
radarZoom = 1000,
},
---[[
--- Vanilla HUD parts hidden every frame (the thread only runs while the list is not empty)
--- 1 wanted stars, 2 weapon icon, 3 cash, 4 MP cash, 6 vehicle name, 7 area name,
--- 8 vehicle class, 9 street name, 13 cash change, 17 save game, 20 weapon wheel stats
---]]
---@type integer[]
hideComponents = { 1, 2, 3, 4, 13, 17, 20, },
---[[
--- Cinematic mode: black bars slide in, the HUD and the radar go away (/cinematic or the keybind)
---]]
cinematic = {
---@type boolean
enabled = true,
---@type number # height of one bar, fraction of the screen
barHeight = 0.12,
---@type integer # ms the bars take to slide in / out
duration = 400,
keybind = {
---@type boolean
enabled = true,
---@type string
name = "rec_hud_cinematic",
---@type string # empty leaves it unbound, the player sets it in the key settings
defaultKey = "",
},
},
}
---@type REC_Hud.Shared.Preset
local preset = require "@REC_Hud.shared.sh_preset"
---@type table # paste an exported preset into config/ui_defaults.json
config.defaultPrefs = preset:load(config.ui)
return config
