qb-hud icon indicating copy to clipboard operation
qb-hud copied to clipboard

[SUGGESTION] Feature Addition: Toggle HUD Command

Open LawProductions opened this issue 1 year ago • 3 comments

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)

LawProductions avatar Jan 15 '25 19:01 LawProductions