0.0.1
This commit is contained in:
1367
resources/[core]/es_extended/client/functions.lua
Normal file
1367
resources/[core]/es_extended/client/functions.lua
Normal file
File diff suppressed because it is too large
Load Diff
21
resources/[core]/es_extended/client/imports/class.lua
Normal file
21
resources/[core]/es_extended/client/imports/class.lua
Normal file
@@ -0,0 +1,21 @@
|
||||
local class = {}
|
||||
class.__index = class
|
||||
|
||||
function class:new(...)
|
||||
local instance = setmetatable({}, self)
|
||||
if instance.constructor then
|
||||
local ret = instance:constructor(...)
|
||||
if type(ret) == 'table' then
|
||||
return ret
|
||||
end
|
||||
end
|
||||
return instance
|
||||
end
|
||||
|
||||
function Class(body, heritage)
|
||||
local prototype = body or {}
|
||||
prototype.__index = prototype
|
||||
return setmetatable(prototype, heritage or class)
|
||||
end
|
||||
|
||||
return Class
|
||||
53
resources/[core]/es_extended/client/imports/point.lua
Normal file
53
resources/[core]/es_extended/client/imports/point.lua
Normal file
@@ -0,0 +1,53 @@
|
||||
local Point = ESX.Class()
|
||||
|
||||
local nearby, loop = {}, nil
|
||||
|
||||
function Point:constructor(properties)
|
||||
self.coords = properties.coords
|
||||
self.hidden = properties.hidden
|
||||
self.enter = properties.enter
|
||||
self.leave = properties.leave
|
||||
self.inside = properties.inside
|
||||
self.handle = ESX.CreatePointInternal(properties.coords, properties.distance, properties.hidden, function()
|
||||
nearby[self.handle] = self
|
||||
if self.enter then
|
||||
self:enter()
|
||||
end
|
||||
if not loop then
|
||||
loop = true
|
||||
CreateThread(function()
|
||||
while loop do
|
||||
local coords = GetEntityCoords(ESX.PlayerData.ped)
|
||||
for _, point in pairs(nearby) do
|
||||
if point.inside then
|
||||
point:inside(#(coords - point.coords))
|
||||
end
|
||||
end
|
||||
Wait(0)
|
||||
end
|
||||
end)
|
||||
end
|
||||
end, function()
|
||||
nearby[self.handle] = nil
|
||||
if self.leave then
|
||||
self:leave()
|
||||
end
|
||||
if #nearby == 0 then
|
||||
loop = false
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function Point:delete()
|
||||
ESX.RemovePointInternal(self.handle)
|
||||
end
|
||||
|
||||
function Point:toggle(hidden)
|
||||
if hidden == nil then
|
||||
hidden = not self.hidden
|
||||
end
|
||||
self.hidden = hidden
|
||||
ESX.HidePointInternal(self.handle, hidden)
|
||||
end
|
||||
|
||||
return Point
|
||||
30
resources/[core]/es_extended/client/main.lua
Normal file
30
resources/[core]/es_extended/client/main.lua
Normal file
@@ -0,0 +1,30 @@
|
||||
Core = {}
|
||||
Core.Input = {}
|
||||
Core.Events = {}
|
||||
|
||||
ESX.PlayerData = {}
|
||||
ESX.PlayerLoaded = false
|
||||
ESX.playerId = PlayerId()
|
||||
ESX.serverId = GetPlayerServerId(ESX.playerId)
|
||||
|
||||
ESX.UI = {}
|
||||
ESX.UI.Menu = {}
|
||||
ESX.UI.Menu.RegisteredTypes = {}
|
||||
ESX.UI.Menu.Opened = {}
|
||||
|
||||
ESX.Game = {}
|
||||
ESX.Game.Utils = {}
|
||||
|
||||
CreateThread(function()
|
||||
while not Config.Multichar do
|
||||
Wait(100)
|
||||
|
||||
if NetworkIsPlayerActive(ESX.playerId) then
|
||||
ESX.DisableSpawnManager()
|
||||
DoScreenFadeOut(0)
|
||||
Wait(500)
|
||||
TriggerServerEvent("esx:onPlayerJoined")
|
||||
break
|
||||
end
|
||||
end
|
||||
end)
|
||||
234
resources/[core]/es_extended/client/modules/actions.lua
Normal file
234
resources/[core]/es_extended/client/modules/actions.lua
Normal file
@@ -0,0 +1,234 @@
|
||||
Actions = {}
|
||||
Actions._index = Actions
|
||||
|
||||
Actions.inVehicle = false
|
||||
Actions.enteringVehicle = false
|
||||
Actions.inPauseMenu = false
|
||||
Actions.currentWeapon = false
|
||||
|
||||
function Actions:GetSeatPedIsIn()
|
||||
for i = -1, 16 do
|
||||
if GetPedInVehicleSeat(self.vehicle, i) == ESX.PlayerData.ped then
|
||||
return i
|
||||
end
|
||||
end
|
||||
return -1
|
||||
end
|
||||
|
||||
function Actions:GetVehicleData()
|
||||
if not DoesEntityExist(self.vehicle) then
|
||||
return
|
||||
end
|
||||
|
||||
local vehicleModel = GetEntityModel(self.vehicle)
|
||||
local displayName = GetDisplayNameFromVehicleModel(vehicleModel)
|
||||
local netId = NetworkGetEntityIsNetworked(self.vehicle) and VehToNet(self.vehicle) or self.vehicle
|
||||
local plate = GetVehicleNumberPlateText(self.vehicle)
|
||||
|
||||
return displayName, netId, plate
|
||||
end
|
||||
|
||||
function Actions:SetVehicleStatus()
|
||||
ESX.SetPlayerData("vehicle", self.vehicle)
|
||||
ESX.SetPlayerData("seat", self.seat)
|
||||
end
|
||||
|
||||
function Actions:TrackPedCoordsOnce()
|
||||
CreateThread(function()
|
||||
while not ESX.IsPlayerLoaded() do
|
||||
Wait(250)
|
||||
end
|
||||
|
||||
ESX.PlayerData.coords = nil
|
||||
|
||||
setmetatable(ESX.PlayerData, {
|
||||
__index = function(_, key)
|
||||
if key ~= "coords" then
|
||||
return
|
||||
end
|
||||
|
||||
local coords = GetEntityCoords(ESX.PlayerData.ped)
|
||||
|
||||
return coords
|
||||
end
|
||||
})
|
||||
end)
|
||||
end
|
||||
|
||||
function Actions:TrackPed()
|
||||
local playerPed = ESX.PlayerData.ped
|
||||
local newPed = PlayerPedId()
|
||||
|
||||
if playerPed ~= newPed then
|
||||
ESX.SetPlayerData("ped", newPed)
|
||||
|
||||
TriggerEvent("esx:playerPedChanged", newPed)
|
||||
|
||||
if Config.EnableDebug then
|
||||
print("[DEBUG] Player ped changed:", newPed)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Actions:TrackPauseMenu()
|
||||
local isActive = IsPauseMenuActive()
|
||||
|
||||
if isActive ~= self.inPauseMenu then
|
||||
self.inPauseMenu = isActive
|
||||
TriggerEvent("esx:pauseMenuActive", isActive)
|
||||
|
||||
if Config.EnableDebug then
|
||||
print("[DEBUG] Pause menu active:", isActive)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Actions:EnterVehicle()
|
||||
self.seat = GetSeatPedIsTryingToEnter(ESX.PlayerData.ped)
|
||||
|
||||
local _, netId, plate = self:GetVehicleData()
|
||||
|
||||
self.enteringVehicle = true
|
||||
TriggerEvent("esx:enteringVehicle", self.vehicle, plate, self.seat, netId)
|
||||
TriggerServerEvent("esx:enteringVehicle", plate, self.seat, netId)
|
||||
|
||||
self:SetVehicleStatus()
|
||||
|
||||
if Config.EnableDebug then
|
||||
print("[DEBUG] Entering vehicle:", self.vehicle, plate, self.seat, netId)
|
||||
end
|
||||
end
|
||||
|
||||
function Actions:ResetVehicleData()
|
||||
self.enteringVehicle = false
|
||||
self.vehicle = false
|
||||
self.seat = false
|
||||
self.inVehicle = false
|
||||
|
||||
self:SetVehicleStatus()
|
||||
end
|
||||
|
||||
function Actions:EnterAborted()
|
||||
self:ResetVehicleData()
|
||||
|
||||
TriggerEvent("esx:enteringVehicleAborted")
|
||||
TriggerServerEvent("esx:enteringVehicleAborted")
|
||||
|
||||
if Config.EnableDebug then
|
||||
print("[DEBUG] Entering vehicle aborted")
|
||||
end
|
||||
end
|
||||
|
||||
function Actions:WarpEnter()
|
||||
self.enteringVehicle = false
|
||||
self.inVehicle = true
|
||||
|
||||
self.seat = self:GetSeatPedIsIn()
|
||||
|
||||
local displayName, netId, plate = self:GetVehicleData()
|
||||
|
||||
self:SetVehicleStatus()
|
||||
TriggerEvent("esx:enteredVehicle", self.vehicle, plate, self.seat, displayName, netId)
|
||||
TriggerServerEvent("esx:enteredVehicle", plate, self.seat, displayName, netId)
|
||||
|
||||
if Config.EnableDebug then
|
||||
print("[DEBUG] Entered vehicle:", self.vehicle, plate, self.seat, displayName, netId)
|
||||
end
|
||||
end
|
||||
|
||||
function Actions:ExitVehicle()
|
||||
local currentVehicle = GetVehiclePedIsIn(ESX.PlayerData.ped, false)
|
||||
|
||||
if currentVehicle ~= self.vehicle or ESX.PlayerData.dead then
|
||||
local displayName, netId, plate = self:GetVehicleData()
|
||||
|
||||
TriggerEvent("esx:exitedVehicle", self.vehicle, plate, self.seat, displayName, netId)
|
||||
TriggerServerEvent("esx:exitedVehicle", plate, self.seat, displayName, netId)
|
||||
|
||||
if Config.EnableDebug then
|
||||
print("[DEBUG] Exited vehicle:", self.vehicle, plate, self.seat, displayName, netId)
|
||||
end
|
||||
|
||||
self:ResetVehicleData()
|
||||
end
|
||||
end
|
||||
|
||||
function Actions:TrackVehicle()
|
||||
if not self.inVehicle and not ESX.PlayerData.dead then
|
||||
local tempVehicle = GetVehiclePedIsTryingToEnter(ESX.PlayerData.ped)
|
||||
|
||||
if DoesEntityExist(tempVehicle) and not self.enteringVehicle then
|
||||
self.vehicle = tempVehicle
|
||||
self:EnterVehicle()
|
||||
elseif not DoesEntityExist(tempVehicle) and not IsPedInAnyVehicle(ESX.PlayerData.ped, true) and self.enteringVehicle then
|
||||
self:EnterAborted()
|
||||
elseif IsPedInAnyVehicle(ESX.PlayerData.ped, false) then
|
||||
self.vehicle = GetVehiclePedIsIn(ESX.PlayerData.ped, false)
|
||||
self:WarpEnter()
|
||||
end
|
||||
elseif self.inVehicle then
|
||||
self:ExitVehicle()
|
||||
self:TrackSeat()
|
||||
end
|
||||
end
|
||||
|
||||
function Actions:TrackSeat()
|
||||
if not self.inVehicle then
|
||||
return
|
||||
end
|
||||
|
||||
local newSeat = self:GetSeatPedIsIn()
|
||||
if newSeat ~= self.seat then
|
||||
self.seat = newSeat
|
||||
ESX.SetPlayerData("seat", self.seat)
|
||||
TriggerEvent("esx:vehicleSeatChanged", self.seat)
|
||||
|
||||
if Config.EnableDebug then
|
||||
print("[DEBUG] Vehicle seat changed:", self.seat)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Actions:TrackWeapon()
|
||||
---@type number|false
|
||||
local newWeapon = GetSelectedPedWeapon(ESX.PlayerData.ped)
|
||||
newWeapon = newWeapon ~= `WEAPON_UNARMED` and newWeapon or false
|
||||
|
||||
if newWeapon ~= self.currentWeapon then
|
||||
self.currentWeapon = newWeapon
|
||||
ESX.SetPlayerData("weapon", self.currentWeapon)
|
||||
TriggerEvent("esx:weaponChanged", self.currentWeapon)
|
||||
|
||||
if Config.EnableDebug then
|
||||
print("[DEBUG] Weapon changed:", self.currentWeapon)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Actions:SlowLoop()
|
||||
CreateThread(function()
|
||||
while ESX.PlayerLoaded do
|
||||
self:TrackPauseMenu()
|
||||
self:TrackVehicle()
|
||||
self:TrackWeapon()
|
||||
Wait(500)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function Actions:PedLoop()
|
||||
CreateThread(function()
|
||||
while ESX.PlayerLoaded do
|
||||
self:TrackPed()
|
||||
Wait(0)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function Actions:Init()
|
||||
self:SlowLoop()
|
||||
self:PedLoop()
|
||||
self:TrackPedCoordsOnce()
|
||||
end
|
||||
|
||||
Actions:Init()
|
||||
253
resources/[core]/es_extended/client/modules/adjustments.lua
Normal file
253
resources/[core]/es_extended/client/modules/adjustments.lua
Normal file
@@ -0,0 +1,253 @@
|
||||
Adjustments = {}
|
||||
|
||||
function Adjustments:RemoveHudComponents()
|
||||
for i = 1, #Config.RemoveHudComponents do
|
||||
if Config.RemoveHudComponents[i] then
|
||||
SetHudComponentSize(i, 0.0, 0.0)
|
||||
SetHudComponentPosition(i, 900.0, 900.0)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Adjustments:DisableAimAssist()
|
||||
if Config.DisableAimAssist then
|
||||
SetPlayerTargetingMode(3)
|
||||
end
|
||||
end
|
||||
|
||||
function Adjustments:DisableNPCDrops()
|
||||
if Config.DisableNPCDrops then
|
||||
local weaponPickups = { `PICKUP_WEAPON_CARBINERIFLE`, `PICKUP_WEAPON_PISTOL`, `PICKUP_WEAPON_PUMPSHOTGUN` }
|
||||
for i = 1, #weaponPickups do
|
||||
ToggleUsePickupsForPlayer(ESX.playerId, weaponPickups[i], false)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Adjustments:SeatShuffle()
|
||||
if Config.DisableVehicleSeatShuff then
|
||||
AddEventHandler("esx:enteredVehicle", function(vehicle, _, seat)
|
||||
if seat > -1 then
|
||||
SetPedIntoVehicle(ESX.PlayerData.ped, vehicle, seat)
|
||||
SetPedConfigFlag(ESX.PlayerData.ped, 184, true)
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
function Adjustments:HealthRegeneration()
|
||||
if Config.DisableHealthRegeneration then
|
||||
SetPlayerHealthRechargeMultiplier(ESX.playerId, 0.0)
|
||||
end
|
||||
end
|
||||
|
||||
function Adjustments:AmmoAndVehicleRewards()
|
||||
CreateThread(function()
|
||||
while true do
|
||||
if Config.DisableDisplayAmmo then
|
||||
DisplayAmmoThisFrame(false)
|
||||
end
|
||||
|
||||
if Config.DisableVehicleRewards then
|
||||
DisablePlayerVehicleRewards(ESX.playerId)
|
||||
end
|
||||
|
||||
Wait(0)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function Adjustments:EnablePvP()
|
||||
if Config.EnablePVP then
|
||||
SetCanAttackFriendly(ESX.PlayerData.ped, true, false)
|
||||
NetworkSetFriendlyFireOption(true)
|
||||
end
|
||||
end
|
||||
|
||||
function Adjustments:DispatchServices()
|
||||
if Config.DisableDispatchServices then
|
||||
for i = 1, 15 do
|
||||
EnableDispatchService(i, false)
|
||||
end
|
||||
SetAudioFlag('PoliceScannerDisabled', true)
|
||||
end
|
||||
end
|
||||
|
||||
function Adjustments:NPCScenarios()
|
||||
if Config.DisableScenarios then
|
||||
local scenarios = {
|
||||
"WORLD_VEHICLE_ATTRACTOR",
|
||||
"WORLD_VEHICLE_AMBULANCE",
|
||||
"WORLD_VEHICLE_BICYCLE_BMX",
|
||||
"WORLD_VEHICLE_BICYCLE_BMX_BALLAS",
|
||||
"WORLD_VEHICLE_BICYCLE_BMX_FAMILY",
|
||||
"WORLD_VEHICLE_BICYCLE_BMX_HARMONY",
|
||||
"WORLD_VEHICLE_BICYCLE_BMX_VAGOS",
|
||||
"WORLD_VEHICLE_BICYCLE_MOUNTAIN",
|
||||
"WORLD_VEHICLE_BICYCLE_ROAD",
|
||||
"WORLD_VEHICLE_BIKE_OFF_ROAD_RACE",
|
||||
"WORLD_VEHICLE_BIKER",
|
||||
"WORLD_VEHICLE_BOAT_IDLE",
|
||||
"WORLD_VEHICLE_BOAT_IDLE_ALAMO",
|
||||
"WORLD_VEHICLE_BOAT_IDLE_MARQUIS",
|
||||
"WORLD_VEHICLE_BROKEN_DOWN",
|
||||
"WORLD_VEHICLE_BUSINESSMEN",
|
||||
"WORLD_VEHICLE_HELI_LIFEGUARD",
|
||||
"WORLD_VEHICLE_CLUCKIN_BELL_TRAILER",
|
||||
"WORLD_VEHICLE_CONSTRUCTION_SOLO",
|
||||
"WORLD_VEHICLE_CONSTRUCTION_PASSENGERS",
|
||||
"WORLD_VEHICLE_DRIVE_PASSENGERS",
|
||||
"WORLD_VEHICLE_DRIVE_PASSENGERS_LIMITED",
|
||||
"WORLD_VEHICLE_DRIVE_SOLO",
|
||||
"WORLD_VEHICLE_FIRE_TRUCK",
|
||||
"WORLD_VEHICLE_EMPTY",
|
||||
"WORLD_VEHICLE_MARIACHI",
|
||||
"WORLD_VEHICLE_MECHANIC",
|
||||
"WORLD_VEHICLE_MILITARY_PLANES_BIG",
|
||||
"WORLD_VEHICLE_MILITARY_PLANES_SMALL",
|
||||
"WORLD_VEHICLE_PARK_PARALLEL",
|
||||
"WORLD_VEHICLE_PARK_PERPENDICULAR_NOSE_IN",
|
||||
"WORLD_VEHICLE_PASSENGER_EXIT",
|
||||
"WORLD_VEHICLE_POLICE_BIKE",
|
||||
"WORLD_VEHICLE_POLICE_CAR",
|
||||
"WORLD_VEHICLE_POLICE",
|
||||
"WORLD_VEHICLE_POLICE_NEXT_TO_CAR",
|
||||
"WORLD_VEHICLE_QUARRY",
|
||||
"WORLD_VEHICLE_SALTON",
|
||||
"WORLD_VEHICLE_SALTON_DIRT_BIKE",
|
||||
"WORLD_VEHICLE_SECURITY_CAR",
|
||||
"WORLD_VEHICLE_STREETRACE",
|
||||
"WORLD_VEHICLE_TOURBUS",
|
||||
"WORLD_VEHICLE_TOURIST",
|
||||
"WORLD_VEHICLE_TANDL",
|
||||
"WORLD_VEHICLE_TRACTOR",
|
||||
"WORLD_VEHICLE_TRACTOR_BEACH",
|
||||
"WORLD_VEHICLE_TRUCK_LOGS",
|
||||
"WORLD_VEHICLE_TRUCKS_TRAILERS",
|
||||
"WORLD_VEHICLE_DISTANT_EMPTY_GROUND",
|
||||
"WORLD_HUMAN_PAPARAZZI",
|
||||
}
|
||||
|
||||
for i=1, #scenarios do
|
||||
SetScenarioTypeEnabled(scenarios[i], false)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Adjustments:LicensePlates()
|
||||
SetDefaultVehicleNumberPlateTextPattern(-1, Config.CustomAIPlates)
|
||||
end
|
||||
|
||||
local placeHolders = {
|
||||
server_name = function()
|
||||
return GetConvar("sv_projectName", "ESX-Framework")
|
||||
end,
|
||||
server_endpoint = function()
|
||||
return GetCurrentServerEndpoint() or "localhost:30120"
|
||||
end,
|
||||
server_players = function()
|
||||
return GlobalState.playerCount or 0
|
||||
end,
|
||||
server_maxplayers = function()
|
||||
return GetConvarInt("sv_maxClients", 48)
|
||||
end,
|
||||
player_name = function()
|
||||
return GetPlayerName(ESX.playerId)
|
||||
end,
|
||||
player_rp_name = function()
|
||||
return ESX.PlayerData.name or "John Doe"
|
||||
end,
|
||||
player_id = function()
|
||||
return ESX.serverId
|
||||
end,
|
||||
player_street = function()
|
||||
if not ESX.PlayerData.ped then return "Unknown" end
|
||||
|
||||
local playerCoords = GetEntityCoords(ESX.PlayerData.ped)
|
||||
local streetHash = GetStreetNameAtCoord(playerCoords.x, playerCoords.y, playerCoords.z)
|
||||
|
||||
return GetStreetNameFromHashKey(streetHash) or "Unknown"
|
||||
end,
|
||||
}
|
||||
|
||||
function Adjustments:ReplacePlaceholders(text)
|
||||
for placeholder, cb in pairs(placeHolders) do
|
||||
local success, result = pcall(cb)
|
||||
|
||||
if not success then
|
||||
error(("Failed to execute placeholder: ^5%s^7\n%s"):format(placeholder, result))
|
||||
result = "Unknown"
|
||||
end
|
||||
|
||||
text = text:gsub(("{%s}"):format(placeholder), tostring(result))
|
||||
end
|
||||
return text
|
||||
end
|
||||
|
||||
function Adjustments:DiscordPresence()
|
||||
if Config.DiscordActivity.appId ~= 0 then
|
||||
CreateThread(function()
|
||||
while true do
|
||||
SetDiscordAppId(Config.DiscordActivity.appId)
|
||||
SetRichPresence(self:ReplacePlaceholders(Config.DiscordActivity.presence))
|
||||
SetDiscordRichPresenceAsset(Config.DiscordActivity.assetName)
|
||||
SetDiscordRichPresenceAssetText(self:ReplacePlaceholders(Config.DiscordActivity.assetText))
|
||||
|
||||
for i = 1, #Config.DiscordActivity.buttons do
|
||||
local button = Config.DiscordActivity.buttons[i]
|
||||
local buttonUrl = self:ReplacePlaceholders(button.url)
|
||||
SetDiscordRichPresenceAction(i - 1, button.label, buttonUrl)
|
||||
end
|
||||
|
||||
Wait(Config.DiscordActivity.refresh)
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
function Adjustments:WantedLevel()
|
||||
if not Config.EnableWantedLevel then
|
||||
ClearPlayerWantedLevel(ESX.playerId)
|
||||
SetMaxWantedLevel(0)
|
||||
end
|
||||
end
|
||||
|
||||
function Adjustments:DisableRadio()
|
||||
if Config.RemoveHudComponents[16] then
|
||||
AddEventHandler("esx:enteredVehicle", function(vehicle, plate, seat, displayName, netId)
|
||||
SetVehRadioStation(vehicle,"OFF")
|
||||
SetUserRadioControlEnabled(false)
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
function Adjustments:Multipliers()
|
||||
CreateThread(function()
|
||||
while true do
|
||||
SetPedDensityMultiplierThisFrame(Config.Multipliers.pedDensity)
|
||||
SetScenarioPedDensityMultiplierThisFrame(Config.Multipliers.scenarioPedDensityInterior, Config.Multipliers.scenarioPedDensityExterior)
|
||||
SetAmbientVehicleRangeMultiplierThisFrame(Config.Multipliers.ambientVehicleRange)
|
||||
SetParkedVehicleDensityMultiplierThisFrame(Config.Multipliers.parkedVehicleDensity)
|
||||
SetRandomVehicleDensityMultiplierThisFrame(Config.Multipliers.randomVehicleDensity)
|
||||
SetVehicleDensityMultiplierThisFrame(Config.Multipliers.vehicleDensity)
|
||||
Wait(0)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function Adjustments:Load()
|
||||
self:RemoveHudComponents()
|
||||
self:DisableAimAssist()
|
||||
self:DisableNPCDrops()
|
||||
self:SeatShuffle()
|
||||
self:HealthRegeneration()
|
||||
self:AmmoAndVehicleRewards()
|
||||
self:EnablePvP()
|
||||
self:DispatchServices()
|
||||
self:NPCScenarios()
|
||||
self:LicensePlates()
|
||||
self:DiscordPresence()
|
||||
self:WantedLevel()
|
||||
self:DisableRadio()
|
||||
self:Multipliers()
|
||||
end
|
||||
146
resources/[core]/es_extended/client/modules/callback.lua
Normal file
146
resources/[core]/es_extended/client/modules/callback.lua
Normal file
@@ -0,0 +1,146 @@
|
||||
---@diagnostic disable: duplicate-set-field
|
||||
|
||||
-- =============================================
|
||||
-- MARK: Variables
|
||||
-- =============================================
|
||||
|
||||
Callbacks = {}
|
||||
|
||||
Callbacks.requests = {}
|
||||
Callbacks.storage = {}
|
||||
Callbacks.id = 0
|
||||
|
||||
-- =============================================
|
||||
-- MARK: Internal Functions
|
||||
-- =============================================
|
||||
|
||||
|
||||
function Callbacks:Register(name, resource, cb)
|
||||
self.storage[name] = {
|
||||
resource = resource,
|
||||
cb = cb
|
||||
}
|
||||
end
|
||||
|
||||
function Callbacks:Execute(cb, id, ...)
|
||||
local success, errorString = pcall(cb, ...)
|
||||
|
||||
if not success then
|
||||
print(("[^1ERROR^7] Failed to execute Callback with RequestId: ^5%s^7"):format(id))
|
||||
error(errorString)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
function Callbacks:Trigger(event, cb, invoker, ...)
|
||||
self.requests[self.id] = {
|
||||
await = type(cb) == "boolean",
|
||||
cb = cb or promise:new()
|
||||
}
|
||||
local table = self.requests[self.id]
|
||||
|
||||
TriggerServerEvent("esx:triggerServerCallback", event, self.id, invoker, ...)
|
||||
|
||||
self.id += 1
|
||||
|
||||
return table.cb
|
||||
end
|
||||
|
||||
function Callbacks:ServerRecieve(requestId, invoker, ...)
|
||||
if not self.requests[requestId] then
|
||||
return error(("Server Callback with requestId ^5%s^1 Was Called by ^5%s^1 but does not exist."):format(requestId, invoker))
|
||||
end
|
||||
|
||||
local callback = self.requests[requestId]
|
||||
|
||||
self.requests[requestId] = nil
|
||||
|
||||
if callback.await then
|
||||
callback.cb:resolve({ ... })
|
||||
else
|
||||
self:Execute(callback.cb, requestId, ...)
|
||||
end
|
||||
end
|
||||
|
||||
function Callbacks:ClientRecieve(eventName, requestId, invoker, ...)
|
||||
if not self.storage[eventName] then
|
||||
return error(("Client Callback with requestId ^5%s^1 Was Called by ^5%s^1 but does not exist."):format(eventName, invoker))
|
||||
end
|
||||
|
||||
local returnCb = function(...)
|
||||
TriggerServerEvent("esx:clientCallback", requestId, invoker, ...)
|
||||
end
|
||||
local callback = self.storage[eventName].cb
|
||||
|
||||
self:Execute(callback, requestId, returnCb, ...)
|
||||
end
|
||||
|
||||
-- =============================================
|
||||
-- MARK: ESX Functions
|
||||
-- =============================================
|
||||
|
||||
---@param eventName string
|
||||
---@param callback function
|
||||
---@param ... any
|
||||
---@return nil
|
||||
function ESX.TriggerServerCallback(eventName, callback, ...)
|
||||
local invokingResource = GetInvokingResource()
|
||||
local invoker = (invokingResource and invokingResource ~= "unknown") and invokingResource or "es_extended"
|
||||
|
||||
Callbacks:Trigger(eventName, callback, invoker, ...)
|
||||
end
|
||||
|
||||
---@param eventName string
|
||||
---@param ... any
|
||||
---@return ...
|
||||
function ESX.AwaitServerCallback(eventName, ...)
|
||||
local invokingResource = GetInvokingResource()
|
||||
local invoker = (invokingResource and invokingResource ~= "unknown") and invokingResource or "es_extended"
|
||||
|
||||
local p = Callbacks:Trigger(eventName, false, invoker, ...)
|
||||
if not p then return end
|
||||
|
||||
-- if the server callback takes longer than 15 seconds to respond, reject the promise
|
||||
SetTimeout(15000, function()
|
||||
if p.state == "pending" then
|
||||
p:reject("Server Callback Timed Out")
|
||||
end
|
||||
end)
|
||||
|
||||
Citizen.Await(p)
|
||||
|
||||
return table.unpack(p.value)
|
||||
end
|
||||
|
||||
function ESX.RegisterClientCallback(eventName, callback)
|
||||
local invokingResource = GetInvokingResource()
|
||||
local invoker = (invokingResource and invokingResource ~= "Unknown") and invokingResource or "es_extended"
|
||||
|
||||
Callbacks:Register(eventName, invoker, callback)
|
||||
end
|
||||
|
||||
---@param eventName string
|
||||
---@return boolean
|
||||
function ESX.DoesClientCallbackExist(eventName)
|
||||
return Callbacks.storage[eventName] ~= nil
|
||||
end
|
||||
|
||||
-- =============================================
|
||||
-- MARK: Events
|
||||
-- =============================================
|
||||
|
||||
ESX.SecureNetEvent("esx:serverCallback", function(...)
|
||||
Callbacks:ServerRecieve(...)
|
||||
end)
|
||||
|
||||
ESX.SecureNetEvent("esx:triggerClientCallback", function(...)
|
||||
Callbacks:ClientRecieve(...)
|
||||
end)
|
||||
|
||||
AddEventHandler("onResourceStop", function(resource)
|
||||
for k, v in pairs(Callbacks.storage) do
|
||||
if v.resource == resource then
|
||||
Callbacks.storage[k] = nil
|
||||
end
|
||||
end
|
||||
end)
|
||||
75
resources/[core]/es_extended/client/modules/death.lua
Normal file
75
resources/[core]/es_extended/client/modules/death.lua
Normal file
@@ -0,0 +1,75 @@
|
||||
Death = {}
|
||||
Death._index = Death
|
||||
|
||||
function Death:ResetValues()
|
||||
self.killerEntity = nil
|
||||
self.deathCause = nil
|
||||
self.killerId = nil
|
||||
self.killerServerId = nil
|
||||
end
|
||||
|
||||
function Death:ByPlayer()
|
||||
local victimCoords = GetEntityCoords(ESX.PlayerData.ped)
|
||||
local killerCoords = GetEntityCoords(self.killerEntity)
|
||||
local distance = #(victimCoords - killerCoords)
|
||||
|
||||
local data = {
|
||||
victimCoords = { x = ESX.Math.Round(victimCoords.x, 1), y = ESX.Math.Round(victimCoords.y, 1), z = ESX.Math.Round(victimCoords.z, 1) },
|
||||
killerCoords = { x = ESX.Math.Round(killerCoords.x, 1), y = ESX.Math.Round(killerCoords.y, 1), z = ESX.Math.Round(killerCoords.z, 1) },
|
||||
|
||||
killedByPlayer = true,
|
||||
deathCause = self.deathCause,
|
||||
distance = ESX.Math.Round(distance, 1),
|
||||
|
||||
killerServerId = self.killerServerId,
|
||||
killerClientId = self.killerId,
|
||||
}
|
||||
|
||||
TriggerEvent("esx:onPlayerDeath", data)
|
||||
TriggerServerEvent("esx:onPlayerDeath", data)
|
||||
end
|
||||
|
||||
function Death:Natural()
|
||||
local coords = GetEntityCoords(ESX.PlayerData.ped)
|
||||
|
||||
local data = {
|
||||
victimCoords = { x = ESX.Math.Round(coords.x, 1), y = ESX.Math.Round(coords.y, 1), z = ESX.Math.Round(coords.z, 1) },
|
||||
|
||||
killedByPlayer = false,
|
||||
deathCause = self.deathCause,
|
||||
}
|
||||
|
||||
TriggerEvent("esx:onPlayerDeath", data)
|
||||
TriggerServerEvent("esx:onPlayerDeath", data)
|
||||
end
|
||||
|
||||
function Death:Died()
|
||||
self.killerEntity = GetPedSourceOfDeath(ESX.PlayerData.ped)
|
||||
self.deathCause = GetPedCauseOfDeath(ESX.PlayerData.ped)
|
||||
self.killerId = NetworkGetPlayerIndexFromPed(self.killerEntity)
|
||||
self.killerServerId = GetPlayerServerId(self.killerId)
|
||||
|
||||
local isActive = NetworkIsPlayerActive(self.killerId)
|
||||
|
||||
if self.killerEntity ~= ESX.PlayerData.ped and self.killerId and isActive then
|
||||
self:ByPlayer()
|
||||
else
|
||||
self:Natural()
|
||||
end
|
||||
|
||||
self:ResetValues()
|
||||
end
|
||||
|
||||
AddEventHandler("esx:onPlayerSpawn", function()
|
||||
Citizen.CreateThreadNow(function()
|
||||
while not ESX.PlayerLoaded do Wait(0) end
|
||||
|
||||
while ESX.PlayerLoaded and not ESX.PlayerData.dead do
|
||||
if DoesEntityExist(ESX.PlayerData.ped) and (IsPedDeadOrDying(ESX.PlayerData.ped, true) or IsPedFatallyInjured(ESX.PlayerData.ped)) then
|
||||
Death:Died()
|
||||
break
|
||||
end
|
||||
Citizen.Wait(250)
|
||||
end
|
||||
end)
|
||||
end)
|
||||
615
resources/[core]/es_extended/client/modules/events.lua
Normal file
615
resources/[core]/es_extended/client/modules/events.lua
Normal file
@@ -0,0 +1,615 @@
|
||||
local pickups = {}
|
||||
|
||||
RegisterNetEvent("esx:requestModel", function(model)
|
||||
ESX.Streaming.RequestModel(model)
|
||||
end)
|
||||
|
||||
RegisterNetEvent("esx:playerLoaded", function(xPlayer, _, skin)
|
||||
ESX.PlayerData = xPlayer
|
||||
|
||||
if not Config.Multichar then
|
||||
ESX.SpawnPlayer(skin, ESX.PlayerData.coords, function()
|
||||
TriggerEvent("esx:onPlayerSpawn")
|
||||
TriggerEvent("esx:restoreLoadout")
|
||||
TriggerServerEvent("esx:onPlayerSpawn")
|
||||
TriggerEvent("esx:loadingScreenOff")
|
||||
ShutdownLoadingScreen()
|
||||
ShutdownLoadingScreenNui()
|
||||
end)
|
||||
end
|
||||
|
||||
while not DoesEntityExist(ESX.PlayerData.ped) do
|
||||
Wait(20)
|
||||
end
|
||||
|
||||
ESX.PlayerLoaded = true
|
||||
|
||||
local timer = GetGameTimer()
|
||||
while not HaveAllStreamingRequestsCompleted(ESX.PlayerData.ped) and (GetGameTimer() - timer) < 2000 do
|
||||
Wait(0)
|
||||
end
|
||||
|
||||
Adjustments:Load()
|
||||
|
||||
ClearPedTasksImmediately(ESX.PlayerData.ped)
|
||||
|
||||
if not Config.Multichar then
|
||||
Core.FreezePlayer(false)
|
||||
end
|
||||
|
||||
if IsScreenFadedOut() then
|
||||
DoScreenFadeIn(500)
|
||||
end
|
||||
|
||||
Actions:Init()
|
||||
StartPointsLoop()
|
||||
StartServerSyncLoops()
|
||||
NetworkSetLocalPlayerSyncLookAt(true)
|
||||
end)
|
||||
|
||||
local isFirstSpawn = true
|
||||
ESX.SecureNetEvent("esx:onPlayerLogout", function()
|
||||
ESX.PlayerLoaded = false
|
||||
isFirstSpawn = true
|
||||
end)
|
||||
|
||||
ESX.SecureNetEvent("esx:setMaxWeight", function(newMaxWeight)
|
||||
ESX.SetPlayerData("maxWeight", newMaxWeight)
|
||||
end)
|
||||
|
||||
ESX.SecureNetEvent("esx:setInventory", function(newInventory)
|
||||
ESX.SetPlayerData("inventory", newInventory)
|
||||
end)
|
||||
|
||||
local function onPlayerSpawn()
|
||||
ESX.SetPlayerData("ped", PlayerPedId())
|
||||
ESX.SetPlayerData("dead", false)
|
||||
end
|
||||
|
||||
AddEventHandler("playerSpawned", onPlayerSpawn)
|
||||
AddEventHandler("esx:onPlayerSpawn", function()
|
||||
onPlayerSpawn()
|
||||
|
||||
if isFirstSpawn then
|
||||
isFirstSpawn = false
|
||||
|
||||
if ESX.PlayerData.metadata.health and (ESX.PlayerData.metadata.health > 0 or Config.SaveDeathStatus) then
|
||||
SetEntityHealth(ESX.PlayerData.ped, ESX.PlayerData.metadata.health)
|
||||
end
|
||||
|
||||
if ESX.PlayerData.metadata.armor and ESX.PlayerData.metadata.armor > 0 then
|
||||
SetPedArmour(ESX.PlayerData.ped, ESX.PlayerData.metadata.armor)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
AddEventHandler("esx:onPlayerDeath", function()
|
||||
ESX.SetPlayerData("ped", PlayerPedId())
|
||||
ESX.SetPlayerData("dead", true)
|
||||
end)
|
||||
|
||||
AddEventHandler("skinchanger:modelLoaded", function()
|
||||
while not ESX.PlayerLoaded do
|
||||
Wait(100)
|
||||
end
|
||||
TriggerEvent("esx:restoreLoadout")
|
||||
end)
|
||||
|
||||
AddEventHandler("esx:restoreLoadout", function()
|
||||
ESX.SetPlayerData("ped", PlayerPedId())
|
||||
|
||||
if not Config.CustomInventory then
|
||||
local ammoTypes = {}
|
||||
RemoveAllPedWeapons(ESX.PlayerData.ped, true)
|
||||
|
||||
for _, v in ipairs(ESX.PlayerData.loadout) do
|
||||
local weaponName = v.name
|
||||
local weaponHash = joaat(weaponName)
|
||||
|
||||
GiveWeaponToPed(ESX.PlayerData.ped, weaponHash, 0, false, false)
|
||||
SetPedWeaponTintIndex(ESX.PlayerData.ped, weaponHash, v.tintIndex)
|
||||
|
||||
local ammoType = GetPedAmmoTypeFromWeapon(ESX.PlayerData.ped, weaponHash)
|
||||
|
||||
for _, v2 in ipairs(v.components) do
|
||||
local componentHash = ESX.GetWeaponComponent(weaponName, v2).hash
|
||||
GiveWeaponComponentToPed(ESX.PlayerData.ped, weaponHash, componentHash)
|
||||
end
|
||||
|
||||
if not ammoTypes[ammoType] then
|
||||
AddAmmoToPed(ESX.PlayerData.ped, weaponHash, v.ammo)
|
||||
ammoTypes[ammoType] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
---@diagnostic disable-next-line: param-type-mismatch
|
||||
AddStateBagChangeHandler("VehicleProperties", nil, function(bagName, _, value)
|
||||
if not value then
|
||||
return
|
||||
end
|
||||
|
||||
bagName = bagName:gsub("entity:", "")
|
||||
local netId = tonumber(bagName)
|
||||
if not netId then
|
||||
error("Tried to set vehicle properties with invalid netId")
|
||||
return
|
||||
end
|
||||
|
||||
local tries = 0
|
||||
|
||||
while not NetworkDoesEntityExistWithNetworkId(netId) do
|
||||
Wait(200)
|
||||
tries = tries + 1
|
||||
if tries > 20 then
|
||||
return error(("Invalid entity - ^5%s^7!"):format(netId))
|
||||
end
|
||||
end
|
||||
|
||||
local vehicle = NetToVeh(netId)
|
||||
|
||||
if NetworkGetEntityOwner(vehicle) ~= ESX.playerId then
|
||||
return
|
||||
end
|
||||
|
||||
ESX.Game.SetVehicleProperties(vehicle, value)
|
||||
end)
|
||||
|
||||
ESX.SecureNetEvent("esx:setAccountMoney", function(account)
|
||||
for i = 1, #ESX.PlayerData.accounts do
|
||||
if ESX.PlayerData.accounts[i].name == account.name then
|
||||
ESX.PlayerData.accounts[i] = account
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
ESX.SetPlayerData("accounts", ESX.PlayerData.accounts)
|
||||
end)
|
||||
|
||||
if not Config.CustomInventory then
|
||||
ESX.SecureNetEvent("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
|
||||
end)
|
||||
|
||||
ESX.SecureNetEvent("esx:removeInventoryItem", function(item, count, showNotification)
|
||||
for i = 1, #ESX.PlayerData.inventory do
|
||||
if ESX.PlayerData.inventory[i].name == item then
|
||||
ESX.UI.ShowInventoryItemNotification(false, ESX.PlayerData.inventory[i].label, ESX.PlayerData.inventory[i].count - count)
|
||||
ESX.PlayerData.inventory[i].count = count
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if showNotification then
|
||||
ESX.UI.ShowInventoryItemNotification(false, item, count)
|
||||
end
|
||||
end)
|
||||
|
||||
ESX.SecureNetEvent("esx:addLoadoutItem", function(weaponName, weaponLabel, ammo)
|
||||
table.insert(ESX.PlayerData.loadout, {
|
||||
name = weaponName,
|
||||
ammo = ammo,
|
||||
label = weaponLabel,
|
||||
components = {},
|
||||
tintIndex = 0,
|
||||
})
|
||||
end)
|
||||
|
||||
ESX.SecureNetEvent("esx:removeLoadoutItem", function(weaponName, weaponLabel)
|
||||
for i = 1, #ESX.PlayerData.loadout do
|
||||
if ESX.PlayerData.loadout[i].name == weaponName then
|
||||
table.remove(ESX.PlayerData.loadout, i)
|
||||
break
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
RegisterNetEvent("esx:addWeapon", function()
|
||||
error("event ^5'esx:addWeapon'^1 Has Been Removed. Please use ^5xPlayer.addWeapon^1 Instead!")
|
||||
end)
|
||||
|
||||
|
||||
RegisterNetEvent("esx:addWeaponComponent", function()
|
||||
error("event ^5'esx:addWeaponComponent'^1 Has Been Removed. Please use ^5xPlayer.addWeaponComponent^1 Instead!")
|
||||
end)
|
||||
|
||||
RegisterNetEvent("esx:setWeaponAmmo", function()
|
||||
error("event ^5'esx:setWeaponAmmo'^1 Has Been Removed. Please use ^5xPlayer.addWeaponAmmo^1 Instead!")
|
||||
end)
|
||||
|
||||
ESX.SecureNetEvent("esx:setWeaponTint", function(weapon, weaponTintIndex)
|
||||
SetPedWeaponTintIndex(ESX.PlayerData.ped, joaat(weapon), weaponTintIndex)
|
||||
end)
|
||||
|
||||
RegisterNetEvent("esx:removeWeapon", function()
|
||||
error("event ^5'esx:removeWeapon'^1 Has Been Removed. Please use ^5xPlayer.removeWeapon^1 Instead!")
|
||||
end)
|
||||
|
||||
ESX.SecureNetEvent("esx:removeWeaponComponent", function(weapon, weaponComponent)
|
||||
local componentHash = ESX.GetWeaponComponent(weapon, weaponComponent).hash
|
||||
RemoveWeaponComponentFromPed(ESX.PlayerData.ped, joaat(weapon), componentHash)
|
||||
end)
|
||||
end
|
||||
|
||||
ESX.SecureNetEvent("esx:setJob", function(Job)
|
||||
ESX.SetPlayerData("job", Job)
|
||||
end)
|
||||
|
||||
ESX.SecureNetEvent("esx:setGroup", function(group)
|
||||
ESX.SetPlayerData("group", group)
|
||||
end)
|
||||
|
||||
if not Config.CustomInventory then
|
||||
ESX.SecureNetEvent("esx:createPickup", function(pickupId, label, coords, itemType, 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 = coords,
|
||||
}
|
||||
end
|
||||
|
||||
if itemType == "item_weapon" then
|
||||
local weaponHash = joaat(name)
|
||||
ESX.Streaming.RequestWeaponAsset(weaponHash)
|
||||
local pickupObject = CreateWeaponObject(weaponHash, 50, coords.x, coords.y, coords.z, true, 1.0, 0)
|
||||
SetWeaponObjectTintIndex(pickupObject, tintIndex)
|
||||
|
||||
for _, v in ipairs(components) do
|
||||
local component = ESX.GetWeaponComponent(name, v)
|
||||
if component then
|
||||
GiveWeaponComponentToWeaponObject(pickupObject, component.hash)
|
||||
end
|
||||
end
|
||||
|
||||
setObjectProperties(pickupObject)
|
||||
else
|
||||
ESX.Game.SpawnLocalObject("prop_money_bag_01", coords, setObjectProperties)
|
||||
end
|
||||
end)
|
||||
|
||||
ESX.SecureNetEvent("esx:createMissingPickups", function(missingPickups)
|
||||
for pickupId, pickup in pairs(missingPickups) do
|
||||
TriggerEvent("esx:createPickup", pickupId, pickup.label, vector3(pickup.coords.x, pickup.coords.y, pickup.coords.z - 1.0), pickup.type, pickup.name, pickup.components, pickup.tintIndex)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
ESX.SecureNetEvent("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)
|
||||
|
||||
if not Config.CustomInventory then
|
||||
ESX.SecureNetEvent("esx:removePickup", function(pickupId)
|
||||
if pickups[pickupId] and pickups[pickupId].obj then
|
||||
ESX.Game.DeleteObject(pickups[pickupId].obj)
|
||||
pickups[pickupId] = nil
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function StartServerSyncLoops()
|
||||
if Config.CustomInventory then return end
|
||||
|
||||
local currentWeapon = {
|
||||
---@type number
|
||||
---@diagnostic disable-next-line: assign-type-mismatch
|
||||
hash = `WEAPON_UNARMED`,
|
||||
ammo = 0,
|
||||
}
|
||||
|
||||
local function updateCurrentWeaponAmmo(weaponName)
|
||||
local newAmmo = GetAmmoInPedWeapon(ESX.PlayerData.ped, currentWeapon.hash)
|
||||
|
||||
if newAmmo ~= currentWeapon.ammo then
|
||||
currentWeapon.ammo = newAmmo
|
||||
TriggerServerEvent("esx:updateWeaponAmmo", weaponName, newAmmo)
|
||||
end
|
||||
end
|
||||
|
||||
CreateThread(function()
|
||||
while ESX.PlayerLoaded do
|
||||
currentWeapon.hash = GetSelectedPedWeapon(ESX.PlayerData.ped)
|
||||
|
||||
if currentWeapon.hash ~= `WEAPON_UNARMED` then
|
||||
local weaponConfig = ESX.GetWeaponFromHash(currentWeapon.hash)
|
||||
|
||||
if weaponConfig then
|
||||
currentWeapon.ammo = GetAmmoInPedWeapon(ESX.PlayerData.ped, currentWeapon.hash)
|
||||
|
||||
while GetSelectedPedWeapon(ESX.PlayerData.ped) == currentWeapon.hash do
|
||||
updateCurrentWeaponAmmo(weaponConfig.name)
|
||||
Wait(1000)
|
||||
end
|
||||
|
||||
updateCurrentWeaponAmmo(weaponConfig.name)
|
||||
end
|
||||
end
|
||||
Wait(250)
|
||||
end
|
||||
end)
|
||||
|
||||
CreateThread(function()
|
||||
local PARACHUTE_OPENING <const> = 1
|
||||
local PARACHUTE_OPEN <const> = 2
|
||||
|
||||
while ESX.PlayerLoaded do
|
||||
local parachuteState = GetPedParachuteState(ESX.PlayerData.ped)
|
||||
|
||||
if parachuteState == PARACHUTE_OPENING or parachuteState == PARACHUTE_OPEN then
|
||||
TriggerServerEvent("esx:updateWeaponAmmo", "GADGET_PARACHUTE", 0)
|
||||
|
||||
while GetPedParachuteState(ESX.PlayerData.ped) ~= -1 do Wait(1000) end
|
||||
end
|
||||
Wait(500)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
if not Config.CustomInventory then
|
||||
CreateThread(function()
|
||||
while true do
|
||||
local Sleep = 1500
|
||||
local playerCoords = GetEntityCoords(ESX.PlayerData.ped)
|
||||
local _, closestDistance = ESX.Game.GetClosestPlayer(playerCoords)
|
||||
|
||||
for pickupId, pickup in pairs(pickups) do
|
||||
local distance = #(playerCoords - pickup.coords)
|
||||
|
||||
if distance < 5 then
|
||||
Sleep = 0
|
||||
local label = pickup.label
|
||||
|
||||
if distance < 1 then
|
||||
if IsControlJustReleased(0, 38) then
|
||||
if IsPedOnFoot(ESX.PlayerData.ped) 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(ESX.PlayerData.ped, dict, anim, 8.0, 1.0, 1000, 16, 0.0, false, false, false)
|
||||
RemoveAnimDict(dict)
|
||||
Wait(1000)
|
||||
|
||||
TriggerServerEvent("esx:onPickup", pickupId)
|
||||
PlaySoundFrontend(-1, "PICK_UP", "HUD_FRONTEND_DEFAULT_SOUNDSET", false)
|
||||
end
|
||||
end
|
||||
|
||||
label = ("%s~n~%s"):format(label, TranslateCap("threw_pickup_prompt"))
|
||||
end
|
||||
|
||||
local textCoords = pickup.coords + vector3(0.0, 0.0, 0.25)
|
||||
ESX.Game.Utils.DrawText3D(textCoords, label, 1.2, 1)
|
||||
elseif pickup.inRange then
|
||||
pickup.inRange = false
|
||||
end
|
||||
end
|
||||
Wait(Sleep)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
----- Admin commands from esx_adminplus
|
||||
RegisterNetEvent("esx:tpm", function()
|
||||
local GetEntityCoords = GetEntityCoords
|
||||
local GetGroundZFor_3dCoord = GetGroundZFor_3dCoord
|
||||
local GetFirstBlipInfoId = GetFirstBlipInfoId
|
||||
local DoesBlipExist = DoesBlipExist
|
||||
local DoScreenFadeOut = DoScreenFadeOut
|
||||
local GetBlipInfoIdCoord = GetBlipInfoIdCoord
|
||||
local GetVehiclePedIsIn = GetVehiclePedIsIn
|
||||
|
||||
ESX.TriggerServerCallback("esx:isUserAdmin", function(admin)
|
||||
if not admin then
|
||||
return
|
||||
end
|
||||
local blipMarker = GetFirstBlipInfoId(8)
|
||||
if not DoesBlipExist(blipMarker) then
|
||||
ESX.ShowNotification(TranslateCap("tpm_nowaypoint"), "error")
|
||||
return "marker"
|
||||
end
|
||||
|
||||
-- Fade screen to hide how clients get teleported.
|
||||
DoScreenFadeOut(650)
|
||||
while not IsScreenFadedOut() do
|
||||
Wait(0)
|
||||
end
|
||||
|
||||
local ped, coords = ESX.PlayerData.ped, GetBlipInfoIdCoord(blipMarker)
|
||||
local vehicle = GetVehiclePedIsIn(ped, false)
|
||||
local oldCoords = GetEntityCoords(ped)
|
||||
|
||||
-- Unpack coords instead of having to unpack them while iterating.
|
||||
-- 825.0 seems to be the max a player can reach while 0.0 being the lowest.
|
||||
local x, y, groundZ, Z_START = coords["x"], coords["y"], 850.0, 950.0
|
||||
local found = false
|
||||
FreezeEntityPosition(vehicle > 0 and vehicle or ped, true)
|
||||
|
||||
for i = Z_START, 0, -25.0 do
|
||||
local z = i
|
||||
if (i % 2) ~= 0 then
|
||||
z = Z_START - i
|
||||
end
|
||||
|
||||
NewLoadSceneStart(x, y, z, x, y, z, 50.0, 0)
|
||||
local curTime = GetGameTimer()
|
||||
while IsNetworkLoadingScene() do
|
||||
if GetGameTimer() - curTime > 1000 then
|
||||
break
|
||||
end
|
||||
Wait(0)
|
||||
end
|
||||
NewLoadSceneStop()
|
||||
SetPedCoordsKeepVehicle(ped, x, y, z)
|
||||
|
||||
while not HasCollisionLoadedAroundEntity(ped) do
|
||||
RequestCollisionAtCoord(x, y, z)
|
||||
if GetGameTimer() - curTime > 1000 then
|
||||
break
|
||||
end
|
||||
Wait(0)
|
||||
end
|
||||
|
||||
-- Get ground coord. As mentioned in the natives, this only works if the client is in render distance.
|
||||
found, groundZ = GetGroundZFor_3dCoord(x, y, z, false)
|
||||
if found then
|
||||
Wait(0)
|
||||
SetPedCoordsKeepVehicle(ped, x, y, groundZ)
|
||||
break
|
||||
end
|
||||
Wait(0)
|
||||
end
|
||||
|
||||
-- Remove black screen once the loop has ended.
|
||||
DoScreenFadeIn(650)
|
||||
FreezeEntityPosition(vehicle > 0 and vehicle or ped, false)
|
||||
|
||||
if not found then
|
||||
-- If we can't find the coords, set the coords to the old ones.
|
||||
-- We don't unpack them before since they aren't in a loop and only called once.
|
||||
SetPedCoordsKeepVehicle(ped, oldCoords["x"], oldCoords["y"], oldCoords["z"] - 1.0)
|
||||
ESX.ShowNotification(TranslateCap("tpm_success"), "success")
|
||||
end
|
||||
|
||||
-- If Z coord was found, set coords in found coords.
|
||||
SetPedCoordsKeepVehicle(ped, x, y, groundZ)
|
||||
ESX.ShowNotification(TranslateCap("tpm_success"), "success")
|
||||
end)
|
||||
end)
|
||||
|
||||
local noclip = false
|
||||
local noclip_pos = vector3(0, 0, 70)
|
||||
local heading = 0
|
||||
|
||||
local function noclipThread()
|
||||
while noclip do
|
||||
SetEntityCoordsNoOffset(ESX.PlayerData.ped, noclip_pos.x, noclip_pos.y, noclip_pos.z, false, false, true)
|
||||
|
||||
if IsControlPressed(1, 34) then
|
||||
heading = heading + 1.5
|
||||
if heading > 360 then
|
||||
heading = 0
|
||||
end
|
||||
|
||||
SetEntityHeading(ESX.PlayerData.ped, heading)
|
||||
end
|
||||
|
||||
if IsControlPressed(1, 9) then
|
||||
heading = heading - 1.5
|
||||
if heading < 0 then
|
||||
heading = 360
|
||||
end
|
||||
|
||||
SetEntityHeading(ESX.PlayerData.ped, heading)
|
||||
end
|
||||
|
||||
if IsControlPressed(1, 8) then
|
||||
noclip_pos = GetOffsetFromEntityInWorldCoords(ESX.PlayerData.ped, 0.0, 1.0, 0.0)
|
||||
end
|
||||
|
||||
if IsControlPressed(1, 32) then
|
||||
noclip_pos = GetOffsetFromEntityInWorldCoords(ESX.PlayerData.ped, 0.0, -1.0, 0.0)
|
||||
end
|
||||
|
||||
if IsControlPressed(1, 27) then
|
||||
noclip_pos = GetOffsetFromEntityInWorldCoords(ESX.PlayerData.ped, 0.0, 0.0, 1.0)
|
||||
end
|
||||
|
||||
if IsControlPressed(1, 173) then
|
||||
noclip_pos = GetOffsetFromEntityInWorldCoords(ESX.PlayerData.ped, 0.0, 0.0, -1.0)
|
||||
end
|
||||
Wait(0)
|
||||
end
|
||||
end
|
||||
|
||||
RegisterNetEvent("esx:noclip", function()
|
||||
ESX.TriggerServerCallback("esx:isUserAdmin", function(admin)
|
||||
if not admin then
|
||||
return
|
||||
end
|
||||
|
||||
if not noclip then
|
||||
noclip_pos = GetEntityCoords(ESX.PlayerData.ped, false)
|
||||
heading = GetEntityHeading(ESX.PlayerData.ped)
|
||||
end
|
||||
|
||||
noclip = not noclip
|
||||
if noclip then
|
||||
CreateThread(noclipThread)
|
||||
end
|
||||
|
||||
if noclip then
|
||||
ESX.ShowNotification(TranslateCap("noclip_message", Translate("enabled")), "success")
|
||||
else
|
||||
ESX.ShowNotification(TranslateCap("noclip_message", Translate("disabled")), "error")
|
||||
end
|
||||
end)
|
||||
end)
|
||||
|
||||
RegisterNetEvent("esx:killPlayer", function()
|
||||
SetEntityHealth(ESX.PlayerData.ped, 0)
|
||||
end)
|
||||
|
||||
RegisterNetEvent("esx:repairPedVehicle", function()
|
||||
local ped = ESX.PlayerData.ped
|
||||
local vehicle = GetVehiclePedIsIn(ped, false)
|
||||
SetVehicleEngineHealth(vehicle, 1000)
|
||||
SetVehicleEngineOn(vehicle, true, true, false)
|
||||
SetVehicleFixed(vehicle)
|
||||
SetVehicleDirtLevel(vehicle, 0)
|
||||
end)
|
||||
|
||||
RegisterNetEvent("esx:freezePlayer", function(input)
|
||||
if input == "freeze" then
|
||||
SetEntityCollision(ESX.PlayerData.ped, false, false)
|
||||
FreezeEntityPosition(ESX.PlayerData.ped, true)
|
||||
SetPlayerInvincible(ESX.playerId, true)
|
||||
elseif input == "unfreeze" then
|
||||
SetEntityCollision(ESX.PlayerData.ped, true, true)
|
||||
FreezeEntityPosition(ESX.PlayerData.ped, false)
|
||||
SetPlayerInvincible(ESX.playerId, false)
|
||||
end
|
||||
end)
|
||||
|
||||
ESX.RegisterClientCallback("esx:GetVehicleType", function(cb, model)
|
||||
cb(ESX.GetVehicleTypeClient(model))
|
||||
end)
|
||||
|
||||
ESX.SecureNetEvent('esx:updatePlayerData', function(key, val)
|
||||
ESX.SetPlayerData(key, val)
|
||||
end)
|
||||
|
||||
---@param command string
|
||||
ESX.SecureNetEvent("esx:executeCommand", function(command)
|
||||
ExecuteCommand(command)
|
||||
end)
|
||||
|
||||
AddEventHandler("onResourceStop", function(resource)
|
||||
if Core.Events[resource] then
|
||||
for i = 1, #Core.Events[resource] do
|
||||
RemoveEventHandler(Core.Events[resource][i])
|
||||
end
|
||||
end
|
||||
end)
|
||||
38
resources/[core]/es_extended/client/modules/interactions.lua
Normal file
38
resources/[core]/es_extended/client/modules/interactions.lua
Normal file
@@ -0,0 +1,38 @@
|
||||
local interactions = {}
|
||||
local pressedInteractions = {}
|
||||
|
||||
function ESX.RemoveInteraction(name)
|
||||
if not interactions[name] then return end
|
||||
interactions[name] = nil
|
||||
end
|
||||
|
||||
ESX.RegisterInteraction = function(name, onPress, condition)
|
||||
interactions[name] = {
|
||||
condition = condition or function() return true end,
|
||||
onPress = onPress,
|
||||
creator = GetInvokingResource() or "es_extended"
|
||||
}
|
||||
end
|
||||
|
||||
function ESX.GetInteractKey()
|
||||
local hash = joaat('esx_interact') | 0x80000000
|
||||
return GetControlInstructionalButton(0, hash, true):sub(3)
|
||||
end
|
||||
|
||||
ESX.RegisterInput("esx_interact", "Interact", "keyboard", "e", function()
|
||||
for _, interaction in pairs(interactions) do
|
||||
local success, result = pcall(interaction.condition)
|
||||
if success and result then
|
||||
pressedInteractions[#pressedInteractions+1] = interaction
|
||||
interaction.onPress()
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
AddEventHandler("onResourceStop", function(resource)
|
||||
for name, interaction in pairs(interactions) do
|
||||
if interaction.creator == resource then
|
||||
interactions[name] = nil
|
||||
end
|
||||
end
|
||||
end)
|
||||
57
resources/[core]/es_extended/client/modules/npwd.lua
Normal file
57
resources/[core]/es_extended/client/modules/npwd.lua
Normal file
@@ -0,0 +1,57 @@
|
||||
local npwd = GetResourceState("npwd"):find("start") and exports.npwd or nil
|
||||
|
||||
local function checkPhone()
|
||||
if not npwd then
|
||||
return
|
||||
end
|
||||
|
||||
local phoneItem <const> = ESX.SearchInventory("phone")
|
||||
npwd:setPhoneDisabled((phoneItem and phoneItem.count or 0) <= 0)
|
||||
end
|
||||
|
||||
RegisterNetEvent("esx:playerLoaded", checkPhone)
|
||||
|
||||
AddEventHandler("onClientResourceStart", function(resource)
|
||||
if resource ~= "npwd" then
|
||||
return
|
||||
end
|
||||
|
||||
npwd = GetResourceState("npwd"):find("start") and exports.npwd or nil
|
||||
|
||||
if ESX.PlayerLoaded then
|
||||
checkPhone()
|
||||
end
|
||||
end)
|
||||
|
||||
AddEventHandler("onClientResourceStop", function(resource)
|
||||
if resource == "npwd" then
|
||||
npwd = nil
|
||||
end
|
||||
end)
|
||||
|
||||
ESX.SecureNetEvent("esx:onPlayerLogout", function()
|
||||
if not npwd then
|
||||
return
|
||||
end
|
||||
|
||||
npwd:setPhoneVisible(false)
|
||||
npwd:setPhoneDisabled(true)
|
||||
end)
|
||||
|
||||
ESX.SecureNetEvent("esx:removeInventoryItem", function(item, count)
|
||||
if not npwd then
|
||||
return
|
||||
end
|
||||
|
||||
if item == "phone" and count == 0 then
|
||||
npwd:setPhoneDisabled(true)
|
||||
end
|
||||
end)
|
||||
|
||||
ESX.SecureNetEvent("esx:addInventoryItem", function(item)
|
||||
if not npwd or item ~= "phone" then
|
||||
return
|
||||
end
|
||||
|
||||
npwd:setPhoneDisabled(false)
|
||||
end)
|
||||
54
resources/[core]/es_extended/client/modules/points.lua
Normal file
54
resources/[core]/es_extended/client/modules/points.lua
Normal file
@@ -0,0 +1,54 @@
|
||||
local points = {}
|
||||
|
||||
function ESX.CreatePointInternal(coords, distance, hidden, enter, leave)
|
||||
local point = {
|
||||
coords = coords,
|
||||
distance = distance,
|
||||
hidden = hidden,
|
||||
enter = enter,
|
||||
leave = leave,
|
||||
resource = GetInvokingResource()
|
||||
}
|
||||
local handle = ESX.Table.SizeOf(points) + 1
|
||||
points[handle] = point
|
||||
return handle
|
||||
end
|
||||
|
||||
function ESX.RemovePointInternal(handle)
|
||||
points[handle] = nil
|
||||
end
|
||||
|
||||
function ESX.HidePointInternal(handle, hidden)
|
||||
if points[handle] then
|
||||
points[handle].hidden = hidden
|
||||
end
|
||||
end
|
||||
|
||||
function StartPointsLoop()
|
||||
CreateThread(function()
|
||||
while true do
|
||||
local coords = GetEntityCoords(ESX.PlayerData.ped)
|
||||
for handle, point in pairs(points) do
|
||||
if not point.hidden and #(coords - point.coords) <= point.distance then
|
||||
if not point.nearby then
|
||||
points[handle].nearby = true
|
||||
points[handle].enter()
|
||||
end
|
||||
elseif point.nearby then
|
||||
points[handle].nearby = false
|
||||
points[handle].leave()
|
||||
end
|
||||
end
|
||||
Wait(500)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
AddEventHandler('onResourceStop', function(resource)
|
||||
for handle, point in pairs(points) do
|
||||
if point.resource == resource then
|
||||
points[handle] = nil
|
||||
end
|
||||
end
|
||||
end)
|
||||
99
resources/[core]/es_extended/client/modules/scaleform.lua
Normal file
99
resources/[core]/es_extended/client/modules/scaleform.lua
Normal file
@@ -0,0 +1,99 @@
|
||||
ESX.Scaleform = {}
|
||||
ESX.Scaleform.Utils = {}
|
||||
|
||||
function ESX.Scaleform.ShowFreemodeMessage(title, msg, sec)
|
||||
local scaleform = ESX.Scaleform.Utils.RunMethod("MP_BIG_MESSAGE_FREEMODE", "SHOW_SHARD_WASTED_MP_MESSAGE", false, title, msg)
|
||||
|
||||
local endTime = GetGameTimer() + (sec * 1000)
|
||||
while GetGameTimer() < endTime do
|
||||
Wait(0)
|
||||
DrawScaleformMovieFullscreen(scaleform, 255, 255, 255, 255, 0)
|
||||
end
|
||||
|
||||
SetScaleformMovieAsNoLongerNeeded(scaleform)
|
||||
end
|
||||
|
||||
function ESX.Scaleform.ShowBreakingNews(title, msg, bottom, sec)
|
||||
local scaleform = ESX.Scaleform.Utils.RunMethod("BREAKING_NEWS", "SET_TEXT", false, msg, bottom)
|
||||
ESX.Scaleform.Utils.RunMethod(scaleform, "SET_SCROLL_TEXT", false, 0, 0, title)
|
||||
ESX.Scaleform.Utils.RunMethod(scaleform, "DISPLAY_SCROLL_TEXT", false, 0, 0)
|
||||
|
||||
local endTime = GetGameTimer() + (sec * 1000)
|
||||
while GetGameTimer() < endTime do
|
||||
Wait(0)
|
||||
DrawScaleformMovieFullscreen(scaleform, 255, 255, 255, 255, 0)
|
||||
end
|
||||
|
||||
SetScaleformMovieAsNoLongerNeeded(scaleform)
|
||||
end
|
||||
|
||||
function ESX.Scaleform.ShowPopupWarning(title, msg, bottom, sec)
|
||||
local scaleform = ESX.Scaleform.Utils.RunMethod("POPUP_WARNING", "SHOW_POPUP_WARNING", false, 500.0, title, msg, bottom, true)
|
||||
|
||||
local endTime = GetGameTimer() + (sec * 1000)
|
||||
while GetGameTimer() < endTime do
|
||||
Wait(0)
|
||||
DrawScaleformMovieFullscreen(scaleform, 255, 255, 255, 255, 0)
|
||||
end
|
||||
|
||||
SetScaleformMovieAsNoLongerNeeded(scaleform)
|
||||
end
|
||||
|
||||
function ESX.Scaleform.ShowTrafficMovie(sec)
|
||||
local scaleform = ESX.Scaleform.Utils.RunMethod("TRAFFIC_CAM", "PLAY_CAM_MOVIE", false)
|
||||
|
||||
local endTime = GetGameTimer() + (sec * 1000)
|
||||
while GetGameTimer() < endTime do
|
||||
Wait(0)
|
||||
DrawScaleformMovieFullscreen(scaleform, 255, 255, 255, 255, 0)
|
||||
end
|
||||
|
||||
SetScaleformMovieAsNoLongerNeeded(scaleform)
|
||||
end
|
||||
|
||||
function ESX.Scaleform.Utils.RequestScaleformMovie(movie)
|
||||
local scaleform = RequestScaleformMovie(movie)
|
||||
|
||||
while not HasScaleformMovieLoaded(scaleform) do
|
||||
Wait(0)
|
||||
end
|
||||
|
||||
return scaleform
|
||||
end
|
||||
|
||||
--- Executes a method on a scaleform movie with optional arguments and return value.
|
||||
--- The caller is responsible for disposing of the scaleform using `SetScaleformMovieAsNoLongerNeeded`.
|
||||
---@param scaleform number|string # Scaleform handle or name to request the scaleform movie
|
||||
---@param methodName string # The method name to call on the scaleform
|
||||
---@param returnValue? boolean # Whether to return the value from the method
|
||||
---@param ... number|string|boolean # Arguments to pass to the method
|
||||
---@return number, number? # The scaleform handle, and the return value if `returnValue` is true
|
||||
function ESX.Scaleform.Utils.RunMethod(scaleform, methodName, returnValue, ...)
|
||||
scaleform = type(scaleform) == "number" and scaleform or ESX.Scaleform.Utils.RequestScaleformMovie(scaleform)
|
||||
BeginScaleformMovieMethod(scaleform, methodName)
|
||||
|
||||
local args = { ... }
|
||||
for _, arg in ipairs(args) do
|
||||
local typeArg = type(arg)
|
||||
|
||||
if typeArg == "number" then
|
||||
if math.type(arg) == "float" then
|
||||
ScaleformMovieMethodAddParamFloat(arg)
|
||||
else
|
||||
ScaleformMovieMethodAddParamInt(arg)
|
||||
end
|
||||
elseif typeArg == "string" then
|
||||
ScaleformMovieMethodAddParamTextureNameString(arg)
|
||||
elseif typeArg == "boolean" then
|
||||
ScaleformMovieMethodAddParamBool(arg)
|
||||
end
|
||||
end
|
||||
|
||||
if returnValue then
|
||||
return scaleform, EndScaleformMovieMethodReturnValue()
|
||||
end
|
||||
|
||||
EndScaleformMovieMethod()
|
||||
|
||||
return scaleform
|
||||
end
|
||||
70
resources/[core]/es_extended/client/modules/streaming.lua
Normal file
70
resources/[core]/es_extended/client/modules/streaming.lua
Normal file
@@ -0,0 +1,70 @@
|
||||
ESX.Streaming = {}
|
||||
|
||||
---@param modelHash number | string
|
||||
---@param cb? function
|
||||
---@return number | nil
|
||||
function ESX.Streaming.RequestModel(modelHash, cb)
|
||||
modelHash = type(modelHash) == "number" and modelHash or joaat(modelHash)
|
||||
|
||||
if not IsModelInCdimage(modelHash) then return end
|
||||
|
||||
RequestModel(modelHash)
|
||||
while not HasModelLoaded(modelHash) do Wait(500) end
|
||||
|
||||
return cb and cb(modelHash) or modelHash
|
||||
end
|
||||
|
||||
---@param textureDict string
|
||||
---@param cb? function
|
||||
---@return string | nil
|
||||
function ESX.Streaming.RequestStreamedTextureDict(textureDict, cb)
|
||||
RequestStreamedTextureDict(textureDict, false)
|
||||
|
||||
while not HasStreamedTextureDictLoaded(textureDict) do Wait(500) end
|
||||
|
||||
return cb and cb(textureDict) or textureDict
|
||||
end
|
||||
|
||||
---@param assetName string
|
||||
---@param cb? function
|
||||
---@return string | nil
|
||||
function ESX.Streaming.RequestNamedPtfxAsset(assetName, cb)
|
||||
RequestNamedPtfxAsset(assetName)
|
||||
|
||||
while not HasNamedPtfxAssetLoaded(assetName) do Wait(500) end
|
||||
|
||||
return cb and cb(assetName) or assetName
|
||||
end
|
||||
|
||||
---@param animSet string
|
||||
---@param cb? function
|
||||
---@return string | nil
|
||||
function ESX.Streaming.RequestAnimSet(animSet, cb)
|
||||
RequestAnimSet(animSet)
|
||||
|
||||
while not HasAnimSetLoaded(animSet) do Wait(500) end
|
||||
|
||||
return cb and cb(animSet) or animSet
|
||||
end
|
||||
|
||||
---@param animDict string
|
||||
---@param cb? function
|
||||
---@return string | nil
|
||||
function ESX.Streaming.RequestAnimDict(animDict, cb)
|
||||
RequestAnimDict(animDict)
|
||||
|
||||
while not HasAnimDictLoaded(animDict) do Wait(500) end
|
||||
|
||||
return cb and cb(animDict) or animDict
|
||||
end
|
||||
|
||||
---@param weaponHash number | string
|
||||
---@param cb? function
|
||||
---@return string | number | nil
|
||||
function ESX.Streaming.RequestWeaponAsset(weaponHash, cb)
|
||||
RequestWeaponAsset(weaponHash, 31, 0)
|
||||
|
||||
while not HasWeaponAssetLoaded(weaponHash) do Wait(500) end
|
||||
|
||||
return cb and cb(weaponHash) or weaponHash
|
||||
end
|
||||
14
resources/[core]/es_extended/client/modules/wrapper.lua
Normal file
14
resources/[core]/es_extended/client/modules/wrapper.lua
Normal file
@@ -0,0 +1,14 @@
|
||||
local Chunks = {}
|
||||
|
||||
RegisterNUICallback("__chunk", function(data, cb)
|
||||
Chunks[data.id] = Chunks[data.id] or ""
|
||||
Chunks[data.id] = Chunks[data.id] .. data.chunk
|
||||
|
||||
if data["end"] then
|
||||
local msg = json.decode(Chunks[data.id])
|
||||
TriggerEvent(GetCurrentResourceName() .. ":message:" .. data.__type, msg)
|
||||
Chunks[data.id] = nil
|
||||
end
|
||||
|
||||
cb("")
|
||||
end)
|
||||
Reference in New Issue
Block a user