forked from Simnation/Main
1105 lines
39 KiB
Lua
1105 lines
39 KiB
Lua
QBCore.Functions = {}
|
|
|
|
-- Callbacks
|
|
|
|
function QBCore.Functions.CreateClientCallback(name, cb)
|
|
QBCore.ClientCallbacks[name] = cb
|
|
end
|
|
|
|
function QBCore.Functions.TriggerCallback(name, ...)
|
|
local cb = nil
|
|
local args = { ... }
|
|
|
|
if QBCore.Shared.IsFunction(args[1]) then
|
|
cb = args[1]
|
|
table.remove(args, 1)
|
|
end
|
|
|
|
QBCore.ServerCallbacks[name] = {
|
|
callback = cb,
|
|
promise = promise.new()
|
|
}
|
|
|
|
TriggerServerEvent('QBCore:Server:TriggerCallback', name, table.unpack(args))
|
|
|
|
if cb == nil then
|
|
Citizen.Await(QBCore.ServerCallbacks[name].promise)
|
|
return QBCore.ServerCallbacks[name].promise.value
|
|
end
|
|
end
|
|
|
|
function QBCore.Debug(resource, obj, depth)
|
|
TriggerServerEvent('QBCore:DebugSomething', resource, obj, depth)
|
|
end
|
|
|
|
-- Player
|
|
|
|
function QBCore.Functions.GetPlayerData(cb)
|
|
if not cb then return QBCore.PlayerData end
|
|
cb(QBCore.PlayerData)
|
|
end
|
|
|
|
function QBCore.Functions.GetCoords(entity)
|
|
local coords = GetEntityCoords(entity)
|
|
return vector4(coords.x, coords.y, coords.z, GetEntityHeading(entity))
|
|
end
|
|
|
|
function QBCore.Functions.HasItem(items, amount)
|
|
return exports["tgiann-inventory"]:HasItem(items, amount)
|
|
end
|
|
|
|
---Returns the full character name
|
|
---@return string
|
|
function QBCore.Functions.GetName()
|
|
local charinfo = QBCore.PlayerData.charinfo
|
|
return charinfo.firstname .. ' ' .. charinfo.lastname
|
|
end
|
|
|
|
---@param entity number - The entity to look at
|
|
---@param timeout number - The time in milliseconds before the function times out
|
|
---@param speed number - The speed at which the entity should turn
|
|
---@return number - The time at which the entity was looked at
|
|
function QBCore.Functions.LookAtEntity(entity, timeout, speed)
|
|
local involved = GetInvokingResource()
|
|
if not DoesEntityExist(entity) then
|
|
return involved .. ' :^1 Entity does not exist'
|
|
end
|
|
if type(entity) ~= 'number' then
|
|
return involved .. ' :^1 Entity must be a number'
|
|
end
|
|
if type(speed) ~= 'number' then
|
|
return involved .. ' :^1 Speed must be a number'
|
|
end
|
|
if speed > 5.0 then speed = 5.0 end
|
|
if timeout > 5000 then timeout = 5000 end
|
|
local ped = PlayerPedId()
|
|
local playerPos = GetEntityCoords(ped)
|
|
local targetPos = GetEntityCoords(entity)
|
|
local dx = targetPos.x - playerPos.x
|
|
local dy = targetPos.y - playerPos.y
|
|
local targetHeading = GetHeadingFromVector_2d(dx, dy)
|
|
local turnSpeed
|
|
local startTimeout = GetGameTimer()
|
|
while true do
|
|
local currentHeading = GetEntityHeading(ped)
|
|
local diff = targetHeading - currentHeading
|
|
if math.abs(diff) < 2 then
|
|
break
|
|
end
|
|
if diff < -180 then
|
|
diff = diff + 360
|
|
elseif diff > 180 then
|
|
diff = diff - 360
|
|
end
|
|
turnSpeed = speed + (2.5 - speed) * (1 - math.abs(diff) / 180)
|
|
if diff > 0 then
|
|
currentHeading = currentHeading + turnSpeed
|
|
else
|
|
currentHeading = currentHeading - turnSpeed
|
|
end
|
|
SetEntityHeading(ped, currentHeading)
|
|
Wait(0)
|
|
if (startTimeout + timeout) < GetGameTimer() then break end
|
|
end
|
|
SetEntityHeading(ped, targetHeading)
|
|
end
|
|
|
|
-- Function to run an animation
|
|
--- @param animDic string: The name of the animation dictionary
|
|
--- @param animName string - The name of the animation within the dictionary
|
|
--- @param duration number - The duration of the animation in milliseconds. -1 will play the animation indefinitely
|
|
--- @param upperbodyOnly boolean - If true, the animation will only affect the upper body of the ped
|
|
--- @return number - The timestamp indicating when the animation concluded. For animations set to loop indefinitely, this will still return the maximum duration of the animation.
|
|
function QBCore.Functions.PlayAnim(animDict, animName, upperbodyOnly, duration)
|
|
local invoked = GetInvokingResource()
|
|
local animPromise = promise.new()
|
|
if type(animDict) ~= 'string' or type(animName) ~= 'string' then
|
|
animPromise:reject(invoked .. ' :^1 Wrong type for animDict or animName')
|
|
return animPromise.value
|
|
end
|
|
if not DoesAnimDictExist(animDict) then
|
|
animPromise:reject(invoked .. ' :^1 Animation dictionary does not exist')
|
|
return animPromise.value
|
|
end
|
|
local flags = upperbodyOnly and 16 or 0
|
|
local runTime = duration or -1
|
|
if runTime == -1 then flags = 49 end
|
|
local ped = PlayerPedId()
|
|
local start = GetGameTimer()
|
|
while not HasAnimDictLoaded(animDict) do
|
|
RequestAnimDict(animDict)
|
|
if (GetGameTimer() - start) > 5000 then
|
|
animPromise:reject(invoked .. ' :^1 Animation dictionary failed to load')
|
|
return animPromise.value
|
|
end
|
|
Wait(1)
|
|
end
|
|
TaskPlayAnim(ped, animDict, animName, 8.0, 8.0, runTime, flags, 0, true, true, true)
|
|
Wait(10) -- Wait a bit for the animation to start, then check if it exists
|
|
local currentTime = GetAnimDuration(animDict, animName)
|
|
if currentTime == 0 then
|
|
animPromise:reject(invoked .. ' :^1 Animation does not exist')
|
|
return animPromise.value
|
|
end
|
|
local fullDuration = currentTime * 1000
|
|
-- If duration is provided and is less than the full duration, use it instead
|
|
local waitTime = duration and math.min(duration, fullDuration) or fullDuration
|
|
Wait(waitTime)
|
|
RemoveAnimDict(animDict)
|
|
animPromise:resolve(currentTime)
|
|
return animPromise.value
|
|
end
|
|
|
|
function QBCore.Functions.IsWearingGloves()
|
|
local ped = PlayerPedId()
|
|
local armIndex = GetPedDrawableVariation(ped, 3)
|
|
local model = GetEntityModel(ped)
|
|
if model == `mp_m_freemode_01` then
|
|
if QBCore.Shared.MaleNoGloves[armIndex] then
|
|
return false
|
|
end
|
|
else
|
|
if QBCore.Shared.FemaleNoGloves[armIndex] then
|
|
return false
|
|
end
|
|
end
|
|
return true
|
|
end
|
|
|
|
-- NUI Calls
|
|
|
|
function QBCore.Functions.Notify(text, texttype, length, icon)
|
|
local message = {
|
|
action = 'notify',
|
|
type = texttype or 'primary',
|
|
length = length or 5000,
|
|
}
|
|
|
|
if type(text) == 'table' then
|
|
message.text = text.text or 'Placeholder'
|
|
message.caption = text.caption or 'Placeholder'
|
|
else
|
|
message.text = text
|
|
end
|
|
|
|
if icon then
|
|
message.icon = icon
|
|
end
|
|
|
|
SendNUIMessage(message)
|
|
end
|
|
|
|
function QBCore.Functions.Progressbar(name, label, duration, useWhileDead, canCancel, disableControls, animation, prop, propTwo, onFinish, onCancel)
|
|
if GetResourceState('progressbar') ~= 'started' then error('progressbar needs to be started in order for QBCore.Functions.Progressbar to work') end
|
|
exports['progressbar']:Progress({
|
|
name = name:lower(),
|
|
duration = duration,
|
|
label = label,
|
|
useWhileDead = useWhileDead,
|
|
canCancel = canCancel,
|
|
controlDisables = disableControls,
|
|
animation = animation,
|
|
prop = prop,
|
|
propTwo = propTwo,
|
|
}, function(cancelled)
|
|
if not cancelled then
|
|
if onFinish then
|
|
onFinish()
|
|
end
|
|
else
|
|
if onCancel then
|
|
onCancel()
|
|
end
|
|
end
|
|
end)
|
|
end
|
|
|
|
-- World Getters
|
|
|
|
function QBCore.Functions.GetVehicles()
|
|
return GetGamePool('CVehicle')
|
|
end
|
|
|
|
function QBCore.Functions.GetObjects()
|
|
return GetGamePool('CObject')
|
|
end
|
|
|
|
function QBCore.Functions.GetPlayers()
|
|
return GetActivePlayers()
|
|
end
|
|
|
|
function QBCore.Functions.GetPlayersFromCoords(coords, distance)
|
|
local players = GetActivePlayers()
|
|
local ped = PlayerPedId()
|
|
if coords then
|
|
coords = type(coords) == 'table' and vec3(coords.x, coords.y, coords.z) or coords
|
|
else
|
|
coords = GetEntityCoords(ped)
|
|
end
|
|
distance = distance or 5
|
|
local closePlayers = {}
|
|
for _, player in ipairs(players) do
|
|
local targetCoords = GetEntityCoords(GetPlayerPed(player))
|
|
local targetdistance = #(targetCoords - coords)
|
|
if targetdistance <= distance then
|
|
closePlayers[#closePlayers + 1] = player
|
|
end
|
|
end
|
|
return closePlayers
|
|
end
|
|
|
|
function QBCore.Functions.GetClosestPlayer(coords)
|
|
local ped = PlayerPedId()
|
|
if coords then
|
|
coords = type(coords) == 'table' and vec3(coords.x, coords.y, coords.z) or coords
|
|
else
|
|
coords = GetEntityCoords(ped)
|
|
end
|
|
local closestPlayers = QBCore.Functions.GetPlayersFromCoords(coords)
|
|
local closestDistance = -1
|
|
local closestPlayer = -1
|
|
for i = 1, #closestPlayers, 1 do
|
|
if closestPlayers[i] ~= PlayerId() and closestPlayers[i] ~= -1 then
|
|
local pos = GetEntityCoords(GetPlayerPed(closestPlayers[i]))
|
|
local distance = #(pos - coords)
|
|
|
|
if closestDistance == -1 or closestDistance > distance then
|
|
closestPlayer = closestPlayers[i]
|
|
closestDistance = distance
|
|
end
|
|
end
|
|
end
|
|
return closestPlayer, closestDistance
|
|
end
|
|
|
|
function QBCore.Functions.GetPeds(ignoreList)
|
|
local pedPool = GetGamePool('CPed')
|
|
local peds = {}
|
|
local ignoreTable = {}
|
|
ignoreList = ignoreList or {}
|
|
for i = 1, #ignoreList do
|
|
ignoreTable[ignoreList[i]] = true
|
|
end
|
|
for i = 1, #pedPool do
|
|
if not ignoreTable[pedPool[i]] then
|
|
peds[#peds + 1] = pedPool[i]
|
|
end
|
|
end
|
|
return peds
|
|
end
|
|
|
|
function QBCore.Functions.GetClosestPed(coords, ignoreList)
|
|
local ped = PlayerPedId()
|
|
if coords then
|
|
coords = type(coords) == 'table' and vec3(coords.x, coords.y, coords.z) or coords
|
|
else
|
|
coords = GetEntityCoords(ped)
|
|
end
|
|
ignoreList = ignoreList or {}
|
|
local peds = QBCore.Functions.GetPeds(ignoreList)
|
|
local closestDistance = -1
|
|
local closestPed = -1
|
|
for i = 1, #peds, 1 do
|
|
local pedCoords = GetEntityCoords(peds[i])
|
|
local distance = #(pedCoords - coords)
|
|
|
|
if closestDistance == -1 or closestDistance > distance then
|
|
closestPed = peds[i]
|
|
closestDistance = distance
|
|
end
|
|
end
|
|
return closestPed, closestDistance
|
|
end
|
|
|
|
function QBCore.Functions.GetClosestVehicle(coords)
|
|
local ped = PlayerPedId()
|
|
local vehicles = GetGamePool('CVehicle')
|
|
local closestDistance = -1
|
|
local closestVehicle = -1
|
|
if coords then
|
|
coords = type(coords) == 'table' and vec3(coords.x, coords.y, coords.z) or coords
|
|
else
|
|
coords = GetEntityCoords(ped)
|
|
end
|
|
for i = 1, #vehicles, 1 do
|
|
local vehicleCoords = GetEntityCoords(vehicles[i])
|
|
local distance = #(vehicleCoords - coords)
|
|
|
|
if closestDistance == -1 or closestDistance > distance then
|
|
closestVehicle = vehicles[i]
|
|
closestDistance = distance
|
|
end
|
|
end
|
|
return closestVehicle, closestDistance
|
|
end
|
|
|
|
function QBCore.Functions.GetClosestObject(coords)
|
|
local ped = PlayerPedId()
|
|
local objects = GetGamePool('CObject')
|
|
local closestDistance = -1
|
|
local closestObject = -1
|
|
if coords then
|
|
coords = type(coords) == 'table' and vec3(coords.x, coords.y, coords.z) or coords
|
|
else
|
|
coords = GetEntityCoords(ped)
|
|
end
|
|
for i = 1, #objects, 1 do
|
|
local objectCoords = GetEntityCoords(objects[i])
|
|
local distance = #(objectCoords - coords)
|
|
if closestDistance == -1 or closestDistance > distance then
|
|
closestObject = objects[i]
|
|
closestDistance = distance
|
|
end
|
|
end
|
|
return closestObject, closestDistance
|
|
end
|
|
|
|
-- Vehicle
|
|
|
|
function QBCore.Functions.LoadModel(model)
|
|
if HasModelLoaded(model) then return end
|
|
RequestModel(model)
|
|
while not HasModelLoaded(model) do
|
|
Wait(0)
|
|
end
|
|
end
|
|
|
|
function QBCore.Functions.SpawnVehicle(model, cb, coords, isnetworked, teleportInto)
|
|
local ped = PlayerPedId()
|
|
model = type(model) == 'string' and joaat(model) or model
|
|
if not IsModelInCdimage(model) then return end
|
|
if coords then
|
|
coords = type(coords) == 'table' and vec3(coords.x, coords.y, coords.z) or coords
|
|
else
|
|
coords = GetEntityCoords(ped)
|
|
end
|
|
isnetworked = isnetworked == nil or isnetworked
|
|
QBCore.Functions.LoadModel(model)
|
|
local veh = CreateVehicle(model, coords.x, coords.y, coords.z, coords.w, isnetworked, false)
|
|
local netid = NetworkGetNetworkIdFromEntity(veh)
|
|
SetVehicleHasBeenOwnedByPlayer(veh, true)
|
|
SetNetworkIdCanMigrate(netid, true)
|
|
SetVehicleNeedsToBeHotwired(veh, false)
|
|
SetVehRadioStation(veh, 'OFF')
|
|
SetVehicleFuelLevel(veh, 100.0)
|
|
SetModelAsNoLongerNeeded(model)
|
|
if teleportInto then TaskWarpPedIntoVehicle(PlayerPedId(), veh, -1) end
|
|
if cb then cb(veh) end
|
|
end
|
|
|
|
function QBCore.Functions.DeleteVehicle(vehicle)
|
|
SetEntityAsMissionEntity(vehicle, true, true)
|
|
DeleteVehicle(vehicle)
|
|
end
|
|
|
|
function QBCore.Functions.GetPlate(vehicle)
|
|
if vehicle == 0 then return end
|
|
return QBCore.Shared.Trim(GetVehicleNumberPlateText(vehicle))
|
|
end
|
|
|
|
function QBCore.Functions.GetVehicleLabel(vehicle)
|
|
if vehicle == nil or vehicle == 0 then return end
|
|
return GetLabelText(GetDisplayNameFromVehicleModel(GetEntityModel(vehicle)))
|
|
end
|
|
|
|
function QBCore.Functions.GetVehicleProperties(vehicle)
|
|
if DoesEntityExist(vehicle) then
|
|
local pearlescentColor, wheelColor = GetVehicleExtraColours(vehicle)
|
|
|
|
local colorPrimary, colorSecondary = GetVehicleColours(vehicle)
|
|
if GetIsVehiclePrimaryColourCustom(vehicle) then
|
|
local r, g, b = GetVehicleCustomPrimaryColour(vehicle)
|
|
colorPrimary = { r, g, b }
|
|
end
|
|
|
|
if GetIsVehicleSecondaryColourCustom(vehicle) then
|
|
local r, g, b = GetVehicleCustomSecondaryColour(vehicle)
|
|
colorSecondary = { r, g, b }
|
|
end
|
|
|
|
local extras = {}
|
|
for extraId = 0, 12 do
|
|
if DoesExtraExist(vehicle, extraId) then
|
|
local state = IsVehicleExtraTurnedOn(vehicle, extraId) == 1
|
|
extras[tostring(extraId)] = state
|
|
end
|
|
end
|
|
|
|
local modLivery = GetVehicleMod(vehicle, 48)
|
|
if GetVehicleMod(vehicle, 48) == -1 and GetVehicleLivery(vehicle) ~= 0 then
|
|
modLivery = GetVehicleLivery(vehicle)
|
|
end
|
|
|
|
local tireHealth = {}
|
|
for i = 0, 3 do
|
|
tireHealth[i] = GetVehicleWheelHealth(vehicle, i)
|
|
end
|
|
|
|
local tireBurstState = {}
|
|
for i = 0, 5 do
|
|
tireBurstState[i] = IsVehicleTyreBurst(vehicle, i, false)
|
|
end
|
|
|
|
local tireBurstCompletely = {}
|
|
for i = 0, 5 do
|
|
tireBurstCompletely[i] = IsVehicleTyreBurst(vehicle, i, true)
|
|
end
|
|
|
|
local windowStatus = {}
|
|
for i = 0, 7 do
|
|
windowStatus[i] = IsVehicleWindowIntact(vehicle, i) == 1
|
|
end
|
|
|
|
local doorStatus = {}
|
|
for i = 0, 5 do
|
|
doorStatus[i] = IsVehicleDoorDamaged(vehicle, i) == 1
|
|
end
|
|
|
|
local xenonColor
|
|
local hasCustom, r, g, b = GetVehicleXenonLightsCustomColor(vehicle)
|
|
if hasCustom then
|
|
xenonColor = table.pack(r, g, b)
|
|
else
|
|
xenonColor = GetVehicleXenonLightsColor(vehicle)
|
|
end
|
|
|
|
return {
|
|
model = GetEntityModel(vehicle),
|
|
plate = QBCore.Functions.GetPlate(vehicle),
|
|
plateIndex = GetVehicleNumberPlateTextIndex(vehicle),
|
|
bodyHealth = QBCore.Shared.Round(GetVehicleBodyHealth(vehicle), 0.1),
|
|
engineHealth = QBCore.Shared.Round(GetVehicleEngineHealth(vehicle), 0.1),
|
|
tankHealth = QBCore.Shared.Round(GetVehiclePetrolTankHealth(vehicle), 0.1),
|
|
fuelLevel = QBCore.Shared.Round(GetVehicleFuelLevel(vehicle), 0.1),
|
|
dirtLevel = QBCore.Shared.Round(GetVehicleDirtLevel(vehicle), 0.1),
|
|
oilLevel = QBCore.Shared.Round(GetVehicleOilLevel(vehicle), 0.1),
|
|
color1 = colorPrimary,
|
|
color2 = colorSecondary,
|
|
pearlescentColor = pearlescentColor,
|
|
dashboardColor = GetVehicleDashboardColour(vehicle),
|
|
wheelColor = wheelColor,
|
|
wheels = GetVehicleWheelType(vehicle),
|
|
wheelSize = GetVehicleWheelSize(vehicle),
|
|
wheelWidth = GetVehicleWheelWidth(vehicle),
|
|
tireHealth = tireHealth,
|
|
tireBurstState = tireBurstState,
|
|
tireBurstCompletely = tireBurstCompletely,
|
|
windowTint = GetVehicleWindowTint(vehicle),
|
|
windowStatus = windowStatus,
|
|
doorStatus = doorStatus,
|
|
neonEnabled = {
|
|
IsVehicleNeonLightEnabled(vehicle, 0),
|
|
IsVehicleNeonLightEnabled(vehicle, 1),
|
|
IsVehicleNeonLightEnabled(vehicle, 2),
|
|
IsVehicleNeonLightEnabled(vehicle, 3)
|
|
},
|
|
neonColor = table.pack(GetVehicleNeonLightsColour(vehicle)),
|
|
interiorColor = GetVehicleInteriorColour(vehicle),
|
|
extras = extras,
|
|
tyreSmokeColor = table.pack(GetVehicleTyreSmokeColor(vehicle)),
|
|
xenonColor = xenonColor,
|
|
modSpoilers = GetVehicleMod(vehicle, 0),
|
|
modFrontBumper = GetVehicleMod(vehicle, 1),
|
|
modRearBumper = GetVehicleMod(vehicle, 2),
|
|
modSideSkirt = GetVehicleMod(vehicle, 3),
|
|
modExhaust = GetVehicleMod(vehicle, 4),
|
|
modFrame = GetVehicleMod(vehicle, 5),
|
|
modGrille = GetVehicleMod(vehicle, 6),
|
|
modHood = GetVehicleMod(vehicle, 7),
|
|
modFender = GetVehicleMod(vehicle, 8),
|
|
modRightFender = GetVehicleMod(vehicle, 9),
|
|
modRoof = GetVehicleMod(vehicle, 10),
|
|
modEngine = GetVehicleMod(vehicle, 11),
|
|
modBrakes = GetVehicleMod(vehicle, 12),
|
|
modTransmission = GetVehicleMod(vehicle, 13),
|
|
modHorns = GetVehicleMod(vehicle, 14),
|
|
modSuspension = GetVehicleMod(vehicle, 15),
|
|
modArmor = GetVehicleMod(vehicle, 16),
|
|
modKit17 = GetVehicleMod(vehicle, 17),
|
|
modTurbo = IsToggleModOn(vehicle, 18),
|
|
modKit19 = GetVehicleMod(vehicle, 19),
|
|
modSmokeEnabled = IsToggleModOn(vehicle, 20),
|
|
modKit21 = GetVehicleMod(vehicle, 21),
|
|
modXenon = IsToggleModOn(vehicle, 22),
|
|
modFrontWheels = GetVehicleMod(vehicle, 23),
|
|
modBackWheels = GetVehicleMod(vehicle, 24),
|
|
modCustomTiresF = GetVehicleModVariation(vehicle, 23),
|
|
modCustomTiresR = GetVehicleModVariation(vehicle, 24),
|
|
modPlateHolder = GetVehicleMod(vehicle, 25),
|
|
modVanityPlate = GetVehicleMod(vehicle, 26),
|
|
modTrimA = GetVehicleMod(vehicle, 27),
|
|
modOrnaments = GetVehicleMod(vehicle, 28),
|
|
modDashboard = GetVehicleMod(vehicle, 29),
|
|
modDial = GetVehicleMod(vehicle, 30),
|
|
modDoorSpeaker = GetVehicleMod(vehicle, 31),
|
|
modSeats = GetVehicleMod(vehicle, 32),
|
|
modSteeringWheel = GetVehicleMod(vehicle, 33),
|
|
modShifterLeavers = GetVehicleMod(vehicle, 34),
|
|
modAPlate = GetVehicleMod(vehicle, 35),
|
|
modSpeakers = GetVehicleMod(vehicle, 36),
|
|
modTrunk = GetVehicleMod(vehicle, 37),
|
|
modHydrolic = GetVehicleMod(vehicle, 38),
|
|
modEngineBlock = GetVehicleMod(vehicle, 39),
|
|
modAirFilter = GetVehicleMod(vehicle, 40),
|
|
modStruts = GetVehicleMod(vehicle, 41),
|
|
modArchCover = GetVehicleMod(vehicle, 42),
|
|
modAerials = GetVehicleMod(vehicle, 43),
|
|
modTrimB = GetVehicleMod(vehicle, 44),
|
|
modTank = GetVehicleMod(vehicle, 45),
|
|
modWindows = GetVehicleMod(vehicle, 46),
|
|
modKit47 = GetVehicleMod(vehicle, 47),
|
|
modLivery = modLivery,
|
|
modKit49 = GetVehicleMod(vehicle, 49),
|
|
liveryRoof = GetVehicleRoofLivery(vehicle),
|
|
}
|
|
else
|
|
return
|
|
end
|
|
end
|
|
|
|
function QBCore.Functions.SetVehicleProperties(vehicle, props)
|
|
if DoesEntityExist(vehicle) then
|
|
if props.extras then
|
|
for id, enabled in pairs(props.extras) do
|
|
if enabled then
|
|
SetVehicleExtra(vehicle, tonumber(id), 0)
|
|
else
|
|
SetVehicleExtra(vehicle, tonumber(id), 1)
|
|
end
|
|
end
|
|
end
|
|
|
|
local colorPrimary, colorSecondary = GetVehicleColours(vehicle)
|
|
local pearlescentColor, wheelColor = GetVehicleExtraColours(vehicle)
|
|
SetVehicleModKit(vehicle, 0)
|
|
if props.plate then
|
|
SetVehicleNumberPlateText(vehicle, props.plate)
|
|
end
|
|
if props.plateIndex then
|
|
SetVehicleNumberPlateTextIndex(vehicle, props.plateIndex)
|
|
end
|
|
if props.bodyHealth then
|
|
SetVehicleBodyHealth(vehicle, props.bodyHealth + 0.0)
|
|
end
|
|
if props.engineHealth then
|
|
SetVehicleEngineHealth(vehicle, props.engineHealth + 0.0)
|
|
end
|
|
if props.tankHealth then
|
|
SetVehiclePetrolTankHealth(vehicle, props.tankHealth + 0.0)
|
|
end
|
|
if props.fuelLevel then
|
|
SetVehicleFuelLevel(vehicle, props.fuelLevel + 0.0)
|
|
end
|
|
if props.dirtLevel then
|
|
SetVehicleDirtLevel(vehicle, props.dirtLevel + 0.0)
|
|
end
|
|
if props.oilLevel then
|
|
SetVehicleOilLevel(vehicle, props.oilLevel + 0.0)
|
|
end
|
|
if props.color1 then
|
|
if type(props.color1) == 'number' then
|
|
ClearVehicleCustomPrimaryColour(vehicle)
|
|
SetVehicleColours(vehicle, props.color1, colorSecondary)
|
|
else
|
|
SetVehicleCustomPrimaryColour(vehicle, props.color1[1], props.color1[2], props.color1[3])
|
|
end
|
|
end
|
|
if props.color2 then
|
|
if type(props.color2) == 'number' then
|
|
ClearVehicleCustomSecondaryColour(vehicle)
|
|
SetVehicleColours(vehicle, props.color1 or colorPrimary, props.color2)
|
|
else
|
|
SetVehicleCustomSecondaryColour(vehicle, props.color2[1], props.color2[2], props.color2[3])
|
|
end
|
|
end
|
|
if props.pearlescentColor then
|
|
SetVehicleExtraColours(vehicle, props.pearlescentColor, wheelColor)
|
|
end
|
|
if props.interiorColor then
|
|
SetVehicleInteriorColor(vehicle, props.interiorColor)
|
|
end
|
|
if props.dashboardColor then
|
|
SetVehicleDashboardColour(vehicle, props.dashboardColor)
|
|
end
|
|
if props.wheelColor then
|
|
SetVehicleExtraColours(vehicle, props.pearlescentColor or pearlescentColor, props.wheelColor)
|
|
end
|
|
if props.wheels then
|
|
SetVehicleWheelType(vehicle, props.wheels)
|
|
end
|
|
if props.tireHealth then
|
|
for wheelIndex, health in pairs(props.tireHealth) do
|
|
SetVehicleWheelHealth(vehicle, wheelIndex, health)
|
|
end
|
|
end
|
|
if props.tireBurstState then
|
|
for wheelIndex, burstState in pairs(props.tireBurstState) do
|
|
if burstState then
|
|
SetVehicleTyreBurst(vehicle, tonumber(wheelIndex), false, 1000.0)
|
|
end
|
|
end
|
|
end
|
|
if props.tireBurstCompletely then
|
|
for wheelIndex, burstState in pairs(props.tireBurstCompletely) do
|
|
if burstState then
|
|
SetVehicleTyreBurst(vehicle, tonumber(wheelIndex), true, 1000.0)
|
|
end
|
|
end
|
|
end
|
|
if props.windowTint then
|
|
SetVehicleWindowTint(vehicle, props.windowTint)
|
|
end
|
|
if props.windowStatus then
|
|
for windowIndex, smashWindow in pairs(props.windowStatus) do
|
|
if not smashWindow then SmashVehicleWindow(vehicle, windowIndex) end
|
|
end
|
|
end
|
|
if props.doorStatus then
|
|
for doorIndex, breakDoor in pairs(props.doorStatus) do
|
|
if breakDoor then
|
|
SetVehicleDoorBroken(vehicle, tonumber(doorIndex), true)
|
|
end
|
|
end
|
|
end
|
|
if props.neonEnabled then
|
|
SetVehicleNeonLightEnabled(vehicle, 0, props.neonEnabled[1])
|
|
SetVehicleNeonLightEnabled(vehicle, 1, props.neonEnabled[2])
|
|
SetVehicleNeonLightEnabled(vehicle, 2, props.neonEnabled[3])
|
|
SetVehicleNeonLightEnabled(vehicle, 3, props.neonEnabled[4])
|
|
end
|
|
if props.neonColor then
|
|
SetVehicleNeonLightsColour(vehicle, props.neonColor[1], props.neonColor[2], props.neonColor[3])
|
|
end
|
|
if props.interiorColor then
|
|
SetVehicleInteriorColour(vehicle, props.interiorColor)
|
|
end
|
|
if props.wheelSize then
|
|
SetVehicleWheelSize(vehicle, props.wheelSize)
|
|
end
|
|
if props.wheelWidth then
|
|
SetVehicleWheelWidth(vehicle, props.wheelWidth)
|
|
end
|
|
if props.tyreSmokeColor then
|
|
SetVehicleTyreSmokeColor(vehicle, props.tyreSmokeColor[1], props.tyreSmokeColor[2], props.tyreSmokeColor[3])
|
|
end
|
|
if props.modSpoilers then
|
|
SetVehicleMod(vehicle, 0, props.modSpoilers, false)
|
|
end
|
|
if props.modFrontBumper then
|
|
SetVehicleMod(vehicle, 1, props.modFrontBumper, false)
|
|
end
|
|
if props.modRearBumper then
|
|
SetVehicleMod(vehicle, 2, props.modRearBumper, false)
|
|
end
|
|
if props.modSideSkirt then
|
|
SetVehicleMod(vehicle, 3, props.modSideSkirt, false)
|
|
end
|
|
if props.modExhaust then
|
|
SetVehicleMod(vehicle, 4, props.modExhaust, false)
|
|
end
|
|
if props.modFrame then
|
|
SetVehicleMod(vehicle, 5, props.modFrame, false)
|
|
end
|
|
if props.modGrille then
|
|
SetVehicleMod(vehicle, 6, props.modGrille, false)
|
|
end
|
|
if props.modHood then
|
|
SetVehicleMod(vehicle, 7, props.modHood, false)
|
|
end
|
|
if props.modFender then
|
|
SetVehicleMod(vehicle, 8, props.modFender, false)
|
|
end
|
|
if props.modRightFender then
|
|
SetVehicleMod(vehicle, 9, props.modRightFender, false)
|
|
end
|
|
if props.modRoof then
|
|
SetVehicleMod(vehicle, 10, props.modRoof, false)
|
|
end
|
|
if props.modEngine then
|
|
SetVehicleMod(vehicle, 11, props.modEngine, false)
|
|
end
|
|
if props.modBrakes then
|
|
SetVehicleMod(vehicle, 12, props.modBrakes, false)
|
|
end
|
|
if props.modTransmission then
|
|
SetVehicleMod(vehicle, 13, props.modTransmission, false)
|
|
end
|
|
if props.modHorns then
|
|
SetVehicleMod(vehicle, 14, props.modHorns, false)
|
|
end
|
|
if props.modSuspension then
|
|
SetVehicleMod(vehicle, 15, props.modSuspension, false)
|
|
end
|
|
if props.modArmor then
|
|
SetVehicleMod(vehicle, 16, props.modArmor, false)
|
|
end
|
|
if props.modKit17 then
|
|
SetVehicleMod(vehicle, 17, props.modKit17, false)
|
|
end
|
|
if props.modTurbo then
|
|
ToggleVehicleMod(vehicle, 18, props.modTurbo)
|
|
end
|
|
if props.modKit19 then
|
|
SetVehicleMod(vehicle, 19, props.modKit19, false)
|
|
end
|
|
if props.modSmokeEnabled then
|
|
ToggleVehicleMod(vehicle, 20, props.modSmokeEnabled)
|
|
end
|
|
if props.modKit21 then
|
|
SetVehicleMod(vehicle, 21, props.modKit21, false)
|
|
end
|
|
if props.modXenon then
|
|
ToggleVehicleMod(vehicle, 22, props.modXenon)
|
|
end
|
|
if props.xenonColor then
|
|
if type(props.xenonColor) == 'table' then
|
|
SetVehicleXenonLightsCustomColor(vehicle, props.xenonColor[1], props.xenonColor[2], props.xenonColor[3])
|
|
else
|
|
SetVehicleXenonLightsColor(vehicle, props.xenonColor)
|
|
end
|
|
end
|
|
if props.modFrontWheels then
|
|
SetVehicleMod(vehicle, 23, props.modFrontWheels, false)
|
|
end
|
|
if props.modBackWheels then
|
|
SetVehicleMod(vehicle, 24, props.modBackWheels, false)
|
|
end
|
|
if props.modCustomTiresF then
|
|
SetVehicleMod(vehicle, 23, props.modFrontWheels, props.modCustomTiresF)
|
|
end
|
|
if props.modCustomTiresR then
|
|
SetVehicleMod(vehicle, 24, props.modBackWheels, props.modCustomTiresR)
|
|
end
|
|
if props.modPlateHolder then
|
|
SetVehicleMod(vehicle, 25, props.modPlateHolder, false)
|
|
end
|
|
if props.modVanityPlate then
|
|
SetVehicleMod(vehicle, 26, props.modVanityPlate, false)
|
|
end
|
|
if props.modTrimA then
|
|
SetVehicleMod(vehicle, 27, props.modTrimA, false)
|
|
end
|
|
if props.modOrnaments then
|
|
SetVehicleMod(vehicle, 28, props.modOrnaments, false)
|
|
end
|
|
if props.modDashboard then
|
|
SetVehicleMod(vehicle, 29, props.modDashboard, false)
|
|
end
|
|
if props.modDial then
|
|
SetVehicleMod(vehicle, 30, props.modDial, false)
|
|
end
|
|
if props.modDoorSpeaker then
|
|
SetVehicleMod(vehicle, 31, props.modDoorSpeaker, false)
|
|
end
|
|
if props.modSeats then
|
|
SetVehicleMod(vehicle, 32, props.modSeats, false)
|
|
end
|
|
if props.modSteeringWheel then
|
|
SetVehicleMod(vehicle, 33, props.modSteeringWheel, false)
|
|
end
|
|
if props.modShifterLeavers then
|
|
SetVehicleMod(vehicle, 34, props.modShifterLeavers, false)
|
|
end
|
|
if props.modAPlate then
|
|
SetVehicleMod(vehicle, 35, props.modAPlate, false)
|
|
end
|
|
if props.modSpeakers then
|
|
SetVehicleMod(vehicle, 36, props.modSpeakers, false)
|
|
end
|
|
if props.modTrunk then
|
|
SetVehicleMod(vehicle, 37, props.modTrunk, false)
|
|
end
|
|
if props.modHydrolic then
|
|
SetVehicleMod(vehicle, 38, props.modHydrolic, false)
|
|
end
|
|
if props.modEngineBlock then
|
|
SetVehicleMod(vehicle, 39, props.modEngineBlock, false)
|
|
end
|
|
if props.modAirFilter then
|
|
SetVehicleMod(vehicle, 40, props.modAirFilter, false)
|
|
end
|
|
if props.modStruts then
|
|
SetVehicleMod(vehicle, 41, props.modStruts, false)
|
|
end
|
|
if props.modArchCover then
|
|
SetVehicleMod(vehicle, 42, props.modArchCover, false)
|
|
end
|
|
if props.modAerials then
|
|
SetVehicleMod(vehicle, 43, props.modAerials, false)
|
|
end
|
|
if props.modTrimB then
|
|
SetVehicleMod(vehicle, 44, props.modTrimB, false)
|
|
end
|
|
if props.modTank then
|
|
SetVehicleMod(vehicle, 45, props.modTank, false)
|
|
end
|
|
if props.modWindows then
|
|
SetVehicleMod(vehicle, 46, props.modWindows, false)
|
|
end
|
|
if props.modKit47 then
|
|
SetVehicleMod(vehicle, 47, props.modKit47, false)
|
|
end
|
|
if props.modLivery then
|
|
SetVehicleMod(vehicle, 48, props.modLivery, false)
|
|
SetVehicleLivery(vehicle, props.modLivery)
|
|
end
|
|
if props.modKit49 then
|
|
SetVehicleMod(vehicle, 49, props.modKit49, false)
|
|
end
|
|
if props.liveryRoof then
|
|
SetVehicleRoofLivery(vehicle, props.liveryRoof)
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Unused
|
|
|
|
function QBCore.Functions.DrawText(x, y, width, height, scale, r, g, b, a, text)
|
|
-- Use local function instead
|
|
SetTextFont(4)
|
|
SetTextScale(scale, scale)
|
|
SetTextColour(r, g, b, a)
|
|
BeginTextCommandDisplayText('STRING')
|
|
AddTextComponentSubstringPlayerName(text)
|
|
EndTextCommandDisplayText(x - width / 2, y - height / 2 + 0.005)
|
|
end
|
|
|
|
function QBCore.Functions.DrawText3D(x, y, z, text)
|
|
-- Use local function instead
|
|
SetTextScale(0.35, 0.35)
|
|
SetTextFont(4)
|
|
SetTextProportional(1)
|
|
SetTextColour(255, 255, 255, 215)
|
|
BeginTextCommandDisplayText('STRING')
|
|
SetTextCentre(true)
|
|
AddTextComponentSubstringPlayerName(text)
|
|
SetDrawOrigin(x, y, z, 0)
|
|
EndTextCommandDisplayText(0.0, 0.0)
|
|
local factor = (string.len(text)) / 370
|
|
DrawRect(0.0, 0.0 + 0.0125, 0.017 + factor, 0.03, 0, 0, 0, 75)
|
|
ClearDrawOrigin()
|
|
end
|
|
|
|
function QBCore.Functions.RequestAnimDict(animDict)
|
|
if HasAnimDictLoaded(animDict) then return end
|
|
RequestAnimDict(animDict)
|
|
while not HasAnimDictLoaded(animDict) do
|
|
Wait(0)
|
|
end
|
|
end
|
|
|
|
function QBCore.Functions.GetClosestBone(entity, list)
|
|
local playerCoords, bone, coords, distance = GetEntityCoords(PlayerPedId())
|
|
for _, element in pairs(list) do
|
|
local boneCoords = GetWorldPositionOfEntityBone(entity, element.id or element)
|
|
local boneDistance = #(playerCoords - boneCoords)
|
|
if not coords then
|
|
bone, coords, distance = element, boneCoords, boneDistance
|
|
elseif distance > boneDistance then
|
|
bone, coords, distance = element, boneCoords, boneDistance
|
|
end
|
|
end
|
|
if not bone then
|
|
bone = { id = GetEntityBoneIndexByName(entity, 'bodyshell'), type = 'remains', name = 'bodyshell' }
|
|
coords = GetWorldPositionOfEntityBone(entity, bone.id)
|
|
distance = #(coords - playerCoords)
|
|
end
|
|
return bone, coords, distance
|
|
end
|
|
|
|
function QBCore.Functions.GetBoneDistance(entity, boneType, boneIndex)
|
|
local bone
|
|
if boneType == 1 then
|
|
bone = GetPedBoneIndex(entity, boneIndex)
|
|
else
|
|
bone = GetEntityBoneIndexByName(entity, boneIndex)
|
|
end
|
|
local boneCoords = GetWorldPositionOfEntityBone(entity, bone)
|
|
local playerCoords = GetEntityCoords(PlayerPedId())
|
|
return #(boneCoords - playerCoords)
|
|
end
|
|
|
|
function QBCore.Functions.AttachProp(ped, model, boneId, x, y, z, xR, yR, zR, vertex)
|
|
local modelHash = type(model) == 'string' and joaat(model) or model
|
|
local bone = GetPedBoneIndex(ped, boneId)
|
|
QBCore.Functions.LoadModel(modelHash)
|
|
local prop = CreateObject(modelHash, 1.0, 1.0, 1.0, 1, 1, 0)
|
|
AttachEntityToEntity(prop, ped, bone, x, y, z, xR, yR, zR, 1, 1, 0, 1, not vertex and 2 or 0, 1)
|
|
SetModelAsNoLongerNeeded(modelHash)
|
|
return prop
|
|
end
|
|
|
|
function QBCore.Functions.SpawnClear(coords, radius)
|
|
if coords then
|
|
coords = type(coords) == 'table' and vec3(coords.x, coords.y, coords.z) or coords
|
|
else
|
|
coords = GetEntityCoords(PlayerPedId())
|
|
end
|
|
local vehicles = GetGamePool('CVehicle')
|
|
local closeVeh = {}
|
|
for i = 1, #vehicles, 1 do
|
|
local vehicleCoords = GetEntityCoords(vehicles[i])
|
|
local distance = #(vehicleCoords - coords)
|
|
if distance <= radius then
|
|
closeVeh[#closeVeh + 1] = vehicles[i]
|
|
end
|
|
end
|
|
if #closeVeh > 0 then return false end
|
|
return true
|
|
end
|
|
|
|
function QBCore.Functions.LoadAnimSet(animSet)
|
|
if HasAnimSetLoaded(animSet) then return end
|
|
RequestAnimSet(animSet)
|
|
while not HasAnimSetLoaded(animSet) do
|
|
Wait(0)
|
|
end
|
|
end
|
|
|
|
function QBCore.Functions.LoadParticleDictionary(dictionary)
|
|
if HasNamedPtfxAssetLoaded(dictionary) then return end
|
|
RequestNamedPtfxAsset(dictionary)
|
|
while not HasNamedPtfxAssetLoaded(dictionary) do
|
|
Wait(0)
|
|
end
|
|
end
|
|
|
|
function QBCore.Functions.StartParticleAtCoord(dict, ptName, looped, coords, rot, scale, alpha, color, duration)
|
|
if coords then
|
|
coords = type(coords) == 'table' and vec3(coords.x, coords.y, coords.z) or coords
|
|
else
|
|
coords = GetEntityCoords(PlayerPedId())
|
|
end
|
|
QBCore.Functions.LoadParticleDictionary(dict)
|
|
UseParticleFxAssetNextCall(dict)
|
|
SetPtfxAssetNextCall(dict)
|
|
local particleHandle
|
|
if looped then
|
|
particleHandle = StartParticleFxLoopedAtCoord(ptName, coords.x, coords.y, coords.z, rot.x, rot.y, rot.z, scale or 1.0)
|
|
if color then
|
|
SetParticleFxLoopedColour(particleHandle, color.r, color.g, color.b, false)
|
|
end
|
|
SetParticleFxLoopedAlpha(particleHandle, alpha or 10.0)
|
|
if duration then
|
|
Wait(duration)
|
|
StopParticleFxLooped(particleHandle, 0)
|
|
end
|
|
else
|
|
SetParticleFxNonLoopedAlpha(alpha or 10.0)
|
|
if color then
|
|
SetParticleFxNonLoopedColour(color.r, color.g, color.b)
|
|
end
|
|
StartParticleFxNonLoopedAtCoord(ptName, coords.x, coords.y, coords.z, rot.x, rot.y, rot.z, scale or 1.0)
|
|
end
|
|
return particleHandle
|
|
end
|
|
|
|
function QBCore.Functions.StartParticleOnEntity(dict, ptName, looped, entity, bone, offset, rot, scale, alpha, color, evolution, duration)
|
|
QBCore.Functions.LoadParticleDictionary(dict)
|
|
UseParticleFxAssetNextCall(dict)
|
|
local particleHandle, boneID
|
|
if bone and GetEntityType(entity) == 1 then
|
|
boneID = GetPedBoneIndex(entity, bone)
|
|
elseif bone then
|
|
boneID = GetEntityBoneIndexByName(entity, bone)
|
|
end
|
|
if looped then
|
|
if bone then
|
|
particleHandle = StartParticleFxLoopedOnEntityBone(ptName, entity, offset.x, offset.y, offset.z, rot.x, rot.y, rot.z, boneID, scale)
|
|
else
|
|
particleHandle = StartParticleFxLoopedOnEntity(ptName, entity, offset.x, offset.y, offset.z, rot.x, rot.y, rot.z, scale)
|
|
end
|
|
if evolution then
|
|
SetParticleFxLoopedEvolution(particleHandle, evolution.name, evolution.amount, false)
|
|
end
|
|
if color then
|
|
SetParticleFxLoopedColour(particleHandle, color.r, color.g, color.b, false)
|
|
end
|
|
SetParticleFxLoopedAlpha(particleHandle, alpha)
|
|
if duration then
|
|
Wait(duration)
|
|
StopParticleFxLooped(particleHandle, 0)
|
|
end
|
|
else
|
|
SetParticleFxNonLoopedAlpha(alpha or 10.0)
|
|
if color then
|
|
SetParticleFxNonLoopedColour(color.r, color.g, color.b)
|
|
end
|
|
if bone then
|
|
StartParticleFxNonLoopedOnPedBone(ptName, entity, offset.x, offset.y, offset.z, rot.x, rot.y, rot.z, boneID, scale)
|
|
else
|
|
StartParticleFxNonLoopedOnEntity(ptName, entity, offset.x, offset.y, offset.z, rot.x, rot.y, rot.z, scale)
|
|
end
|
|
end
|
|
return particleHandle
|
|
end
|
|
|
|
function QBCore.Functions.GetStreetNametAtCoords(coords)
|
|
local streetname1, streetname2 = GetStreetNameAtCoord(coords.x, coords.y, coords.z)
|
|
return { main = GetStreetNameFromHashKey(streetname1), cross = GetStreetNameFromHashKey(streetname2) }
|
|
end
|
|
|
|
function QBCore.Functions.GetZoneAtCoords(coords)
|
|
return GetLabelText(GetNameOfZone(coords))
|
|
end
|
|
|
|
function QBCore.Functions.GetCardinalDirection(entity)
|
|
entity = DoesEntityExist(entity) and entity or PlayerPedId()
|
|
if DoesEntityExist(entity) then
|
|
local heading = GetEntityHeading(entity)
|
|
if ((heading >= 0 and heading < 45) or (heading >= 315 and heading < 360)) then
|
|
return 'North'
|
|
elseif (heading >= 45 and heading < 135) then
|
|
return 'West'
|
|
elseif (heading >= 135 and heading < 225) then
|
|
return 'South'
|
|
elseif (heading >= 225 and heading < 315) then
|
|
return 'East'
|
|
end
|
|
else
|
|
return 'Cardinal Direction Error'
|
|
end
|
|
end
|
|
|
|
function QBCore.Functions.GetCurrentTime()
|
|
local obj = {}
|
|
obj.min = GetClockMinutes()
|
|
obj.hour = GetClockHours()
|
|
if obj.hour <= 12 then
|
|
obj.ampm = 'AM'
|
|
elseif obj.hour >= 13 then
|
|
obj.ampm = 'PM'
|
|
obj.formattedHour = obj.hour - 12
|
|
end
|
|
if obj.min <= 9 then
|
|
obj.formattedMin = '0' .. obj.min
|
|
end
|
|
return obj
|
|
end
|
|
|
|
function QBCore.Functions.GetGroundZCoord(coords)
|
|
if not coords then return end
|
|
|
|
local retval, groundZ = GetGroundZFor_3dCoord(coords.x, coords.y, coords.z, 0)
|
|
if retval then
|
|
return vector3(coords.x, coords.y, groundZ)
|
|
else
|
|
return coords
|
|
end
|
|
end
|
|
|
|
function QBCore.Functions.GetGroundHash(entity)
|
|
local coords = GetEntityCoords(entity)
|
|
local num = StartShapeTestCapsule(coords.x, coords.y, coords.z + 4, coords.x, coords.y, coords.z - 2.0, 1, 1, entity, 7)
|
|
local retval, success, endCoords, surfaceNormal, materialHash, entityHit = GetShapeTestResultEx(num)
|
|
return materialHash, entityHit, surfaceNormal, endCoords, success, retval
|
|
end
|
|
|
|
for functionName, func in pairs(QBCore.Functions) do
|
|
if type(func) == 'function' then
|
|
exports(functionName, func)
|
|
end
|
|
end
|
|
|
|
-- Access a specific function directly:
|
|
-- exports['qb-core']:Notify('Hello Player!')
|