if not lib then return end local shopTypes = {} local shops = {} local createBlip = require 'modules.utils.client'.CreateBlip for shopType, shopData in pairs(data('shops') --[[@as table]]) do local shop = { name = shopData.name, groups = shopData.groups or shopData.jobs, blip = shopData.blip, label = shopData.label, icon = shopData.icon, } if shared.target then shop.model = shopData.model shop.targets = shopData.targets else shop.model = shopData.model or nil shop.locations = shopData.locations end shopTypes[shopType] = shop local blip = shop.blip if blip then blip.name = ('ox_shop_%s'):format(shopType) AddTextEntry(blip.name, shop.name or shopType) end end ---@param point CPoint local function nearbyShop(point) ---@diagnostic disable-next-line: param-type-mismatch DrawMarker(2, point.coords.x, point.coords.y, point.coords.z, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.3, 0.2, 0.15, 30, 150, 30, 222, false, false, 0, true, false, false, false) if point.isClosest and point.currentDistance < 1.2 and IsControlJustReleased(0, 38) then client.openInventory('shop', { id = point.invId, type = point.type }) end end ---@param point CPoint local function onEnterShop(point) if not point.entity then local model = lib.requestModel(point.ped) if not model then return end local entity = CreatePed(0, model, point.coords.x, point.coords.y, point.coords.z, point.heading, false, true) if point.scenario then TaskStartScenarioInPlace(entity, point.scenario, 0, true) end SetModelAsNoLongerNeeded(model) FreezeEntityPosition(entity, true) SetEntityInvincible(entity, true) SetBlockingOfNonTemporaryEvents(entity, true) exports.ox_target:addLocalEntity(entity, { { icon = point.icon or 'fas fa-shopping-basket', label = point.label, groups = point.groups, onSelect = function() client.openInventory('shop', { id = point.invId, type = point.type }) end, iconColor = point.iconColor, distance = point.shopDistance or 2.0 } }) point.entity = entity end end local function SpawnPed(ped, coords) local model = lib.requestModel(ped) if not model then return end local entity = CreatePed(0, model, coords.x, coords.y, coords.z, coords.heading, false, true) SetModelAsNoLongerNeeded(model) FreezeEntityPosition(entity, true) SetEntityInvincible(entity, true) SetBlockingOfNonTemporaryEvents(entity, true) end local Utils = require 'modules.utils.client' local function onExitShop(point) local entity = point.entity if not entity then return end exports.ox_target:removeLocalEntity(entity) Utils.DeleteEntity(entity) point.entity = nil end local function hasShopAccess(shop) return not shop.groups or client.hasGroup(shop.groups) end local function wipeShops() for i = 1, #shops do local shop = shops[i] if shop.zoneId then exports.ox_target:removeZone(shop.zoneId) shop.zoneId = nil end if shop.remove then if shop.entity then onExitShop(shop) end shop:remove() end if shop.blip then RemoveBlip(shop.blip) end end table.wipe(shops) end local function refreshShops() wipeShops() local id = 0 for type, shop in pairs(shopTypes) do local blip = shop.blip local label = shop.label or locale('open_label', shop.name) if shared.target then if shop.model then if not hasShopAccess(shop) then goto skipLoop end exports.ox_target:removeModel(shop.model, shop.name) exports.ox_target:addModel(shop.model, { { name = shop.name, icon = shop.icon or 'fas fa-shopping-basket', label = label, onSelect = function() client.openInventory('shop', { type = type }) end, distance = 2 }, }) elseif shop.targets then for i = 1, #shop.targets do local target = shop.targets[i] local shopid = ('%s-%s'):format(type, i) if target.ped then id += 1 shops[id] = lib.points.new({ coords = target.loc, heading = target.heading, distance = 60, inv = 'shop', invId = i, type = type, blip = blip and hasShopAccess(shop) and createBlip(blip, target.loc), ped = target.ped, scenario = target.scenario, label = label, groups = shop.groups, icon = shop.icon, iconColor = target.iconColor, onEnter = onEnterShop, onExit = onExitShop, shopDistance = target.distance, }) else if not hasShopAccess(shop) then goto nextShop end id += 1 shops[id] = { zoneId = Utils.CreateBoxZone(target, { { name = shopid, icon = 'fas fa-shopping-basket', label = label, groups = shop.groups, onSelect = function() client.openInventory('shop', { id = i, type = type }) end, iconColor = target.iconColor, } }), blip = blip and createBlip(blip, target.coords) } end ::nextShop:: end end elseif shop.locations then if not hasShopAccess(shop) then goto skipLoop end for i = 1, #shop.locations do local coords = shop.locations[i] id += 1 if shop.model then local ncoords = {x = coords.x, y = coords.y, z = coords.z - 1.0, heading = shop.heading} SpawnPed(shop.model, ncoords) end shops[id] = lib.points.new(coords, 16, { coords = coords, distance = 16, inv = 'shop', invId = i, type = type, nearby = nearbyShop, blip = blip and createBlip(blip, coords) }) end end ::skipLoop:: end end return { refreshShops = refreshShops, wipeShops = wipeShops, }