308 lines
No EOL
9.5 KiB
Lua
308 lines
No EOL
9.5 KiB
Lua
local shopZones, shopPeds, shopPoints = {}, {}, {}
|
|
local stashZones, stashPeds, stashPoints = {}, {}, {}
|
|
|
|
local function drawMarkerOnFrame(coords, marker)
|
|
---@diagnostic disable-next-line: missing-parameter
|
|
DrawMarker(marker.id, coords.x, coords.y, coords.z, 0, 0, 0, 0, 0, 0, marker.size.x, marker.size.y, marker.size.z, marker.color.r, marker.color.g, marker.color.b, marker.color.a, marker.bobUpAndDown, marker.faceCamera, 0, marker.rotate, marker.drawOnEnts)
|
|
end
|
|
|
|
local function drawCustomMarker(center, marker, shopDistance, mechanicId, shopName, stashName)
|
|
if not marker then
|
|
if shopName and not stashName then
|
|
debugPrint("Marker is not setup for [SHOPS] ".. shopName .. " for location: " .. mechanicId, "warning")
|
|
elseif stashName then
|
|
debugPrint("Marker is not setup for [STASHES] " .. stashName .. " for location: " .. mechanicId, "warning")
|
|
end
|
|
|
|
return
|
|
end
|
|
|
|
local point = lib.points.new({
|
|
coords = center,
|
|
distance = shopDistance or 20,
|
|
})
|
|
|
|
function point:nearby()
|
|
drawMarkerOnFrame(center, marker)
|
|
end
|
|
|
|
return point
|
|
end
|
|
|
|
local function openShop(mechanicId, shopIndex)
|
|
local mechanicConfig = Config.MechanicLocations[mechanicId]
|
|
|
|
if not mechanicConfig or not mechanicConfig.shops or not mechanicConfig.shops[shopIndex] then
|
|
Framework.Client.Notify("Shop not found: " .. mechanicId .. " .. index: " .. shopIndex, "error")
|
|
return
|
|
end
|
|
|
|
local shop = mechanicConfig.shops[shopIndex]
|
|
local shopItems = shop.items or {}
|
|
|
|
local options = {}
|
|
for index, v in pairs(shopItems) do
|
|
table.insert(options, {
|
|
title = v.label,
|
|
icon = "box",
|
|
description = ("Buy for %d %s"):format(v.price, Config.Currency),
|
|
event = "jg-mechanic:client:input-shop-purchase-qty",
|
|
args = { shopIndex = shopIndex, itemIndex = index, item = v.name, price = v.price, mechanicId = mechanicId }
|
|
})
|
|
end
|
|
|
|
local context = {
|
|
id = "shop_" .. mechanicId .. "_" .. shopIndex,
|
|
title = shop.name .. " Shop",
|
|
options = options
|
|
}
|
|
|
|
lib.registerContext(context)
|
|
lib.showContext("shop_" .. mechanicId .. "_" .. shopIndex)
|
|
end
|
|
|
|
RegisterNetEvent("jg-mechanic:client:input-shop-purchase-qty", function(args)
|
|
local input = lib.inputDialog("Enter the amount you want to buy", { "Amount" })
|
|
|
|
if not input then
|
|
Framework.Client.Notify("Invalid amount", "error")
|
|
return
|
|
end
|
|
|
|
local qty = tonumber(input[1])
|
|
if qty == nil or qty <= 0 then
|
|
Framework.Client.Notify("Invalid amount entered", "error")
|
|
return
|
|
end
|
|
|
|
TriggerServerEvent("jg-mechanic:server:buy-item", args.shopIndex, args.itemIndex, qty, args.mechanicId)
|
|
end)
|
|
|
|
function createMechanicShops()
|
|
for _, zone in pairs(shopZones) do
|
|
if zone and zone.remove then zone:remove() end
|
|
end
|
|
|
|
for _, ped in pairs(shopPeds) do
|
|
if ped then DeleteEntity(ped) end
|
|
end
|
|
|
|
for _, point in pairs(shopPoints) do
|
|
if point and point.remove then point:remove() end
|
|
end
|
|
|
|
shopZones, shopPeds, shopPoints = {}, {}, {}
|
|
|
|
for mechanicId, mechanicConfig in pairs(Config.MechanicLocations) do
|
|
local isMechanicEmployee = lib.callback.await("jg-mechanic:server:is-mechanic-employee", false, mechanicId)
|
|
if not isMechanicEmployee then goto continue end
|
|
|
|
if not mechanicConfig.shops then
|
|
debugPrint(("No shops defined for '%s' in Config.MechanicLocations"):format(mechanicId), "warning")
|
|
goto continue
|
|
end
|
|
|
|
for shopIndex, shop in ipairs(mechanicConfig.shops) do
|
|
if shop.type == "self-service" then
|
|
debugPrint(("Skipping self-service shop for '%s' (index: %d)"):format(mechanicId, shopIndex), "debug")
|
|
goto shop_continue
|
|
end
|
|
|
|
if not shop.coords or not shop.size then
|
|
debugPrint(("Invalid shop data for '%s' (index: %d) - missing coords or size"):format(mechanicId, shopIndex), "warning")
|
|
end
|
|
|
|
if shop.usePed then
|
|
local ped = createPedForTarget(shop.pedModel or "s_m_m_lathandy_01", shop.coords.xyz)
|
|
shopPeds[#shopPeds+1] = ped
|
|
|
|
-- If vec4, set heading
|
|
if shop.coords.w then
|
|
SetEntityHeading(ped, shop.coords.w or 0)
|
|
end
|
|
|
|
if Config.Target == "qb-target" then
|
|
exports["qb-target"]:AddTargetEntity(ped, {
|
|
options = {
|
|
{
|
|
label = "Access Shop",
|
|
icon = "fas fa-store",
|
|
action = function()
|
|
openShop(mechanicId, shopIndex)
|
|
end,
|
|
},
|
|
},
|
|
distance = 2.5,
|
|
})
|
|
elseif Config.Target == "ox_target" then
|
|
exports.ox_target:addLocalEntity(ped, {
|
|
{
|
|
name = "access_shop_" .. mechanicId .. "_" .. shopIndex,
|
|
label = "Access Shop",
|
|
icon = "fas fa-store",
|
|
onSelect = function()
|
|
openShop(mechanicId, shopIndex)
|
|
end,
|
|
},
|
|
})
|
|
end
|
|
else
|
|
local zoneData = {
|
|
coords = shop.coords,
|
|
size = vector3(shop.size, shop.size, 2.0),
|
|
rotation = shop.coords.w or 0,
|
|
debug = Config.Debug,
|
|
onEnter = function()
|
|
Framework.Client.ShowTextUI("Press [E] to access " .. shop.name)
|
|
end,
|
|
onExit = function()
|
|
Framework.Client.HideTextUI()
|
|
lib.hideContext()
|
|
end,
|
|
inside = function()
|
|
if IsControlJustReleased(0, 38) then
|
|
openShop(mechanicId, shopIndex)
|
|
end
|
|
end
|
|
}
|
|
|
|
local zone = lib.zones.box(zoneData)
|
|
shopZones[#shopZones+1] = zone
|
|
|
|
local point = drawCustomMarker(shop.coords, shop.marker, 10.0, mechanicId, shop.name, nil)
|
|
shopPoints[#shopPoints + 1] = point
|
|
end
|
|
|
|
::shop_continue::
|
|
end
|
|
|
|
::continue::
|
|
end
|
|
end
|
|
|
|
function createMechanicStashes()
|
|
for _, zone in pairs(stashZones) do
|
|
if zone and zone.remove then zone:remove() end
|
|
end
|
|
|
|
for _, ped in pairs(stashPeds) do
|
|
if ped then DeleteEntity(ped) end
|
|
end
|
|
|
|
for _, point in pairs(stashPoints) do
|
|
if point and point.remove then point:remove() end
|
|
end
|
|
|
|
stashZones, stashPeds, stashPoints = {}, {}, {}
|
|
|
|
for mechanicId, mechanicConfig in pairs(Config.MechanicLocations) do
|
|
local isMechanicEmployee = lib.callback.await("jg-mechanic:server:is-mechanic-employee", false, mechanicId)
|
|
if not isMechanicEmployee then goto continue end
|
|
|
|
if not mechanicConfig or not mechanicConfig.stashes then
|
|
debugPrint(("No stashes defined for '%s' in Config.MechanicLocations"):format(mechanicId), "warning")
|
|
goto continue
|
|
end
|
|
|
|
for stashIndex, stash in ipairs(mechanicConfig.stashes) do
|
|
if stash.type == "self-service" then
|
|
debugPrint(("Skipping self-service stash for '%s' (index: %d)"):format(mechanicId, stashIndex), "debug")
|
|
goto stash_continue
|
|
end
|
|
|
|
if not stash.coords or not stash.size then
|
|
debugPrint(("Invalid stash data for '%s' (index: %d) - missing coords or size"):format(mechanicId, stashIndex), "warning")
|
|
goto stash_continue
|
|
end
|
|
|
|
local stashId = mechanicId .. "_" .. stash.name:gsub(" ", "_"):lower() .. "_" .. stashIndex
|
|
|
|
if stash.usePed then
|
|
local ped = createPedForTarget(stash.pedModel or "s_m_m_lathandy_01", stash.coords.xyz)
|
|
stashPeds[#stashPeds + 1] = ped
|
|
|
|
-- If vec4, set heading
|
|
if stash.coords.w then
|
|
SetEntityHeading(ped, stash.coords.w or 0)
|
|
end
|
|
|
|
if Config.Target == "qb-target" then
|
|
exports["qb-target"]:AddTargetEntity(ped, {
|
|
options = {
|
|
{
|
|
label = "Access Stash",
|
|
icon = "fas fa-box",
|
|
action = function()
|
|
Framework.Client.OpenInventoryStash(stashId, stash.name)
|
|
end,
|
|
},
|
|
},
|
|
distance = 2.5,
|
|
})
|
|
elseif Config.Target == "ox_target" then
|
|
exports.ox_target:addLocalEntity(ped, {
|
|
{
|
|
name = "access_stash_" .. stashId,
|
|
label = "Access Stash",
|
|
icon = "fas fa-box",
|
|
onSelect = function()
|
|
Framework.Client.OpenInventoryStash(stashId, stash.name)
|
|
end,
|
|
},
|
|
})
|
|
end
|
|
else
|
|
local zoneData = {
|
|
coords = stash.coords,
|
|
size = vector3(stash.size, stash.size, 2.0),
|
|
rotation = stash.coords.w or 0,
|
|
debug = Config.Debug,
|
|
onEnter = function()
|
|
Framework.Client.ShowTextUI("Press [E] to access " .. stash.name)
|
|
end,
|
|
onExit = function()
|
|
Framework.Client.HideTextUI()
|
|
end,
|
|
inside = function()
|
|
if IsControlJustReleased(0, 38) then
|
|
Framework.Client.OpenInventoryStash(stashId, stash.name)
|
|
end
|
|
end
|
|
}
|
|
|
|
local zone = lib.zones.box(zoneData)
|
|
stashZones[#stashZones + 1] = zone
|
|
|
|
local point = drawCustomMarker(stash.coords, stash.marker, 10.0, mechanicId, nil, stash.name)
|
|
stashPoints[#stashPoints + 1] = point
|
|
end
|
|
|
|
::stash_continue::
|
|
end
|
|
|
|
::continue::
|
|
end
|
|
end
|
|
|
|
-- Remove peds on resource stop/restart
|
|
AddEventHandler("onResourceStop", function(resource)
|
|
if resource ~= GetCurrentResourceName() then return end
|
|
|
|
if shopPeds then
|
|
for _, ped in pairs(shopPeds) do
|
|
if DoesEntityExist(ped) then
|
|
DeleteEntity(ped)
|
|
end
|
|
end
|
|
shopPeds = {}
|
|
end
|
|
|
|
if stashPeds then
|
|
for _, ped in pairs(stashPeds) do
|
|
if DoesEntityExist(ped) then
|
|
DeleteEntity(ped)
|
|
end
|
|
end
|
|
stashPeds = {}
|
|
end
|
|
end) |