Skip to content

[SUGGESTION] Feature Addition: Toggle HUD Command #199

@LawProductions

Description

@LawProductions

The problem

I noticed qb-hud currently lacks a native way to programmatically hide/show the HUD, which is crucial for developers creating immersive UI experiences.

Ideal solution

This adds a new command /togglehud that allows players to completely hide/show the HUD and minimap. This feature is useful for:

Cinematic gameplay/screenshots
Reducing screen clutter when needed
Role-playing scenarios
Content creation

Changes Made

Added server-side command /togglehud with player state tracking
Added client-side toggle functionality
Added export ToggleHud for other resources to use
Properly handles minimap visibility based on vehicle state and menu settings
Includes server-side notifications for command usage

Implementation Details

Maintains existing HUD settings when re-enabling
Respects vehicle/on-foot minimap rules
Doesn't interfere with existing HUD functionality
Clean implementation using existing NUI messages
Lightweight addition with minimal overhead

Testing

Tested functionality in the following scenarios:

On foot/in vehicle transitions
Menu setting interactions
Multiple toggle cycles
Export usage from other resources
Different notification states

NEW CLIENT CODE:

local QBCore = exports['qb-core']:GetCoreObject()
local PlayerData = QBCore.Functions.GetPlayerData()
local config = Config
local speedMultiplier = config.UseMPH and 2.23694 or 3.6
local seatbeltOn = false
local cruiseOn = false
local showAltitude = false
local showSeatbelt = false
local nos = 0
local stress = 0
local hunger = 100
local thirst = 100
local cashAmount = 0
local bankAmount = 0
local nitroActive = 0
local harness = 0
local hp = 100
local armed = 0
local parachute = -1
local oxygen = 100
local dev = false
local playerDead = false
local showMenu = false
local showCircleB = false
local showSquareB = false
local Menu = config.Menu
local CinematicHeight = 0.2
local w = 0
local radioActive = false
local isPauseMenuActive = false
local hudHidden = false

-- HUD VISIBILITY

local function shouldDisplayRadar()
if hudHidden then return false end
if isPauseMenuActive then return false end
if Menu.isHideMapChecked then return false end
if Menu.isCinematicModeChecked then return false end

local player = PlayerPedId()
local vehicle = GetVehiclePedIsIn(player, false)

if IsPedInAnyVehicle(player) and not IsThisModelABicycle(vehicle) then
    return true
end

return Menu.isOutMapChecked

end

-- HUD Visibility Toggle Function
local function ToggleHudVisibility()
hudHidden = not hudHidden

if hudHidden then
    SendNUIMessage({
        action = 'hudtick',
        show = false
    })
    SendNUIMessage({
        action = 'car',
        show = false
    })
    SendNUIMessage({
        action = 'baseplate',
        show = false
    })
    DisplayRadar(false)
else
    if not isPauseMenuActive then
        SendNUIMessage({
            action = 'hudtick',
            show = true
        })
        DisplayRadar(shouldDisplayRadar())
    end
end

end

-- Export Functions
exports('ToggleHud', function()
ToggleHudVisibility()
end)

exports('SetHudState', function(state)
if hudHidden ~= not state then
ToggleHudVisibility()
end
DisplayRadar(shouldDisplayRadar())
end)

exports('IsHudHidden', function()
return hudHidden
end)

-- Event Handlers
RegisterNetEvent('qb-hud:client:ToggleHud', function()
ToggleHudVisibility()
end)

DisplayRadar(false)

local function CinematicShow(bool)
SetBigmapActive(true, false)
Wait(0)
SetBigmapActive(false, false)
if bool then
for i = CinematicHeight, 0, -1.0 do
Wait(10)
w = i
end
else
for i = 0, CinematicHeight, 1.0 do
Wait(10)
w = i
end
end
end

local function loadSettings(settings)
for k, v in pairs(settings) do
if k == 'isToggleMapShapeChecked' then
Menu.isToggleMapShapeChecked = v
SendNUIMessage({ test = true, event = k, toggle = v })
elseif k == 'isCinematicModeChecked' then
Menu.isCinematicModeChecked = v
CinematicShow(v)
SendNUIMessage({ test = true, event = k, toggle = v })
elseif k == 'isChangeFPSChecked' then
Menu[k] = v
local val = v and 'Optimized' or 'Synced'
SendNUIMessage({ test = true, event = k, toggle = val })
else
Menu[k] = v
SendNUIMessage({ test = true, event = k, toggle = v })
end
end
QBCore.Functions.Notify(Lang:t('notify.hud_settings_loaded'), 'success')
Wait(1000)
TriggerEvent('hud:client:LoadMap')
end

local function saveSettings()
SetResourceKvp('hudSettings', json.encode(Menu))
end

local function hasHarness(items)
local ped = PlayerPedId()
if not IsPedInAnyVehicle(ped, false) then return end

local _harness = false
if items then
    for _, v in pairs(items) do
        if v.name == 'harness' then
            _harness = true
        end
    end
end

harness = _harness

end

RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function()
Wait(2000)
local hudSettings = GetResourceKvpString('hudSettings')
if hudSettings then loadSettings(json.decode(hudSettings)) end
PlayerData = QBCore.Functions.GetPlayerData()
Wait(3000)
SetEntityHealth(PlayerPedId(), 200)
end)

