[Asking] Vanilla Pause Menu with title AND subtitle

Hello there,

I’m looking to customize my server!
I’ve lost my oldest backup that had THIS so I know this existed for a long time and searching since two completes hours using three differents methods including AI to FIND this but…welp.

CreateThread(function()
   Citizen.InvokeNative(GetHashKey("ADD_TEXT_ENTRY"),'FE_THDR_GTAO', 'TITLE')
   Citizen.InvokeNative(GetHashKey("ADD_TEXT_ENTRY"),'PM_SCR_MAP', 'MAP')
   Citizen.InvokeNative(GetHashKey("ADD_TEXT_ENTRY"),'PM_SCR_GAM', 'GAME')
   Citizen.InvokeNative(GetHashKey("ADD_TEXT_ENTRY"),'PM_PANE_LEAVE', 'DISCONNECT')
   Citizen.InvokeNative(GetHashKey("ADD_TEXT_ENTRY"),'PM_PANE_QUIT', 'QUIT')
   Citizen.InvokeNative(GetHashKey("ADD_TEXT_ENTRY"),'PM_SCR_INF', 'INFO')
   Citizen.InvokeNative(GetHashKey("ADD_TEXT_ENTRY"),'PM_SCR_STA', 'STATS')
   Citizen.InvokeNative(GetHashKey("ADD_TEXT_ENTRY"),'PM_SCR_SET', 'SETTINGS')
   Citizen.InvokeNative(GetHashKey("ADD_TEXT_ENTRY"),'PM_SCR_GAL', 'GALERY')
   Citizen.InvokeNative(GetHashKey("ADD_TEXT_ENTRY"),'PM_SCR_RPL', 'ROCKSTAR EDITOR')
    while true do
        BeginScaleformMovieMethodOnFrontendHeader('SET_HEADING_DETAILS')
        ScaleformMovieMethodAddParamTextureNameString('first line')
        ScaleformMovieMethodAddParamTextureNameString('second line')
        ScaleformMovieMethodAddParamTextureNameString('third line')
        ScaleformMovieMethodAddParamBool(false)
        EndScaleformMovieMethod()
        Citizen.Wait(0)
    end
end)

I KNOW there is a way to display a subtitle between Title and MAP or others tabs.
I am not willing to use NUI.
I do remember having one unique file for that thing over 3 differents servers. And then, nothing.
Can anyone help me please?

Thanks:

you need to call the frontend_header scaleform function
"SET_HEADER_TITLE" with params title, subtitle, shiftUpHeader

also this

    while true do
          BeginScaleformMovieMethodOnFrontendHeader('SET_HEADING_DETAILS')
          ScaleformMovieMethodAddParamTextureNameString('first line')
          ScaleformMovieMethodAddParamTextureNameString('second line')
          ScaleformMovieMethodAddParamTextureNameString('third line')
          ScaleformMovieMethodAddParamBool(false)
          EndScaleformMovieMethod()
        Citizen.Wait(0)
    end

you don’t need to call it every frame.. you can simply call this everytime the game is paused checking the native
local bool = IsPauseMenuActive()

or for a more aggressive check: GetPauseMenuState() != 0

so you won’t need to call the scaleform function “on tick” but only once when the pause menu is opened or once every 1000ms if you want to make it looped.

CreateThread(function()
   Citizen.InvokeNative(GetHashKey("ADD_TEXT_ENTRY"),'FE_THDR_GTAO', 'TITLE')
   Citizen.InvokeNative(GetHashKey("ADD_TEXT_ENTRY"),'PM_SCR_MAP', 'MAP')
   Citizen.InvokeNative(GetHashKey("ADD_TEXT_ENTRY"),'PM_SCR_GAM', 'GAME')
   Citizen.InvokeNative(GetHashKey("ADD_TEXT_ENTRY"),'PM_PANE_LEAVE', 'DISCONNECT')
   Citizen.InvokeNative(GetHashKey("ADD_TEXT_ENTRY"),'PM_PANE_QUIT', 'QUIT')
   Citizen.InvokeNative(GetHashKey("ADD_TEXT_ENTRY"),'PM_SCR_INF', 'INFO')
   Citizen.InvokeNative(GetHashKey("ADD_TEXT_ENTRY"),'PM_SCR_STA', 'STATS')
   Citizen.InvokeNative(GetHashKey("ADD_TEXT_ENTRY"),'PM_SCR_SET', 'SETTINGS')
   Citizen.InvokeNative(GetHashKey("ADD_TEXT_ENTRY"),'PM_SCR_GAL', 'GALERY')
   Citizen.InvokeNative(GetHashKey("ADD_TEXT_ENTRY"),'PM_SCR_RPL', 'ROCKSTAR EDITOR')
   local timer = 500
    while true do
        Wait(timer)
        if IsPauseMenuActive() then
            BeginScaleformMovieMethodOnFrontendHeader('SET_HEADING_DETAILS')
            ScaleformMovieMethodAddParamTextureNameString('first line')
            ScaleformMovieMethodAddParamTextureNameString('second line')
            ScaleformMovieMethodAddParamTextureNameString('third line')
            ScaleformMovieMethodAddParamBool(false)
            EndScaleformMovieMethod()
            -- set the waiting timer to 1000 in pause menu
            if timer == 500 then timer = 1000 end
        end
        -- reset the timer to half second for outside pause menu for a bit more reactivity in checking.
        if timer == 1000 then timer = 500 end
    end
end)

