structura foldere
mutat kq- folders in un singur folder [kq]
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
if not Config.Debug then return end
|
||||
|
||||
Debug('`gizmo` debug command initialized')
|
||||
RegisterCommand('gizmo', function(source, args, raw)
|
||||
currentlyInGarage = 'Pillbox Hill Garage'
|
||||
decorate:open()
|
||||
end)
|
||||
@@ -0,0 +1,213 @@
|
||||
if Config.Framework ~= 'esx' then
|
||||
return
|
||||
end
|
||||
|
||||
ESX = exports['es_extended']:getSharedObject()
|
||||
|
||||
RegisterNetEvent('esx:playerLoaded')
|
||||
AddEventHandler('esx:playerLoaded', function(playerData)
|
||||
PlayerData = playerData
|
||||
Debug('player loaded', json.encode(playerData))
|
||||
end)
|
||||
|
||||
CreateThread(function()
|
||||
PlayerData = GetPlayerData()
|
||||
Debug('init playerData')
|
||||
end)
|
||||
|
||||
RegisterNetEvent('esx:setJob', function(jobData)
|
||||
PlayerData.job = jobData
|
||||
end)
|
||||
|
||||
function TriggerServerCallback(name, cb, ...)
|
||||
ESX.TriggerServerCallback(name, cb, ...)
|
||||
end
|
||||
|
||||
function GetPlayerData()
|
||||
return ESX.GetPlayerData()
|
||||
end
|
||||
|
||||
function GetPlayers()
|
||||
return ESX.Game.GetPlayers()
|
||||
end
|
||||
|
||||
function GetPlayerIdentifier()
|
||||
return GetPlayerData().identifier
|
||||
end
|
||||
|
||||
function GetJobName()
|
||||
return PlayerData?.job?.name or 'unemployed'
|
||||
end
|
||||
|
||||
function GetJobGrade()
|
||||
return PlayerData?.job?.grade or 0
|
||||
end
|
||||
|
||||
local hasGang = GetResourceState('qs-gangs') == 'started'
|
||||
|
||||
Gang = nil
|
||||
|
||||
if hasGang then
|
||||
RegisterNetEvent('gangs:setGang', function(gang)
|
||||
Gang = gang
|
||||
end)
|
||||
end
|
||||
|
||||
function GetGang()
|
||||
if not hasGang then
|
||||
return {
|
||||
name = '',
|
||||
grades = {}
|
||||
}
|
||||
end
|
||||
if Gang then
|
||||
return Gang
|
||||
end
|
||||
local gang = exports['qs-gangs']:GetGang()
|
||||
Gang = gang
|
||||
if not gang then
|
||||
return {
|
||||
name = '',
|
||||
grades = {}
|
||||
}
|
||||
end
|
||||
return gang
|
||||
end
|
||||
|
||||
function DrawMarkerZone(x, y, z)
|
||||
DrawMarker(1, x, y, z, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 4.0, 4.0, 0.8, 255, 255, 255, 150, false, false, false, true, false, false, false)
|
||||
end
|
||||
|
||||
function SpawnGiveVehicle(model, generatedPlate, playerID, playerName, vehicleType, addcommand)
|
||||
local playerPed = cache.ped
|
||||
local coords = GetEntityCoords(playerPed)
|
||||
|
||||
ESX.Game.SpawnVehicle(model, coords, 0.0, function(vehicle)
|
||||
if DoesEntityExist(vehicle) then
|
||||
local carExist = true
|
||||
SetEntityVisible(vehicle, false)
|
||||
SetEntityCollision(vehicle, false)
|
||||
|
||||
local newPlate = generatedPlate
|
||||
local vehicleProps = ESX.Game.GetVehicleProperties(vehicle)
|
||||
vehicleProps.plate = newPlate
|
||||
TriggerServerEvent('advancedgarages:server:setVehicle', vehicleProps, model, playerID, vehicleType, addcommand)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function SpawnVehicleEvents(vehicle, plate)
|
||||
if GetResourceState(Config.Framework .. '-wheelstancer') == 'started' then
|
||||
-- You can ignore this, it only works with tuff-wheelstancer
|
||||
TriggerServerCallback('advancedgarages:server:GetStanceValues', function(stance_value)
|
||||
if stance_value ~= nil then
|
||||
Wait(500)
|
||||
local veh = cache.vehicle
|
||||
TriggerServerEvent('Stancer_sv:LoadStanceValues', stance_value, VehToNet(veh))
|
||||
end
|
||||
end, plate)
|
||||
end
|
||||
-- You can add your events here when the vehicle spawns
|
||||
end
|
||||
|
||||
function GetVehiclePropertiesFramework(vehicle)
|
||||
return ESX.Game.GetVehicleProperties(vehicle)
|
||||
end
|
||||
|
||||
function SetVehiclePropertiesFramework(vehicle, props)
|
||||
ESX.Game.SetVehicleProperties(vehicle, props)
|
||||
end
|
||||
|
||||
function ToggleHud(show)
|
||||
if GetResourceState('qs-interface') == 'started' then
|
||||
exports['qs-interface']:ToggleHud(show)
|
||||
end
|
||||
end
|
||||
|
||||
function Notification(msg, type)
|
||||
SendReactMessage('notification', {
|
||||
msg = msg,
|
||||
type = type
|
||||
})
|
||||
-- if GetResourceState('qs-interface') == 'started' then
|
||||
-- if type == 'info' then
|
||||
-- exports['qs-interface']:AddNotify(msg, 'Inform', 2500, 'fas fa-file')
|
||||
-- elseif type == 'error' then
|
||||
-- exports['qs-interface']:AddNotify(msg, 'Error', 2500, 'fas fa-bug')
|
||||
-- elseif type == 'success' then
|
||||
-- exports['qs-interface']:AddNotify(msg, 'Success', 2500, 'fas fa-thumbs-up')
|
||||
-- end
|
||||
-- return
|
||||
-- end
|
||||
|
||||
-- if type == 'info' then
|
||||
-- lib.notify({
|
||||
-- title = 'Garages',
|
||||
-- description = msg,
|
||||
-- type = 'info'
|
||||
-- })
|
||||
-- elseif type == 'error' then
|
||||
-- lib.notify({
|
||||
-- title = 'Garages',
|
||||
-- description = msg,
|
||||
-- type = 'error'
|
||||
-- })
|
||||
-- elseif type == 'success' then
|
||||
-- lib.notify({
|
||||
-- title = 'Garages',
|
||||
-- description = msg,
|
||||
-- type = 'success'
|
||||
-- })
|
||||
-- end
|
||||
end
|
||||
|
||||
function ShowHelpNotification(msg, thisFrame, beep, duration)
|
||||
AddTextEntry('HelpNotification', msg)
|
||||
|
||||
if thisFrame then
|
||||
DisplayHelpTextThisFrame('HelpNotification', false)
|
||||
else
|
||||
if beep == nil then
|
||||
beep = true
|
||||
end
|
||||
BeginTextCommandDisplayHelp('HelpNotification')
|
||||
EndTextCommandDisplayHelp(0, false, beep, duration or -1)
|
||||
end
|
||||
end
|
||||
|
||||
local texts = {}
|
||||
if GetResourceState('qs-textui') == 'started' then
|
||||
function DrawText3D(x, y, z, text, id, key, theme)
|
||||
local _id = key
|
||||
if not texts[_id] then
|
||||
CreateThread(function()
|
||||
texts[_id] = 5
|
||||
while texts[_id] > 0 do
|
||||
texts[_id] = texts[_id] - 1
|
||||
Wait(0)
|
||||
end
|
||||
texts[_id] = nil
|
||||
exports['qs-textui']:DeleteDrawText3D(id)
|
||||
Debug('Deleted text', id)
|
||||
end)
|
||||
Debug('Created text', id)
|
||||
TriggerEvent('textui:DrawText3D', x, y, z, text, id, key, theme)
|
||||
end
|
||||
texts[_id] = 5
|
||||
end
|
||||
else
|
||||
function DrawText3D(x, y, z, text)
|
||||
SetTextScale(0.35, 0.35)
|
||||
SetTextFont(4)
|
||||
SetTextProportional(1)
|
||||
SetTextColour(255, 255, 255, 215)
|
||||
SetTextEntry('STRING')
|
||||
SetTextCentre(true)
|
||||
AddTextComponentString(text)
|
||||
SetDrawOrigin(x, y, z, 0)
|
||||
DrawText(0.0, 0.0)
|
||||
local factor = text:len() / 370
|
||||
DrawRect(0.0, 0.0 + 0.0125, 0.017 + factor, 0.03, 0, 0, 0, 75)
|
||||
ClearDrawOrigin()
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,207 @@
|
||||
if Config.Framework ~= 'qb' then
|
||||
return
|
||||
end
|
||||
|
||||
QBCore = exports['qb-core']:GetCoreObject()
|
||||
|
||||
RegisterNetEvent('QBCore:Client:OnPlayerLoaded')
|
||||
AddEventHandler('QBCore:Client:OnPlayerLoaded', function()
|
||||
PlayerData = GetPlayerData()
|
||||
end)
|
||||
|
||||
RegisterNetEvent('QBCore:Client:OnJobUpdate', function(jobData)
|
||||
PlayerData.job = jobData
|
||||
end)
|
||||
|
||||
CreateThread(function()
|
||||
PlayerData = GetPlayerData()
|
||||
end)
|
||||
|
||||
function TriggerServerCallback(name, cb, ...)
|
||||
QBCore.Functions.TriggerCallback(name, cb, ...)
|
||||
end
|
||||
|
||||
function GetPlayerData()
|
||||
return QBCore.Functions.GetPlayerData()
|
||||
end
|
||||
|
||||
function GetPlayers()
|
||||
return QBCore.Functions.GetPlayers()
|
||||
end
|
||||
|
||||
function GetPlayerIdentifier()
|
||||
return GetPlayerData().citizenid
|
||||
end
|
||||
|
||||
function GetJobName()
|
||||
return PlayerData?.job?.name or 'unemployed'
|
||||
end
|
||||
|
||||
function GetJobGrade()
|
||||
return PlayerData?.job?.grade?.level or 0
|
||||
end
|
||||
|
||||
local hasGang = GetResourceState('qs-gangs') == 'started'
|
||||
Gang = nil
|
||||
|
||||
if hasGang then
|
||||
RegisterNetEvent('gangs:setGang', function(gang)
|
||||
Gang = gang
|
||||
end)
|
||||
end
|
||||
|
||||
function GetGang()
|
||||
if not hasGang then
|
||||
return {
|
||||
name = '',
|
||||
grades = {}
|
||||
}
|
||||
end
|
||||
if Gang then
|
||||
return Gang
|
||||
end
|
||||
local gang = exports['qs-gangs']:GetGang()
|
||||
Gang = gang
|
||||
if not gang then
|
||||
return {
|
||||
name = '',
|
||||
grades = {}
|
||||
}
|
||||
end
|
||||
return gang
|
||||
end
|
||||
|
||||
function DrawMarkerZone(x, y, z)
|
||||
DrawMarker(1, x, y, z, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 4.0, 4.0, 0.8, 255, 255, 255, 150, false, false, false, true, false, false, false)
|
||||
end
|
||||
|
||||
function SpawnGiveVehicle(model, generatedPlate, playerID, playerName, vehicleType, addcommand)
|
||||
QBCore.Functions.SpawnVehicle(model, function(vehicle)
|
||||
if DoesEntityExist(vehicle) then
|
||||
local carExist = true
|
||||
SetEntityVisible(vehicle, false)
|
||||
SetEntityCollision(vehicle, false)
|
||||
|
||||
local newPlate = generatedPlate
|
||||
local vehicleProps = QBCore.Functions.GetVehicleProperties(vehicle)
|
||||
vehicleProps.plate = newPlate
|
||||
TriggerServerEvent('advancedgarages:server:setVehicle', vehicleProps, model, playerID, vehicleType, addcommand)
|
||||
end
|
||||
end, coords, true)
|
||||
end
|
||||
|
||||
function SpawnVehicleEvents(vehicle, plate)
|
||||
if GetResourceState(Config.Framework .. '-wheelstancer') == 'started' then
|
||||
-- You can ignore this, it only works with tuff-wheelstancer
|
||||
TriggerServerCallback('advancedgarages:server:GetStanceValues', function(stance_value)
|
||||
if stance_value ~= nil then
|
||||
Wait(500)
|
||||
local veh = cache.vehicle
|
||||
TriggerServerEvent('Stancer_sv:LoadStanceValues', stance_value, VehToNet(veh))
|
||||
end
|
||||
end, plate)
|
||||
end
|
||||
-- You can add your events here when the vehicle spawns
|
||||
end
|
||||
|
||||
function GetVehiclePropertiesFramework(vehicle)
|
||||
return QBCore.Functions.GetVehicleProperties(vehicle)
|
||||
end
|
||||
|
||||
function SetVehiclePropertiesFramework(vehicle, props)
|
||||
QBCore.Functions.SetVehicleProperties(vehicle, props)
|
||||
end
|
||||
|
||||
function ToggleHud(show)
|
||||
if GetResourceState('qs-interface') == 'started' then
|
||||
exports['qs-interface']:ToggleHud(show)
|
||||
end
|
||||
end
|
||||
|
||||
function Notification(msg, type)
|
||||
SendReactMessage('notification', {
|
||||
msg = msg,
|
||||
type = type
|
||||
})
|
||||
-- if GetResourceState('qs-interface') == 'started' then
|
||||
-- if type == 'info' then
|
||||
-- exports['qs-interface']:AddNotify(msg, 'Inform', 2500, 'fas fa-file')
|
||||
-- elseif type == 'error' then
|
||||
-- exports['qs-interface']:AddNotify(msg, 'Error', 2500, 'fas fa-bug')
|
||||
-- elseif type == 'success' then
|
||||
-- exports['qs-interface']:AddNotify(msg, 'Success', 2500, 'fas fa-thumbs-up')
|
||||
-- end
|
||||
-- return
|
||||
-- end
|
||||
|
||||
-- if type == 'info' then
|
||||
-- lib.notify({
|
||||
-- title = 'Garages',
|
||||
-- description = msg,
|
||||
-- type = 'info'
|
||||
-- })
|
||||
-- elseif type == 'error' then
|
||||
-- lib.notify({
|
||||
-- title = 'Garages',
|
||||
-- description = msg,
|
||||
-- type = 'error'
|
||||
-- })
|
||||
-- elseif type == 'success' then
|
||||
-- lib.notify({
|
||||
-- title = 'Garages',
|
||||
-- description = msg,
|
||||
-- type = 'success'
|
||||
-- })
|
||||
-- end
|
||||
end
|
||||
|
||||
function ShowHelpNotification(msg, thisFrame, beep, duration)
|
||||
AddTextEntry('HelpNotification', msg)
|
||||
|
||||
if thisFrame then
|
||||
DisplayHelpTextThisFrame('HelpNotification', false)
|
||||
else
|
||||
if beep == nil then
|
||||
beep = true
|
||||
end
|
||||
BeginTextCommandDisplayHelp('HelpNotification')
|
||||
EndTextCommandDisplayHelp(0, false, beep, duration or -1)
|
||||
end
|
||||
end
|
||||
|
||||
local texts = {}
|
||||
if GetResourceState('qs-textui') == 'started' then
|
||||
function DrawText3D(x, y, z, text, id, key, theme)
|
||||
local _id = key
|
||||
if not texts[_id] then
|
||||
CreateThread(function()
|
||||
texts[_id] = 5
|
||||
while texts[_id] > 0 do
|
||||
texts[_id] = texts[_id] - 1
|
||||
Wait(0)
|
||||
end
|
||||
texts[_id] = nil
|
||||
exports['qs-textui']:DeleteDrawText3D(id)
|
||||
Debug('Deleted text', id)
|
||||
end)
|
||||
Debug('Created text', id)
|
||||
TriggerEvent('textui:DrawText3D', x, y, z, text, id, key, theme)
|
||||
end
|
||||
texts[_id] = 5
|
||||
end
|
||||
else
|
||||
function DrawText3D(x, y, z, text)
|
||||
SetTextScale(0.35, 0.35)
|
||||
SetTextFont(4)
|
||||
SetTextProportional(1)
|
||||
SetTextColour(255, 255, 255, 215)
|
||||
SetTextEntry('STRING')
|
||||
SetTextCentre(true)
|
||||
AddTextComponentString(text)
|
||||
SetDrawOrigin(x, y, z, 0)
|
||||
DrawText(0.0, 0.0)
|
||||
local factor = text:len() / 370
|
||||
DrawRect(0.0, 0.0 + 0.0125, 0.017 + factor, 0.03, 0, 0, 0, 75)
|
||||
ClearDrawOrigin()
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,18 @@
|
||||
if Config.Fuel ~= 'BigDaddy-Fuel' then
|
||||
return
|
||||
end
|
||||
|
||||
function SetFuel(vehicle, fuelLevel)
|
||||
local success, error = pcall(function()
|
||||
exports['BigDaddy-Fuel']:SetFuel(vehicle, fuelLevel)
|
||||
end)
|
||||
|
||||
if not success then
|
||||
Debug('You did not configure your fuel system and it is set to 100.0 in fuel, check in Config.Fuel')
|
||||
return 100.0
|
||||
end
|
||||
end
|
||||
|
||||
function GetFuel(vehicle)
|
||||
return exports['BigDaddy-Fuel']:GetFuel(vehicle)
|
||||
end
|
||||
@@ -0,0 +1,18 @@
|
||||
if Config.Fuel ~= 'LegacyFuel' then
|
||||
return 100.0
|
||||
end
|
||||
|
||||
function SetFuel(vehicle, fuelLevel)
|
||||
local success, error = pcall(function()
|
||||
exports['LegacyFuel']:SetFuel(vehicle, fuelLevel)
|
||||
end)
|
||||
|
||||
if not success then
|
||||
Debug('You did not configure your fuel system and it is set to 100.0 in fuel, check in Config.Fuel')
|
||||
return 100.0
|
||||
end
|
||||
end
|
||||
|
||||
function GetFuel(vehicle)
|
||||
return exports['LegacyFuel']:GetFuel(vehicle)
|
||||
end
|
||||
@@ -0,0 +1,18 @@
|
||||
if Config.Fuel ~= 'cdn-fuel' then
|
||||
return
|
||||
end
|
||||
|
||||
function SetFuel(vehicle, fuelLevel)
|
||||
local success, error = pcall(function()
|
||||
exports['cdn-fuel']:SetFuel(vehicle, fuelLevel)
|
||||
end)
|
||||
|
||||
if not success then
|
||||
Debug('You did not configure your fuel system and it is set to 100.0 in fuel, check in Config.Fuel')
|
||||
return 100.0
|
||||
end
|
||||
end
|
||||
|
||||
function GetFuel(vehicle)
|
||||
return exports['cdn-fuel']:GetFuel(vehicle)
|
||||
end
|
||||
@@ -0,0 +1,18 @@
|
||||
if Config.Fuel ~= 'esx-sna-fuel' then
|
||||
return
|
||||
end
|
||||
|
||||
function SetFuel(vehicle, fuelLevel)
|
||||
local success, error = pcall(function()
|
||||
exports['esx-sna-fuel']:SetFuel(vehicle, fuelLevel)
|
||||
end)
|
||||
|
||||
if not success then
|
||||
Debug('You did not configure your fuel system and it is set to 100.0 in fuel, check in Config.Fuel')
|
||||
return 100.0
|
||||
end
|
||||
end
|
||||
|
||||
function GetFuel(vehicle)
|
||||
return exports['esx-sna-fuel']:GetFuel(vehicle)
|
||||
end
|
||||
@@ -0,0 +1,18 @@
|
||||
if Config.Fuel ~= 'lc_fuel' then
|
||||
return
|
||||
end
|
||||
|
||||
function SetFuel(vehicle, fuelLevel)
|
||||
local success, error = pcall(function()
|
||||
exports["lc_fuel"]:SetFuel(vehicle, fuelLevel)
|
||||
end)
|
||||
|
||||
if not success then
|
||||
Debug('You did not configure your fuel system and it is set to 100.0 in fuel, check in Config.Fuel')
|
||||
return 100.0
|
||||
end
|
||||
end
|
||||
|
||||
function GetFuel(vehicle)
|
||||
return exports["lc_fuel"]:GetFuel(vehicle)
|
||||
end
|
||||
@@ -0,0 +1,18 @@
|
||||
if Config.Fuel ~= 'lj-fuel' then
|
||||
return
|
||||
end
|
||||
|
||||
function SetFuel(vehicle, fuelLevel)
|
||||
local success, error = pcall(function()
|
||||
exports['lj-fuel']:SetFuel(vehicle, fuelLevel)
|
||||
end)
|
||||
|
||||
if not success then
|
||||
Debug('You did not configure your fuel system and it is set to 100.0 in fuel, check in Config.Fuel')
|
||||
return 100.0
|
||||
end
|
||||
end
|
||||
|
||||
function GetFuel(vehicle)
|
||||
return exports['lj-fuel']:GetFuel(vehicle)
|
||||
end
|
||||
@@ -0,0 +1,18 @@
|
||||
if Config.Fuel ~= 'okokGasStation' then
|
||||
return 100.0
|
||||
end
|
||||
|
||||
function SetFuel(vehicle, fuelLevel)
|
||||
local success, error = pcall(function()
|
||||
exports['okokGasStation']:SetFuel(vehicle, fuelLevel)
|
||||
end)
|
||||
|
||||
if not success then
|
||||
Debug('You did not configure your fuel system and it is set to 100.0 in fuel, check in Config.Fuel')
|
||||
return 100.0
|
||||
end
|
||||
end
|
||||
|
||||
function GetFuel(vehicle)
|
||||
return exports['okokGasStation']:GetFuel(vehicle)
|
||||
end
|
||||
@@ -0,0 +1,11 @@
|
||||
if Config.Fuel ~= 'ox_fuel' then
|
||||
return
|
||||
end
|
||||
|
||||
function SetFuel(vehicle, fuelLevel)
|
||||
Entity(vehicle).state.fuel = fuelLevel
|
||||
end
|
||||
|
||||
function GetFuel(vehicle)
|
||||
return Entity(vehicle).state.fuel
|
||||
end
|
||||
@@ -0,0 +1,18 @@
|
||||
if Config.Fuel ~= 'ps-fuel' then
|
||||
return
|
||||
end
|
||||
|
||||
function SetFuel(vehicle, fuelLevel)
|
||||
local success, error = pcall(function()
|
||||
exports['ps-fuel']:SetFuel(vehicle, fuelLevel)
|
||||
end)
|
||||
|
||||
if not success then
|
||||
Debug('You did not configure your fuel system and it is set to 100.0 in fuel, check in Config.Fuel')
|
||||
return 100.0
|
||||
end
|
||||
end
|
||||
|
||||
function GetFuel(vehicle)
|
||||
return exports['ps-fuel']:GetFuel(vehicle)
|
||||
end
|
||||
@@ -0,0 +1,18 @@
|
||||
if Config.Fuel ~= 'qs-fuelstations' then
|
||||
return
|
||||
end
|
||||
|
||||
function SetFuel(vehicle, fuelLevel)
|
||||
local success, error = pcall(function()
|
||||
exports['qs-fuelstations']:SetFuel(vehicle, fuelLevel)
|
||||
end)
|
||||
|
||||
if not success then
|
||||
Debug('You did not configure your fuel system and it is set to 100.0 in fuel, check in Config.Fuel')
|
||||
return 100.0
|
||||
end
|
||||
end
|
||||
|
||||
function GetFuel(vehicle)
|
||||
return exports['qs-fuelstations']:GetFuel(vehicle)
|
||||
end
|
||||
@@ -0,0 +1,18 @@
|
||||
if Config.Fuel ~= 'ti_fuel' then
|
||||
return
|
||||
end
|
||||
|
||||
function SetFuel(vehicle, fuelLevel)
|
||||
local success, error = pcall(function()
|
||||
exports['ti_fuel']:setFuel(vehicle, fuelLevel, 'RON91')
|
||||
end)
|
||||
|
||||
if not success then
|
||||
Debug('You did not configure your fuel system and it is set to 100.0 in fuel, check in Config.Fuel')
|
||||
return 100.0
|
||||
end
|
||||
end
|
||||
|
||||
function GetFuel(vehicle)
|
||||
return exports['ti_fuel']:getFuel(vehicle)
|
||||
end
|
||||
@@ -0,0 +1,11 @@
|
||||
if Config.Inventory ~= 'inventory' then
|
||||
return
|
||||
end
|
||||
|
||||
function openStash(customData, uniq)
|
||||
local data = customData or Config.DefaultStashData
|
||||
uniq = uniq or currentlyInGarage
|
||||
uniq = uniq:gsub('-', '_')
|
||||
local maxweight = data.maxweight or 10000
|
||||
TriggerEvent('inventory:openInventory', { type = 'stash', id = uniq, title = 'Stash_' .. uniq, weight = maxweight, delay = 100, save = true })
|
||||
end
|
||||
@@ -0,0 +1,15 @@
|
||||
if Config.Inventory ~= 'codem-inventory' then
|
||||
return
|
||||
end
|
||||
|
||||
function openStash(customData, uniq)
|
||||
local data = customData or Config.DefaultStashData
|
||||
uniq = uniq or currentlyInGarage
|
||||
uniq = tostring(uniq or 'garage'):gsub('-', '_')
|
||||
local name = 'stash_' .. uniq
|
||||
local maxweight = data.maxweight or 10000
|
||||
local slots = data.slots or 30
|
||||
|
||||
print('[INFO] Open stash CodeM:', name, 'MaxWeight:', maxweight, 'Slots:', slots)
|
||||
TriggerServerEvent('codem-inventory:server:openstash', name, slots, maxweight, name)
|
||||
end
|
||||
@@ -0,0 +1,10 @@
|
||||
if Config.Inventory ~= 'core_inventory' then
|
||||
return
|
||||
end
|
||||
|
||||
function openStash(customData, uniq)
|
||||
local data = customData or Config.DefaultStashData
|
||||
uniq = uniq or currentlyInGarage
|
||||
uniq = uniq:gsub('-', '_')
|
||||
TriggerServerEvent('core_inventory:server:openInventory', tostring(uniq):gsub(':', ''):gsub('#', ''):gsub(' ', ''), 'stash', nil, nil)
|
||||
end
|
||||
@@ -0,0 +1,10 @@
|
||||
if Config.Inventory ~= 'origen_inventory' then
|
||||
return
|
||||
end
|
||||
|
||||
function openStash(customData, uniq)
|
||||
local data = customData or Config.DefaultStashData
|
||||
uniq = uniq or currentlyInGarage
|
||||
uniq = uniq:gsub('-', '_')
|
||||
TriggerServerEvent('inventory:server:OpenInventory', 'stash', 'stash_house' .. uniq .. '', data)
|
||||
end
|
||||
@@ -0,0 +1,19 @@
|
||||
if Config.Inventory ~= 'ox_inventory' then
|
||||
return
|
||||
end
|
||||
|
||||
local ox_inventory = exports.ox_inventory
|
||||
|
||||
function openStash(customData, uniq)
|
||||
local data = customData or Config.DefaultStashData
|
||||
uniq = uniq or currentlyInGarage
|
||||
uniq = uniq:gsub('-', '_')
|
||||
uniq = uniq:gsub('-', '_')
|
||||
local maxweight = data.maxweight or 10000
|
||||
local slot = data.slots or 30
|
||||
if ox_inventory:openInventory('stash', uniq) == false then
|
||||
TriggerServerEvent('garages:ox:registerStash', uniq, slot, maxweight)
|
||||
ox_inventory:openInventory('stash', uniq)
|
||||
Debug('Ox Stash', 'Registering new stash', uniq)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,15 @@
|
||||
if Config.Inventory ~= 'ps-inventory' then
|
||||
return
|
||||
end
|
||||
|
||||
function openStash(customData, uniq)
|
||||
local data = customData or Config.DefaultStashData
|
||||
uniq = uniq or currentlyInGarage
|
||||
uniq = uniq:gsub('-', '_')
|
||||
TriggerServerEvent('inventory:server:OpenInventory', 'stash', uniq, data)
|
||||
TriggerEvent('inventory:client:SetCurrentStash', uniq)
|
||||
end
|
||||
|
||||
RegisterNetEvent('inventory:client:SetCurrentStash', function(stash)
|
||||
CurrentStash = stash
|
||||
end)
|
||||
@@ -0,0 +1,13 @@
|
||||
if Config.Inventory ~= 'qb-inventory' then
|
||||
return
|
||||
end
|
||||
|
||||
function openStash(customData, uniq)
|
||||
local data = customData or Config.DefaultStashData
|
||||
uniq = uniq or currentlyInGarage
|
||||
uniq = uniq:gsub('-', '_')
|
||||
-- if you use old qb-inventory version, uncomment here and remove 'housing:openStash' trigger.
|
||||
-- TriggerServerEvent('inventory:server:OpenInventory', 'stash', uniq, data)
|
||||
-- TriggerEvent('inventory:client:SetCurrentStash', uniq)
|
||||
TriggerServerEvent('garages:openStash', uniq, data)
|
||||
end
|
||||
@@ -0,0 +1,11 @@
|
||||
if Config.Inventory ~= 'qs-inventory' then
|
||||
return
|
||||
end
|
||||
|
||||
function openStash(customData, uniq)
|
||||
local data = customData or Config.DefaultStashData
|
||||
uniq = uniq or currentlyInGarage
|
||||
uniq = uniq:gsub('-', '_')
|
||||
TriggerServerEvent('inventory:server:OpenInventory', 'stash', uniq, data)
|
||||
TriggerEvent('inventory:client:SetCurrentStash', uniq)
|
||||
end
|
||||
@@ -0,0 +1,14 @@
|
||||
if Config.Inventory ~= 'tgiann-inventory' then
|
||||
return
|
||||
end
|
||||
|
||||
function openStash(customData, uniq)
|
||||
local data = customData or Config.DefaultStashData
|
||||
uniq = uniq or currentlyInGarage
|
||||
uniq = uniq:gsub('-', '_')
|
||||
local maxweight = data.maxweight or 10000
|
||||
exports['tgiann-inventory']:OpenInventory('stash', uniq, {
|
||||
maxweight = maxweight,
|
||||
slots = data.slots or 100,
|
||||
})
|
||||
end
|
||||
@@ -0,0 +1,243 @@
|
||||
if Config.Menu ~= 'esx_context' then
|
||||
return
|
||||
end
|
||||
|
||||
function OpenManagementMenu()
|
||||
local Elements = {
|
||||
{
|
||||
unselectable = true,
|
||||
title = 'Management',
|
||||
},
|
||||
{
|
||||
title = 'Give Key',
|
||||
name = 'givekey',
|
||||
},
|
||||
{
|
||||
title = 'Key Holders',
|
||||
name = 'keyholders',
|
||||
},
|
||||
{
|
||||
title = 'Sell Garage',
|
||||
name = 'sell',
|
||||
},
|
||||
}
|
||||
|
||||
ESX.OpenContext('right', Elements,
|
||||
function(menu, element)
|
||||
if element.name == 'givekey' then
|
||||
TriggerEvent('advancedgarages:openGiveKeyMenu')
|
||||
ESX.CloseContext()
|
||||
end
|
||||
if element.name == 'keyholders' then
|
||||
TriggerEvent('advancedgarages:openKeyHoldersMenu')
|
||||
ESX.CloseContext()
|
||||
end
|
||||
if element.name == 'sell' then
|
||||
TriggerEvent('advancedgarages:sellGarage')
|
||||
ESX.CloseContext()
|
||||
end
|
||||
end, function(menu)
|
||||
ESX.CloseContext()
|
||||
end)
|
||||
end
|
||||
|
||||
function openGiveKeyMenu(vehicleList)
|
||||
local Elements = {}
|
||||
table.insert(Elements, {
|
||||
unselectable = true,
|
||||
title = 'Give Key',
|
||||
})
|
||||
|
||||
for k, v in pairs(vehicleList) do
|
||||
table.insert(Elements, {
|
||||
title = 'Player: ' .. v.name.firstName .. ' ' .. v.name.lastName,
|
||||
name = 'givekey',
|
||||
data = {
|
||||
id = v.id,
|
||||
garage = ClosestGarage
|
||||
}
|
||||
})
|
||||
end
|
||||
|
||||
ESX.OpenContext('right', Elements, function(menu, element)
|
||||
if element.name == 'givekey' then
|
||||
local selectedData = element.data
|
||||
local data = {
|
||||
id = selectedData.id,
|
||||
garage = selectedData.garage
|
||||
}
|
||||
TriggerServerEvent('advancedgarages:giveKey', data)
|
||||
ESX.CloseContext()
|
||||
end
|
||||
end,
|
||||
function(menu)
|
||||
ESX.CloseContext()
|
||||
end)
|
||||
end
|
||||
|
||||
function openTakeKeyMenu()
|
||||
local Elements = {}
|
||||
local holders = lib.callback.await('advancedgarages:getGarageKeyHolders', false, ClosestGarage)
|
||||
if not holders or #holders == 0 then
|
||||
Notification(i18n.t('keyholders.empty_list'), 'info')
|
||||
return
|
||||
end
|
||||
|
||||
table.insert(Elements, {
|
||||
unselectable = true,
|
||||
title = 'Take Key',
|
||||
})
|
||||
|
||||
for k, v in pairs(holders) do
|
||||
table.insert(Elements, {
|
||||
title = 'Player: ' .. v.firstname .. ' ' .. v.lastname,
|
||||
name = 'keyholders',
|
||||
data = {
|
||||
id = v.identifier,
|
||||
garage = ClosestGarage
|
||||
}
|
||||
})
|
||||
end
|
||||
|
||||
ESX.OpenContext('right', Elements, function(menu, element)
|
||||
if element.name == 'keyholders' then
|
||||
local selectedData = element.data
|
||||
local data = {
|
||||
id = selectedData.id,
|
||||
garage = selectedData.garage
|
||||
}
|
||||
TriggerServerEvent('advancedgarages:takeKey', data)
|
||||
ESX.CloseContext()
|
||||
end
|
||||
end,
|
||||
function(menu)
|
||||
ESX.CloseContext()
|
||||
end)
|
||||
end
|
||||
|
||||
function HandleKeyboard(callback)
|
||||
local Elements = {
|
||||
{
|
||||
title = 'Set a Price',
|
||||
input = true,
|
||||
inputType = 'number',
|
||||
inputValue = 1,
|
||||
inputPlaceholder = 'Garage Price...',
|
||||
name = 'price',
|
||||
},
|
||||
{
|
||||
title = 'Continue',
|
||||
name = 'next',
|
||||
},
|
||||
}
|
||||
ESX.OpenContext('right', Elements, function(menu, element)
|
||||
local amount = menu.eles[1].inputValue
|
||||
if amount == 0 or amount == nil then return end
|
||||
if element.name == 'next' then
|
||||
ESX.CloseContext()
|
||||
callback(amount)
|
||||
end
|
||||
end, function(menu)
|
||||
ESX.CloseContext()
|
||||
end)
|
||||
end
|
||||
|
||||
function HandleGarageJob()
|
||||
local promise = promise.new()
|
||||
local Elements = {
|
||||
{
|
||||
title = 'Job Name (you can leave it blank for everyone)',
|
||||
input = true,
|
||||
inputType = 'text',
|
||||
inputValue = '',
|
||||
inputPlaceholder = 'Job Name...',
|
||||
name = 'Job Name',
|
||||
},
|
||||
{
|
||||
title = 'Continue',
|
||||
name = 'next',
|
||||
},
|
||||
}
|
||||
|
||||
ESX.OpenContext('right', Elements, function(menu, element)
|
||||
local jobName = menu.eles[1].inputValue
|
||||
if jobName == nil then
|
||||
return promise:resolve(false)
|
||||
end
|
||||
if element.name == 'next' then
|
||||
ESX.CloseContext()
|
||||
promise:resolve(jobName)
|
||||
end
|
||||
end, function(menu)
|
||||
ESX.CloseContext()
|
||||
end)
|
||||
return Citizen.Await(promise)
|
||||
end
|
||||
|
||||
function OpenRecoveryMenu(vehicleList)
|
||||
local Elements = {}
|
||||
table.insert(Elements, {
|
||||
unselectable = true,
|
||||
title = 'Recovery Vehicle (OUT)',
|
||||
})
|
||||
|
||||
for k, v in pairs(vehicleList) do
|
||||
table.insert(Elements, {
|
||||
title = v.plate,
|
||||
plate = v.plate,
|
||||
type = v.type,
|
||||
name = 'recovery',
|
||||
data = {
|
||||
plate = v.plate,
|
||||
type = v.type
|
||||
}
|
||||
})
|
||||
end
|
||||
|
||||
ESX.OpenContext('right', Elements, function(menu, element)
|
||||
if element.name == 'recovery' then
|
||||
local selectedData = element.data
|
||||
TriggerServerEvent('advancedgarages:RecoveryVehicle', selectedData)
|
||||
ESX.CloseContext()
|
||||
end
|
||||
end,
|
||||
function(menu)
|
||||
ESX.CloseContext()
|
||||
end)
|
||||
end
|
||||
|
||||
function OpenDeleteJobVehicleMenu(garage, job)
|
||||
local Elements = {}
|
||||
local vehicles = lib.callback.await('advancedgarages:getJobVehicles', false, garage, job)
|
||||
if not vehicles or #vehicles == 0 then
|
||||
Notification(i18n.t('keyholders.empty_out'), 'info')
|
||||
return
|
||||
end
|
||||
|
||||
table.insert(Elements, {
|
||||
unselectable = true,
|
||||
title = 'Delete work vehicles',
|
||||
})
|
||||
|
||||
|
||||
for k, v in pairs(vehicles) do
|
||||
table.insert(Elements, {
|
||||
title = v.plate,
|
||||
name = 'next',
|
||||
data = {
|
||||
plate = v.plate,
|
||||
garage = garage
|
||||
}
|
||||
})
|
||||
end
|
||||
|
||||
ESX.OpenContext('right', Elements, function(menu, element)
|
||||
if element.name == 'next' then
|
||||
local selectedData = element.data
|
||||
TriggerServerEvent('advancedgarages:deleteJobVehicle', selectedData)
|
||||
ESX.CloseContext()
|
||||
end
|
||||
end, function(menu)
|
||||
ESX.CloseContext()
|
||||
end)
|
||||
end
|
||||
@@ -0,0 +1,203 @@
|
||||
if Config.Menu ~= 'esx_menu_default' then
|
||||
return
|
||||
end
|
||||
|
||||
function OpenManagementMenu()
|
||||
local elementsList = {}
|
||||
|
||||
table.insert(elementsList, { label = 'Give Key', value = 'givekey' })
|
||||
table.insert(elementsList, { label = 'Key Holders', value = 'keyholders' })
|
||||
table.insert(elementsList, { label = 'Sell Garage', value = 'sell' })
|
||||
|
||||
ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'management', {
|
||||
title = 'Management',
|
||||
align = 'right',
|
||||
elements = elementsList
|
||||
}, function(data, menu)
|
||||
if data.current.value == 'givekey' then
|
||||
menu.close()
|
||||
TriggerEvent('advancedgarages:openGiveKeyMenu')
|
||||
end
|
||||
if data.current.value == 'keyholders' then
|
||||
menu.close()
|
||||
TriggerEvent('advancedgarages:openKeyHoldersMenu')
|
||||
end
|
||||
if data.current.value == 'sell' then
|
||||
menu.close()
|
||||
TriggerEvent('advancedgarages:sellGarage')
|
||||
end
|
||||
end, function(data, menu)
|
||||
menu.close()
|
||||
end)
|
||||
end
|
||||
|
||||
function openGiveKeyMenu(players)
|
||||
local elementsList = {}
|
||||
|
||||
for k, v in pairs(players) do
|
||||
table.insert(elementsList, {
|
||||
label = 'Player: ' .. v.name.firstName .. ' ' .. v.name.lastName,
|
||||
value = {
|
||||
id = v.id,
|
||||
garage = ClosestGarage
|
||||
}
|
||||
})
|
||||
end
|
||||
|
||||
ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'givekey', {
|
||||
title = 'Give Key',
|
||||
align = 'right',
|
||||
elements = elementsList
|
||||
}, function(data, menu)
|
||||
if data.current.value then
|
||||
menu.close()
|
||||
local selectedData = data.current.value
|
||||
local data = {
|
||||
id = selectedData.id,
|
||||
garage = selectedData.garage
|
||||
}
|
||||
TriggerServerEvent('advancedgarages:giveKey', data)
|
||||
end
|
||||
end, function(data, menu)
|
||||
menu.close()
|
||||
end)
|
||||
end
|
||||
|
||||
function openTakeKeyMenu()
|
||||
local elementsList = {}
|
||||
local holders = lib.callback.await('advancedgarages:getGarageKeyHolders', false, ClosestGarage)
|
||||
if not holders or #holders == 0 then
|
||||
Notification(i18n.t('keyholders.empty_list'), 'info')
|
||||
return
|
||||
end
|
||||
for k, v in pairs(holders) do
|
||||
table.insert(elementsList, {
|
||||
label = 'Player: ' .. v.firstname .. ' ' .. v.lastname,
|
||||
value = {
|
||||
id = v.identifier,
|
||||
garage = ClosestGarage
|
||||
}
|
||||
})
|
||||
end
|
||||
|
||||
ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'keyholders', {
|
||||
title = 'Recovery',
|
||||
align = 'right',
|
||||
elements = elementsList
|
||||
}, function(data, menu)
|
||||
if data.current.value then
|
||||
menu.close()
|
||||
local selectedData = data.current.value
|
||||
local data = {
|
||||
id = selectedData.id,
|
||||
garage = selectedData.garage
|
||||
}
|
||||
TriggerServerEvent('advancedgarages:takeKey', data)
|
||||
end
|
||||
end, function(data, menu)
|
||||
menu.close()
|
||||
end)
|
||||
end
|
||||
|
||||
function HandleKeyboard(callback)
|
||||
ESX.UI.Menu.Open('dialog', GetCurrentResourceName(), 'price',
|
||||
{
|
||||
title = ('Set a price')
|
||||
},
|
||||
function(data, menu)
|
||||
local amount = tonumber(data.value)
|
||||
if amount == nil then
|
||||
Notification('Invalid Amount', 'error')
|
||||
else
|
||||
menu.close()
|
||||
callback(amount)
|
||||
end
|
||||
end,
|
||||
function(data, menu)
|
||||
menu.close()
|
||||
end)
|
||||
end
|
||||
|
||||
function HandleGarageJob()
|
||||
local promise = promise.new()
|
||||
ESX.UI.Menu.Open('dialog', GetCurrentResourceName(), 'job',
|
||||
{
|
||||
title = ('Job Name (you can leave it blank for everyone)')
|
||||
},
|
||||
function(data, menu)
|
||||
local jobName = data.value
|
||||
if jobName == nil then
|
||||
menu.close()
|
||||
return promise:resolve(false)
|
||||
end
|
||||
|
||||
promise:resolve(jobName)
|
||||
menu.close()
|
||||
end,
|
||||
function(data, menu)
|
||||
menu.close()
|
||||
end)
|
||||
return Citizen.Await(promise)
|
||||
end
|
||||
|
||||
function OpenRecoveryMenu(vehicleList)
|
||||
local elementsList = {}
|
||||
|
||||
for k, v in pairs(vehicleList) do
|
||||
table.insert(elementsList, {
|
||||
label = v.plate,
|
||||
type = v.type,
|
||||
value = {
|
||||
plate = v.plate,
|
||||
type = v.type
|
||||
}
|
||||
})
|
||||
end
|
||||
|
||||
ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'recovery', {
|
||||
title = 'Recovery Vehicle (OUT)',
|
||||
align = 'right',
|
||||
elements = elementsList
|
||||
}, function(data, menu)
|
||||
if data.current.value then
|
||||
menu.close()
|
||||
local selectedData = data.current.value
|
||||
TriggerServerEvent('advancedgarages:RecoveryVehicle', selectedData)
|
||||
end
|
||||
end, function(data, menu)
|
||||
menu.close()
|
||||
end)
|
||||
end
|
||||
|
||||
function OpenDeleteJobVehicleMenu(garage, job)
|
||||
local elementsList = {}
|
||||
local vehicles = lib.callback.await('advancedgarages:getJobVehicles', false, garage, job)
|
||||
if not vehicles or #vehicles == 0 then
|
||||
Notification(i18n.t('keyholders.empty_out'), 'info')
|
||||
return
|
||||
end
|
||||
|
||||
for k, v in pairs(vehicles) do
|
||||
table.insert(elementsList, {
|
||||
label = v.plate,
|
||||
value = {
|
||||
plate = v.plate,
|
||||
garage = garage
|
||||
}
|
||||
})
|
||||
end
|
||||
|
||||
ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'deletejob', {
|
||||
title = 'Delete work vehicles',
|
||||
align = 'right',
|
||||
elements = elementsList
|
||||
}, function(data, menu)
|
||||
local selectedData = data.current.value
|
||||
if selectedData then
|
||||
TriggerServerEvent('advancedgarages:deleteJobVehicle', selectedData)
|
||||
menu.close()
|
||||
end
|
||||
end, function(data, menu)
|
||||
menu.close()
|
||||
end)
|
||||
end
|
||||
@@ -0,0 +1,145 @@
|
||||
if Config.Menu ~= 'nh-context' then
|
||||
return
|
||||
end
|
||||
|
||||
function OpenManagementMenu()
|
||||
TriggerEvent('nh-context:createMenu', {
|
||||
{
|
||||
header = 'Management',
|
||||
},
|
||||
{
|
||||
header = 'Give Key',
|
||||
event = 'advancedgarages:openGiveKeyMenu',
|
||||
},
|
||||
{
|
||||
header = 'Key Holders',
|
||||
event = 'advancedgarages:openKeyHoldersMenu',
|
||||
},
|
||||
{
|
||||
header = 'Sell Garage',
|
||||
event = 'advancedgarages:sellGarage',
|
||||
}
|
||||
})
|
||||
end
|
||||
|
||||
function openGiveKeyMenu(players)
|
||||
local Elements = {
|
||||
{
|
||||
header = 'Give Key',
|
||||
}
|
||||
}
|
||||
for k, v in pairs(players) do
|
||||
local data = {
|
||||
id = v.id,
|
||||
garage = ClosestGarage
|
||||
}
|
||||
table.insert(Elements, {
|
||||
header = 'Give Key',
|
||||
context = 'Player: ' .. v.name.firstName .. ' ' .. v.name.lastName,
|
||||
event = 'advancedgarages:giveKey',
|
||||
server = true,
|
||||
args = {
|
||||
data
|
||||
}
|
||||
})
|
||||
end
|
||||
TriggerEvent('nh-context:createMenu', Elements)
|
||||
end
|
||||
|
||||
function openTakeKeyMenu()
|
||||
local Elements = {
|
||||
{
|
||||
header = 'Take Key',
|
||||
}
|
||||
}
|
||||
local holders = lib.callback.await('advancedgarages:getGarageKeyHolders', false, ClosestGarage)
|
||||
if not holders or #holders == 0 then
|
||||
Notification(i18n.t('keyholders.empty_list'), 'info')
|
||||
return
|
||||
end
|
||||
for k, v in pairs(holders) do
|
||||
local data = {
|
||||
id = v.identifier,
|
||||
garage = ClosestGarage
|
||||
}
|
||||
table.insert(Elements, {
|
||||
header = 'Take Key',
|
||||
context = 'Player: ' .. v.firstname .. ' ' .. v.lastname,
|
||||
event = 'advancedgarages:takeKey',
|
||||
server = true,
|
||||
args = {
|
||||
data
|
||||
}
|
||||
})
|
||||
end
|
||||
TriggerEvent('nh-context:createMenu', Elements)
|
||||
end
|
||||
|
||||
function HandleKeyboard(callback)
|
||||
local keyboard, value = exports['nh-keyboard']:Keyboard({
|
||||
header = 'Set a Price',
|
||||
rows = { 'Price' }
|
||||
})
|
||||
if keyboard then
|
||||
callback(value)
|
||||
end
|
||||
end
|
||||
|
||||
function HandleGarageJob()
|
||||
local keyboard, value = exports['nh-keyboard']:Keyboard({
|
||||
header = 'Job Name (you can leave it blank for everyone)',
|
||||
rows = { 'Job Name' }
|
||||
})
|
||||
if keyboard then
|
||||
return value
|
||||
end
|
||||
end
|
||||
|
||||
function OpenRecoveryMenu(vehicleList)
|
||||
local menu = {}
|
||||
table.insert(menu, {
|
||||
header = 'Recovery Vehicle (OUT)'
|
||||
})
|
||||
for k, v in pairs(vehicleList) do
|
||||
table.insert(menu, {
|
||||
header = v.plate,
|
||||
event = 'advancedgarages:RecoveryVehicle',
|
||||
server = true,
|
||||
args = {
|
||||
v
|
||||
}
|
||||
})
|
||||
end
|
||||
TriggerEvent('nh-context:createMenu', menu)
|
||||
end
|
||||
|
||||
function OpenDeleteJobVehicleMenu(garage, job)
|
||||
local menu = {}
|
||||
local vehicles = lib.callback.await('advancedgarages:getJobVehicles', false, garage, job)
|
||||
|
||||
if not vehicles or #vehicles == 0 then
|
||||
Notification(i18n.t('keyholders.empty_out'), 'info')
|
||||
return
|
||||
end
|
||||
|
||||
table.insert(menu, {
|
||||
header = 'Delete work vehicles'
|
||||
})
|
||||
|
||||
for k, v in pairs(vehicles) do
|
||||
local data = {
|
||||
plate = v.plate,
|
||||
garage = garage
|
||||
}
|
||||
table.insert(menu, {
|
||||
header = v.plate,
|
||||
event = 'advancedgarages:deleteJobVehicle',
|
||||
server = true,
|
||||
args = {
|
||||
data
|
||||
}
|
||||
})
|
||||
end
|
||||
|
||||
TriggerEvent('nh-context:createMenu', menu)
|
||||
end
|
||||
@@ -0,0 +1,152 @@
|
||||
if Config.Menu ~= 'ox_lib' then
|
||||
return
|
||||
end
|
||||
|
||||
function OpenManagementMenu()
|
||||
local elements = {
|
||||
{
|
||||
title = 'Give Key',
|
||||
onSelect = function(args)
|
||||
TriggerEvent('advancedgarages:openGiveKeyMenu')
|
||||
end
|
||||
},
|
||||
{
|
||||
title = 'Key Holders',
|
||||
onSelect = function(args)
|
||||
TriggerEvent('advancedgarages:openKeyHoldersMenu')
|
||||
end
|
||||
},
|
||||
{
|
||||
title = 'Sell Garage',
|
||||
onSelect = function(args)
|
||||
TriggerEvent('advancedgarages:sellGarage')
|
||||
end
|
||||
}
|
||||
}
|
||||
lib.registerContext({
|
||||
id = 'management',
|
||||
title = 'Management',
|
||||
options = elements
|
||||
})
|
||||
lib.showContext('management')
|
||||
end
|
||||
|
||||
function openGiveKeyMenu(players)
|
||||
local elements = {}
|
||||
for k, v in pairs(players) do
|
||||
table.insert(elements, {
|
||||
title = 'Player: ' .. v.name.firstName .. ' ' .. v.name.lastName,
|
||||
onSelect = function(args)
|
||||
local data = {
|
||||
id = v.id,
|
||||
garage = ClosestGarage
|
||||
}
|
||||
TriggerServerEvent('advancedgarages:giveKey', data)
|
||||
end
|
||||
})
|
||||
end
|
||||
lib.registerContext({
|
||||
id = 'givekey',
|
||||
title = 'Give Keys',
|
||||
options = elements
|
||||
})
|
||||
lib.showContext('givekey')
|
||||
end
|
||||
|
||||
function openTakeKeyMenu()
|
||||
local elements = {}
|
||||
local holders = lib.callback.await('advancedgarages:getGarageKeyHolders', false, ClosestGarage)
|
||||
if not holders or #holders == 0 then
|
||||
Notification(i18n.t('keyholders.empty_list'), 'info')
|
||||
return
|
||||
end
|
||||
for k, v in pairs(holders) do
|
||||
table.insert(elements, {
|
||||
title = 'Player: ' .. v.firstname .. ' ' .. v.lastname,
|
||||
onSelect = function(args)
|
||||
local data = {
|
||||
id = v.identifier,
|
||||
garage = ClosestGarage
|
||||
}
|
||||
TriggerServerEvent('advancedgarages:takeKey', data)
|
||||
end
|
||||
})
|
||||
end
|
||||
lib.registerContext({
|
||||
id = 'keyholders',
|
||||
title = 'Key Holders',
|
||||
options = elements
|
||||
})
|
||||
lib.showContext('keyholders')
|
||||
end
|
||||
|
||||
function HandleKeyboard(callback)
|
||||
local input = lib.inputDialog('Set a Price', { 'Garage Price...' })
|
||||
|
||||
if not input then return end
|
||||
local price = tonumber(input[1])
|
||||
|
||||
if price then
|
||||
local amount = price
|
||||
if amount == nil then
|
||||
Notification('Invalid Amount', 'error')
|
||||
else
|
||||
if amount >= 0 then
|
||||
callback(amount)
|
||||
else
|
||||
Notification('Invalid Amount', 'error')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function HandleGarageJob()
|
||||
local input = lib.inputDialog('Job Name (you can leave it blank for everyone)', { 'Job Name' })
|
||||
if not input or input[1] == '' then return false end
|
||||
return input[1]
|
||||
end
|
||||
|
||||
function OpenRecoveryMenu(vehicleList)
|
||||
local menu = {}
|
||||
for k, v in pairs(vehicleList) do
|
||||
table.insert(menu, {
|
||||
title = v.plate,
|
||||
onSelect = function(args)
|
||||
TriggerServerEvent('advancedgarages:RecoveryVehicle', { plate = v.plate, type = v.type })
|
||||
end,
|
||||
})
|
||||
end
|
||||
lib.registerContext({
|
||||
id = 'recovery',
|
||||
title = 'Recovery Vehicle (OUT)',
|
||||
options = menu
|
||||
})
|
||||
lib.showContext('recovery')
|
||||
end
|
||||
|
||||
function OpenDeleteJobVehicleMenu(garage, job)
|
||||
local menu = {}
|
||||
local vehicles = lib.callback.await('advancedgarages:getJobVehicles', false, garage, job)
|
||||
if not vehicles or #vehicles == 0 then
|
||||
Notification(i18n.t('keyholders.empty_out'), 'info')
|
||||
return
|
||||
end
|
||||
for k, v in pairs(vehicles) do
|
||||
local data = {
|
||||
plate = v.plate,
|
||||
garage = garage
|
||||
}
|
||||
table.insert(menu, {
|
||||
title = v.plate,
|
||||
onSelect = function(args)
|
||||
TriggerServerEvent('advancedgarages:deleteJobVehicle', data)
|
||||
end,
|
||||
})
|
||||
end
|
||||
lib.registerContext({
|
||||
id = 'deletejobvehicle',
|
||||
title = 'Delete work vehicles',
|
||||
options = menu
|
||||
})
|
||||
lib.showContext('deletejobvehicle')
|
||||
end
|
||||
@@ -0,0 +1,176 @@
|
||||
if Config.Menu ~= 'qb-menu' then
|
||||
return
|
||||
end
|
||||
|
||||
function OpenManagementMenu()
|
||||
local elementsList = {
|
||||
{
|
||||
header = 'Management',
|
||||
isMenuHeader = true,
|
||||
},
|
||||
{
|
||||
header = 'Give Key',
|
||||
params = {
|
||||
event = 'advancedgarages:openGiveKeyMenu',
|
||||
}
|
||||
},
|
||||
{
|
||||
header = 'Key Holders',
|
||||
params = {
|
||||
event = 'advancedgarages:openKeyHoldersMenu',
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exports['qb-menu']:openMenu(elementsList)
|
||||
end
|
||||
|
||||
function openGiveKeyMenu(players)
|
||||
local elementsList = {}
|
||||
table.insert(elementsList, {
|
||||
header = 'Give Key',
|
||||
isMenuHeader = true,
|
||||
})
|
||||
for k, v in pairs(players) do
|
||||
table.insert(elementsList, {
|
||||
header = 'Player: ' .. v.name.firstName .. ' ' .. v.name.lastName,
|
||||
params = {
|
||||
isServer = true,
|
||||
event = 'advancedgarages:giveKey',
|
||||
args = {
|
||||
id = v.id,
|
||||
garage = ClosestGarage
|
||||
}
|
||||
}
|
||||
})
|
||||
end
|
||||
exports['qb-menu']:openMenu(elementsList)
|
||||
end
|
||||
|
||||
function openTakeKeyMenu()
|
||||
local elementsList = {}
|
||||
local holders = lib.callback.await('advancedgarages:getGarageKeyHolders', false, ClosestGarage)
|
||||
if not holders or #holders == 0 then
|
||||
Notification(i18n.t('keyholders.empty_list'), 'info')
|
||||
return
|
||||
end
|
||||
|
||||
table.insert(elementsList, {
|
||||
header = 'Take Key',
|
||||
isMenuHeader = true,
|
||||
})
|
||||
|
||||
for k, v in pairs(holders) do
|
||||
table.insert(elementsList, {
|
||||
header = 'Player: ' .. v.firstname .. ' ' .. v.lastname,
|
||||
params = {
|
||||
isServer = true,
|
||||
event = 'advancedgarages:takeKey',
|
||||
args = {
|
||||
id = v.identifier,
|
||||
garage = ClosestGarage
|
||||
}
|
||||
}
|
||||
})
|
||||
end
|
||||
exports['qb-menu']:openMenu(elementsList)
|
||||
end
|
||||
|
||||
function HandleKeyboard(callback)
|
||||
local dialog = exports['qb-input']:ShowInput({
|
||||
header = 'Set a Price',
|
||||
submitText = 'Continue',
|
||||
inputs = {
|
||||
{
|
||||
text = 'Garage Price...',
|
||||
name = 'price',
|
||||
type = 'number',
|
||||
isRequired = true,
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
if dialog ~= nil then
|
||||
for k, v in pairs(dialog) do
|
||||
callback(v)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function HandleGarageJob()
|
||||
local dialog = exports['qb-input']:ShowInput({
|
||||
header = 'Job Name (you can leave it blank for everyone)',
|
||||
submitText = 'Continue',
|
||||
inputs = {
|
||||
{
|
||||
text = 'Job Name...',
|
||||
name = 'Job public garage',
|
||||
type = 'text',
|
||||
isRequired = false,
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
if dialog ~= nil then
|
||||
for k, v in pairs(dialog) do
|
||||
if v and v ~= '' then
|
||||
return v
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function OpenRecoveryMenu(vehicleList)
|
||||
local elementsList = {}
|
||||
table.insert(elementsList, {
|
||||
header = 'Recovery Vehicle (OUT)',
|
||||
isMenuHeader = true,
|
||||
})
|
||||
|
||||
for k, v in pairs(vehicleList) do
|
||||
table.insert(elementsList, {
|
||||
header = v.plate,
|
||||
params = {
|
||||
isServer = true,
|
||||
event = 'advancedgarages:RecoveryVehicle',
|
||||
args = {
|
||||
plate = v.plate,
|
||||
type = v.type
|
||||
}
|
||||
}
|
||||
})
|
||||
end
|
||||
exports['qb-menu']:openMenu(elementsList)
|
||||
end
|
||||
|
||||
function OpenDeleteJobVehicleMenu(garage, job)
|
||||
local menu = {}
|
||||
local vehicles = lib.callback.await('advancedgarages:getJobVehicles', false, garage, job)
|
||||
|
||||
if not vehicles or #vehicles == 0 then
|
||||
Notification(i18n.t('keyholders.empty_out'), 'info')
|
||||
return
|
||||
end
|
||||
|
||||
table.insert(menu, {
|
||||
header = 'Delete work vehicles'
|
||||
})
|
||||
|
||||
for k, v in pairs(vehicles) do
|
||||
table.insert(menu, {
|
||||
header = v.plate,
|
||||
params = {
|
||||
isServer = true,
|
||||
event = 'advancedgarages:deleteJobVehicle',
|
||||
args = {
|
||||
plate = v.plate,
|
||||
garage = garage
|
||||
}
|
||||
}
|
||||
})
|
||||
end
|
||||
|
||||
exports['qb-menu']:openMenu(menu)
|
||||
end
|
||||
@@ -0,0 +1,352 @@
|
||||
if Config.UseTarget ~= 'ox_target' then
|
||||
return
|
||||
end
|
||||
|
||||
local function storeVehicleZone2()
|
||||
local id = exports.ox_target:addGlobalVehicle({
|
||||
{
|
||||
name = 'garages:storeVehicle',
|
||||
icon = 'fas fa-car',
|
||||
label = 'Store Vehicle',
|
||||
-- bones = { 'door_dside_f', 'seat_dside_f' },
|
||||
canInteract = function(entity, distance, coords, name)
|
||||
if IsNearbyJobGarage() then return true end
|
||||
if CurrentShellGarage then return false end
|
||||
local _garage = ClosestGarage
|
||||
if not _garage then
|
||||
return false
|
||||
end
|
||||
local garage = Config.Garages[_garage]
|
||||
if not CheckGarageAuthorization(garage.jobs, garage.gangs) then return end
|
||||
if not garage then
|
||||
return false
|
||||
end
|
||||
local distance = #(coords - vec3(garage.coords.spawnCoords.x, garage.coords.spawnCoords.y, garage.coords.spawnCoords.z))
|
||||
if distance > 50.0 then
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end,
|
||||
onSelect = function(data)
|
||||
local jobGarage = IsNearbyJobGarage()
|
||||
if jobGarage then
|
||||
StoreVehicle(jobGarage, true, data.entity)
|
||||
return
|
||||
end
|
||||
if CurrentShellGarage and existKey then
|
||||
nearbyGarageType = 'vehicle'
|
||||
StoreVehicle(CurrentShellGarage, false, data.entity)
|
||||
return
|
||||
end
|
||||
StoreVehicle(ClosestGarage, false, data.entity)
|
||||
end
|
||||
}
|
||||
})
|
||||
return id
|
||||
end
|
||||
|
||||
storeVehicleZone2()
|
||||
|
||||
local function storeVehicleZone(garage, garageName, isJob)
|
||||
local options = {
|
||||
{
|
||||
onSelect = function()
|
||||
if isJob then
|
||||
StoreVehicle(garage, isJob)
|
||||
return
|
||||
end
|
||||
StoreVehicle(ClosestGarage or garageName, isJob)
|
||||
end,
|
||||
canInteract = function()
|
||||
return (isJob and CheckGarageAuthorization(garage.jobs, garage.gangs) and cache.vehicle) or (not garage.isImpound and (IsGarageOwner or garage.available or IsKeyHolder) and cache.vehicle)
|
||||
end,
|
||||
distance = 150.0,
|
||||
icon = 'fas fa-car',
|
||||
label = 'Store Vehicle'
|
||||
}
|
||||
}
|
||||
local id = exports.ox_target:addBoxZone({
|
||||
coords = garage.coords.spawnCoords,
|
||||
distance = 150.0,
|
||||
rotation = 180.0,
|
||||
options = options,
|
||||
debug = Config.ZoneDebug
|
||||
})
|
||||
return id
|
||||
end
|
||||
|
||||
local boxZones = {}
|
||||
function InitZones()
|
||||
if #boxZones > 0 then
|
||||
for k, v in pairs(boxZones) do
|
||||
exports.ox_target:removeZone(v)
|
||||
end
|
||||
boxZones = {}
|
||||
end
|
||||
Wait(100)
|
||||
for k, garage in pairs(Config.Garages) do
|
||||
local options = {}
|
||||
if garage.type ~= 'plane' or garage.isImpound then
|
||||
table.insert(options, {
|
||||
onSelect = function()
|
||||
OpenGarageMenu(k, garage.isImpound, nil, garage.type == 'boat')
|
||||
end,
|
||||
canInteract = function()
|
||||
local job = CheckGarageAuthorization(garage.jobs, garage.gangs)
|
||||
return (IsGarageOwner or garage.available or IsKeyHolder) and job
|
||||
end,
|
||||
distance = 5.0,
|
||||
icon = 'fas fa-car',
|
||||
label = 'Open Garage'
|
||||
})
|
||||
end
|
||||
if not garage.isImpound then
|
||||
local garageType = garage.type
|
||||
if garageType == 'vehicle' or garageType == 'plane' then
|
||||
if garageType == 'plane' or (garageType == 'vehicle' and (Config.EnablePublicInteriors or not garage.available)) then
|
||||
table.insert(options, {
|
||||
onSelect = function()
|
||||
GotoShellGarage(k, garage.coords.spawnCoords, garage.shell)
|
||||
end,
|
||||
canInteract = function()
|
||||
local job = CheckGarageAuthorization(garage.jobs, garage.gangs)
|
||||
return (IsGarageOwner or garage.available or IsKeyHolder) and job
|
||||
end,
|
||||
icon = 'fas fa-warehouse',
|
||||
label = 'Enter the Garage',
|
||||
distance = 5.0
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
if not garage.owner or garage.owner == '' and not garage.isImpound then
|
||||
table.insert(options, {
|
||||
onSelect = function()
|
||||
local price = garage.price
|
||||
TriggerServerEvent('advancedgarages:buyGarage', k, price)
|
||||
end,
|
||||
canInteract = function()
|
||||
local job = CheckGarageAuthorization(garage.jobs, garage.gangs)
|
||||
return job
|
||||
end,
|
||||
distance = 5.0,
|
||||
icon = 'fas fa-store',
|
||||
label = 'Buy Garage',
|
||||
debug = true
|
||||
})
|
||||
end
|
||||
local id = exports.ox_target:addBoxZone({
|
||||
coords = garage.coords.menuCoords,
|
||||
distance = 5.5,
|
||||
rotation = 180.0,
|
||||
name = 'garage:' .. k,
|
||||
id = k,
|
||||
index = k,
|
||||
options = options,
|
||||
debug = Config.ZoneDebug,
|
||||
})
|
||||
table.insert(boxZones, id)
|
||||
local otherId = storeVehicleZone(garage, k, false)
|
||||
table.insert(boxZones, otherId)
|
||||
end
|
||||
end
|
||||
|
||||
local shellBoxes = {}
|
||||
function InitShellGarages()
|
||||
for k, v in pairs(shellBoxes) do
|
||||
exports.ox_target:removeZone(v)
|
||||
shellBoxes = {}
|
||||
end
|
||||
for k, garage in pairs(ShellGarages) do
|
||||
if not garage.takeVehicle or not garage.takeVehicle.x then goto continue end
|
||||
local options = {}
|
||||
|
||||
table.insert(options, {
|
||||
onSelect = function()
|
||||
local shell = garage?.shell
|
||||
nearbyGarageType = 'vehicle'
|
||||
GotoGarage(CurrentShellGarage, vec4(garage.takeVehicle.x, garage.takeVehicle.y, garage.takeVehicle.z, garage.takeVehicle.h), shell)
|
||||
end,
|
||||
distance = 5.0,
|
||||
canInteract = function()
|
||||
return CurrentShellGarage == k and existKey
|
||||
end,
|
||||
icon = 'fas fa-warehouse',
|
||||
label = 'Enter the garage'
|
||||
})
|
||||
table.insert(options, {
|
||||
onSelect = function()
|
||||
local shell = garage?.shell
|
||||
nearbyGarageType = 'vehicle'
|
||||
SaveVehicle(k, true)
|
||||
-- GotoGarage(k, vec4(garage.takeVehicle.x, garage.takeVehicle.y, garage.takeVehicle.z, garage.takeVehicle.h), shell?.shell)
|
||||
end,
|
||||
distance = 5.0,
|
||||
icon = 'fas fa-car',
|
||||
label = 'Store Vehicle',
|
||||
canInteract = function()
|
||||
return CurrentShellGarage == k and existKey and cache.vehicle
|
||||
end,
|
||||
})
|
||||
local id = exports.ox_target:addBoxZone({
|
||||
coords = vec3(garage.takeVehicle.x, garage.takeVehicle.y, garage.takeVehicle.z),
|
||||
distance = 5.5,
|
||||
rotation = 180.0,
|
||||
name = 'shell-garage:' .. k,
|
||||
id = 'shell-' .. k,
|
||||
index = k,
|
||||
options = options,
|
||||
debug = Config.ZoneDebug,
|
||||
})
|
||||
shellBoxes[k] = id
|
||||
::continue::
|
||||
end
|
||||
end
|
||||
|
||||
CreateThread(function()
|
||||
for k, garage in pairs(Config.JobGarages) do
|
||||
local job = garage.job or garage.gang
|
||||
local options = {}
|
||||
table.insert(options, {
|
||||
onSelect = function()
|
||||
local serverVehicles = lib.callback.await('advancedgarages:getJobVehicles', false, garage.name, job)
|
||||
local vehicleList = serverVehicles
|
||||
local garageIsAvailable = lib.callback.await('advancedgarages:isGarageAvailable', false, k)
|
||||
if not garageIsAvailable then return Notification(i18n.t('garage_not_available'), 'error') end
|
||||
for _, veh in pairs(vehicleList) do
|
||||
veh.vehicle = json.encode(veh.vehicle)
|
||||
end
|
||||
for a, model in ipairs(garage.vehicles) do
|
||||
local plate = tostring(job .. math.random(111, 999))
|
||||
table.insert(vehicleList, {
|
||||
id = #vehicleList + 1,
|
||||
vehicle = json.encode({
|
||||
model = model,
|
||||
plate = plate
|
||||
}),
|
||||
plate = plate,
|
||||
})
|
||||
end
|
||||
TriggerServerEvent('advancedgarages:setInJobGarage', k, true)
|
||||
OpenGarageMenu(k, garage.isImpound, vehicleList)
|
||||
end,
|
||||
canInteract = function()
|
||||
return CheckJob(garage.job, garage.grade)
|
||||
end,
|
||||
distance = 5.0,
|
||||
icon = 'fas fa-car',
|
||||
label = 'Open Garage'
|
||||
})
|
||||
exports.ox_target:addBoxZone({
|
||||
coords = garage.coords.menuCoords,
|
||||
distance = 5.5,
|
||||
rotation = 180.0,
|
||||
name = 'job-garage:' .. k,
|
||||
id = k,
|
||||
index = k,
|
||||
options = options,
|
||||
debug = Config.ZoneDebug,
|
||||
})
|
||||
storeVehicleZone(garage, k, true)
|
||||
end
|
||||
end)
|
||||
|
||||
CreateThread(function()
|
||||
for k, types in pairs(Config.VehicleShowRooms) do
|
||||
for a, v in pairs(types) do
|
||||
local options = {}
|
||||
table.insert(options, {
|
||||
onSelect = function()
|
||||
ExitGarage()
|
||||
end,
|
||||
distance = 5.0,
|
||||
icon = 'fas fa-warehouse',
|
||||
label = 'Exit Garage'
|
||||
})
|
||||
exports.ox_target:addBoxZone({
|
||||
coords = vec3(v.entry.x, v.entry.y, v.entry.z),
|
||||
distance = 5.5,
|
||||
rotation = 180.0,
|
||||
name = 'exit-garage:' .. k,
|
||||
id = k,
|
||||
index = k,
|
||||
options = options,
|
||||
debug = Config.ZoneDebug,
|
||||
})
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
---@param coords vector4
|
||||
function InitShellExit(coords)
|
||||
exports.ox_target:addBoxZone({
|
||||
coords = coords,
|
||||
distance = 5.5,
|
||||
rotation = 180.0,
|
||||
name = 'exit-shell-garage',
|
||||
id = 'exit-shell-garage',
|
||||
options = {
|
||||
{
|
||||
onSelect = function()
|
||||
ExitGarage()
|
||||
end,
|
||||
distance = 5.0,
|
||||
icon = 'fas fa-warehouse',
|
||||
label = 'Exit Garage'
|
||||
}
|
||||
},
|
||||
})
|
||||
end
|
||||
|
||||
function RemoveShellExit()
|
||||
exports.ox_target:removeZone('exit-shell-garage')
|
||||
end
|
||||
|
||||
CreateThread(function()
|
||||
for k, v in pairs(Config.Recovery.coords) do
|
||||
local options = {}
|
||||
table.insert(options, {
|
||||
onSelect = function()
|
||||
local vehicleList = lib.callback.await('advancedgarages:getRecoveryVehicles', false)
|
||||
if #vehicleList == 0 then
|
||||
return Notification(i18n.t('keyholders.empty_out'), 'info')
|
||||
end
|
||||
OpenRecoveryMenu(vehicleList)
|
||||
end,
|
||||
distance = 5.0,
|
||||
icon = 'fas fa-car-on',
|
||||
label = 'Recover vehicle $' .. Config.Recovery.price
|
||||
})
|
||||
exports.ox_target:addBoxZone({
|
||||
coords = v,
|
||||
size = vec3(2.0, 2.0, 2.0),
|
||||
rotation = 180.0,
|
||||
name = 'recovery-garage:' .. k,
|
||||
id = k,
|
||||
index = k,
|
||||
options = options,
|
||||
debug = Config.ZoneDebug,
|
||||
})
|
||||
end
|
||||
end)
|
||||
|
||||
CreateThread(function()
|
||||
local function checkMenu()
|
||||
local sleep = 500
|
||||
if not ClosestGarage then return sleep end
|
||||
local garage = Config.Garages[ClosestGarage]
|
||||
if not IsGarageOwner and not garage.available and not IsKeyHolder then return sleep end
|
||||
if not CheckGarageAuthorization(garage.jobs, garage.gangs) then return sleep end
|
||||
if garage.isImpound then return sleep end
|
||||
if cache.vehicle then
|
||||
sleep = 0
|
||||
DrawMarkerZone(garage.coords.spawnCoords.x, garage.coords.spawnCoords.y, garage.coords.spawnCoords.z)
|
||||
-- DrawMarker(1, garage.coords.spawnCoords.x, garage.coords.spawnCoords.y, garage.coords.spawnCoords.z, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 4.0, 4.0, 0.8, 255, 255, 255, 150, false, false, false, true, false, false, false)
|
||||
end
|
||||
return sleep
|
||||
end
|
||||
while true do
|
||||
local sleep = checkMenu()
|
||||
Wait(sleep)
|
||||
end
|
||||
end)
|
||||
@@ -0,0 +1,181 @@
|
||||
if Config.UseTarget ~= 'qb-radialmenu' then
|
||||
return
|
||||
end
|
||||
|
||||
local menuItems = {}
|
||||
|
||||
local function AddRadialOption()
|
||||
RemoveRadialOptions()
|
||||
local garage, garageJobName
|
||||
|
||||
if ClosestGarage then
|
||||
garage = Config.Garages[ClosestGarage]
|
||||
end
|
||||
|
||||
if garage then
|
||||
if not cache.vehicle and (garage.available or IsGarageOwner or IsKeyHolder) then
|
||||
if not CheckGarageAuthorization(garage.jobs, garage.gangs) then goto continue end
|
||||
if garage.type ~= 'plane' and not cache.vehicle then
|
||||
table.insert(menuItems, {
|
||||
id = 'radialOpenMenu',
|
||||
title = 'Open Garage',
|
||||
icon = 'car',
|
||||
type = 'client',
|
||||
event = 'advancedgarages:client:radialOpenMenu',
|
||||
shouldClose = true
|
||||
})
|
||||
end
|
||||
|
||||
if garage.type == 'plane' or ((Config.EnablePublicInteriors or not garage.available) and garage.type ~= 'boat' and not garage.isImpound and not cache.vehicle) then
|
||||
table.insert(menuItems, {
|
||||
id = 'radialEnterShell',
|
||||
title = 'Enter Garage',
|
||||
icon = 'warehouse',
|
||||
type = 'client',
|
||||
event = 'advancedgarages:client:radialEnterShell',
|
||||
shouldClose = true
|
||||
})
|
||||
end
|
||||
end
|
||||
::continue::
|
||||
end
|
||||
|
||||
if cache.vehicle and ClosestGarage and not garage.isImpound then
|
||||
if not CheckGarageAuthorization(garage.jobs, garage.gangs) then goto continue end
|
||||
table.insert(menuItems, {
|
||||
id = 'radialSaveVehicle',
|
||||
title = 'Store Vehicle',
|
||||
icon = 'warehouse',
|
||||
type = 'client',
|
||||
event = 'advancedgarages:client:radialSaveVehicle',
|
||||
garage = ClosestGarage,
|
||||
shouldClose = true
|
||||
})
|
||||
::continue::
|
||||
end
|
||||
|
||||
local nearbyElevator = nearbyElevator()
|
||||
if nearbyElevator and nearbyElevator == 0 then
|
||||
table.insert(menuItems, {
|
||||
id = 'radialExitShell',
|
||||
title = 'Exit',
|
||||
icon = 'warehouse',
|
||||
type = 'client',
|
||||
event = 'advancedgarages:client:radialExitShell',
|
||||
shouldClose = true
|
||||
})
|
||||
end
|
||||
|
||||
local recover = checkMenu()
|
||||
if recover == 0 then
|
||||
table.insert(menuItems, {
|
||||
id = 'radialRecoverVehicle',
|
||||
title = 'Recover',
|
||||
icon = 'car',
|
||||
type = 'client',
|
||||
event = 'advancedgarages:client:radialRecoverVehicle',
|
||||
shouldClose = true
|
||||
})
|
||||
end
|
||||
|
||||
if IsGarageOwner and not cache.vehicle then
|
||||
table.insert(menuItems, {
|
||||
id = 'radialGarageManagement',
|
||||
title = 'Management',
|
||||
icon = 'bars-progress',
|
||||
type = 'client',
|
||||
event = 'advancedgarages:client:radialGarageManagement',
|
||||
shouldClose = true
|
||||
})
|
||||
end
|
||||
|
||||
local nearbyHouseGarage = CheckNearbyGarage()
|
||||
if nearbyHouseGarage and nearbyHouseGarage == 0 and cache.vehicle then
|
||||
table.insert(menuItems, {
|
||||
id = 'save_vehicle',
|
||||
title = 'Store Vehicle',
|
||||
icon = 'warehouse',
|
||||
type = 'client',
|
||||
event = 'advancedgarages:client:radialSaveHousingGarage',
|
||||
shouldClose = true
|
||||
})
|
||||
end
|
||||
|
||||
if nearbyHouseGarage and nearbyHouseGarage == 0 and not cache.vehicle then
|
||||
table.insert(menuItems, {
|
||||
id = 'enter_garage_shell',
|
||||
title = 'Enter Garage',
|
||||
icon = 'warehouse',
|
||||
type = 'client',
|
||||
event = 'advancedgarages:client:radialEnterHousingGarage',
|
||||
shouldClose = true
|
||||
})
|
||||
end
|
||||
|
||||
local job = GetJobName()
|
||||
if IsJobAllowed(job, 'impound') and not cache.vehicle then
|
||||
table.insert(menuItems, {
|
||||
id = 'radialImpoundVehicle',
|
||||
title = 'Impound vehicle',
|
||||
icon = 'car-side',
|
||||
type = 'client',
|
||||
event = 'advancedgarages:client:radialImpoundVehicle',
|
||||
shouldClose = true
|
||||
})
|
||||
end
|
||||
|
||||
local playerCoords = GetEntityCoords(cache.ped)
|
||||
for k, garage in pairs(Config.JobGarages) do
|
||||
local access = CheckJob(garage.job, garage.grade)
|
||||
if access then
|
||||
local dst = #(playerCoords - vec3(garage.coords.menuCoords.x, garage.coords.menuCoords.y, garage.coords.menuCoords.z))
|
||||
if dst < 15.0 and not cache.vehicle then
|
||||
table.insert(menuItems, {
|
||||
id = 'radialOpenJobGarage',
|
||||
title = 'Open Garage',
|
||||
icon = 'warehouse',
|
||||
type = 'client',
|
||||
event = 'advancedgarages:client:radialOpenJobGarage',
|
||||
garage = k,
|
||||
shouldClose = true
|
||||
})
|
||||
end
|
||||
|
||||
if dst < 15.0 and cache.vehicle then
|
||||
table.insert(menuItems, {
|
||||
id = 'radialSaveVehicle',
|
||||
title = 'Save Vehicle',
|
||||
icon = 'warehouse',
|
||||
type = 'client',
|
||||
event = 'advancedgarages:client:radialSaveVehicle',
|
||||
garage = k,
|
||||
isJob = true,
|
||||
shouldClose = true
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for _, item in ipairs(menuItems) do
|
||||
item.id = exports['qb-radialmenu']:AddOption(item)
|
||||
end
|
||||
end
|
||||
|
||||
function RemoveRadialOptions()
|
||||
for _, item in ipairs(menuItems) do
|
||||
exports['qb-radialmenu']:RemoveOption(item.id)
|
||||
end
|
||||
menuItems = {}
|
||||
|
||||
Debug('The qb-radialmenu table has been cleaned!')
|
||||
end
|
||||
|
||||
RegisterNetEvent('qb-radialmenu:client:onRadialmenuOpen', function()
|
||||
AddRadialOption()
|
||||
end)
|
||||
|
||||
AddEventHandler('onResourceStop', function(resourceName)
|
||||
if (resourceName == 'qs-advancedgarages') then
|
||||
RemoveRadialOptions()
|
||||
end
|
||||
end)
|
||||
@@ -0,0 +1,483 @@
|
||||
if Config.UseTarget ~= 'qs-radialmenu' then
|
||||
return
|
||||
end
|
||||
|
||||
-- ============================================================
|
||||
-- State
|
||||
-- ============================================================
|
||||
|
||||
local shellExitCoords = nil
|
||||
local nearestGarage = nil
|
||||
|
||||
-- ============================================================
|
||||
-- Self-contained proximity detection
|
||||
-- Maintains nearestGarage independently of the escrowed code,
|
||||
-- so garage items appear even when ClosestGarage is not set.
|
||||
-- ============================================================
|
||||
|
||||
CreateThread(function()
|
||||
while true do
|
||||
local playerCoords = GetEntityCoords(cache.ped)
|
||||
local closest, closestDist = nil, 10.0
|
||||
for k, g in pairs(Config.Garages) do
|
||||
if g.coords and g.coords.menuCoords then
|
||||
local mc = g.coords.menuCoords
|
||||
local d = #(playerCoords - vec3(mc.x, mc.y, mc.z))
|
||||
if d < closestDist then
|
||||
closest = k
|
||||
closestDist = d
|
||||
end
|
||||
end
|
||||
end
|
||||
nearestGarage = closest
|
||||
Wait(closest and 250 or 1000)
|
||||
end
|
||||
end)
|
||||
|
||||
local function getClosestGarage()
|
||||
return ClosestGarage or nearestGarage
|
||||
end
|
||||
|
||||
-- ============================================================
|
||||
-- Lifecycle hooks (same interface as ox_target.lua)
|
||||
-- The escrowed code calls these at key moments.
|
||||
-- ============================================================
|
||||
|
||||
function InitZones() end
|
||||
|
||||
function InitShellGarages() end
|
||||
|
||||
---@param coords vector4
|
||||
function InitShellExit(coords)
|
||||
shellExitCoords = coords
|
||||
end
|
||||
|
||||
function RemoveShellExit()
|
||||
shellExitCoords = nil
|
||||
end
|
||||
|
||||
-- ============================================================
|
||||
-- Provider: getRadialItems export
|
||||
-- Called synchronously by qs-radialmenu before building menu.
|
||||
-- Returns a plain table of items — no cross-resource closures.
|
||||
-- ============================================================
|
||||
|
||||
exports('getRadialItems', function()
|
||||
local items = {}
|
||||
local playerCoords = GetEntityCoords(cache.ped)
|
||||
|
||||
local garageName = getClosestGarage()
|
||||
local garage = garageName and Config.Garages[garageName] or nil
|
||||
|
||||
local authorized = false
|
||||
if garage then
|
||||
local jobOk = type(CheckGarageAuthorization) ~= 'function' or CheckGarageAuthorization(garage.jobs, garage.gangs)
|
||||
authorized = jobOk and (IsGarageOwner or garage.available or IsKeyHolder)
|
||||
end
|
||||
|
||||
-- ── 1. Open Garage (on foot, authorized)
|
||||
if garage and not cache.vehicle and authorized then
|
||||
if garage.type ~= 'plane' or garage.isImpound then
|
||||
table.insert(items, {
|
||||
id = 'radialOpenMenu',
|
||||
title = 'Open Garage',
|
||||
icon = 'Car',
|
||||
type = 'client',
|
||||
event = 'qs-radialmenu:garages:openGarage',
|
||||
shouldClose = true
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
-- ── 2. Enter Garage interior (on foot, authorized)
|
||||
if garage and not cache.vehicle and authorized and not garage.isImpound then
|
||||
local gt = garage.type
|
||||
if gt == 'plane' or (gt == 'vehicle' and (Config.EnablePublicInteriors or not garage.available)) then
|
||||
table.insert(items, {
|
||||
id = 'radialEnterShell',
|
||||
title = 'Enter Garage',
|
||||
icon = 'Warehouse',
|
||||
type = 'client',
|
||||
event = 'qs-radialmenu:garages:enterShell',
|
||||
shouldClose = true
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
-- ── 3. Buy Garage (no owner, authorized)
|
||||
if garage and not garage.isImpound and (not garage.owner or garage.owner == '') then
|
||||
local jobOk = type(CheckGarageAuthorization) ~= 'function' or CheckGarageAuthorization(garage.jobs, garage.gangs)
|
||||
if jobOk then
|
||||
table.insert(items, {
|
||||
id = 'radialBuyGarage',
|
||||
title = 'Buy Garage',
|
||||
icon = 'Store',
|
||||
type = 'client',
|
||||
event = 'qs-radialmenu:garages:buyGarage',
|
||||
shouldClose = true
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
-- ── 4. Store Vehicle – regular garage (in vehicle)
|
||||
if cache.vehicle and not CurrentShellGarage then
|
||||
local canStore = false
|
||||
if type(IsNearbyJobGarage) == 'function' and IsNearbyJobGarage() then
|
||||
canStore = true
|
||||
elseif garage and not garage.isImpound and authorized then
|
||||
local sp = garage.coords.spawnCoords
|
||||
local dst = #(playerCoords - vec3(sp.x, sp.y, sp.z))
|
||||
if dst <= 50.0 then
|
||||
canStore = true
|
||||
end
|
||||
end
|
||||
if canStore then
|
||||
table.insert(items, {
|
||||
id = 'radialStoreVehicle',
|
||||
title = 'Store Vehicle',
|
||||
icon = 'Car',
|
||||
type = 'client',
|
||||
event = 'qs-radialmenu:garages:storeVehicle',
|
||||
shouldClose = true
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
-- ── 5. Shell garage options
|
||||
if CurrentShellGarage and existKey then
|
||||
local shellData = type(ShellGarages) == 'table' and ShellGarages[CurrentShellGarage] or nil
|
||||
if shellData and shellData.takeVehicle and shellData.takeVehicle.x then
|
||||
if not cache.vehicle then
|
||||
table.insert(items, {
|
||||
id = 'radialEnterShellGarage',
|
||||
title = 'Enter Garage',
|
||||
icon = 'Warehouse',
|
||||
type = 'client',
|
||||
event = 'qs-radialmenu:garages:enterShellGarage',
|
||||
shouldClose = true
|
||||
})
|
||||
else
|
||||
table.insert(items, {
|
||||
id = 'radialStoreShellVehicle',
|
||||
title = 'Store Vehicle',
|
||||
icon = 'Car',
|
||||
type = 'client',
|
||||
event = 'qs-radialmenu:garages:storeShellVehicle',
|
||||
shouldClose = true
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- ── 6. Exit Garage (shell exit or VehicleShowRooms)
|
||||
local showExit = false
|
||||
if shellExitCoords then
|
||||
showExit = true
|
||||
end
|
||||
if not showExit and Config.VehicleShowRooms then
|
||||
for _, types in pairs(Config.VehicleShowRooms) do
|
||||
for _, v in pairs(types) do
|
||||
if v.entry and v.entry.x then
|
||||
local dst = #(playerCoords - vec3(v.entry.x, v.entry.y, v.entry.z))
|
||||
if dst <= 5.5 then
|
||||
showExit = true
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
if showExit then break end
|
||||
end
|
||||
end
|
||||
if showExit then
|
||||
table.insert(items, {
|
||||
id = 'radialExitGarage',
|
||||
title = 'Exit',
|
||||
icon = 'DoorOpen',
|
||||
type = 'client',
|
||||
event = 'qs-radialmenu:garages:exitGarage',
|
||||
shouldClose = true
|
||||
})
|
||||
end
|
||||
|
||||
-- ── 7. Recover Vehicle
|
||||
if Config.Recovery and Config.Recovery.coords then
|
||||
for _, v in pairs(Config.Recovery.coords) do
|
||||
local dst = #(playerCoords - vec3(v.x, v.y, v.z))
|
||||
if dst <= 5.0 then
|
||||
table.insert(items, {
|
||||
id = 'radialRecoverVehicle',
|
||||
title = 'Recover $' .. (Config.Recovery.price or 0),
|
||||
icon = 'Car',
|
||||
type = 'client',
|
||||
event = 'qs-radialmenu:garages:recoverVehicle',
|
||||
shouldClose = true
|
||||
})
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- ── 8. Garage Management (owner only, on foot)
|
||||
if IsGarageOwner and not cache.vehicle then
|
||||
table.insert(items, {
|
||||
id = 'radialGarageManagement',
|
||||
title = 'Management',
|
||||
icon = 'Settings',
|
||||
type = 'client',
|
||||
event = 'qs-radialmenu:garages:management',
|
||||
shouldClose = true
|
||||
})
|
||||
end
|
||||
|
||||
-- ── 9. Impound Vehicle (allowed job, on foot)
|
||||
if not cache.vehicle then
|
||||
local job = type(GetJobName) == 'function' and GetJobName() or nil
|
||||
if job and type(IsJobAllowed) == 'function' and IsJobAllowed(job, 'impound') then
|
||||
table.insert(items, {
|
||||
id = 'radialImpoundVehicle',
|
||||
title = 'Impound Vehicle',
|
||||
icon = 'Car',
|
||||
type = 'client',
|
||||
event = 'qs-radialmenu:garages:impoundVehicle',
|
||||
shouldClose = true
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
-- ── 10. Job Garages
|
||||
if Config.JobGarages then
|
||||
for k, jGarage in pairs(Config.JobGarages) do
|
||||
local access = type(CheckJob) == 'function' and CheckJob(jGarage.job, jGarage.grade) or false
|
||||
if access then
|
||||
local mc = jGarage.coords.menuCoords
|
||||
local dst = #(playerCoords - vec3(mc.x, mc.y, mc.z))
|
||||
if dst <= 15.0 then
|
||||
if not cache.vehicle then
|
||||
table.insert(items, {
|
||||
id = 'radialOpenJobGarage_' .. k,
|
||||
title = 'Open Garage',
|
||||
icon = 'Warehouse',
|
||||
type = 'client',
|
||||
event = 'qs-radialmenu:garages:openJobGarage',
|
||||
shouldClose = true
|
||||
})
|
||||
else
|
||||
table.insert(items, {
|
||||
id = 'radialStoreJobVehicle_' .. k,
|
||||
title = 'Store Vehicle',
|
||||
icon = 'Warehouse',
|
||||
type = 'client',
|
||||
event = 'qs-radialmenu:garages:storeJobVehicle',
|
||||
shouldClose = true
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return items
|
||||
end)
|
||||
|
||||
-- ============================================================
|
||||
-- Register as an item provider once qs-radialmenu is ready
|
||||
-- ============================================================
|
||||
|
||||
CreateThread(function()
|
||||
local attempts = 0
|
||||
while attempts < 60 do
|
||||
local ok = pcall(function()
|
||||
exports['qs-radialmenu']:RegisterItemProvider(GetCurrentResourceName())
|
||||
end)
|
||||
if ok then return end
|
||||
attempts = attempts + 1
|
||||
Wait(500)
|
||||
end
|
||||
end)
|
||||
|
||||
-- ============================================================
|
||||
-- Bridge events — call escrowed functions directly
|
||||
-- (mirrors ox_target onSelect callbacks)
|
||||
-- Use getClosestGarage() so bridge events also benefit from
|
||||
-- the self-contained proximity fallback.
|
||||
-- ============================================================
|
||||
|
||||
RegisterNetEvent('qs-radialmenu:garages:openGarage', function()
|
||||
local gName = getClosestGarage()
|
||||
if not gName then return end
|
||||
local garage = Config.Garages[gName]
|
||||
if not garage then return end
|
||||
if type(OpenGarageMenu) == 'function' then
|
||||
OpenGarageMenu(gName, garage.isImpound, nil, garage.type == 'boat')
|
||||
end
|
||||
end)
|
||||
|
||||
RegisterNetEvent('qs-radialmenu:garages:enterShell', function()
|
||||
local gName = getClosestGarage()
|
||||
if not gName then return end
|
||||
local garage = Config.Garages[gName]
|
||||
if not garage then return end
|
||||
if type(GotoShellGarage) == 'function' then
|
||||
GotoShellGarage(gName, garage.coords.spawnCoords, garage.shell)
|
||||
end
|
||||
end)
|
||||
|
||||
RegisterNetEvent('qs-radialmenu:garages:buyGarage', function()
|
||||
local gName = getClosestGarage()
|
||||
if not gName then return end
|
||||
local garage = Config.Garages[gName]
|
||||
if not garage then return end
|
||||
TriggerServerEvent('advancedgarages:buyGarage', gName, garage.price)
|
||||
end)
|
||||
|
||||
RegisterNetEvent('qs-radialmenu:garages:storeVehicle', function()
|
||||
if type(StoreVehicle) ~= 'function' then return end
|
||||
local jobGarage = type(IsNearbyJobGarage) == 'function' and IsNearbyJobGarage() or nil
|
||||
if jobGarage then
|
||||
StoreVehicle(jobGarage, true, cache.vehicle)
|
||||
return
|
||||
end
|
||||
local gName = getClosestGarage()
|
||||
StoreVehicle(gName, false, cache.vehicle)
|
||||
end)
|
||||
|
||||
RegisterNetEvent('qs-radialmenu:garages:enterShellGarage', function()
|
||||
if not CurrentShellGarage or not existKey then return end
|
||||
local shellData = type(ShellGarages) == 'table' and ShellGarages[CurrentShellGarage] or nil
|
||||
if not shellData or not shellData.takeVehicle then return end
|
||||
nearbyGarageType = 'vehicle'
|
||||
if type(GotoGarage) == 'function' then
|
||||
GotoGarage(CurrentShellGarage, vec4(shellData.takeVehicle.x, shellData.takeVehicle.y, shellData.takeVehicle.z, shellData.takeVehicle.h), shellData.shell)
|
||||
end
|
||||
end)
|
||||
|
||||
RegisterNetEvent('qs-radialmenu:garages:storeShellVehicle', function()
|
||||
if not CurrentShellGarage or not existKey then return end
|
||||
nearbyGarageType = 'vehicle'
|
||||
if type(SaveVehicle) == 'function' then
|
||||
SaveVehicle(CurrentShellGarage, true)
|
||||
end
|
||||
end)
|
||||
|
||||
RegisterNetEvent('qs-radialmenu:garages:exitGarage', function()
|
||||
if type(ExitGarage) == 'function' then
|
||||
ExitGarage()
|
||||
end
|
||||
end)
|
||||
|
||||
RegisterNetEvent('qs-radialmenu:garages:recoverVehicle', function()
|
||||
local vehicleList = lib.callback.await('advancedgarages:getRecoveryVehicles', false)
|
||||
if not vehicleList or #vehicleList == 0 then
|
||||
if type(Notification) == 'function' then
|
||||
Notification(i18n.t('keyholders.empty_out'), 'info')
|
||||
end
|
||||
return
|
||||
end
|
||||
if type(OpenRecoveryMenu) == 'function' then
|
||||
OpenRecoveryMenu(vehicleList)
|
||||
end
|
||||
end)
|
||||
|
||||
RegisterNetEvent('qs-radialmenu:garages:management', function()
|
||||
TriggerEvent('advancedgarages:client:radialGarageManagement')
|
||||
end)
|
||||
|
||||
RegisterNetEvent('qs-radialmenu:garages:impoundVehicle', function()
|
||||
TriggerEvent('advancedgarages:client:radialImpoundVehicle')
|
||||
end)
|
||||
|
||||
RegisterNetEvent('qs-radialmenu:garages:openJobGarage', function()
|
||||
if not Config.JobGarages then return end
|
||||
local playerCoords = GetEntityCoords(cache.ped)
|
||||
for k, jGarage in pairs(Config.JobGarages) do
|
||||
local access = type(CheckJob) == 'function' and CheckJob(jGarage.job, jGarage.grade) or false
|
||||
if access then
|
||||
local mc = jGarage.coords.menuCoords
|
||||
local dst = #(playerCoords - vec3(mc.x, mc.y, mc.z))
|
||||
if dst <= 15.0 then
|
||||
local job = jGarage.job or jGarage.gang
|
||||
local serverVehicles = lib.callback.await('advancedgarages:getJobVehicles', false, jGarage.name, job)
|
||||
local vehicleList = serverVehicles or {}
|
||||
local garageIsAvailable = lib.callback.await('advancedgarages:isGarageAvailable', false, k)
|
||||
if not garageIsAvailable then
|
||||
if type(Notification) == 'function' then Notification(i18n.t('garage_not_available'), 'error') end
|
||||
return
|
||||
end
|
||||
for _, veh in pairs(vehicleList) do
|
||||
veh.vehicle = json.encode(veh.vehicle)
|
||||
end
|
||||
if jGarage.vehicles then
|
||||
for _, model in ipairs(jGarage.vehicles) do
|
||||
local plate = tostring(job .. math.random(111, 999))
|
||||
table.insert(vehicleList, {
|
||||
id = #vehicleList + 1,
|
||||
vehicle = json.encode({ model = model, plate = plate }),
|
||||
plate = plate,
|
||||
})
|
||||
end
|
||||
end
|
||||
TriggerServerEvent('advancedgarages:setInJobGarage', k, true)
|
||||
if type(OpenGarageMenu) == 'function' then
|
||||
OpenGarageMenu(k, jGarage.isImpound, vehicleList)
|
||||
end
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
RegisterNetEvent('qs-radialmenu:garages:storeJobVehicle', function()
|
||||
if not Config.JobGarages or type(StoreVehicle) ~= 'function' then return end
|
||||
local playerCoords = GetEntityCoords(cache.ped)
|
||||
for k, jGarage in pairs(Config.JobGarages) do
|
||||
local access = type(CheckJob) == 'function' and CheckJob(jGarage.job, jGarage.grade) or false
|
||||
if access then
|
||||
local mc = jGarage.coords.menuCoords
|
||||
local dst = #(playerCoords - vec3(mc.x, mc.y, mc.z))
|
||||
if dst <= 15.0 then
|
||||
StoreVehicle(jGarage, true)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
-- ============================================================
|
||||
-- Cleanup
|
||||
-- ============================================================
|
||||
|
||||
AddEventHandler('onResourceStop', function(resourceName)
|
||||
if resourceName == 'qs-advancedgarages' then
|
||||
pcall(function()
|
||||
exports['qs-radialmenu']:UnregisterItemProvider(GetCurrentResourceName())
|
||||
end)
|
||||
end
|
||||
end)
|
||||
|
||||
-- ============================================================
|
||||
-- Marker thread (mirrors ox_target lines 333-352)
|
||||
-- Uses getClosestGarage() for proximity fallback.
|
||||
-- ============================================================
|
||||
|
||||
CreateThread(function()
|
||||
local function checkStoreMarker()
|
||||
local sleep = 500
|
||||
local gName = getClosestGarage()
|
||||
if not gName then return sleep end
|
||||
local garage = Config.Garages[gName]
|
||||
if not garage then return sleep end
|
||||
if not IsGarageOwner and not garage.available and not IsKeyHolder then return sleep end
|
||||
if type(CheckGarageAuthorization) == 'function' and not CheckGarageAuthorization(garage.jobs, garage.gangs) then return sleep end
|
||||
if garage.isImpound then return sleep end
|
||||
if cache.vehicle then
|
||||
sleep = 0
|
||||
if type(DrawMarkerZone) == 'function' then
|
||||
DrawMarkerZone(garage.coords.spawnCoords.x, garage.coords.spawnCoords.y, garage.coords.spawnCoords.z)
|
||||
end
|
||||
end
|
||||
return sleep
|
||||
end
|
||||
while true do
|
||||
Wait(checkStoreMarker())
|
||||
end
|
||||
end)
|
||||
@@ -0,0 +1,11 @@
|
||||
if Config.Vehiclekeys ~= 'F_RealCarKeysSystem' then
|
||||
return
|
||||
end
|
||||
|
||||
function AddVehiclekeys(vehicle, plate, item)
|
||||
TriggerServerEvent('F_RealCarKeysSystem:generateVehicleKeys', plate)
|
||||
end
|
||||
|
||||
function RemoveVehiclekeys(vehicle, plate)
|
||||
return
|
||||
end
|
||||
@@ -0,0 +1,11 @@
|
||||
if Config.Vehiclekeys ~= 'MrNewbVehicleKeys' then
|
||||
return
|
||||
end
|
||||
|
||||
function AddVehiclekeys(vehicle, plate, item)
|
||||
exports.MrNewbVehicleKeys:GiveKeysByPlate(plate)
|
||||
end
|
||||
|
||||
function RemoveVehiclekeys(vehicle, plate)
|
||||
exports.MrNewbVehicleKeys:RemoveKeysByPlate(plate)
|
||||
end
|
||||
@@ -0,0 +1,11 @@
|
||||
if Config.Vehiclekeys ~= 'fivecode_carkeys' then
|
||||
return
|
||||
end
|
||||
|
||||
function AddVehiclekeys(vehicle, plate, item)
|
||||
DecorSetInt(vehicle, 'owner', GetPlayerServerId(PlayerId()))
|
||||
end
|
||||
|
||||
function RemoveVehiclekeys(vehicle, plate)
|
||||
return
|
||||
end
|
||||
@@ -0,0 +1,15 @@
|
||||
if Config.Vehiclekeys ~= 'glfp10_carkeys' then
|
||||
return
|
||||
end
|
||||
|
||||
function AddVehiclekeys(vehicle, plate, item)
|
||||
if not item then return end
|
||||
if type(vehicle) ~= 'string' then return end
|
||||
|
||||
local model = GetDisplayNameFromVehicleModel(GetEntityModel(vehicle))
|
||||
TriggerServerEvent('carkeys:server:buyKey', plate, model)
|
||||
end
|
||||
|
||||
function RemoveVehiclekeys(vehicle, plate)
|
||||
return
|
||||
end
|
||||
@@ -0,0 +1,11 @@
|
||||
if Config.Vehiclekeys ~= 'jc_vehiclekeys' then
|
||||
return
|
||||
end
|
||||
|
||||
function AddVehiclekeys(vehicle, plate, item)
|
||||
exports['jc_vehiclekeys']:GiveKeys(plate)
|
||||
end
|
||||
|
||||
function RemoveVehiclekeys(vehicle, plate)
|
||||
exports['jc_vehiclekeys']:RemoveKeys(plate)
|
||||
end
|
||||
@@ -0,0 +1,14 @@
|
||||
if Config.Vehiclekeys ~= 'mono_carkeys' then
|
||||
return
|
||||
end
|
||||
|
||||
function AddVehiclekeys(vehicle, plate, item)
|
||||
if not item then return end
|
||||
if type(vehicle) ~= 'string' then return end
|
||||
TriggerServerEvent('mono_carkeys:CreateKey', plate)
|
||||
end
|
||||
|
||||
function RemoveVehiclekeys(vehicle, plate)
|
||||
if type(vehicle) ~= 'string' then return end
|
||||
TriggerServerEvent('mono_carkeys:DeleteKey', 1, plate)
|
||||
end
|
||||
@@ -0,0 +1,12 @@
|
||||
if Config.Vehiclekeys ~= 'qb-vehiclekeys' then
|
||||
return
|
||||
end
|
||||
|
||||
function AddVehiclekeys(vehicle, plate, item)
|
||||
Wait(100)
|
||||
TriggerEvent('vehiclekeys:client:SetOwner', plate)
|
||||
end
|
||||
|
||||
function RemoveVehiclekeys(vehicle, plate)
|
||||
return
|
||||
end
|
||||
@@ -0,0 +1,12 @@
|
||||
if Config.Vehiclekeys ~= 'qbx_vehiclekeys' then
|
||||
return
|
||||
end
|
||||
|
||||
function AddVehiclekeys(vehicle, plate, item)
|
||||
Wait(100)
|
||||
TriggerServerEvent('qb-vehiclekeys:server:AcquireVehicleKeys', plate)
|
||||
end
|
||||
|
||||
function RemoveVehiclekeys(vehicle, plate)
|
||||
return
|
||||
end
|
||||
@@ -0,0 +1,14 @@
|
||||
if Config.Vehiclekeys ~= 'qs-vehiclekeys' then
|
||||
return
|
||||
end
|
||||
|
||||
function AddVehiclekeys(vehicle, plate, item)
|
||||
if not item then
|
||||
return
|
||||
end
|
||||
exports['qs-vehiclekeys']:GiveKeys(plate, vehicle, item)
|
||||
end
|
||||
|
||||
function RemoveVehiclekeys(vehicle, plate)
|
||||
exports['qs-vehiclekeys']:RemoveKeys(plate, vehicle)
|
||||
end
|
||||
@@ -0,0 +1,11 @@
|
||||
if Config.Vehiclekeys ~= 'ti_vehicleKeys' then
|
||||
return
|
||||
end
|
||||
|
||||
function AddVehiclekeys(vehicle, plate, item)
|
||||
exports['ti_vehicleKeys']:addTemporaryVehicle(plate)
|
||||
end
|
||||
|
||||
function RemoveVehiclekeys(vehicle, plate)
|
||||
return
|
||||
end
|
||||
@@ -0,0 +1,11 @@
|
||||
if Config.Vehiclekeys ~= 'vehicles_keys' then
|
||||
return
|
||||
end
|
||||
|
||||
function AddVehiclekeys(vehicle, plate, item)
|
||||
TriggerServerEvent('vehicles_keys:selfGiveVehicleKeys', plate)
|
||||
end
|
||||
|
||||
function RemoveVehiclekeys(vehicle, plate)
|
||||
return
|
||||
end
|
||||
@@ -0,0 +1,33 @@
|
||||
if Config.Vehiclekeys ~= 'wasabi_carlock' then
|
||||
return
|
||||
end
|
||||
|
||||
local givenKeys = {}
|
||||
|
||||
function AddVehiclekeys(vehicle, plate, item)
|
||||
if not plate or plate == '' then
|
||||
print('[WARNING] Invalid plate, unable to give key.')
|
||||
return
|
||||
end
|
||||
|
||||
if givenKeys[plate] then
|
||||
print('[INFO] Key already given for: ' .. plate)
|
||||
return
|
||||
end
|
||||
|
||||
givenKeys[plate] = true
|
||||
print('[DEBUG] Giving key via wasabi_carlock for plate: ' .. plate)
|
||||
exports.wasabi_carlock:GiveKey(plate)
|
||||
end
|
||||
|
||||
function RemoveVehiclekeys(vehicle, plate)
|
||||
if not plate or plate == '' then
|
||||
print('[WARNING] Invalid plate, unable to remove key.')
|
||||
return
|
||||
end
|
||||
|
||||
givenKeys[plate] = nil
|
||||
|
||||
print('[DEBUG] Removing key via wasabi_carlock for plate: ' .. plate)
|
||||
exports.wasabi_carlock:RemoveKey(plate)
|
||||
end
|
||||
@@ -0,0 +1,11 @@
|
||||
if Config.Vehiclekeys ~= 'xd_locksystem' then
|
||||
return
|
||||
end
|
||||
|
||||
function AddVehiclekeys(vehicle, plate, item)
|
||||
exports['xd_locksystem']:givePlayerKeys(plate)
|
||||
end
|
||||
|
||||
function RemoveVehiclekeys(vehicle, plate)
|
||||
return
|
||||
end
|
||||
@@ -0,0 +1,8 @@
|
||||
if Config.Wardrobe ~= 'ak47_clothing' then
|
||||
return
|
||||
end
|
||||
|
||||
function openWardrobe()
|
||||
exports['ak47_clothing']:openOutfit() -- if it doesn't work with this export use other event
|
||||
-- TriggerEvent('ak47_clothing:openOutfitMenu') -- Use this only if the first export doesn't work, depend of you'r version
|
||||
end
|
||||
@@ -0,0 +1,7 @@
|
||||
if Config.Wardrobe ~= 'codem-appearance' then
|
||||
return
|
||||
end
|
||||
|
||||
function openWardrobe()
|
||||
TriggerEvent('codem-apperance:OpenWardrobe')
|
||||
end
|
||||
@@ -0,0 +1,78 @@
|
||||
if Config.Wardrobe ~= 'default' then
|
||||
return
|
||||
end
|
||||
|
||||
function openWardrobe()
|
||||
if Config.Framework == 'qb' then
|
||||
return TriggerEvent('qb-clothing:client:openOutfitMenu')
|
||||
end
|
||||
|
||||
ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'room', {
|
||||
title = Lang('HOUSING_MENU_WARDROBE_DEFAULT_TITLE'),
|
||||
align = 'right',
|
||||
elements = {
|
||||
{ label = Lang('HOUSING_MENU_CLOTHES_MENU'), value = 'player_dressing' },
|
||||
{ label = Lang('HOUSING_MENU_DELETE_CLOTHES'), value = 'remove_cloth' }
|
||||
}
|
||||
}, function(data, menu)
|
||||
if data.current.value == 'player_dressing' then
|
||||
menu.close()
|
||||
TriggerServerCallback('qb-houses:server:getPlayerDressing', function(dressing)
|
||||
elements = {}
|
||||
|
||||
for i = 1, #dressing, 1 do
|
||||
table.insert(elements, {
|
||||
label = dressing[i],
|
||||
value = i
|
||||
})
|
||||
end
|
||||
|
||||
ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'player_dressing',
|
||||
{
|
||||
title = Lang('HOUSING_MENU_WARDROBE_DEFAULT_TITLE'),
|
||||
align = 'right',
|
||||
elements = elements
|
||||
}, function(data2, menu2)
|
||||
TriggerEvent('skinchanger:getSkin', function(skin)
|
||||
TriggerServerCallback('qb-houses:server:getPlayerOutfit', function(clothes)
|
||||
TriggerEvent('skinchanger:loadClothes', skin, clothes)
|
||||
TriggerEvent('esx_skin:setLastSkin', skin)
|
||||
|
||||
TriggerEvent('skinchanger:getSkin', function(skin)
|
||||
TriggerServerEvent('esx_skin:save', skin)
|
||||
end)
|
||||
end, data2.current.value)
|
||||
end)
|
||||
end, function(data2, menu2)
|
||||
menu2.close()
|
||||
end)
|
||||
end)
|
||||
elseif data.current.value == 'remove_cloth' then
|
||||
menu.close()
|
||||
TriggerServerCallback('qb-houses:server:getPlayerDressing', function(dressing)
|
||||
elements = {}
|
||||
|
||||
for i = 1, #dressing, 1 do
|
||||
table.insert(elements, {
|
||||
label = dressing[i],
|
||||
value = i
|
||||
})
|
||||
end
|
||||
|
||||
ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'remove_cloth', {
|
||||
title = Lang('HOUSING_MENU_DELETE_CLOTHES'),
|
||||
align = 'right',
|
||||
elements = elements
|
||||
}, function(data2, menu2)
|
||||
menu2.close()
|
||||
TriggerServerEvent('qb-houses:server:removeOutfit', data2.current.value)
|
||||
Notification(Lang('HOUSING_NOTIFICATION_OUTFIT_DELETE'), 'inform')
|
||||
end, function(data2, menu2)
|
||||
menu2.close()
|
||||
end)
|
||||
end)
|
||||
end
|
||||
end, function(data, menu)
|
||||
menu.close()
|
||||
end)
|
||||
end
|
||||
@@ -0,0 +1,7 @@
|
||||
if Config.Wardrobe ~= 'fivem-appearance' then
|
||||
return
|
||||
end
|
||||
|
||||
function openWardrobe()
|
||||
exports['fivem-appearance']:openWardrobe()
|
||||
end
|
||||
@@ -0,0 +1,7 @@
|
||||
if Config.Wardrobe ~= 'illenium-appearance' then
|
||||
return
|
||||
end
|
||||
|
||||
function openWardrobe()
|
||||
TriggerEvent('illenium-appearance:client:openOutfitMenu')
|
||||
end
|
||||
@@ -0,0 +1,7 @@
|
||||
if Config.Wardrobe ~= 'mAppearance' then
|
||||
return
|
||||
end
|
||||
|
||||
function openWardrobe()
|
||||
TriggerEvent('codem-appearance:OpenWardrobe')
|
||||
end
|
||||
@@ -0,0 +1,7 @@
|
||||
if Config.Wardrobe ~= 'p_appearance' then
|
||||
return
|
||||
end
|
||||
|
||||
function openWardrobe()
|
||||
exports['p_appearance']:openOutfits()
|
||||
end
|
||||
@@ -0,0 +1,7 @@
|
||||
if Config.Wardrobe ~= 'qb-clothing' then
|
||||
return
|
||||
end
|
||||
|
||||
function openWardrobe()
|
||||
TriggerEvent('qb-clothing:client:openOutfitMenu')
|
||||
end
|
||||
@@ -0,0 +1,7 @@
|
||||
if Config.Wardrobe ~= 'qs-appearance' then
|
||||
return
|
||||
end
|
||||
|
||||
function openWardrobe()
|
||||
TriggerEvent('clothing:openOutfitMenu')
|
||||
end
|
||||
@@ -0,0 +1,7 @@
|
||||
if Config.Wardrobe ~= 'raid_clothes' then
|
||||
return
|
||||
end
|
||||
|
||||
function openWardrobe()
|
||||
TriggerEvent('raid_clothes:openmenu')
|
||||
end
|
||||
@@ -0,0 +1,7 @@
|
||||
if Config.Wardrobe ~= 'rcore_clothes' then
|
||||
return
|
||||
end
|
||||
|
||||
function openWardrobe()
|
||||
TriggerEvent('rcore_clothes:openOutfits')
|
||||
end
|
||||
@@ -0,0 +1,7 @@
|
||||
if Config.Wardrobe ~= 'rcore_clothing' then
|
||||
return
|
||||
end
|
||||
|
||||
function openWardrobe()
|
||||
TriggerEvent('rcore_clothing:openChangingRoom')
|
||||
end
|
||||
@@ -0,0 +1,7 @@
|
||||
if Config.Wardrobe ~= 'sleek-clothestore' then
|
||||
return
|
||||
end
|
||||
|
||||
function openWardrobe()
|
||||
exports['sleek-clothestore']:OpenWardrobe()
|
||||
end
|
||||
@@ -0,0 +1,7 @@
|
||||
if Config.Wardrobe ~= 'tgiann-clothing' then
|
||||
return
|
||||
end
|
||||
|
||||
function openWardrobe()
|
||||
TriggerEvent('tgiann-clothing:openOutfitMenu')
|
||||
end
|
||||
@@ -0,0 +1,27 @@
|
||||
--[[
|
||||
Here you have the weather tyme configuration, you can modify it or even
|
||||
create your own! In case your inventory is not here, you can ask the
|
||||
creator to create a file following this example and add it!
|
||||
]]
|
||||
|
||||
if Config.Weather ~= 'cd_easytime' then
|
||||
return
|
||||
end
|
||||
|
||||
RegisterNetEvent('advancedgarages:GetWeatherSync')
|
||||
AddEventHandler('advancedgarages:GetWeatherSync', function(bool, time)
|
||||
if bool then
|
||||
Wait(150)
|
||||
TriggerEvent('cd_easytime:PauseSync', true)
|
||||
NetworkOverrideClockTime(time, 0, 0)
|
||||
ClearOverrideWeather()
|
||||
ClearWeatherTypePersist()
|
||||
SetWeatherTypePersist('CLEAR')
|
||||
SetWeatherTypeNow('CLEAR')
|
||||
SetWeatherTypeNowPersist('CLEAR')
|
||||
else
|
||||
Wait(150)
|
||||
TriggerEvent('cd_easytime:PauseSync', false)
|
||||
Debug('Time was resynchronized to the original')
|
||||
end
|
||||
end)
|
||||
@@ -0,0 +1,27 @@
|
||||
--[[
|
||||
Here you have the weather tyme configuration, you can modify it or even
|
||||
create your own! In case your inventory is not here, you can ask the
|
||||
creator to create a file following this example and add it!
|
||||
]]
|
||||
|
||||
if Config.Weather ~= 'qb-weathersync' then
|
||||
return
|
||||
end
|
||||
|
||||
RegisterNetEvent('advancedgarages:GetWeatherSync')
|
||||
AddEventHandler('advancedgarages:GetWeatherSync', function(bool, time)
|
||||
if bool then
|
||||
Wait(150)
|
||||
TriggerEvent('qb-weathersync:client:DisableSync')
|
||||
NetworkOverrideClockTime(time, 0, 0)
|
||||
ClearOverrideWeather()
|
||||
ClearWeatherTypePersist()
|
||||
SetWeatherTypePersist('CLEAR')
|
||||
SetWeatherTypeNow('CLEAR')
|
||||
SetWeatherTypeNowPersist('CLEAR')
|
||||
else
|
||||
Wait(150)
|
||||
TriggerEvent('qb-weathersync:client:EnableSync')
|
||||
Debug('Time was resynchronized to the original')
|
||||
end
|
||||
end)
|
||||
@@ -0,0 +1,28 @@
|
||||
--[[
|
||||
Here you have the weather tyme configuration, you can modify it or even
|
||||
create your own! In case your inventory is not here, you can ask the
|
||||
creator to create a file following this example and add it!
|
||||
]]
|
||||
|
||||
if Config.Weather ~= 'vSync' then
|
||||
return
|
||||
end
|
||||
|
||||
RegisterNetEvent('advancedgarages:GetWeatherSync')
|
||||
AddEventHandler('advancedgarages:GetWeatherSync', function(bool, time)
|
||||
if bool then
|
||||
Wait(150)
|
||||
TriggerEvent('vSync:updateWeather', 'EXTRASUNNY', false)
|
||||
NetworkOverrideClockTime(time, 0, 0)
|
||||
ClearOverrideWeather()
|
||||
ClearWeatherTypePersist()
|
||||
SetWeatherTypePersist('CLEAR')
|
||||
SetWeatherTypeNow('CLEAR')
|
||||
SetWeatherTypeNowPersist('CLEAR')
|
||||
else
|
||||
Wait(150)
|
||||
TriggerEvent('vSync:toggle', true)
|
||||
TriggerServerEvent('vSync:requestSync')
|
||||
Debug('Time was resynchronized to the original')
|
||||
end
|
||||
end)
|
||||
Reference in New Issue
Block a user