RegisterNetEvent('QBCore:Client:OnPlayerUnload', function()
PlayerData = {}
end)

RegisterNetEvent('QBCore:Player:SetPlayerData', function(val)
PlayerData = val
end)

AddEventHandler('onResourceStart', function(resourceName)
if GetCurrentResourceName() ~= resourceName then return end
Wait(2000)
local hudSettings = GetResourceKvpString('hudSettings')
if hudSettings then loadSettings(json.decode(hudSettings)) end
end)

AddEventHandler('pma-voice:radioActive', function(data)
radioActive = data
end)

-- Callbacks & Events
RegisterCommand('menu', function()
Wait(50)
if showMenu then return end
TriggerEvent('hud:client:playOpenMenuSounds')
SetNuiFocus(true, true)
SendNUIMessage({ action = 'open' })
showMenu = true
end)

RegisterNUICallback('closeMenu', function(_, cb)
Wait(50)
TriggerEvent('hud:client:playCloseMenuSounds')
showMenu = false
SetNuiFocus(false, false)
cb('ok')
end)

RegisterKeyMapping('menu', 'Open Menu', 'keyboard', config.OpenMenu)

-- Reset hud
local function restartHud()
TriggerEvent('hud:client:playResetHudSounds')
QBCore.Functions.Notify(Lang:t('notify.hud_restart'), 'error')
if IsPedInAnyVehicle(PlayerPedId()) then
Wait(2600)
SendNUIMessage({ action = 'car', show = false })
SendNUIMessage({ action = 'car', show = true })
end
Wait(2600)
SendNUIMessage({ action = 'hudtick', show = false })
SendNUIMessage({ action = 'hudtick', show = true })
Wait(2600)
QBCore.Functions.Notify(Lang:t('notify.hud_start'), 'success')
end

RegisterNUICallback('restartHud', function(_, cb)
Wait(50)
restartHud()
cb('ok')
end)

RegisterCommand('resethud', function()
Wait(50)
restartHud()
end)

RegisterNUICallback('resetStorage', function(_, cb)
Wait(50)
TriggerEvent('hud:client:resetStorage')
cb('ok')
end)

RegisterNetEvent('hud:client:resetStorage', function()
Wait(50)
if Menu.isResetSoundsChecked then
TriggerServerEvent('InteractSound_SV:PlayOnSource', 'airwrench', 0.1)
end
QBCore.Functions.TriggerCallback('hud:server:getMenu', function(menu)
loadSettings(menu); SetResourceKvp('hudSettings', json.encode(menu))
end)
end)

-- Notifications
RegisterNUICallback('openMenuSounds', function(_, cb)
Wait(50)
Menu.isOpenMenuSoundsChecked = not Menu.isOpenMenuSoundsChecked
TriggerEvent('hud:client:playHudChecklistSound')
saveSettings()
cb('ok')
end)

RegisterNetEvent('hud:client:playOpenMenuSounds', function()
Wait(50)
if not Menu.isOpenMenuSoundsChecked then return end
TriggerServerEvent('InteractSound_SV:PlayOnSource', 'monkeyopening', 0.5)
end)

RegisterNetEvent('hud:client:playCloseMenuSounds', function()
Wait(50)
if not Menu.isOpenMenuSoundsChecked then return end
TriggerServerEvent('InteractSound_SV:PlayOnSource', 'catclosing', 0.05)
end)

RegisterNUICallback('resetHudSounds', function(_, cb)
Wait(50)
Menu.isResetSoundsChecked = not Menu.isResetSoundsChecked
TriggerEvent('hud:client:playHudChecklistSound')
saveSettings()
cb('ok')
end)

RegisterNetEvent('hud:client:playResetHudSounds', function()
Wait(50)
if not Menu.isResetSoundsChecked then return end
TriggerServerEvent('InteractSound_SV:PlayOnSource', 'airwrench', 0.1)
end)

RegisterNUICallback('checklistSounds', function(_, cb)
Wait(50)
TriggerEvent('hud:client:checklistSounds')
cb('ok')
end)

RegisterNetEvent('hud:client:checklistSounds', function()
Wait(50)
Menu.isListSoundsChecked = not Menu.isListSoundsChecked
TriggerEvent('hud:client:playHudChecklistSound')
saveSettings()
end)

RegisterNetEvent('hud:client:playHudChecklistSound', function()
Wait(50)
if not Menu.isListSoundsChecked then return end
TriggerServerEvent('InteractSound_SV:PlayOnSource', 'shiftyclick', 0.5)
end)

RegisterNUICallback('showOutMap', function(_, cb)
Wait(50)
Menu.isOutMapChecked = not Menu.isOutMapChecked
TriggerEvent('hud:client:playHudChecklistSound')
saveSettings()
cb('ok')
end)

RegisterNUICallback('showOutCompass', function(_, cb)
Wait(50)
Menu.isOutCompassChecked = not Menu.isOutCompassChecked
TriggerEvent('hud:client:playHudChecklistSound')
saveSettings()
cb('ok')
end)

RegisterNUICallback('showFollowCompass', function(_, cb)
Wait(50)
Menu.isCompassFollowChecked = not Menu.isCompassFollowChecked
TriggerEvent('hud:client:playHudChecklistSound')
saveSettings()
cb('ok')
end)