if you want to make your own pause menus customizable and fully controllable :slight_smile: Check ScaleformUI it allows you to make your own Pause Menus and Lobbies.

Hello @manups4e, first of all thanks for your reply.

I obviously already tried to reduce the .Wait, however… It just flickers. Even at 15 or 10 ms. Or 5.
Its some details but yeah.

I dare I knew a almost as short as possible snippet to just do this, even if called every frame. Optimized or not, thats not the guess especially if its 0.03ms loaded 0.02ms in background

I just don’t remind where is that cfx re thread :frowning:

You’re right the game updates the clock time every second resending the 3 lines :thinking:

Hello,

Posting fixed version. It was NOT 1 line only. And it was my bad! Sorry!

core/modules/pausemenu/client/main.lua
-- Framework Get Data
ESX = exports["es_extended"]:getSharedObject()

local name = GetPlayerName(PlayerId())
local id = GetPlayerServerId(PlayerId())
local money = 0

CreateThread(function()
    while not ESX.IsPlayerLoaded() do Wait(200) end
    local function refreshData()
        local data = ESX.GetPlayerData()
        local cash = data.money or 0
        local bank = 0
        name = (data.name and data.name ~= '' and data.name) or name
        for _, acc in ipairs(data.accounts or {}) do
            if acc.name == 'bank' then
                bank = acc.money or 0
                break
            end
        end
        money = cash + bank
    end
    RegisterNetEvent('esx:playerLoaded', refreshData)
    RegisterNetEvent('esx:setAccountMoney', refreshData)
    refreshData()
end)

-- Format Money (as an example : 1000000 to 10 00 000 $)
local function formatMoney(n)
    n = tonumber(n) or 0
    local s = tostring(math.floor(n))
    local out, c = {}, 0
    for i = #s, 1, -1 do
        c = c + 1
        out[#out+1] = s:sub(i,i)
        if c % 3 == 0 and i > 1 then out[#out+1] = " " end
    end
    local r = table.concat(out):reverse()
    return r .. "$"
end

-- Pause Menu Main Function
CreateThread(function()
   Citizen.InvokeNative(GetHashKey("ADD_TEXT_ENTRY"),'PM_SCR_MAP', '~o~GPS')
   Citizen.InvokeNative(GetHashKey("ADD_TEXT_ENTRY"),'PM_SCR_GAM', '~o~Partir')
   Citizen.InvokeNative(GetHashKey("ADD_TEXT_ENTRY"),'PM_PANE_LEAVE', '~o~Quitter server')
   Citizen.InvokeNative(GetHashKey("ADD_TEXT_ENTRY"),'PM_PANE_QUIT', '~r~Quitter FiveM')
   Citizen.InvokeNative(GetHashKey("ADD_TEXT_ENTRY"),'PM_SCR_INF', '~o~Informations')
   Citizen.InvokeNative(GetHashKey("ADD_TEXT_ENTRY"),'PM_SCR_STA', '~o~Statistiques')
   Citizen.InvokeNative(GetHashKey("ADD_TEXT_ENTRY"),'PM_SCR_SET', '~o~Paramètres')
   Citizen.InvokeNative(GetHashKey("ADD_TEXT_ENTRY"),'PM_SCR_GAL', '~o~Galerie')
   Citizen.InvokeNative(GetHashKey("ADD_TEXT_ENTRY"),'PM_SCR_RPL', '~o~Rockstar Editor')
    while true do
        BeginScaleformMovieMethodOnFrontendHeader('SET_HEADING_DETAILS')
        ScaleformMovieMethodAddParamTextureNameString('~o~'..name)
        ScaleformMovieMethodAddParamTextureNameString('~t~ID '..id)
        ScaleformMovieMethodAddParamTextureNameString('~g~'..formatMoney(money))
        ScaleformMovieMethodAddParamBool(false)
        EndScaleformMovieMethod()
        Wait(6) -- Raising this will break/flicker display
    end
end)

local title = 'your server title line'
local subtitle = "your server catchphrase / subtitle"
CreateThread(function()
    while true do
        Wait(6) -- Raising this will break/flicker display
        N_0xb9449845f73f5e9c("SHIFT_CORONA_DESC")
        PushScaleformMovieFunctionParameterBool(true)
        PopScaleformMovieFunction()
        N_0xb9449845f73f5e9c("SET_HEADER_TITLE")
        PushScaleformMovieFunctionParameterString(title)
        PushScaleformMovieFunctionParameterBool(true)
        PushScaleformMovieFunctionParameterString(subtitle)
        PushScaleformMovieFunctionParameterBool(true)
        PopScaleformMovieFunctionVoid()
    end
end)

-- Roleplay Integration while opening Pause Menu
local wasMenuOpen = false
local startedTabletEmote = false
local function disarmOx(noAnim)
    TriggerEvent('ox_inventory:disarm', false)
end

local function startTablet()
    if startedTabletEmote then return end

    disarmOx(true)
    ExecuteCommand('e tablet2')
    ExecuteCommand('me consulte sa tablette')
    startedTabletEmote = true
end

local function stopTablet()
    if not startedTabletEmote then return end
    ExecuteCommand('e c')
    startedTabletEmote = false
end

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

        if IsPauseMenuActive() and not wasMenuOpen then
            startTablet()
            wasMenuOpen = true
        end

        if not IsPauseMenuActive() and wasMenuOpen then
            Wait(2000)
            stopTablet()
            wasMenuOpen = false
        end
    end
end)