220 lines
6.4 KiB
Lua
220 lines
6.4 KiB
Lua
if Config.Framework ~= "esx" then return end
|
||
local function CheckESXStatus()
|
||
local state = GetResourceState('es_extended')
|
||
return state == "started" or state == "starting"
|
||
end
|
||
|
||
ESX = nil
|
||
Core = nil
|
||
|
||
if CheckESXStatus() then
|
||
local ok, result = pcall(function()
|
||
return exports['es_extended']:getSharedObject()
|
||
end)
|
||
|
||
if ok and result then
|
||
ESX = result
|
||
Core = ESX
|
||
print('^2[codem-phone] ^7ESX object retrieved successfully')
|
||
else
|
||
Core = nil
|
||
print('^1[codem-phone] ^7Error: ESX object could not be retrieved')
|
||
return
|
||
end
|
||
else
|
||
Core = nil
|
||
print('^1[codem-phone] ^7Error: es_extended not found or not started')
|
||
return
|
||
end
|
||
|
||
RegisterNetEvent("esx:playerLoaded")
|
||
AddEventHandler("esx:playerLoaded", function(xPlayerData)
|
||
Wait(100)
|
||
if LoadedUI and LoadedUI() then
|
||
TriggerServerEvent('codem-phone:server:LoadPhone')
|
||
end
|
||
end)
|
||
|
||
-- ============= Duty Toggle =============
|
||
-- QBCore: TriggerServerEvent('QBCore:ToggleDuty')
|
||
-- ESX doesn’t have a native toggle; most servers use esx_service/esx_duty or a custom event.
|
||
-- Replace 'esx_duty:toggle' with whatever your duty script exposes.
|
||
function ToggleDuty()
|
||
-- Common patterns (uncomment the one you use):
|
||
-- TriggerServerEvent('esx_service:enableService') -- with args in some forks
|
||
-- TriggerServerEvent('esx_service:disableService')
|
||
-- TriggerServerEvent('esx_duty:toggle')
|
||
TriggerServerEvent('esx_duty:toggle')
|
||
end
|
||
|
||
-- ============= Vehicle Helpers =============
|
||
|
||
local function EnsureTableMods(mods)
|
||
if type(mods) == "string" then
|
||
local ok, decoded = pcall(json.decode, mods)
|
||
if ok and decoded then return decoded end
|
||
return {}
|
||
end
|
||
return mods or {}
|
||
end
|
||
|
||
function ApplyVehicleMods(vehicle, vehicleData)
|
||
if not (vehicle and DoesEntityExist(vehicle)) then return end
|
||
vehicleData = vehicleData or {}
|
||
|
||
-- plate
|
||
if vehicleData.plate then
|
||
SetVehicleNumberPlateText(vehicle, tostring(vehicleData.plate))
|
||
end
|
||
|
||
-- properties (ESX)
|
||
local props = EnsureTableMods(vehicleData.mods)
|
||
ESX.Game.SetVehicleProperties(vehicle, props)
|
||
|
||
if GetResourceState("vehiclekeys") == "started" or GetResourceState("qs-vehiclekeys") == "started" then
|
||
TriggerEvent("vehiclekeys:client:SetOwner", ESX.Math.Trim(GetVehicleNumberPlateText(vehicle)))
|
||
end
|
||
|
||
|
||
if GetResourceState("LegacyFuel") == "started" and vehicleData.fuel then
|
||
exports.LegacyFuel:SetFuel(vehicle, vehicleData.fuel + 0.0)
|
||
end
|
||
|
||
if GetResourceState("lc_fuel") == "started" and vehicleData.fuel then
|
||
exports["lc_fuel"]:SetFuel(vehicle, vehicleData.fuel + 0.0)
|
||
end
|
||
|
||
|
||
if vehicleData.engine then
|
||
SetVehicleEngineHealth(vehicle, vehicleData.engine + 0.0)
|
||
end
|
||
if vehicleData.body then
|
||
SetVehicleBodyHealth(vehicle, vehicleData.body + 0.0)
|
||
end
|
||
end
|
||
|
||
function LoadModel(model)
|
||
local mdl = type(model) == "number" and model or joaat(model)
|
||
if not IsModelInCdimage(mdl) then return nil end
|
||
|
||
RequestModel(mdl)
|
||
while not HasModelLoaded(mdl) do
|
||
Wait(0)
|
||
end
|
||
return mdl
|
||
end
|
||
|
||
function WaitForNetworkId(netId)
|
||
local deadline = GetGameTimer() + 5000
|
||
while not NetworkDoesNetworkIdExist(netId) do
|
||
if GetGameTimer() > deadline then return nil end
|
||
Wait(0)
|
||
end
|
||
|
||
deadline = GetGameTimer() + 5000
|
||
local ent = NetworkGetEntityFromNetworkId(netId)
|
||
while not DoesEntityExist(ent) do
|
||
if GetGameTimer() > deadline then return nil end
|
||
Wait(0)
|
||
ent = NetworkGetEntityFromNetworkId(netId)
|
||
end
|
||
|
||
return ent
|
||
end
|
||
|
||
function CreateFrameworkVehicle(vehicleData, coords, cb)
|
||
if not vehicleData or not coords then
|
||
if cb then cb(nil) end
|
||
return
|
||
end
|
||
|
||
local model = tonumber(vehicleData.hash)
|
||
or (vehicleData.model and joaat(vehicleData.model))
|
||
if not model then
|
||
print("^1[CreateFrameworkVehicle] invalid model/hash^7")
|
||
if cb then cb(nil) end
|
||
return
|
||
end
|
||
|
||
local pos = vector3(coords.x, coords.y, coords.z)
|
||
local heading = coords.w or coords.h or coords.heading or 0.0
|
||
|
||
ESX.Game.SpawnVehicle(model, pos, heading, function(veh)
|
||
if not veh then
|
||
if cb then cb(nil) end
|
||
return
|
||
end
|
||
SetVehicleOnGroundProperly(veh)
|
||
ApplyVehicleMods(veh, vehicleData) -- your existing helper
|
||
SetEntityAsMissionEntity(veh, true, true)
|
||
SetVehicleNeedsToBeHotwired(veh, false)
|
||
if cb then cb(veh) end
|
||
end)
|
||
end
|
||
|
||
function TakeControlOfEntity(entity)
|
||
if not entity or not DoesEntityExist(entity) then return false end
|
||
if NetworkHasControlOfEntity(entity) then return true end
|
||
|
||
local deadline = GetGameTimer() + 5000
|
||
while not NetworkHasControlOfEntity(entity) and GetGameTimer() < deadline do
|
||
NetworkRequestControlOfEntity(entity)
|
||
Wait(0)
|
||
end
|
||
return NetworkHasControlOfEntity(entity)
|
||
end
|
||
|
||
function GiveVehicleKey(vehicle, plate)
|
||
Config.GiveVehicleKey(vehicle, plate)
|
||
end
|
||
|
||
local isDead = false
|
||
AddEventHandler('esx:onPlayerDeath', function() isDead = true end)
|
||
AddEventHandler('esx:onPlayerSpawn', function() isDead = false end)
|
||
|
||
function CanPhoneOpen()
|
||
local isHandcuffed = false
|
||
local inLastStand = false
|
||
|
||
if isHandcuffed or isDead or inLastStand then
|
||
return false
|
||
end
|
||
|
||
return true
|
||
end
|
||
|
||
local hadPhoneBefore = nil
|
||
RegisterNetEvent("esx:removeInventoryItem", function(item, count)
|
||
if not Config.ItemRequired then
|
||
return
|
||
end
|
||
|
||
if item ~= Config.ItemName then
|
||
return
|
||
end
|
||
|
||
if hadPhoneBefore == nil then
|
||
hadPhoneBefore = HasPhoneItems()
|
||
return
|
||
end
|
||
|
||
local hasPhoneNow = HasPhoneItems()
|
||
if hadPhoneBefore and not hasPhoneNow then
|
||
Wait(500)
|
||
if Config.UniquePhone then
|
||
if ClientPhoneNumber then
|
||
local result = RPC.execute('codem-phone:server:CheckPhoneAfterDrop', ClientPhoneNumber)
|
||
if result and result.shouldClose then
|
||
CloseAllPhoneActivities()
|
||
end
|
||
end
|
||
else
|
||
if CloseAllPhoneActivities then
|
||
CloseAllPhoneActivities()
|
||
end
|
||
end
|
||
end
|
||
|
||
hadPhoneBefore = hasPhoneNow
|
||
end)
|