RegisterNUICallback('showMapNotif', function(_, cb)
Wait(50)
Menu.isMapNotifChecked = not Menu.isMapNotifChecked
TriggerEvent('hud:client:playHudChecklistSound')
saveSettings()
cb('ok')
end)

RegisterNUICallback('showFuelAlert', function(_, cb)
Wait(50)
Menu.isLowFuelChecked = not Menu.isLowFuelChecked
TriggerEvent('hud:client:playHudChecklistSound')
saveSettings()
cb('ok')
end)

RegisterNUICallback('showCinematicNotif', function(_, cb)
Wait(50)
Menu.isCinematicNotifChecked = not Menu.isCinematicNotifChecked
TriggerEvent('hud:client:playHudChecklistSound')
saveSettings()
cb('ok')
end)

-- Status
RegisterNUICallback('dynamicHealth', function(_, cb)
Wait(50)
TriggerEvent('hud:client:ToggleHealth')
cb('ok')
end)

RegisterNetEvent('hud:client:ToggleHealth', function()
Wait(50)
Menu.isDynamicHealthChecked = not Menu.isDynamicHealthChecked
TriggerEvent('hud:client:playHudChecklistSound')
saveSettings()
end)

RegisterNUICallback('dynamicArmor', function(_, cb)
Wait(50)
Menu.isDynamicArmorChecked = not Menu.isDynamicArmorChecked
TriggerEvent('hud:client:playHudChecklistSound')
saveSettings()
cb('ok')
end)

RegisterNUICallback('dynamicHunger', function(_, cb)
Wait(50)
Menu.isDynamicHungerChecked = not Menu.isDynamicHungerChecked
TriggerEvent('hud:client:playHudChecklistSound')
saveSettings()
cb('ok')
end)

RegisterNUICallback('dynamicThirst', function(_, cb)
Wait(50)
Menu.isDynamicThirstChecked = not Menu.isDynamicThirstChecked
TriggerEvent('hud:client:playHudChecklistSound')
saveSettings()
cb('ok')
end)

RegisterNUICallback('dynamicStress', function(_, cb)
Wait(50)
Menu.isDynamicStressChecked = not Menu.isDynamicStressChecked
TriggerEvent('hud:client:playHudChecklistSound')
saveSettings()
cb('ok')
end)

RegisterNUICallback('dynamicOxygen', function(_, cb)
Wait(50)
Menu.isDynamicOxygenChecked = not Menu.isDynamicOxygenChecked
TriggerEvent('hud:client:playHudChecklistSound')
saveSettings()
cb('ok')
end)

-- Vehicle
RegisterNUICallback('changeFPS', function(_, cb)
Wait(50)
Menu.isChangeFPSChecked = not Menu.isChangeFPSChecked
TriggerEvent('hud:client:playHudChecklistSound')
saveSettings()
cb('ok')
end)

RegisterNUICallback('HideMap', function(_, cb)
Wait(50)
Menu.isHideMapChecked = not Menu.isHideMapChecked
DisplayRadar(shouldDisplayRadar())
TriggerEvent('hud:client:playHudChecklistSound')
saveSettings()
cb('ok')
end)

