Skip to content

Improve VehicleInfo Event Handling #1192

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion client/events.lua
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ RegisterNetEvent('QBCore:Client:VehicleInfo', function(info)
local plate = QBCore.Functions.GetPlate(info.vehicle)
local hasKeys = true

if GetResourceState('qb-vehiclekeys') == 'started' then
if GetResourceState('qb-vehiclekeys') == 'started' or GetResourceState('qb-vehiclekeys') == 'starting' then -- qb-vehiclekeys starting AFTER qb-core
hasKeys = exports['qb-vehiclekeys']:HasKeys(plate)
end

Expand Down
279 changes: 279 additions & 0 deletions events.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,279 @@
-- Player load and unload handling
-- New method for checking if logged in across all scripts (optional)
-- if LocalPlayer.state['isLoggedIn'] then
RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function()
ShutdownLoadingScreenNui()
LocalPlayer.state:set('isLoggedIn', true, false)
if not QBCore.Config.Server.PVP then return end
SetCanAttackFriendly(PlayerPedId(), true, false)
NetworkSetFriendlyFireOption(true)
end)

RegisterNetEvent('QBCore:Client:OnPlayerUnload', function()
LocalPlayer.state:set('isLoggedIn', false, false)
end)

RegisterNetEvent('QBCore:Client:PvpHasToggled', function(pvp_state)
SetCanAttackFriendly(PlayerPedId(), pvp_state, false)
NetworkSetFriendlyFireOption(pvp_state)
end)
-- Teleport Commands

RegisterNetEvent('QBCore:Command:TeleportToPlayer', function(coords)
local ped = PlayerPedId()
SetPedCoordsKeepVehicle(ped, coords.x, coords.y, coords.z)
end)

RegisterNetEvent('QBCore:Command:TeleportToCoords', function(x, y, z, h)
local ped = PlayerPedId()
SetPedCoordsKeepVehicle(ped, x, y, z)
SetEntityHeading(ped, h or GetEntityHeading(ped))
end)

RegisterNetEvent('QBCore:Command:GoToMarker', function()
local PlayerPedId = PlayerPedId
local GetEntityCoords = GetEntityCoords
local GetGroundZFor_3dCoord = GetGroundZFor_3dCoord

local blipMarker <const> = GetFirstBlipInfoId(8)
if not DoesBlipExist(blipMarker) then
QBCore.Functions.Notify(Lang:t('error.no_waypoint'), 'error', 5000)
return 'marker'
end

-- Fade screen to hide how clients get teleported.
DoScreenFadeOut(650)
while not IsScreenFadedOut() do
Wait(0)
end

local ped, coords <const> = PlayerPedId(), GetBlipInfoIdCoord(blipMarker)
local vehicle = GetVehiclePedIsIn(ped, false)
local oldCoords <const> = GetEntityCoords(ped)

-- Unpack coords instead of having to unpack them while iterating.
-- 825.0 seems to be the max a player can reach while 0.0 being the lowest.
local x, y, groundZ, Z_START = coords['x'], coords['y'], 850.0, 950.0
local found = false
if vehicle > 0 then
FreezeEntityPosition(vehicle, true)
else
FreezeEntityPosition(ped, true)
end

for i = Z_START, 0, -25.0 do
local z = i
if (i % 2) ~= 0 then
z = Z_START - i
end

NewLoadSceneStart(x, y, z, x, y, z, 50.0, 0)
local curTime = GetGameTimer()
while IsNetworkLoadingScene() do
if GetGameTimer() - curTime > 1000 then
break
end
Wait(0)
end
NewLoadSceneStop()
SetPedCoordsKeepVehicle(ped, x, y, z)

while not HasCollisionLoadedAroundEntity(ped) do
RequestCollisionAtCoord(x, y, z)
if GetGameTimer() - curTime > 1000 then
break
end
Wait(0)
end

-- Get ground coord. As mentioned in the natives, this only works if the client is in render distance.
found, groundZ = GetGroundZFor_3dCoord(x, y, z, false);
if found then
Wait(0)
SetPedCoordsKeepVehicle(ped, x, y, groundZ)
break
end
Wait(0)
end

-- Remove black screen once the loop has ended.
DoScreenFadeIn(650)
if vehicle > 0 then
FreezeEntityPosition(vehicle, false)
else
FreezeEntityPosition(ped, false)
end

if not found then
-- If we can't find the coords, set the coords to the old ones.
-- We don't unpack them before since they aren't in a loop and only called once.
SetPedCoordsKeepVehicle(ped, oldCoords['x'], oldCoords['y'], oldCoords['z'] - 1.0)
QBCore.Functions.Notify(Lang:t('error.tp_error'), 'error', 5000)
end

-- If Z coord was found, set coords in found coords.
SetPedCoordsKeepVehicle(ped, x, y, groundZ)
QBCore.Functions.Notify(Lang:t('success.teleported_waypoint'), 'success', 5000)
end)

-- Vehicle Commands

