monitor/resource/menu/client/cl_main_page.lua
2025-04-16 22:30:27 +07:00

311 lines
9.9 KiB
Lua

-- Prevent running if menu is disabled
if not TX_MENU_ENABLED then return end
-- =============================================
-- This file is for all main page logic not controlled in its
-- own file (mainly simpler logic)
-- =============================================
--[[ NUI CALLBACKS ]]
-- Data is a object with x, y, z
RegisterSecureNuiCallback('tpToCoords', function(data, cb)
debugPrint(json.encode(data))
TriggerServerEvent('txsv:req:tpToCoords', data.x + 0.0, data.y + 0.0, data.z + 0.0)
cb({})
end)
RegisterCommand('txAdmin:menu:tpToCoords', function()
if not menuIsAccessible then return end
if not DoesPlayerHavePerm(menuPermissions, 'players.teleport') then
return sendSnackbarMessage('error', 'nui_menu.misc.no_perms', true)
end
toggleMenuVisibility(true)
SetNuiFocus(true, true)
sendMenuMessage('openTeleportCoordsDialog', {})
end)
local function reqTpToWaypoint(_, cb)
TriggerServerEvent('txsv:req:tpToWaypoint')
if cb then cb({}) end
end
RegisterSecureNuiCallback('tpToWaypoint', reqTpToWaypoint)
RegisterCommand('txAdmin:menu:tpToWaypoint', function()
if not menuIsAccessible then return end
if not DoesPlayerHavePerm(menuPermissions, 'players.teleport') then
return sendSnackbarMessage('error', 'nui_menu.misc.no_perms', true)
end
reqTpToWaypoint()
end)
local function reqTpBack(_, cb)
if lastTpCoords then
TriggerServerEvent('txsv:req:tpToCoords', lastTpCoords.x, lastTpCoords.y, lastTpCoords.z)
else
sendSnackbarMessage('error', 'nui_menu.page_main.teleport.back.error', true)
end
if cb then cb({}) end
end
RegisterSecureNuiCallback('tpBack', reqTpBack)
RegisterCommand('txAdmin:menu:tpBack', function()
if not menuIsAccessible then return end
if not DoesPlayerHavePerm(menuPermissions, 'players.teleport') then
return sendSnackbarMessage('error', 'nui_menu.misc.no_perms', true)
end
reqTpBack()
end)
RegisterSecureNuiCallback('tpToPlayer', function(data, cb)
TriggerServerEvent('txsv:req:tpToPlayer', tonumber(data.id))
cb({})
end)
RegisterSecureNuiCallback('summonPlayer', function(data, cb)
TriggerServerEvent('txsv:req:bringPlayer', tonumber(data.id))
cb({})
end)
RegisterSecureNuiCallback('copyCurrentCoords', function(_, cb)
local ped = PlayerPedId()
local curCoords = GetEntityCoords(ped)
local currHeading = GetEntityHeading(ped)
-- We will cut coords to 4 decimal points
local stringCoords = ('%.4f, %.4f, %.4f, %.4f'):format(curCoords.x, curCoords.y, curCoords.z, currHeading)
cb({ coords = stringCoords })
end)
RegisterSecureNuiCallback('clearArea', function(radius, cb)
TriggerServerEvent('txsv:req:clearArea', radius)
cb({})
end)
RegisterCommand('txAdmin:menu:clearArea', function()
if not menuIsAccessible then return end
if not DoesPlayerHavePerm(menuPermissions, 'menu.clear_area') then
return sendSnackbarMessage('error', 'nui_menu.misc.no_perms', true)
end
toggleMenuVisibility(true)
SetNuiFocus(true, true)
sendMenuMessage('openClearAreaDialog', {})
end)
-- [[ Spawn weapon (only in dev, for now) ]]
RegisterSecureNuiCallback('spawnWeapon', function(weapon, cb)
if not TX_DEBUG_MODE then return end
debugPrint("Spawning weapon: " .. weapon)
GiveWeaponToPed(PlayerPedId(), weapon, 500, false, true)
cb({})
end)
RegisterSecureNuiCallback('healPlayer', function(data, cb)
TriggerServerEvent('txsv:req:healPlayer', tonumber(data.id))
cb({})
end)
local healSelfMessage = 0
local function reqHealMyself(_, cb)
local msg = 'nui_menu.page_main.heal.myself.success_'..healSelfMessage
sendSnackbarMessage('success', msg, true)
healSelfMessage = healSelfMessage + 1
if healSelfMessage > 3 then
healSelfMessage = 0
end
TriggerServerEvent('txsv:req:healMyself')
if cb then cb({}) end
end
RegisterSecureNuiCallback('healMyself', reqHealMyself)
RegisterCommand('txAdmin:menu:healMyself', function()
if not menuIsAccessible then return end
if not DoesPlayerHavePerm(menuPermissions, 'players.heal') then
return sendSnackbarMessage('error', 'nui_menu.misc.no_perms', true)
end
reqHealMyself()
end)
RegisterSecureNuiCallback('healAllPlayers', function(_, cb)
TriggerServerEvent('txsv:req:healEveryone')
cb({})
end)
-- Data will be an object with a message attribute
RegisterSecureNuiCallback('sendAnnouncement', function(data, cb)
TriggerServerEvent('txsv:req:sendAnnouncement', data.message)
cb({})
end)
--[[ EVENT HANDLERS + FUNCTION LOGIC ]]
local function handleTpNormally(x, y, z)
local ped = PlayerPedId()
local veh = GetVehiclePedIsIn(ped, false)
local horse
if IS_FIVEM then
SetPedCoordsKeepVehicle(ped, x, y, 100.0)
else
if IsPedOnMount(ped) then
horse = GetMount(ped)
SetEntityCoords(horse, x, y, 100.0, false, false, false, false)
FreezeEntityPosition(horse, true)
end
SetEntityCoords(ped, x, y, 100.0, false, false, false, false)
end
--Prepare vehicle
if veh > 0 then
if IS_REDM then
SetVehicleCanBreak(veh, false)
SetVehicleWheelsCanBreak(veh, false)
SetEntityCollision(veh, false, false)
SetEntityCoords(veh, x, y, 100.0, false, false, false, false)
SetPedIntoVehicle(ped, veh, -1)
end
FreezeEntityPosition(veh, true)
else
FreezeEntityPosition(ped, true)
end
while IsEntityWaitingForWorldCollision(ped) do
debugPrint("waiting for collision...")
Wait(100)
end
-- Automatically calculate ground Z
if z == 0 then
local _finalZ
local DELAY = 500
for i = 1, 5 do
if _finalZ ~= nil then break end
debugPrint("Z calc attempt #" .. i .. " (" .. (i * DELAY) .. "ms)")
_finalZ = FindZForCoords(x, y)
if _z == nil then
debugPrint("Didn't resolve! Trying again in " .. DELAY)
Wait(DELAY)
end
end
if _finalZ ~= nil then
z = _finalZ
end
end
-- Teleport to targert
ped = PlayerPedId() --update ped id
if IS_FIVEM then
SetPedCoordsKeepVehicle(ped, x, y, z)
else
if horse then
SetEntityCoords(horse, x, y, z + 0.5, false, false, false, false)
FreezeEntityPosition(horse, false)
end
SetEntityCoords(ped, x, y, z + 0.5, false, false, false, false)
end
-- handle vehicle teleport
if veh > 0 then
veh = GetVehiclePedIsIn(ped, false) --update veh id
SetEntityAlpha(veh, 125)
SetEntityCoords(veh, x, y, z + 0.5, false, false, false, false)
SetPedIntoVehicle(ped, veh, -1)
SetVehicleOnGroundProperly(veh)
SetEntityCollision(veh, true, true)
FreezeEntityPosition(veh, false)
CreateThread(function()
Wait(2000)
ResetEntityAlpha(veh)
SetVehicleCanBreak(veh, true)
SetVehicleWheelsCanBreak(veh, true)
end)
else
FreezeEntityPosition(ped, false)
end
-- point camera to the ped direction
if IS_FIVEM then
SetGameplayCamRelativeHeading(0)
else
Citizen.InvokeNative(0x14F3947318CA8AD2, 0.0, 0.0) -- SetThirdPersonCamRelativeHeadingLimitsThisUpdate
end
end
local function handleTpForFreecam(x, y, z)
debugPrint("Handling TP for freecam")
local ped = PlayerPedId()
-- As we allow the freecam to have a vehicle attached. We need to make
-- sure to teleport this as well
local veh = GetVehiclePedIsIn(ped, false)
debugPrint('Freecam has vehicle attached: ' .. tostring(veh))
if veh and veh > 0 then
SetEntityCoords(veh, x, y, z)
end
SetFreecamPosition(x, y, z)
end
local function teleportToCoords(coords)
if type(coords) ~= 'vector3' then
return debugPrint("^1Invalid coords")
end
local x = coords[1]
local y = coords[2]
local z = coords[3]
local ped = PlayerPedId()
DoScreenFadeOut(500)
while not IsScreenFadedOut() do Wait(0) end
if IsFreecamActive() then
local curCamPos = GetFreecamPosition()
lastTpCoords = curCamPos
handleTpForFreecam(x, y, z)
else
lastTpCoords = GetEntityCoords(ped)
handleTpNormally(x, y, z)
end
DoScreenFadeIn(500)
end
--- Teleport the player to the coordinates
---@param x number
---@param y number
---@param z number
RegisterNetEvent('txcl:tpToCoords', function(x, y, z)
teleportToCoords(vec3(x, y, z))
return sendSnackbarMessage('success', 'nui_menu.page_main.teleport.generic_success', true)
end)
-- Teleport to the current waypoint
RegisterNetEvent('txcl:tpToWaypoint', function()
if not IsWaypointActive() then
return sendSnackbarMessage('error', 'nui_menu.page_main.teleport.waypoint.error', true)
end
local destCoords
if IS_FIVEM then
local waypoint = GetFirstBlipInfoId(GetWaypointBlipEnumId())
destCoords = GetBlipInfoIdCoord(waypoint)
else
destCoords = GetWaypointCoords()
end
teleportToCoords(vec3(destCoords.x, destCoords.y, 0))
sendSnackbarMessage('success', 'nui_menu.page_main.teleport.generic_success', true)
end)
RegisterNetEvent('txcl:clearArea', function(radius)
sendSnackbarMessage(
'success',
'nui_menu.page_main.clear_area.dialog_success',
true,
{ radius = radius }
)
if IS_REDM then return end
local curCoords = GetEntityCoords(PlayerPedId())
local radiusToFloat = radius + 0.0
debugPrint(('Radius to clear %d'):format(radius))
-- WTF?: User reports that this native actually clears dead peds compared to
-- ClearArea? Weird considering Gottfried updated this native from _CLEAR_AREA_OF_EVERYTHING
-- after found nativedb info. Maybe needs research lmao?
ClearAreaLeaveVehicleHealth(curCoords.x, curCoords.y, curCoords.z, radiusToFloat, false, false, false, false, false)
end)