mirror of
https://github.com/esx-framework/esx_core.git
synced 2026-08-29 23:01:30 +00:00
579 lines
16 KiB
Lua
579 lines
16 KiB
Lua
local isPaused, isDead, pickups = false, false, {}
|
|
|
|
Citizen.CreateThread(function()
|
|
while NetworkIsPlayerActive(PlayerId()) do
|
|
Citizen.Wait(5)
|
|
TriggerServerEvent('esx:onPlayerJoined')
|
|
break
|
|
end
|
|
end)
|
|
|
|
|
|
RegisterNetEvent('esx:playerLoaded')
|
|
AddEventHandler('esx:playerLoaded', function(playerData, isNew)
|
|
ESX.PlayerLoaded = true
|
|
ESX.PlayerData = playerData
|
|
|
|
|
|
FreezeEntityPosition(PlayerPedId(), true)
|
|
|
|
-- enable PVP
|
|
if Config.EnablePVP then
|
|
SetCanAttackFriendly(PlayerPedId(), true, false)
|
|
NetworkSetFriendlyFireOption(true)
|
|
end
|
|
|
|
if Config.EnableHud then
|
|
for k,v in ipairs(playerData.accounts) do
|
|
local accountTpl = '<div><img src="img/accounts/' .. v.name .. '.png"/> {{money}}</div>'
|
|
ESX.UI.HUD.RegisterElement('account_' .. v.name, k, 0, accountTpl, {money = ESX.Math.GroupDigits(v.money)})
|
|
end
|
|
|
|
local jobTpl = '<div>{{job_label}} - {{grade_label}}</div>'
|
|
|
|
if playerData.job.grade_label == '' or playerData.job.grade_label == playerData.job.label then
|
|
jobTpl = '<div>{{job_label}}</div>'
|
|
end
|
|
|
|
ESX.UI.HUD.RegisterElement('job', #playerData.accounts, 0, jobTpl, {
|
|
job_label = playerData.job.label,
|
|
grade_label = playerData.job.grade_label
|
|
})
|
|
end
|
|
|
|
exports.spawnmanager:spawnPlayer({
|
|
x = playerData.coords.x,
|
|
y = playerData.coords.y,
|
|
z = playerData.coords.z + 0.25,
|
|
heading = playerData.coords.heading,
|
|
model = `mp_m_freemode_01`,
|
|
skipFade = false
|
|
}, function()
|
|
TriggerEvent('esx:onPlayerSpawn')
|
|
TriggerEvent('playerSpawned') -- compatibility with old scripts, will be removed soon
|
|
TriggerEvent('esx:restoreLoadout')
|
|
|
|
Citizen.Wait(4000)
|
|
ShutdownLoadingScreen()
|
|
ShutdownLoadingScreenNui()
|
|
FreezeEntityPosition(PlayerPedId(), false)
|
|
StartServerSyncLoops()
|
|
end)
|
|
if isNew then
|
|
TriggerEvent('esx_identity:showRegisterIdentity')
|
|
else
|
|
ESX.TriggerServerCallback('esx_skin:getPlayerSkin', function(skin, jobSkin)
|
|
TriggerEvent('skinchanger:loadSkin', skin)
|
|
end)
|
|
end
|
|
if Config.EnableHud then
|
|
ESX.UI.HUD.SetDisplay(1.0)
|
|
end
|
|
end)
|
|
|
|
RegisterNetEvent('esx:setMaxWeight')
|
|
AddEventHandler('esx:setMaxWeight', function(newMaxWeight) ESX.PlayerData.maxWeight = newMaxWeight end)
|
|
|
|
AddEventHandler('esx:onPlayerSpawn', function() isDead = false end)
|
|
AddEventHandler('esx:onPlayerDeath', function() isDead = true end)
|
|
|
|
AddEventHandler('skinchanger:modelLoaded', function()
|
|
while not ESX.PlayerLoaded do
|
|
Citizen.Wait(100)
|
|
end
|
|
|
|
TriggerEvent('esx:restoreLoadout')
|
|
end)
|
|
|
|
AddEventHandler('esx:restoreLoadout', function()
|
|
local playerPed = PlayerPedId()
|
|
local ammoTypes = {}
|
|
RemoveAllPedWeapons(playerPed, true)
|
|
|
|
for k,v in ipairs(ESX.PlayerData.loadout) do
|
|
local weaponName = v.name
|
|
local weaponHash = GetHashKey(weaponName)
|
|
|
|
GiveWeaponToPed(playerPed, weaponHash, 0, false, false)
|
|
SetPedWeaponTintIndex(playerPed, weaponHash, v.tintIndex)
|
|
|
|
local ammoType = GetPedAmmoTypeFromWeapon(playerPed, weaponHash)
|
|
|
|
for k2,v2 in ipairs(v.components) do
|
|
local componentHash = ESX.GetWeaponComponent(weaponName, v2).hash
|
|
GiveWeaponComponentToPed(playerPed, weaponHash, componentHash)
|
|
end
|
|
|
|
if not ammoTypes[ammoType] then
|
|
AddAmmoToPed(playerPed, weaponHash, v.ammo)
|
|
ammoTypes[ammoType] = true
|
|
end
|
|
end
|
|
end)
|
|
|
|
RegisterNetEvent('esx:setAccountMoney')
|
|
AddEventHandler('esx:setAccountMoney', function(account)
|
|
for k,v in ipairs(ESX.PlayerData.accounts) do
|
|
if v.name == account.name then
|
|
ESX.PlayerData.accounts[k] = account
|
|
break
|
|
end
|
|
end
|
|
|
|
if Config.EnableHud then
|
|
ESX.UI.HUD.UpdateElement('account_' .. account.name, {
|
|
money = ESX.Math.GroupDigits(account.money)
|
|
})
|
|
end
|
|
end)
|
|
|
|
RegisterNetEvent('esx:addInventoryItem')
|
|
AddEventHandler('esx:addInventoryItem', function(item, count, showNotification)
|
|
for k,v in ipairs(ESX.PlayerData.inventory) do
|
|
if v.name == item then
|
|
ESX.UI.ShowInventoryItemNotification(true, v.label, count - v.count)
|
|
ESX.PlayerData.inventory[k].count = count
|
|
break
|
|
end
|
|
end
|
|
|
|
if showNotification then
|
|
ESX.UI.ShowInventoryItemNotification(true, item, count)
|
|
end
|
|
|
|
if ESX.UI.Menu.IsOpen('default', 'es_extended', 'inventory') then
|
|
ESX.ShowInventory()
|
|
end
|
|
end)
|
|
|
|
RegisterNetEvent('esx:removeInventoryItem')
|
|
AddEventHandler('esx:removeInventoryItem', function(item, count, showNotification)
|
|
for k,v in ipairs(ESX.PlayerData.inventory) do
|
|
if v.name == item then
|
|
ESX.UI.ShowInventoryItemNotification(false, v.label, v.count - count)
|
|
ESX.PlayerData.inventory[k].count = count
|
|
break
|
|
end
|
|
end
|
|
|
|
if showNotification then
|
|
ESX.UI.ShowInventoryItemNotification(false, item, count)
|
|
end
|
|
|
|
if ESX.UI.Menu.IsOpen('default', 'es_extended', 'inventory') then
|
|
ESX.ShowInventory()
|
|
end
|
|
end)
|
|
|
|
RegisterNetEvent('esx:addWeapon')
|
|
AddEventHandler('esx:addWeapon', function(weaponName, ammo)
|
|
-- Removed PlayerPedId() from being stored in a variable, not needed
|
|
-- when it's only being used once, also doing it in a few
|
|
-- functions below this one
|
|
GiveWeaponToPed(PlayerPedId(), weaponName, ammo, false, false)
|
|
end)
|
|
|
|
RegisterNetEvent('esx:addWeaponComponent')
|
|
AddEventHandler('esx:addWeaponComponent', function(weaponName, weaponComponent)
|
|
local componentHash = ESX.GetWeaponComponent(weaponName, weaponComponent).hash
|
|
GiveWeaponComponentToPed(PlayerPedId(), weaponName, componentHash)
|
|
end)
|
|
|
|
RegisterNetEvent('esx:setWeaponAmmo')
|
|
AddEventHandler('esx:setWeaponAmmo', function(weaponName, weaponAmmo)
|
|
SetPedAmmo(PlayerPedId(), weaponName, weaponAmmo)
|
|
end)
|
|
|
|
RegisterNetEvent('esx:setWeaponTint')
|
|
AddEventHandler('esx:setWeaponTint', function(weaponName, weaponTintIndex)
|
|
SetPedWeaponTintIndex(PlayerPedId(), weaponName, weaponTintIndex)
|
|
end)
|
|
|
|
RegisterNetEvent('esx:removeWeapon')
|
|
AddEventHandler('esx:removeWeapon', function(weaponName)
|
|
local playerPed = PlayerPedId()
|
|
RemoveWeaponFromPed(playerPed, weaponName)
|
|
SetPedAmmo(playerPed, weaponName, 0)
|
|
end)
|
|
|
|
RegisterNetEvent('esx:removeWeaponComponent')
|
|
AddEventHandler('esx:removeWeaponComponent', function(weaponName, weaponComponent)
|
|
local componentHash = ESX.GetWeaponComponent(weaponName, weaponComponent).hash
|
|
RemoveWeaponComponentFromPed(PlayerPedId(), weaponName, componentHash)
|
|
end)
|
|
|
|
RegisterNetEvent('esx:teleport')
|
|
AddEventHandler('esx:teleport', function(coords)
|
|
-- The coords x, y and z were having 0.0 added to them here to make them floats
|
|
-- Since we are forcing vectors in the teleport function now we don't need to do it
|
|
ESX.Game.Teleport(PlayerPedId(), coords)
|
|
end)
|
|
|
|
RegisterNetEvent('esx:setJob')
|
|
AddEventHandler('esx:setJob', function(Job)
|
|
if Config.EnableHud then
|
|
ESX.UI.HUD.UpdateElement('job', {
|
|
job_label = Job.label,
|
|
grade_label = Job.grade_label
|
|
})
|
|
end
|
|
ESX.SetPlayerData("job", Job)
|
|
end)
|
|
|
|
RegisterNetEvent('esx:spawnVehicle')
|
|
AddEventHandler('esx:spawnVehicle', function(vehicleName)
|
|
local model = (type(vehicleName) == 'number' and vehicleName or GetHashKey(vehicleName))
|
|
|
|
if IsModelInCdimage(model) then
|
|
local playerPed = PlayerPedId()
|
|
local playerCoords, playerHeading = GetEntityCoords(playerPed), GetEntityHeading(playerPed)
|
|
|
|
ESX.Game.SpawnVehicle(model, playerCoords, playerHeading, function(vehicle)
|
|
TaskWarpPedIntoVehicle(playerPed, vehicle, -1)
|
|
end)
|
|
else
|
|
TriggerEvent('chat:addMessage', {args = {'^1SYSTEM', 'Invalid vehicle model.'}})
|
|
end
|
|
end)
|
|
|
|
RegisterNetEvent('esx:createPickup')
|
|
AddEventHandler('esx:createPickup', function(pickupId, label, coords, type, name, components, tintIndex)
|
|
local function setObjectProperties(object)
|
|
SetEntityAsMissionEntity(object, true, false)
|
|
PlaceObjectOnGroundProperly(object)
|
|
FreezeEntityPosition(object, true)
|
|
SetEntityCollision(object, false, true)
|
|
|
|
pickups[pickupId] = {
|
|
obj = object,
|
|
label = label,
|
|
inRange = false,
|
|
coords = vector3(coords.x, coords.y, coords.z)
|
|
}
|
|
end
|
|
|
|
if type == 'item_weapon' then
|
|
local weaponHash = GetHashKey(name)
|
|
ESX.Streaming.RequestWeaponAsset(weaponHash)
|
|
local pickupObject = CreateWeaponObject(weaponHash, 50, coords.x, coords.y, coords.z, true, 1.0, 0)
|
|
SetWeaponObjectTintIndex(pickupObject, tintIndex)
|
|
|
|
for k,v in ipairs(components) do
|
|
local component = ESX.GetWeaponComponent(name, v)
|
|
GiveWeaponComponentToWeaponObject(pickupObject, component.hash)
|
|
end
|
|
|
|
setObjectProperties(pickupObject)
|
|
else
|
|
ESX.Game.SpawnLocalObject('prop_money_bag_01', coords, setObjectProperties)
|
|
end
|
|
end)
|
|
|
|
RegisterNetEvent('esx:createMissingPickups')
|
|
AddEventHandler('esx:createMissingPickups', function(missingPickups)
|
|
for pickupId,pickup in pairs(missingPickups) do
|
|
TriggerEvent('esx:createPickup', pickupId, pickup.label, pickup.coords, pickup.type, pickup.name, pickup.components, pickup.tintIndex)
|
|
end
|
|
end)
|
|
|
|
RegisterNetEvent('esx:registerSuggestions')
|
|
AddEventHandler('esx:registerSuggestions', function(registeredCommands)
|
|
for name,command in pairs(registeredCommands) do
|
|
if command.suggestion then
|
|
TriggerEvent('chat:addSuggestion', ('/%s'):format(name), command.suggestion.help, command.suggestion.arguments)
|
|
end
|
|
end
|
|
end)
|
|
|
|
RegisterNetEvent('esx:removePickup')
|
|
AddEventHandler('esx:removePickup', function(pickupId)
|
|
if pickups[pickupId] and pickups[pickupId].obj then
|
|
ESX.Game.DeleteObject(pickups[pickupId].obj)
|
|
pickups[pickupId] = nil
|
|
end
|
|
end)
|
|
|
|
RegisterNetEvent('esx:deleteVehicle')
|
|
AddEventHandler('esx:deleteVehicle', function(radius)
|
|
local playerPed = PlayerPedId()
|
|
|
|
if radius and tonumber(radius) then
|
|
radius = tonumber(radius) + 0.01
|
|
local vehicles = ESX.Game.GetVehiclesInArea(GetEntityCoords(playerPed), radius)
|
|
|
|
for k,entity in ipairs(vehicles) do
|
|
local attempt = 0
|
|
|
|
while not NetworkHasControlOfEntity(entity) and attempt < 100 and DoesEntityExist(entity) do
|
|
Citizen.Wait(100)
|
|
NetworkRequestControlOfEntity(entity)
|
|
attempt = attempt + 1
|
|
end
|
|
|
|
if DoesEntityExist(entity) and NetworkHasControlOfEntity(entity) then
|
|
ESX.Game.DeleteVehicle(entity)
|
|
end
|
|
end
|
|
else
|
|
local vehicle, attempt = ESX.Game.GetVehicleInDirection(), 0
|
|
|
|
if IsPedInAnyVehicle(playerPed, true) then
|
|
vehicle = GetVehiclePedIsIn(playerPed, false)
|
|
end
|
|
|
|
while not NetworkHasControlOfEntity(vehicle) and attempt < 100 and DoesEntityExist(vehicle) do
|
|
Citizen.Wait(100)
|
|
NetworkRequestControlOfEntity(vehicle)
|
|
attempt = attempt + 1
|
|
end
|
|
|
|
if DoesEntityExist(vehicle) and NetworkHasControlOfEntity(vehicle) then
|
|
ESX.Game.DeleteVehicle(vehicle)
|
|
end
|
|
end
|
|
end)
|
|
|
|
-- Pause menu disables HUD display
|
|
if Config.EnableHud then
|
|
Citizen.CreateThread(function()
|
|
while true do
|
|
Citizen.Wait(300)
|
|
|
|
if IsPauseMenuActive() and not isPaused then
|
|
isPaused = true
|
|
ESX.UI.HUD.SetDisplay(0.0)
|
|
elseif not IsPauseMenuActive() and isPaused then
|
|
isPaused = false
|
|
ESX.UI.HUD.SetDisplay(1.0)
|
|
end
|
|
end
|
|
end)
|
|
end
|
|
|
|
function StartServerSyncLoops()
|
|
-- keep track of ammo
|
|
Citizen.CreateThread(function()
|
|
while true do
|
|
Citizen.Wait(1000)
|
|
|
|
local letSleep = true
|
|
local playerPed = PlayerPedId()
|
|
|
|
if IsPedArmed(playerPed, 4) then
|
|
if IsPedShooting(playerPed) then
|
|
local _,weaponHash = GetCurrentPedWeapon(playerPed, true)
|
|
local weapon = ESX.GetWeaponFromHash(weaponHash)
|
|
|
|
if weapon then
|
|
local ammoCount = GetAmmoInPedWeapon(playerPed, weaponHash)
|
|
TriggerServerEvent('esx:updateWeaponAmmo', weapon.name, ammoCount)
|
|
end
|
|
end
|
|
end
|
|
if letSleep then
|
|
Citizen.Wait(500)
|
|
end
|
|
end
|
|
end)
|
|
|
|
-- sync current player coords with server
|
|
Citizen.CreateThread(function()
|
|
local previousCoords = vector3(ESX.PlayerData.coords.x, ESX.PlayerData.coords.y, ESX.PlayerData.coords.z)
|
|
|
|
while true do
|
|
Citizen.Wait(1500)
|
|
local playerPed = PlayerPedId()
|
|
|
|
if DoesEntityExist(playerPed) then
|
|
local playerCoords = GetEntityCoords(playerPed)
|
|
local distance = #(playerCoords - previousCoords)
|
|
|
|
if distance > 1 then
|
|
previousCoords = playerCoords
|
|
local playerHeading = ESX.Math.Round(GetEntityHeading(playerPed), 1)
|
|
local formattedCoords = {x = ESX.Math.Round(playerCoords.x, 1), y = ESX.Math.Round(playerCoords.y, 1), z = ESX.Math.Round(playerCoords.z, 1), heading = playerHeading}
|
|
TriggerServerEvent('esx:updateCoords', formattedCoords)
|
|
end
|
|
end
|
|
end
|
|
end)
|
|
end
|
|
|
|
if Config.EnableDefaultInventory then
|
|
RegisterCommand('showinv', function()
|
|
if not isDead and not ESX.UI.Menu.IsOpen('default', 'es_extended', 'inventory') then
|
|
ESX.ShowInventory()
|
|
end
|
|
end)
|
|
|
|
RegisterKeyMapping('showinv', _U('keymap_showinventory'), 'keyboard', 'F2')
|
|
end
|
|
|
|
-- disable wanted level
|
|
if not Config.EnableWantedLevel then
|
|
ClearPlayerWantedLevel(PlayerId())
|
|
SetMaxWantedLevel(0)
|
|
end
|
|
|
|
Citizen.CreateThread(function()
|
|
while true do
|
|
Citizen.Wait(0)
|
|
local playerPed = PlayerPedId()
|
|
local playerCoords, letSleep = GetEntityCoords(playerPed), true
|
|
local closestPlayer, closestDistance = ESX.Game.GetClosestPlayer(playerCoords)
|
|
|
|
for pickupId,pickup in pairs(pickups) do
|
|
local distance = #(playerCoords - pickup.coords)
|
|
|
|
if distance < 5 then
|
|
local label = pickup.label
|
|
letSleep = false
|
|
|
|
if distance < 1 then
|
|
if IsControlJustReleased(0, 38) then
|
|
if IsPedOnFoot(playerPed) and (closestDistance == -1 or closestDistance > 3) and not pickup.inRange then
|
|
pickup.inRange = true
|
|
|
|
local dict, anim = 'weapons@first_person@aim_rng@generic@projectile@sticky_bomb@', 'plant_floor'
|
|
ESX.Streaming.RequestAnimDict(dict)
|
|
TaskPlayAnim(playerPed, dict, anim, 8.0, 1.0, 1000, 16, 0.0, false, false, false)
|
|
Citizen.Wait(1000)
|
|
|
|
TriggerServerEvent('esx:onPickup', pickupId)
|
|
PlaySoundFrontend(-1, 'PICK_UP', 'HUD_FRONTEND_DEFAULT_SOUNDSET', false)
|
|
end
|
|
end
|
|
|
|
label = ('%s~n~%s'):format(label, _U('threw_pickup_prompt'))
|
|
end
|
|
|
|
ESX.Game.Utils.DrawText3D({
|
|
x = pickup.coords.x,
|
|
y = pickup.coords.y,
|
|
z = pickup.coords.z + 0.25
|
|
}, label, 1.2, 1)
|
|
elseif pickup.inRange then
|
|
pickup.inRange = false
|
|
end
|
|
end
|
|
|
|
if letSleep then
|
|
Citizen.Wait(500)
|
|
end
|
|
end
|
|
end)
|
|
|
|
----- Admin commnads from esx_adminplus
|
|
|
|
RegisterNetEvent("esx:tpm")
|
|
AddEventHandler("esx:tpm", function()
|
|
local WaypointHandle = GetFirstBlipInfoId(8)
|
|
if DoesBlipExist(WaypointHandle) then
|
|
local waypointCoords = GetBlipInfoIdCoord(WaypointHandle)
|
|
|
|
for height = 1, 1000 do
|
|
SetPedCoordsKeepVehicle(PlayerPedId(), waypointCoords["x"], waypointCoords["y"], height + 0.0)
|
|
|
|
local foundGround, zPos = GetGroundZFor_3dCoord(waypointCoords["x"], waypointCoords["y"], height + 0.0)
|
|
|
|
if foundGround then
|
|
SetPedCoordsKeepVehicle(PlayerPedId(), waypointCoords["x"], waypointCoords["y"], height + 0.0)
|
|
|
|
break
|
|
end
|
|
|
|
Citizen.Wait(5)
|
|
end
|
|
TriggerEvent('chatMessage', "Successfully Teleported")
|
|
else
|
|
TriggerEvent('chatMessage', "No Waypoint Set")
|
|
end
|
|
end)
|
|
|
|
local noclip = false
|
|
RegisterNetEvent("esx:noclip")
|
|
AddEventHandler("esx:noclip", function(input)
|
|
local player = PlayerId()
|
|
local ped = PlayerPedId
|
|
|
|
local msg = "disabled"
|
|
if(noclip == false)then
|
|
noclip_pos = GetEntityCoords(PlayerPedId(), false)
|
|
end
|
|
|
|
noclip = not noclip
|
|
|
|
if(noclip)then
|
|
msg = "enabled"
|
|
end
|
|
|
|
TriggerEvent("chatMessage", "Noclip has been ^2^*" .. msg)
|
|
end)
|
|
|
|
local heading = 0
|
|
Citizen.CreateThread(function()
|
|
while true do
|
|
Citizen.Wait(0)
|
|
|
|
if(noclip)then
|
|
SetEntityCoordsNoOffset(PlayerPedId(), noclip_pos.x, noclip_pos.y, noclip_pos.z, 0, 0, 0)
|
|
|
|
if(IsControlPressed(1, 34))then
|
|
heading = heading + 1.5
|
|
if(heading > 360)then
|
|
heading = 0
|
|
end
|
|
|
|
SetEntityHeading(PlayerPedId(), heading)
|
|
end
|
|
|
|
if(IsControlPressed(1, 9))then
|
|
heading = heading - 1.5
|
|
if(heading < 0)then
|
|
heading = 360
|
|
end
|
|
|
|
SetEntityHeading(PlayerPedId(), heading)
|
|
end
|
|
|
|
if(IsControlPressed(1, 8))then
|
|
noclip_pos = GetOffsetFromEntityInWorldCoords(PlayerPedId(), 0.0, 1.0, 0.0)
|
|
end
|
|
|
|
if(IsControlPressed(1, 32))then
|
|
noclip_pos = GetOffsetFromEntityInWorldCoords(PlayerPedId(), 0.0, -1.0, 0.0)
|
|
end
|
|
|
|
if(IsControlPressed(1, 27))then
|
|
noclip_pos = GetOffsetFromEntityInWorldCoords(PlayerPedId(), 0.0, 0.0, 1.0)
|
|
end
|
|
|
|
if(IsControlPressed(1, 173))then
|
|
noclip_pos = GetOffsetFromEntityInWorldCoords(PlayerPedId(), 0.0, 0.0, -1.0)
|
|
end
|
|
else
|
|
Citizen.Wait(200)
|
|
end
|
|
end
|
|
end)
|
|
|
|
RegisterNetEvent("esx:killPlayer")
|
|
AddEventHandler("esx:killPlayer", function()
|
|
SetEntityHealth(PlayerPedId(), 0)
|
|
end)
|
|
|
|
RegisterNetEvent("esx:freezePlayer")
|
|
AddEventHandler("esx:freezePlayer", function(input)
|
|
local player = PlayerId()
|
|
local ped = PlayerPedId()
|
|
if input == 'freeze' then
|
|
SetEntityCollision(ped, false)
|
|
FreezeEntityPosition(ped, true)
|
|
SetPlayerInvincible(player, true)
|
|
elseif input == 'unfreeze' then
|
|
SetEntityCollision(ped, true)
|
|
FreezeEntityPosition(ped, false)
|
|
SetPlayerInvincible(player, false)
|
|
end
|
|
end)
|