RegisterNetEvent('hud:client:LoadMap', function()
Wait(50)
-- Credit to Dalrae for the solve.
local defaultAspectRatio = 1920 / 1080 -- Don't change this.
local resolutionX, resolutionY = GetActiveScreenResolution()
local aspectRatio = resolutionX / resolutionY
local minimapOffset = 0
if aspectRatio > defaultAspectRatio then
minimapOffset = ((defaultAspectRatio - aspectRatio) / 3.6) - 0.008
end
if Menu.isToggleMapShapeChecked == 'square' then
RequestStreamedTextureDict('squaremap', false)
if not HasStreamedTextureDictLoaded('squaremap') then
Wait(150)
end
if Menu.isMapNotifChecked then
QBCore.Functions.Notify(Lang:t('notify.load_square_map'))
end
SetMinimapClipType(0)
AddReplaceTexture('platform:/textures/graphics', 'radarmasksm', 'squaremap', 'radarmasksm')
AddReplaceTexture('platform:/textures/graphics', 'radarmask1g', 'squaremap', 'radarmasksm')
-- 0.0 = nav symbol and icons left
-- 0.1638 = nav symbol and icons stretched
-- 0.216 = nav symbol and icons raised up
SetMinimapComponentPosition('minimap', 'L', 'B', 0.0 + minimapOffset, -0.047, 0.1638, 0.183)

    -- icons within map
    SetMinimapComponentPosition('minimap_mask', 'L', 'B', 0.0 + minimapOffset, 0.0, 0.128, 0.20)

    -- -0.01 = map pulled left
    -- 0.025 = map raised up
    -- 0.262 = map stretched
    -- 0.315 = map shorten
    SetMinimapComponentPosition('minimap_blur', 'L', 'B', -0.01 + minimapOffset, 0.025, 0.262, 0.300)
    SetBlipAlpha(GetNorthRadarBlip(), 0)
    SetBigmapActive(true, false)
    SetMinimapClipType(0)
    Wait(50)
    SetBigmapActive(false, false)
    if Menu.isToggleMapBordersChecked then
        showCircleB = false
        showSquareB = true
    end
    Wait(1200)
    if Menu.isMapNotifChecked then
        QBCore.Functions.Notify(Lang:t('notify.loaded_square_map'))
    end
elseif Menu.isToggleMapShapeChecked == 'circle' then
    RequestStreamedTextureDict('circlemap', false)
    if not HasStreamedTextureDictLoaded('circlemap') then
        Wait(150)
    end
    if Menu.isMapNotifChecked then
        QBCore.Functions.Notify(Lang:t('notify.load_circle_map'))
    end
    SetMinimapClipType(1)
    AddReplaceTexture('platform:/textures/graphics', 'radarmasksm', 'circlemap', 'radarmasksm')
    AddReplaceTexture('platform:/textures/graphics', 'radarmask1g', 'circlemap', 'radarmasksm')
    -- -0.0100 = nav symbol and icons left
    -- 0.180 = nav symbol and icons stretched
    -- 0.258 = nav symbol and icons raised up
    SetMinimapComponentPosition('minimap', 'L', 'B', -0.0100 + minimapOffset, -0.030, 0.180, 0.258)

    -- icons within map
    SetMinimapComponentPosition('minimap_mask', 'L', 'B', 0.200 + minimapOffset, 0.0, 0.065, 0.20)

    -- -0.00 = map pulled left
    -- 0.015 = map raised up
    -- 0.252 = map stretched
    -- 0.338 = map shorten
    SetMinimapComponentPosition('minimap_blur', 'L', 'B', -0.00 + minimapOffset, 0.015, 0.252, 0.338)
    SetBlipAlpha(GetNorthRadarBlip(), 0)
    SetMinimapClipType(1)
    SetBigmapActive(true, false)
    Wait(50)
    SetBigmapActive(false, false)
    if Menu.isToggleMapBordersChecked then
        showSquareB = false
        showCircleB = true
    end
    Wait(1200)
    if Menu.isMapNotifChecked then
        QBCore.Functions.Notify(Lang:t('notify.loaded_circle_map'))
    end
end

end)

RegisterNUICallback('ToggleMapShape', function(_, cb)
Wait(50)
if not Menu.isHideMapChecked then
Menu.isToggleMapShapeChecked = Menu.isToggleMapShapeChecked == 'circle' and 'square' or 'circle'
Wait(50)
TriggerEvent('hud:client:LoadMap')
end
TriggerEvent('hud:client:playHudChecklistSound')
saveSettings()
cb('ok')
end)

RegisterNUICallback('ToggleMapBorders', function(_, cb)
Wait(50)
Menu.isToggleMapBordersChecked = not Menu.isToggleMapBordersChecked
if Menu.isToggleMapBordersChecked then
if Menu.isToggleMapShapeChecked == 'square' then
showSquareB = true
else
showCircleB = true
end
else
showSquareB = false
showCircleB = false
end
TriggerEvent('hud:client:playHudChecklistSound')
saveSettings()
cb('ok')
end)

RegisterNUICallback('dynamicEngine', function(_, cb)
Wait(50)
Menu.isDynamicEngineChecked = not Menu.isDynamicEngineChecked
TriggerEvent('hud:client:playHudChecklistSound')
saveSettings()
cb('ok')
end)

RegisterNUICallback('dynamicNitro', function(_, cb)
Wait(50)
Menu.isDynamicNitroChecked = not Menu.isDynamicNitroChecked
TriggerEvent('hud:client:playHudChecklistSound')
saveSettings()
cb('ok')
end)

-- Compass
RegisterNUICallback('showCompassBase', function(_, cb)
Wait(50)
Menu.isCompassShowChecked = not Menu.isCompassShowChecked
TriggerEvent('hud:client:playHudChecklistSound')
saveSettings()
cb('ok')
end)

RegisterNUICallback('showStreetsNames', function(_, cb)
Wait(50)
Menu.isShowStreetsChecked = not Menu.isShowStreetsChecked
TriggerEvent('hud:client:playHudChecklistSound')
saveSettings()
cb('ok')
end)

RegisterNUICallback('showPointerIndex', function(_, cb)
Wait(50)
Menu.isPointerShowChecked = not Menu.isPointerShowChecked
TriggerEvent('hud:client:playHudChecklistSound')
saveSettings()
cb('ok')
end)

RegisterNUICallback('showDegreesNum', function(_, cb)
Wait(50)
Menu.isDegreesShowChecked = not Menu.isDegreesShowChecked
TriggerEvent('hud:client:playHudChecklistSound')
saveSettings()
cb('ok')
end)

RegisterNUICallback('changeCompassFPS', function(_, cb)
Wait(50)
Menu.isChangeCompassFPSChecked = not Menu.isChangeCompassFPSChecked
TriggerEvent('hud:client:playHudChecklistSound')
saveSettings()
cb('ok')
end)

RegisterNUICallback('cinematicMode', function(_, cb)
Wait(50)
if Menu.isCinematicModeChecked then
CinematicShow(false)
Menu.isCinematicModeChecked = false
if Menu.isCinematicNotifChecked then
QBCore.Functions.Notify(Lang:t('notify.cinematic_off'), 'error')
end
DisplayRadar(1)
else
CinematicShow(true)
Menu.isCinematicModeChecked = true
if Menu.isCinematicNotifChecked then
QBCore.Functions.Notify(Lang:t('notify.cinematic_on'))
end
end
TriggerEvent('hud:client:playHudChecklistSound')
saveSettings()
cb('ok')
end)

