-
Notifications
You must be signed in to change notification settings - Fork 201
Description
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)