mirror of
https://github.com/esx-framework/esx_core.git
synced 2026-08-29 01:08:54 +00:00
Merge branch 'dev' into fix/multichar
This commit is contained in:
@@ -720,7 +720,9 @@ function ESX.Game.GetVehicleProperties(vehicle)
|
||||
modXenon = IsToggleModOn(vehicle, 22),
|
||||
|
||||
modFrontWheels = GetVehicleMod(vehicle, 23),
|
||||
modCustomFrontWheels = GetVehicleModVariation(vehicle, 23),
|
||||
modBackWheels = GetVehicleMod(vehicle, 24),
|
||||
modCustomBackWheels = GetVehicleModVariation(vehicle, 24),
|
||||
|
||||
modPlateHolder = GetVehicleMod(vehicle, 25),
|
||||
modVanityPlate = GetVehicleMod(vehicle, 26),
|
||||
@@ -906,10 +908,16 @@ function ESX.Game.SetVehicleProperties(vehicle, props)
|
||||
end
|
||||
if props.modFrontWheels ~= nil then
|
||||
SetVehicleMod(vehicle, 23, props.modFrontWheels, false)
|
||||
end
|
||||
if props.modCustomFrontWheels ~= nil then
|
||||
SetVehicleMod(vehicle, 23, props.modCustomFrontWheels, false)
|
||||
end
|
||||
if props.modBackWheels ~= nil then
|
||||
SetVehicleMod(vehicle, 24, props.modBackWheels, false)
|
||||
end
|
||||
if props.modCustomBackWheels ~= nil then
|
||||
SetVehicleMod(vehicle, 24, props.modCustomBackWheels, false)
|
||||
end
|
||||
if props.modPlateHolder ~= nil then
|
||||
SetVehicleMod(vehicle, 25, props.modPlateHolder, false)
|
||||
end
|
||||
|
||||
@@ -2,8 +2,7 @@ Locales = {}
|
||||
|
||||
function Translate(str, ...) -- Translate string
|
||||
if not str then
|
||||
local currentResourceName = GetCurrentResourceName()
|
||||
print(("[^1ERROR^7] Resource ^5%s^7 You did not specify a parameter for the Translate function or the value is nil!"):format(currentResourceName))
|
||||
print(("[^1ERROR^7] Resource ^5%s^7 You did not specify a parameter for the Translate function or the value is nil!"):format(GetInvokingResource() or GetCurrentResourceName()))
|
||||
return 'Given translate function parameter is nil!'
|
||||
end
|
||||
if Locales[Config.Locale] then
|
||||
|
||||
@@ -47,31 +47,18 @@ function CreateExtendedPlayer(playerId, identifier, group, accounts, inventory,
|
||||
SetEntityHeading(Ped, vector.w)
|
||||
end
|
||||
|
||||
function self.updateCoords()
|
||||
SetTimeout(1000,function()
|
||||
local Ped = GetPlayerPed(self.source)
|
||||
if DoesEntityExist(Ped) then
|
||||
local coords = GetEntityCoords(Ped)
|
||||
local distance = #(coords - vector3(self.coords.x, self.coords.y, self.coords.z))
|
||||
if distance > 1.5 then
|
||||
local heading = GetEntityHeading(Ped)
|
||||
self.coords = {
|
||||
x = coords.x,
|
||||
y = coords.y,
|
||||
z = coords.z,
|
||||
heading = heading or 0.0
|
||||
}
|
||||
end
|
||||
end
|
||||
self.updateCoords()
|
||||
end)
|
||||
end
|
||||
|
||||
function self.getCoords(vector)
|
||||
local ped = GetPlayerPed(self.source)
|
||||
local coords = GetEntityCoords(ped)
|
||||
|
||||
if vector then
|
||||
return vector3(self.coords.x, self.coords.y, self.coords.z)
|
||||
return coords
|
||||
else
|
||||
return self.coords
|
||||
return {
|
||||
x = coords.x,
|
||||
y = coords.y,
|
||||
z = coords.z,
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
@@ -572,57 +559,59 @@ function CreateExtendedPlayer(playerId, identifier, group, accounts, inventory,
|
||||
end
|
||||
end
|
||||
|
||||
function self.showNotification(msg)
|
||||
self.triggerEvent('esx:showNotification', msg)
|
||||
function self.showNotification(msg, type, length)
|
||||
self.triggerEvent('esx:showNotification', msg, type, length)
|
||||
end
|
||||
|
||||
function self.showAdvancedNotification(sender, subject, msg, textureDict, iconType, flash, saveToBrief, hudColorIndex)
|
||||
self.triggerEvent('esx:showAdvancedNotification', sender, subject, msg, textureDict, iconType, flash, saveToBrief, hudColorIndex)
|
||||
end
|
||||
|
||||
function self.showHelpNotification(msg, thisFrame, beep, duration)
|
||||
self.triggerEvent('esx:showHelpNotification', msg, thisFrame, beep, duration)
|
||||
end
|
||||
|
||||
function self.getMeta(index, subIndex)
|
||||
if index then
|
||||
function self.getMeta(index, subIndex)
|
||||
if not (index) then return self.metadata end
|
||||
|
||||
if type(index) ~= "string" then
|
||||
return print("[^1ERROR^7] xPlayer.getMeta ^5index^7 should be ^5string^7!")
|
||||
end
|
||||
if type(index) ~= "string" then
|
||||
return print("[^1ERROR^7] xPlayer.getMeta ^5index^7 should be ^5string^7!")
|
||||
end
|
||||
|
||||
if self.metadata[index] then
|
||||
local metadata = self.metadata[index]
|
||||
if (metadata == nil) then
|
||||
return Config.EnableDebug and print(("[^1ERROR^7] xPlayer.getMeta ^5%s^7 not exist!"):format(index)) or nil
|
||||
end
|
||||
|
||||
if subIndex and type(self.metadata[index]) == "table" then
|
||||
local _type = type(subIndex)
|
||||
if (subIndex and type(metadata) == "table") then
|
||||
local _type = type(subIndex)
|
||||
|
||||
if _type == "string" then
|
||||
if self.metadata[index][subIndex] then
|
||||
return self.metadata[index][subIndex]
|
||||
end
|
||||
return
|
||||
end
|
||||
if (_type == "string") then
|
||||
local value = metadata[subIndex]
|
||||
return value
|
||||
end
|
||||
|
||||
if _type == "table" then
|
||||
local returnValues = {}
|
||||
for i = 1, #subIndex do
|
||||
if self.metadata[index][subIndex[i]] then
|
||||
returnValues[subIndex[i]] = self.metadata[index][subIndex[i]]
|
||||
else
|
||||
print(("[^1ERROR^7] xPlayer.getMeta ^5%s^7 not esxist on ^5%s^7!"):format(subIndex[i], index))
|
||||
end
|
||||
end
|
||||
if (_type == "table") then
|
||||
local returnValues = {}
|
||||
|
||||
return returnValues
|
||||
end
|
||||
for i = 1, #subIndex do
|
||||
local key = subIndex[i]
|
||||
if (type(key) == "string") then
|
||||
returnValues[key] = self.getMeta(index, key)
|
||||
else
|
||||
print(("[^1ERROR^7] xPlayer.getMeta subIndex should be ^5string^7 or ^5table^7! that contains ^5string^7, received ^5%s^7!, skipping..."):format(type(key)))
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
return returnValues
|
||||
end
|
||||
|
||||
return self.metadata[index]
|
||||
else
|
||||
return print(("[^1ERROR^7] xPlayer.getMeta ^5%s^7 not exist!"):format(index))
|
||||
end
|
||||
return print(("[^1ERROR^7] xPlayer.getMeta subIndex should be ^5string^7 or ^5table^7!, received ^5%s^7!"):format(_type))
|
||||
end
|
||||
|
||||
end
|
||||
return metadata
|
||||
end
|
||||
|
||||
return self.metadata
|
||||
end
|
||||
|
||||
function self.setMeta(index, value, subValue)
|
||||
if not index then
|
||||
|
||||
@@ -221,18 +221,36 @@ end
|
||||
|
||||
ESX.GetPlayers = GetPlayers
|
||||
|
||||
local function checkTable(key, val, player, xPlayers)
|
||||
for valIndex = 1, #val do
|
||||
local value = val[valIndex]
|
||||
if not xPlayers[value] then
|
||||
xPlayers[value] = {}
|
||||
end
|
||||
|
||||
if (key == 'job' and player.job.name == value) or player[key] == value then
|
||||
xPlayers[value][#xPlayers[value] + 1] = player
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function ESX.GetExtendedPlayers(key, val)
|
||||
local xPlayers = {}
|
||||
for k, v in pairs(ESX.Players) do
|
||||
if key then
|
||||
if (key == 'job' and v.job.name == val) or v[key] == val then
|
||||
xPlayers[#xPlayers + 1] = v
|
||||
end
|
||||
else
|
||||
xPlayers[#xPlayers + 1] = v
|
||||
end
|
||||
end
|
||||
return xPlayers
|
||||
if not key then return ESX.Players end
|
||||
|
||||
local xPlayers = {}
|
||||
if type(val) == "table" then
|
||||
for _, v in pairs(ESX.Players) do
|
||||
checkTable(key, val, v, xPlayers)
|
||||
end
|
||||
else
|
||||
for _, v in pairs(ESX.Players) do
|
||||
if (key == 'job' and v.job.name == val) or v[key] == val then
|
||||
xPlayers[#xPlayers + 1] = v
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return xPlayers
|
||||
end
|
||||
|
||||
function ESX.GetPlayerFromId(source)
|
||||
@@ -321,6 +339,37 @@ function ESX.DiscordLogFields(name, title, color, fields)
|
||||
})
|
||||
end
|
||||
|
||||
--- Create Job at Runtime
|
||||
--- @param name string
|
||||
--- @param label string
|
||||
--- @param grades table
|
||||
function ESX.CreateJob(name, label, grades)
|
||||
if not name then
|
||||
return print('[^3WARNING^7] missing argument `name(string)` while creating a job')
|
||||
end
|
||||
|
||||
if not label then
|
||||
return print('[^3WARNING^7] missing argument `label(string)` while creating a job')
|
||||
end
|
||||
|
||||
if not grades or not next(grades) then
|
||||
return print('[^3WARNING^7] missing argument `grades(table)` while creating a job!')
|
||||
end
|
||||
|
||||
local parameters = {}
|
||||
local job = {name = name, label = label, grades = {}}
|
||||
|
||||
for k,v in pairs(grades) do
|
||||
job.grades[tostring(v.grade)] = {job_name = name, grade = v.grade, name = v.name, label = v.label, salary = v.salary, skin_male = {}, skin_female = {}}
|
||||
parameters[#parameters + 1] = { name, v.grade, v.name, v.label, v.salary}
|
||||
end
|
||||
|
||||
MySQL.insert('INSERT IGNORE INTO jobs (name, label) VALUES (?, ?)', {name, label})
|
||||
MySQL.prepare('INSERT INTO job_grades (job_name, grade, name, label, salary) VALUES (?, ?, ?, ?, ?)', parameters)
|
||||
|
||||
ESX.Jobs[name] = job
|
||||
end
|
||||
|
||||
function ESX.RefreshJobs()
|
||||
local Jobs = {}
|
||||
local jobs = MySQL.query.await('SELECT * FROM jobs')
|
||||
|
||||
+229
-185
@@ -121,221 +121,249 @@ if not Config.Multichar then
|
||||
end
|
||||
|
||||
function loadESXPlayer(identifier, playerId, isNew)
|
||||
local userData = {accounts = {}, inventory = {}, job = {}, loadout = {}, playerName = GetPlayerName(playerId), weight = 0, metadata = {}}
|
||||
local result = MySQL.prepare.await(loadPlayer, {identifier})
|
||||
local job, grade, jobObject, gradeObject = result.job, tostring(result.job_grade)
|
||||
local foundAccounts, foundItems = {}, {}
|
||||
local userData = {
|
||||
accounts = {},
|
||||
inventory = {},
|
||||
job = {},
|
||||
loadout = {},
|
||||
playerName = GetPlayerName(playerId),
|
||||
weight = 0,
|
||||
metadata = {}
|
||||
}
|
||||
local result = MySQL.prepare.await(loadPlayer, { identifier })
|
||||
local job, grade, jobObject, gradeObject = result.job, tostring(result.job_grade)
|
||||
local foundAccounts, foundItems = {}, {}
|
||||
|
||||
-- Accounts
|
||||
if result.accounts and result.accounts ~= '' then
|
||||
local accounts = json.decode(result.accounts)
|
||||
-- Accounts
|
||||
if result.accounts and result.accounts ~= '' then
|
||||
local accounts = json.decode(result.accounts)
|
||||
|
||||
for account, money in pairs(accounts) do
|
||||
foundAccounts[account] = money
|
||||
end
|
||||
end
|
||||
for account, money in pairs(accounts) do
|
||||
foundAccounts[account] = money
|
||||
end
|
||||
end
|
||||
|
||||
for account, data in pairs(Config.Accounts) do
|
||||
if data.round == nil then
|
||||
data.round = true
|
||||
end
|
||||
local index = #userData.accounts + 1
|
||||
userData.accounts[index] = {
|
||||
name = account,
|
||||
money = foundAccounts[account] or Config.StartingAccountMoney[account] or 0,
|
||||
label = data.label,
|
||||
round = data.round,
|
||||
index = index
|
||||
}
|
||||
end
|
||||
for account, data in pairs(Config.Accounts) do
|
||||
if data.round == nil then
|
||||
data.round = true
|
||||
end
|
||||
local index = #userData.accounts + 1
|
||||
userData.accounts[index] = {
|
||||
name = account,
|
||||
money = foundAccounts[account] or Config.StartingAccountMoney[account] or 0,
|
||||
label = data.label,
|
||||
round = data.round,
|
||||
index = index
|
||||
}
|
||||
end
|
||||
|
||||
-- Job
|
||||
if ESX.DoesJobExist(job, grade) then
|
||||
jobObject, gradeObject = ESX.Jobs[job], ESX.Jobs[job].grades[grade]
|
||||
else
|
||||
print(('[^3WARNING^7] Ignoring invalid job for ^5%s^7 [job: ^5%s^7, grade: ^5%s^7]'):format(identifier, job, grade))
|
||||
job, grade = 'unemployed', '0'
|
||||
jobObject, gradeObject = ESX.Jobs[job], ESX.Jobs[job].grades[grade]
|
||||
end
|
||||
-- Job
|
||||
if ESX.DoesJobExist(job, grade) then
|
||||
jobObject, gradeObject = ESX.Jobs[job], ESX.Jobs[job].grades[grade]
|
||||
else
|
||||
print(('[^3WARNING^7] Ignoring invalid job for ^5%s^7 [job: ^5%s^7, grade: ^5%s^7]'):format(identifier, job, grade))
|
||||
job, grade = 'unemployed', '0'
|
||||
jobObject, gradeObject = ESX.Jobs[job], ESX.Jobs[job].grades[grade]
|
||||
end
|
||||
|
||||
userData.job.id = jobObject.id
|
||||
userData.job.name = jobObject.name
|
||||
userData.job.label = jobObject.label
|
||||
userData.job.id = jobObject.id
|
||||
userData.job.name = jobObject.name
|
||||
userData.job.label = jobObject.label
|
||||
|
||||
userData.job.grade = tonumber(grade)
|
||||
userData.job.grade_name = gradeObject.name
|
||||
userData.job.grade_label = gradeObject.label
|
||||
userData.job.grade_salary = gradeObject.salary
|
||||
userData.job.grade = tonumber(grade)
|
||||
userData.job.grade_name = gradeObject.name
|
||||
userData.job.grade_label = gradeObject.label
|
||||
userData.job.grade_salary = gradeObject.salary
|
||||
|
||||
userData.job.skin_male = {}
|
||||
userData.job.skin_female = {}
|
||||
userData.job.skin_male = {}
|
||||
userData.job.skin_female = {}
|
||||
|
||||
if gradeObject.skin_male then
|
||||
userData.job.skin_male = json.decode(gradeObject.skin_male)
|
||||
end
|
||||
if gradeObject.skin_female then
|
||||
userData.job.skin_female = json.decode(gradeObject.skin_female)
|
||||
end
|
||||
if gradeObject.skin_male then
|
||||
userData.job.skin_male = json.decode(gradeObject.skin_male)
|
||||
end
|
||||
if gradeObject.skin_female then
|
||||
userData.job.skin_female = json.decode(gradeObject.skin_female)
|
||||
end
|
||||
|
||||
-- Inventory
|
||||
if not Config.OxInventory then
|
||||
if result.inventory and result.inventory ~= '' then
|
||||
local inventory = json.decode(result.inventory)
|
||||
-- Inventory
|
||||
if not Config.OxInventory then
|
||||
if result.inventory and result.inventory ~= '' then
|
||||
local inventory = json.decode(result.inventory)
|
||||
|
||||
for name, count in pairs(inventory) do
|
||||
local item = ESX.Items[name]
|
||||
for name, count in pairs(inventory) do
|
||||
local item = ESX.Items[name]
|
||||
|
||||
if item then
|
||||
foundItems[name] = count
|
||||
else
|
||||
print(('[^3WARNING^7] Ignoring invalid item ^5"%s"^7 for ^5"%s^7"'):format(name, identifier))
|
||||
end
|
||||
end
|
||||
end
|
||||
if item then
|
||||
foundItems[name] = count
|
||||
else
|
||||
print(('[^3WARNING^7] Ignoring invalid item ^5"%s"^7 for ^5"%s^7"'):format(name, identifier))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for name, item in pairs(ESX.Items) do
|
||||
local count = foundItems[name] or 0
|
||||
if count > 0 then
|
||||
userData.weight = userData.weight + (item.weight * count)
|
||||
end
|
||||
for name, item in pairs(ESX.Items) do
|
||||
local count = foundItems[name] or 0
|
||||
if count > 0 then
|
||||
userData.weight = userData.weight + (item.weight * count)
|
||||
end
|
||||
|
||||
table.insert(userData.inventory,
|
||||
{name = name, count = count, label = item.label, weight = item.weight, usable = Core.UsableItemsCallbacks[name] ~= nil, rare = item.rare,
|
||||
canRemove = item.canRemove})
|
||||
end
|
||||
table.insert(userData.inventory,
|
||||
{
|
||||
name = name,
|
||||
count = count,
|
||||
label = item.label,
|
||||
weight = item.weight,
|
||||
usable = Core.UsableItemsCallbacks[name] ~= nil,
|
||||
rare = item.rare,
|
||||
canRemove = item.canRemove
|
||||
})
|
||||
end
|
||||
|
||||
table.sort(userData.inventory, function(a, b)
|
||||
return a.label < b.label
|
||||
end)
|
||||
else
|
||||
if result.inventory and result.inventory ~= '' then
|
||||
userData.inventory = json.decode(result.inventory)
|
||||
else
|
||||
userData.inventory = {}
|
||||
end
|
||||
end
|
||||
table.sort(userData.inventory, function(a, b)
|
||||
return a.label < b.label
|
||||
end)
|
||||
else
|
||||
if result.inventory and result.inventory ~= '' then
|
||||
userData.inventory = json.decode(result.inventory)
|
||||
else
|
||||
userData.inventory = {}
|
||||
end
|
||||
end
|
||||
|
||||
-- Group
|
||||
if result.group then
|
||||
if result.group == "superadmin" then
|
||||
userData.group = "admin"
|
||||
print("[^3WARNING^7] ^5Superadmin^7 detected, setting group to ^5admin^7")
|
||||
else
|
||||
userData.group = result.group
|
||||
end
|
||||
else
|
||||
userData.group = 'user'
|
||||
end
|
||||
-- Group
|
||||
if result.group then
|
||||
if result.group == "superadmin" then
|
||||
userData.group = "admin"
|
||||
print("[^3WARNING^7] ^5Superadmin^7 detected, setting group to ^5admin^7")
|
||||
else
|
||||
userData.group = result.group
|
||||
end
|
||||
else
|
||||
userData.group = 'user'
|
||||
end
|
||||
|
||||
-- Loadout
|
||||
if not Config.OxInventory then
|
||||
if result.loadout and result.loadout ~= '' then
|
||||
local loadout = json.decode(result.loadout)
|
||||
-- Loadout
|
||||
if not Config.OxInventory then
|
||||
if result.loadout and result.loadout ~= '' then
|
||||
local loadout = json.decode(result.loadout)
|
||||
|
||||
for name, weapon in pairs(loadout) do
|
||||
local label = ESX.GetWeaponLabel(name)
|
||||
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
|
||||
if label then
|
||||
if not weapon.components then
|
||||
weapon.components = {}
|
||||
end
|
||||
if not weapon.tintIndex then
|
||||
weapon.tintIndex = 0
|
||||
end
|
||||
|
||||
table.insert(userData.loadout,
|
||||
{name = name, ammo = weapon.ammo, label = label, components = weapon.components, tintIndex = weapon.tintIndex})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
table.insert(userData.loadout,
|
||||
{
|
||||
name = name,
|
||||
ammo = weapon.ammo,
|
||||
label = label,
|
||||
components = weapon.components,
|
||||
tintIndex = weapon.tintIndex
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Position
|
||||
userData.coords = json.decode(result.position) or Config.DefaultSpawns[math.random(#Config.DefaultSpawns)]
|
||||
-- Position
|
||||
userData.coords = json.decode(result.position) or Config.DefaultSpawns[math.random(#Config.DefaultSpawns)]
|
||||
|
||||
-- Skin
|
||||
if result.skin and result.skin ~= '' then
|
||||
userData.skin = json.decode(result.skin)
|
||||
else
|
||||
if userData.sex == 'f' then
|
||||
userData.skin = {sex = 1}
|
||||
else
|
||||
userData.skin = {sex = 0}
|
||||
end
|
||||
end
|
||||
-- Skin
|
||||
if result.skin and result.skin ~= '' then
|
||||
userData.skin = json.decode(result.skin)
|
||||
else
|
||||
if userData.sex == 'f' then
|
||||
userData.skin = { sex = 1 }
|
||||
else
|
||||
userData.skin = { sex = 0 }
|
||||
end
|
||||
end
|
||||
|
||||
-- Identity
|
||||
if result.firstname and result.firstname ~= '' then
|
||||
userData.firstname = result.firstname
|
||||
userData.lastname = result.lastname
|
||||
userData.playerName = userData.firstname .. ' ' .. userData.lastname
|
||||
if result.dateofbirth then
|
||||
userData.dateofbirth = result.dateofbirth
|
||||
end
|
||||
if result.sex then
|
||||
userData.sex = result.sex
|
||||
end
|
||||
if result.height then
|
||||
userData.height = result.height
|
||||
end
|
||||
end
|
||||
-- Identity
|
||||
if result.firstname and result.firstname ~= '' then
|
||||
userData.firstname = result.firstname
|
||||
userData.lastname = result.lastname
|
||||
userData.playerName = userData.firstname .. ' ' .. userData.lastname
|
||||
if result.dateofbirth then
|
||||
userData.dateofbirth = result.dateofbirth
|
||||
end
|
||||
if result.sex then
|
||||
userData.sex = result.sex
|
||||
end
|
||||
if result.height then
|
||||
userData.height = result.height
|
||||
end
|
||||
end
|
||||
|
||||
if result.metadata and result.metadata ~= '' then
|
||||
local metadata = json.decode(result.metadata)
|
||||
userData.metadata = metadata
|
||||
end
|
||||
if result.metadata and result.metadata ~= '' then
|
||||
local metadata = json.decode(result.metadata)
|
||||
userData.metadata = metadata
|
||||
end
|
||||
|
||||
local xPlayer = CreateExtendedPlayer(playerId, identifier, userData.group, userData.accounts, userData.inventory, userData.weight, userData.job,
|
||||
userData.loadout, userData.playerName, userData.coords, userData.metadata)
|
||||
ESX.Players[playerId] = xPlayer
|
||||
Core.playersByIdentifier[identifier] = xPlayer
|
||||
local xPlayer = CreateExtendedPlayer(playerId, identifier, userData.group, userData.accounts, userData.inventory, userData.weight, userData.job, userData.loadout, userData.playerName, userData.coords, userData.metadata)
|
||||
ESX.Players[playerId] = xPlayer
|
||||
Core.playersByIdentifier[identifier] = xPlayer
|
||||
|
||||
if userData.firstname then
|
||||
xPlayer.set('firstName', userData.firstname)
|
||||
xPlayer.set('lastName', userData.lastname)
|
||||
if userData.dateofbirth then
|
||||
xPlayer.set('dateofbirth', userData.dateofbirth)
|
||||
end
|
||||
if userData.sex then
|
||||
xPlayer.set('sex', userData.sex)
|
||||
end
|
||||
if userData.height then
|
||||
xPlayer.set('height', userData.height)
|
||||
end
|
||||
end
|
||||
if userData.firstname then
|
||||
xPlayer.set('firstName', userData.firstname)
|
||||
xPlayer.set('lastName', userData.lastname)
|
||||
if userData.dateofbirth then
|
||||
xPlayer.set('dateofbirth', userData.dateofbirth)
|
||||
end
|
||||
if userData.sex then
|
||||
xPlayer.set('sex', userData.sex)
|
||||
end
|
||||
if userData.height then
|
||||
xPlayer.set('height', userData.height)
|
||||
end
|
||||
end
|
||||
|
||||
TriggerEvent('esx:playerLoaded', playerId, xPlayer, isNew)
|
||||
TriggerEvent('esx:playerLoaded', playerId, xPlayer, isNew)
|
||||
|
||||
xPlayer.triggerEvent('esx:playerLoaded',
|
||||
{
|
||||
accounts = xPlayer.getAccounts(),
|
||||
coords = xPlayer.getCoords(),
|
||||
identifier = xPlayer.getIdentifier(),
|
||||
inventory = xPlayer.getInventory(),
|
||||
job = xPlayer.getJob(),
|
||||
loadout = xPlayer.getLoadout(),
|
||||
maxWeight = xPlayer.getMaxWeight(),
|
||||
money = xPlayer.getMoney(),
|
||||
sex = xPlayer.get("sex") or "m",
|
||||
firstName = xPlayer.get("firstName") or "John",
|
||||
lastName = xPlayer.get("lastName") or "Doe",
|
||||
dateofbirth = xPlayer.get("dateofbirth") or "01/01/2000",
|
||||
height = xPlayer.get("height") or 120,
|
||||
dead = false,
|
||||
metadata = xPlayer.getMeta()
|
||||
}, isNew,
|
||||
userData.skin)
|
||||
xPlayer.triggerEvent('esx:playerLoaded',
|
||||
{
|
||||
accounts = xPlayer.getAccounts(),
|
||||
coords = userData.coords,
|
||||
identifier = xPlayer.getIdentifier(),
|
||||
inventory = xPlayer.getInventory(),
|
||||
job = xPlayer.getJob(),
|
||||
loadout = xPlayer.getLoadout(),
|
||||
maxWeight = xPlayer.getMaxWeight(),
|
||||
money = xPlayer.getMoney(),
|
||||
sex = xPlayer.get("sex") or "m",
|
||||
firstName = xPlayer.get("firstName") or "John",
|
||||
lastName = xPlayer.get("lastName") or "Doe",
|
||||
dateofbirth = xPlayer.get("dateofbirth") or "01/01/2000",
|
||||
height = xPlayer.get("height") or 120,
|
||||
dead = false,
|
||||
metadata = xPlayer.getMeta()
|
||||
}, isNew,
|
||||
userData.skin)
|
||||
|
||||
if not Config.OxInventory then
|
||||
xPlayer.triggerEvent('esx:createMissingPickups', Core.Pickups)
|
||||
else
|
||||
exports.ox_inventory:setPlayerInventory(xPlayer, userData.inventory)
|
||||
end
|
||||
xPlayer.updateCoords()
|
||||
xPlayer.triggerEvent('esx:registerSuggestions', Core.RegisteredCommands)
|
||||
print(('[^2INFO^0] Player ^5"%s"^0 has connected to the server. ID: ^5%s^7'):format(xPlayer.getName(), playerId))
|
||||
if not Config.OxInventory then
|
||||
xPlayer.triggerEvent('esx:createMissingPickups', Core.Pickups)
|
||||
else
|
||||
exports.ox_inventory:setPlayerInventory(xPlayer, userData.inventory)
|
||||
|
||||
if isNew then
|
||||
for account, money in pairs(Config.StartingAccountMoney) do
|
||||
if account == 'money' or account == 'black_money' then
|
||||
exports.ox_inventory:AddItem(playerId, account, money)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
xPlayer.triggerEvent('esx:registerSuggestions', Core.RegisteredCommands)
|
||||
print(('[^2INFO^0] Player ^5"%s"^0 has connected to the server. ID: ^5%s^7'):format(xPlayer.getName(), playerId))
|
||||
end
|
||||
|
||||
|
||||
AddEventHandler('chatMessage', function(playerId, author, message)
|
||||
local xPlayer = ESX.GetPlayerFromId(playerId)
|
||||
if message:sub(1, 1) == '/' and playerId > 0 then
|
||||
@@ -628,6 +656,22 @@ ESX.RegisterServerCallback('esx:getPlayerNames', function(source, cb, players)
|
||||
cb(players)
|
||||
end)
|
||||
|
||||
ESX.RegisterServerCallback("esx:spawnVehicle", function(source,cb,vehData)
|
||||
local ped = GetPlayerPed(source)
|
||||
ESX.OneSync.SpawnVehicle(vehData.model or `ADDER`, vehData.coords or GetEntityCoords(ped), vehData.coords.w or 0.0, vehData.props or {}, function(id)
|
||||
if vehData.warp then
|
||||
local vehicle = NetworkGetEntityFromNetworkId(id)
|
||||
local timeout = 0
|
||||
while GetVehiclePedIsIn(ped) ~= vehicle and timeout <= 15 do
|
||||
Wait(0)
|
||||
TaskWarpPedIntoVehicle(ped, vehicle, -1)
|
||||
timeout += 1
|
||||
end
|
||||
end
|
||||
cb(id)
|
||||
end)
|
||||
end)
|
||||
|
||||
AddEventHandler('txAdmin:events:scheduledRestart', function(eventData)
|
||||
if eventData.secondsRemaining == 60 then
|
||||
CreateThread(function()
|
||||
|
||||
@@ -14,8 +14,10 @@ end
|
||||
|
||||
local function closeMenu(namespace, name)
|
||||
CurrentNameSpace = namespace
|
||||
if OpenedMenus < 1 then return end
|
||||
OpenedMenus = OpenedMenus - 1
|
||||
OpenedMenus -= 1
|
||||
if OpenedMenus < 0 then
|
||||
OpenedMenus = 0
|
||||
end
|
||||
SendNUIMessage({
|
||||
action = 'closeMenu',
|
||||
namespace = namespace,
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
local mp_m_freemode_01 = `mp_m_freemode_01`
|
||||
local mp_f_freemode_01 = `mp_f_freemode_01`
|
||||
|
||||
local SpawnCoords = Config.Spawn[math.random(#Config.Spawn)]
|
||||
|
||||
if ESX.GetConfig().Multichar then
|
||||
|
||||
CreateThread(function()
|
||||
@@ -9,7 +12,7 @@ if ESX.GetConfig().Multichar then
|
||||
if NetworkIsPlayerActive(PlayerId()) then
|
||||
exports.spawnmanager:setAutoSpawn(false)
|
||||
DoScreenFadeOut(0)
|
||||
while not GetResourceState('esx_context') == 'started' do
|
||||
while GetResourceState('esx_context') ~= 'started' do
|
||||
Wait(100)
|
||||
end
|
||||
TriggerEvent("esx_multicharacter:SetupCharacters")
|
||||
@@ -28,14 +31,14 @@ if ESX.GetConfig().Multichar then
|
||||
spawned = false
|
||||
cam = CreateCam("DEFAULT_SCRIPTED_CAMERA", true)
|
||||
local playerPed = PlayerPedId()
|
||||
SetEntityCoords(playerPed, Config.Spawn.x, Config.Spawn.y, Config.Spawn.z, true, false, false, false)
|
||||
SetEntityHeading(playerPed, Config.Spawn.w)
|
||||
SetEntityCoords(playerPed, SpawnCoords.x, SpawnCoords.y, SpawnCoords.z, true, false, false, false)
|
||||
SetEntityHeading(playerPed, SpawnCoords.w)
|
||||
local offset = GetOffsetFromEntityInWorldCoords(playerPed, 0, 1.7, 0.4)
|
||||
DoScreenFadeOut(0)
|
||||
SetCamActive(cam, true)
|
||||
RenderScriptCams(true, false, 1, true, true)
|
||||
SetCamCoord(cam, offset.x, offset.y, offset.z)
|
||||
PointCamAtCoord(cam, Config.Spawn.x, Config.Spawn.y, Config.Spawn.z + 1.3)
|
||||
PointCamAtCoord(cam, SpawnCoords.x, SpawnCoords.y, SpawnCoords.z + 1.3)
|
||||
StartLoop()
|
||||
ShutdownLoadingScreen()
|
||||
ShutdownLoadingScreenNui()
|
||||
@@ -98,10 +101,10 @@ if ESX.GetConfig().Multichar then
|
||||
SetupCharacter = function(index)
|
||||
if not spawned then
|
||||
exports.spawnmanager:spawnPlayer({
|
||||
x = Config.Spawn.x,
|
||||
y = Config.Spawn.y,
|
||||
z = Config.Spawn.z,
|
||||
heading = Config.Spawn.w,
|
||||
x = SpawnCoords.x,
|
||||
y = SpawnCoords.y,
|
||||
z = SpawnCoords.z,
|
||||
heading = SpawnCoords.w,
|
||||
model = Characters[index].model or mp_m_freemode_01,
|
||||
skipFade = true
|
||||
}, function()
|
||||
@@ -147,7 +150,7 @@ if ESX.GetConfig().Multichar then
|
||||
{title = TranslateCap('return'), unselectable = false, icon = "fa-solid fa-arrow-left", description = TranslateCap('char_delete_no_description'), action = "return"}
|
||||
}
|
||||
|
||||
ESX.OpenContext("left", elements, function(element, Action)
|
||||
ESX.OpenContext("left", elements, function(_, Action)
|
||||
if Action.action == "delete" then
|
||||
ESX.CloseContext()
|
||||
TriggerServerEvent('esx_multicharacter:DeleteCharacter', Action.value)
|
||||
@@ -167,7 +170,7 @@ if ESX.GetConfig().Multichar then
|
||||
elements[3] = {title = TranslateCap('char_disabled'), value = SelectedCharacter.value, icon ="fa-solid fa-xmark", description = TranslateCap('char_disabled_description'),}
|
||||
end
|
||||
if Config.CanDelete then elements[4] = {title = TranslateCap('char_delete'),icon ="fa-solid fa-xmark",description = TranslateCap('char_delete_description'), action = 'delete', value = SelectedCharacter.value} end
|
||||
ESX.OpenContext("left", elements, function(element, Action)
|
||||
ESX.OpenContext("left", elements, function(_, Action)
|
||||
if Action.action == "play" then
|
||||
SendNUIMessage({
|
||||
action = "closeui"
|
||||
@@ -201,7 +204,7 @@ if ESX.GetConfig().Multichar then
|
||||
elements[#elements+1] = {title = TranslateCap('create_char'), icon = "fa-solid fa-plus", value = (#elements+1), new = true}
|
||||
end
|
||||
|
||||
ESX.OpenContext("left", elements, function(menu, SelectedCharacter)
|
||||
ESX.OpenContext("left", elements, function(_, SelectedCharacter)
|
||||
if SelectedCharacter.new then
|
||||
ESX.CloseContext()
|
||||
local GetSlot = function()
|
||||
@@ -242,10 +245,10 @@ if ESX.GetConfig().Multichar then
|
||||
action = "closeui"
|
||||
})
|
||||
exports.spawnmanager:spawnPlayer({
|
||||
x = Config.Spawn.x,
|
||||
y = Config.Spawn.y,
|
||||
z = Config.Spawn.z,
|
||||
heading = Config.Spawn.w,
|
||||
x = SpawnCoords.x,
|
||||
y = SpawnCoords.y,
|
||||
z = SpawnCoords.z,
|
||||
heading = SpawnCoords.w,
|
||||
model = mp_m_freemode_01,
|
||||
skipFade = true
|
||||
}, function()
|
||||
@@ -318,7 +321,7 @@ if ESX.GetConfig().Multichar then
|
||||
end)
|
||||
|
||||
if Config.Relog then
|
||||
RegisterCommand('relog', function(source, args, rawCommand)
|
||||
RegisterCommand('relog', function()
|
||||
if canRelog then
|
||||
canRelog = false
|
||||
TriggerServerEvent('esx_multicharacter:relog')
|
||||
|
||||
@@ -16,7 +16,9 @@ if IsDuplicityVersion() then
|
||||
else
|
||||
-- Sets the location for the character selection scene
|
||||
-- To set the spawn location for new characters, modify the default value in the users SQL table
|
||||
Config.Spawn = vector4(-284.2856, 562.4627, 172.9182, 19.9895)
|
||||
Config.Spawn = {
|
||||
{x = -284.2856, y = 562.4627, z = 172.9182, heading = 19.9895},
|
||||
}
|
||||
--------------------
|
||||
|
||||
-- Do not use unless you are prepared to adjust your resources to correctly reset data
|
||||
|
||||
@@ -24,7 +24,7 @@ end, true, {help = TranslateCap('command_remslots'), validate = true, arguments
|
||||
{name = 'identifier', help = TranslateCap('command_identifier'), type = 'string'}
|
||||
}})
|
||||
|
||||
ESX.RegisterCommand('enablechar', 'admin', function(xPlayer, args, showError)
|
||||
ESX.RegisterCommand('enablechar', 'admin', function(xPlayer, args)
|
||||
|
||||
local selectedCharacter = 'char'..args.charslot..':'..args.identifier;
|
||||
|
||||
@@ -43,7 +43,7 @@ end, true, {help = TranslateCap('command_enablechar'), validate = true, argument
|
||||
{name = 'charslot', help = TranslateCap('command_charslot'), type = 'number'}
|
||||
}})
|
||||
|
||||
ESX.RegisterCommand('disablechar', 'admin', function(xPlayer, args, showError)
|
||||
ESX.RegisterCommand('disablechar', 'admin', function(xPlayer, args)
|
||||
|
||||
local selectedCharacter = 'char'..args.charslot..':'..args.identifier;
|
||||
|
||||
@@ -62,6 +62,6 @@ end, true, {help = TranslateCap('command_disablechar'), validate = true, argumen
|
||||
{name = 'charslot', help = TranslateCap('command_charslot'), type = 'number'}
|
||||
}})
|
||||
|
||||
RegisterCommand('forcelog', function(source, args, rawCommand)
|
||||
RegisterCommand('forcelog', function(source)
|
||||
TriggerEvent('esx:playerLogout', source)
|
||||
end, true)
|
||||
|
||||
@@ -96,7 +96,7 @@ end
|
||||
TriggerClientEvent('esx_multicharacter:SetupUI', source, characters, slots)
|
||||
end
|
||||
|
||||
AddEventHandler('playerConnecting', function(playerName, setKickReason, deferrals)
|
||||
AddEventHandler('playerConnecting', function(_, _, deferrals)
|
||||
deferrals.defer()
|
||||
local identifier = GetIdentifier(source)
|
||||
if oneSyncState == "off" or oneSyncState == "legacy" then
|
||||
@@ -214,6 +214,14 @@ end
|
||||
if isNew then
|
||||
awaitingRegistration[source] = charid
|
||||
else
|
||||
if not ESX.GetConfig().EnableDebug then
|
||||
local identifier = PREFIX..charid .. ':' .. GetIdentifier(source)
|
||||
if ESX.GetPlayerFromIdentifier(identifier) then
|
||||
DropPlayer(source, 'Your identifier '..identifier..' is already on the server!')
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
TriggerEvent('esx:onPlayerJoined', source, PREFIX..charid)
|
||||
ESX.Players[GetIdentifier(source)] = true
|
||||
end
|
||||
@@ -226,7 +234,7 @@ end
|
||||
ESX.Players[GetIdentifier(source)] = true
|
||||
end)
|
||||
|
||||
AddEventHandler('playerDropped', function(reason)
|
||||
AddEventHandler('playerDropped', function()
|
||||
awaitingRegistration[source] = nil
|
||||
ESX.Players[GetIdentifier(source)] = nil
|
||||
end)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
local lastSkin, cam, isCameraActive
|
||||
local firstSpawn, zoomOffset, camOffset, heading, skinLoaded = true, 0.0, 0.0, 90.0, false
|
||||
local firstSpawn, zoomOffset, camOffset, heading = true, 0.0, 0.0, 90.0, false
|
||||
|
||||
RegisterNetEvent('esx:playerLoaded')
|
||||
AddEventHandler('esx:playerLoaded', function(xPlayer, isNew, skin)
|
||||
AddEventHandler('esx:playerLoaded', function(_, _, skin)
|
||||
TriggerServerEvent('esx_skin:setWeight', skin)
|
||||
end)
|
||||
|
||||
@@ -117,7 +117,7 @@ function OpenMenu(submitCb, cancelCb, restrict)
|
||||
|
||||
menu.refresh()
|
||||
end
|
||||
end, function(data, menu)
|
||||
end, function()
|
||||
DeleteSkinCam()
|
||||
end)
|
||||
end)
|
||||
@@ -248,7 +248,6 @@ end
|
||||
|
||||
AddEventHandler('esx_skin:resetFirstSpawn', function()
|
||||
firstSpawn = true
|
||||
skinLoaded = false
|
||||
ESX.PlayerLoaded = false
|
||||
end)
|
||||
|
||||
@@ -259,15 +258,13 @@ AddEventHandler('esx_skin:playerRegistered', function()
|
||||
end
|
||||
|
||||
if firstSpawn then
|
||||
ESX.TriggerServerCallback('esx_skin:getPlayerSkin', function(skin, jobSkin)
|
||||
ESX.TriggerServerCallback('esx_skin:getPlayerSkin', function(skin)
|
||||
if skin == nil then
|
||||
TriggerEvent('skinchanger:loadSkin', {sex = 0}, OpenSaveableMenu)
|
||||
Wait(100)
|
||||
skinLoaded = true
|
||||
else
|
||||
TriggerEvent('skinchanger:loadSkin', skin)
|
||||
Wait(100)
|
||||
skinLoaded = true
|
||||
end
|
||||
end)
|
||||
|
||||
@@ -277,7 +274,7 @@ AddEventHandler('esx_skin:playerRegistered', function()
|
||||
end)
|
||||
|
||||
RegisterNetEvent('esx:playerLoaded')
|
||||
AddEventHandler('esx:playerLoaded', function(xPlayer)
|
||||
AddEventHandler('esx:playerLoaded', function()
|
||||
ESX.PlayerLoaded = true
|
||||
end)
|
||||
|
||||
|
||||
@@ -71,10 +71,10 @@ ESX.RegisterServerCallback('esx_skin:getPlayerSkin', function(source, cb)
|
||||
end)
|
||||
end)
|
||||
|
||||
ESX.RegisterCommand('skin', 'admin', function(xPlayer, args, showError)
|
||||
ESX.RegisterCommand('skin', 'admin', function(xPlayer)
|
||||
xPlayer.triggerEvent('esx_skin:openSaveableMenu')
|
||||
end, false, {help = TranslateCap('skin')})
|
||||
|
||||
ESX.RegisterCommand('skinsave', 'admin', function(xPlayer, args, showError)
|
||||
ESX.RegisterCommand('skinsave', 'admin', function(xPlayer)
|
||||
xPlayer.triggerEvent('esx_skin:requestSaveSkin')
|
||||
end, false, {help = TranslateCap('saveskin')})
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<p align='center'><a href='https://discord.esx-framework.org/'>Discord</a> - <a href='https://esx-framework.org/'>Website</a> - <a href='https://documentation.esx-framework.org/legacy/installation'>Documentation</a></b></h5>
|
||||
|
||||
<p align='center'>Want more resources? You can browse the <a href="https://github.com/esx-community/">ESX Community Github</a> or <a href="https://forum.cfx.re/tag/esx">Cfx.re Releases board</a> for more!
|
||||
<p align='center'><b>ESX is the leading framework, trusted By thousands of commmunitys for the highest quality roleplay servers on FiveM</b></p>
|
||||
<p align='center'><b>ESX is the leading framework, trusted by thousands of communities for the highest quality roleplay servers on FiveM</b></p>
|
||||
|
||||
<hr>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user