Merge branch 'dev' into fix/multichar

This commit is contained in:
Gellipapa
2023-06-27 22:29:52 +02:00
committed by GitHub
13 changed files with 391 additions and 290 deletions
+8
View File
@@ -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
+1 -2
View File
@@ -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
+46 -57
View File
@@ -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
+60 -11
View File
@@ -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
View File
@@ -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()
+4 -2
View File
@@ -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,
+19 -16
View File
@@ -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')
+3 -1
View File
@@ -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)
+10 -2
View File
@@ -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)
+5 -8
View File
@@ -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)
+2 -2
View File
@@ -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')})
+1 -1
View File
@@ -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>