RegisterNetEvent('hud:client:ToggleAirHud', function()
showAltitude = not showAltitude
end)

RegisterNetEvent('hud:client:UpdateNeeds', function(newHunger, newThirst) -- Triggered in qb-core
hunger = newHunger
thirst = newThirst
end)

RegisterNetEvent('hud:client:UpdateStress', function(newStress) -- Add this event with adding stress elsewhere
stress = newStress
end)

RegisterNetEvent('hud:client:ToggleShowSeatbelt', function()
showSeatbelt = not showSeatbelt
end)

RegisterNetEvent('seatbelt:client:ToggleSeatbelt', function() -- Triggered in smallresources
seatbeltOn = not seatbeltOn
end)

RegisterNetEvent('seatbelt:client:ToggleCruise', function() -- Triggered in smallresources
cruiseOn = not cruiseOn
end)

RegisterNetEvent('hud:client:UpdateNitrous', function(nitroLevel, bool)
nos = nitroLevel
nitroActive = bool
end)

RegisterNetEvent('hud:client:UpdateHarness', function(harnessHp)
hp = harnessHp
end)

RegisterNetEvent('qb-admin:client:ToggleDevmode', function()
dev = not dev
end)

local prevPlayerStats = { nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil }

local function updatePlayerHud(data)
local shouldUpdate = false
for k, v in pairs(data) do
if prevPlayerStats[k] ~= v then
shouldUpdate = true
break
end
end
prevPlayerStats = data
if shouldUpdate then
SendNUIMessage({
action = 'hudtick',
show = data[1],
dynamicHealth = data[2],
dynamicArmor = data[3],
dynamicHunger = data[4],
dynamicThirst = data[5],
dynamicStress = data[6],
dynamicOxygen = data[7],
dynamicEngine = data[8],
dynamicNitro = data[9],
health = data[10],
playerDead = data[11],
armor = data[12],
thirst = data[13],
hunger = data[14],
stress = data[15],
voice = data[16],
radio = data[17],
talking = data[18],
armed = data[19],
oxygen = data[20],
parachute = data[21],
nos = data[22],
cruise = data[23],
nitroActive = data[24],
harness = data[25],
hp = data[26],
speed = data[27],
engine = data[28],
cinematic = data[29],
dev = data[30],
radioActive = data[31],
})
end
end

local prevVehicleStats = { nil, nil, nil, nil, nil, nil, nil, nil, nil, nil }

local function updateVehicleHud(data)
local shouldUpdate = false
for k, v in pairs(data) do
if prevVehicleStats[k] ~= v then
shouldUpdate = true
break
end
end
prevVehicleStats = data
if shouldUpdate then
SendNUIMessage({
action = 'car',
show = data[1],
isPaused = data[2],
seatbelt = data[3],
speed = data[4],
fuel = data[5],
altitude = data[6],
showAltitude = data[7],
showSeatbelt = data[8],
showSquareB = data[9],
showCircleB = data[10],
})
end
end

local lastFuelUpdate = 0
local lastFuelCheck = {}

local function getFuelLevel(vehicle)
local updateTick = GetGameTimer()
if (updateTick - lastFuelUpdate) > 2000 then
lastFuelUpdate = updateTick
lastFuelCheck = math.floor(exports['LegacyFuel']:GetFuel(vehicle))
end
return lastFuelCheck
end

