484 lines
18 KiB
Lua
484 lines
18 KiB
Lua
|
|
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)
|