447 lines
17 KiB
Lua
447 lines
17 KiB
Lua
|
QBCore = exports['qb-core']:GetCoreObject()
|
||
|
local currentDealer = nil
|
||
|
local dealerIsHome = false
|
||
|
local waitingDelivery = nil
|
||
|
local activeDelivery = nil
|
||
|
local deliveryTimeout = 0
|
||
|
local waitingKeyPress = false
|
||
|
local dealerCombo = nil
|
||
|
local drugDeliveryZone
|
||
|
|
||
|
-- Handlers
|
||
|
|
||
|
AddStateBagChangeHandler('isLoggedIn', nil, function(_, _, value)
|
||
|
if value then
|
||
|
QBCore.Functions.TriggerCallback('qb-drugs:server:RequestConfig', function(DealerConfig)
|
||
|
Config.Dealers = DealerConfig
|
||
|
end)
|
||
|
Wait(1000)
|
||
|
InitZones()
|
||
|
else
|
||
|
if not Config.UseTarget and dealerCombo then dealerCombo:destroy() end
|
||
|
end
|
||
|
end)
|
||
|
|
||
|
-- Functions
|
||
|
|
||
|
local function GetClosestDealer()
|
||
|
local ped = PlayerPedId()
|
||
|
local pCoords = GetEntityCoords(ped)
|
||
|
for k,v in pairs(Config.Dealers) do
|
||
|
local dealerCoords = vector3(v.coords.x, v.coords.y, v.coords.z)
|
||
|
if #(pCoords - dealerCoords) < 2 then
|
||
|
currentDealer = k
|
||
|
break
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
local function OpenDealerShop()
|
||
|
GetClosestDealer()
|
||
|
local repItems = {}
|
||
|
repItems.label = Config.Dealers[currentDealer]["name"]
|
||
|
repItems.items = {}
|
||
|
repItems.slots = 30
|
||
|
for k, _ in pairs(Config.Dealers[currentDealer]["products"]) do
|
||
|
if QBCore.Functions.GetPlayerData().metadata["dealerrep"] >= Config.Dealers[currentDealer]["products"][k].minrep then
|
||
|
repItems.items[k] = Config.Dealers[currentDealer]["products"][k]
|
||
|
end
|
||
|
end
|
||
|
TriggerServerEvent("inventory:server:OpenInventory", "shop", "Dealer_"..Config.Dealers[currentDealer]["name"], repItems)
|
||
|
end
|
||
|
|
||
|
local function KnockDoorAnim(home)
|
||
|
local knockAnimLib = "timetable@jimmy@doorknock@"
|
||
|
local knockAnim = "knockdoor_idle"
|
||
|
local PlayerPed = PlayerPedId()
|
||
|
local myData = QBCore.Functions.GetPlayerData()
|
||
|
if home then
|
||
|
TriggerServerEvent("InteractSound_SV:PlayOnSource", "knock_door", 0.2)
|
||
|
Wait(100)
|
||
|
while (not HasAnimDictLoaded(knockAnimLib)) do
|
||
|
RequestAnimDict(knockAnimLib)
|
||
|
Wait(100)
|
||
|
end
|
||
|
TaskPlayAnim(PlayerPed, knockAnimLib, knockAnim, 3.0, 3.0, -1, 1, 0, false, false, false )
|
||
|
Wait(3500)
|
||
|
TaskPlayAnim(PlayerPed, knockAnimLib, "exit", 3.0, 3.0, -1, 1, 0, false, false, false)
|
||
|
Wait(1000)
|
||
|
dealerIsHome = true
|
||
|
|
||
|
exports['hp_hud']:Notification('info', Config.Dealers[currentDealer]["name"], Lang:t("info.fred_knock_message", {firstName = myData.charinfo.firstname}))
|
||
|
exports['qb-core']:DrawText(Lang:t("info.other_dealers_button"), 'top')
|
||
|
AwaitingInput()
|
||
|
else
|
||
|
TriggerServerEvent("InteractSound_SV:PlayOnSource", "knock_door", 0.2)
|
||
|
Wait(100)
|
||
|
while (not HasAnimDictLoaded(knockAnimLib)) do
|
||
|
RequestAnimDict(knockAnimLib)
|
||
|
Wait(100)
|
||
|
end
|
||
|
TaskPlayAnim(PlayerPed, knockAnimLib, knockAnim, 3.0, 3.0, -1, 1, 0, false, false, false )
|
||
|
Wait(3500)
|
||
|
TaskPlayAnim(PlayerPed, knockAnimLib, "exit", 3.0, 3.0, -1, 1, 0, false, false, false)
|
||
|
Wait(1000)
|
||
|
QBCore.Functions.Notify(Lang:t("info.no_one_home"), 'error')
|
||
|
end
|
||
|
end
|
||
|
|
||
|
local function KnockDealerDoor()
|
||
|
GetClosestDealer()
|
||
|
local hours = GetClockHours()
|
||
|
local min = Config.Dealers[currentDealer]["time"]["min"]
|
||
|
local max = Config.Dealers[currentDealer]["time"]["max"]
|
||
|
if max < min then
|
||
|
if hours <= max then
|
||
|
KnockDoorAnim(true)
|
||
|
elseif hours >= min then
|
||
|
KnockDoorAnim(true)
|
||
|
else
|
||
|
KnockDoorAnim(false)
|
||
|
end
|
||
|
else
|
||
|
if hours >= min and hours <= max then
|
||
|
KnockDoorAnim(true)
|
||
|
else
|
||
|
KnockDoorAnim(false)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
local function RandomDeliveryItemOnRep()
|
||
|
local myRep = QBCore.Functions.GetPlayerData().metadata["dealerrep"]
|
||
|
local availableItems = {}
|
||
|
for k, _ in pairs(Config.DeliveryItems) do
|
||
|
if Config.DeliveryItems[k]["minrep"] <= myRep then
|
||
|
availableItems[#availableItems+1] = k
|
||
|
end
|
||
|
end
|
||
|
return availableItems[math.random(1, #availableItems)]
|
||
|
end
|
||
|
|
||
|
local function RequestDelivery()
|
||
|
if not waitingDelivery then
|
||
|
GetClosestDealer()
|
||
|
local location = math.random(1, #Config.DeliveryLocations)
|
||
|
local amount = math.random(1, 3)
|
||
|
local item = RandomDeliveryItemOnRep()
|
||
|
waitingDelivery = {
|
||
|
["coords"] = Config.DeliveryLocations[location]["coords"],
|
||
|
["location"] = location,
|
||
|
["locationLabel"] = Config.DeliveryLocations[location]["label"],
|
||
|
["amount"] = amount,
|
||
|
["dealer"] = currentDealer,
|
||
|
["itemData"] = Config.DeliveryItems[item],
|
||
|
["item"] = item
|
||
|
}
|
||
|
QBCore.Functions.Notify(Lang:t("info.sending_delivery_email"), 'success')
|
||
|
-- TriggerServerEvent('qb-drugs:server:giveDeliveryItems', waitingDelivery)
|
||
|
SetTimeout(2000, function()
|
||
|
TriggerServerEvent('qb-phone:server:sendNewMail', {
|
||
|
sender = Config.Dealers[currentDealer]["name"],
|
||
|
subject = "Leverings informationer",
|
||
|
message = Lang:t("info.delivery_info_email", {itemAmount = amount, itemLabel = QBCore.Shared.Items[waitingDelivery["itemData"]["item"]]["label"]}),
|
||
|
button = {
|
||
|
enabled = true,
|
||
|
buttonEvent = "qb-drugs:client:setLocation",
|
||
|
buttonData = waitingDelivery
|
||
|
}
|
||
|
})
|
||
|
end)
|
||
|
else
|
||
|
QBCore.Functions.Notify(Lang:t("error.pending_delivery"), 'error')
|
||
|
end
|
||
|
end
|
||
|
|
||
|
local function DeliveryTimer()
|
||
|
CreateThread(function()
|
||
|
while deliveryTimeout - 1 > 0 do
|
||
|
deliveryTimeout -= 1
|
||
|
Wait(1000)
|
||
|
end
|
||
|
deliveryTimeout = 0
|
||
|
end)
|
||
|
end
|
||
|
|
||
|
local function PoliceCall()
|
||
|
if Config.PoliceCallChance <= math.random(1, 100) then
|
||
|
exports['ps-dispatch']:DrugSale()
|
||
|
TriggerServerEvent('police:server:policeAlert', 'Salg af stoffer på:')
|
||
|
end
|
||
|
end
|
||
|
|
||
|
local function DeliverStuff()
|
||
|
if deliveryTimeout > 0 then
|
||
|
Wait(500)
|
||
|
TriggerEvent('animations:client:EmoteCommandStart', {"bumbin"})
|
||
|
PoliceCall()
|
||
|
QBCore.Functions.Progressbar("work_dropbox", Lang:t("info.delivering_products"), 3500, false, true, {
|
||
|
disableMovement = true,
|
||
|
disableCarMovement = true,
|
||
|
disableMouse = false,
|
||
|
disableCombat = true,
|
||
|
}, {}, {}, {}, function() -- Done
|
||
|
TriggerServerEvent('qb-drugs:server:successDelivery', activeDelivery, true)
|
||
|
activeDelivery = nil
|
||
|
ClearPedTasks(PlayerPedId())
|
||
|
if Config.UseTarget then
|
||
|
exports['qb-target']:RemoveZone('drugDeliveryZone')
|
||
|
else
|
||
|
drugDeliveryZone:destroy()
|
||
|
end
|
||
|
end, function() -- Cancel
|
||
|
ClearPedTasks(PlayerPedId())
|
||
|
end)
|
||
|
else
|
||
|
TriggerServerEvent('qb-drugs:server:successDelivery', activeDelivery, false)
|
||
|
end
|
||
|
deliveryTimeout = 0
|
||
|
end
|
||
|
|
||
|
local function SetMapBlip(x, y)
|
||
|
SetNewWaypoint(x, y)
|
||
|
QBCore.Functions.Notify(Lang:t("success.route_has_been_set"), 'success');
|
||
|
end
|
||
|
|
||
|
-- PolyZone specific functions
|
||
|
|
||
|
function AwaitingInput()
|
||
|
CreateThread(function()
|
||
|
waitingKeyPress = true
|
||
|
while waitingKeyPress do
|
||
|
if not dealerIsHome then
|
||
|
if IsControlPressed(0, 38) then
|
||
|
exports['qb-core']:KeyPressed()
|
||
|
KnockDealerDoor()
|
||
|
end
|
||
|
elseif dealerIsHome then
|
||
|
if IsControlJustPressed(0, 38) then
|
||
|
OpenDealerShop()
|
||
|
exports['qb-core']:KeyPressed()
|
||
|
waitingKeyPress = false
|
||
|
end
|
||
|
if IsControlJustPressed(0, 47) then
|
||
|
if waitingDelivery then
|
||
|
exports['qb-core']:KeyPressed()
|
||
|
waitingKeyPress = false
|
||
|
end
|
||
|
RequestDelivery()
|
||
|
exports['qb-core']:KeyPressed()
|
||
|
dealerIsHome = false
|
||
|
waitingKeyPress = false
|
||
|
end
|
||
|
end
|
||
|
Wait(0)
|
||
|
end
|
||
|
end)
|
||
|
end
|
||
|
|
||
|
function InitZones()
|
||
|
|
||
|
if next(Config.Dealers) == nil then return end
|
||
|
|
||
|
if Config.UseTarget then
|
||
|
for k,v in pairs(Config.Dealers) do
|
||
|
exports["qb-target"]:AddBoxZone("dealer_"..k, vector3(v.coords.x, v.coords.y, v.coords.z), 1.5, 1.5, {
|
||
|
name = "dealer_"..k,
|
||
|
heading = v.heading,
|
||
|
minZ = v.coords.z - 1,
|
||
|
maxZ = v.coords.z + 1,
|
||
|
debugPoly = false,
|
||
|
}, {
|
||
|
options = {
|
||
|
{
|
||
|
icon = 'fas fa-user-secret',
|
||
|
label = Lang:t("info.target_request"),
|
||
|
action = function()
|
||
|
RequestDelivery()
|
||
|
end,
|
||
|
canInteract = function()
|
||
|
GetClosestDealer()
|
||
|
local hours = GetClockHours()
|
||
|
local min = Config.Dealers[currentDealer]["time"]["min"]
|
||
|
local max = Config.Dealers[currentDealer]["time"]["max"]
|
||
|
if max < min then
|
||
|
if hours <= max then
|
||
|
if not waitingDelivery then
|
||
|
return true
|
||
|
end
|
||
|
elseif hours >= min then
|
||
|
if not waitingDelivery then
|
||
|
return true
|
||
|
end
|
||
|
end
|
||
|
else
|
||
|
if hours >= min and hours <= max then
|
||
|
if not waitingDelivery then
|
||
|
return true
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
},
|
||
|
{
|
||
|
icon = 'fas fa-user-secret',
|
||
|
label = Lang:t("info.target_openshop"),
|
||
|
action = function()
|
||
|
OpenDealerShop()
|
||
|
end,
|
||
|
canInteract = function()
|
||
|
GetClosestDealer()
|
||
|
local hours = GetClockHours()
|
||
|
local min = Config.Dealers[currentDealer]["time"]["min"]
|
||
|
local max = Config.Dealers[currentDealer]["time"]["max"]
|
||
|
if max < min then
|
||
|
if hours <= max then
|
||
|
return true
|
||
|
elseif hours >= min then
|
||
|
return true
|
||
|
end
|
||
|
else
|
||
|
if hours >= min and hours <= max then
|
||
|
return true
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
}
|
||
|
},
|
||
|
distance = 1.5
|
||
|
})
|
||
|
end
|
||
|
else
|
||
|
local dealerPoly = {}
|
||
|
for k,v in pairs(Config.Dealers) do
|
||
|
dealerPoly[#dealerPoly+1] = BoxZone:Create(vector3(v.coords.x, v.coords.y, v.coords.z), 1.5, 1.5, {
|
||
|
heading = -20,
|
||
|
name="dealer_"..k,
|
||
|
debugPoly = false,
|
||
|
minZ = v.coords.z - 1,
|
||
|
maxZ = v.coords.z + 1,
|
||
|
})
|
||
|
-- dealerCombo = ComboZone:Create(dealerPoly, {name = "dealerPoly"})
|
||
|
end
|
||
|
dealerCombo = ComboZone:Create(dealerPoly, {name = "dealerPoly"})
|
||
|
if not dealerCombo then return end
|
||
|
dealerCombo:onPlayerInOut(function(isPointInside)
|
||
|
if isPointInside then
|
||
|
if not dealerIsHome then
|
||
|
exports['qb-core']:DrawText(Lang:t("info.knock_button"), 'top')
|
||
|
AwaitingInput()
|
||
|
elseif dealerIsHome then
|
||
|
exports['qb-core']:DrawText(Lang:t("info.other_dealers_button"), 'top')
|
||
|
AwaitingInput()
|
||
|
end
|
||
|
else
|
||
|
waitingKeyPress = false
|
||
|
exports['qb-core']:HideText()
|
||
|
end
|
||
|
end)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- Events
|
||
|
|
||
|
RegisterNetEvent('qb-drugs:client:RefreshDealers', function(DealerData)
|
||
|
if not Config.UseTarget and dealerCombo then dealerCombo:destroy() end
|
||
|
Config.Dealers = DealerData
|
||
|
Wait(1000)
|
||
|
InitZones()
|
||
|
end)
|
||
|
|
||
|
RegisterNetEvent('qb-drugs:client:updateDealerItems', function(itemData, amount)
|
||
|
TriggerServerEvent('qb-drugs:server:updateDealerItems', itemData, amount, currentDealer)
|
||
|
end)
|
||
|
|
||
|
RegisterNetEvent('qb-drugs:client:setDealerItems', function(itemData, amount, dealer)
|
||
|
Config.Dealers[dealer]["products"][itemData.slot].amount = Config.Dealers[dealer]["products"][itemData.slot].amount - amount
|
||
|
end)
|
||
|
|
||
|
RegisterNetEvent('qb-drugs:client:setLocation', function(locationData)
|
||
|
if activeDelivery then
|
||
|
SetMapBlip(activeDelivery["coords"]["x"], activeDelivery["coords"]["y"])
|
||
|
QBCore.Functions.Notify(Lang:t("error.pending_delivery"), 'error')
|
||
|
return
|
||
|
end
|
||
|
activeDelivery = locationData
|
||
|
deliveryTimeout = 300
|
||
|
DeliveryTimer()
|
||
|
TriggerServerEvent('qb-drugs:server:giveDeliveryItems', waitingDelivery)
|
||
|
SetMapBlip(Config.DeliveryLocations[locationData.location]["coords"].x, Config.DeliveryLocations[locationData.location]["coords"].y)
|
||
|
if Config.UseTarget then
|
||
|
exports["qb-target"]:AddBoxZone('drugDeliveryZone', Config.DeliveryLocations[locationData.location]["coords"], 1.5, 1.5, {
|
||
|
name = 'drugDeliveryZone',
|
||
|
heading = 0,
|
||
|
minZ = Config.DeliveryLocations[locationData.location]["coords"].z - 1,
|
||
|
maxZ = Config.DeliveryLocations[locationData.location]["coords"].z + 1,
|
||
|
debugPoly = false
|
||
|
}, {
|
||
|
options = {
|
||
|
{
|
||
|
icon = 'fas fa-user-secret',
|
||
|
label = Lang:t("info.target_deliver"),
|
||
|
action = function()
|
||
|
DeliverStuff()
|
||
|
waitingDelivery = nil
|
||
|
end,
|
||
|
canInteract = function()
|
||
|
if waitingDelivery then
|
||
|
return true
|
||
|
end
|
||
|
end
|
||
|
}
|
||
|
},
|
||
|
distance = 1.5
|
||
|
})
|
||
|
else
|
||
|
drugDeliveryZone = BoxZone:Create(Config.DeliveryLocations[locationData.location]["coords"], 1.5, 1.5, {
|
||
|
heading = 0,
|
||
|
name = "drugDelivery",
|
||
|
debugPoly = false,
|
||
|
minZ = Config.DeliveryLocations[locationData.location]["coords"].z - 1,
|
||
|
maxZ = Config.DeliveryLocations[locationData.location]["coords"].z + 1,
|
||
|
})
|
||
|
drugDeliveryZone:onPlayerInOut(function(isPointInside)
|
||
|
if isPointInside then
|
||
|
local inDeliveryZone = true
|
||
|
exports['qb-core']:DrawText(Lang:t("info.deliver_items_button", { itemAmount = activeDelivery["amount"], itemLabel = QBCore.Shared.Items[activeDelivery["itemData"]["item"]]["label"] }), 'top')
|
||
|
CreateThread(function()
|
||
|
while inDeliveryZone do
|
||
|
if IsControlJustPressed(0, 38) then
|
||
|
exports['qb-core']:KeyPressed()
|
||
|
DeliverStuff()
|
||
|
waitingDelivery = nil
|
||
|
break
|
||
|
end
|
||
|
Wait(0)
|
||
|
end
|
||
|
end)
|
||
|
else
|
||
|
inDeliveryZone = false
|
||
|
exports['qb-core']:HideText()
|
||
|
end
|
||
|
end)
|
||
|
end
|
||
|
end)
|
||
|
|
||
|
RegisterNetEvent('qb-drugs:client:sendDeliveryMail', function(type, deliveryData)
|
||
|
if type == 'perfect' then
|
||
|
TriggerServerEvent('qb-phone:server:sendNewMail', {
|
||
|
sender = Config.Dealers[deliveryData["dealer"]]["name"],
|
||
|
subject = "Levering",
|
||
|
message = Lang:t("info.perfect_delivery", {dealerName = Config.Dealers[deliveryData["dealer"]]["name"]})
|
||
|
})
|
||
|
elseif type == 'bad' then
|
||
|
TriggerServerEvent('qb-phone:server:sendNewMail', {
|
||
|
sender = Config.Dealers[deliveryData["dealer"]]["name"],
|
||
|
subject = "Levering",
|
||
|
message = Lang:t("info.bad_delivery")
|
||
|
})
|
||
|
elseif type == 'late' then
|
||
|
TriggerServerEvent('qb-phone:server:sendNewMail', {
|
||
|
sender = Config.Dealers[deliveryData["dealer"]]["name"],
|
||
|
subject = "Levering",
|
||
|
message = Lang:t("info.late_delivery")
|
||
|
})
|
||
|
end
|
||
|
end)
|