-- HUD Update loop
-- UPDATED TO RESPECT THE HUD HIDDEN STATE
CreateThread(function()
local wasInVehicle = false
while true do
if Menu.isChangeFPSChecked then
Wait(500)
else
Wait(50)
end

    if LocalPlayer.state.isLoggedIn then
        local show = not hudHidden
        local player = PlayerPedId()
        local playerId = PlayerId()
        
        -- Check pause menu state
        local currentPauseState = IsPauseMenuActive()
        if currentPauseState ~= isPauseMenuActive then
            isPauseMenuActive = currentPauseState
            if isPauseMenuActive then
                show = false
            end
            DisplayRadar(shouldDisplayRadar())
        end

        -- If pause menu is active, hide HUD elements
        if isPauseMenuActive then
            show = false
            SendNUIMessage({
                action = 'hudtick',
                show = false
            })
            SendNUIMessage({
                action = 'car',
                show = false
            })
            Wait(100)
            goto continue
        end

        local weapon = GetSelectedPedWeapon(player)
        if not config.WhitelistedWeaponArmed[weapon] then
            if weapon ~= `WEAPON_UNARMED` then
                armed = true
            else
                armed = false
            end
        end

        playerDead = IsEntityDead(player) or PlayerData.metadata['inlaststand'] or PlayerData.metadata['isdead'] or false
        parachute = GetPedParachuteState(player)

        -- Stamina
        if not IsEntityInWater(player) then
            oxygen = 100 - GetPlayerSprintStaminaRemaining(playerId)
        end
        
        -- Oxygen
        if IsEntityInWater(player) then
            oxygen = GetPlayerUnderwaterTimeRemaining(playerId) * 10
        end

        local talking = NetworkIsPlayerTalking(playerId)
        local voice = 0
        if LocalPlayer.state['proximity'] then
            voice = LocalPlayer.state['proximity'].distance
        end

        local vehicle = GetVehiclePedIsIn(player)
        if not (IsPedInAnyVehicle(player) and not IsThisModelABicycle(vehicle)) then
            updatePlayerHud({
                show,
                Menu.isDynamicHealthChecked,
                Menu.isDynamicArmorChecked,
                Menu.isDynamicHungerChecked,
                Menu.isDynamicThirstChecked,
                Menu.isDynamicStressChecked,
                Menu.isDynamicOxygenChecked,
                Menu.isDynamicEngineChecked,
                Menu.isDynamicNitroChecked,
                GetEntityHealth(player) - 100,
                playerDead,
                GetPedArmour(player),
                thirst,
                hunger,
                stress,
                voice,
                LocalPlayer.state['radioChannel'],
                talking,
                armed,
                oxygen,
                parachute,
                -1,
                cruiseOn,
                nitroActive,
                harness,
                hp,
                math.ceil(GetEntitySpeed(vehicle) * speedMultiplier),
                -1,
                Menu.isCinematicModeChecked,
                dev,
                radioActive
            })
        end

        -- Vehicle HUD
        if IsPedInAnyHeli(player) or IsPedInAnyPlane(player) then
            showAltitude = true
            showSeatbelt = false
        end

        if IsPedInAnyVehicle(player) and not IsThisModelABicycle(vehicle) then
            if not wasInVehicle then
                wasInVehicle = true
                DisplayRadar(shouldDisplayRadar())
            end

            local engineHealth = GetVehicleEngineHealth(vehicle)
            if engineHealth ~= engineHealth then
                engineHealth = 0
            end

            updatePlayerHud({
                show,
                Menu.isDynamicHealthChecked,
                Menu.isDynamicArmorChecked,
                Menu.isDynamicHungerChecked,
                Menu.isDynamicThirstChecked,
                Menu.isDynamicStressChecked,
                Menu.isDynamicOxygenChecked,
                Menu.isDynamicEngineChecked,
                Menu.isDynamicNitroChecked,
                GetEntityHealth(player) - 100,
                playerDead,
                GetPedArmour(player),
                thirst,
                hunger,
                stress,
                voice,
                LocalPlayer.state['radioChannel'],
                talking,
                armed,
                oxygen,
                GetPedParachuteState(player),
                nos,
                cruiseOn,
                nitroActive,
                harness,
                hp,
                math.ceil(GetEntitySpeed(vehicle) * speedMultiplier),
                (engineHealth / 10),
                Menu.isCinematicModeChecked,
                dev,
                radioActive
            })

            updateVehicleHud({
                show,
                isPauseMenuActive,
                seatbeltOn,
                math.ceil(GetEntitySpeed(vehicle) * speedMultiplier),
                getFuelLevel(vehicle),
                math.ceil(GetEntityCoords(player).z * 0.5),
                showAltitude,
                showSeatbelt,
                showSquareB,
                showCircleB
            })

            showAltitude = false
            showSeatbelt = true
        else
            if wasInVehicle then
                wasInVehicle = false
                SendNUIMessage({
                    action = 'car',
                    show = false,
                    seatbelt = false,
                    cruise = false,
                })
                seatbeltOn = false
                cruiseOn = false
                harness = false
            end
            DisplayRadar(shouldDisplayRadar())
        end
        
        ::continue::
    else
        SendNUIMessage({
            action = 'hudtick',
            show = false
        })
        DisplayRadar(false)
    end
end

end)

-- Low fuel
CreateThread(function()
while true do
if LocalPlayer.state.isLoggedIn then
local ped = PlayerPedId()
if IsPedInAnyVehicle(ped, false) and not IsThisModelABicycle(GetEntityModel(GetVehiclePedIsIn(ped, false))) then
if exports['LegacyFuel']:GetFuel(GetVehiclePedIsIn(ped, false)) <= 20 then -- At 20% Fuel Left
if Menu.isLowFuelChecked then
TriggerServerEvent('InteractSound_SV:PlayOnSource', 'pager', 0.10)
QBCore.Functions.Notify(Lang:t('notify.low_fuel'), 'error')
Wait(60000) -- repeats every 1 min until empty
end
end
end
end
Wait(10000)
end
end)

-- Money HUD

local Round = math.floor

RegisterNetEvent('hud:client:ShowAccounts', function(type, amount)
if type == 'cash' then
SendNUIMessage({
action = 'show',
type = 'cash',
cash = Round(amount)
})
else
SendNUIMessage({
action = 'show',
type = 'bank',
bank = Round(amount)
})
end
end)

RegisterNetEvent('hud:client:OnMoneyChange', function(type, amount, isMinus)
cashAmount = PlayerData.money['cash']
bankAmount = PlayerData.money['bank']
SendNUIMessage({
action = 'updatemoney',
cash = Round(cashAmount),
bank = Round(bankAmount),
amount = Round(amount),
minus = isMinus,
type = type
})
end)

-- Harness Check

