mirror of
https://github.com/qbcore-fivem/qb-core.git
synced 2026-08-29 01:08:57 +00:00
Merge branch 'main' into main
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
# Set to true to add reviewers to pull requests
|
||||
addReviewers: true
|
||||
|
||||
# Set to true to add assignees to pull requests
|
||||
addAssignees: author
|
||||
|
||||
# A list of reviewers to be added to pull requests (GitHub user name)
|
||||
reviewers:
|
||||
- qbcore-framework/maintenance
|
||||
|
||||
# A list of keywords to be skipped the process that add reviewers if pull requests include it
|
||||
skipKeywords:
|
||||
- wip
|
||||
|
||||
# A number of reviewers added to the pull request
|
||||
# Set 0 to add all the reviewers (default: 0)
|
||||
numberOfReviewers: 0
|
||||
@@ -0,0 +1,60 @@
|
||||
local function hideText()
|
||||
SendNUIMessage({
|
||||
action = 'HIDE_TEXT',
|
||||
})
|
||||
end
|
||||
|
||||
local function drawText(text, position)
|
||||
if not type(position) == "string" then position = "left" end
|
||||
|
||||
SendNUIMessage({
|
||||
action = 'DRAW_TEXT',
|
||||
data = {
|
||||
text = text,
|
||||
position = position
|
||||
}
|
||||
})
|
||||
end
|
||||
|
||||
local function changeText(text, position)
|
||||
if not type(position) == "string" then position = "left" end
|
||||
|
||||
SendNUIMessage({
|
||||
action = 'CHANGE_TEXT',
|
||||
data = {
|
||||
text = text,
|
||||
position = position
|
||||
}
|
||||
})
|
||||
end
|
||||
|
||||
local function keyPressed()
|
||||
CreateThread(function() -- Not sure if a thread is needed but why not eh?
|
||||
SendNUIMessage({
|
||||
action = 'KEY_PRESSED',
|
||||
})
|
||||
Wait(500)
|
||||
hideText()
|
||||
end)
|
||||
end
|
||||
|
||||
RegisterNetEvent('qb-core:client:DrawText', function(text, position)
|
||||
drawText(text, position)
|
||||
end)
|
||||
|
||||
RegisterNetEvent('qb-core:client:ChangeText', function(text, position)
|
||||
changeText(text, position)
|
||||
end)
|
||||
|
||||
RegisterNetEvent('qb-core:client:HideText', function()
|
||||
hideText()
|
||||
end)
|
||||
|
||||
RegisterNetEvent('qb-core:client:KeyPressed', function()
|
||||
keyPressed()
|
||||
end)
|
||||
|
||||
exports('DrawText', drawText)
|
||||
exports('ChangeText', changeText)
|
||||
exports('HideText', hideText)
|
||||
exports('KeyPressed', keyPressed)
|
||||
+29
-12
@@ -4,10 +4,9 @@
|
||||
RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function()
|
||||
ShutdownLoadingScreenNui()
|
||||
LocalPlayer.state:set('isLoggedIn', true, false)
|
||||
if QBConfig.Server.pvp then
|
||||
SetCanAttackFriendly(PlayerPedId(), true, false)
|
||||
NetworkSetFriendlyFireOption(true)
|
||||
end
|
||||
if not QBConfig.Server.PVP then return end
|
||||
SetCanAttackFriendly(PlayerPedId(), true, false)
|
||||
NetworkSetFriendlyFireOption(true)
|
||||
end)
|
||||
|
||||
RegisterNetEvent('QBCore:Client:OnPlayerUnload', function()
|
||||
@@ -121,16 +120,21 @@ end)
|
||||
RegisterNetEvent('QBCore:Command:SpawnVehicle', function(vehName)
|
||||
local ped = PlayerPedId()
|
||||
local hash = GetHashKey(vehName)
|
||||
if not IsModelInCdimage(hash) then
|
||||
return
|
||||
end
|
||||
local veh = GetVehiclePedIsUsing(ped)
|
||||
if not IsModelInCdimage(hash) then return end
|
||||
RequestModel(hash)
|
||||
while not HasModelLoaded(hash) do
|
||||
Wait(10)
|
||||
Wait(0)
|
||||
end
|
||||
|
||||
if IsPedInAnyVehicle(ped) then
|
||||
DeleteVehicle(veh)
|
||||
end
|
||||
|
||||
local vehicle = CreateVehicle(hash, GetEntityCoords(ped), GetEntityHeading(ped), true, false)
|
||||
TaskWarpPedIntoVehicle(ped, vehicle, -1)
|
||||
SetModelAsNoLongerNeeded(vehicle)
|
||||
SetVehicleFuelLevel(vehicle, 100.0)
|
||||
SetModelAsNoLongerNeeded(hash)
|
||||
TriggerEvent("vehiclekeys:client:SetOwner", QBCore.Functions.GetPlate(vehicle))
|
||||
end)
|
||||
|
||||
@@ -191,9 +195,9 @@ local function Draw3DText(coords, str)
|
||||
SetTextProportional(1)
|
||||
SetTextOutline()
|
||||
SetTextCentre(1)
|
||||
SetTextEntry("STRING")
|
||||
AddTextComponentString(str)
|
||||
DrawText(worldX, worldY)
|
||||
BeginTextCommandDisplayText("STRING")
|
||||
AddTextComponentSubstringPlayerName(str)
|
||||
EndTextCommandDisplayText(worldX, worldY)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -209,3 +213,16 @@ RegisterNetEvent('QBCore:Command:ShowMe3D', function(senderId, msg)
|
||||
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)
|
||||
|
||||
+239
-121
@@ -1,20 +1,14 @@
|
||||
QBCore.Functions = {}
|
||||
QBCore.RequestId = 0
|
||||
|
||||
-- Player
|
||||
|
||||
function QBCore.Functions.GetPlayerData(cb)
|
||||
if cb then
|
||||
cb(QBCore.PlayerData)
|
||||
else
|
||||
return QBCore.PlayerData
|
||||
end
|
||||
if not cb then return QBCore.PlayerData end
|
||||
cb(QBCore.PlayerData)
|
||||
end
|
||||
|
||||
function QBCore.Functions.GetCoords(entity)
|
||||
local coords = GetEntityCoords(entity, false)
|
||||
local heading = GetEntityHeading(entity)
|
||||
return vector4(coords.x, coords.y, coords.z, heading)
|
||||
return vector4(GetEntityCoords(entity), GetEntityHeading(entity))
|
||||
end
|
||||
|
||||
function QBCore.Functions.HasItem(item)
|
||||
@@ -58,37 +52,60 @@ function QBCore.Functions.DrawText3D(x, y, z, text)
|
||||
ClearDrawOrigin()
|
||||
end
|
||||
|
||||
function QBCore.Functions.CreateBlip(coords, sprite, display, scale, colour, shortRange, title)
|
||||
if not coords or not sprite or not display or not scale or not colour or shortRange == nil or not title then
|
||||
print("Blip failed to create, most likely missed a setting, debug log: ")
|
||||
print("Coords: " .. coords .. " Sprite: " .. sprite .. " Display: " .. display .. " scale: " .. scale .. " shortRange: " .. shortRange .. " Title: " .. title .. " if you're attempting to use a blip without a title, use an empty string.")
|
||||
else
|
||||
blip = AddBlipForCoord(coords)
|
||||
SetBlipSprite(blip, sprite)
|
||||
SetBlipDisplay(blip, display)
|
||||
SetBlipScale(blip, scale)
|
||||
SetBlipColour(blip, colour)
|
||||
SetBlipAsShortRange(blip, shortRange)
|
||||
function QBCore.Functions.CreateBlip(coords, sprite, display, scale, colour, shortRange, title, alpha, friendly, bright, category, hiddenOnLegend, highDetail, rotation, cone, shrink, showHeight, showNumber, showOutline)
|
||||
if not coords or (type(coords) ~= 'table' and type(coords) ~= 'vector3') then
|
||||
print("Blip failed to create, the coords were not specified or was specified in the wrong format, coords must be a table or vector3, debug log: ")
|
||||
print(("Coords: %s Sprite: %s Display: %s scale: %s shortRange: %s Title: %s Alpha: %s Friendly: %s Bright: %s Category: %s Hidden On Legend: %s High Detail: %s Rotation: %s Cone: %s Shrink: %s Show Heigt: %s Show Number: %s Show Outline: %s"):format(coords, sprite, display, scale, colour, shortRange, title, alpha, friendly, bright, category, hiddenOnLegend, highDetail, rotation, cone, shrink, showHeight, showNumber, showOutline))
|
||||
return
|
||||
end
|
||||
coords = type(coords) == 'table' and vec3(coords.x, coords.y, coords.z) or coords
|
||||
local blip = AddBlipForCoord(coords)
|
||||
if sprite then SetBlipSprite(blip, sprite) end
|
||||
if display then SetBlipDisplay(blip, display) end
|
||||
if scale then SetBlipScale(blip, scale) end
|
||||
if colour then SetBlipColour(blip, colour) end
|
||||
if shortRange ~= nil then SetBlipAsShortRange(blip, shortRange) end
|
||||
if title then
|
||||
BeginTextCommandSetBlipName("STRING")
|
||||
AddTextComponentString(title)
|
||||
EndTextCommandSetBlipName(blip)
|
||||
end
|
||||
if alpha then SetBlipAlpha(blip, alpha) end
|
||||
if friendly ~= nil then SetBlipAsFriendly(blip, friendly) end
|
||||
if bright ~= nil then SetBlipBright(blip, bright) end
|
||||
if category then SetBlipCategory(blip, category) end -- categories can be found here: https://docs.fivem.net/natives/?_0x234CDD44D996FD9A
|
||||
if hiddenOnLegend ~= nil then SetBlipHiddenOnLegend(blip, hiddenOnLegend) end
|
||||
if highDetail ~= nil then SetBlipHighDetail(blip, highDetail) end
|
||||
if rotation then SetBlipRotation(blip, rotation) end -- Required to be an integer
|
||||
if cone ~= nil then SetBlipShowCone(blip, cone) end
|
||||
if shrink ~= nil then SetBlipShrink(blip, shrink) end
|
||||
if showHeight ~= nil then ShowHeightOnBlip(blip, showHeight) end
|
||||
if showNumber then ShowNumberOnBlip(blip, showNumber) end
|
||||
if showOutline ~= nil then ShowOutlineIndicatorOnBlip(blip, showOutline) end
|
||||
return blip
|
||||
end
|
||||
|
||||
function QBCore.Functions.RequestAnimDict(animDict)
|
||||
if not HasAnimDictLoaded(animDict) then
|
||||
RequestAnimDict(animDict)
|
||||
|
||||
while not HasAnimDictLoaded(animDict) do
|
||||
Wait(4)
|
||||
end
|
||||
if HasAnimDictLoaded(animDict) then return end
|
||||
RequestAnimDict(animDict)
|
||||
while not HasAnimDictLoaded(animDict) do
|
||||
Wait(0)
|
||||
end
|
||||
end
|
||||
|
||||
function QBCore.Functions.LoadModel(ModelName)
|
||||
RequestModel(ModelName)
|
||||
while not HasModelLoaded(ModelName) do
|
||||
Wait(100)
|
||||
function QBCore.Functions.PlayAnim(animDict, animName, upperbodyOnly, duration)
|
||||
local flags = upperbodyOnly == true and 16 or 0
|
||||
local runTime = duration ~= nil and duration or -1
|
||||
QBCore.Functions.RequestAnimDict(animDict)
|
||||
TaskPlayAnim(PlayerPedId(), animDict, animName, 8.0, 1.0, runTime, flags, 0.0, false, false, true)
|
||||
RemoveAnimDict(animDict)
|
||||
end
|
||||
|
||||
function QBCore.Functions.LoadModel(model)
|
||||
if HasModelLoaded(model) then return end
|
||||
RequestModel(model)
|
||||
while not HasModelLoaded(model) do
|
||||
Wait(0)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -96,25 +113,25 @@ RegisterNUICallback('getNotifyConfig', function(_, cb)
|
||||
cb(QBCore.Config.Notify)
|
||||
end)
|
||||
|
||||
function QBCore.Functions.Notify(text, textype, length)
|
||||
function QBCore.Functions.Notify(text, texttype, length)
|
||||
if type(text) == "table" then
|
||||
local ttext = text.text or 'Placeholder'
|
||||
local caption = text.caption or 'Placeholder'
|
||||
local ttype = textype or 'primary'
|
||||
local length = length or 5000
|
||||
texttype = texttype or 'primary'
|
||||
length = length or 5000
|
||||
SendNUIMessage({
|
||||
action = 'notify',
|
||||
type = ttype,
|
||||
type = texttype,
|
||||
length = length,
|
||||
text = ttext,
|
||||
caption = caption
|
||||
})
|
||||
else
|
||||
local ttype = textype or 'primary'
|
||||
local length = length or 5000
|
||||
texttype = texttype or 'primary'
|
||||
length = length or 5000
|
||||
SendNUIMessage({
|
||||
action = 'notify',
|
||||
type = ttype,
|
||||
type = texttype,
|
||||
length = length,
|
||||
text = text
|
||||
})
|
||||
@@ -131,6 +148,7 @@ function QBCore.Functions.TriggerCallback(name, cb, ...)
|
||||
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,
|
||||
@@ -159,17 +177,19 @@ end
|
||||
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.GetPeds(ignoreList)
|
||||
local pedPool = GetGamePool('CPed')
|
||||
local ignoreList = ignoreList or {}
|
||||
local peds = {}
|
||||
ignoreList = ignoreList or {}
|
||||
for i = 1, #pedPool, 1 do
|
||||
local found = false
|
||||
for j = 1, #ignoreList, 1 do
|
||||
@@ -208,19 +228,19 @@ function QBCore.Functions.GetClosestPed(coords, ignoreList)
|
||||
end
|
||||
|
||||
function QBCore.Functions.IsWearingGloves()
|
||||
local armIndex = GetPedDrawableVariation(PlayerPedId(), 3)
|
||||
local model = GetEntityModel(PlayerPedId())
|
||||
local retval = true
|
||||
local ped = PlayerPedId()
|
||||
local armIndex = GetPedDrawableVariation(ped, 3)
|
||||
local model = GetEntityModel(ped)
|
||||
if model == `mp_m_freemode_01` then
|
||||
if QBCore.Shared.MaleNoGloves[armIndex] ~= nil and QBCore.Shared.MaleNoGloves[armIndex] then
|
||||
retval = false
|
||||
if QBCore.Shared.MaleNoGloves[armIndex] then
|
||||
return false
|
||||
end
|
||||
else
|
||||
if QBCore.Shared.FemaleNoGloves[armIndex] ~= nil and QBCore.Shared.FemaleNoGloves[armIndex] then
|
||||
retval = false
|
||||
if QBCore.Shared.FemaleNoGloves[armIndex] then
|
||||
return false
|
||||
end
|
||||
end
|
||||
return retval
|
||||
return true
|
||||
end
|
||||
|
||||
function QBCore.Functions.GetClosestPlayer(coords)
|
||||
@@ -248,14 +268,14 @@ function QBCore.Functions.GetClosestPlayer(coords)
|
||||
end
|
||||
|
||||
function QBCore.Functions.GetPlayersFromCoords(coords, distance)
|
||||
local players = QBCore.Functions.GetPlayers()
|
||||
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
|
||||
local distance = distance or 5
|
||||
distance = distance or 5
|
||||
local closePlayers = {}
|
||||
for _, player in pairs(players) do
|
||||
local target = GetPlayerPed(player)
|
||||
@@ -313,83 +333,68 @@ 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, Type, Bone)
|
||||
function QBCore.Functions.GetBoneDistance(entity, boneType, boneIndex)
|
||||
local bone
|
||||
|
||||
if Type == 1 then
|
||||
bone = GetPedBoneIndex(entity, Bone)
|
||||
if boneType == 1 then
|
||||
bone = GetPedBoneIndex(entity, boneIndex)
|
||||
else
|
||||
bone = GetEntityBoneIndexByName(entity, Bone)
|
||||
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 = GetHashKey(model)
|
||||
function QBCore.Functions.AttachProp(ped, model, boneId, x, y, z, xR, yR, zR, vertex)
|
||||
local modelHash = type(model) == 'string' and GetHashKey(model) or model
|
||||
local bone = GetPedBoneIndex(ped, boneId)
|
||||
RequestModel(modelHash)
|
||||
while not HasModelLoaded(modelHash) do
|
||||
Wait(0)
|
||||
end
|
||||
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)
|
||||
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
|
||||
|
||||
-- Vehicle
|
||||
|
||||
function QBCore.Functions.SpawnVehicle(model, cb, coords, isnetworked)
|
||||
local model = GetHashKey(model)
|
||||
function QBCore.Functions.SpawnVehicle(model, cb, coords, isnetworked, teleportInto)
|
||||
local ped = PlayerPedId()
|
||||
model = type(model) == 'string' and GetHashKey(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
|
||||
local isnetworked = isnetworked or true
|
||||
if not IsModelInCdimage(model) then
|
||||
return
|
||||
end
|
||||
RequestModel(model)
|
||||
while not HasModelLoaded(model) do
|
||||
Citizen.Wait(10)
|
||||
end
|
||||
isnetworked = isnetworked or true
|
||||
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 cb then
|
||||
cb(veh)
|
||||
end
|
||||
if teleportInto then TaskWarpPedIntoVehicle(PlayerPedId(), veh, -1) end
|
||||
if cb then cb(veh) end
|
||||
end
|
||||
|
||||
function QBCore.Functions.DeleteVehicle(vehicle)
|
||||
@@ -403,9 +408,14 @@ function QBCore.Functions.GetPlate(vehicle)
|
||||
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
|
||||
for i = 1, #vehicles, 1 do
|
||||
local vehicleCoords = GetEntityCoords(vehicles[i])
|
||||
local distance = #(vehicleCoords - coords)
|
||||
if distance <= radius then
|
||||
@@ -418,20 +428,20 @@ end
|
||||
|
||||
function QBCore.Functions.GetVehicleProperties(vehicle)
|
||||
if DoesEntityExist(vehicle) then
|
||||
local colorPrimary, colorSecondary = GetVehicleColours(vehicle)
|
||||
local pearlescentColor, wheelColor = GetVehicleExtraColours(vehicle)
|
||||
local extras = {}
|
||||
|
||||
local colorPrimary, colorSecondary = GetVehicleColours(vehicle)
|
||||
if GetIsVehiclePrimaryColourCustom(vehicle) then
|
||||
r, g, b = GetVehicleCustomPrimaryColour(vehicle)
|
||||
colorPrimary = { r, g, b }
|
||||
colorPrimary = {r, g, b}
|
||||
end
|
||||
|
||||
if GetIsVehicleSecondaryColourCustom(vehicle) then
|
||||
r, g, b = GetVehicleCustomSecondaryColour(vehicle)
|
||||
colorSecondary = { r, g, b }
|
||||
colorSecondary = {r, g, b}
|
||||
end
|
||||
|
||||
local extras = {}
|
||||
for extraId = 0, 12 do
|
||||
if DoesExtraExist(vehicle, extraId) then
|
||||
local state = IsVehicleExtraTurnedOn(vehicle, extraId) == 1
|
||||
@@ -439,10 +449,39 @@ function QBCore.Functions.GetVehicleProperties(vehicle)
|
||||
end
|
||||
end
|
||||
|
||||
if GetVehicleMod(vehicle, 48) == -1 and GetVehicleLivery(vehicle) ~= -1 then
|
||||
local modLivery = GetVehicleMod(vehicle, 48)
|
||||
if GetVehicleMod(vehicle, 48) == -1 and GetVehicleLivery(vehicle) ~= 0 then
|
||||
modLivery = GetVehicleLivery(vehicle)
|
||||
else
|
||||
modLivery = GetVehicleMod(vehicle, 48)
|
||||
end
|
||||
|
||||
local neons = {}
|
||||
for i = 0, 3 do
|
||||
neons[i] = IsVehicleNeonLightEnabled(vehicle, i)
|
||||
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
|
||||
|
||||
return {
|
||||
@@ -454,22 +493,26 @@ function QBCore.Functions.GetVehicleProperties(vehicle)
|
||||
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,
|
||||
interiorColor = GetVehicleInteriorColor(vehicle),
|
||||
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,
|
||||
xenonColor = GetVehicleXenonLightsColour(vehicle),
|
||||
neonEnabled = {
|
||||
IsVehicleNeonLightEnabled(vehicle, 0),
|
||||
IsVehicleNeonLightEnabled(vehicle, 1),
|
||||
IsVehicleNeonLightEnabled(vehicle, 2),
|
||||
IsVehicleNeonLightEnabled(vehicle, 3)
|
||||
},
|
||||
neonEnabled = neons,
|
||||
neonColor = table.pack(GetVehicleNeonLightsColour(vehicle)),
|
||||
headlightColor = GetVehicleHeadlightsColour(vehicle),
|
||||
interiorColor = GetVehicleInteriorColour(vehicle),
|
||||
extras = extras,
|
||||
tyreSmokeColor = table.pack(GetVehicleTyreSmokeColor(vehicle)),
|
||||
modSpoilers = GetVehicleMod(vehicle, 0),
|
||||
@@ -489,8 +532,11 @@ function QBCore.Functions.GetVehicleProperties(vehicle)
|
||||
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),
|
||||
@@ -518,7 +564,10 @@ function QBCore.Functions.GetVehicleProperties(vehicle)
|
||||
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
|
||||
@@ -527,6 +576,16 @@ 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)
|
||||
@@ -542,12 +601,18 @@ function QBCore.Functions.SetVehicleProperties(vehicle, props)
|
||||
if props.engineHealth then
|
||||
SetVehicleEngineHealth(vehicle, props.engineHealth + 0.0)
|
||||
end
|
||||
if props.tankHealth then
|
||||
SetVehiclePetrolTankHealth(vehicle, props.tankHealth)
|
||||
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)
|
||||
end
|
||||
if props.color1 then
|
||||
if type(props.color1) == "number" then
|
||||
SetVehicleColours(vehicle, props.color1, colorSecondary)
|
||||
@@ -577,29 +642,59 @@ function QBCore.Functions.SetVehicleProperties(vehicle, props)
|
||||
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.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])
|
||||
if props.windowStatus then
|
||||
for windowIndex, smashWindow in pairs(props.windowStatus) do
|
||||
if not smashWindow then SmashVehicleWindow(vehicle, windowIndex) end
|
||||
end
|
||||
end
|
||||
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)
|
||||
if props.doorStatus then
|
||||
for doorIndex, breakDoor in pairs(props.doorStatus) do
|
||||
if breakDoor then
|
||||
SetVehicleDoorBroken(vehicle, doorIndex, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
if props.neonEnabled then
|
||||
for neonIndex, enableNeons in pairs(props.neonEnabled) do
|
||||
SetVehicleNeonLightEnabled(vehicle, neonIndex, enableNeons)
|
||||
end
|
||||
end
|
||||
if props.neonColor then
|
||||
SetVehicleNeonLightsColour(vehicle, props.neonColor[1], props.neonColor[2], props.neonColor[3])
|
||||
end
|
||||
if props.modSmokeEnabled then
|
||||
ToggleVehicleMod(vehicle, 20, true)
|
||||
if props.headlightColor then
|
||||
SetVehicleHeadlightsColour(vehicle, props.headlightColor)
|
||||
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])
|
||||
@@ -655,9 +750,21 @@ function QBCore.Functions.SetVehicleProperties(vehicle, props)
|
||||
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
|
||||
@@ -742,26 +849,39 @@ function QBCore.Functions.SetVehicleProperties(vehicle, props)
|
||||
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
|
||||
|
||||
function QBCore.Functions.LoadParticleDictionary(dictionary)
|
||||
if not HasNamedPtfxAssetLoaded(dictionary) then
|
||||
RequestNamedPtfxAsset(dictionary)
|
||||
while not HasNamedPtfxAssetLoaded(dictionary) do
|
||||
Wait(0)
|
||||
end
|
||||
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)
|
||||
QBCore.Functions.LoadParticleDictionary(Dict)
|
||||
UseParticleFxAssetNextCall(Dict)
|
||||
SetPtfxAssetNextCall(Dict)
|
||||
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)
|
||||
@@ -780,13 +900,12 @@ function QBCore.Functions.StartParticleAtCoord(Dict, ptName, looped, coords, rot
|
||||
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)
|
||||
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)
|
||||
@@ -821,6 +940,5 @@ function QBCore.Functions.StartParticleOnEntity(Dict, ptName, looped, entity, bo
|
||||
StartParticleFxNonLoopedOnEntity(ptName, entity, offset.x, offset.y, offset.z, rot.x, rot.y, rot.z, scale)
|
||||
end
|
||||
end
|
||||
|
||||
return particleHandle
|
||||
end
|
||||
|
||||
+7
-6
@@ -1,23 +1,24 @@
|
||||
CreateThread(function()
|
||||
while true do
|
||||
Wait(0)
|
||||
local sleep = 0
|
||||
if LocalPlayer.state.isLoggedIn then
|
||||
Wait((1000 * 60) * QBCore.Config.UpdateInterval)
|
||||
sleep = (1000 * 60) * QBCore.Config.UpdateInterval
|
||||
TriggerServerEvent('QBCore:UpdatePlayer')
|
||||
end
|
||||
Wait(sleep)
|
||||
end
|
||||
end)
|
||||
|
||||
CreateThread(function()
|
||||
while true do
|
||||
Wait(QBCore.Config.StatusInterval)
|
||||
if LocalPlayer.state.isLoggedIn then
|
||||
if QBCore.Functions.GetPlayerData().metadata['hunger'] <= 0 or
|
||||
QBCore.Functions.GetPlayerData().metadata['thirst'] <= 0 then
|
||||
if (QBCore.PlayerData.metadata['hunger'] <= 0 or QBCore.PlayerData.metadata['thirst'] <= 0) and not QBCore.PlayerData.metadata['isdead'] then
|
||||
local ped = PlayerPedId()
|
||||
local currentHealth = GetEntityHealth(ped)
|
||||
SetEntityHealth(ped, currentHealth - math.random(5, 10))
|
||||
local decreaseTreshold = math.random(5, 10)
|
||||
SetEntityHealth(ped, currentHealth - decreaseTreshold)
|
||||
end
|
||||
end
|
||||
Wait(QBCore.Config.StatusInterval)
|
||||
end
|
||||
end)
|
||||
|
||||
+14
-19
@@ -3,11 +3,11 @@ QBConfig = {}
|
||||
QBConfig.MaxPlayers = GetConvarInt('sv_maxclients', 48) -- Gets max players from config file, default 48
|
||||
QBConfig.DefaultSpawn = vector4(-1035.71, -2731.87, 12.86, 0.0)
|
||||
QBConfig.UpdateInterval = 5 -- how often to update player data in minutes
|
||||
QBConfig.StatusInterval = 5000 -- how often to check hunger/thirst status in ms
|
||||
QBConfig.StatusInterval = 5000 -- how often to check hunger/thirst status in milliseconds
|
||||
|
||||
QBConfig.Money = {}
|
||||
QBConfig.Money.MoneyTypes = { ['cash'] = 500, ['bank'] = 5000, ['crypto'] = 0 } -- ['type']=startamount - Add or remove money types for your server (for ex. ['blackmoney']=0), remember once added it will not be removed from the database!
|
||||
QBConfig.Money.DontAllowMinus = { 'cash', 'crypto' } -- Money that is not allowed going in minus
|
||||
QBConfig.Money.MoneyTypes = {['cash'] = 500, ['bank'] = 5000, ['crypto'] = 0} -- ['type'] = startamount - Add or remove money types for your server (for ex. ['blackmoney'] = 0), remember once added it will not be removed from the database!
|
||||
QBConfig.Money.DontAllowMinus = {'cash', 'crypto'} -- Money that is not allowed going in minus
|
||||
QBConfig.Money.PayCheckTimeOut = 10 -- The time in minutes that it will give the paycheck
|
||||
QBConfig.Money.PayCheckSociety = false -- If true paycheck will come from the society account that the player is employed at, requires qb-bossmenu
|
||||
|
||||
@@ -17,25 +17,20 @@ QBConfig.Player.MaxInvSlots = 41 -- Max inventory slots for a player
|
||||
QBConfig.Player.HungerRate = 4.2 -- Rate at which hunger goes down.
|
||||
QBConfig.Player.ThirstRate = 3.8 -- Rate at which thirst goes down.
|
||||
QBConfig.Player.Bloodtypes = {
|
||||
"A+",
|
||||
"A-",
|
||||
"B+",
|
||||
"B-",
|
||||
"AB+",
|
||||
"AB-",
|
||||
"O+",
|
||||
"O-",
|
||||
"A+", "A-", "B+", "B-", "AB+", "AB-", "O+", "O-",
|
||||
}
|
||||
|
||||
QBConfig.Server = {} -- General server config
|
||||
QBConfig.Server.closed = false -- Set server closed (no one can join except people with ace permission 'qbadmin.join')
|
||||
QBConfig.Server.closedReason = "Server Closed" -- Reason message to display when people can't join the server
|
||||
QBConfig.Server.uptime = 0 -- Time the server has been up.
|
||||
QBConfig.Server.whitelist = false -- Enable or disable whitelist on the server
|
||||
QBConfig.Server.pvp = true -- Enable or disable pvp on the server (Ability to shoot other players)
|
||||
QBConfig.Server.discord = "" -- Discord invite link
|
||||
QBConfig.Server.checkDuplicateLicense = true -- check for duplicate rockstar license on join
|
||||
QBConfig.Server.PermissionList = {} -- permission list
|
||||
QBConfig.Server.UseConnectQueue = true -- Use connectqueue as a queue for your server
|
||||
QBConfig.Server.Closed = false -- Set server closed (no one can join except people with ace permission 'qbadmin.join')
|
||||
QBConfig.Server.ClosedReason = "Server Closed" -- Reason message to display when people can't join the server
|
||||
QBConfig.Server.Uptime = 0 -- Time the server has been up.
|
||||
QBConfig.Server.Whitelist = false -- Enable or disable whitelist on the server
|
||||
QBConfig.Server.WhitelistPermission = 'admin' -- Permission that's able to enter the server when the whitelist is on
|
||||
QBConfig.Server.PVP = true -- Enable or disable pvp on the server (Ability to shoot other players)
|
||||
QBConfig.Server.Discord = "" -- Discord invite link
|
||||
QBConfig.Server.CheckDuplicateLicense = true -- Check for duplicate rockstar license on join
|
||||
QBConfig.Server.Permissions = {'god', 'admin', 'mod'} -- Add as many groups as you want here after creating them in your server.cfg
|
||||
|
||||
QBConfig.Notify = {}
|
||||
|
||||
|
||||
+11
-12
@@ -2,12 +2,12 @@ fx_version 'cerulean'
|
||||
game 'gta5'
|
||||
|
||||
description 'QB-Core'
|
||||
version '1.0.0'
|
||||
version '1.1.0'
|
||||
|
||||
shared_scripts {
|
||||
'shared/locale.lua',
|
||||
'locale/en.lua', -- replace with desired language
|
||||
'config.lua',
|
||||
'shared/locale.lua',
|
||||
'locale/en.lua', -- replace with desired language
|
||||
'shared/main.lua',
|
||||
'shared/items.lua',
|
||||
'shared/jobs.lua',
|
||||
@@ -20,7 +20,8 @@ client_scripts {
|
||||
'client/main.lua',
|
||||
'client/functions.lua',
|
||||
'client/loops.lua',
|
||||
'client/events.lua'
|
||||
'client/events.lua',
|
||||
'client/drawtext.lua'
|
||||
}
|
||||
|
||||
server_scripts {
|
||||
@@ -30,6 +31,7 @@ server_scripts {
|
||||
'server/player.lua',
|
||||
'server/events.lua',
|
||||
'server/commands.lua',
|
||||
'server/exports.lua',
|
||||
'server/debug.lua'
|
||||
}
|
||||
|
||||
@@ -37,14 +39,11 @@ ui_page 'html/index.html'
|
||||
|
||||
files {
|
||||
'html/index.html',
|
||||
'html/style.css',
|
||||
'html/*.js'
|
||||
'html/css/style.css',
|
||||
'html/css/drawtext.css',
|
||||
'html/js/*.js'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
'oxmysql',
|
||||
'progressbar',
|
||||
'connectqueue'
|
||||
}
|
||||
dependency 'oxmysql'
|
||||
|
||||
lua54 'yes'
|
||||
lua54 'yes'
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
@import url("https://fonts.googleapis.com/css2?family=Poppins:wght@300;500&display=swap");
|
||||
:root {
|
||||
--primary-bg: rgba(23, 23, 23, 90%);
|
||||
--active-bg: #dc143c;
|
||||
--font-color: white;
|
||||
}
|
||||
|
||||
#drawtext-container {
|
||||
display: none;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font-family: "Poppins", sans-serif !important;
|
||||
font-weight: 300;
|
||||
}
|
||||
.text {
|
||||
position: absolute;
|
||||
background: var(--primary-bg);
|
||||
color: var(--font-color);
|
||||
margin-top: 0.5rem;
|
||||
padding: 0.45rem;
|
||||
border-radius: 0.15rem;
|
||||
box-shadow: 0rem 0rem 0.1rem 0.05rem #000000;
|
||||
}
|
||||
|
||||
.text.pressed {
|
||||
background: var(--active-bg);
|
||||
}
|
||||
|
||||
.top {
|
||||
left: 45vw;
|
||||
top: -100px;
|
||||
}
|
||||
.top.show {
|
||||
transition: 0.5s;
|
||||
top: 10px;
|
||||
opacity: 1;
|
||||
}
|
||||
.top.hide {
|
||||
transition: 0.5s;
|
||||
top: -100px;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.right {
|
||||
top: 50%;
|
||||
right: -100px;
|
||||
}
|
||||
.right.show {
|
||||
transition: 0.5s;
|
||||
right: 10px;
|
||||
opacity: 1;
|
||||
}
|
||||
.right.hide {
|
||||
transition: 0.5s;
|
||||
right: -100px;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.left {
|
||||
top: 50%;
|
||||
left: -100px;
|
||||
}
|
||||
|
||||
.left.show {
|
||||
transition: 0.5s;
|
||||
left: 10px;
|
||||
opacity: 1;
|
||||
}
|
||||
.left.hide {
|
||||
transition: 0.5s;
|
||||
left: -100px;
|
||||
opacity: 0;
|
||||
}
|
||||
@@ -1,3 +1,7 @@
|
||||
html::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.success {
|
||||
background-color: rgba(23, 23, 23, 90%);
|
||||
border-radius: 10px;
|
||||
@@ -31,4 +35,4 @@
|
||||
border-radius: 10px;
|
||||
box-shadow: 0rem 0rem 0.1rem 0.05rem #000000;
|
||||
border-left: 5px solid #f44236;
|
||||
}
|
||||
}
|
||||
+8
-3
@@ -19,7 +19,7 @@
|
||||
type="text/css"
|
||||
/>
|
||||
<link
|
||||
href="style.css"
|
||||
href="css/style.css"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<script
|
||||
@@ -30,12 +30,17 @@
|
||||
src="https://cdn.jsdelivr.net/npm/quasar@2.1.0/dist/quasar.umd.prod.js"
|
||||
defer
|
||||
></script>
|
||||
<script type="module" src="app.js"></script>
|
||||
<script type="module" src="js/app.js"></script>
|
||||
<script src="js/drawtext.js"></script>
|
||||
<link rel="stylesheet" href="css/drawtext.css">
|
||||
</head>
|
||||
<body style="font-family: 'Poppins', sans-serif">
|
||||
<div
|
||||
id="q-app"
|
||||
style="min-height: 100vh"
|
||||
></div>
|
||||
<div id="drawtext-container">
|
||||
<div id="text" class="text"></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
let direction = null;
|
||||
|
||||
const drawText = async (textData) => {
|
||||
const text = document.getElementById("text");
|
||||
let {position} = textData;
|
||||
switch (textData.position) {
|
||||
case "left":
|
||||
addClass(text, position);
|
||||
direction = "left";
|
||||
break;
|
||||
case "top":
|
||||
addClass(text, position);
|
||||
direction = "top";
|
||||
break;
|
||||
case "right":
|
||||
addClass(text, position);
|
||||
direction = "right";
|
||||
break;
|
||||
default:
|
||||
addClass(text, "left");
|
||||
direction = "left";
|
||||
break;
|
||||
}
|
||||
|
||||
text.innerHTML = textData.text;
|
||||
document.getElementById("drawtext-container").style.display = "block";
|
||||
await sleep(100);
|
||||
addClass(text, "show");
|
||||
};
|
||||
|
||||
const changeText = async (textData) => {
|
||||
const text = document.getElementById("text");
|
||||
let {position} = textData;
|
||||
|
||||
removeClass(text, "show");
|
||||
addClass(text, "pressed");
|
||||
addClass(text, "hide");
|
||||
|
||||
await sleep(500);
|
||||
removeClass(text, "left");
|
||||
removeClass(text, "right");
|
||||
removeClass(text, "top");
|
||||
removeClass(text, "bottom");
|
||||
removeClass(text, "hide");
|
||||
removeClass(text, "pressed");
|
||||
|
||||
switch (textData.position) {
|
||||
case "left":
|
||||
addClass(text, position);
|
||||
direction = "left";
|
||||
break;
|
||||
case "top":
|
||||
addClass(text, position);
|
||||
direction = "top";
|
||||
break;
|
||||
case "right":
|
||||
addClass(text, position);
|
||||
direction = "right";
|
||||
break;
|
||||
default:
|
||||
addClass(text, "left");
|
||||
direction = "left";
|
||||
break;
|
||||
}
|
||||
text.innerHTML = textData.text;
|
||||
|
||||
await sleep(100);
|
||||
text.classList.add("show");
|
||||
};
|
||||
|
||||
const hideText = async () => {
|
||||
const text = document.getElementById("text");
|
||||
removeClass(text, "show");
|
||||
addClass(text, "hide");
|
||||
|
||||
setTimeout(() => {
|
||||
removeClass(text, "left");
|
||||
removeClass(text, "right");
|
||||
removeClass(text, "top");
|
||||
removeClass(text, "bottom");
|
||||
removeClass(text, "hide");
|
||||
removeClass(text, "pressed");
|
||||
document.getElementById("drawtext-container").style.display = "none";
|
||||
}, 1000);
|
||||
};
|
||||
|
||||
const keyPressed = () => {
|
||||
const text = document.getElementById("text");
|
||||
addClass(text, "pressed");
|
||||
};
|
||||
|
||||
window.addEventListener("message", (event) => {
|
||||
const data = event.data;
|
||||
const action = data.action;
|
||||
const textData = data.data;
|
||||
switch (action) {
|
||||
case "DRAW_TEXT":
|
||||
return drawText(textData);
|
||||
case "CHANGE_TEXT":
|
||||
return changeText(textData);
|
||||
case "HIDE_TEXT":
|
||||
return hideText();
|
||||
case "KEY_PRESSED":
|
||||
return keyPressed();
|
||||
default:
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
const sleep = (ms) => {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
};
|
||||
|
||||
const removeClass = (element, name) => {
|
||||
if (element.classList.contains(name)) {
|
||||
element.classList.remove(name);
|
||||
}
|
||||
};
|
||||
|
||||
const addClass = (element, name) => {
|
||||
if (!element.classList.contains(name)) {
|
||||
element.classList.add(name);
|
||||
}
|
||||
};
|
||||
+11
-11
@@ -1,21 +1,21 @@
|
||||
local Translations = {
|
||||
error = {
|
||||
not_online = 'اللاعب غير متواجد',
|
||||
not_online = 'اللاعب غير متصل',
|
||||
wrong_format = 'التنسيق غير صحيح',
|
||||
missing_args = 'لم يتم ادخل جميع الحقول تاكد من وضع (x, y, z)',
|
||||
missing_args2 = 'يجب ملأ جميع الحقول اللازمة!',
|
||||
missing_args = '(x, y, z) لم يتم ادخل جميع المعلومات',
|
||||
missing_args2 = 'يجب ملأ جميع الحقول اللازمة',
|
||||
no_access = 'لا يمكن الوصول إلى هذا الأمر',
|
||||
company_too_poor = 'رئيس العمل الخاص بك لا يملك اموال كافية',
|
||||
item_not_exist = 'لا يوجد هذا العنصر',
|
||||
too_heavy = 'المحفظة ممتلئة'
|
||||
company_too_poor = 'مسؤول الوظيفة لا يمكلك مال كاف-ي',
|
||||
item_not_exist = 'عنصر غير موجود',
|
||||
too_heavy = 'لا يوجد مساحة في جقيبتك'
|
||||
},
|
||||
success = {},
|
||||
info = {
|
||||
received_paycheck = 'لقد استملت راتبك الشهري $%{value}',
|
||||
job_info = 'الوظيفة: %{value} | الرتبة: %{value2} | الخدمة: %{value3}',
|
||||
gang_info = 'العصابة: %{value} | الرتبة: %{value2}',
|
||||
on_duty = 'انت الان خارج الخدمة!',
|
||||
off_duty = 'انت الان في الخدمة!'
|
||||
received_paycheck = '$%{value} لقد استملت راتبك الشهري',
|
||||
job_info = '%{value} | %{value2} | %{value3}',
|
||||
gang_info = '%{value} | %{value2}',
|
||||
on_duty = 'انت الان خارج الخدمة',
|
||||
off_duty = 'انت الان في الخدمة'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-3
@@ -4,8 +4,6 @@ local Translations = {
|
||||
wrong_format = 'Formato incorrecto!',
|
||||
missing_args = 'No todos los argumentos estan presente! (x, y, z)',
|
||||
missing_args2 = 'Todos los argumentos tienen que estar presente!',
|
||||
missing_args = 'No todos los argumentos estan presentes! (x, y, z)',
|
||||
missing_args2 = 'Todos los argumentos deben estar presentes!',
|
||||
no_access = 'No tienes acceso a este comando!',
|
||||
company_too_poor = 'Tu empresa está en bancarrota. No hay dinero suficiente.',
|
||||
item_not_exist = 'El objeto no existe en el sistema.',
|
||||
@@ -24,4 +22,4 @@ local Translations = {
|
||||
Lang = Locale:new({
|
||||
phrases = Translations,
|
||||
warnOnMissing = true
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,25 @@
|
||||
local Translations = {
|
||||
error = {
|
||||
not_online = 'שחקן לא מחובר',
|
||||
wrong_format = 'פורמט שגוי',
|
||||
missing_args = 'יש לכתוב את הפקודה לפי מה שכתוב (x, y, z)',
|
||||
missing_args2 = 'יש למלא את כל המידע המבוקש',
|
||||
no_access = 'אין לך גישה לפקודה זו',
|
||||
company_too_poor = 'העסק שלך שבור',
|
||||
item_not_exist = 'אייטם לא נמצא',
|
||||
too_heavy = 'אינבנטורי מלא'
|
||||
},
|
||||
success = {},
|
||||
info = {
|
||||
received_paycheck = '$%{value} קיבלת משבורת על סך',
|
||||
job_info = '%{value3} :בתפקיד | %{value2} :דרגה | %{value} :עבודה',
|
||||
gang_info = '%{value2} :דרגה | %{value} :גאנג',
|
||||
on_duty = 'אתה בתפקיד כעת',
|
||||
off_duty = 'ירדת מתפקיד כעת'
|
||||
}
|
||||
}
|
||||
|
||||
Lang = Locale:new({
|
||||
phrases = Translations,
|
||||
warnOnMissing = true
|
||||
})
|
||||
+1
-1
@@ -13,7 +13,7 @@ local Translations = {
|
||||
info = {
|
||||
received_paycheck = 'Recebeste o pagamento de %{value}€',
|
||||
job_info = 'Emprego: %{value} | Grau: %{value2} | Serviço: %{value3}',
|
||||
gang_info = 'Gang: %{value} | Grade: %{value2}',
|
||||
gang_info = 'Gang: %{value} | Grau: %{value2}',
|
||||
on_duty = 'Agora estás de serviço!',
|
||||
off_duty = 'Agora estás fora de serviço!'
|
||||
}
|
||||
|
||||
+93
-62
@@ -1,17 +1,29 @@
|
||||
QBCore.Commands = {}
|
||||
QBCore.Commands.List = {}
|
||||
QBCore.Commands.IgnoreList = { -- Ignore old perm levels while keeping backwards compatibility
|
||||
['god'] = true, -- We don't need to create an ace because god is allowed all commands
|
||||
['user'] = true -- We don't need to create an ace because builtin.everyone
|
||||
}
|
||||
|
||||
CreateThread(function() -- Add ace to node for perm checking
|
||||
for k,v in pairs(QBConfig.Server.Permissions) do
|
||||
ExecuteCommand(('add_ace qbcore.%s %s allow'):format(v, v))
|
||||
end
|
||||
end)
|
||||
|
||||
-- Register & Refresh Commands
|
||||
|
||||
function QBCore.Commands.Add(name, help, arguments, argsrequired, callback, permission)
|
||||
if type(permission) == 'string' then
|
||||
permission = permission:lower()
|
||||
else
|
||||
permission = 'user'
|
||||
local restricted = true -- Default to restricted for all commands
|
||||
if not permission then permission = 'user' end -- some commands don't pass permission level
|
||||
if permission == 'user' then restricted = false end -- allow all users to use command
|
||||
RegisterCommand(name, callback, restricted) -- Register command within fivem
|
||||
if not QBCore.Commands.IgnoreList[permission] then -- only create aces for extra perm levels
|
||||
ExecuteCommand(('add_ace qbcore.%s command.%s allow'):format(permission, name))
|
||||
end
|
||||
QBCore.Commands.List[name:lower()] = {
|
||||
name = name:lower(),
|
||||
permission = permission,
|
||||
permission = tostring(permission:lower()),
|
||||
help = help,
|
||||
arguments = arguments,
|
||||
argsrequired = argsrequired,
|
||||
@@ -25,195 +37,214 @@ function QBCore.Commands.Refresh(source)
|
||||
local suggestions = {}
|
||||
if Player then
|
||||
for command, info in pairs(QBCore.Commands.List) do
|
||||
local isGod = QBCore.Functions.HasPermission(src, 'god')
|
||||
local hasPerm = QBCore.Functions.HasPermission(src, QBCore.Commands.List[command].permission)
|
||||
local isPrincipal = IsPlayerAceAllowed(src, 'command')
|
||||
if isGod or hasPerm or isPrincipal then
|
||||
local hasPerm = IsPlayerAceAllowed(tostring(src), 'command.'..command)
|
||||
if hasPerm then
|
||||
suggestions[#suggestions + 1] = {
|
||||
name = '/' .. command,
|
||||
help = info.help,
|
||||
params = info.arguments
|
||||
}
|
||||
else
|
||||
TriggerClientEvent('chat:removeSuggestion', src, '/'..command)
|
||||
end
|
||||
end
|
||||
TriggerClientEvent('chat:addSuggestions', tonumber(source), suggestions)
|
||||
TriggerClientEvent('chat:addSuggestions', src, suggestions)
|
||||
end
|
||||
end
|
||||
|
||||
-- Teleport
|
||||
|
||||
QBCore.Commands.Add('tp', 'TP To Player or Coords (Admin Only)', { { name = 'id/x', help = 'ID of player or X position' }, { name = 'y', help = 'Y position' }, { name = 'z', help = 'Z position' } }, false, function(source, args)
|
||||
local src = source
|
||||
if args[1] and not args[2] and not args[3] then
|
||||
local target = GetPlayerPed(tonumber(args[1]))
|
||||
if target ~= 0 then
|
||||
local coords = GetEntityCoords(target)
|
||||
TriggerClientEvent('QBCore:Command:TeleportToPlayer', src, coords)
|
||||
TriggerClientEvent('QBCore:Command:TeleportToPlayer', source, coords)
|
||||
else
|
||||
TriggerClientEvent('QBCore:Notify', src, Lang:t('error.not_online'), 'error')
|
||||
TriggerClientEvent('QBCore:Notify', source, Lang:t('error.not_online'), 'error')
|
||||
end
|
||||
else
|
||||
if args[1] and args[2] and args[3] then
|
||||
local x = tonumber(args[1])
|
||||
local y = tonumber(args[2])
|
||||
local z = tonumber(args[3])
|
||||
if (x ~= 0) and (y ~= 0) and (z ~= 0) then
|
||||
TriggerClientEvent('QBCore:Command:TeleportToCoords', src, x, y, z)
|
||||
if x ~= 0 and y ~= 0 and z ~= 0 then
|
||||
TriggerClientEvent('QBCore:Command:TeleportToCoords', source, x, y, z)
|
||||
else
|
||||
TriggerClientEvent('QBCore:Notify', src, Lang:t('error.wrong_format'), 'error')
|
||||
TriggerClientEvent('QBCore:Notify', source, Lang:t('error.wrong_format'), 'error')
|
||||
end
|
||||
else
|
||||
TriggerClientEvent('QBCore:Notify', src, Lang:t('error.missing_args'), 'error')
|
||||
TriggerClientEvent('QBCore:Notify', source, Lang:t('error.missing_args'), 'error')
|
||||
end
|
||||
end
|
||||
end, 'admin')
|
||||
|
||||
QBCore.Commands.Add('tpm', 'TP To Marker (Admin Only)', {}, false, function(source)
|
||||
local src = source
|
||||
TriggerClientEvent('QBCore:Command:GoToMarker', src)
|
||||
TriggerClientEvent('QBCore:Command:GoToMarker', source)
|
||||
end, 'admin')
|
||||
|
||||
|
||||
QBCore.Commands.Add('togglepvp', 'Toggle PVP on the server (Admin Only)', {}, false, function(source)
|
||||
local src = source
|
||||
local pvp_state = QBConfig.Server.pvp
|
||||
QBConfig.Server.pvp = not pvp_state
|
||||
TriggerClientEvent('QBCore:Client:PvpHasToggled', -1, QBConfig.Server.pvp)
|
||||
QBCore.Commands.Add('togglepvp', 'Toggle PVP on the server (Admin Only)', {}, false, function()
|
||||
QBConfig.Server.PVP = not QBConfig.Server.PVP
|
||||
TriggerClientEvent('QBCore:Client:PvpHasToggled', -1, QBConfig.Server.PVP)
|
||||
end, 'admin')
|
||||
|
||||
-- Permissions
|
||||
|
||||
QBCore.Commands.Add('addpermission', 'Give Player Permissions (God Only)', { { name = 'id', help = 'ID of player' }, { name = 'permission', help = 'Permission level' } }, true, function(source, args)
|
||||
local src = source
|
||||
local Player = QBCore.Functions.GetPlayer(tonumber(args[1]))
|
||||
local permission = tostring(args[2]):lower()
|
||||
if Player then
|
||||
QBCore.Functions.AddPermission(Player.PlayerData.source, permission)
|
||||
else
|
||||
TriggerClientEvent('QBCore:Notify', src, Lang:t('error.not_online'), 'error')
|
||||
TriggerClientEvent('QBCore:Notify', source, Lang:t('error.not_online'), 'error')
|
||||
end
|
||||
end, 'god')
|
||||
|
||||
QBCore.Commands.Add('removepermission', 'Remove Players Permissions (God Only)', { { name = 'id', help = 'ID of player' } }, true, function(source, args)
|
||||
local src = source
|
||||
QBCore.Commands.Add('removepermission', 'Remove Players Permissions (God Only)', { { name = 'id', help = 'ID of player' }, { name = 'permission', help = 'Permission level' } }, true, function(source, args)
|
||||
local Player = QBCore.Functions.GetPlayer(tonumber(args[1]))
|
||||
local permission = tostring(args[2]):lower()
|
||||
if Player then
|
||||
QBCore.Functions.RemovePermission(Player.PlayerData.source)
|
||||
QBCore.Functions.RemovePermission(Player.PlayerData.source, permission)
|
||||
else
|
||||
TriggerClientEvent('QBCore:Notify', src, Lang:t('error.not_online'), 'error')
|
||||
TriggerClientEvent('QBCore:Notify', source, Lang:t('error.not_online'), 'error')
|
||||
end
|
||||
end, 'god')
|
||||
|
||||
-- Open & Close Server
|
||||
|
||||
QBCore.Commands.Add('openserver', 'Open the server for everyone (Admin Only)', {}, false, function(source)
|
||||
if not QBCore.Config.Server.Closed then
|
||||
TriggerClientEvent('QBCore:Notify', source, 'The server is already open', 'error')
|
||||
return
|
||||
end
|
||||
if QBCore.Functions.HasPermission(source, 'admin') then
|
||||
QBCore.Config.Server.Closed = false
|
||||
else
|
||||
QBCore.Functions.Kick(source, 'You don\'t have permissions for this..', nil, nil)
|
||||
end
|
||||
end, 'admin')
|
||||
|
||||
QBCore.Commands.Add('closeserver', 'Close the server for people without permissions (Admin Only)', { { name = 'reason', help = 'Reason for closing it (optional)' } }, false, function(source, args)
|
||||
if QBCore.Config.Server.Closed then
|
||||
TriggerClientEvent('QBCore:Notify', source, 'The server is already closed', 'error')
|
||||
return
|
||||
end
|
||||
if QBCore.Functions.HasPermission(source, 'admin') then
|
||||
local reason = args[1] or 'No reason specified'
|
||||
QBCore.Config.Server.Closed = true
|
||||
QBCore.Config.Server.ClosedReason = reason
|
||||
for k in pairs(QBCore.Players) do
|
||||
if not QBCore.Functions.HasPermission(k, QBCore.Config.Server.WhitelistPermission) then
|
||||
QBCore.Functions.Kick(k, reason, nil, nil)
|
||||
end
|
||||
end
|
||||
else
|
||||
QBCore.Functions.Kick(source, 'You don\'t have permissions for this..', nil, nil)
|
||||
end
|
||||
end, 'admin')
|
||||
|
||||
-- Vehicle
|
||||
|
||||
QBCore.Commands.Add('car', 'Spawn Vehicle (Admin Only)', { { name = 'model', help = 'Model name of the vehicle' } }, true, function(source, args)
|
||||
local src = source
|
||||
TriggerClientEvent('QBCore:Command:SpawnVehicle', src, args[1])
|
||||
TriggerClientEvent('QBCore:Command:SpawnVehicle', source, args[1])
|
||||
end, 'admin')
|
||||
|
||||
QBCore.Commands.Add('dv', 'Delete Vehicle (Admin Only)', {}, false, function(source)
|
||||
local src = source
|
||||
TriggerClientEvent('QBCore:Command:DeleteVehicle', src)
|
||||
TriggerClientEvent('QBCore:Command:DeleteVehicle', source)
|
||||
end, 'admin')
|
||||
|
||||
-- Money
|
||||
|
||||
QBCore.Commands.Add('givemoney', 'Give A Player Money (Admin Only)', { { name = 'id', help = 'Player ID' }, { name = 'moneytype', help = 'Type of money (cash, bank, crypto)' }, { name = 'amount', help = 'Amount of money' } }, true, function(source, args)
|
||||
local src = source
|
||||
local Player = QBCore.Functions.GetPlayer(tonumber(args[1]))
|
||||
if Player then
|
||||
Player.Functions.AddMoney(tostring(args[2]), tonumber(args[3]))
|
||||
else
|
||||
TriggerClientEvent('QBCore:Notify', src, Lang:t('error.not_online'), 'error')
|
||||
TriggerClientEvent('QBCore:Notify', source, Lang:t('error.not_online'), 'error')
|
||||
end
|
||||
end, 'admin')
|
||||
|
||||
QBCore.Commands.Add('setmoney', 'Set Players Money Amount (Admin Only)', { { name = 'id', help = 'Player ID' }, { name = 'moneytype', help = 'Type of money (cash, bank, crypto)' }, { name = 'amount', help = 'Amount of money' } }, true, function(source, args)
|
||||
local src = source
|
||||
local Player = QBCore.Functions.GetPlayer(tonumber(args[1]))
|
||||
if Player then
|
||||
Player.Functions.SetMoney(tostring(args[2]), tonumber(args[3]))
|
||||
else
|
||||
TriggerClientEvent('QBCore:Notify', src, Lang:t('error.not_online'), 'error')
|
||||
TriggerClientEvent('QBCore:Notify', source, Lang:t('error.not_online'), 'error')
|
||||
end
|
||||
end, 'admin')
|
||||
|
||||
-- Job
|
||||
|
||||
QBCore.Commands.Add('job', 'Check Your Job', {}, false, function(source)
|
||||
local src = source
|
||||
local PlayerJob = QBCore.Functions.GetPlayer(src).PlayerData.job
|
||||
TriggerClientEvent('QBCore:Notify', src, Lang:t('info.job_info', {value = PlayerJob.label, value2 = PlayerJob.grade.name, value3 = PlayerJob.onduty}))
|
||||
local PlayerJob = QBCore.Functions.GetPlayer(source).PlayerData.job
|
||||
TriggerClientEvent('QBCore:Notify', source, Lang:t('info.job_info', {value = PlayerJob.label, value2 = PlayerJob.grade.name, value3 = PlayerJob.onduty}))
|
||||
end, 'user')
|
||||
|
||||
QBCore.Commands.Add('setjob', 'Set A Players Job (Admin Only)', { { name = 'id', help = 'Player ID' }, { name = 'job', help = 'Job name' }, { name = 'grade', help = 'Grade' } }, true, function(source, args)
|
||||
local src = source
|
||||
local Player = QBCore.Functions.GetPlayer(tonumber(args[1]))
|
||||
if Player then
|
||||
Player.Functions.SetJob(tostring(args[2]), tonumber(args[3]))
|
||||
else
|
||||
TriggerClientEvent('QBCore:Notify', src, Lang:t('error.not_online'), 'error')
|
||||
TriggerClientEvent('QBCore:Notify', source, Lang:t('error.not_online'), 'error')
|
||||
end
|
||||
end, 'admin')
|
||||
|
||||
-- Gang
|
||||
|
||||
QBCore.Commands.Add('gang', 'Check Your Gang', {}, false, function(source)
|
||||
local src = source
|
||||
local PlayerGang = QBCore.Functions.GetPlayer(source).PlayerData.gang
|
||||
TriggerClientEvent('QBCore:Notify', src, Lang:t('info.gang_info', {value = PlayerGang.label, value2 = PlayerGang.grade.name}))
|
||||
TriggerClientEvent('QBCore:Notify', source, Lang:t('info.gang_info', {value = PlayerGang.label, value2 = PlayerGang.grade.name}))
|
||||
end, 'user')
|
||||
|
||||
QBCore.Commands.Add('setgang', 'Set A Players Gang (Admin Only)', { { name = 'id', help = 'Player ID' }, { name = 'gang', help = 'Name of a gang' }, { name = 'grade', help = 'Grade' } }, true, function(source, args)
|
||||
local src = source
|
||||
local Player = QBCore.Functions.GetPlayer(tonumber(args[1]))
|
||||
if Player then
|
||||
Player.Functions.SetGang(tostring(args[2]), tonumber(args[3]))
|
||||
else
|
||||
TriggerClientEvent('QBCore:Notify', src, Lang:t('error.not_online'), 'error')
|
||||
TriggerClientEvent('QBCore:Notify', source, Lang:t('error.not_online'), 'error')
|
||||
end
|
||||
end, 'admin')
|
||||
|
||||
-- Inventory (should be in qb-inventory?)
|
||||
|
||||
QBCore.Commands.Add('clearinv', 'Clear Players Inventory (Admin Only)', { { name = 'id', help = 'Player ID' } }, false, function(source, args)
|
||||
local src = source
|
||||
local playerId = args[1] or src
|
||||
local playerId = args[1] and args[1] ~= '' or source
|
||||
local Player = QBCore.Functions.GetPlayer(tonumber(playerId))
|
||||
if Player then
|
||||
Player.Functions.ClearInventory()
|
||||
else
|
||||
TriggerClientEvent('QBCore:Notify', src, Lang:t('error.not_online'), 'error')
|
||||
TriggerClientEvent('QBCore:Notify', source, Lang:t('error.not_online'), 'error')
|
||||
end
|
||||
end, 'admin')
|
||||
|
||||
-- Out of Character Chat
|
||||
|
||||
QBCore.Commands.Add('ooc', 'OOC Chat Message', {}, false, function(source, args)
|
||||
local src = source
|
||||
local message = table.concat(args, ' ')
|
||||
local Players = QBCore.Functions.GetPlayers()
|
||||
local Player = QBCore.Functions.GetPlayer(src)
|
||||
local Player = QBCore.Functions.GetPlayer(source)
|
||||
local playerCoords = GetEntityCoords(GetPlayerPed(source))
|
||||
for k, v in pairs(Players) do
|
||||
if v == src then
|
||||
if v == source then
|
||||
TriggerClientEvent('chat:addMessage', v, {
|
||||
color = { 0, 0, 255},
|
||||
multiline = true,
|
||||
args = {'OOC | '.. GetPlayerName(src), message}
|
||||
args = {'OOC | '.. GetPlayerName(source), message}
|
||||
})
|
||||
elseif #(GetEntityCoords(GetPlayerPed(src)) - GetEntityCoords(GetPlayerPed(v))) < 20.0 then
|
||||
elseif #(playerCoords - GetEntityCoords(GetPlayerPed(v))) < 20.0 then
|
||||
TriggerClientEvent('chat:addMessage', v, {
|
||||
color = { 0, 0, 255},
|
||||
multiline = true,
|
||||
args = {'OOC | '.. GetPlayerName(src), message}
|
||||
args = {'OOC | '.. GetPlayerName(source), message}
|
||||
})
|
||||
elseif QBCore.Functions.HasPermission(v, 'admin') then
|
||||
if QBCore.Functions.IsOptin(v) then
|
||||
TriggerClientEvent('chat:addMessage', v, {
|
||||
color = { 0, 0, 255},
|
||||
multiline = true,
|
||||
args = {'Proxmity OOC | '.. GetPlayerName(src), message}
|
||||
args = {'Proxmity OOC | '.. GetPlayerName(source), message}
|
||||
})
|
||||
TriggerEvent('qb-log:server:CreateLog', 'ooc', 'OOC', 'white', '**' .. GetPlayerName(src) .. '** (CitizenID: ' .. Player.PlayerData.citizenid .. ' | ID: ' .. src .. ') **Message:** ' .. message, false)
|
||||
TriggerEvent('qb-log:server:CreateLog', 'ooc', 'OOC', 'white', '**' .. GetPlayerName(source) .. '** (CitizenID: ' .. Player.PlayerData.citizenid .. ' | ID: ' .. source .. ') **Message:** ' .. message, false)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -222,16 +253,16 @@ end, 'user')
|
||||
-- Me command
|
||||
|
||||
QBCore.Commands.Add('me', 'Show local message', {{name = 'message', help = 'Message to respond with'}}, false, function(source, args)
|
||||
local src = source
|
||||
local ped = GetPlayerPed(src)
|
||||
local ped = GetPlayerPed(source)
|
||||
local pCoords = GetEntityCoords(ped)
|
||||
local msg = table.concat(args, ' ')
|
||||
if msg == '' then return end
|
||||
if string.match(msg, "<") then TriggerClientEvent('QBCore:Notify', source, Lang:t('error.wrong_format'), 'error') return end
|
||||
for k,v in pairs(QBCore.Functions.GetPlayers()) do
|
||||
local target = GetPlayerPed(v)
|
||||
local tCoords = GetEntityCoords(target)
|
||||
if #(pCoords - tCoords) < 20 then
|
||||
TriggerClientEvent('QBCore:Command:ShowMe3D', v, src, msg)
|
||||
TriggerClientEvent('QBCore:Command:ShowMe3D', v, source, msg)
|
||||
end
|
||||
end
|
||||
end, 'user')
|
||||
|
||||
+25
-24
@@ -1,38 +1,39 @@
|
||||
local function tPrint(tbl, indent)
|
||||
indent = indent or 0
|
||||
for k, v in pairs(tbl) do
|
||||
local tblType = type(v)
|
||||
local formatting = ("%s ^3%s:^0"):format(string.rep(" ", indent), k)
|
||||
if type(tbl) == 'table' then
|
||||
for k, v in pairs(tbl) do
|
||||
local tblType = type(v)
|
||||
local formatting = ("%s ^3%s:^0"):format(string.rep(" ", indent), k)
|
||||
|
||||
if tblType == "table" then
|
||||
print(formatting)
|
||||
tPrint(v, indent + 1)
|
||||
elseif tblType == 'boolean' then
|
||||
print(("%s^1 %s ^0"):format(formatting, v))
|
||||
elseif tblType == "function" then
|
||||
print(("%s^9 %s ^0"):format(formatting, v))
|
||||
elseif tblType == 'number' then
|
||||
print(("%s^5 %s ^0"):format(formatting, v))
|
||||
elseif tblType == 'string' then
|
||||
print(("%s ^2'%s' ^0"):format(formatting, v))
|
||||
else
|
||||
print(("%s^2 %s ^0"):format(formatting, v))
|
||||
if tblType == "table" then
|
||||
print(formatting)
|
||||
tPrint(v, indent + 1)
|
||||
elseif tblType == 'boolean' then
|
||||
print(("%s^1 %s ^0"):format(formatting, v))
|
||||
elseif tblType == "function" then
|
||||
print(("%s^9 %s ^0"):format(formatting, v))
|
||||
elseif tblType == 'number' then
|
||||
print(("%s^5 %s ^0"):format(formatting, v))
|
||||
elseif tblType == 'string' then
|
||||
print(("%s ^2'%s' ^0"):format(formatting, v))
|
||||
else
|
||||
print(("%s^2 %s ^0"):format(formatting, v))
|
||||
end
|
||||
end
|
||||
else
|
||||
print(("%s ^0%s"):format(string.rep(" ", indent), tbl))
|
||||
end
|
||||
end
|
||||
|
||||
RegisterServerEvent('QBCore:DebugSomething', function(table, indent)
|
||||
RegisterServerEvent('QBCore:DebugSomething', function(tbl, indent)
|
||||
local resource = GetInvokingResource() or "qb-core"
|
||||
|
||||
print(('\x1b[4m\x1b[36m[ %s : DEBUG]\x1b[0m'):format(resource))
|
||||
|
||||
tPrint(table, indent)
|
||||
|
||||
tPrint(tbl, indent)
|
||||
print('\x1b[4m\x1b[36m[ END DEBUG ]\x1b[0m')
|
||||
end)
|
||||
|
||||
function QBCore.Debug(table, indent)
|
||||
TriggerEvent('QBCore:DebugSomething', table, indent)
|
||||
function QBCore.Debug(tbl, indent)
|
||||
TriggerEvent('QBCore:DebugSomething', tbl, indent)
|
||||
end
|
||||
|
||||
function QBCore.ShowError(resource, msg)
|
||||
@@ -41,4 +42,4 @@ end
|
||||
|
||||
function QBCore.ShowSuccess(resource, msg)
|
||||
print('\x1b[32m['..resource..':LOG]\x1b[0m '..msg)
|
||||
end
|
||||
end
|
||||
+117
-134
@@ -1,54 +1,39 @@
|
||||
-- Event Handler
|
||||
|
||||
AddEventHandler('playerDropped', function()
|
||||
local src = source
|
||||
if QBCore.Players[src] then
|
||||
local Player = QBCore.Players[src]
|
||||
TriggerEvent('qb-log:server:CreateLog', 'joinleave', 'Dropped', 'red', '**' .. GetPlayerName(src) .. '** (' .. Player.PlayerData.license .. ') left..')
|
||||
Player.Functions.Save()
|
||||
_G.Player_Buckets[Player.PlayerData.license] = nil
|
||||
QBCore.Players[src] = nil
|
||||
AddEventHandler('chatMessage', function(source, _, message)
|
||||
if string.sub(message, 1, 1) == '/' then
|
||||
CancelEvent()
|
||||
return
|
||||
end
|
||||
end)
|
||||
|
||||
AddEventHandler('chatMessage', function(source, n, message)
|
||||
AddEventHandler('playerDropped', function()
|
||||
local src = source
|
||||
if string.sub(message, 1, 1) == '/' then
|
||||
local args = QBCore.Shared.SplitStr(message, ' ')
|
||||
local command = string.gsub(args[1]:lower(), '/', '')
|
||||
CancelEvent()
|
||||
if QBCore.Commands.List[command] then
|
||||
local Player = QBCore.Functions.GetPlayer(src)
|
||||
if Player then
|
||||
local isGod = QBCore.Functions.HasPermission(src, 'god')
|
||||
local hasPerm = QBCore.Functions.HasPermission(src, QBCore.Commands.List[command].permission)
|
||||
local isPrincipal = IsPlayerAceAllowed(src, 'command')
|
||||
table.remove(args, 1)
|
||||
if isGod or hasPerm or isPrincipal then
|
||||
if (QBCore.Commands.List[command].argsrequired and #QBCore.Commands.List[command].arguments ~= 0 and args[#QBCore.Commands.List[command].arguments] == nil) then
|
||||
TriggerClientEvent('QBCore:Notify', src, Lang:t('error.missing_args2'), 'error')
|
||||
else
|
||||
QBCore.Commands.List[command].callback(src, args)
|
||||
end
|
||||
else
|
||||
TriggerClientEvent('QBCore:Notify', src, Lang:t('error.no_access'), 'error')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if not QBCore.Players[src] then return end
|
||||
local Player = QBCore.Players[src]
|
||||
TriggerEvent('qb-log:server:CreateLog', 'joinleave', 'Dropped', 'red', '**' .. GetPlayerName(src) .. '** (' .. Player.PlayerData.license .. ') left..')
|
||||
Player.Functions.Save()
|
||||
QBCore.Player_Buckets[Player.PlayerData.license] = nil
|
||||
QBCore.Players[src] = nil
|
||||
end)
|
||||
|
||||
-- Player Connecting
|
||||
|
||||
local function OnPlayerConnecting(name, setKickReason, deferrals)
|
||||
local player = source
|
||||
local function onPlayerConnecting(name, setKickReason, deferrals)
|
||||
local src = source
|
||||
local license
|
||||
local identifiers = GetPlayerIdentifiers(player)
|
||||
local identifiers = GetPlayerIdentifiers(src)
|
||||
deferrals.defer()
|
||||
|
||||
-- mandatory wait!
|
||||
-- Mandatory wait
|
||||
Wait(0)
|
||||
|
||||
if QBCore.Config.Server.Closed then
|
||||
if not IsPlayerAceAllowed(src, 'qbadmin.join') then
|
||||
deferrals.done(QBCore.Config.Server.ClosedReason)
|
||||
end
|
||||
end
|
||||
|
||||
deferrals.update(string.format('Hello %s. Validating Your Rockstar License', name))
|
||||
|
||||
for _, v in pairs(identifiers) do
|
||||
@@ -58,13 +43,14 @@ local function OnPlayerConnecting(name, setKickReason, deferrals)
|
||||
end
|
||||
end
|
||||
|
||||
-- mandatory wait!
|
||||
-- Mandatory wait
|
||||
Wait(2500)
|
||||
|
||||
deferrals.update(string.format('Hello %s. We are checking if you are banned.', name))
|
||||
deferrals.update(string.format('Hello %s. We are checking your allowance.', name))
|
||||
|
||||
local isBanned, Reason = QBCore.Functions.IsPlayerBanned(player)
|
||||
local isBanned, Reason = QBCore.Functions.IsPlayerBanned(src)
|
||||
local isLicenseAlreadyInUse = QBCore.Functions.IsLicenseInUse(license)
|
||||
local isWhitelist, whitelisted = QBCore.Config.Server.Whitelist, QBCore.Functions.IsWhitelisted(src)
|
||||
|
||||
Wait(2500)
|
||||
|
||||
@@ -74,35 +60,44 @@ local function OnPlayerConnecting(name, setKickReason, deferrals)
|
||||
deferrals.done('No Valid Rockstar License Found')
|
||||
elseif isBanned then
|
||||
deferrals.done(Reason)
|
||||
elseif isLicenseAlreadyInUse and QBCore.Config.Server.checkDuplicateLicense then
|
||||
elseif isLicenseAlreadyInUse and QBCore.Config.Server.CheckDuplicateLicense then
|
||||
deferrals.done('Duplicate Rockstar License Found')
|
||||
elseif isWhitelist and not whitelisted then
|
||||
deferrals.done('You\'re not whitelisted for this server')
|
||||
else
|
||||
deferrals.done()
|
||||
Wait(1000)
|
||||
TriggerEvent('connectqueue:playerConnect', name, setKickReason, deferrals)
|
||||
if QBCore.Config.Server.UseConnectQueue then
|
||||
Wait(1000)
|
||||
TriggerEvent('connectqueue:playerConnect', name, setKickReason, deferrals)
|
||||
end
|
||||
end
|
||||
--Add any additional defferals you may need!
|
||||
-- Add any additional defferals you may need!
|
||||
end
|
||||
|
||||
AddEventHandler('playerConnecting', OnPlayerConnecting)
|
||||
AddEventHandler('playerConnecting', onPlayerConnecting)
|
||||
|
||||
-- Open & Close Server (prevents players from joining)
|
||||
|
||||
RegisterNetEvent('QBCore:server:CloseServer', function(reason)
|
||||
RegisterNetEvent('QBCore:Server:CloseServer', function(reason)
|
||||
local src = source
|
||||
if QBCore.Functions.HasPermission(src, 'admin') or QBCore.Functions.HasPermission(src, 'god') then
|
||||
local reason = reason or 'No reason specified'
|
||||
QBCore.Config.Server.closed = true
|
||||
QBCore.Config.Server.closedReason = reason
|
||||
if QBCore.Functions.HasPermission(src, 'admin') then
|
||||
reason = reason or 'No reason specified'
|
||||
QBCore.Config.Server.Closed = true
|
||||
QBCore.Config.Server.ClosedReason = reason
|
||||
for k in pairs(QBCore.Players) do
|
||||
if not QBCore.Functions.HasPermission(k, QBCore.Config.Server.WhitelistPermission) then
|
||||
QBCore.Functions.Kick(k, reason, nil, nil)
|
||||
end
|
||||
end
|
||||
else
|
||||
QBCore.Functions.Kick(src, 'You don\'t have permissions for this..', nil, nil)
|
||||
end
|
||||
end)
|
||||
|
||||
RegisterNetEvent('QBCore:server:OpenServer', function()
|
||||
RegisterNetEvent('QBCore:Server:OpenServer', function()
|
||||
local src = source
|
||||
if QBCore.Functions.HasPermission(src, 'admin') or QBCore.Functions.HasPermission(src, 'god') then
|
||||
QBCore.Config.Server.closed = false
|
||||
if QBCore.Functions.HasPermission(src, 'admin') then
|
||||
QBCore.Config.Server.Closed = false
|
||||
else
|
||||
QBCore.Functions.Kick(src, 'You don\'t have permissions for this..', nil, nil)
|
||||
end
|
||||
@@ -122,20 +117,19 @@ end)
|
||||
RegisterNetEvent('QBCore:UpdatePlayer', function()
|
||||
local src = source
|
||||
local Player = QBCore.Functions.GetPlayer(src)
|
||||
if Player then
|
||||
local newHunger = Player.PlayerData.metadata['hunger'] - QBCore.Config.Player.HungerRate
|
||||
local newThirst = Player.PlayerData.metadata['thirst'] - QBCore.Config.Player.ThirstRate
|
||||
if newHunger <= 0 then
|
||||
newHunger = 0
|
||||
end
|
||||
if newThirst <= 0 then
|
||||
newThirst = 0
|
||||
end
|
||||
Player.Functions.SetMetaData('thirst', newThirst)
|
||||
Player.Functions.SetMetaData('hunger', newHunger)
|
||||
TriggerClientEvent('hud:client:UpdateNeeds', src, newHunger, newThirst)
|
||||
Player.Functions.Save()
|
||||
if not Player then return end
|
||||
local newHunger = Player.PlayerData.metadata['hunger'] - QBCore.Config.Player.HungerRate
|
||||
local newThirst = Player.PlayerData.metadata['thirst'] - QBCore.Config.Player.ThirstRate
|
||||
if newHunger <= 0 then
|
||||
newHunger = 0
|
||||
end
|
||||
if newThirst <= 0 then
|
||||
newThirst = 0
|
||||
end
|
||||
Player.Functions.SetMetaData('thirst', newThirst)
|
||||
Player.Functions.SetMetaData('hunger', newHunger)
|
||||
TriggerClientEvent('hud:client:UpdateNeeds', src, newHunger, newThirst)
|
||||
Player.Functions.Save()
|
||||
end)
|
||||
|
||||
RegisterNetEvent('QBCore:Server:SetMetaData', function(meta, data)
|
||||
@@ -155,6 +149,7 @@ end)
|
||||
RegisterNetEvent('QBCore:ToggleDuty', function()
|
||||
local src = source
|
||||
local Player = QBCore.Functions.GetPlayer(src)
|
||||
if not Player then return end
|
||||
if Player.PlayerData.job.onduty then
|
||||
Player.Functions.SetJobDuty(false)
|
||||
TriggerClientEvent('QBCore:Notify', src, Lang:t('info.off_duty'))
|
||||
@@ -169,22 +164,21 @@ end)
|
||||
|
||||
RegisterNetEvent('QBCore:Server:UseItem', function(item)
|
||||
local src = source
|
||||
if item and item.amount > 0 then
|
||||
if QBCore.Functions.CanUseItem(item.name) then
|
||||
QBCore.Functions.UseItem(src, item)
|
||||
end
|
||||
end
|
||||
if not item or item.amount <= 0 or not QBCore.Functions.CanUseItem(item.name) then return end
|
||||
QBCore.Functions.UseItem(src, item)
|
||||
end)
|
||||
|
||||
RegisterNetEvent('QBCore:Server:RemoveItem', function(itemName, amount, slot)
|
||||
local src = source
|
||||
local Player = QBCore.Functions.GetPlayer(src)
|
||||
if not Player then return end
|
||||
Player.Functions.RemoveItem(itemName, amount, slot)
|
||||
end)
|
||||
|
||||
RegisterNetEvent('QBCore:Server:AddItem', function(itemName, amount, slot, info)
|
||||
local src = source
|
||||
local Player = QBCore.Functions.GetPlayer(src)
|
||||
if not Player then return end
|
||||
Player.Functions.AddItem(itemName, amount, slot, info)
|
||||
end)
|
||||
|
||||
@@ -192,83 +186,72 @@ end)
|
||||
|
||||
RegisterNetEvent('QBCore:CallCommand', function(command, args)
|
||||
local src = source
|
||||
if QBCore.Commands.List[command] then
|
||||
local Player = QBCore.Functions.GetPlayer(src)
|
||||
if Player then
|
||||
local isGod = QBCore.Functions.HasPermission(src, 'god')
|
||||
local hasPerm = QBCore.Functions.HasPermission(src, QBCore.Commands.List[command].permission)
|
||||
local isPrincipal = IsPlayerAceAllowed(src, 'command')
|
||||
if (QBCore.Commands.List[command].permission == Player.PlayerData.job.name) or isGod or hasPerm or isPrincipal then
|
||||
if (QBCore.Commands.List[command].argsrequired and #QBCore.Commands.List[command].arguments ~= 0 and args[#QBCore.Commands.List[command].arguments] == nil) then
|
||||
TriggerClientEvent('QBCore:Notify', src, Lang:t('error.missing_args2'), 'error')
|
||||
else
|
||||
QBCore.Commands.List[command].callback(src, args)
|
||||
end
|
||||
else
|
||||
TriggerClientEvent('QBCore:Notify', src, Lang:t('error.no_access'), 'error')
|
||||
end
|
||||
if not QBCore.Commands.List[command] then return end
|
||||
local Player = QBCore.Functions.GetPlayer(src)
|
||||
if not Player then return end
|
||||
local hasPerm = QBCore.Functions.HasPermission(src, QBCore.Commands.List[command].permission)
|
||||
if hasPerm then
|
||||
if QBCore.Commands.List[command].argsrequired and #QBCore.Commands.List[command].arguments ~= 0 and not args[#QBCore.Commands.List[command].arguments] then
|
||||
TriggerClientEvent('QBCore:Notify', src, Lang:t('error.missing_args2'), 'error')
|
||||
else
|
||||
QBCore.Commands.List[command].callback(src, args)
|
||||
end
|
||||
else
|
||||
TriggerClientEvent('QBCore:Notify', src, Lang:t('error.no_access'), 'error')
|
||||
end
|
||||
end)
|
||||
|
||||
-- Has Item Callback (can also use client function - QBCore.Functions.HasItem(item))
|
||||
|
||||
QBCore.Functions.CreateCallback('QBCore:HasItem', function(source, cb, items, amount)
|
||||
local src = source
|
||||
local retval = false
|
||||
local Player = QBCore.Functions.GetPlayer(src)
|
||||
if Player then
|
||||
if type(items) == 'table' then
|
||||
local count = 0
|
||||
local finalcount = 0
|
||||
for k, v in pairs(items) do
|
||||
if type(k) == 'string' then
|
||||
finalcount = 0
|
||||
for i, _ in pairs(items) do
|
||||
if i then
|
||||
finalcount = finalcount + 1
|
||||
end
|
||||
end
|
||||
local item = Player.Functions.GetItemByName(k)
|
||||
if item then
|
||||
if item.amount >= v then
|
||||
count = count + 1
|
||||
if count == finalcount then
|
||||
retval = true
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
finalcount = #items
|
||||
local item = Player.Functions.GetItemByName(v)
|
||||
if item then
|
||||
if amount then
|
||||
if item.amount >= amount then
|
||||
count = count + 1
|
||||
if count == finalcount then
|
||||
retval = true
|
||||
end
|
||||
end
|
||||
else
|
||||
count = count + 1
|
||||
if count == finalcount then
|
||||
retval = true
|
||||
end
|
||||
local Player = QBCore.Functions.GetPlayer(source)
|
||||
if not Player then return cb(false) end
|
||||
if type(items) == 'table' then
|
||||
local count = 0
|
||||
local finalcount = 0
|
||||
for k, v in pairs(items) do
|
||||
if type(k) == 'string' then
|
||||
finalcount = 0
|
||||
for i, _ in pairs(items) do finalcount += 1 end
|
||||
local item = Player.Functions.GetItemByName(k)
|
||||
if item then
|
||||
if item.amount >= v then
|
||||
count += 1
|
||||
if count == finalcount then
|
||||
retval = true
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
finalcount = #items
|
||||
local item = Player.Functions.GetItemByName(v)
|
||||
if item then
|
||||
if amount then
|
||||
if item.amount >= amount then
|
||||
count += 1
|
||||
if count == finalcount then
|
||||
retval = true
|
||||
end
|
||||
end
|
||||
else
|
||||
count += 1
|
||||
if count == finalcount then
|
||||
retval = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
local item = Player.Functions.GetItemByName(items)
|
||||
if not item then return cb(false) end
|
||||
if amount then
|
||||
if item.amount >= amount then
|
||||
retval = true
|
||||
end
|
||||
else
|
||||
local item = Player.Functions.GetItemByName(items)
|
||||
if item then
|
||||
if amount then
|
||||
if item.amount >= amount then
|
||||
retval = true
|
||||
end
|
||||
else
|
||||
retval = true
|
||||
end
|
||||
end
|
||||
retval = true
|
||||
end
|
||||
end
|
||||
cb(retval)
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
-- Single add job function which should only be used if you planning on adding a single job
|
||||
local function AddJob(jobName, job)
|
||||
if type(jobName) ~= "string" then
|
||||
return false, "invalid_job_name"
|
||||
end
|
||||
|
||||
if QBCore.Shared.Jobs[jobName] then
|
||||
return false, "job_exists"
|
||||
end
|
||||
|
||||
QBCore.Shared.Jobs[jobName] = job
|
||||
TriggerClientEvent('QBCore:Client:OnSharedUpdate', -1,'Jobs', jobName, job)
|
||||
TriggerEvent('QBCore:Server:UpdateObject')
|
||||
return true, "success"
|
||||
end
|
||||
QBCore.Functions.AddJob = AddJob
|
||||
exports('AddJob', AddJob)
|
||||
|
||||
-- Multiple Add Jobs
|
||||
local function AddJobs(jobs)
|
||||
local shouldContinue = true
|
||||
local message = "success"
|
||||
local errorItem = nil
|
||||
for key, value in pairs(jobs) do
|
||||
if type(key) ~= "string" then
|
||||
message = 'invalid_job_name'
|
||||
shouldContinue = false
|
||||
errorItem = jobs[key]
|
||||
break
|
||||
end
|
||||
|
||||
if QBCore.Shared.Jobs[key] then
|
||||
message = 'job_exists'
|
||||
shouldContinue = false
|
||||
errorItem = jobs[key]
|
||||
break
|
||||
end
|
||||
|
||||
QBCore.Shared.Jobs[key] = value
|
||||
end
|
||||
|
||||
if not shouldContinue then return false, message, errorItem end
|
||||
TriggerClientEvent('QBCore:Client:OnSharedUpdateMultiple', -1, 'Jobs', jobs)
|
||||
TriggerEvent('QBCore:Server:UpdateObject')
|
||||
return true, message, nil
|
||||
end
|
||||
QBCore.Functions.AddJobs = AddJobs
|
||||
exports('AddJobs', AddJobs)
|
||||
|
||||
-- Single add item
|
||||
local function AddItem(itemName, item)
|
||||
if type(itemName) ~= "string" then
|
||||
return false, "invalid_item_name"
|
||||
end
|
||||
|
||||
if QBCore.Shared.Items[itemName] then
|
||||
return false, "item_exists"
|
||||
end
|
||||
|
||||
QBCore.Shared.Items[itemName] = item
|
||||
TriggerClientEvent('QBCore:Client:OnSharedUpdate', -1, 'Items', itemName, item)
|
||||
TriggerEvent('QBCore:Server:UpdateObject')
|
||||
return true, "success"
|
||||
end
|
||||
QBCore.Functions.AddItem = AddItem
|
||||
exports('AddItem', AddItem)
|
||||
|
||||
-- Multiple Add Items
|
||||
local function AddItems(items)
|
||||
local shouldContinue = true
|
||||
local message = "success"
|
||||
local errorItem = nil
|
||||
for key, value in pairs(items) do
|
||||
if type(key) ~= "string" then
|
||||
message = "invalid_item_name"
|
||||
shouldContinue = false
|
||||
errorItem = items[key]
|
||||
break
|
||||
end
|
||||
|
||||
if QBCore.Shared.Items[key] then
|
||||
message = "item_exists"
|
||||
shouldContinue = false
|
||||
errorItem = items[key]
|
||||
break
|
||||
end
|
||||
|
||||
QBCore.Shared.Items[key] = value
|
||||
end
|
||||
|
||||
if not shouldContinue then return false, message, errorItem end
|
||||
TriggerClientEvent('QBCore:Client:OnSharedUpdateMultiple', -1, 'Items', items)
|
||||
TriggerEvent('QBCore:Server:UpdateObject')
|
||||
return true, message, nil
|
||||
end
|
||||
QBCore.Functions.AddItems = AddItems
|
||||
exports('AddItems', AddItems)
|
||||
|
||||
-- Single Add Gang
|
||||
local function AddGang(gangName, gang)
|
||||
if type(gangName) ~= "string" then
|
||||
return false, "invalid_gang_name"
|
||||
end
|
||||
if QBCore.Shared.Gangs[gangName] then
|
||||
return false, "gang_exists"
|
||||
end
|
||||
|
||||
QBCore.Shared.Gangs[gangName] = gang
|
||||
TriggerClientEvent('QBCore:Client:OnSharedUpdate', -1, 'Gangs', gangName, gang)
|
||||
TriggerEvent('QBCore:Server:UpdateObject')
|
||||
return true, "success"
|
||||
end
|
||||
QBCore.Functions.AddGang = AddGang
|
||||
exports('AddGang', AddGang)
|
||||
|
||||
-- Multiple Add Gangs
|
||||
local function AddGangs(gangs)
|
||||
local shouldContinue = true
|
||||
local message = "success"
|
||||
local errorItem = nil
|
||||
for key, value in pairs(gangs) do
|
||||
if type(key) ~= "string" then
|
||||
message = "invalid_gang_name"
|
||||
shouldContinue = false
|
||||
errorItem = gangs[key]
|
||||
break
|
||||
end
|
||||
|
||||
if QBCore.Shared.Gangs[key] then
|
||||
message = "gang_exists"
|
||||
shouldContinue = false
|
||||
errorItem = gangs[key]
|
||||
break
|
||||
end
|
||||
QBCore.Shared.Gangs[key] = value
|
||||
end
|
||||
|
||||
if not shouldContinue then return false, message, errorItem end
|
||||
TriggerClientEvent('QBCore:Client:OnSharedUpdateMultiple', -1, 'Gangs', gangs)
|
||||
TriggerEvent('QBCore:Server:UpdateObject')
|
||||
return true, message, nil
|
||||
end
|
||||
QBCore.Functions.AddGangs = AddGangs
|
||||
exports('AddGangs', AddGangs)
|
||||
|
||||
local function GetCoreVersion(InvokingResource)
|
||||
local resourceVersion = GetResourceMetadata(GetCurrentResourceName(), 'version')
|
||||
if InvokingResource and InvokingResource ~= '' then
|
||||
print(("%s called qbcore version check: %s"):format(InvokingResource or 'Unknown Resource', resourceVersion))
|
||||
end
|
||||
return resourceVersion
|
||||
end
|
||||
QBCore.Functions.GetCoreVersion = GetCoreVersion
|
||||
exports('GetCoreVersion', GetCoreVersion)
|
||||
+112
-173
@@ -1,4 +1,6 @@
|
||||
QBCore.Functions = {}
|
||||
QBCore.Player_Buckets = {}
|
||||
QBCore.Entity_Buckets = {}
|
||||
|
||||
-- Getters
|
||||
-- Get your player first and then trigger a function on them
|
||||
@@ -12,9 +14,8 @@ function QBCore.Functions.GetCoords(entity)
|
||||
end
|
||||
|
||||
function QBCore.Functions.GetIdentifier(source, idtype)
|
||||
local src = source
|
||||
local idtype = idtype or QBConfig.IdentifierType
|
||||
for _, identifier in pairs(GetPlayerIdentifiers(src)) do
|
||||
local identifiers = GetPlayerIdentifiers(source)
|
||||
for _, identifier in pairs(identifiers) do
|
||||
if string.find(identifier, idtype) then
|
||||
return identifier
|
||||
end
|
||||
@@ -23,7 +24,7 @@ function QBCore.Functions.GetIdentifier(source, idtype)
|
||||
end
|
||||
|
||||
function QBCore.Functions.GetSource(identifier)
|
||||
for src, player in pairs(QBCore.Players) do
|
||||
for src, _ in pairs(QBCore.Players) do
|
||||
local idens = GetPlayerIdentifiers(src)
|
||||
for _, id in pairs(idens) do
|
||||
if identifier == id then
|
||||
@@ -35,18 +36,16 @@ function QBCore.Functions.GetSource(identifier)
|
||||
end
|
||||
|
||||
function QBCore.Functions.GetPlayer(source)
|
||||
local src = source
|
||||
if type(src) == 'number' then
|
||||
return QBCore.Players[src]
|
||||
if type(source) == 'number' then
|
||||
return QBCore.Players[source]
|
||||
else
|
||||
return QBCore.Players[QBCore.Functions.GetSource(src)]
|
||||
return QBCore.Players[QBCore.Functions.GetSource(source)]
|
||||
end
|
||||
end
|
||||
|
||||
function QBCore.Functions.GetPlayerByCitizenId(citizenid)
|
||||
for src, player in pairs(QBCore.Players) do
|
||||
local cid = citizenid
|
||||
if QBCore.Players[src].PlayerData.citizenid == cid then
|
||||
for src, _ in pairs(QBCore.Players) do
|
||||
if QBCore.Players[src].PlayerData.citizenid == citizenid then
|
||||
return QBCore.Players[src]
|
||||
end
|
||||
end
|
||||
@@ -54,8 +53,7 @@ function QBCore.Functions.GetPlayerByCitizenId(citizenid)
|
||||
end
|
||||
|
||||
function QBCore.Functions.GetPlayerByPhone(number)
|
||||
for src, player in pairs(QBCore.Players) do
|
||||
local cid = citizenid
|
||||
for src, _ in pairs(QBCore.Players) do
|
||||
if QBCore.Players[src].PlayerData.charinfo.phone == number then
|
||||
return QBCore.Players[src]
|
||||
end
|
||||
@@ -81,12 +79,11 @@ end
|
||||
function QBCore.Functions.GetPlayersOnDuty(job)
|
||||
local players = {}
|
||||
local count = 0
|
||||
|
||||
for src, Player in pairs(QBCore.Players) do
|
||||
if Player.PlayerData.job.name == job then
|
||||
if Player.PlayerData.job.onduty then
|
||||
players[#players + 1] = src
|
||||
count = count + 1
|
||||
count += 1
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -96,59 +93,53 @@ end
|
||||
-- Returns only the amount of players on duty for the specified job
|
||||
function QBCore.Functions.GetDutyCount(job)
|
||||
local count = 0
|
||||
|
||||
for _, Player in pairs(QBCore.Functions.GetQBPlayers()) do
|
||||
for _, Player in pairs(QBCore.Players) do
|
||||
if Player.PlayerData.job.name == job then
|
||||
if Player.PlayerData.job.onduty then
|
||||
count = count + 1
|
||||
count += 1
|
||||
end
|
||||
end
|
||||
end
|
||||
return count
|
||||
end
|
||||
|
||||
--- Routingbucket stuff (Only touch if you know what you are doing)
|
||||
_G.Player_Buckets = {} -- Bucket array containing all players that have been set to a different bucket
|
||||
_G.Entity_Buckets = {} -- Bucket array containing all entities that have been set to a different bucket
|
||||
-- Routing buckets (Only touch if you know what you are doing)
|
||||
|
||||
|
||||
--- Returns the objects related to buckets, first returned value is the player buckets , second one is entity buckets
|
||||
-- Returns the objects related to buckets, first returned value is the player buckets, second one is entity buckets
|
||||
function QBCore.Functions.GetBucketObjects()
|
||||
return _G.Player_Buckets, _G.Entity_Buckets
|
||||
return QBCore.Player_Buckets, QBCore.Entity_Buckets
|
||||
end
|
||||
|
||||
|
||||
--- Will set the provided player id / source into the provided bucket id
|
||||
function QBCore.Functions.SetPlayerBucket(player_source --[[int]],bucket --[[int]])
|
||||
if player_source and bucket then
|
||||
local plicense = QBCore.Functions.GetIdentifier(player_source, 'license')
|
||||
SetPlayerRoutingBucket(player_source, bucket)
|
||||
_G.Player_Buckets[plicense] = {player_id = player_source, player_bucket = bucket}
|
||||
-- Will set the provided player id / source into the provided bucket id
|
||||
function QBCore.Functions.SetPlayerBucket(source --[[ int ]], bucket --[[ int ]])
|
||||
if source and bucket then
|
||||
local plicense = QBCore.Functions.GetIdentifier(source, 'license')
|
||||
SetPlayerRoutingBucket(source, bucket)
|
||||
QBCore.Player_Buckets[plicense] = {id = source, bucket = bucket}
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
--- Will set any entity into the provided bucket, for example peds / vehicles / props / etc...
|
||||
function QBCore.Functions.SetEntityBucket(entity --[[int]],bucket --[[int]])
|
||||
-- Will set any entity into the provided bucket, for example peds / vehicles / props / etc.
|
||||
function QBCore.Functions.SetEntityBucket(entity --[[ int ]], bucket --[[ int ]])
|
||||
if entity and bucket then
|
||||
SetEntityRoutingBucket(entity, bucket)
|
||||
_G.Entity_Buckets[entity] = {entity_id = entity, entity_bucket = bucket}
|
||||
QBCore.Entity_Buckets[entity] = {id = entity, bucket = bucket}
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- Will return an array of all the player ids inside the current bucket
|
||||
function QBCore.Functions.GetPlayersInBucket(bucket --[[int]])
|
||||
function QBCore.Functions.GetPlayersInBucket(bucket --[[ int ]])
|
||||
local curr_bucket_pool = {}
|
||||
if _G.Player_Buckets ~= nil then
|
||||
for k, v in pairs(_G.Player_Buckets) do
|
||||
if k['player_bucket'] == bucket then
|
||||
curr_bucket_pool[#curr_bucket_pool + 1] = k['player_id']
|
||||
if QBCore.Player_Buckets and next(QBCore.Player_Buckets) then
|
||||
for k, v in pairs(QBCore.Player_Buckets) do
|
||||
if v.bucket == bucket then
|
||||
curr_bucket_pool[#curr_bucket_pool + 1] = v.id
|
||||
end
|
||||
end
|
||||
return curr_bucket_pool
|
||||
@@ -157,14 +148,13 @@ function QBCore.Functions.GetPlayersInBucket(bucket --[[int]])
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--- Will return an array of all the entities inside the current bucket (Not player entities , use GetPlayersInBucket for that)
|
||||
function QBCore.Functions.GetEntitiesInBucket(bucket --[[int]])
|
||||
-- Will return an array of all the entities inside the current bucket (not for player entities, use GetPlayersInBucket for that)
|
||||
function QBCore.Functions.GetEntitiesInBucket(bucket --[[ int ]])
|
||||
local curr_bucket_pool = {}
|
||||
if _G.Entity_Buckets ~= nil then
|
||||
for k, v in pairs(_G.Entity_Buckets) do
|
||||
if k['entity_bucket'] == bucket then
|
||||
curr_bucket_pool[#curr_bucket_pool + 1] = k['entity_id']
|
||||
if QBCore.Entity_Buckets and next(QBCore.Entity_Buckets) then
|
||||
for k, v in pairs(QBCore.Entity_Buckets) do
|
||||
if v.bucket == bucket then
|
||||
curr_bucket_pool[#curr_bucket_pool + 1] = v.id
|
||||
end
|
||||
end
|
||||
return curr_bucket_pool
|
||||
@@ -173,40 +163,37 @@ function QBCore.Functions.GetEntitiesInBucket(bucket --[[int]])
|
||||
end
|
||||
end
|
||||
|
||||
--- Will return true / false wheter the mentioned player id is present in the bucket provided
|
||||
function QBCore.Functions.IsPlayerInBucket(player_source --[[int]] ,bucket --[[int]])
|
||||
local curr_player_bucket = GetPlayerRoutingBucket(player_source)
|
||||
return curr_player_bucket == bucket
|
||||
end
|
||||
|
||||
-- Paychecks (standalone - don't touch)
|
||||
|
||||
function PaycheckLoop()
|
||||
local Players = QBCore.Functions.GetQBPlayers()
|
||||
for _, Player in pairs(Players) do
|
||||
local payment = Player.PlayerData.job.payment
|
||||
if Player.PlayerData.job and payment > 0 and (QBShared.Jobs[Player.PlayerData.job.name].offDutyPay or Player.PlayerData.job.onduty) then
|
||||
if QBCore.Config.Money.PayCheckSociety then
|
||||
local account = exports['qb-bossmenu']:GetAccount(Player.PlayerData.job.name)
|
||||
if account ~= 0 then -- Checks if player is employed by a society
|
||||
if account < payment then -- Checks if company has enough money to pay society
|
||||
TriggerClientEvent('QBCore:Notify', Player.PlayerData.source, Lang:t('error.company_too_poor'), 'error')
|
||||
function PaycheckInterval()
|
||||
if next(QBCore.Players) then
|
||||
for _, Player in pairs(QBCore.Players) do
|
||||
if Player then
|
||||
local payment = Player.PlayerData.job.payment
|
||||
if Player.PlayerData.job and payment > 0 and (QBShared.Jobs[Player.PlayerData.job.name].offDutyPay or Player.PlayerData.job.onduty) then
|
||||
if QBCore.Config.Money.PayCheckSociety then
|
||||
local account = exports['qb-management']:GetAccount(Player.PlayerData.job.name)
|
||||
if account ~= 0 then -- Checks if player is employed by a society
|
||||
if account < payment then -- Checks if company has enough money to pay society
|
||||
TriggerClientEvent('QBCore:Notify', Player.PlayerData.source, Lang:t('error.company_too_poor'), 'error')
|
||||
else
|
||||
Player.Functions.AddMoney('bank', payment)
|
||||
exports['qb-management']:RemoveMoney(Player.PlayerData.job.name, payment)
|
||||
TriggerClientEvent('QBCore:Notify', Player.PlayerData.source, Lang:t('info.received_paycheck', {value = payment}))
|
||||
end
|
||||
else
|
||||
Player.Functions.AddMoney('bank', payment)
|
||||
TriggerClientEvent('QBCore:Notify', Player.PlayerData.source, Lang:t('info.received_paycheck', {value = payment}))
|
||||
end
|
||||
else
|
||||
Player.Functions.AddMoney('bank', payment)
|
||||
TriggerEvent('qb-bossmenu:server:removeAccountMoney', Player.PlayerData.job.name, payment)
|
||||
TriggerClientEvent('QBCore:Notify', Player.PlayerData.source, Lang:t('info.received_paycheck', {value = payment}))
|
||||
end
|
||||
else
|
||||
Player.Functions.AddMoney('bank', payment)
|
||||
TriggerClientEvent('QBCore:Notify', Player.PlayerData.source, Lang:t('info.received_paycheck', {value = payment}))
|
||||
end
|
||||
else
|
||||
Player.Functions.AddMoney('bank', payment)
|
||||
TriggerClientEvent('QBCore:Notify', Player.PlayerData.source, Lang:t('info.received_paycheck', {value = payment}))
|
||||
end
|
||||
end
|
||||
end
|
||||
SetTimeout(QBCore.Config.Money.PayCheckTimeOut * (60 * 1000), PaycheckLoop)
|
||||
SetTimeout(QBCore.Config.Money.PayCheckTimeOut * (60 * 1000), PaycheckInterval)
|
||||
end
|
||||
|
||||
-- Callbacks
|
||||
@@ -216,10 +203,8 @@ function QBCore.Functions.CreateCallback(name, cb)
|
||||
end
|
||||
|
||||
function QBCore.Functions.TriggerCallback(name, source, cb, ...)
|
||||
local src = source
|
||||
if QBCore.ServerCallbacks[name] then
|
||||
QBCore.ServerCallbacks[name](src, cb, ...)
|
||||
end
|
||||
if not QBCore.ServerCallbacks[name] then return end
|
||||
QBCore.ServerCallbacks[name](source, cb, ...)
|
||||
end
|
||||
|
||||
-- Items
|
||||
@@ -233,15 +218,13 @@ function QBCore.Functions.CanUseItem(item)
|
||||
end
|
||||
|
||||
function QBCore.Functions.UseItem(source, item)
|
||||
local src = source
|
||||
QBCore.UseableItems[item.name](src, item)
|
||||
QBCore.UseableItems[item.name](source, item)
|
||||
end
|
||||
|
||||
-- Kick Player
|
||||
|
||||
function QBCore.Functions.Kick(source, reason, setKickReason, deferrals)
|
||||
local src = source
|
||||
reason = '\n' .. reason .. '\n🔸 Check our Discord for further information: ' .. QBCore.Config.Server.discord
|
||||
reason = '\n' .. reason .. '\n🔸 Check our Discord for further information: ' .. QBCore.Config.Server.Discord
|
||||
if setKickReason then
|
||||
setKickReason(reason)
|
||||
end
|
||||
@@ -250,20 +233,18 @@ function QBCore.Functions.Kick(source, reason, setKickReason, deferrals)
|
||||
deferrals.update(reason)
|
||||
Wait(2500)
|
||||
end
|
||||
if src then
|
||||
DropPlayer(src, reason)
|
||||
if source then
|
||||
DropPlayer(source, reason)
|
||||
end
|
||||
local i = 0
|
||||
while (i <= 4) do
|
||||
i = i + 1
|
||||
for i = 0, 4 do
|
||||
while true do
|
||||
if src then
|
||||
if (GetPlayerPing(src) >= 0) then
|
||||
if source then
|
||||
if GetPlayerPing(source) >= 0 then
|
||||
break
|
||||
end
|
||||
Wait(100)
|
||||
CreateThread(function()
|
||||
DropPlayer(src, reason)
|
||||
DropPlayer(source, reason)
|
||||
end)
|
||||
end
|
||||
end
|
||||
@@ -272,24 +253,11 @@ function QBCore.Functions.Kick(source, reason, setKickReason, deferrals)
|
||||
end)
|
||||
end
|
||||
|
||||
-- Check if player is whitelisted (not used anywhere)
|
||||
-- Check if player is whitelisted, kept like this for backwards compatibility or future plans
|
||||
|
||||
function QBCore.Functions.IsWhitelisted(source)
|
||||
local src = source
|
||||
local plicense = QBCore.Functions.GetIdentifier(src, 'license')
|
||||
local identifiers = GetPlayerIdentifiers(src)
|
||||
if QBCore.Config.Server.whitelist then
|
||||
local result = MySQL.Sync.fetchSingle('SELECT * FROM whitelist WHERE license = ?', { plicense })
|
||||
if result then
|
||||
for _, id in pairs(identifiers) do
|
||||
if result.license == id then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
return true
|
||||
end
|
||||
if not QBCore.Config.Server.Whitelist then return true end
|
||||
if QBCore.Functions.HasPermission(source, QBCore.Config.Server.WhitelistPermission) then return true end
|
||||
return false
|
||||
end
|
||||
|
||||
@@ -297,34 +265,26 @@ end
|
||||
|
||||
function QBCore.Functions.AddPermission(source, permission)
|
||||
local src = source
|
||||
local Player = QBCore.Functions.GetPlayer(src)
|
||||
local plicense = Player.PlayerData.license
|
||||
if Player then
|
||||
QBCore.Config.Server.PermissionList[plicense] = {
|
||||
license = plicense,
|
||||
permission = permission:lower(),
|
||||
}
|
||||
MySQL.Async.execute('DELETE FROM permissions WHERE license = ?', { plicense })
|
||||
|
||||
MySQL.Async.insert('INSERT INTO permissions (name, license, permission) VALUES (?, ?, ?)', {
|
||||
GetPlayerName(src),
|
||||
plicense,
|
||||
permission:lower()
|
||||
})
|
||||
|
||||
Player.Functions.UpdatePlayerData()
|
||||
TriggerClientEvent('QBCore:Client:OnPermissionUpdate', src, permission)
|
||||
end
|
||||
local license = QBCore.Functions.GetIdentifier(src, 'license')
|
||||
ExecuteCommand(('add_principal identifier.%s qbcore.%s'):format(license, permission))
|
||||
QBCore.Commands.Refresh(src)
|
||||
end
|
||||
|
||||
function QBCore.Functions.RemovePermission(source)
|
||||
function QBCore.Functions.RemovePermission(source, permission)
|
||||
local src = source
|
||||
local Player = QBCore.Functions.GetPlayer(src)
|
||||
local license = Player.PlayerData.license
|
||||
if Player then
|
||||
QBCore.Config.Server.PermissionList[license] = nil
|
||||
MySQL.Async.execute('DELETE FROM permissions WHERE license = ?', { license })
|
||||
Player.Functions.UpdatePlayerData()
|
||||
local license = QBCore.Functions.GetIdentifier(src, 'license')
|
||||
if permission then
|
||||
if IsPlayerAceAllowed(src, permission) then
|
||||
ExecuteCommand(('remove_principal identifier.%s qbcore.%s'):format(license, permission))
|
||||
QBCore.Commands.Refresh(src)
|
||||
end
|
||||
else
|
||||
for k,v in pairs(QBCore.Config.Server.Permissions) do
|
||||
if IsPlayerAceAllowed(src, v) then
|
||||
ExecuteCommand(('remove_principal identifier.%s qbcore.%s'):format(license, v))
|
||||
QBCore.Commands.Refresh(src)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -332,71 +292,51 @@ end
|
||||
|
||||
function QBCore.Functions.HasPermission(source, permission)
|
||||
local src = source
|
||||
local license = QBCore.Functions.GetIdentifier(src, 'license')
|
||||
local permission = tostring(permission:lower())
|
||||
if permission == 'user' then
|
||||
return true
|
||||
else
|
||||
if QBCore.Config.Server.PermissionList[license] then
|
||||
if QBCore.Config.Server.PermissionList[license].license == license then
|
||||
if QBCore.Config.Server.PermissionList[license].permission == permission or QBCore.Config.Server.PermissionList[license].permission == 'god' then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if IsPlayerAceAllowed(src, permission) then return true end
|
||||
return false
|
||||
end
|
||||
|
||||
function QBCore.Functions.GetPermission(source)
|
||||
local src = source
|
||||
local license = QBCore.Functions.GetIdentifier(src, 'license')
|
||||
if license then
|
||||
if QBCore.Config.Server.PermissionList[license] then
|
||||
if QBCore.Config.Server.PermissionList[license].license == license then
|
||||
return QBCore.Config.Server.PermissionList[license].permission
|
||||
end
|
||||
local perms = {}
|
||||
for k,v in pairs (QBCore.Config.Server.Permissions) do
|
||||
if IsPlayerAceAllowed(src, v) then
|
||||
perms[v] = true
|
||||
end
|
||||
end
|
||||
return 'user'
|
||||
return perms
|
||||
end
|
||||
|
||||
-- Opt in or out of admin reports
|
||||
|
||||
function QBCore.Functions.IsOptin(source)
|
||||
local src = source
|
||||
local license = QBCore.Functions.GetIdentifier(src, 'license')
|
||||
if QBCore.Functions.HasPermission(src, 'admin') then
|
||||
return QBCore.Config.Server.PermissionList[license].optin
|
||||
end
|
||||
local license = QBCore.Functions.GetIdentifier(source, 'license')
|
||||
if not license or not QBCore.Functions.HasPermission(source, 'admin') then return false end
|
||||
local Player = QBCore.Functions.GetPlayer(source)
|
||||
return Player.PlayerData.optin
|
||||
end
|
||||
|
||||
function QBCore.Functions.ToggleOptin(source)
|
||||
local src = source
|
||||
local license = QBCore.Functions.GetIdentifier(src, 'license')
|
||||
if QBCore.Functions.HasPermission(src, 'admin') then
|
||||
QBCore.Config.Server.PermissionList[license].optin = not QBCore.Config.Server.PermissionList[license].optin
|
||||
end
|
||||
local license = QBCore.Functions.GetIdentifier(source, 'license')
|
||||
if not license or not QBCore.Functions.HasPermission(source, 'admin') then return end
|
||||
local Player = QBCore.Functions.GetPlayer(source)
|
||||
Player.PlayerData.optin = not Player.PlayerData.optin
|
||||
Player.Functions.SetMetaData('optin', Player.PlayerData.optin)
|
||||
end
|
||||
|
||||
-- Check if player is banned
|
||||
|
||||
function QBCore.Functions.IsPlayerBanned(source)
|
||||
local src = source
|
||||
local retval = false
|
||||
local message = ''
|
||||
local plicense = QBCore.Functions.GetIdentifier(src, 'license')
|
||||
local plicense = QBCore.Functions.GetIdentifier(source, 'license')
|
||||
local result = MySQL.Sync.fetchSingle('SELECT * FROM bans WHERE license = ?', { plicense })
|
||||
if result then
|
||||
if os.time() < result.expire then
|
||||
retval = true
|
||||
local timeTable = os.date('*t', tonumber(result.expire))
|
||||
message = 'You have been banned from the server:\n' .. result[1].reason .. '\nYour ban expires ' .. timeTable.day .. '/' .. timeTable.month .. '/' .. timeTable.year .. ' ' .. timeTable.hour .. ':' .. timeTable.min .. '\n'
|
||||
else
|
||||
MySQL.Async.execute('DELETE FROM bans WHERE id = ?', { result[1].id })
|
||||
end
|
||||
if not result then return false end
|
||||
if os.time() < result.expire then
|
||||
local timeTable = os.date('*t', tonumber(result.expire))
|
||||
return true, 'You have been banned from the server:\n' .. result.reason .. '\nYour ban expires ' .. timeTable.day .. '/' .. timeTable.month .. '/' .. timeTable.year .. ' ' .. timeTable.hour .. ':' .. timeTable.min .. '\n'
|
||||
else
|
||||
MySQL.Async.execute('DELETE FROM bans WHERE id = ?', { result.id })
|
||||
end
|
||||
return retval, message
|
||||
return false
|
||||
end
|
||||
|
||||
-- Check for duplicate license
|
||||
@@ -407,8 +347,7 @@ function QBCore.Functions.IsLicenseInUse(license)
|
||||
local identifiers = GetPlayerIdentifiers(player)
|
||||
for _, id in pairs(identifiers) do
|
||||
if string.find(id, 'license') then
|
||||
local playerLicense = id
|
||||
if playerLicense == license then
|
||||
if id == license then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
+1
-16
@@ -10,19 +10,4 @@ end)
|
||||
|
||||
-- To use this export in a script instead of manifest method
|
||||
-- Just put this line of code below at the very top of the script
|
||||
-- local QBCore = exports['qb-core']:GetCoreObject()
|
||||
|
||||
-- Get permissions on server start
|
||||
|
||||
CreateThread(function()
|
||||
local result = MySQL.Sync.fetchAll('SELECT * FROM permissions', {})
|
||||
if result[1] then
|
||||
for k, v in pairs(result) do
|
||||
QBCore.Config.Server.PermissionList[v.license] = {
|
||||
license = v.license,
|
||||
permission = v.permission,
|
||||
optin = true,
|
||||
}
|
||||
end
|
||||
end
|
||||
end)
|
||||
-- local QBCore = exports['qb-core']:GetCoreObject()
|
||||
+229
-239
@@ -6,10 +6,9 @@ QBCore.Player = {}
|
||||
-- Will cause major issues!
|
||||
|
||||
function QBCore.Player.Login(source, citizenid, newData)
|
||||
local src = source
|
||||
if src then
|
||||
if source and source ~= '' then
|
||||
if citizenid then
|
||||
local license = QBCore.Functions.GetIdentifier(src, 'license')
|
||||
local license = QBCore.Functions.GetIdentifier(source, 'license')
|
||||
local PlayerData = MySQL.Sync.prepare('SELECT * FROM players where citizenid = ?', { citizenid })
|
||||
if PlayerData and license == PlayerData.license then
|
||||
PlayerData.money = json.decode(PlayerData.money)
|
||||
@@ -22,13 +21,13 @@ function QBCore.Player.Login(source, citizenid, newData)
|
||||
else
|
||||
PlayerData.gang = {}
|
||||
end
|
||||
QBCore.Player.CheckPlayerData(src, PlayerData)
|
||||
QBCore.Player.CheckPlayerData(source, PlayerData)
|
||||
else
|
||||
DropPlayer(src, 'You Have Been Kicked For Exploitation')
|
||||
TriggerEvent('qb-log:server:CreateLog', 'anticheat', 'Anti-Cheat', 'white', GetPlayerName(src) .. ' Has Been Dropped For Character Joining Exploit', false)
|
||||
DropPlayer(source, 'You Have Been Kicked For Exploitation')
|
||||
TriggerEvent('qb-log:server:CreateLog', 'anticheat', 'Anti-Cheat', 'white', GetPlayerName(source) .. ' Has Been Dropped For Character Joining Exploit', false)
|
||||
end
|
||||
else
|
||||
QBCore.Player.CheckPlayerData(src, newData)
|
||||
QBCore.Player.CheckPlayerData(source, newData)
|
||||
end
|
||||
return true
|
||||
else
|
||||
@@ -38,14 +37,14 @@ function QBCore.Player.Login(source, citizenid, newData)
|
||||
end
|
||||
|
||||
function QBCore.Player.CheckPlayerData(source, PlayerData)
|
||||
local src = source
|
||||
PlayerData = PlayerData or {}
|
||||
PlayerData.source = src
|
||||
PlayerData.source = source
|
||||
PlayerData.citizenid = PlayerData.citizenid or QBCore.Player.CreateCitizenId()
|
||||
PlayerData.license = PlayerData.license or QBCore.Functions.GetIdentifier(src, 'license')
|
||||
PlayerData.name = GetPlayerName(src)
|
||||
PlayerData.license = PlayerData.license or QBCore.Functions.GetIdentifier(source, 'license')
|
||||
PlayerData.name = GetPlayerName(source)
|
||||
PlayerData.cid = PlayerData.cid or 1
|
||||
PlayerData.money = PlayerData.money or {}
|
||||
PlayerData.optin = PlayerData.optin or true
|
||||
for moneytype, startamount in pairs(QBCore.Config.Money.MoneyTypes) do
|
||||
PlayerData.money[moneytype] = PlayerData.money[moneytype] or startamount
|
||||
end
|
||||
@@ -57,8 +56,8 @@ function QBCore.Player.CheckPlayerData(source, PlayerData)
|
||||
PlayerData.charinfo.gender = PlayerData.charinfo.gender or 0
|
||||
PlayerData.charinfo.backstory = PlayerData.charinfo.backstory or 'placeholder backstory'
|
||||
PlayerData.charinfo.nationality = PlayerData.charinfo.nationality or 'USA'
|
||||
PlayerData.charinfo.phone = PlayerData.charinfo.phone ~= nil and PlayerData.charinfo.phone or '1' .. math.random(111111111, 999999999)
|
||||
PlayerData.charinfo.account = PlayerData.charinfo.account ~= nil and PlayerData.charinfo.account or 'US0' .. math.random(1, 9) .. 'QBCore' .. math.random(1111, 9999) .. math.random(1111, 9999) .. math.random(11, 99)
|
||||
PlayerData.charinfo.phone = PlayerData.charinfo.phone or QBCore.Functions.CreatePhoneNumber()
|
||||
PlayerData.charinfo.account = PlayerData.charinfo.account or QBCore.Functions.CreateAccountNumber()
|
||||
-- Metadata
|
||||
PlayerData.metadata = PlayerData.metadata or {}
|
||||
PlayerData.metadata['hunger'] = PlayerData.metadata['hunger'] or 100
|
||||
@@ -80,21 +79,11 @@ function QBCore.Player.CheckPlayerData(source, PlayerData)
|
||||
PlayerData.metadata['craftingrep'] = PlayerData.metadata['craftingrep'] or 0
|
||||
PlayerData.metadata['attachmentcraftingrep'] = PlayerData.metadata['attachmentcraftingrep'] or 0
|
||||
PlayerData.metadata['currentapartment'] = PlayerData.metadata['currentapartment'] or nil
|
||||
if PlayerData.metadata['jobrep'] ~= nil then
|
||||
PlayerData.metadata['jobrep'] = {
|
||||
['tow'] = PlayerData.metadata['jobrep']['tow'] or 0,
|
||||
['trucker'] = PlayerData.metadata['jobrep']['trucker'] or 0,
|
||||
['taxi'] = PlayerData.metadata['jobrep']['taxi'] or 0,
|
||||
['hotdog'] = PlayerData.metadata['jobrep']['hotdog'] or 0,
|
||||
}
|
||||
else
|
||||
PlayerData.metadata['jobrep'] = {
|
||||
['tow'] = 0,
|
||||
['trucker'] = 0,
|
||||
['taxi'] = 0,
|
||||
['hotdog'] = 0,
|
||||
}
|
||||
end
|
||||
PlayerData.metadata['jobrep'] = PlayerData.metadata['jobrep'] or {}
|
||||
PlayerData.metadata['jobrep']['tow'] = PlayerData.metadata['jobrep']['tow'] or 0
|
||||
PlayerData.metadata['jobrep']['trucker'] = PlayerData.metadata['jobrep']['trucker'] or 0
|
||||
PlayerData.metadata['jobrep']['taxi'] = PlayerData.metadata['jobrep']['taxi'] or 0
|
||||
PlayerData.metadata['jobrep']['hotdog'] = PlayerData.metadata['jobrep']['hotdog'] or 0
|
||||
PlayerData.metadata['callsign'] = PlayerData.metadata['callsign'] or 'NO CALLSIGN'
|
||||
PlayerData.metadata['fingerprint'] = PlayerData.metadata['fingerprint'] or QBCore.Player.CreateFingerId()
|
||||
PlayerData.metadata['walletid'] = PlayerData.metadata['walletid'] or QBCore.Player.CreateWalletId()
|
||||
@@ -119,6 +108,7 @@ function QBCore.Player.CheckPlayerData(source, PlayerData)
|
||||
InstalledApps = {},
|
||||
}
|
||||
-- Job
|
||||
if PlayerData.job and PlayerData.job.name and not QBCore.Shared.Jobs[PlayerData.job.name] then PlayerData.job = nil end
|
||||
PlayerData.job = PlayerData.job or {}
|
||||
PlayerData.job.name = PlayerData.job.name or 'unemployed'
|
||||
PlayerData.job.label = PlayerData.job.label or 'Civilian'
|
||||
@@ -131,6 +121,7 @@ function QBCore.Player.CheckPlayerData(source, PlayerData)
|
||||
PlayerData.job.grade.name = PlayerData.job.grade.name or 'Freelancer'
|
||||
PlayerData.job.grade.level = PlayerData.job.grade.level or 0
|
||||
-- Gang
|
||||
if PlayerData.gang and PlayerData.gang.name and not QBCore.Shared.Gangs[PlayerData.gang.name] then PlayerData.gang = nil end
|
||||
PlayerData.gang = PlayerData.gang or {}
|
||||
PlayerData.gang.name = PlayerData.gang.name or 'none'
|
||||
PlayerData.gang.label = PlayerData.gang.label or 'No Gang Affiliaton'
|
||||
@@ -140,7 +131,6 @@ function QBCore.Player.CheckPlayerData(source, PlayerData)
|
||||
PlayerData.gang.grade.level = PlayerData.gang.grade.level or 0
|
||||
-- Other
|
||||
PlayerData.position = PlayerData.position or QBConfig.DefaultSpawn
|
||||
PlayerData.LoggedIn = true
|
||||
PlayerData = QBCore.Player.LoadInventory(PlayerData)
|
||||
QBCore.Player.CreatePlayer(PlayerData)
|
||||
end
|
||||
@@ -148,11 +138,10 @@ end
|
||||
-- On player logout
|
||||
|
||||
function QBCore.Player.Logout(source)
|
||||
local src = source
|
||||
TriggerClientEvent('QBCore:Client:OnPlayerUnload', src)
|
||||
TriggerClientEvent('QBCore:Player:UpdatePlayerData', src)
|
||||
TriggerClientEvent('QBCore:Client:OnPlayerUnload', source)
|
||||
TriggerClientEvent('QBCore:Player:UpdatePlayerData', source)
|
||||
Wait(200)
|
||||
QBCore.Players[src] = nil
|
||||
QBCore.Players[source] = nil
|
||||
end
|
||||
|
||||
-- Create a new character
|
||||
@@ -164,180 +153,154 @@ function QBCore.Player.CreatePlayer(PlayerData)
|
||||
self.Functions = {}
|
||||
self.PlayerData = PlayerData
|
||||
|
||||
self.Functions.UpdatePlayerData = function(dontUpdateChat)
|
||||
function self.Functions.UpdatePlayerData(dontUpdateChat)
|
||||
TriggerClientEvent('QBCore:Player:SetPlayerData', self.PlayerData.source, self.PlayerData)
|
||||
if dontUpdateChat == nil then
|
||||
if not dontUpdateChat then
|
||||
QBCore.Commands.Refresh(self.PlayerData.source)
|
||||
end
|
||||
end
|
||||
|
||||
self.Functions.SetJob = function(job, grade)
|
||||
local job = job:lower()
|
||||
local grade = tostring(grade) or '0'
|
||||
|
||||
if QBCore.Shared.Jobs[job] then
|
||||
self.PlayerData.job.name = job
|
||||
self.PlayerData.job.label = QBCore.Shared.Jobs[job].label
|
||||
self.PlayerData.job.onduty = QBCore.Shared.Jobs[job].defaultDuty
|
||||
|
||||
if QBCore.Shared.Jobs[job].grades[grade] then
|
||||
local jobgrade = QBCore.Shared.Jobs[job].grades[grade]
|
||||
self.PlayerData.job.grade = {}
|
||||
self.PlayerData.job.grade.name = jobgrade.name
|
||||
self.PlayerData.job.grade.level = tonumber(grade)
|
||||
self.PlayerData.job.payment = jobgrade.payment or 30
|
||||
self.PlayerData.job.isboss = jobgrade.isboss or false
|
||||
else
|
||||
self.PlayerData.job.grade = {}
|
||||
self.PlayerData.job.grade.name = 'No Grades'
|
||||
self.PlayerData.job.grade.level = 0
|
||||
self.PlayerData.job.payment = 30
|
||||
self.PlayerData.job.isboss = false
|
||||
end
|
||||
|
||||
self.Functions.UpdatePlayerData()
|
||||
TriggerEvent('QBCore:Server:OnJobUpdate', self.PlayerData.source, self.PlayerData.job)
|
||||
TriggerClientEvent('QBCore:Client:OnJobUpdate', self.PlayerData.source, self.PlayerData.job)
|
||||
return true
|
||||
function self.Functions.SetJob(job, grade)
|
||||
job = job:lower()
|
||||
grade = tostring(grade) or '0'
|
||||
if not QBCore.Shared.Jobs[job] then return false end
|
||||
self.PlayerData.job.name = job
|
||||
self.PlayerData.job.label = QBCore.Shared.Jobs[job].label
|
||||
self.PlayerData.job.onduty = QBCore.Shared.Jobs[job].defaultDuty
|
||||
if QBCore.Shared.Jobs[job].grades[grade] then
|
||||
local jobgrade = QBCore.Shared.Jobs[job].grades[grade]
|
||||
self.PlayerData.job.grade = {}
|
||||
self.PlayerData.job.grade.name = jobgrade.name
|
||||
self.PlayerData.job.grade.level = tonumber(grade)
|
||||
self.PlayerData.job.payment = jobgrade.payment or 30
|
||||
self.PlayerData.job.isboss = jobgrade.isboss or false
|
||||
else
|
||||
self.PlayerData.job.grade = {}
|
||||
self.PlayerData.job.grade.name = 'No Grades'
|
||||
self.PlayerData.job.grade.level = 0
|
||||
self.PlayerData.job.payment = 30
|
||||
self.PlayerData.job.isboss = false
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
self.Functions.SetGang = function(gang, grade)
|
||||
local gang = gang:lower()
|
||||
local grade = tostring(grade) or '0'
|
||||
|
||||
if QBCore.Shared.Gangs[gang] then
|
||||
self.PlayerData.gang.name = gang
|
||||
self.PlayerData.gang.label = QBCore.Shared.Gangs[gang].label
|
||||
if QBCore.Shared.Gangs[gang].grades[grade] then
|
||||
local ganggrade = QBCore.Shared.Gangs[gang].grades[grade]
|
||||
self.PlayerData.gang.grade = {}
|
||||
self.PlayerData.gang.grade.name = ganggrade.name
|
||||
self.PlayerData.gang.grade.level = tonumber(grade)
|
||||
self.PlayerData.gang.isboss = ganggrade.isboss or false
|
||||
else
|
||||
self.PlayerData.gang.grade = {}
|
||||
self.PlayerData.gang.grade.name = 'No Grades'
|
||||
self.PlayerData.gang.grade.level = 0
|
||||
self.PlayerData.gang.isboss = false
|
||||
end
|
||||
|
||||
self.Functions.UpdatePlayerData()
|
||||
TriggerClientEvent('QBCore:Client:OnGangUpdate', self.PlayerData.source, self.PlayerData.gang)
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
self.Functions.SetJobDuty = function(onDuty)
|
||||
self.PlayerData.job.onduty = onDuty
|
||||
self.Functions.UpdatePlayerData()
|
||||
TriggerEvent('QBCore:Server:OnJobUpdate', self.PlayerData.source, self.PlayerData.job)
|
||||
TriggerClientEvent('QBCore:Client:OnJobUpdate', self.PlayerData.source, self.PlayerData.job)
|
||||
return true
|
||||
end
|
||||
|
||||
self.Functions.SetMetaData = function(meta, val)
|
||||
local meta = meta:lower()
|
||||
if val ~= nil then
|
||||
self.PlayerData.metadata[meta] = val
|
||||
self.Functions.UpdatePlayerData()
|
||||
function self.Functions.SetGang(gang, grade)
|
||||
gang = gang:lower()
|
||||
grade = tostring(grade) or '0'
|
||||
if not QBCore.Shared.Gangs[gang] then return false end
|
||||
self.PlayerData.gang.name = gang
|
||||
self.PlayerData.gang.label = QBCore.Shared.Gangs[gang].label
|
||||
if QBCore.Shared.Gangs[gang].grades[grade] then
|
||||
local ganggrade = QBCore.Shared.Gangs[gang].grades[grade]
|
||||
self.PlayerData.gang.grade = {}
|
||||
self.PlayerData.gang.grade.name = ganggrade.name
|
||||
self.PlayerData.gang.grade.level = tonumber(grade)
|
||||
self.PlayerData.gang.isboss = ganggrade.isboss or false
|
||||
else
|
||||
self.PlayerData.gang.grade = {}
|
||||
self.PlayerData.gang.grade.name = 'No Grades'
|
||||
self.PlayerData.gang.grade.level = 0
|
||||
self.PlayerData.gang.isboss = false
|
||||
end
|
||||
self.Functions.UpdatePlayerData()
|
||||
TriggerClientEvent('QBCore:Client:OnGangUpdate', self.PlayerData.source, self.PlayerData.gang)
|
||||
return true
|
||||
end
|
||||
|
||||
self.Functions.AddJobReputation = function(amount)
|
||||
local amount = tonumber(amount)
|
||||
function self.Functions.SetJobDuty(onDuty)
|
||||
self.PlayerData.job.onduty = onDuty
|
||||
self.Functions.UpdatePlayerData()
|
||||
end
|
||||
|
||||
function self.Functions.SetMetaData(meta, val)
|
||||
if not meta then return end
|
||||
meta = meta:lower()
|
||||
self.PlayerData.metadata[meta] = val
|
||||
self.Functions.UpdatePlayerData()
|
||||
end
|
||||
|
||||
function self.Functions.AddJobReputation(amount)
|
||||
if not amount then return end
|
||||
amount = tonumber(amount)
|
||||
self.PlayerData.metadata['jobrep'][self.PlayerData.job.name] = self.PlayerData.metadata['jobrep'][self.PlayerData.job.name] + amount
|
||||
self.Functions.UpdatePlayerData()
|
||||
end
|
||||
|
||||
self.Functions.AddMoney = function(moneytype, amount, reason)
|
||||
function self.Functions.AddMoney(moneytype, amount, reason)
|
||||
reason = reason or 'unknown'
|
||||
local moneytype = moneytype:lower()
|
||||
local amount = tonumber(amount)
|
||||
if amount < 0 then
|
||||
return
|
||||
moneytype = moneytype:lower()
|
||||
amount = tonumber(amount)
|
||||
if amount < 0 then return end
|
||||
if not self.PlayerData.money[moneytype] then return false end
|
||||
self.PlayerData.money[moneytype] = self.PlayerData.money[moneytype] + amount
|
||||
self.Functions.UpdatePlayerData()
|
||||
if amount > 100000 then
|
||||
TriggerEvent('qb-log:server:CreateLog', 'playermoney', 'AddMoney', 'lightgreen', '**' .. GetPlayerName(self.PlayerData.source) .. ' (citizenid: ' .. self.PlayerData.citizenid .. ' | id: ' .. self.PlayerData.source .. ')** $' .. amount .. ' (' .. moneytype .. ') added, new ' .. moneytype .. ' balance: ' .. self.PlayerData.money[moneytype], true)
|
||||
else
|
||||
TriggerEvent('qb-log:server:CreateLog', 'playermoney', 'AddMoney', 'lightgreen', '**' .. GetPlayerName(self.PlayerData.source) .. ' (citizenid: ' .. self.PlayerData.citizenid .. ' | id: ' .. self.PlayerData.source .. ')** $' .. amount .. ' (' .. moneytype .. ') added, new ' .. moneytype .. ' balance: ' .. self.PlayerData.money[moneytype])
|
||||
end
|
||||
if self.PlayerData.money[moneytype] then
|
||||
self.PlayerData.money[moneytype] = self.PlayerData.money[moneytype] + amount
|
||||
self.Functions.UpdatePlayerData()
|
||||
if amount > 100000 then
|
||||
TriggerEvent('qb-log:server:CreateLog', 'playermoney', 'AddMoney', 'lightgreen', '**' .. GetPlayerName(self.PlayerData.source) .. ' (citizenid: ' .. self.PlayerData.citizenid .. ' | id: ' .. self.PlayerData.source .. ')** $' .. amount .. ' (' .. moneytype .. ') added, new ' .. moneytype .. ' balance: ' .. self.PlayerData.money[moneytype], true)
|
||||
else
|
||||
TriggerEvent('qb-log:server:CreateLog', 'playermoney', 'AddMoney', 'lightgreen', '**' .. GetPlayerName(self.PlayerData.source) .. ' (citizenid: ' .. self.PlayerData.citizenid .. ' | id: ' .. self.PlayerData.source .. ')** $' .. amount .. ' (' .. moneytype .. ') added, new ' .. moneytype .. ' balance: ' .. self.PlayerData.money[moneytype])
|
||||
end
|
||||
TriggerClientEvent('hud:client:OnMoneyChange', self.PlayerData.source, moneytype, amount, false)
|
||||
return true
|
||||
end
|
||||
return false
|
||||
TriggerClientEvent('hud:client:OnMoneyChange', self.PlayerData.source, moneytype, amount, false)
|
||||
return true
|
||||
end
|
||||
|
||||
self.Functions.RemoveMoney = function(moneytype, amount, reason)
|
||||
function self.Functions.RemoveMoney(moneytype, amount, reason)
|
||||
reason = reason or 'unknown'
|
||||
local moneytype = moneytype:lower()
|
||||
local amount = tonumber(amount)
|
||||
if amount < 0 then
|
||||
return
|
||||
end
|
||||
if self.PlayerData.money[moneytype] then
|
||||
for _, mtype in pairs(QBCore.Config.Money.DontAllowMinus) do
|
||||
if mtype == moneytype then
|
||||
if self.PlayerData.money[moneytype] - amount < 0 then
|
||||
return false
|
||||
end
|
||||
moneytype = moneytype:lower()
|
||||
amount = tonumber(amount)
|
||||
if amount < 0 then return end
|
||||
if not self.PlayerData.money[moneytype] then return false end
|
||||
for _, mtype in pairs(QBCore.Config.Money.DontAllowMinus) do
|
||||
if mtype == moneytype then
|
||||
if (self.PlayerData.money[moneytype] - amount) < 0 then
|
||||
return false
|
||||
end
|
||||
end
|
||||
self.PlayerData.money[moneytype] = self.PlayerData.money[moneytype] - amount
|
||||
self.Functions.UpdatePlayerData()
|
||||
if amount > 100000 then
|
||||
TriggerEvent('qb-log:server:CreateLog', 'playermoney', 'RemoveMoney', 'red', '**' .. GetPlayerName(self.PlayerData.source) .. ' (citizenid: ' .. self.PlayerData.citizenid .. ' | id: ' .. self.PlayerData.source .. ')** $' .. amount .. ' (' .. moneytype .. ') removed, new ' .. moneytype .. ' balance: ' .. self.PlayerData.money[moneytype], true)
|
||||
else
|
||||
TriggerEvent('qb-log:server:CreateLog', 'playermoney', 'RemoveMoney', 'red', '**' .. GetPlayerName(self.PlayerData.source) .. ' (citizenid: ' .. self.PlayerData.citizenid .. ' | id: ' .. self.PlayerData.source .. ')** $' .. amount .. ' (' .. moneytype .. ') removed, new ' .. moneytype .. ' balance: ' .. self.PlayerData.money[moneytype])
|
||||
end
|
||||
TriggerClientEvent('hud:client:OnMoneyChange', self.PlayerData.source, moneytype, amount, true)
|
||||
if moneytype == 'bank' then
|
||||
TriggerClientEvent('qb-phone:client:RemoveBankMoney', self.PlayerData.source, amount)
|
||||
end
|
||||
return true
|
||||
end
|
||||
return false
|
||||
self.PlayerData.money[moneytype] = self.PlayerData.money[moneytype] - amount
|
||||
self.Functions.UpdatePlayerData()
|
||||
if amount > 100000 then
|
||||
TriggerEvent('qb-log:server:CreateLog', 'playermoney', 'RemoveMoney', 'red', '**' .. GetPlayerName(self.PlayerData.source) .. ' (citizenid: ' .. self.PlayerData.citizenid .. ' | id: ' .. self.PlayerData.source .. ')** $' .. amount .. ' (' .. moneytype .. ') removed, new ' .. moneytype .. ' balance: ' .. self.PlayerData.money[moneytype], true)
|
||||
else
|
||||
TriggerEvent('qb-log:server:CreateLog', 'playermoney', 'RemoveMoney', 'red', '**' .. GetPlayerName(self.PlayerData.source) .. ' (citizenid: ' .. self.PlayerData.citizenid .. ' | id: ' .. self.PlayerData.source .. ')** $' .. amount .. ' (' .. moneytype .. ') removed, new ' .. moneytype .. ' balance: ' .. self.PlayerData.money[moneytype])
|
||||
end
|
||||
TriggerClientEvent('hud:client:OnMoneyChange', self.PlayerData.source, moneytype, amount, true)
|
||||
if moneytype == 'bank' then
|
||||
TriggerClientEvent('qb-phone:client:RemoveBankMoney', self.PlayerData.source, amount)
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
self.Functions.SetMoney = function(moneytype, amount, reason)
|
||||
function self.Functions.SetMoney(moneytype, amount, reason)
|
||||
reason = reason or 'unknown'
|
||||
local moneytype = moneytype:lower()
|
||||
local amount = tonumber(amount)
|
||||
if amount < 0 then
|
||||
return
|
||||
end
|
||||
if self.PlayerData.money[moneytype] then
|
||||
self.PlayerData.money[moneytype] = amount
|
||||
self.Functions.UpdatePlayerData()
|
||||
TriggerEvent('qb-log:server:CreateLog', 'playermoney', 'SetMoney', 'green', '**' .. GetPlayerName(self.PlayerData.source) .. ' (citizenid: ' .. self.PlayerData.citizenid .. ' | id: ' .. self.PlayerData.source .. ')** $' .. amount .. ' (' .. moneytype .. ') set, new ' .. moneytype .. ' balance: ' .. self.PlayerData.money[moneytype])
|
||||
return true
|
||||
end
|
||||
return false
|
||||
moneytype = moneytype:lower()
|
||||
amount = tonumber(amount)
|
||||
if amount < 0 then return false end
|
||||
if not self.PlayerData.money[moneytype] then return false end
|
||||
self.PlayerData.money[moneytype] = amount
|
||||
self.Functions.UpdatePlayerData()
|
||||
TriggerEvent('qb-log:server:CreateLog', 'playermoney', 'SetMoney', 'green', '**' .. GetPlayerName(self.PlayerData.source) .. ' (citizenid: ' .. self.PlayerData.citizenid .. ' | id: ' .. self.PlayerData.source .. ')** $' .. amount .. ' (' .. moneytype .. ') set, new ' .. moneytype .. ' balance: ' .. self.PlayerData.money[moneytype])
|
||||
return true
|
||||
end
|
||||
|
||||
self.Functions.GetMoney = function(moneytype)
|
||||
if moneytype then
|
||||
local moneytype = moneytype:lower()
|
||||
return self.PlayerData.money[moneytype]
|
||||
end
|
||||
return false
|
||||
function self.Functions.GetMoney(moneytype)
|
||||
if not moneytype then return false end
|
||||
moneytype = moneytype:lower()
|
||||
return self.PlayerData.money[moneytype]
|
||||
end
|
||||
|
||||
self.Functions.AddItem = function(item, amount, slot, info)
|
||||
function self.Functions.AddItem(item, amount, slot, info)
|
||||
local totalWeight = QBCore.Player.GetTotalWeight(self.PlayerData.items)
|
||||
local itemInfo = QBCore.Shared.Items[item:lower()]
|
||||
if itemInfo == nil then
|
||||
if not itemInfo then
|
||||
TriggerClientEvent('QBCore:Notify', self.PlayerData.source, Lang:t('error.item_not_exist'), 'error')
|
||||
return
|
||||
end
|
||||
local amount = tonumber(amount)
|
||||
local slot = tonumber(slot) or QBCore.Player.GetFirstSlotByItem(self.PlayerData.items, item)
|
||||
if itemInfo['type'] == 'weapon' and info == nil then
|
||||
amount = tonumber(amount)
|
||||
slot = tonumber(slot) or QBCore.Player.GetFirstSlotByItem(self.PlayerData.items, item)
|
||||
if itemInfo['type'] == 'weapon' and not info then
|
||||
info = {
|
||||
serie = tostring(QBCore.Shared.RandomInt(2) .. QBCore.Shared.RandomStr(3) .. QBCore.Shared.RandomInt(1) .. QBCore.Shared.RandomStr(2) .. QBCore.Shared.RandomInt(3) .. QBCore.Shared.RandomStr(4)),
|
||||
}
|
||||
@@ -348,12 +311,12 @@ function QBCore.Player.CreatePlayer(PlayerData)
|
||||
self.Functions.UpdatePlayerData()
|
||||
TriggerEvent('qb-log:server:CreateLog', 'playerinventory', 'AddItem', 'green', '**' .. GetPlayerName(self.PlayerData.source) .. ' (citizenid: ' .. self.PlayerData.citizenid .. ' | id: ' .. self.PlayerData.source .. ')** got item: [slot:' .. slot .. '], itemname: ' .. self.PlayerData.items[slot].name .. ', added amount: ' .. amount .. ', new total amount: ' .. self.PlayerData.items[slot].amount)
|
||||
return true
|
||||
elseif (not itemInfo['unique'] and slot or slot and self.PlayerData.items[slot] == nil) then
|
||||
elseif not itemInfo['unique'] and slot or slot and self.PlayerData.items[slot] == nil then
|
||||
self.PlayerData.items[slot] = { name = itemInfo['name'], amount = amount, info = info or '', label = itemInfo['label'], description = itemInfo['description'] or '', weight = itemInfo['weight'], type = itemInfo['type'], unique = itemInfo['unique'], useable = itemInfo['useable'], image = itemInfo['image'], shouldClose = itemInfo['shouldClose'], slot = slot, combinable = itemInfo['combinable'] }
|
||||
self.Functions.UpdatePlayerData()
|
||||
TriggerEvent('qb-log:server:CreateLog', 'playerinventory', 'AddItem', 'green', '**' .. GetPlayerName(self.PlayerData.source) .. ' (citizenid: ' .. self.PlayerData.citizenid .. ' | id: ' .. self.PlayerData.source .. ')** got item: [slot:' .. slot .. '], itemname: ' .. self.PlayerData.items[slot].name .. ', added amount: ' .. amount .. ', new total amount: ' .. self.PlayerData.items[slot].amount)
|
||||
return true
|
||||
elseif (itemInfo['unique']) or (not slot or slot == nil) or (itemInfo['type'] == 'weapon') then
|
||||
elseif itemInfo['unique'] or (not slot or slot == nil) or itemInfo['type'] == 'weapon' then
|
||||
for i = 1, QBConfig.Player.MaxInvSlots, 1 do
|
||||
if self.PlayerData.items[i] == nil then
|
||||
self.PlayerData.items[i] = { name = itemInfo['name'], amount = amount, info = info or '', label = itemInfo['label'], description = itemInfo['description'] or '', weight = itemInfo['weight'], type = itemInfo['type'], unique = itemInfo['unique'], useable = itemInfo['useable'], image = itemInfo['image'], shouldClose = itemInfo['shouldClose'], slot = i, combinable = itemInfo['combinable'] }
|
||||
@@ -369,9 +332,9 @@ function QBCore.Player.CreatePlayer(PlayerData)
|
||||
return false
|
||||
end
|
||||
|
||||
self.Functions.RemoveItem = function(item, amount, slot)
|
||||
local amount = tonumber(amount)
|
||||
local slot = tonumber(slot)
|
||||
function self.Functions.RemoveItem(item, amount, slot)
|
||||
amount = tonumber(amount)
|
||||
slot = tonumber(slot)
|
||||
if slot then
|
||||
if self.PlayerData.items[slot].amount > amount then
|
||||
self.PlayerData.items[slot].amount = self.PlayerData.items[slot].amount - amount
|
||||
@@ -406,29 +369,26 @@ function QBCore.Player.CreatePlayer(PlayerData)
|
||||
return false
|
||||
end
|
||||
|
||||
self.Functions.SetInventory = function(items, dontUpdateChat)
|
||||
function self.Functions.SetInventory(items, dontUpdateChat)
|
||||
self.PlayerData.items = items
|
||||
self.Functions.UpdatePlayerData(dontUpdateChat)
|
||||
TriggerEvent('qb-log:server:CreateLog', 'playerinventory', 'SetInventory', 'blue', '**' .. GetPlayerName(self.PlayerData.source) .. ' (citizenid: ' .. self.PlayerData.citizenid .. ' | id: ' .. self.PlayerData.source .. ')** items set: ' .. json.encode(items))
|
||||
end
|
||||
|
||||
self.Functions.ClearInventory = function()
|
||||
function self.Functions.ClearInventory()
|
||||
self.PlayerData.items = {}
|
||||
self.Functions.UpdatePlayerData()
|
||||
TriggerEvent('qb-log:server:CreateLog', 'playerinventory', 'ClearInventory', 'red', '**' .. GetPlayerName(self.PlayerData.source) .. ' (citizenid: ' .. self.PlayerData.citizenid .. ' | id: ' .. self.PlayerData.source .. ')** inventory cleared')
|
||||
end
|
||||
|
||||
self.Functions.GetItemByName = function(item)
|
||||
local item = tostring(item):lower()
|
||||
function self.Functions.GetItemByName(item)
|
||||
item = tostring(item):lower()
|
||||
local slot = QBCore.Player.GetFirstSlotByItem(self.PlayerData.items, item)
|
||||
if slot then
|
||||
return self.PlayerData.items[slot]
|
||||
end
|
||||
return nil
|
||||
return self.PlayerData.items[slot]
|
||||
end
|
||||
|
||||
self.Functions.GetItemsByName = function(item)
|
||||
local item = tostring(item):lower()
|
||||
function self.Functions.GetItemsByName(item)
|
||||
item = tostring(item):lower()
|
||||
local items = {}
|
||||
local slots = QBCore.Player.GetSlotsByItem(self.PlayerData.items, item)
|
||||
for _, slot in pairs(slots) do
|
||||
@@ -439,12 +399,12 @@ function QBCore.Player.CreatePlayer(PlayerData)
|
||||
return items
|
||||
end
|
||||
|
||||
self.Functions.SetCreditCard = function(cardNumber)
|
||||
function self.Functions.SetCreditCard(cardNumber)
|
||||
self.PlayerData.charinfo.card = cardNumber
|
||||
self.Functions.UpdatePlayerData()
|
||||
end
|
||||
|
||||
self.Functions.GetCardSlot = function(cardNumber, cardType)
|
||||
function self.Functions.GetCardSlot(cardNumber, cardType)
|
||||
local item = tostring(cardType):lower()
|
||||
local slots = QBCore.Player.GetSlotsByItem(self.PlayerData.items, item)
|
||||
for _, slot in pairs(slots) do
|
||||
@@ -457,18 +417,19 @@ function QBCore.Player.CreatePlayer(PlayerData)
|
||||
return nil
|
||||
end
|
||||
|
||||
self.Functions.GetItemBySlot = function(slot)
|
||||
local slot = tonumber(slot)
|
||||
if self.PlayerData.items[slot] then
|
||||
return self.PlayerData.items[slot]
|
||||
end
|
||||
return nil
|
||||
function self.Functions.GetItemBySlot(slot)
|
||||
slot = tonumber(slot)
|
||||
return self.PlayerData.items[slot]
|
||||
end
|
||||
|
||||
self.Functions.Save = function()
|
||||
function self.Functions.Save()
|
||||
QBCore.Player.Save(self.PlayerData.source)
|
||||
end
|
||||
|
||||
function self.Functions.Logout()
|
||||
QBCore.Player.Logout(self.PlayerData.source)
|
||||
end
|
||||
|
||||
QBCore.Players[self.PlayerData.source] = self
|
||||
QBCore.Player.Save(self.PlayerData.source)
|
||||
|
||||
@@ -480,10 +441,9 @@ end
|
||||
-- Save player info to database (make sure citizenid is the primary key in your database)
|
||||
|
||||
function QBCore.Player.Save(source)
|
||||
local src = source
|
||||
local ped = GetPlayerPed(src)
|
||||
local ped = GetPlayerPed(source)
|
||||
local pcoords = GetEntityCoords(ped)
|
||||
local PlayerData = QBCore.Players[src].PlayerData
|
||||
local PlayerData = QBCore.Players[source].PlayerData
|
||||
if PlayerData then
|
||||
MySQL.Async.insert('INSERT INTO players (citizenid, cid, license, name, money, charinfo, job, gang, position, metadata) VALUES (:citizenid, :cid, :license, :name, :money, :charinfo, :job, :gang, :position, :metadata) ON DUPLICATE KEY UPDATE cid = :cid, name = :name, money = :money, charinfo = :charinfo, job = :job, gang = :gang, position = :position, metadata = :metadata', {
|
||||
citizenid = PlayerData.citizenid,
|
||||
@@ -497,7 +457,7 @@ function QBCore.Player.Save(source)
|
||||
position = json.encode(pcoords),
|
||||
metadata = json.encode(PlayerData.metadata)
|
||||
})
|
||||
QBCore.Player.SaveInventory(src)
|
||||
QBCore.Player.SaveInventory(source)
|
||||
QBCore.ShowSuccess(GetCurrentResourceName(), PlayerData.name .. ' PLAYER SAVED!')
|
||||
else
|
||||
QBCore.ShowError(GetCurrentResourceName(), 'ERROR QBCORE.PLAYER.SAVE - PLAYERDATA IS EMPTY!')
|
||||
@@ -523,35 +483,35 @@ local playertables = { -- Add tables as needed
|
||||
}
|
||||
|
||||
function QBCore.Player.DeleteCharacter(source, citizenid)
|
||||
local src = source
|
||||
local license = QBCore.Functions.GetIdentifier(src, 'license')
|
||||
local license = QBCore.Functions.GetIdentifier(source, 'license')
|
||||
local result = MySQL.Sync.fetchScalar('SELECT license FROM players where citizenid = ?', { citizenid })
|
||||
if license == result then
|
||||
local query = "DELETE FROM %s WHERE citizenid = ?"
|
||||
local tableCount = #playertables
|
||||
local queries = table.create(tableCount, 0)
|
||||
|
||||
for i=1, tableCount do
|
||||
for i = 1, tableCount do
|
||||
local v = playertables[i]
|
||||
queries[i] = {query = query:format(v.table), values = { citizenid }}
|
||||
end
|
||||
|
||||
MySQL.Async.transaction(queries, function(result)
|
||||
if result then
|
||||
TriggerEvent('qb-log:server:CreateLog', 'joinleave', 'Character Deleted', 'red', '**' .. GetPlayerName(src) .. '** ' .. license .. ' deleted **' .. citizenid .. '**..')
|
||||
TriggerEvent('qb-log:server:CreateLog', 'joinleave', 'Character Deleted', 'red', '**' .. GetPlayerName(source) .. '** ' .. license .. ' deleted **' .. citizenid .. '**..')
|
||||
end
|
||||
end)
|
||||
else
|
||||
DropPlayer(src, 'You Have Been Kicked For Exploitation')
|
||||
TriggerEvent('qb-log:server:CreateLog', 'anticheat', 'Anti-Cheat', 'white', GetPlayerName(src) .. ' Has Been Dropped For Character Deletion Exploit', false)
|
||||
DropPlayer(source, 'You Have Been Kicked For Exploitation')
|
||||
TriggerEvent('qb-log:server:CreateLog', 'anticheat', 'Anti-Cheat', 'white', GetPlayerName(source) .. ' Has Been Dropped For Character Deletion Exploit', true)
|
||||
end
|
||||
end
|
||||
|
||||
-- Inventory
|
||||
|
||||
QBCore.Player.LoadInventory = function(PlayerData)
|
||||
function QBCore.Player.LoadInventory(PlayerData)
|
||||
PlayerData.items = {}
|
||||
local inventory = MySQL.Sync.prepare('SELECT inventory FROM players WHERE citizenid = ?', { PlayerData.citizenid })
|
||||
local missingItems = {}
|
||||
if inventory then
|
||||
inventory = json.decode(inventory)
|
||||
if next(inventory) then
|
||||
@@ -574,36 +534,41 @@ QBCore.Player.LoadInventory = function(PlayerData)
|
||||
slot = item.slot,
|
||||
combinable = itemInfo['combinable']
|
||||
}
|
||||
else
|
||||
missingItems[#missingItems+1] = item.name:lower()
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if #missingItems > 0 then
|
||||
print(("%s the following items removed as they no longer exist: %s"):format(GetPlayerName(PlayerData.source), json.encode(missingItems)))
|
||||
end
|
||||
return PlayerData
|
||||
end
|
||||
|
||||
QBCore.Player.SaveInventory = function(source)
|
||||
local src = source
|
||||
if QBCore.Players[src] then
|
||||
local PlayerData = QBCore.Players[src].PlayerData
|
||||
local items = PlayerData.items
|
||||
local ItemsJson = {}
|
||||
if items and next(items) then
|
||||
for slot, item in pairs(items) do
|
||||
if items[slot] then
|
||||
ItemsJson[#ItemsJson+1] = {
|
||||
name = item.name,
|
||||
amount = item.amount,
|
||||
info = item.info,
|
||||
type = item.type,
|
||||
slot = slot,
|
||||
}
|
||||
end
|
||||
function QBCore.Player.SaveInventory(source)
|
||||
if not QBCore.Players[source] then return end
|
||||
local PlayerData = QBCore.Players[source].PlayerData
|
||||
local items = PlayerData.items
|
||||
local ItemsJson = {}
|
||||
if items and next(items) then
|
||||
for slot, item in pairs(items) do
|
||||
if items[slot] then
|
||||
ItemsJson[#ItemsJson+1] = {
|
||||
name = item.name,
|
||||
amount = item.amount,
|
||||
info = item.info,
|
||||
type = item.type,
|
||||
slot = slot,
|
||||
}
|
||||
end
|
||||
MySQL.Async.prepare('UPDATE players SET inventory = ? WHERE citizenid = ?', { json.encode(ItemsJson), PlayerData.citizenid })
|
||||
else
|
||||
MySQL.Async.prepare('UPDATE players SET inventory = ? WHERE citizenid = ?', { '[]', PlayerData.citizenid })
|
||||
end
|
||||
MySQL.Async.prepare('UPDATE players SET inventory = ? WHERE citizenid = ?', { json.encode(ItemsJson), PlayerData.citizenid })
|
||||
else
|
||||
MySQL.Async.prepare('UPDATE players SET inventory = ? WHERE citizenid = ?', { '[]', PlayerData.citizenid })
|
||||
end
|
||||
end
|
||||
|
||||
@@ -611,32 +576,29 @@ end
|
||||
|
||||
function QBCore.Player.GetTotalWeight(items)
|
||||
local weight = 0
|
||||
if items then
|
||||
for slot, item in pairs(items) do
|
||||
weight = weight + (item.weight * item.amount)
|
||||
end
|
||||
if not items then return 0 end
|
||||
for _, item in pairs(items) do
|
||||
weight += item.weight * item.amount
|
||||
end
|
||||
return tonumber(weight)
|
||||
end
|
||||
|
||||
function QBCore.Player.GetSlotsByItem(items, itemName)
|
||||
local slotsFound = {}
|
||||
if items then
|
||||
for slot, item in pairs(items) do
|
||||
if item.name:lower() == itemName:lower() then
|
||||
slotsFound[#slotsFound+1] = slot
|
||||
end
|
||||
if not items then return slotsFound end
|
||||
for slot, item in pairs(items) do
|
||||
if item.name:lower() == itemName:lower() then
|
||||
slotsFound[#slotsFound+1] = slot
|
||||
end
|
||||
end
|
||||
return slotsFound
|
||||
end
|
||||
|
||||
function QBCore.Player.GetFirstSlotByItem(items, itemName)
|
||||
if items then
|
||||
for slot, item in pairs(items) do
|
||||
if item.name:lower() == itemName:lower() then
|
||||
return tonumber(slot)
|
||||
end
|
||||
if not items then return nil end
|
||||
for slot, item in pairs(items) do
|
||||
if item.name:lower() == itemName:lower() then
|
||||
return tonumber(slot)
|
||||
end
|
||||
end
|
||||
return nil
|
||||
@@ -655,6 +617,34 @@ function QBCore.Player.CreateCitizenId()
|
||||
return CitizenId
|
||||
end
|
||||
|
||||
function QBCore.Functions.CreateAccountNumber()
|
||||
local UniqueFound = false
|
||||
local AccountNumber = nil
|
||||
while not UniqueFound do
|
||||
AccountNumber = 'US0' .. math.random(1, 9) .. 'QBCore' .. math.random(1111, 9999) .. math.random(1111, 9999) .. math.random(11, 99)
|
||||
local query = '%' .. AccountNumber .. '%'
|
||||
local result = MySQL.Sync.prepare('SELECT COUNT(*) as count FROM players WHERE charinfo LIKE ?', { query })
|
||||
if result == 0 then
|
||||
UniqueFound = true
|
||||
end
|
||||
end
|
||||
return AccountNumber
|
||||
end
|
||||
|
||||
function QBCore.Functions.CreatePhoneNumber()
|
||||
local UniqueFound = false
|
||||
local PhoneNumber = nil
|
||||
while not UniqueFound do
|
||||
PhoneNumber = math.random(100,999) .. math.random(1000000,9999999)
|
||||
local query = '%' .. PhoneNumber .. '%'
|
||||
local result = MySQL.Sync.prepare('SELECT COUNT(*) as count FROM players WHERE charinfo LIKE ?', { query })
|
||||
if result == 0 then
|
||||
UniqueFound = true
|
||||
end
|
||||
end
|
||||
return PhoneNumber
|
||||
end
|
||||
|
||||
function QBCore.Player.CreateFingerId()
|
||||
local UniqueFound = false
|
||||
local FingerId = nil
|
||||
@@ -697,4 +687,4 @@ function QBCore.Player.CreateSerialNumber()
|
||||
return SerialNumber
|
||||
end
|
||||
|
||||
PaycheckLoop() -- This just starts the paycheck system
|
||||
PaycheckInterval() -- This starts the paycheck system
|
||||
|
||||
@@ -356,6 +356,7 @@ QBShared.Items = {
|
||||
-- Theft and Jewelry
|
||||
['rolex'] = {['name'] = 'rolex', ['label'] = 'Golden Watch', ['weight'] = 1500, ['type'] = 'item', ['image'] = 'rolex.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = true, ['combinable'] = nil, ['description'] = 'A golden watch seems like the jackpot to me!'},
|
||||
['diamond_ring'] = {['name'] = 'diamond_ring', ['label'] = 'Diamond Ring', ['weight'] = 1500, ['type'] = 'item', ['image'] = 'diamond_ring.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = true, ['combinable'] = nil, ['description'] = 'A diamond ring seems like the jackpot to me!'},
|
||||
['diamond'] = {['name'] = 'diamond', ['label'] = 'Diamond', ['weight'] = 1000, ['type'] = 'item', ['image'] = 'diamond.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = true, ['combinable'] = nil, ['description'] = 'A diamond seems like the jackpot to me!'},
|
||||
['goldchain'] = {['name'] = 'goldchain', ['label'] = 'Golden Chain', ['weight'] = 1500, ['type'] = 'item', ['image'] = 'goldchain.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = true, ['combinable'] = nil, ['description'] = 'A golden chain seems like the jackpot to me!'},
|
||||
['10kgoldchain'] = {['name'] = '10kgoldchain', ['label'] = '10k Gold Chain', ['weight'] = 2000, ['type'] = 'item', ['image'] = '10kgoldchain.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = true, ['combinable'] = nil, ['description'] = '10 carat golden chain'},
|
||||
['goldbar'] = {['name'] = 'goldbar', ['label'] = 'Gold Bar', ['weight'] = 7000, ['type'] = 'item', ['image'] = 'goldbar.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = true, ['combinable'] = nil, ['description'] = 'Looks pretty expensive to me'},
|
||||
|
||||
+1
-1
@@ -135,4 +135,4 @@ function Locale:delete(phraseTarget, prefix)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
+87
-14
@@ -1,4 +1,4 @@
|
||||
QBShared = {}
|
||||
QBShared = QBShared or {}
|
||||
|
||||
local StringCharset = {}
|
||||
local NumberCharset = {}
|
||||
@@ -7,18 +7,18 @@ for i = 48, 57 do NumberCharset[#NumberCharset+1] = string.char(i) end
|
||||
for i = 65, 90 do StringCharset[#StringCharset+1] = string.char(i) end
|
||||
for i = 97, 122 do StringCharset[#StringCharset+1] = string.char(i) end
|
||||
|
||||
QBShared.RandomStr = function(length)
|
||||
function QBShared.RandomStr(length)
|
||||
if length <= 0 then return '' end
|
||||
return QBShared.RandomStr(length - 1) .. StringCharset[math.random(1, #StringCharset)]
|
||||
end
|
||||
|
||||
QBShared.RandomInt = function(length)
|
||||
function QBShared.RandomInt(length)
|
||||
if length <= 0 then return '' end
|
||||
return QBShared.RandomInt(length - 1) .. NumberCharset[math.random(1, #NumberCharset)]
|
||||
end
|
||||
|
||||
QBShared.SplitStr = function(str, delimiter)
|
||||
local result = { }
|
||||
function QBShared.SplitStr(str, delimiter)
|
||||
local result = {}
|
||||
local from = 1
|
||||
local delim_from, delim_to = string.find(str, delimiter, from)
|
||||
while delim_from do
|
||||
@@ -30,18 +30,18 @@ QBShared.SplitStr = function(str, delimiter)
|
||||
return result
|
||||
end
|
||||
|
||||
QBShared.Trim = function(value)
|
||||
function QBShared.Trim(value)
|
||||
if not value then return nil end
|
||||
return (string.gsub(value, '^%s*(.-)%s*$', '%1'))
|
||||
end
|
||||
|
||||
QBShared.Round = function(value, numDecimalPlaces)
|
||||
function QBShared.Round(value, numDecimalPlaces)
|
||||
if not numDecimalPlaces then return math.floor(value + 0.5) end
|
||||
local power = 10 ^ numDecimalPlaces
|
||||
return math.floor((value * power) + 0.5) / (power)
|
||||
end
|
||||
|
||||
QBShared.ChangeVehicleExtra = function (vehicle, extra, enable)
|
||||
function QBShared.ChangeVehicleExtra(vehicle, extra, enable)
|
||||
if DoesExtraExist(vehicle, extra) then
|
||||
if enable then
|
||||
SetVehicleExtra(vehicle, extra, false)
|
||||
@@ -57,16 +57,16 @@ QBShared.ChangeVehicleExtra = function (vehicle, extra, enable)
|
||||
end
|
||||
end
|
||||
|
||||
QBShared.SetDefaultVehicleExtras = function (vehicle, config)
|
||||
function QBShared.SetDefaultVehicleExtras(vehicle, config)
|
||||
-- Clear Extras
|
||||
for i=1,20 do
|
||||
for i = 1,20 do
|
||||
if DoesExtraExist(vehicle, i) then
|
||||
SetVehicleExtra(vehicle, i, 1)
|
||||
end
|
||||
end
|
||||
|
||||
for id, enabled in pairs(config) do
|
||||
QBShared.ChangeVehicleExtra(vehicle, tonumber(id), true)
|
||||
QBShared.ChangeVehicleExtra(vehicle, tonumber(id), type(enabled) == 'boolean' and enabled or true)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -77,9 +77,82 @@ QBShared.StarterItems = {
|
||||
}
|
||||
|
||||
QBShared.MaleNoGloves = {
|
||||
[0] = true, [1] = true, [2] = true, [3] = true, [4] = true, [5] = true, [6] = true, [7] = true, [8] = true, [9] = true, [10] = true, [11] = true, [12] = true, [13] = true, [14] = true, [15] = true, [18] = true, [26] = true, [52] = true, [53] = true, [54] = true, [55] = true, [56] = true, [57] = true, [58] = true, [59] = true, [60] = true, [61] = true, [62] = true, [112] = true, [113] = true, [114] = true, [118] = true, [125] = true, [132] = true
|
||||
[0] = true,
|
||||
[1] = true,
|
||||
[2] = true,
|
||||
[3] = true,
|
||||
[4] = true,
|
||||
[5] = true,
|
||||
[6] = true,
|
||||
[7] = true,
|
||||
[8] = true,
|
||||
[9] = true,
|
||||
[10] = true,
|
||||
[11] = true,
|
||||
[12] = true,
|
||||
[13] = true,
|
||||
[14] = true,
|
||||
[15] = true,
|
||||
[18] = true,
|
||||
[26] = true,
|
||||
[52] = true,
|
||||
[53] = true,
|
||||
[54] = true,
|
||||
[55] = true,
|
||||
[56] = true,
|
||||
[57] = true,
|
||||
[58] = true,
|
||||
[59] = true,
|
||||
[60] = true,
|
||||
[61] = true,
|
||||
[62] = true,
|
||||
[112] = true,
|
||||
[113] = true,
|
||||
[114] = true,
|
||||
[118] = true,
|
||||
[125] = true,
|
||||
[132] = true
|
||||
}
|
||||
|
||||
QBShared.FemaleNoGloves = {
|
||||
[0] = true, [1] = true, [2] = true, [3] = true, [4] = true, [5] = true, [6] = true, [7] = true, [8] = true, [9] = true, [10] = true, [11] = true, [12] = true, [13] = true, [14] = true, [15] = true, [19] = true, [59] = true, [60] = true, [61] = true, [62] = true, [63] = true, [64] = true, [65] = true, [66] = true, [67] = true, [68] = true, [69] = true, [70] = true, [71] = true, [129] = true, [130] = true, [131] = true, [135] = true, [142] = true, [149] = true, [153] = true, [157] = true, [161] = true, [165] = true
|
||||
}
|
||||
[0] = true,
|
||||
[1] = true,
|
||||
[2] = true,
|
||||
[3] = true,
|
||||
[4] = true,
|
||||
[5] = true,
|
||||
[6] = true,
|
||||
[7] = true,
|
||||
[8] = true,
|
||||
[9] = true,
|
||||
[10] = true,
|
||||
[11] = true,
|
||||
[12] = true,
|
||||
[13] = true,
|
||||
[14] = true,
|
||||
[15] = true,
|
||||
[19] = true,
|
||||
[59] = true,
|
||||
[60] = true,
|
||||
[61] = true,
|
||||
[62] = true,
|
||||
[63] = true,
|
||||
[64] = true,
|
||||
[65] = true,
|
||||
[66] = true,
|
||||
[67] = true,
|
||||
[68] = true,
|
||||
[69] = true,
|
||||
[70] = true,
|
||||
[71] = true,
|
||||
[129] = true,
|
||||
[130] = true,
|
||||
[131] = true,
|
||||
[135] = true,
|
||||
[142] = true,
|
||||
[149] = true,
|
||||
[153] = true,
|
||||
[157] = true,
|
||||
[161] = true,
|
||||
[165] = true
|
||||
}
|
||||
+34
-34
@@ -4018,13 +4018,13 @@ QBShared.Vehicles = {
|
||||
['hash'] = `warrener2`,
|
||||
['shop'] = 'pdm',
|
||||
},
|
||||
-- Boats
|
||||
-- Boats
|
||||
['squalo'] = {
|
||||
['name'] = 'Squalo',
|
||||
['brand'] = 'Shitzu',
|
||||
['model'] = 'squalo',
|
||||
['price'] = 40000,
|
||||
['category'] = 'speed',
|
||||
['category'] = 'boats',
|
||||
['hash'] = `squalo`,
|
||||
['shop'] = 'boats',
|
||||
},
|
||||
@@ -4033,7 +4033,7 @@ QBShared.Vehicles = {
|
||||
['brand'] = 'Dinka',
|
||||
['model'] = 'marquis',
|
||||
['price'] = 40000,
|
||||
['category'] = 'sail',
|
||||
['category'] = 'boats',
|
||||
['hash'] = `marquis`,
|
||||
['shop'] = 'boats',
|
||||
},
|
||||
@@ -4042,7 +4042,7 @@ QBShared.Vehicles = {
|
||||
['brand'] = 'Speedophile',
|
||||
['model'] = 'seashark',
|
||||
['price'] = 40000,
|
||||
['category'] = 'jetski',
|
||||
['category'] = 'boats',
|
||||
['hash'] = `seashark`,
|
||||
['shop'] = 'boats',
|
||||
},
|
||||
@@ -4051,7 +4051,7 @@ QBShared.Vehicles = {
|
||||
['brand'] = 'Speedophile',
|
||||
['model'] = 'seashark2',
|
||||
['price'] = 40000,
|
||||
['category'] = 'jetski',
|
||||
['category'] = 'boats',
|
||||
['hash'] = `seashark2`,
|
||||
['shop'] = 'boats',
|
||||
},
|
||||
@@ -4060,7 +4060,7 @@ QBShared.Vehicles = {
|
||||
['brand'] = 'Speedophile',
|
||||
['model'] = 'seashark3',
|
||||
['price'] = 40000,
|
||||
['category'] = 'jetski',
|
||||
['category'] = 'boats',
|
||||
['hash'] = `seashark3`,
|
||||
['shop'] = 'boats',
|
||||
},
|
||||
@@ -4069,7 +4069,7 @@ QBShared.Vehicles = {
|
||||
['brand'] = 'Jetmax',
|
||||
['model'] = 'jetmax',
|
||||
['price'] = 40000,
|
||||
['category'] = 'speed',
|
||||
['category'] = 'boats',
|
||||
['hash'] = `jetmax`,
|
||||
['shop'] = 'boats',
|
||||
},
|
||||
@@ -4078,7 +4078,7 @@ QBShared.Vehicles = {
|
||||
['brand'] = 'Tropic',
|
||||
['model'] = 'tropic',
|
||||
['price'] = 40000,
|
||||
['category'] = 'speed',
|
||||
['category'] = 'boats',
|
||||
['hash'] = `tropic`,
|
||||
['shop'] = 'boats',
|
||||
},
|
||||
@@ -4087,7 +4087,7 @@ QBShared.Vehicles = {
|
||||
['brand'] = 'Tropic',
|
||||
['model'] = 'tropic2',
|
||||
['price'] = 40000,
|
||||
['category'] = 'speed',
|
||||
['category'] = 'boats',
|
||||
['hash'] = `tropic2`,
|
||||
['shop'] = 'boats',
|
||||
},
|
||||
@@ -4096,7 +4096,7 @@ QBShared.Vehicles = {
|
||||
['brand'] = 'Dinghy',
|
||||
['model'] = 'dinghy',
|
||||
['price'] = 40000,
|
||||
['category'] = 'speed',
|
||||
['category'] = 'boats',
|
||||
['hash'] = `dinghy`,
|
||||
['shop'] = 'boats',
|
||||
},
|
||||
@@ -4105,7 +4105,7 @@ QBShared.Vehicles = {
|
||||
['brand'] = 'Dinghy',
|
||||
['model'] = 'dinghy2',
|
||||
['price'] = 40000,
|
||||
['category'] = 'speed',
|
||||
['category'] = 'boats',
|
||||
['hash'] = `dinghy2`,
|
||||
['shop'] = 'boats',
|
||||
},
|
||||
@@ -4114,7 +4114,7 @@ QBShared.Vehicles = {
|
||||
['brand'] = 'Dinghy',
|
||||
['model'] = 'dinghy3',
|
||||
['price'] = 40000,
|
||||
['category'] = 'speed',
|
||||
['category'] = 'boats',
|
||||
['hash'] = `dinghy3`,
|
||||
['shop'] = 'boats',
|
||||
},
|
||||
@@ -4123,7 +4123,7 @@ QBShared.Vehicles = {
|
||||
['brand'] = 'Dinghy',
|
||||
['model'] = 'dinghy4',
|
||||
['price'] = 40000,
|
||||
['category'] = 'speed',
|
||||
['category'] = 'boats',
|
||||
['hash'] = `dinghy4`,
|
||||
['shop'] = 'boats',
|
||||
},
|
||||
@@ -4132,7 +4132,7 @@ QBShared.Vehicles = {
|
||||
['brand'] = 'Suntrap',
|
||||
['model'] = 'suntrap',
|
||||
['price'] = 40000,
|
||||
['category'] = 'speed',
|
||||
['category'] = 'boats',
|
||||
['hash'] = `suntrap`,
|
||||
['shop'] = 'boats',
|
||||
},
|
||||
@@ -4141,7 +4141,7 @@ QBShared.Vehicles = {
|
||||
['brand'] = 'Pegassi',
|
||||
['model'] = 'speeder',
|
||||
['price'] = 40000,
|
||||
['category'] = 'speed',
|
||||
['category'] = 'boats',
|
||||
['hash'] = `speeder`,
|
||||
['shop'] = 'boats',
|
||||
},
|
||||
@@ -4150,7 +4150,7 @@ QBShared.Vehicles = {
|
||||
['brand'] = 'Pegassi',
|
||||
['model'] = 'speeder2',
|
||||
['price'] = 40000,
|
||||
['category'] = 'speed',
|
||||
['category'] = 'boats',
|
||||
['hash'] = `speeder2`,
|
||||
['shop'] = 'boats',
|
||||
},
|
||||
@@ -4159,7 +4159,7 @@ QBShared.Vehicles = {
|
||||
['brand'] = 'Shitzu',
|
||||
['model'] = 'longfin',
|
||||
['price'] = 40000,
|
||||
['category'] = 'speed',
|
||||
['category'] = 'boats',
|
||||
['hash'] = `longfin`,
|
||||
['shop'] = 'boats',
|
||||
},
|
||||
@@ -4168,7 +4168,7 @@ QBShared.Vehicles = {
|
||||
['brand'] = 'Lampadati',
|
||||
['model'] = 'toro',
|
||||
['price'] = 40000,
|
||||
['category'] = 'speed',
|
||||
['category'] = 'boats',
|
||||
['hash'] = `toro`,
|
||||
['shop'] = 'boats',
|
||||
},
|
||||
@@ -4177,17 +4177,17 @@ QBShared.Vehicles = {
|
||||
['brand'] = 'Lampadati',
|
||||
['model'] = 'toro2',
|
||||
['price'] = 40000,
|
||||
['category'] = 'speed',
|
||||
['category'] = 'boats',
|
||||
['hash'] = `toro2`,
|
||||
['shop'] = 'boats',
|
||||
},
|
||||
-- Helis
|
||||
-- helicopters
|
||||
['buzzard2'] = {
|
||||
['name'] = 'Buzzard',
|
||||
['brand'] = 'Unknown',
|
||||
['model'] = 'buzzard2',
|
||||
['price'] = 52000,
|
||||
['category'] = 'helis',
|
||||
['category'] = 'helicopters',
|
||||
['hash'] = `buzzard2`,
|
||||
['shop'] = 'air',
|
||||
},
|
||||
@@ -4196,7 +4196,7 @@ QBShared.Vehicles = {
|
||||
['brand'] = 'Unknown',
|
||||
['model'] = 'frogger',
|
||||
['price'] = 52000,
|
||||
['category'] = 'helis',
|
||||
['category'] = 'helicopters',
|
||||
['hash'] = `frogger`,
|
||||
['shop'] = 'air',
|
||||
},
|
||||
@@ -4205,7 +4205,7 @@ QBShared.Vehicles = {
|
||||
['brand'] = 'Unknown',
|
||||
['model'] = 'frogger2',
|
||||
['price'] = 52000,
|
||||
['category'] = 'helis',
|
||||
['category'] = 'helicopters',
|
||||
['hash'] = `frogger2`,
|
||||
['shop'] = 'air',
|
||||
},
|
||||
@@ -4214,7 +4214,7 @@ QBShared.Vehicles = {
|
||||
['brand'] = 'Unknown',
|
||||
['model'] = 'maverick',
|
||||
['price'] = 52000,
|
||||
['category'] = 'helis',
|
||||
['category'] = 'helicopters',
|
||||
['hash'] = `maverick`,
|
||||
['shop'] = 'air',
|
||||
},
|
||||
@@ -4223,7 +4223,7 @@ QBShared.Vehicles = {
|
||||
['brand'] = 'Buckingham',
|
||||
['model'] = 'swift',
|
||||
['price'] = 52000,
|
||||
['category'] = 'helis',
|
||||
['category'] = 'helicopters',
|
||||
['hash'] = `swift`,
|
||||
['shop'] = 'air',
|
||||
},
|
||||
@@ -4232,7 +4232,7 @@ QBShared.Vehicles = {
|
||||
['brand'] = 'Buckingham',
|
||||
['model'] = 'swift2',
|
||||
['price'] = 52000,
|
||||
['category'] = 'helis',
|
||||
['category'] = 'helicopters',
|
||||
['hash'] = `swift2`,
|
||||
['shop'] = 'air',
|
||||
},
|
||||
@@ -4241,7 +4241,7 @@ QBShared.Vehicles = {
|
||||
['brand'] = 'Unknown',
|
||||
['model'] = 'seasparrow',
|
||||
['price'] = 52000,
|
||||
['category'] = 'helis',
|
||||
['category'] = 'helicopters',
|
||||
['hash'] = `seasparrow`,
|
||||
['shop'] = 'air',
|
||||
},
|
||||
@@ -4250,7 +4250,7 @@ QBShared.Vehicles = {
|
||||
['brand'] = 'Unknown',
|
||||
['model'] = 'seasparrow2',
|
||||
['price'] = 52000,
|
||||
['category'] = 'helis',
|
||||
['category'] = 'helicopters',
|
||||
['hash'] = `seasparrow2`,
|
||||
['shop'] = 'air',
|
||||
},
|
||||
@@ -4259,7 +4259,7 @@ QBShared.Vehicles = {
|
||||
['brand'] = 'Unknown',
|
||||
['model'] = 'seasparrow3',
|
||||
['price'] = 52000,
|
||||
['category'] = 'helis',
|
||||
['category'] = 'helicopters',
|
||||
['hash'] = `seasparrow3`,
|
||||
['shop'] = 'air',
|
||||
},
|
||||
@@ -4268,7 +4268,7 @@ QBShared.Vehicles = {
|
||||
['brand'] = 'Buckingham',
|
||||
['model'] = 'supervolito',
|
||||
['price'] = 52000,
|
||||
['category'] = 'helis',
|
||||
['category'] = 'helicopters',
|
||||
['hash'] = `supervolito`,
|
||||
['shop'] = 'air',
|
||||
},
|
||||
@@ -4277,7 +4277,7 @@ QBShared.Vehicles = {
|
||||
['brand'] = 'Buckingham',
|
||||
['model'] = 'supervolito2',
|
||||
['price'] = 52000,
|
||||
['category'] = 'helis',
|
||||
['category'] = 'helicopters',
|
||||
['hash'] = `supervolito2`,
|
||||
['shop'] = 'air',
|
||||
},
|
||||
@@ -4286,7 +4286,7 @@ QBShared.Vehicles = {
|
||||
['brand'] = 'Buckingham',
|
||||
['model'] = 'volatus',
|
||||
['price'] = 52000,
|
||||
['category'] = 'helis',
|
||||
['category'] = 'helicopters',
|
||||
['hash'] = `volatus`,
|
||||
['shop'] = 'air',
|
||||
},
|
||||
@@ -4295,7 +4295,7 @@ QBShared.Vehicles = {
|
||||
['brand'] = 'Nagasaki',
|
||||
['model'] = 'havok',
|
||||
['price'] = 52000,
|
||||
['category'] = 'helis',
|
||||
['category'] = 'helicopters',
|
||||
['hash'] = `havok`,
|
||||
['shop'] = 'air',
|
||||
},
|
||||
@@ -4417,4 +4417,4 @@ QBShared.Vehicles = {
|
||||
['hash'] = `nimbus`,
|
||||
['shop'] = 'air',
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user