Scripts/resources/[qb]/[qb_crimes]/qb-blackmarket/server/server.lua

460 lines
15 KiB
Lua
Raw Permalink Normal View History

2024-12-29 20:03:28 +00:00
local QBCore = exports['qb-core']:GetCoreObject()
local marketItems = {}
local pendingOrders = {}
local availableLocations = {}
local function getMarketItems()
if not Config.randomItems then
for i=1, #Config.items do
local randomStock = math.random(Config.items[i].minStock, Config.items[i].maxStock)
marketItems[i] = Config.items[i]
marketItems[i].stock = randomStock
end
TriggerClientEvent("qb-blackmarket_cl:updateMarketItems", -1, marketItems)
SetTimeout(Config.reset * 60000, getMarketItems)
return
end
local copyTable = {}
for i=1, #Config.items do
copyTable[i] = Config.items[i]
end
local newLen = #copyTable
local chosenItems = {}
for i=1, Config.randomItems do
local randomIndex = math.random(newLen)
local randomStock = math.random(copyTable[randomIndex].minStock, copyTable[randomIndex].maxStock)
chosenItems[i] = copyTable[randomIndex]
chosenItems[i].stock = randomStock
table.remove(copyTable, randomIndex)
newLen -= 1
end
marketItems = chosenItems
TriggerClientEvent("qb-blackmarket_cl:updateMarketItems", -1, marketItems)
SetTimeout(Config.reset * 60000, getMarketItems)
end
local function isMarketItem(item)
local inMarket = false
for i=1, #marketItems do
if marketItems[i].item == item then
inMarket = true
break
end
end
return inMarket
end
local function checkStock(item, quantity)
local hasStock = false
for i=1, #marketItems do
if marketItems[i].item == item then
if marketItems[i].stock >= quantity then
hasStock = true
end
break
end
end
return hasStock
end
local function getItemPrice(item)
local price = 0
for i=1, #marketItems do
if marketItems[i].item == item then
price = marketItems[i].price
break
end
end
return price
end
local function updateMarketStock(item, quantity)
for i=1, #marketItems do
if marketItems[i].item == item then
marketItems[i].stock -= quantity
break
end
end
end
local function generateStashId()
local id = "GBM_"
for i=1, 6 do
id = id .. tostring(math.random(0,9))
end
return id
end
local function saveOrderStash(stashId, items, cb)
if not stashId or not items then return end
for _, item in pairs(items) do
item.description = nil
end
MySQL.insert('INSERT INTO stashitems (stash, items) VALUES (:stash, :items) ON DUPLICATE KEY UPDATE items = :items', {
['stash'] = stashId,
['items'] = json.encode(items)
}, function(id)
cb(id)
end)
end
local function deleteStash(stashId)
MySQL.query("DELETE FROM stashitems WHERE stash = ?", {stashId})
end
local function setupAvailableLocations()
for i=1, #Config.deliveryLocations do
availableLocations[#availableLocations + 1] = i
end
end
local function getRandomAvailLocation()
local chosenIndex = math.random(#availableLocations)
local locationIndex = availableLocations[chosenIndex]
table.remove(availableLocations, chosenIndex)
return locationIndex
end
local function orderComplete(index, stashId)
if not pendingOrders[index] or not pendingOrders[index].stashId == stashId then return end
if pendingOrders[index].props then
for _, v in pairs(pendingOrders[index].props) do
local entity = NetworkGetEntityFromNetworkId(v)
if DoesEntityExist(entity) then
DeleteEntity(entity)
end
end
end
if pendingOrders[index].isOpen then
TriggerClientEvent("qb-blackmarket_cl:removeLootTarget", -1, index)
else
TriggerClientEvent("qb-blackmarket_cl:removeLockTarget", -1, index)
end
deleteStash(pendingOrders[index].stashId)
if pendingOrders[index].src then
local Player = QBCore.Functions.GetPlayer(pendingOrders[index].src)
if Player.PlayerData.citizenid == pendingOrders[index].cid then
TriggerClientEvent("qb-blackmarket_cl:orderComplete", pendingOrders[index].src)
end
end
availableLocations[#availableLocations + 1] = index
pendingOrders[index] = nil
end
local function orderReady(index, stashId)
if pendingOrders[index].src then
local Player = QBCore.Functions.GetPlayer(pendingOrders[index].src)
if Player.PlayerData.citizenid == pendingOrders[index].cid then
TriggerClientEvent("qb-blackmarket_cl:orderReady", pendingOrders[index].src, index, Config.deliveryLocations[index])
end
end
SetTimeout(Config.orderTimeout * 60000, function()
orderComplete(index, stashId)
end)
end
local function cleanUpProps()
for _, v in pairs(pendingOrders) do
if v.props then
for _, prop in pairs(v.props) do
local entity = NetworkGetEntityFromNetworkId(prop)
if DoesEntityExist(entity) then
DeleteEntity(entity)
end
end
end
end
end
local function cleanUpStashes()
for _, v in pairs(pendingOrders) do
deleteStash(v.stashId)
end
end
QBCore.Functions.CreateUseableItem(Config.useItem, function(source)
local Player = QBCore.Functions.GetPlayer(source)
if not Player or not Player.Functions.GetItemByName(Config.useItem) then return end
TriggerClientEvent("qb-blackmarket_cl:openUI", source)
end)
QBCore.Functions.CreateCallback("qb-blackmarket_sv:getMarketItems", function(src, cb)
cb(marketItems)
end)
QBCore.Functions.CreateCallback("qb-blackmarket_sv:attemptOrder", function(src, cb, order)
if not order or #order == 0 then return end
local cost = 0
local Player = QBCore.Functions.GetPlayer(src)
if not Player or not Player.Functions.GetItemByName(Config.useItem) then return end
local numOfOrders = 0
for _, v in pairs(pendingOrders) do
if v.src == src or v.cid == cid then
cb({success = false, notif = "Ordre fejlet", error = "Spilleren har allerede en ordre"})
return
end
numOfOrders += 1
end
if numOfOrders >= Config.maxOrderQueue then
cb({success = false, notif = Config.notifText.maxOrder})
return
end
local playerOrder = {}
for i=1, #order do
local itemQuant = tonumber(order[i].quantity)
if not isMarketItem(order[i].item) then
cb({success = false, notif = "Ordre fejlet", error = "Ugyldig genstand fundet"})
return
end
if not checkStock(order[i].item, itemQuant) then
cb({success = false, notif = Config.notifText.insufficientStock})
return
end
if playerOrder[order[i].item] then
cb({success = false, notif = "Ordre fejlet", error = "Ordre har flere af samme genstand"})
return
end
playerOrder[order[i].item] = itemQuant
cost += getItemPrice(order[i].item) * itemQuant
end
if Player.Functions.RemoveMoney(Config.paymentType, cost) then
local locationIndex = getRandomAvailLocation()
local deliveryMins = math.random(Config.deliveryTime.min, Config.deliveryTime.max)
local deliveryTime = os.time() + (deliveryMins * 60)
local stashId = generateStashId()
pendingOrders[locationIndex] = {
src = src,
cid = Player.PlayerData.citizenid,
order = playerOrder,
deliveryTime = deliveryTime,
stashId = stashId,
lockInProgress = false,
lootInProgress = false,
isOpen = false,
isLooted = false,
}
for k,v in pairs(playerOrder) do
updateMarketStock(k, v)
end
SetTimeout(deliveryMins * 60000, function()
orderReady(locationIndex, stashId)
end)
TriggerClientEvent("qb-blackmarket_cl:updateStock", -1, marketItems, src)
cb({success = true, notif = Config.notifText.orderSuccess, epochTime = deliveryTime})
else
cb({success = false, notif = Config.notifText.cantAfford})
end
end)
RegisterNetEvent("qb-blackmarket_sv:propsSpawned", function(netIds, locationIndex)
if not pendingOrders[locationIndex] then return end
local lock = NetworkGetEntityFromNetworkId(netIds.lock)
local lockCoords = vec4(GetEntityCoords(lock), GetEntityHeading(lock))
pendingOrders[locationIndex].props = netIds
TriggerClientEvent("qb-blackmarket_cl:addLockTarget", -1, locationIndex, lockCoords)
end)
RegisterNetEvent("qb-blackmarket_sv:attemptContainer", function(index)
local src = source
if #(GetEntityCoords(GetPlayerPed(src)) - vec3(Config.deliveryLocations[index])) > 5 or not pendingOrders[index] then return end
if pendingOrders[index].lockInProgress then
TriggerClientEvent('QBCore:Notify', src, "Nogen er allerede igang med dette", "error")
return
end
if pendingOrders[index].isOpen then
TriggerClientEvent('QBCore:Notify', src, "Dette er allerede åbnet", "error")
return
end
pendingOrders[index].lockInProgress = true
TriggerClientEvent("qb-blackmarket_cl:openContainer", src, index, pendingOrders[index].props)
end)
RegisterNetEvent("qb-blackmarket_sv:openContainer", function(index)
local src = source
local crate = NetworkGetEntityFromNetworkId(pendingOrders[index].props.crate)
local crateCoords = vec4(GetEntityCoords(crate), GetEntityHeading(crate))
pendingOrders[index].lockInProgress = false
pendingOrders[index].isOpen = true
pendingOrders[index].props.lock = nil
TriggerClientEvent("qb-blackmarket_cl:updateOpenContainer", -1, index, pendingOrders[index].props.container, pendingOrders[index].props.collision, crateCoords, true)
end)
RegisterNetEvent("qb-blackmarket_sv:attemptLoot", function(index)
local src = source
if #(GetEntityCoords(GetPlayerPed(src)) - vec3(Config.deliveryLocations[index])) > 5 or not pendingOrders[index] then return end
if pendingOrders[index].lootInProgress then
TriggerClientEvent('QBCore:Notify', src, "Nogen er allerede igang med dette", "error")
return
end
if pendingOrders[index].isLooted then
TriggerClientEvent("inventory:client:SetCurrentStash", src, pendingOrders[index].stashId)
exports["ps-inventory"]:OpenInventory("stash", pendingOrders[index].stashId, nil, src)
return
end
pendingOrders[index].lootInProgress = true
TriggerClientEvent("qb-blackmarket_cl:lootContainer", src, index)
end)
RegisterNetEvent("qb-blackmarket_sv:finishLooting", function(index)
local src = source
if #(GetEntityCoords(GetPlayerPed(src)) - vec3(Config.deliveryLocations[index])) > 5 or not pendingOrders[index] or pendingOrders[index].isLooted then return end
local orderItems = {}
local stashId = pendingOrders[index].stashId
local slot = 1
for k, v in pairs(pendingOrders[index].order) do
local itemInfo = QBCore.Shared.Items[k:lower()]
if itemInfo then
itemInfo.info = {}
itemInfo.amount = v
itemInfo.slot = slot
-- If item has metedata add it here
if itemInfo.type == "weapon" then
itemInfo.info.serie = tostring(QBCore.Shared.RandomInt(2) .. QBCore.Shared.RandomStr(3) .. QBCore.Shared.RandomInt(1) .. QBCore.Shared.RandomStr(2) .. QBCore.Shared.RandomInt(3) .. QBCore.Shared.RandomStr(4))
itemInfo.info.quality = 100
end
orderItems[#orderItems + 1] = itemInfo
end
slot += 1
end
saveOrderStash(stashId, orderItems, function(id)
if id then
TriggerClientEvent("inventory:client:SetCurrentStash", src, stashId)
exports["ps-inventory"]:OpenInventory("stash", stashId, nil, src)
end
end)
pendingOrders[index].lootInProgress = false
pendingOrders[index].isLooted = true
SetTimeout(Config.lootTimeout * 60000, function()
orderComplete(index, stashId)
end)
end)
RegisterNetEvent("qb-blackmarket_sv:cancelLooting", function(index)
pendingOrders[index].lootInProgress = false
end)
RegisterNetEvent("qb-blackmarket_sv:initPendingOrders", function()
local src = source
local Player = QBCore.Functions.GetPlayer(src)
for k, v in pairs(pendingOrders) do
-- check if player has any pending orders
if v.cid == Player.PlayerData.citizenid then
v.src = src
TriggerClientEvent("qb-blackmarket_cl:hasPendingOrder", src, marketItems, v.order, v.deliveryTime)
-- create props if needed
local propDespawned = false
if v.props then
for prop, netId in pairs(v.props) do
local entity = NetworkGetEntityFromNetworkId(netId)
if not DoesEntityExist(entity) then
if not (v.isOpen and prop == "lock") then
propDespawned = true
end
end
end
end
if propDespawned then
for prop, netId in pairs(v.props) do
local entity = NetworkGetEntityFromNetworkId(netId)
if not DoesEntityExist(entity) then
DeleteEntity(entity)
end
end
v.props = nil
end
if os.time() - v.deliveryTime > 0 then
if not v.props then
-- removes targets since it gets recreated later
if v.isOpen then
TriggerClientEvent("qb-blackmarket_cl:removeLootTarget", -1, k)
v.isOpen = false
end
TriggerClientEvent("qb-blackmarket_cl:orderReady", src, k, Config.deliveryLocations[k])
else
TriggerClientEvent("qb-blackmarket_cl:enableLocateButton", src, k)
end
end
end
-- Create target zones for pending orders
if v.props then
if not v.isOpen then
local lock = NetworkGetEntityFromNetworkId(v.props.lock)
local lockCoords = vec4(GetEntityCoords(lock), GetEntityHeading(lock))
TriggerClientEvent("qb-blackmarket_cl:addLockTarget", src, k, lockCoords)
else
local crate = NetworkGetEntityFromNetworkId(v.props.crate)
local crateCoords = vec4(GetEntityCoords(crate), GetEntityHeading(crate))
TriggerClientEvent("qb-blackmarket_cl:updateOpenContainer", src, k, v.props.container, v.props.collision, crateCoords, false)
end
end
end
TriggerClientEvent("qb-blackmarket_cl:updateMarketItems", src, marketItems)
end)
AddEventHandler('playerDropped', function()
local src = source
for _, v in pairs(pendingOrders) do
if v.src == src then
v.src = nil
end
end
end)
AddEventHandler('onResourceStart', function(resource)
if resource ~= GetCurrentResourceName() then return end
getMarketItems()
setupAvailableLocations()
end)
AddEventHandler("onResourceStop", function(resource)
if resource ~= GetCurrentResourceName() then return end
cleanUpProps()
cleanUpStashes()
end)