RegisterNetEvent('QBCore:Command:SpawnVehicle', function(vehName)
local ped = PlayerPedId()
local hash = joaat(vehName)
local veh = GetVehiclePedIsUsing(ped)
if not IsModelInCdimage(hash) then return end
RequestModel(hash)
while not HasModelLoaded(hash) do
Wait(0)
end

if IsPedInAnyVehicle(ped) then
SetEntityAsMissionEntity(veh, true, true)
DeleteVehicle(veh)
end

local vehicle = CreateVehicle(hash, GetEntityCoords(ped), GetEntityHeading(ped), true, false)
TaskWarpPedIntoVehicle(ped, vehicle, -1)
SetVehicleFuelLevel(vehicle, 100.0)
SetVehicleDirtLevel(vehicle, 0.0)
SetModelAsNoLongerNeeded(hash)
TriggerEvent('vehiclekeys:client:SetOwner', QBCore.Functions.GetPlate(vehicle))
end)

RegisterNetEvent('QBCore:Command:DeleteVehicle', function()
local ped = PlayerPedId()
local veh = GetVehiclePedIsUsing(ped)
if veh ~= 0 then
SetEntityAsMissionEntity(veh, true, true)
DeleteVehicle(veh)
else
local pcoords = GetEntityCoords(ped)
local vehicles = GetGamePool('CVehicle')
for _, v in pairs(vehicles) do
if #(pcoords - GetEntityCoords(v)) <= 5.0 then
SetEntityAsMissionEntity(v, true, true)
DeleteVehicle(v)
end
end
end
end)

RegisterNetEvent('QBCore:Client:VehicleInfo', function(info)
local plate = QBCore.Functions.GetPlate(info.vehicle)
local hasKeys = true

if GetResourceState('qb-vehiclekeys') == 'started' or GetResourceState('qb-vehiclekeys') == 'starting' then -- qb-vehiclekeys starting AFTER qb-core
hasKeys = exports['qb-vehiclekeys']:HasKeys(plate)
end

local data = {
vehicle = info.vehicle,
seat = info.seat,
name = info.modelName,
plate = plate,
driver = GetPedInVehicleSeat(info.vehicle, -1),
inseat = GetPedInVehicleSeat(info.vehicle, info.seat),
haskeys = hasKeys
}

TriggerEvent('QBCore:Client:' .. info.event .. 'Vehicle', data)
end)

-- Other stuff

RegisterNetEvent('QBCore:Player:SetPlayerData', function(val)
QBCore.PlayerData = val
end)

RegisterNetEvent('QBCore:Player:UpdatePlayerData', function()
TriggerServerEvent('QBCore:UpdatePlayer')
end)

RegisterNetEvent('QBCore:Notify', function(text, type, length, icon)
QBCore.Functions.Notify(text, type, length, icon)
end)

-- This event is exploitable and should not be used. It has been deprecated, and will be removed soon.
RegisterNetEvent('QBCore:Client:UseItem', function(item)
QBCore.Debug(string.format('%s triggered QBCore:Client:UseItem by ID %s with the following data. This event is deprecated due to exploitation, and will be removed soon. Check qb-inventory for the right use on this event.', GetInvokingResource(), GetPlayerServerId(PlayerId())))
QBCore.Debug(item)
end)

RegisterNUICallback('getNotifyConfig', function(_, cb)
cb(QBCore.Config.Notify)
end)

-- Callback Events --

-- Client Callback
RegisterNetEvent('QBCore:Client:TriggerClientCallback', function(name, ...)
if not QBCore.ClientCallbacks[name] then return end

QBCore.ClientCallbacks[name](function(...)
TriggerServerEvent('QBCore:Server:TriggerClientCallback', name, ...)
end, ...)
end)

-- Server Callback
RegisterNetEvent('QBCore:Client:TriggerCallback', function(name, ...)
if QBCore.ServerCallbacks[name] then
QBCore.ServerCallbacks[name].promise:resolve(...)

if QBCore.ServerCallbacks[name].callback then
QBCore.ServerCallbacks[name].callback(...)
end

QBCore.ServerCallbacks[name] = nil
end
end)

-- Me command

local function Draw3DText(coords, str)
local onScreen, worldX, worldY = World3dToScreen2d(coords.x, coords.y, coords.z)
local camCoords = GetGameplayCamCoord()
local scale = 200 / (GetGameplayCamFov() * #(camCoords - coords))
if onScreen then
SetTextScale(1.0, 0.5 * scale)
SetTextFont(4)
SetTextColour(255, 255, 255, 255)
SetTextEdge(2, 0, 0, 0, 150)
SetTextProportional(1)
SetTextOutline()
SetTextCentre(1)
BeginTextCommandDisplayText('STRING')
AddTextComponentSubstringPlayerName(str)
EndTextCommandDisplayText(worldX, worldY)
end
end

RegisterNetEvent('QBCore:Command:ShowMe3D', function(senderId, msg)
local sender = GetPlayerFromServerId(senderId)
CreateThread(function()
local displayTime = 5000 + GetGameTimer()
while displayTime > GetGameTimer() do
local targetPed = GetPlayerPed(sender)
local tCoords = GetEntityCoords(targetPed)
Draw3DText(tCoords, msg)
Wait(0)
end
end)
end)

-- Listen to Shared being updated
RegisterNetEvent('QBCore:Client:OnSharedUpdate', function(tableName, key, value)
QBCore.Shared[tableName][key] = value
TriggerEvent('QBCore:Client:UpdateObject')
end)

RegisterNetEvent('QBCore:Client:OnSharedUpdateMultiple', function(tableName, values)
for key, value in pairs(values) do
QBCore.Shared[tableName][key] = value
end
TriggerEvent('QBCore:Client:UpdateObject')
end)

RegisterNetEvent('QBCore:Client:SharedUpdate', function(table)
QBCore.Shared = table
end)
Loading