CreateThread(function()
while true do
Wait(1000)

    local ped = PlayerPedId()
    if IsPedInAnyVehicle(ped, false) then
        hasHarness(PlayerData.items)
    end
end

end)

-- Stress Gain

if not config.DisableStress then
CreateThread(function() -- Speeding
while true do
if LocalPlayer.state.isLoggedIn then
local ped = PlayerPedId()
if IsPedInAnyVehicle(ped, false) then
local veh = GetVehiclePedIsIn(ped, false)
local vehClass = GetVehicleClass(veh)
local speed = GetEntitySpeed(veh) * speedMultiplier
local vehHash = GetEntityModel(veh)
if config.VehClassStress[tostring(vehClass)] and not config.WhitelistedVehicles[vehHash] then
local stressSpeed
if vehClass == 8 then -- Motorcycle exception for seatbelt
stressSpeed = config.MinimumSpeed
else
stressSpeed = seatbeltOn and config.MinimumSpeed or config.MinimumSpeedUnbuckled
end
if speed >= stressSpeed then
TriggerServerEvent('hud:server:GainStress', math.random(1, 3))
end
end
end
end
Wait(10000)
end
end)

CreateThread(function() -- Shooting
    while true do
        if LocalPlayer.state.isLoggedIn then
            local ped = PlayerPedId()
            local weapon = GetSelectedPedWeapon(ped)
            if weapon ~= `WEAPON_UNARMED` then
                if IsPedShooting(ped) and not config.WhitelistedWeaponStress[weapon] then
                    if math.random() < config.StressChance then
                        TriggerServerEvent('hud:server:GainStress', math.random(1, 3))
                    end
                end
            else
                Wait(1000)
            end
        end
        Wait(0)
    end
end)

end

-- Stress Screen Effects

local function GetBlurIntensity(stresslevel)
for _, v in pairs(config.Intensity['blur']) do
if stresslevel >= v.min and stresslevel <= v.max then
return v.intensity
end
end
return 1500
end

local function GetEffectInterval(stresslevel)
for _, v in pairs(config.EffectInterval) do
if stresslevel >= v.min and stresslevel <= v.max then
return v.timeout
end
end
return 60000
end

