mirror of
https://github.com/esx-framework/esx_core.git
synced 2026-08-29 17:28:53 +00:00
818 lines
19 KiB
Lua
818 lines
19 KiB
Lua
function CreateExtendedPlayer(data)
|
|
|
|
local self = {}
|
|
|
|
self.source = data.playerId
|
|
self.maxWeight = Config.MaxWeight
|
|
|
|
for k,v in pairs(data) do
|
|
self[k] = v
|
|
end
|
|
|
|
ExecuteCommand(('add_principal identifier.license:%s group.%s'):format(self.identifier, self.group))
|
|
|
|
self.triggerEvent = function(eventName, ...)
|
|
TriggerClientEvent(eventName, self.source, ...)
|
|
end
|
|
|
|
self.setCoords = function(coords)
|
|
self.updateCoords(coords)
|
|
self.triggerEvent('esx:teleport', coords)
|
|
end
|
|
|
|
self.updateCoords = function(coords)
|
|
self.coords = {x = ESX.Math.Round(coords.x, 1), y = ESX.Math.Round(coords.y, 1), z = ESX.Math.Round(coords.z, 1), heading = ESX.Math.Round(coords.heading or 0.0, 1)}
|
|
end
|
|
|
|
self.getCoords = function(vector)
|
|
if vector then
|
|
return vector3(self.coords.x, self.coords.y, self.coords.z)
|
|
else
|
|
return self.coords
|
|
end
|
|
end
|
|
|
|
self.kick = function(reason)
|
|
DropPlayer(self.source, reason)
|
|
end
|
|
|
|
self.setMoney = function(money)
|
|
money = ESX.Math.Round(money)
|
|
self.setAccountMoney('money', money)
|
|
end
|
|
|
|
self.getMoney = function()
|
|
return self.getAccount('money').money
|
|
end
|
|
|
|
self.addMoney = function(money)
|
|
money = ESX.Math.Round(money)
|
|
self.addAccountMoney('money', money)
|
|
end
|
|
|
|
self.removeMoney = function(money)
|
|
money = ESX.Math.Round(money)
|
|
self.removeAccountMoney('money', money)
|
|
end
|
|
|
|
self.getIdentifier = function()
|
|
return self.identifier
|
|
end
|
|
|
|
self.setGroup = function(newGroup)
|
|
ExecuteCommand(('remove_principal identifier.license:%s group.%s'):format(self.identifier, self.group))
|
|
self.group = newGroup
|
|
ExecuteCommand(('add_principal identifier.license:%s group.%s'):format(self.identifier, self.group))
|
|
end
|
|
|
|
self.getGroup = function()
|
|
return self.group
|
|
end
|
|
|
|
self.set = function(k, v)
|
|
self[k] = v
|
|
end
|
|
|
|
self.get = function(k)
|
|
return self[k]
|
|
end
|
|
|
|
self.getAccounts = function(minimal)
|
|
if minimal then
|
|
local minimalAccounts = {}
|
|
|
|
for k,v in ipairs(self.accounts) do
|
|
minimalAccounts[v.name] = v.money
|
|
end
|
|
|
|
return minimalAccounts
|
|
else
|
|
return self.accounts
|
|
end
|
|
end
|
|
|
|
self.getAccount = function(account)
|
|
for k,v in ipairs(self.accounts) do
|
|
if v.name == account then
|
|
return v
|
|
end
|
|
end
|
|
end
|
|
|
|
self.getInventory = function(minimal)
|
|
if minimal then
|
|
local minimalInventory = {}
|
|
|
|
for k,v in ipairs(self.inventory) do
|
|
if v.count > 0 then
|
|
minimalInventory[v.name] = v.count
|
|
end
|
|
end
|
|
|
|
return minimalInventory
|
|
else
|
|
return self.inventory
|
|
end
|
|
end
|
|
|
|
self.getJob = function()
|
|
return self.job
|
|
end
|
|
|
|
self.getLoadout = function(minimal)
|
|
if minimal then
|
|
local minimalLoadout = {}
|
|
|
|
for k,v in ipairs(self.loadout) do
|
|
minimalLoadout[v.name] = {ammo = v.ammo}
|
|
if v.tintIndex > 0 then minimalLoadout[v.name].tintIndex = v.tintIndex end
|
|
|
|
if #v.components > 0 then
|
|
local components = {}
|
|
|
|
for k2,component in ipairs(v.components) do
|
|
if component ~= 'clip_default' then
|
|
table.insert(components, component)
|
|
end
|
|
end
|
|
|
|
if #components > 0 then
|
|
minimalLoadout[v.name].components = components
|
|
end
|
|
end
|
|
end
|
|
|
|
return minimalLoadout
|
|
else
|
|
return self.loadout
|
|
end
|
|
end
|
|
|
|
self.getName = function()
|
|
return self.name
|
|
end
|
|
|
|
self.setName = function(newName)
|
|
self.name = newName
|
|
end
|
|
|
|
self.setAccountMoney = function(accountName, money)
|
|
if money >= 0 then
|
|
local account = self.getAccount(accountName)
|
|
|
|
if account then
|
|
local prevMoney = account.money
|
|
local newMoney = ESX.Math.Round(money)
|
|
account.money = newMoney
|
|
|
|
self.triggerEvent('esx:setAccountMoney', account)
|
|
end
|
|
end
|
|
end
|
|
|
|
self.addAccountMoney = function(accountName, money)
|
|
if money > 0 then
|
|
local account = self.getAccount(accountName)
|
|
|
|
if account then
|
|
local newMoney = account.money + ESX.Math.Round(money)
|
|
account.money = newMoney
|
|
|
|
self.triggerEvent('esx:setAccountMoney', account)
|
|
end
|
|
end
|
|
end
|
|
|
|
self.removeAccountMoney = function(accountName, money)
|
|
if money > 0 then
|
|
local account = self.getAccount(accountName)
|
|
|
|
if account then
|
|
local newMoney = account.money - ESX.Math.Round(money)
|
|
account.money = newMoney
|
|
|
|
self.triggerEvent('esx:setAccountMoney', account)
|
|
end
|
|
end
|
|
end
|
|
|
|
self.getInventoryItem = function(name)
|
|
for k,v in ipairs(self.inventory) do
|
|
if v.name == name then
|
|
return v
|
|
end
|
|
end
|
|
|
|
return
|
|
end
|
|
|
|
self.addInventoryItem = function(name, count)
|
|
local item = self.getInventoryItem(name)
|
|
|
|
if item then
|
|
count = ESX.Math.Round(count)
|
|
item.count = item.count + count
|
|
self.weight = self.weight + (item.weight * count)
|
|
|
|
TriggerEvent('esx:onAddInventoryItem', self.source, item.name, item.count)
|
|
self.triggerEvent('esx:addInventoryItem', item.name, item.count)
|
|
end
|
|
end
|
|
|
|
self.removeInventoryItem = function(name, count)
|
|
local item = self.getInventoryItem(name)
|
|
|
|
if item then
|
|
count = ESX.Math.Round(count)
|
|
local newCount = item.count - count
|
|
|
|
if newCount >= 0 then
|
|
item.count = newCount
|
|
self.weight = self.weight - (item.weight * count)
|
|
|
|
TriggerEvent('esx:onRemoveInventoryItem', self.source, item.name, item.count)
|
|
self.triggerEvent('esx:removeInventoryItem', item.name, item.count)
|
|
end
|
|
end
|
|
end
|
|
|
|
self.setInventoryItem = function(name, count)
|
|
local item = self.getInventoryItem(name)
|
|
|
|
if item and count >= 0 then
|
|
count = ESX.Math.Round(count)
|
|
|
|
if count > item.count then
|
|
self.addInventoryItem(item.name, count - item.count)
|
|
else
|
|
self.removeInventoryItem(item.name, item.count - count)
|
|
end
|
|
end
|
|
end
|
|
|
|
self.getWeight = function()
|
|
return self.weight
|
|
end
|
|
|
|
self.getMaxWeight = function()
|
|
return self.maxWeight
|
|
end
|
|
|
|
self.canCarryItem = function(name, count)
|
|
local currentWeight, itemWeight = self.weight, ESX.Items[name].weight
|
|
local newWeight = currentWeight + (itemWeight * count)
|
|
|
|
return newWeight <= self.maxWeight
|
|
end
|
|
|
|
self.maxCarryItem = function(name)
|
|
local count = 0
|
|
local currentWeight, itemWeight = self.getWeight(), ESX.Items[name].weight
|
|
local newWeight = self.maxWeight - currentWeight
|
|
|
|
-- math.max(0, ... to prevent bad programmers
|
|
return math.max(0, math.floor(newWeight / itemWeight))
|
|
end
|
|
|
|
self.canSwapItem = function(firstItem, firstItemCount, testItem, testItemCount)
|
|
local firstItemObject = self.getInventoryItem(firstItem)
|
|
local testItemObject = self.getInventoryItem(testItem)
|
|
|
|
if firstItemObject.count >= firstItemCount then
|
|
local weightWithoutFirstItem = ESX.Math.Round(self.weight - (firstItemObject.weight * firstItemCount))
|
|
local weightWithTestItem = ESX.Math.Round(weightWithoutFirstItem + (testItemObject.weight * testItemCount))
|
|
|
|
return weightWithTestItem <= self.maxWeight
|
|
end
|
|
|
|
return false
|
|
end
|
|
|
|
self.setMaxWeight = function(newWeight)
|
|
self.maxWeight = newWeight
|
|
self.triggerEvent('esx:setMaxWeight', self.maxWeight)
|
|
end
|
|
|
|
self.setJob = function(job, grade)
|
|
grade = tostring(grade)
|
|
local lastJob = json.decode(json.encode(self.job))
|
|
|
|
if ESX.DoesJobExist(job, grade) then
|
|
local jobObject, gradeObject = ESX.Jobs[job], ESX.Jobs[job].grades[grade]
|
|
|
|
self.job.id = jobObject.id
|
|
self.job.name = jobObject.name
|
|
self.job.label = jobObject.label
|
|
|
|
self.job.grade = tonumber(grade)
|
|
self.job.grade_name = gradeObject.name
|
|
self.job.grade_label = gradeObject.label
|
|
self.job.grade_salary = gradeObject.salary
|
|
|
|
if gradeObject.skin_male then
|
|
self.job.skin_male = json.decode(gradeObject.skin_male)
|
|
else
|
|
self.job.skin_male = {}
|
|
end
|
|
|
|
if gradeObject.skin_female then
|
|
self.job.skin_female = json.decode(gradeObject.skin_female)
|
|
else
|
|
self.job.skin_female = {}
|
|
end
|
|
|
|
TriggerEvent('esx:setJob', self.source, self.job, lastJob)
|
|
self.triggerEvent('esx:setJob', self.job)
|
|
else
|
|
print(('[es_extended] [^3WARNING^7] Ignoring invalid .setJob() usage for "%s"'):format(self.identifier))
|
|
end
|
|
end
|
|
|
|
self.addWeapon = function(weaponName, ammo)
|
|
if not self.hasWeapon(weaponName) then
|
|
local weaponLabel = ESX.GetWeaponLabel(weaponName)
|
|
|
|
table.insert(self.loadout, {
|
|
name = weaponName,
|
|
ammo = ammo,
|
|
label = weaponLabel,
|
|
components = {},
|
|
tintIndex = 0
|
|
})
|
|
|
|
self.triggerEvent('esx:addWeapon', weaponName, ammo)
|
|
self.triggerEvent('esx:addInventoryItem', weaponLabel, false, true)
|
|
end
|
|
end
|
|
|
|
self.addWeaponComponent = function(weaponName, weaponComponent)
|
|
local loadoutNum, weapon = self.getWeapon(weaponName)
|
|
|
|
if weapon then
|
|
local component = ESX.GetWeaponComponent(weaponName, weaponComponent)
|
|
|
|
if component then
|
|
if not self.hasWeaponComponent(weaponName, weaponComponent) then
|
|
table.insert(self.loadout[loadoutNum].components, weaponComponent)
|
|
self.triggerEvent('esx:addWeaponComponent', weaponName, weaponComponent)
|
|
self.triggerEvent('esx:addInventoryItem', component.label, false, true)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
self.addWeaponAmmo = function(weaponName, ammoCount)
|
|
local loadoutNum, weapon = self.getWeapon(weaponName)
|
|
|
|
if weapon then
|
|
weapon.ammo = weapon.ammo + ammoCount
|
|
self.triggerEvent('esx:setWeaponAmmo', weaponName, weapon.ammo)
|
|
end
|
|
end
|
|
|
|
self.updateWeaponAmmo = function(weaponName, ammoCount)
|
|
local loadoutNum, weapon = self.getWeapon(weaponName)
|
|
|
|
if weapon then
|
|
if ammoCount < weapon.ammo then
|
|
weapon.ammo = ammoCount
|
|
end
|
|
end
|
|
end
|
|
|
|
self.setWeaponTint = function(weaponName, weaponTintIndex)
|
|
local loadoutNum, weapon = self.getWeapon(weaponName)
|
|
|
|
if weapon then
|
|
local weaponNum, weaponObject = ESX.GetWeapon(weaponName)
|
|
|
|
if weaponObject.tints and weaponObject.tints[weaponTintIndex] then
|
|
self.loadout[loadoutNum].tintIndex = weaponTintIndex
|
|
self.triggerEvent('esx:setWeaponTint', weaponName, weaponTintIndex)
|
|
self.triggerEvent('esx:addInventoryItem', weaponObject.tints[weaponTintIndex], false, true)
|
|
end
|
|
end
|
|
end
|
|
|
|
self.getWeaponTint = function(weaponName)
|
|
local loadoutNum, weapon = self.getWeapon(weaponName)
|
|
|
|
if weapon then
|
|
return weapon.tintIndex
|
|
end
|
|
|
|
return 0
|
|
end
|
|
|
|
self.removeWeapon = function(weaponName)
|
|
local weaponLabel
|
|
|
|
for k,v in ipairs(self.loadout) do
|
|
if v.name == weaponName then
|
|
weaponLabel = v.label
|
|
|
|
for k2,v2 in ipairs(v.components) do
|
|
self.removeWeaponComponent(weaponName, v2)
|
|
end
|
|
|
|
table.remove(self.loadout, k)
|
|
break
|
|
end
|
|
end
|
|
|
|
if weaponLabel then
|
|
self.triggerEvent('esx:removeWeapon', weaponName)
|
|
self.triggerEvent('esx:removeInventoryItem', weaponLabel, false, true)
|
|
end
|
|
end
|
|
|
|
self.removeWeaponComponent = function(weaponName, weaponComponent)
|
|
local loadoutNum, weapon = self.getWeapon(weaponName)
|
|
|
|
if weapon then
|
|
local component = ESX.GetWeaponComponent(weaponName, weaponComponent)
|
|
|
|
if component then
|
|
if self.hasWeaponComponent(weaponName, weaponComponent) then
|
|
for k,v in ipairs(self.loadout[loadoutNum].components) do
|
|
if v == weaponComponent then
|
|
table.remove(self.loadout[loadoutNum].components, k)
|
|
break
|
|
end
|
|
end
|
|
|
|
self.triggerEvent('esx:removeWeaponComponent', weaponName, weaponComponent)
|
|
self.triggerEvent('esx:removeInventoryItem', component.label, false, true)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
self.removeWeaponAmmo = function(weaponName, ammoCount)
|
|
local loadoutNum, weapon = self.getWeapon(weaponName)
|
|
|
|
if weapon then
|
|
weapon.ammo = weapon.ammo - ammoCount
|
|
self.triggerEvent('esx:setWeaponAmmo', weaponName, weapon.ammo)
|
|
end
|
|
end
|
|
|
|
self.hasWeaponComponent = function(weaponName, weaponComponent)
|
|
local loadoutNum, weapon = self.getWeapon(weaponName)
|
|
|
|
if weapon then
|
|
for k,v in ipairs(weapon.components) do
|
|
if v == weaponComponent then
|
|
return true
|
|
end
|
|
end
|
|
|
|
return false
|
|
else
|
|
return false
|
|
end
|
|
end
|
|
|
|
self.hasWeapon = function(weaponName)
|
|
for k,v in ipairs(self.loadout) do
|
|
if v.name == weaponName then
|
|
return true
|
|
end
|
|
end
|
|
|
|
return false
|
|
end
|
|
|
|
self.getWeapon = function(weaponName)
|
|
for k,v in ipairs(self.loadout) do
|
|
if v.name == weaponName then
|
|
return k, v
|
|
end
|
|
end
|
|
|
|
return
|
|
end
|
|
|
|
self.showNotification = function(msg, flash, saveToBrief, hudColorIndex)
|
|
self.triggerEvent('esx:showNotification', msg, flash, saveToBrief, hudColorIndex)
|
|
end
|
|
|
|
self.showHelpNotification = function(msg, thisFrame, beep, duration)
|
|
self.triggerEvent('esx:showHelpNotification', msg, thisFrame, beep, duration)
|
|
end
|
|
|
|
self.serialize = function()
|
|
|
|
local data = {
|
|
accounts = self.getAccounts(),
|
|
coords = self.getCoords(),
|
|
identifier = self.getIdentifier(),
|
|
inventory = self.getInventory(),
|
|
job = self.getJob(),
|
|
loadout = self.getLoadout(),
|
|
maxWeight = self.getMaxWeight(),
|
|
money = self.getMoney()
|
|
}
|
|
|
|
TriggerEvent('esx:player:serialize', self, function(extraData)
|
|
|
|
for k,v in pairs(extraData) do
|
|
data[k] = v
|
|
end
|
|
|
|
end)
|
|
|
|
return data
|
|
|
|
end
|
|
|
|
self.serializeDB = function()
|
|
|
|
local job = self.getJob()
|
|
|
|
local data = {
|
|
identifier = self.getIdentifier(),
|
|
accounts = json.encode(self.getAccounts(true)),
|
|
group = self.getGroup(),
|
|
inventory = json.encode(self.getInventory(true)),
|
|
job = job.name,
|
|
job_grade = job.grade,
|
|
loadout = json.encode(self.getLoadout(true)),
|
|
position = json.encode(self.getCoords())
|
|
}
|
|
|
|
TriggerEvent('esx:player:serialize:db', self, function(extraData)
|
|
|
|
for k,v in pairs(extraData) do
|
|
data[k] = v
|
|
end
|
|
|
|
end)
|
|
|
|
return data
|
|
|
|
end
|
|
|
|
TriggerEvent('esx:player:create', self) -- You can hook this event to extend xPlayer
|
|
|
|
return self
|
|
|
|
end
|
|
|
|
function LoadExtendedPlayer(identifier, playerId, cb)
|
|
|
|
MySQL.Async.fetchAll('SELECT * FROM users WHERE identifier = @identifier', { ['@identifier'] = identifier }, function(result)
|
|
|
|
local tasks = {}
|
|
|
|
local userData = {
|
|
playerId = playerId,
|
|
identifier = identifier,
|
|
weight = 0,
|
|
}
|
|
|
|
for entryName, entryValue in pairs(result[1]) do
|
|
|
|
TriggerEvent('esx:player:load:' .. entryName, identifier, playerId, result[1], userData, function(task)
|
|
tasks[#tasks + 1] = task
|
|
end)
|
|
|
|
end
|
|
|
|
Async.parallelLimit(tasks, 5, function(results)
|
|
|
|
for i=1, #results, 1 do
|
|
|
|
local result = results[i]
|
|
|
|
for k,v in pairs(result) do
|
|
userData[k] = v
|
|
end
|
|
|
|
end
|
|
|
|
local xPlayer = CreateExtendedPlayer(userData)
|
|
|
|
ESX.Players[playerId] = xPlayer
|
|
|
|
TriggerEvent('esx:playerLoaded', playerId, xPlayer)
|
|
|
|
xPlayer.triggerEvent('esx:playerLoaded', xPlayer.serialize())
|
|
xPlayer.triggerEvent('esx:createMissingPickups', ESX.Pickups)
|
|
xPlayer.triggerEvent('esx:registerSuggestions', ESX.RegisteredCommands)
|
|
|
|
if cb ~= nil then
|
|
cb()
|
|
end
|
|
|
|
end)
|
|
|
|
end)
|
|
|
|
end
|
|
|
|
AddEventHandler('esx:player:load:accounts', function(identifier, playerId, row, userData, addTask)
|
|
|
|
addTask(function(cb)
|
|
|
|
local data = {}
|
|
local foundAccounts = {}
|
|
|
|
if row.accounts and row.accounts ~= '' then
|
|
|
|
local accounts = json.decode(row.accounts)
|
|
|
|
for account, money in pairs(accounts) do
|
|
foundAccounts[account] = money
|
|
end
|
|
|
|
end
|
|
|
|
for account, label in pairs(Config.Accounts) do
|
|
|
|
table.insert(data, {
|
|
name = account,
|
|
money = foundAccounts[account] or Config.StartingAccountMoney[account] or 0,
|
|
label = label
|
|
})
|
|
|
|
end
|
|
|
|
cb({accounts = data})
|
|
|
|
end)
|
|
|
|
end)
|
|
|
|
AddEventHandler('esx:player:load:job', function(identifier, playerId, row, userData, addTask)
|
|
|
|
addTask(function(cb)
|
|
|
|
local data = {}
|
|
local jobObject, gradeObject = {}, {}
|
|
|
|
if ESX.DoesJobExist(row.job, row.job_grade) then
|
|
jobObject, gradeObject = ESX.Jobs[row.job], ESX.Jobs[row.job].grades[tostring(row.job_grade)]
|
|
else
|
|
|
|
print(('[es_extended] [^3WARNING^7] Ignoring invalid job for %s [job: %s, grade: %s]'):format(identifier, job, grade))
|
|
|
|
job, grade = 'unemployed', '0'
|
|
jobObject, gradeObject = ESX.Jobs[row.job], ESX.Jobs[row.job].grades[tostring(rrow.job_grade)]
|
|
|
|
end
|
|
|
|
data.id = jobObject.id
|
|
data.name = jobObject.name
|
|
data.label = jobObject.label
|
|
|
|
data.grade = row.job_grade
|
|
data.grade_name = gradeObject.name
|
|
data.grade_label = gradeObject.label
|
|
data.grade_salary = gradeObject.salary
|
|
|
|
data.skin_male = {}
|
|
data.skin_female = {}
|
|
|
|
if gradeObject.skin_male then data.skin_male = json.decode(gradeObject.skin_male) end
|
|
if gradeObject.skin_female then data.skin_female = json.decode(gradeObject.skin_female) end
|
|
|
|
cb({job = data})
|
|
|
|
end)
|
|
|
|
end)
|
|
|
|
AddEventHandler('esx:player:load:inventory', function(identifier, playerId, row, userData, addTask)
|
|
|
|
addTask(function(cb)
|
|
|
|
local data = {
|
|
weight = userData.weight,
|
|
inventory = {}
|
|
}
|
|
|
|
local foundItems = {}
|
|
|
|
if row.inventory and row.inventory ~= '' then
|
|
|
|
local inventory = json.decode(row.inventory)
|
|
|
|
for name,count in pairs(inventory) do
|
|
|
|
local item = ESX.Items[name]
|
|
|
|
if item then
|
|
foundItems[name] = count
|
|
else
|
|
print(('[es_extended] [^3WARNING^7] Ignoring invalid item "%s" for "%s"'):format(name, identifier))
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
for name,item in pairs(ESX.Items) do
|
|
|
|
local count = foundItems[name] or 0
|
|
|
|
if count > 0 then
|
|
data.weight = data.weight + (item.weight * count)
|
|
end
|
|
|
|
table.insert(data.inventory, {
|
|
name = name,
|
|
count = count,
|
|
label = item.label,
|
|
weight = item.weight,
|
|
usable = ESX.UsableItemsCallbacks[name] ~= nil,
|
|
rare = item.rare,
|
|
canRemove = item.canRemove
|
|
})
|
|
|
|
end
|
|
|
|
table.sort(data.inventory, function(a, b)
|
|
return a.label < b.label
|
|
end)
|
|
|
|
cb(data)
|
|
|
|
end)
|
|
|
|
end)
|
|
|
|
AddEventHandler('esx:player:load:group', function(identifier, playerId, row, userData, addTask)
|
|
|
|
addTask(function(cb)
|
|
|
|
local data = {}
|
|
|
|
if row.group then
|
|
data = row.group
|
|
else
|
|
data.group = 'user'
|
|
end
|
|
|
|
cb({group = data})
|
|
|
|
end)
|
|
|
|
end)
|
|
|
|
AddEventHandler('esx:player:load:loadout', function(identifier, playerId, row, userData, addTask)
|
|
|
|
addTask(function(cb)
|
|
|
|
local data = {}
|
|
|
|
if row.loadout and row.loadout ~= '' then
|
|
|
|
local loadout = json.decode(row.loadout)
|
|
|
|
for name,weapon in pairs(loadout) do
|
|
|
|
local label = ESX.GetWeaponLabel(name)
|
|
|
|
if label then
|
|
|
|
if not weapon.components then weapon.components = {} end
|
|
if not weapon.tintIndex then weapon.tintIndex = 0 end
|
|
|
|
table.insert(data, {
|
|
name = name,
|
|
ammo = weapon.ammo,
|
|
label = label,
|
|
components = weapon.components,
|
|
tintIndex = weapon.tintIndex
|
|
})
|
|
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
cb({loadout = data})
|
|
|
|
end)
|
|
|
|
end)
|
|
|
|
AddEventHandler('esx:player:load:position', function(identifier, playerId, row, userData, addTask)
|
|
|
|
addTask(function(cb)
|
|
|
|
local data = {}
|
|
|
|
if row.position and row.position ~= '' then
|
|
data = json.decode(row.position)
|
|
else
|
|
print('[es_extended] [^3WARNING^7] Column "position" in "users" table is missing required default value. Using backup coords, fix your database.')
|
|
data = {x = -269.4, y = -955.3, z = 31.2, heading = 205.8}
|
|
end
|
|
|
|
cb({coords = data})
|
|
|
|
end)
|
|
|
|
end)
|