feat: Update 1.1.0 (Dev branch merge into Main)

This commit is contained in:
Idris Dev
2022-03-23 14:15:59 +11:00
committed by GitHub
25 changed files with 1392 additions and 811 deletions
+2 -2
View File
@@ -2,11 +2,11 @@
addReviewers: true
# Set to true to add assignees to pull requests
addAssignees: false
addAssignees: author
# A list of reviewers to be added to pull requests (GitHub user name)
reviewers:
- IdrisDose
- /maintenance
# A list of keywords to be skipped the process that add reviewers if pull requests include it
skipKeywords:
+60
View File
@@ -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)
+28 -17
View File
@@ -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()
@@ -33,17 +32,16 @@ end)
RegisterNetEvent('QBCore:Command:GoToMarker', function()
local ped = PlayerPedId()
local blip = GetFirstBlipInfoId(8)
if DoesBlipExist(blip) then
local blipCoords = GetBlipCoords(blip)
for height = 1, 1000 do
if not DoesBlipExist(blip) then return end
local blipCoords = GetBlipCoords(blip)
for height = 1, 1000 do
SetPedCoordsKeepVehicle(ped, blipCoords.x, blipCoords.y, height + 0.0)
local foundGround, zPos = GetGroundZFor_3dCoord(blipCoords.x, blipCoords.y, height + 0.0)
if foundGround then
SetPedCoordsKeepVehicle(ped, blipCoords.x, blipCoords.y, height + 0.0)
local foundGround, zPos = GetGroundZFor_3dCoord(blipCoords.x, blipCoords.y, height + 0.0)
if foundGround then
SetPedCoordsKeepVehicle(ped, blipCoords.x, blipCoords.y, height + 0.0)
break
end
Wait(0)
break
end
Wait(0)
end
end)
@@ -52,16 +50,16 @@ end)
RegisterNetEvent('QBCore:Command:SpawnVehicle', function(vehName)
local ped = PlayerPedId()
local hash = GetHashKey(vehName)
if not IsModelInCdimage(hash) then
return
end
if not IsModelInCdimage(hash) then return end
RequestModel(hash)
while not HasModelLoaded(hash) do
Wait(10)
Wait(0)
end
local vehicle = CreateVehicle(hash, GetEntityCoords(ped), GetEntityHeading(ped), true, false)
TaskWarpPedIntoVehicle(ped, vehicle, -1)
SetVehicleFuelLevel(vehicle, 100.0)
SetModelAsNoLongerNeeded(vehicle)
TriggerEvent("vehiclekeys:client:SetOwner", QBCore.Functions.GetPlate(vehicle))
end)
@@ -140,3 +138,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)
+230 -120
View File
@@ -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,52 @@ 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.LoadModel(model)
if HasModelLoaded(model) then return end
RequestModel(model)
while not HasModelLoaded(model) do
Wait(0)
end
end
@@ -96,25 +105,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 +140,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 +169,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 +220,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 +260,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 +325,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 +400,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 +420,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 +441,39 @@ function QBCore.Functions.GetVehicleProperties(vehicle)
end
end
local modLivery = GetVehicleMod(vehicle, 48)
if GetVehicleMod(vehicle, 48) == -1 and GetVehicleLivery(vehicle) ~= -1 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 +485,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 +524,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 +556,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 +568,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 +593,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 +634,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 +742,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 +841,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 +892,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 +932,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
View File
@@ -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)
+18 -19
View File
@@ -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,24 @@ 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.PermissionList = {} -- Permission list for old permission system
QBConfig.Server.UseOldPermissionSystem = false -- Use old permissions system from the database
QBConfig.Server.AllPermissions = { -- Table of permissions which have access to everything for the new permissions system
'god',
}
QBConfig.Notify = {}
+11 -18
View File
@@ -2,25 +2,20 @@ 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
'shared/*.lua',
'config.lua',
'shared/main.lua',
'shared/items.lua',
'shared/jobs.lua',
'shared/vehicles.lua',
'shared/gangs.lua',
'shared/weapons.lua'
'locale/en.lua' -- replace with desired language
}
client_scripts {
'client/main.lua',
'client/functions.lua',
'client/loops.lua',
'client/events.lua'
'client/events.lua',
'client/drawtext.lua'
}
server_scripts {
@@ -30,6 +25,7 @@ server_scripts {
'server/player.lua',
'server/events.lua',
'server/commands.lua',
'server/exports.lua',
'server/debug.lua'
}
@@ -37,14 +33,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'
+76
View File
@@ -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;
}
+5 -1
View File
@@ -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
View File
@@ -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>
View File
+124
View File
@@ -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);
}
};
View File
+1 -3
View File
@@ -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
})
})
+78 -65
View File
@@ -20,200 +20,214 @@ function QBCore.Commands.Add(name, help, arguments, argsrequired, callback, perm
end
function QBCore.Commands.Refresh(source)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
local Player = QBCore.Functions.GetPlayer(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
suggestions[#suggestions + 1] = {
name = '/' .. command,
help = info.help,
params = info.arguments
}
end
if not Player then return end
for command, info in pairs(QBCore.Commands.List) do
local hasPerm = QBCore.Functions.HasPermission(source, QBCore.Commands.List[command].permission)
if hasPerm then
suggestions[#suggestions + 1] = {
name = '/' .. command,
help = info.help,
params = info.arguments
}
end
TriggerClientEvent('chat:addSuggestions', tonumber(source), suggestions)
end
TriggerClientEvent('chat:addSuggestions', source, suggestions)
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
local Player = QBCore.Functions.GetPlayer(tonumber(args[1]))
if Player then
QBCore.Functions.RemovePermission(Player.PlayerData.source)
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:Notfy', 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:Notfy', source, 'The server is already closed', 'error')
return
end
if QBCore.Functions.HasPermission(source, 'admin') then
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,8 +236,7 @@ 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
@@ -231,7 +244,7 @@ QBCore.Commands.Add('me', 'Show local message', {{name = 'message', help = 'Mess
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
View File
@@ -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
+127 -131
View File
@@ -2,53 +2,51 @@
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
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)
AddEventHandler('chatMessage', function(source, n, message)
AddEventHandler('chatMessage', function(source, _, message)
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
if string.sub(message, 1, 1) ~= '/' then return end
local args = QBCore.Shared.SplitStr(message, ' ')
local command = string.gsub(args[1]:lower(), '/', '')
CancelEvent()
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)
table.remove(args, 1)
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)
-- 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
deferrals.done(QBCore.Config.Server.ClosedReason)
end
deferrals.update(string.format('Hello %s. Validating Your Rockstar License', name))
for _, v in pairs(identifiers) do
@@ -58,13 +56,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 +73,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 +130,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 +162,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 +177,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 +199,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 (QBCore.Commands.List[command].permission == Player.PlayerData.job.name) or 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)
+154
View File
@@ -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)
+125 -150
View File
@@ -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,9 @@ 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
idtype = idtype or QBConfig.IdentifierType
local identifiers = GetPlayerIdentifiers(source)
for _, identifier in pairs(identifiers) do
if string.find(identifier, idtype) then
return identifier
end
@@ -23,7 +25,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 +37,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 +54,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 +80,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 +94,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 +149,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 +164,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-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')
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)
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 +204,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 +219,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 +234,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,131 +254,125 @@ 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, QBConfig.Server.WhitelistPermission) then return true end
return false
end
-- Setting & Removing Permissions
function QBCore.Functions.AddPermission(source, permission)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
local Player = QBCore.Functions.GetPlayer(source)
local plicense = Player.PlayerData.license
if Player then
if not Player then return end
if QBCore.Config.Server.UseOldPermissionSystem 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),
GetPlayerName(source),
plicense,
permission:lower()
})
Player.Functions.UpdatePlayerData()
TriggerClientEvent('QBCore:Client:OnPermissionUpdate', src, permission)
TriggerClientEvent('QBCore:Client:OnPermissionUpdate', source, permission)
else
Player.Functions.SetPermission(permission)
end
end
function QBCore.Functions.RemovePermission(source)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
local Player = QBCore.Functions.GetPlayer(source)
local license = Player.PlayerData.license
if Player then
if not Player then return end
if QBCore.Config.Server.UseOldPermissionSystem then
QBCore.Config.Server.PermissionList[license] = nil
MySQL.Async.execute('DELETE FROM permissions WHERE license = ?', { license })
Player.Functions.UpdatePlayerData()
TriggerClientEvent('QBCore:Client:OnPermissionUpdate', source, 'user')
else
Player.Functions.SetPermission('user')
end
end
-- Checking for Permission Level
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
permission = tostring(permission:lower())
local license = QBCore.Functions.GetIdentifier(source, 'license')
if QBCore.Config.Server.UseOldPermissionSystem then
if permission == 'user' then return true end
if not QBCore.Config.Server.PermissionList[license] or QBCore.Config.Server.PermissionList[license].license ~= license then return false end
if QBCore.Config.Server.PermissionList[license].permission ~= permission and QBCore.Config.Server.PermissionList[license].permission ~= 'god' then return false end
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
local Player = QBCore.Functions.GetPlayer(source)
if next(QBCore.Config.Server.AllPermissions) then
for i = 1, #QBCore.Config.Server.AllPermissions do
if QBCore.Config.Server.AllPermissions[i] == Player.PlayerData.permission then
return true
end
end
end
return Player.PlayerData.permission == permission
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
end
local license = QBCore.Functions.GetIdentifier(source, 'license')
if QBCore.Config.Server.UseOldPermissionSystem then
if not license or not QBCore.Config.Server.PermissionList[license] or QBCore.Config.Server.PermissionList[license].license ~= license then return 'user' end
return QBCore.Config.Server.PermissionList[license].permission
else
local Player = QBCore.Functions.GetPlayer(source)
return Player.PlayerData.permission
end
return 'user'
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
local license = QBCore.Functions.GetIdentifier(source, 'license')
if not license or not QBCore.Functions.HasPermission(source, 'admin') then return false end
if QBCore.Config.Server.UseOldPermissionSystem then
return QBCore.Config.Server.PermissionList[license].optin
else
local Player = QBCore.Functions.GetPlayer(source)
return Player.PlayerData.optin
end
end
function QBCore.Functions.ToggleOptin(source)
local src = source
local license = QBCore.Functions.GetIdentifier(src, 'license')
if QBCore.Functions.HasPermission(src, 'admin') then
local license = QBCore.Functions.GetIdentifier(source, 'license')
if not license or not QBCore.Functions.HasPermission(source, 'admin') then return end
if QBCore.Config.Server.UseOldPermissionSystem then
QBCore.Config.Server.PermissionList[license].optin = not QBCore.Config.Server.PermissionList[license].optin
else
local Player = QBCore.Functions.GetPlayer(source)
Player.PlayerData.optin = not Player.PlayerData.optin
Player.Functions.SetMetaData('optin', Player.PlayerData.optin)
end
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 +383,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
+9 -4
View File
@@ -15,14 +15,19 @@ end)
-- Get permissions on server start
CreateThread(function()
local result = MySQL.Sync.fetchAll('SELECT * FROM permissions', {})
if result[1] then
if QBCore.Config.Server.UseOldPermissionSystem then
local result = MySQL.Sync.fetchAll('SELECT * FROM permissions', {})
if not result then return end
for k, v in pairs(result) do
QBCore.Config.Server.PermissionList[v.license] = {
license = v.license,
permission = v.permission,
optin = true,
optin = true
}
end
else
for i = 1, #QBCore.Config.Server.AllPermissions do
ExecuteCommand(('add_principal group.%s group.admin'):format(QBCore.Config.Server.AllPermissions[i]))
end
end
end)
end)
+216 -233
View File
@@ -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,13 +37,21 @@ 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
if not QBCore.Config.Server.UseOldPermissionSystem then
if PlayerData.permission then ExecuteCommand(('remove_principal identifier.%s group.%s'):format(PlayerData.license, PlayerData.permission)) end
if not PlayerData.permission and IsPlayerAceAllowed(source, 'command') and IsPlayerAceAllowed(source, 'webadmin') then -- if both aces are allowed then the person has group.admin and is a system admin
PlayerData.permission = QBCore.Config.Server.AllPermissions[1] or 'god'
end
PlayerData.permission = PlayerData.permission or 'user'
ExecuteCommand(('add_principal identifier.%s group.%s'):format(PlayerData.license, PlayerData.permission))
PlayerData.optin = PlayerData.optin or true
end
PlayerData.money = PlayerData.money or {}
for moneytype, startamount in pairs(QBCore.Config.Money.MoneyTypes) do
PlayerData.money[moneytype] = PlayerData.money[moneytype] or startamount
@@ -57,8 +64,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 QBCore.Functions.CreatePhoneNumber()
PlayerData.charinfo.account = PlayerData.charinfo.account ~= nil and PlayerData.charinfo.account or QBCore.Functions.CreateAccountNumber()
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 +87,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 +116,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 +129,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 +139,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 +146,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,178 +161,165 @@ 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
if not QBCore.Config.Server.UseOldPermissionSystem then
function self.Functions.SetPermission(permission)
permission = permission:lower()
ExecuteCommand(('remove_principal identifier.%s group.%s'):format(self.PlayerData.license, self.PlayerData.permission))
ExecuteCommand(('add_principal identifier.%s group.%s'):format(self.PlayerData.license, permission))
self.PlayerData.permission = permission
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
TriggerClientEvent('QBCore:Client:OnPermissionUpdate', self.PlayerData.source, permission)
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
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
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.SetJobDuty = function(onDuty)
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
function self.Functions.SetJobDuty(onDuty)
self.PlayerData.job.onduty = onDuty
self.Functions.UpdatePlayerData()
end
self.Functions.SetMetaData = function(meta, val)
local meta = meta:lower()
if val ~= nil then
self.PlayerData.metadata[meta] = val
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
self.Functions.AddJobReputation = function(amount)
local amount = tonumber(amount)
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)),
}
@@ -346,12 +330,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'] }
@@ -367,9 +351,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
@@ -404,29 +388,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
@@ -437,12 +418,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
@@ -455,18 +436,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)
@@ -478,10 +460,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,
@@ -495,7 +476,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!')
@@ -521,35 +502,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
@@ -572,36 +553,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
@@ -609,32 +595,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
@@ -723,4 +706,4 @@ function QBCore.Player.CreateSerialNumber()
return SerialNumber
end
PaycheckLoop() -- This just starts the paycheck system
PaycheckInterval() -- This starts the paycheck system
+1 -1
View File
@@ -135,4 +135,4 @@ function Locale:delete(phraseTarget, prefix)
end
end
end
end
end
+87 -14
View File
@@ -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
}