CreateThread(function()
while true do
local ped = PlayerPedId()
local effectInterval = GetEffectInterval(stress)
if stress >= 100 then
local BlurIntensity = GetBlurIntensity(stress)
local FallRepeat = math.random(2, 4)
local RagdollTimeout = FallRepeat * 1750
TriggerScreenblurFadeIn(1000.0)
Wait(BlurIntensity)
TriggerScreenblurFadeOut(1000.0)

        if not IsPedRagdoll(ped) and IsPedOnFoot(ped) and not IsPedSwimming(ped) then
            SetPedToRagdollWithFall(ped, RagdollTimeout, RagdollTimeout, 1, GetEntityForwardVector(ped), 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
        end

        Wait(1000)
        for _ = 1, FallRepeat, 1 do
            Wait(750)
            DoScreenFadeOut(200)
            Wait(1000)
            DoScreenFadeIn(200)
            TriggerScreenblurFadeIn(1000.0)
            Wait(BlurIntensity)
            TriggerScreenblurFadeOut(1000.0)
        end
    elseif stress >= config.MinimumStress then
        local BlurIntensity = GetBlurIntensity(stress)
        TriggerScreenblurFadeIn(1000.0)
        Wait(BlurIntensity)
        TriggerScreenblurFadeOut(1000.0)
    end
    Wait(effectInterval)
end

end)

-- Minimap update
CreateThread(function()
while true do
SetBigmapActive(false, false)
SetRadarZoom(1000)
Wait(500)
end
end)

local function BlackBars()
DrawRect(0.0, 0.0, 2.0, w, 0, 0, 0, 255)
DrawRect(0.0, 1.0, 2.0, w, 0, 0, 0, 255)
end

CreateThread(function()
local minimap = RequestScaleformMovie('minimap')
if not HasScaleformMovieLoaded(minimap) then
RequestScaleformMovie(minimap)
while not HasScaleformMovieLoaded(minimap) do
Wait(1)
end
end
while true do
if w > 0 then
BlackBars()
DisplayRadar(0)
SendNUIMessage({
action = 'hudtick',
show = false,
})
SendNUIMessage({
action = 'car',
show = false,
})
end
Wait(0)
end
end)

-- Compass
function round(num, numDecimalPlaces)
local mult = 10 ^ (numDecimalPlaces or 0)
return math.floor(num + 0.5 * mult)
end

local prevBaseplateStats = { nil, nil, nil, nil, nil, nil, nil }

local function updateBaseplateHud(data)
local shouldUpdate = false
for k, v in pairs(data) do
if prevBaseplateStats[k] ~= v then
shouldUpdate = true
break
end
end
prevBaseplateStats = data
if shouldUpdate then
SendNUIMessage({
action = 'baseplate',
show = data[1],
street1 = data[2],
street2 = data[3],
showCompass = data[4],
showStreets = data[5],
showPointer = data[6],
showDegrees = data[7],
})
end
end

local lastCrossroadUpdate = 0
local lastCrossroadCheck = {}

local function getCrossroads(player)
local updateTick = GetGameTimer()
if updateTick - lastCrossroadUpdate > 1500 then
local pos = GetEntityCoords(player)
local street1, street2 = GetStreetNameAtCoord(pos.x, pos.y, pos.z)
lastCrossroadUpdate = updateTick
lastCrossroadCheck = { GetStreetNameFromHashKey(street1), GetStreetNameFromHashKey(street2) }
end
return lastCrossroadCheck
end

-- Compass Update loop

CreateThread(function()
local lastHeading = 1
local heading
while true do
if Menu.isChangeCompassFPSChecked then
Wait(50)
else
Wait(0)
end
local show = true
local player = PlayerPedId()
local camRot = GetGameplayCamRot(0)
if Menu.isCompassFollowChecked then
heading = tostring(round(360.0 - ((camRot.z + 360.0) % 360.0)))
else
heading = tostring(round(360.0 - GetEntityHeading(player)))
end
if heading == '360' then heading = '0' end
if heading ~= lastHeading then
if IsPedInAnyVehicle(player) then
local crossroads = getCrossroads(player)
SendNUIMessage({
action = 'update',
value = heading
})
updateBaseplateHud({
show,
crossroads[1],
crossroads[2],
Menu.isCompassShowChecked,
Menu.isShowStreetsChecked,
Menu.isPointerShowChecked,
Menu.isDegreesShowChecked,
})
else
if Menu.isOutCompassChecked then
SendNUIMessage({
action = 'update',
value = heading
})
SendNUIMessage({
action = 'baseplate',
show = true,
showCompass = true,
})
else
SendNUIMessage({
action = 'baseplate',
show = false,
})
end
end
end
lastHeading = heading
end
end)

NEW SERVER CODE:

local QBCore = exports['qb-core']:GetCoreObject()
local ResetStress = false
local hiddenStates = {} -- Added Variable to track hud toggle state (On/Off)

QBCore.Commands.Add('cash', 'Check Cash Balance', {}, false, function(source, _)
local Player = QBCore.Functions.GetPlayer(source)
local cashamount = Player.PlayerData.money.cash
TriggerClientEvent('hud:client:ShowAccounts', source, 'cash', cashamount)
end)

QBCore.Commands.Add('bank', 'Check Bank Balance', {}, false, function(source, _)
local Player = QBCore.Functions.GetPlayer(source)
local bankamount = Player.PlayerData.money.bank
TriggerClientEvent('hud:client:ShowAccounts', source, 'bank', bankamount)
end)

QBCore.Commands.Add('dev', 'Enable/Disable developer Mode', {}, false, function(source, _)
TriggerClientEvent('qb-admin:client:ToggleDevmode', source)
end, 'admin')

RegisterNetEvent('hud:server:GainStress', function(amount)
if Config.DisableStress then return end
local src = source
local Player = QBCore.Functions.GetPlayer(src)
local Job = Player.PlayerData.job.name
local JobType = Player.PlayerData.job.type
local newStress
if not Player or Config.WhitelistedJobs[JobType] or Config.WhitelistedJobs[Job] then return end
if not ResetStress then
if not Player.PlayerData.metadata['stress'] then
Player.PlayerData.metadata['stress'] = 0
end
newStress = Player.PlayerData.metadata['stress'] + amount
if newStress <= 0 then newStress = 0 end
else
newStress = 0
end
if newStress > 100 then
newStress = 100
end
Player.Functions.SetMetaData('stress', newStress)
TriggerClientEvent('hud:client:UpdateStress', src, newStress)
TriggerClientEvent('QBCore:Notify', src, Lang:t('notify.stress_gain'), 'error', 1500)
end)

RegisterNetEvent('hud:server:RelieveStress', function(amount)
if Config.DisableStress then return end
local src = source
local Player = QBCore.Functions.GetPlayer(src)
local newStress
if not Player then return end
if not ResetStress then
if not Player.PlayerData.metadata['stress'] then
Player.PlayerData.metadata['stress'] = 0
end
newStress = Player.PlayerData.metadata['stress'] - amount
if newStress <= 0 then newStress = 0 end
else
newStress = 0
end
if newStress > 100 then
newStress = 100
end
Player.Functions.SetMetaData('stress', newStress)
TriggerClientEvent('hud:client:UpdateStress', src, newStress)
TriggerClientEvent('QBCore:Notify', src, Lang:t('notify.stress_removed'))
end)

QBCore.Functions.CreateCallback('hud:server:getMenu', function(_, cb)
cb(Config.Menu)
end)

local function ToggleHudForPlayer(source, shouldHide)
TriggerClientEvent('qb-hud:client:ToggleHud', source, shouldHide)
end

exports('ToggleHudForPlayer', ToggleHudForPlayer)

QBCore.Commands.Add('togglehud', 'Toggle HUD visibility', {}, false, function(source)
hiddenStates[source] = not hiddenStates[source]
if hiddenStates[source] then
TriggerClientEvent('QBCore:Notify', source, 'HUD Hidden', 'error')
else
TriggerClientEvent('QBCore:Notify', source, 'HUD Visible', 'success')
end

-- Trigger the client event to actually toggle the HUD
TriggerClientEvent('qb-hud:client:ToggleHud', source)

end)

-- Add player cleanup when they disconnect
AddEventHandler('playerDropped', function()
local source = source
hiddenStates[source] = nil
end)

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions