428 lines
15 KiB
Lua
428 lines
15 KiB
Lua
local config = require 'config.client'
|
|
local sharedConfig = require 'config.shared'
|
|
local currentDealer = nil
|
|
local dealerIsHome = false
|
|
local waitingDelivery = nil
|
|
local activeDelivery = nil
|
|
local deliveryTimeout = 0
|
|
local waitingKeyPress = false
|
|
local dealerCombo = false
|
|
local drugDeliveryZone
|
|
|
|
---@diagnostic disable-next-line: param-type-mismatch
|
|
AddStateBagChangeHandler('isLoggedIn', nil, function(_, _, value)
|
|
if value then
|
|
sharedConfig.dealers = lib.callback.await('qb-drugs:server:RequestConfig', false)
|
|
InitZones()
|
|
else
|
|
if not config.useTarget and dealerCombo then dealerCombo:destroy() end
|
|
end
|
|
end)
|
|
|
|
local function getClosestDealer()
|
|
local pCoords = GetEntityCoords(cache.ped)
|
|
for k, v in pairs(sharedConfig.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
|
|
|
|
---@todo Move to ox_inventory Shop
|
|
local function openDealerShop()
|
|
getClosestDealer()
|
|
local repItems = {}
|
|
repItems.label = sharedConfig.dealers[currentDealer].name
|
|
repItems.items = {}
|
|
repItems.slots = 30
|
|
for k, _ in pairs(sharedConfig.dealers[currentDealer].products) do
|
|
if QBX.PlayerData.metadata.dealerrep >= sharedConfig.dealers[currentDealer].products[k].minrep then
|
|
repItems.items[k] = sharedConfig.dealers[currentDealer].products[k]
|
|
end
|
|
end
|
|
TriggerServerEvent('inventory:server:OpenInventory', 'shop', 'Dealer_'..sharedConfig.dealers[currentDealer].name, repItems)
|
|
end
|
|
|
|
local function knockDoorAnim(home)
|
|
local knockAnimLib = 'timetable@jimmy@doorknock@'
|
|
local knockAnim = 'knockdoor_idle'
|
|
|
|
if home then
|
|
TriggerServerEvent('InteractSound_SV:PlayOnSource', 'knock_door', 0.2)
|
|
Wait(100)
|
|
lib.playAnim(cache.ped, knockAnimLib, knockAnim, 3.0, 3.0, -1, 1, 0, false, false, false )
|
|
Wait(3500)
|
|
lib.playAnim(cache.ped, knockAnimLib, 'exit', 3.0, 3.0, -1, 1, 0, false, false, false)
|
|
Wait(1000)
|
|
dealerIsHome = true
|
|
TriggerEvent('chat:addMessage', {
|
|
color = { 255, 0, 0 },
|
|
multiline = true,
|
|
args = {
|
|
locale('info.dealer_name', sharedConfig.dealers[currentDealer].name),
|
|
locale('info.fred_knock_message', QBX.PlayerData.charinfo.firstname)
|
|
}
|
|
})
|
|
lib.showTextUI(locale('info.other_dealers_button'), { position = 'left-center' })
|
|
AwaitingInput()
|
|
else
|
|
TriggerServerEvent('InteractSound_SV:PlayOnSource', 'knock_door', 0.2)
|
|
Wait(100)
|
|
lib.playAnim(cache.ped, knockAnimLib, knockAnim, 3.0, 3.0, -1, 1, 0, false, false, false )
|
|
Wait(3500)
|
|
lib.playAnim(cache.ped, knockAnimLib, 'exit', 3.0, 3.0, -1, 1, 0, false, false, false)
|
|
Wait(1000)
|
|
exports.qbx_core:Notify(locale('info.no_one_home'), 'error')
|
|
end
|
|
end
|
|
|
|
local function knockDealerDoor()
|
|
getClosestDealer()
|
|
local hours = GetClockHours()
|
|
local min = sharedConfig.dealers[currentDealer].time.min
|
|
local max = sharedConfig.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 = QBX.PlayerData.metadata.dealerrep
|
|
local availableItems = {}
|
|
for k in pairs(sharedConfig.deliveryItems) do
|
|
if sharedConfig.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,
|
|
locationLabel = config.deliveryLocations[location].label,
|
|
amount = amount,
|
|
dealer = currentDealer,
|
|
itemData = sharedConfig.deliveryItems[item],
|
|
item = item
|
|
}
|
|
|
|
exports.qbx_core:Notify(locale('info.sending_delivery_email'), 'success')
|
|
TriggerServerEvent('qb-drugs:server:giveDeliveryItems', waitingDelivery)
|
|
SetTimeout(2000, function()
|
|
TriggerServerEvent('qb-phone:server:sendNewMail', {
|
|
sender = sharedConfig.dealers[currentDealer].name,
|
|
subject = 'Delivery Location',
|
|
message = locale('info.delivery_info_email', amount, exports.ox_inventory:Items()[waitingDelivery.itemData.item].label),
|
|
button = {
|
|
enabled = true,
|
|
buttonEvent = 'qb-drugs:client:setLocation',
|
|
buttonData = waitingDelivery
|
|
}
|
|
})
|
|
end)
|
|
else
|
|
exports.qbx_core:Notify(locale('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 deliverStuff()
|
|
if deliveryTimeout > 0 then
|
|
Wait(500)
|
|
TriggerEvent('animations:client:EmoteCommandStart', {'bumbin'})
|
|
TriggerServerEvent('qb-drugs:server:randomPoliceAlert')
|
|
if lib.progressCircle({
|
|
label = locale('info.delivering_products'),
|
|
duration = 3500,
|
|
position = 'bottom',
|
|
useWhileDead = false,
|
|
canCancel = true,
|
|
disable = { car = true, move = true, combat = true }
|
|
}) then
|
|
TriggerServerEvent('qb-drugs:server:successDelivery', activeDelivery, true)
|
|
activeDelivery = nil
|
|
if config.useTarget then
|
|
exports.ox_target:removeZone('drugDeliveryZone')
|
|
else
|
|
drugDeliveryZone:destroy()
|
|
end
|
|
else
|
|
ClearPedTasks(cache.ped)
|
|
end
|
|
else
|
|
TriggerServerEvent('qb-drugs:server:successDelivery', activeDelivery, false)
|
|
end
|
|
deliveryTimeout = 0
|
|
end
|
|
|
|
local function setMapBlip(x, y)
|
|
SetNewWaypoint(x, y)
|
|
exports.qbx_core:Notify(locale('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
|
|
knockDealerDoor()
|
|
end
|
|
elseif dealerIsHome then
|
|
if IsControlJustPressed(0, 38) then
|
|
openDealerShop()
|
|
waitingKeyPress = false
|
|
end
|
|
if IsControlJustPressed(0, 47) then
|
|
if waitingDelivery then
|
|
waitingKeyPress = false
|
|
end
|
|
requestDelivery()
|
|
dealerIsHome = false
|
|
waitingKeyPress = false
|
|
end
|
|
end
|
|
Wait(0)
|
|
end
|
|
end)
|
|
end
|
|
|
|
function InitZones()
|
|
if config.useTarget then
|
|
for k, v in pairs(sharedConfig.dealers) do
|
|
---@todo Move to ox_target
|
|
|
|
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 = locale('info.target_request'),
|
|
action = function()
|
|
requestDelivery()
|
|
end,
|
|
canInteract = function()
|
|
getClosestDealer()
|
|
local hours = GetClockHours()
|
|
local min = sharedConfig.dealers[currentDealer].time.min
|
|
local max = sharedConfig.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 = locale('info.target_openshop'),
|
|
action = function()
|
|
openDealerShop()
|
|
end,
|
|
canInteract = function()
|
|
getClosestDealer()
|
|
local hours = GetClockHours()
|
|
local min = sharedConfig.dealers[currentDealer].time.min
|
|
local max = sharedConfig.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
|
|
---@TODO Move to ox_lib Zoning
|
|
|
|
--[[ local dealerPoly = {}
|
|
for k, v in pairs(sharedConfig.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,
|
|
})
|
|
end
|
|
|
|
if table.type(dealerPoly) == 'empty' then return end
|
|
|
|
dealerCombo = ComboZone:Create(dealerPoly, {name = 'dealerPoly'})
|
|
dealerCombo:onPlayerInOut(function(isPointInside)
|
|
if isPointInside then
|
|
if not dealerIsHome then
|
|
lib.showTextUI(locale('info.knock_button'), { position = 'left-center' })
|
|
AwaitingInput()
|
|
elseif dealerIsHome then
|
|
lib.showTextUI(locale('info.other_dealers_button'), { position = 'left-center' })
|
|
AwaitingInput()
|
|
end
|
|
else
|
|
waitingKeyPress = false
|
|
lib.hideTextUI()
|
|
end
|
|
end) ]]--
|
|
|
|
return
|
|
end
|
|
end
|
|
|
|
-- Events
|
|
|
|
RegisterNetEvent('qb-drugs:client:RefreshDealers', function(DealerData)
|
|
if not config.useTarget and dealerCombo then dealerCombo:destroy() end
|
|
sharedConfig.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)
|
|
sharedConfig.dealers[dealer].products[itemData.slot].amount = sharedConfig.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)
|
|
exports.qbx_core:Notify(locale('error.pending_delivery'), 'error')
|
|
return
|
|
end
|
|
activeDelivery = locationData
|
|
deliveryTimeout = 300
|
|
deliveryTimer()
|
|
setMapBlip(activeDelivery.coords.x, activeDelivery.coords.y)
|
|
if config.useTarget then
|
|
exports.ox_target:addBoxZone({
|
|
name = 'drugDeliveryZone',
|
|
coords = vec3(activeDelivery.coords.x, activeDelivery.coords.y, activeDelivery.coords.z),
|
|
size = vec3(1.5, 1.5, 2.0),
|
|
rotation = 0.0,
|
|
debug = true,
|
|
options = {
|
|
{
|
|
icon = 'fas fa-user-secret',
|
|
label = locale('info.target_deliver'),
|
|
onSelect = function()
|
|
deliverStuff()
|
|
waitingDelivery = nil
|
|
end,
|
|
canInteract = function(_, distance)
|
|
return waitingDelivery and distance <= 2.5
|
|
end
|
|
}
|
|
}
|
|
})
|
|
else
|
|
local inDeliveryZone = false
|
|
drugDeliveryZone = lib.zones.box({
|
|
coords = vec3(activeDelivery.coords.xyz),
|
|
size = vec3(1.5, 1.5, 2.0),
|
|
rotation = 0.0,
|
|
debug = false,
|
|
onEnter = function()
|
|
inDeliveryZone = true
|
|
lib.showTextUI(locale('info.deliver_items_button', activeDelivery.amount, exports.ox_inventory:Items()[activeDelivery.itemData.item].label), {
|
|
position = 'left-center'
|
|
})
|
|
CreateThread(function()
|
|
while inDeliveryZone do
|
|
if IsControlJustPressed(0, 38) then
|
|
deliverStuff()
|
|
waitingDelivery = nil
|
|
break
|
|
end
|
|
Wait(0)
|
|
end
|
|
end)
|
|
end,
|
|
onExit = function()
|
|
inDeliveryZone = false
|
|
lib.hideTextUI()
|
|
end
|
|
})
|
|
end
|
|
end)
|
|
|
|
RegisterNetEvent('qb-drugs:client:sendDeliveryMail', function(type, deliveryData)
|
|
if type == 'perfect' then
|
|
TriggerServerEvent('qb-phone:server:sendNewMail', {
|
|
sender = sharedConfig.dealers[deliveryData.dealer].name,
|
|
subject = 'Delivery',
|
|
message = locale('info.perfect_delivery', sharedConfig.dealers[deliveryData.dealer].name)
|
|
})
|
|
elseif type == 'bad' then
|
|
TriggerServerEvent('qb-phone:server:sendNewMail', {
|
|
sender = sharedConfig.dealers[deliveryData.dealer].name,
|
|
subject = 'Delivery',
|
|
message = locale('info.bad_delivery')
|
|
})
|
|
elseif type == 'late' then
|
|
TriggerServerEvent('qb-phone:server:sendNewMail', {
|
|
sender = sharedConfig.dealers[deliveryData.dealer].name,
|
|
subject = 'Delivery',
|
|
message = locale('info.late_delivery')
|
|
})
|
|
end
|
|
end) |