structura foldere
mutat kq- folders in un singur folder [kq]
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,142 @@
|
||||
RegisterNUICallback('GetCryptoData', function(data, cb)
|
||||
TriggerServerCallback('qb-crypto:server:GetCryptoData', function(CryptoData)
|
||||
cb(CryptoData)
|
||||
end, data.crypto)
|
||||
end)
|
||||
|
||||
RegisterNUICallback('BuyCrypto', function(data, cb)
|
||||
TriggerServerCallback('qb-crypto:server:BuyCrypto', function(CryptoData)
|
||||
cb(CryptoData)
|
||||
end, data)
|
||||
end)
|
||||
|
||||
RegisterNUICallback('SellCrypto', function(data, cb)
|
||||
TriggerServerCallback('qb-crypto:server:SellCrypto', function(CryptoData)
|
||||
cb(CryptoData)
|
||||
end, data)
|
||||
end)
|
||||
|
||||
RegisterNUICallback('TransferCrypto', function(data, cb)
|
||||
TriggerServerCallback('qb-crypto:server:TransferCrypto', function(CryptoData)
|
||||
cb(CryptoData)
|
||||
end, data)
|
||||
end)
|
||||
|
||||
RegisterNUICallback('GetCryptoTransactions', function(data, cb)
|
||||
local Data = {
|
||||
CryptoTransactions = PhoneData.CryptoTransactions
|
||||
}
|
||||
cb(Data)
|
||||
end)
|
||||
|
||||
RegisterNetEvent('phone:client:AddTransaction', function(_, _, Message, Title)
|
||||
local Data = {
|
||||
TransactionTitle = Title,
|
||||
TransactionMessage = Message,
|
||||
}
|
||||
PhoneData.CryptoTransactions[#PhoneData.CryptoTransactions + 1] = Data
|
||||
SendNUIMessage({
|
||||
action = 'UpdateTransactions',
|
||||
CryptoTransactions = PhoneData.CryptoTransactions
|
||||
})
|
||||
SendTempNotificationOld({
|
||||
title = Lang('PHONE_NOTIFICATION_STOCK_TITLE'),
|
||||
app = 'stock',
|
||||
text = Message,
|
||||
timeout = 3500,
|
||||
})
|
||||
TriggerServerEvent('phone:server:AddTransaction', Data)
|
||||
end)
|
||||
|
||||
local function ExchangeSuccess()
|
||||
TriggerServerEvent('qb-crypto:server:ExchangeSuccess', math.random(1, 10))
|
||||
end
|
||||
|
||||
local function ExchangeFail()
|
||||
local Odd = 5
|
||||
local RemoveChance = math.random(1, Odd)
|
||||
local LosingNumber = math.random(1, Odd)
|
||||
if RemoveChance == LosingNumber then
|
||||
TriggerServerEvent('qb-crypto:server:ExchangeFail')
|
||||
TriggerServerEvent('qb-crypto:server:SyncReboot')
|
||||
end
|
||||
end
|
||||
|
||||
local function SystemCrashCooldown()
|
||||
Citizen.CreateThread(function()
|
||||
while Crypto.Exchange.RebootInfo.state do
|
||||
if (Crypto.Exchange.RebootInfo.percentage + 1) <= 100 then
|
||||
Crypto.Exchange.RebootInfo.percentage = Crypto.Exchange.RebootInfo.percentage + 1
|
||||
TriggerServerEvent('qb-crypto:server:Rebooting', true, Crypto.Exchange.RebootInfo.percentage)
|
||||
else
|
||||
Crypto.Exchange.RebootInfo.percentage = 0
|
||||
Crypto.Exchange.RebootInfo.state = false
|
||||
TriggerServerEvent('qb-crypto:server:Rebooting', false, 0)
|
||||
end
|
||||
Citizen.Wait(1200)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function HackingSuccess(success)
|
||||
if success then
|
||||
TriggerEvent('mhacking:hide')
|
||||
ExchangeSuccess()
|
||||
else
|
||||
TriggerEvent('mhacking:hide')
|
||||
ExchangeFail()
|
||||
end
|
||||
end
|
||||
|
||||
Citizen.CreateThread(function()
|
||||
while true do
|
||||
local sleep = 5000
|
||||
local ped = PlayerPedId()
|
||||
local pos = GetEntityCoords(ped)
|
||||
local dist = #(pos - Crypto.Exchange.coords)
|
||||
|
||||
if Config.UseTarget then return end
|
||||
if dist < 15 then
|
||||
sleep = 1
|
||||
if dist < 1.5 then
|
||||
if not Crypto.Exchange.RebootInfo.state then
|
||||
DrawText3D(Crypto.Exchange.coords.x, Crypto.Exchange.coords.y, Crypto.Exchange.coords.z, Lang('PHONE_DRAWTEXT_STOCK_ENTER_USB'), 'stock_enter_usb', 'E')
|
||||
|
||||
if IsControlJustPressed(0, 38) then
|
||||
TriggerServerCallback('qb-crypto:server:HasSticky', function(HasItem)
|
||||
if HasItem then
|
||||
TriggerEvent('mhacking:show')
|
||||
TriggerEvent('mhacking:start', math.random(4, 6), 45, HackingSuccess)
|
||||
else
|
||||
SendTextMessage(Lang('PHONE_NOTIFICATION_STOCK_MISSING_CRYPTOSTICK'), 'error')
|
||||
end
|
||||
end)
|
||||
end
|
||||
else
|
||||
DrawText3Ds(Crypto.Exchange.coords.x, Crypto.Exchange.coords.y, Crypto.Exchange.coords.z, Lang('PHONE_DRAWTEXT_STOCK_REBOOTING') .. ' ' .. Crypto.Exchange.RebootInfo.percentage .. '%')
|
||||
end
|
||||
end
|
||||
end
|
||||
Citizen.Wait(sleep)
|
||||
end
|
||||
end)
|
||||
|
||||
RegisterNetEvent('qb-crypto:client:SyncReboot', function()
|
||||
Crypto.Exchange.RebootInfo.state = true
|
||||
SystemCrashCooldown()
|
||||
end)
|
||||
|
||||
RegisterNetEvent('qb-crypto:client:UpdateCryptoWorth', function(crypto, amount, history)
|
||||
Crypto.Worth[crypto] = amount
|
||||
if history ~= nil then
|
||||
Crypto.History[crypto] = history
|
||||
end
|
||||
end)
|
||||
|
||||
RegisterNetEvent('qb-crypto:client:GetRebootState', function(RebootInfo)
|
||||
if RebootInfo.state then
|
||||
Crypto.Exchange.RebootInfo.state = RebootInfo.state
|
||||
Crypto.Exchange.RebootInfo.percentage = RebootInfo.percentage
|
||||
SystemCrashCooldown()
|
||||
end
|
||||
end)
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,8 @@
|
||||
if Config.Billing ~= 'RxBilling' then return end
|
||||
|
||||
---@param id number
|
||||
---@return boolean
|
||||
function PayInvoice(id)
|
||||
local invoice, msg = exports.RxBilling:PayInvoice(id)
|
||||
if invoice then return true end
|
||||
end
|
||||
@@ -0,0 +1,9 @@
|
||||
if Config.Billing ~= 'codemv2' then return end
|
||||
|
||||
---@param id number
|
||||
---@return boolean
|
||||
function PayInvoice(id)
|
||||
TriggerServerEvent('codemBilling:PayInvoice', id)
|
||||
Wait(250) -- Wait until the server has processed the request (this is a bad way to do it. Use callbacks instead)
|
||||
return true
|
||||
end
|
||||
@@ -0,0 +1,21 @@
|
||||
if Config.Billing ~= 'esx_billing' then return end
|
||||
|
||||
---@param id number
|
||||
---@return boolean
|
||||
function PayInvoice(id)
|
||||
local co = coroutine.running()
|
||||
if not co then
|
||||
return false
|
||||
end
|
||||
|
||||
local result = false
|
||||
ESX.TriggerServerCallback('esx_billing:payBill', function(resp)
|
||||
if resp then
|
||||
TriggerEvent('esx_billing:paidBill', id)
|
||||
result = true
|
||||
end
|
||||
coroutine.resume(co, result)
|
||||
end, id)
|
||||
|
||||
return coroutine.yield()
|
||||
end
|
||||
@@ -0,0 +1,9 @@
|
||||
if Config.Billing ~= 'okok' then return end
|
||||
|
||||
---@param id number
|
||||
---@return boolean
|
||||
function PayInvoice(id)
|
||||
TriggerServerEvent('okokBilling:PayInvoice', id)
|
||||
Wait(250) -- Wait until the server has processed the request (this is a bad way to do it. Use callbacks instead)
|
||||
return true
|
||||
end
|
||||
@@ -0,0 +1,8 @@
|
||||
if Config.Billing ~= 'qs' then return end
|
||||
|
||||
---@param id number
|
||||
---@return boolean
|
||||
function PayInvoice(id)
|
||||
TriggerEvent('qs-billing:client:Notify', 'You must go to pay it presentialy or in your invoice tablet', 'info')
|
||||
return true
|
||||
end
|
||||
@@ -0,0 +1,7 @@
|
||||
if Config.Billing ~= 'standalone' then return end
|
||||
|
||||
---@param id number
|
||||
---@return boolean
|
||||
function PayInvoice(id)
|
||||
return TriggerServerCallbackSync('phone:payInvoice', id)
|
||||
end
|
||||
@@ -0,0 +1,55 @@
|
||||
-- These are examples of how to use the custom functions in the client.
|
||||
|
||||
-- Example of how to use the notification function.
|
||||
RegisterCommand('notifi', function(source)
|
||||
exports['qs-smartphone-pro']:SendTempNotification({
|
||||
title = 'Test',
|
||||
text = 'This is a test notification.',
|
||||
app = 'settings',
|
||||
timeout = 5000,
|
||||
disableBadge = true, -- Disables the badge on the app icon.
|
||||
})
|
||||
end, false)
|
||||
|
||||
-- Its same as the old one
|
||||
RegisterCommand('notifiOld', function(source)
|
||||
exports['qs-smartphone-pro']:SendTempNotificationOld({
|
||||
title = 'Test',
|
||||
text = 'This is a test notification.',
|
||||
app = 'settings',
|
||||
timeout = 5000,
|
||||
disableBadge = true, -- Disables the badge on the app icon.
|
||||
})
|
||||
end, false)
|
||||
|
||||
-- Example of how to use the sendNewMail event.
|
||||
RegisterCommand('mailTest', function(source)
|
||||
TriggerServerEvent('phone:sendNewMail', {
|
||||
sender = 'Movistar Plus',
|
||||
subject = 'Family telephone balance promotion',
|
||||
message = 'Enjoy the family balance at only $8.50 per month, what are you waiting for?'
|
||||
})
|
||||
end, false)
|
||||
|
||||
-- Example of how to use the sendNewMail event for the old smartphone.
|
||||
RegisterCommand('mailTestOld', function(source)
|
||||
TriggerServerEvent('qs-smartphone:server:sendNewMail', {
|
||||
sender = 'Movistar Plus',
|
||||
subject = 'Family telephone balance promotion',
|
||||
message = 'Enjoy the family balance at only $8.50 per month, what are you waiting for?'
|
||||
})
|
||||
end, false)
|
||||
|
||||
-- You can check if user is using phone.
|
||||
RegisterCommand('phoneCheck', function(source)
|
||||
local isUsingPhone = exports['qs-smartphone-pro']:InPhone()
|
||||
if isUsingPhone then
|
||||
print('User is using phone.')
|
||||
else
|
||||
print('User is not using phone.')
|
||||
end
|
||||
end, false)
|
||||
|
||||
-- RegisterCommand('toggleCanOpenPhone', function()
|
||||
-- exports['qs-smartphone-pro']:SetCanOpenPhone(false)
|
||||
-- end, false)
|
||||
@@ -0,0 +1,409 @@
|
||||
--[[
|
||||
Hi dear customer or developer, here you can fully configure your server's
|
||||
framework or you could even duplicate this file to create your own framework.
|
||||
|
||||
If you do not have much experience, we recommend you download the base version
|
||||
of the framework that you use in its latest version and it will work perfectly.
|
||||
]]
|
||||
|
||||
if Config.Framework ~= 'esx' then
|
||||
return
|
||||
end
|
||||
|
||||
ESX = nil
|
||||
|
||||
Citizen.CreateThread(function()
|
||||
local legacyEsx = pcall(function()
|
||||
ESX = exports['es_extended']:getSharedObject()
|
||||
end)
|
||||
Citizen.Wait(0)
|
||||
if legacyEsx then return end
|
||||
while ESX == nil do
|
||||
TriggerEvent('esx:getSharedObject', function(obj) ESX = obj end)
|
||||
Citizen.Wait(0)
|
||||
end
|
||||
end)
|
||||
|
||||
function TriggerServerCallback(name, cb, ...)
|
||||
local startTime = GetGameTimer()
|
||||
ESX.TriggerServerCallback(name, function(...)
|
||||
local endTime = GetGameTimer()
|
||||
local duration = endTime - startTime
|
||||
Debug('TriggerServerCallback ::: ' .. name .. ' took ' .. duration .. 'ms')
|
||||
cb(...)
|
||||
end, ...)
|
||||
end
|
||||
|
||||
exports('TriggerServerCallback', TriggerServerCallback)
|
||||
|
||||
RegisterNetEvent('esx:playerLoaded', function()
|
||||
TriggerServerEvent('qb-crypto:server:FetchWorth')
|
||||
TriggerServerEvent('qb-crypto:server:GetRebootState')
|
||||
end)
|
||||
|
||||
RegisterNetEvent('esx:onPlayerLogout', function()
|
||||
Logout()
|
||||
end)
|
||||
|
||||
RegisterNetEvent('esx:setJob')
|
||||
AddEventHandler('esx:setJob', function(JobInfo)
|
||||
SendNUIMessage({
|
||||
action = 'UpdateApplications',
|
||||
jobName = JobInfo.name,
|
||||
applications = PhoneApplications
|
||||
})
|
||||
end)
|
||||
|
||||
local brutalDead = GetResourceState('brutal_ambulancejob') == 'started'
|
||||
function isDead()
|
||||
if brutalDead then
|
||||
return exports.brutal_ambulancejob:IsDead()
|
||||
end
|
||||
return IsPedDeadOrDying(PlayerPedId(), false) or IsEntityDead(PlayerPedId()) or IsPauseMenuActive() or LocalPlayer.state.dead
|
||||
end
|
||||
|
||||
function GetHungry()
|
||||
local promise = promise.new()
|
||||
TriggerEvent('esx_status:getStatus', 'hunger', function(status)
|
||||
promise:resolve(status.getPercent())
|
||||
end)
|
||||
return Citizen.Await(promise)
|
||||
end
|
||||
|
||||
function GetThirsty()
|
||||
local promise = promise:new()
|
||||
TriggerEvent('esx_status:getStatus', 'thirst', function(status)
|
||||
promise:resolve(status.getPercent())
|
||||
end)
|
||||
return Citizen.Await(promise)
|
||||
end
|
||||
|
||||
function GetPlayerData()
|
||||
return ESX.GetPlayerData()
|
||||
end
|
||||
|
||||
function GetInventory()
|
||||
return GetPlayerData().inventory
|
||||
end
|
||||
|
||||
function GetJobName()
|
||||
return GetPlayerData().job.name
|
||||
end
|
||||
|
||||
function GetMoney()
|
||||
for k, v in pairs(GetPlayerData().accounts) do
|
||||
if v.name == 'bank' then return v.money end
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
function FrameworkGetClosestVehicle()
|
||||
return ESX.Game.GetClosestVehicle()
|
||||
end
|
||||
|
||||
function FrameworkSpawnVehicle(model, coords, heading, cb)
|
||||
ESX.Game.SpawnVehicle(model, coords, heading, cb)
|
||||
end
|
||||
|
||||
function FrameworkSetVehicleProperties(vehicle, props)
|
||||
ESX.Game.SetVehicleProperties(vehicle, props)
|
||||
end
|
||||
|
||||
function FrameworkGetVehicles(cb)
|
||||
return ESX.Game.GetVehicles()
|
||||
end
|
||||
|
||||
function GetIdentifier()
|
||||
return GetPlayerData().identifier
|
||||
end
|
||||
|
||||
function GetPlayerMoney()
|
||||
local playerData = GetPlayerData()
|
||||
for i = 1, #playerData.accounts, 1 do
|
||||
if playerData.accounts[i].name == 'money' then
|
||||
return playerData.accounts[i].money
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function SendTextMessage(msg, type)
|
||||
if GetResourceState('qs-interface') == 'started' then
|
||||
if type == 'inform' then
|
||||
exports['qs-interface']:AddNotify(msg, 'Inform', 2500, 'fas fa-file')
|
||||
elseif type == 'error' then
|
||||
exports['qs-interface']:AddNotify(msg, 'Error', 2500, 'fas fa-bug')
|
||||
elseif type == 'success' then
|
||||
exports['qs-interface']:AddNotify(msg, 'Success', 2500, 'fas fa-thumbs-up')
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
if type == 'inform' then
|
||||
lib.notify({
|
||||
title = 'Smartphone',
|
||||
description = msg,
|
||||
type = 'inform'
|
||||
})
|
||||
elseif type == 'error' then
|
||||
lib.notify({
|
||||
title = 'Smartphone',
|
||||
description = msg,
|
||||
type = 'error'
|
||||
})
|
||||
elseif type == 'success' then
|
||||
lib.notify({
|
||||
title = 'Smartphone',
|
||||
description = msg,
|
||||
type = 'success'
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
local texts = {}
|
||||
if GetResourceState('qs-textui') == 'started' then
|
||||
function DrawText3D(x, y, z, text, id, key)
|
||||
local _id = id
|
||||
if not texts[_id] then
|
||||
CreateThread(function()
|
||||
texts[_id] = 5
|
||||
while texts[_id] > 0 do
|
||||
texts[_id] = texts[_id] - 1
|
||||
Wait(0)
|
||||
end
|
||||
texts[_id] = nil
|
||||
exports['qs-textui']:DeleteDrawText3D(id)
|
||||
Debug('Deleted text', id)
|
||||
end)
|
||||
TriggerEvent('textui:DrawText3D', x, y, z, text, id, key)
|
||||
end
|
||||
texts[_id] = 5
|
||||
end
|
||||
else
|
||||
function DrawText3D(x, y, z, text)
|
||||
SetTextScale(0.35, 0.35)
|
||||
SetTextFont(4)
|
||||
SetTextProportional(1)
|
||||
SetTextColour(255, 255, 255, 215)
|
||||
SetTextEntry('STRING')
|
||||
SetTextCentre(true)
|
||||
AddTextComponentString(text)
|
||||
SetDrawOrigin(x, y, z, 0)
|
||||
DrawText(0.0, 0.0)
|
||||
local factor = text:len() / 370
|
||||
DrawRect(0.0, 0.0 + 0.0125, 0.017 + factor, 0.03, 0, 0, 0, 75)
|
||||
ClearDrawOrigin()
|
||||
end
|
||||
end
|
||||
|
||||
function DrawText3Ds(x, y, z, text)
|
||||
SetTextScale(0.35, 0.35)
|
||||
SetTextFont(4)
|
||||
SetTextProportional(1)
|
||||
SetTextColour(255, 255, 255, 215)
|
||||
SetTextEntry('STRING')
|
||||
SetTextCentre(true)
|
||||
AddTextComponentString(text)
|
||||
SetDrawOrigin(x, y, z, 0)
|
||||
DrawText(0.0, 0.0)
|
||||
local factor = text:len() / 370
|
||||
DrawRect(0.0, 0.0 + 0.0125, 0.017 + factor, 0.03, 0, 0, 0, 75)
|
||||
ClearDrawOrigin()
|
||||
end
|
||||
|
||||
function DrawGenericText(text)
|
||||
SetTextFont(4)
|
||||
SetTextProportional(0)
|
||||
SetTextScale(0.65, 0.65)
|
||||
SetTextDropShadow(0, 0, 0, 0, 255)
|
||||
SetTextEdge(1, 0, 0, 0, 255)
|
||||
SetTextEntry('STRING')
|
||||
AddTextComponentString(text)
|
||||
DrawText(0.825, 0.90)
|
||||
end
|
||||
|
||||
function ProgressBar(name, label, duration, useWhileDead, canCancel, disableControls, animation, prop, propTwo, onFinish, onCancel)
|
||||
if GetResourceState('qs-interface') == 'started' then
|
||||
local success = exports['qs-interface']:ProgressBar({
|
||||
duration = duration,
|
||||
label = label,
|
||||
position = 'bottom',
|
||||
useWhileDead = useWhileDead,
|
||||
canCancel = canCancel,
|
||||
disable = disableControls,
|
||||
anim = {
|
||||
dict = animation.animDict,
|
||||
clip = animation.anim,
|
||||
flag = animation?.flags
|
||||
},
|
||||
prop = prop
|
||||
})
|
||||
if success then
|
||||
onFinish()
|
||||
else
|
||||
onCancel()
|
||||
end
|
||||
return
|
||||
end
|
||||
if lib.progressCircle({
|
||||
duration = duration,
|
||||
label = label,
|
||||
position = 'bottom',
|
||||
useWhileDead = useWhileDead,
|
||||
canCancel = canCancel,
|
||||
disable = disableControls,
|
||||
anim = {
|
||||
dict = animation.animDict,
|
||||
clip = animation.anim,
|
||||
flag = animation?.flags
|
||||
},
|
||||
prop = prop
|
||||
}) then
|
||||
onFinish()
|
||||
else
|
||||
onCancel()
|
||||
end
|
||||
end
|
||||
|
||||
function DepositMoney(amount, cb)
|
||||
Debug('Society Deposit', amount)
|
||||
TriggerServerEvent('esx_society:depositMoney', GetJobName(), amount)
|
||||
SetTimeout(500, function()
|
||||
TriggerServerCallback('esx_society:getSocietyMoney', cb, GetJobName())
|
||||
end)
|
||||
end
|
||||
|
||||
function WithdrawMoney(amount, cb)
|
||||
Debug('society withdraw money', amount)
|
||||
TriggerServerEvent('esx_society:withdrawMoney', GetJobName(), amount)
|
||||
SetTimeout(500, function()
|
||||
TriggerServerCallback('esx_society:getSocietyMoney', cb, GetJobName())
|
||||
end)
|
||||
end
|
||||
|
||||
function HireEmployee(source, cb)
|
||||
TriggerServerCallback('esx_society:getOnlinePlayers', function(players)
|
||||
for i = 1, #players do
|
||||
local player = players[i]
|
||||
if player.source == source then
|
||||
TriggerServerCallback('esx_society:setJob', function()
|
||||
cb({
|
||||
name = player.name,
|
||||
id = player.identifier
|
||||
})
|
||||
end, player.identifier, GetJobName(), 0, 'hire')
|
||||
return
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function FireEmployee(identifier, cb)
|
||||
Debug('Fire Employee', identifier)
|
||||
TriggerServerCallback('esx_society:setJob', function()
|
||||
cb(true)
|
||||
end, identifier, 'unemployed', 0, 'fire')
|
||||
end
|
||||
|
||||
function SetGrade(identifier, newGrade, cb)
|
||||
TriggerServerCallback('esx_society:getJob', function(job)
|
||||
if newGrade > #job.grades - 1 then
|
||||
return cb(false)
|
||||
end
|
||||
|
||||
TriggerServerCallback('esx_society:setJob', function()
|
||||
cb(true)
|
||||
end, identifier, GetJobName(), newGrade, 'promote')
|
||||
end, GetJobName())
|
||||
end
|
||||
|
||||
RegisterNUICallback('getMarketData', function(data, cb)
|
||||
local playerData = GetPlayerData()
|
||||
local jobData = {
|
||||
job = playerData.job.name,
|
||||
jobLabel = playerData.job.label,
|
||||
isBoss = playerData.job.grade_name == 'boss'
|
||||
}
|
||||
|
||||
if not jobData.isBoss then
|
||||
for cId = 1, #Config.Markets do
|
||||
local market = Config.Markets[cId]
|
||||
if table.includes(market.job, jobData.job) then
|
||||
if not market.bossRanks then
|
||||
break
|
||||
end
|
||||
|
||||
jobData.bossRanks = market.bossRanks
|
||||
for i = 1, #market.bossRanks do
|
||||
if market.bossRanks[i] == playerData.job.grade_name then
|
||||
jobData.isBoss = true
|
||||
break
|
||||
end
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if jobData.isBoss then
|
||||
local moneyPromise = promise.new()
|
||||
TriggerServerCallback('esx_society:getSocietyMoney', function(money)
|
||||
jobData.balance = money
|
||||
moneyPromise:resolve()
|
||||
end, jobData.job)
|
||||
Citizen.Await(moneyPromise)
|
||||
|
||||
local employeesPromise = promise.new()
|
||||
TriggerServerCallback('esx_society:getEmployees', function(employees)
|
||||
jobData.employees = employees
|
||||
for i = 1, #employees do
|
||||
local employee = employees[i]
|
||||
employees[i] = {
|
||||
name = employee.name,
|
||||
id = employee.identifier,
|
||||
|
||||
gradeLabel = employee.job.grade_label,
|
||||
grade = employee.job.grade,
|
||||
|
||||
canInteract = employee.job.grade_name ~= 'boss'
|
||||
}
|
||||
end
|
||||
employeesPromise:resolve()
|
||||
end, jobData.job)
|
||||
Citizen.Await(employeesPromise)
|
||||
|
||||
local gradesPromise = promise.new()
|
||||
TriggerServerCallback('esx_society:getJob', function(job)
|
||||
local grades = {}
|
||||
for i = 1, #job.grades do
|
||||
local grade = job.grades[i]
|
||||
grades[i] = {
|
||||
key = grade.grade,
|
||||
value = grade.label
|
||||
}
|
||||
end
|
||||
jobData.grades = grades
|
||||
gradesPromise:resolve()
|
||||
end, jobData.job)
|
||||
Citizen.Await(gradesPromise)
|
||||
end
|
||||
|
||||
Debug('Market Data', jobData)
|
||||
|
||||
cb(jobData)
|
||||
end)
|
||||
|
||||
function ToggleHud(bool)
|
||||
if bool then
|
||||
Debug('Event to show the hud [client/custom/framework/esx.lua line 389]')
|
||||
DisplayRadar(false) -- You can enable or disable mini-map here
|
||||
if GetResourceState('qs-interface') == 'started' then
|
||||
exports['qs-interface']:ToggleHud(false)
|
||||
end
|
||||
else
|
||||
Debug('Event to hide the hud [client/custom/framework/esx.lua line 389]')
|
||||
DisplayRadar(true) -- You can enable or disable mini-map here
|
||||
if GetResourceState('qs-interface') == 'started' then
|
||||
exports['qs-interface']:ToggleHud(true)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,363 @@
|
||||
--[[
|
||||
Hi dear customer or developer, here you can fully configure your server's
|
||||
framework or you could even duplicate this file to create your own framework.
|
||||
|
||||
If you do not have much experience, we recommend you download the base version
|
||||
of the framework that you use in its latest version and it will work perfectly.
|
||||
]]
|
||||
|
||||
if Config.Framework ~= 'qb' then
|
||||
return
|
||||
end
|
||||
|
||||
ESX = nil
|
||||
|
||||
Citizen.CreateThread(function()
|
||||
ESX = exports['qb-core']:GetCoreObject()
|
||||
end)
|
||||
|
||||
function TriggerServerCallback(name, cb, ...)
|
||||
local startTime = GetGameTimer()
|
||||
ESX.Functions.TriggerCallback(name, function(...)
|
||||
local endTime = GetGameTimer()
|
||||
local duration = endTime - startTime
|
||||
Debug('TriggerServerCallback ::: ' .. name .. ' took ' .. duration .. 'ms')
|
||||
cb(...)
|
||||
end, ...)
|
||||
end
|
||||
|
||||
exports('TriggerServerCallback', TriggerServerCallback)
|
||||
|
||||
RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function()
|
||||
TriggerServerEvent('qb-crypto:server:FetchWorth')
|
||||
TriggerServerEvent('qb-crypto:server:GetRebootState')
|
||||
end)
|
||||
|
||||
RegisterNetEvent('QBCore:Client:OnJobUpdate', function(JobInfo)
|
||||
SendNUIMessage({
|
||||
action = 'UpdateApplications',
|
||||
jobName = JobInfo.name,
|
||||
applications = PhoneApplications
|
||||
})
|
||||
end)
|
||||
|
||||
RegisterNetEvent('QBCore:Client:OnPlayerUnload', function()
|
||||
Logout()
|
||||
end)
|
||||
|
||||
function GetPlayerData()
|
||||
return ESX.Functions.GetPlayerData()
|
||||
end
|
||||
|
||||
local brutalDead = GetResourceState('brutal_ambulancejob') == 'started'
|
||||
function isDead()
|
||||
if brutalDead then
|
||||
return exports.brutal_ambulancejob:IsDead()
|
||||
end
|
||||
return GetPlayerData().metadata['ishandcuffed'] or GetPlayerData().metadata['inlaststand'] or GetPlayerData().metadata['isdead'] or IsPauseMenuActive() or LocalPlayer.state.dead
|
||||
end
|
||||
|
||||
function GetIdentifier()
|
||||
return GetPlayerData().citizenid
|
||||
end
|
||||
|
||||
function GetHungry()
|
||||
return GetPlayerData().metadata.hunger
|
||||
end
|
||||
|
||||
function GetThirsty()
|
||||
return GetPlayerData().metadata.thirst
|
||||
end
|
||||
|
||||
function GetInventory()
|
||||
return GetPlayerData().items
|
||||
end
|
||||
|
||||
function GetJobName()
|
||||
return GetPlayerData().job.name
|
||||
end
|
||||
|
||||
function GetMoney()
|
||||
return GetPlayerData().money.bank or 0
|
||||
end
|
||||
|
||||
function FrameworkGetClosestVehicle()
|
||||
return ESX.Functions.GetClosestVehicle()
|
||||
end
|
||||
|
||||
function FrameworkSpawnVehicle(model, coords, heading, cb)
|
||||
ESX.Functions.SpawnVehicle(model, cb, coords, true)
|
||||
end
|
||||
|
||||
function FrameworkSetVehicleProperties(vehicle, props)
|
||||
ESX.Functions.SetVehicleProperties(vehicle, props)
|
||||
end
|
||||
|
||||
function FrameworkGetVehicles(cb)
|
||||
return ESX.Functions.GetVehicles(cb)
|
||||
end
|
||||
|
||||
function GetPlayerMoney()
|
||||
return GetPlayerData().money['cash']
|
||||
end
|
||||
|
||||
function SendTextMessage(msg, type)
|
||||
if GetResourceState('qs-interface') == 'started' then
|
||||
if type == 'inform' then
|
||||
exports['qs-interface']:AddNotify(msg, 'Inform', 2500, 'fas fa-file')
|
||||
elseif type == 'error' then
|
||||
exports['qs-interface']:AddNotify(msg, 'Error', 2500, 'fas fa-bug')
|
||||
elseif type == 'success' then
|
||||
exports['qs-interface']:AddNotify(msg, 'Success', 2500, 'fas fa-thumbs-up')
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
if type == 'inform' then
|
||||
lib.notify({
|
||||
title = 'Smartphone',
|
||||
description = msg,
|
||||
type = 'inform'
|
||||
})
|
||||
elseif type == 'error' then
|
||||
lib.notify({
|
||||
title = 'Smartphone',
|
||||
description = msg,
|
||||
type = 'error'
|
||||
})
|
||||
elseif type == 'success' then
|
||||
lib.notify({
|
||||
title = 'Smartphone',
|
||||
description = msg,
|
||||
type = 'success'
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
local texts = {}
|
||||
if GetResourceState('qs-textui') == 'started' then
|
||||
function DrawText3D(x, y, z, text, id, key)
|
||||
local _id = id
|
||||
if not texts[_id] then
|
||||
CreateThread(function()
|
||||
texts[_id] = 5
|
||||
while texts[_id] > 0 do
|
||||
texts[_id] = texts[_id] - 1
|
||||
Wait(0)
|
||||
end
|
||||
texts[_id] = nil
|
||||
exports['qs-textui']:DeleteDrawText3D(id)
|
||||
Debug('Deleted text', id)
|
||||
end)
|
||||
TriggerEvent('textui:DrawText3D', x, y, z, text, id, key)
|
||||
end
|
||||
texts[_id] = 5
|
||||
end
|
||||
else
|
||||
function DrawText3D(x, y, z, text)
|
||||
SetTextScale(0.35, 0.35)
|
||||
SetTextFont(4)
|
||||
SetTextProportional(1)
|
||||
SetTextColour(255, 255, 255, 215)
|
||||
SetTextEntry('STRING')
|
||||
SetTextCentre(true)
|
||||
AddTextComponentString(text)
|
||||
SetDrawOrigin(x, y, z, 0)
|
||||
DrawText(0.0, 0.0)
|
||||
local factor = text:len() / 370
|
||||
DrawRect(0.0, 0.0 + 0.0125, 0.017 + factor, 0.03, 0, 0, 0, 75)
|
||||
ClearDrawOrigin()
|
||||
end
|
||||
end
|
||||
|
||||
function DrawText3Ds(x, y, z, text)
|
||||
SetTextScale(0.35, 0.35)
|
||||
SetTextFont(4)
|
||||
SetTextProportional(1)
|
||||
SetTextColour(255, 255, 255, 215)
|
||||
SetTextEntry('STRING')
|
||||
SetTextCentre(true)
|
||||
AddTextComponentString(text)
|
||||
SetDrawOrigin(x, y, z, 0)
|
||||
DrawText(0.0, 0.0)
|
||||
local factor = text:len() / 370
|
||||
DrawRect(0.0, 0.0 + 0.0125, 0.017 + factor, 0.03, 0, 0, 0, 75)
|
||||
ClearDrawOrigin()
|
||||
end
|
||||
|
||||
function DrawGenericText(text)
|
||||
SetTextFont(4)
|
||||
SetTextProportional(0)
|
||||
SetTextScale(0.65, 0.65)
|
||||
SetTextDropShadow(0, 0, 0, 0, 255)
|
||||
SetTextEdge(1, 0, 0, 0, 255)
|
||||
SetTextEntry('STRING')
|
||||
AddTextComponentString(text)
|
||||
DrawText(0.825, 0.90)
|
||||
end
|
||||
|
||||
function ProgressBar(name, label, duration, useWhileDead, canCancel, disableControls, animation, prop, propTwo, onFinish, onCancel)
|
||||
if GetResourceState('qs-interface') == 'started' then
|
||||
local success = exports['qs-interface']:ProgressBar({
|
||||
duration = duration,
|
||||
label = label,
|
||||
position = 'bottom',
|
||||
useWhileDead = useWhileDead,
|
||||
canCancel = canCancel,
|
||||
disable = disableControls,
|
||||
anim = {
|
||||
dict = animation.animDict,
|
||||
clip = animation.anim,
|
||||
flag = animation?.flags
|
||||
},
|
||||
prop = prop
|
||||
})
|
||||
if success then
|
||||
onFinish()
|
||||
else
|
||||
onCancel()
|
||||
end
|
||||
return
|
||||
end
|
||||
if lib.progressCircle({
|
||||
duration = duration,
|
||||
label = label,
|
||||
position = 'bottom',
|
||||
useWhileDead = useWhileDead,
|
||||
canCancel = canCancel,
|
||||
disable = disableControls,
|
||||
anim = {
|
||||
dict = animation.animDict,
|
||||
clip = animation.anim,
|
||||
flag = animation?.flags
|
||||
},
|
||||
prop = prop
|
||||
}) then
|
||||
onFinish()
|
||||
else
|
||||
onCancel()
|
||||
end
|
||||
end
|
||||
|
||||
function GetCompanyData(cb)
|
||||
local playerJob = GetPlayerData().job
|
||||
local jobData = {
|
||||
job = playerJob.name,
|
||||
jobLabel = playerJob.label,
|
||||
isBoss = playerJob.isboss,
|
||||
}
|
||||
|
||||
if jobData.isBoss then
|
||||
local moneyPromise = promise.new()
|
||||
TriggerServerCallback('phone:market:getAccountBalance', function(money)
|
||||
moneyPromise:resolve(money)
|
||||
end, jobData.job)
|
||||
jobData.balance = Citizen.Await(moneyPromise)
|
||||
|
||||
local employeesPromise = promise.new()
|
||||
TriggerServerCallback('qb-bossmenu:server:GetEmployees', function(employees)
|
||||
for i = 1, #employees do
|
||||
local employee = employees[i]
|
||||
employees[i] = {
|
||||
name = employee.name,
|
||||
id = employee.empSource,
|
||||
|
||||
gradeLabel = employee.grade.name,
|
||||
grade = employee.grade.level,
|
||||
|
||||
canInteract = not employee.isboss
|
||||
}
|
||||
end
|
||||
employeesPromise:resolve(employees)
|
||||
end, jobData.job)
|
||||
jobData.employees = Citizen.Await(employeesPromise)
|
||||
|
||||
jobData.grades = {}
|
||||
for k, v in pairs(ESX.Shared.Jobs[jobData.job].grades) do
|
||||
jobData.grades[#jobData.grades + 1] = {
|
||||
key = tonumber(k),
|
||||
value = v.name,
|
||||
}
|
||||
end
|
||||
|
||||
table.sort(jobData.grades, function(a, b)
|
||||
return a.key < b.key
|
||||
end)
|
||||
end
|
||||
|
||||
cb(jobData)
|
||||
end
|
||||
|
||||
RegisterNUICallback('getMarketData', function(data, cb)
|
||||
return GetCompanyData(function(companyData)
|
||||
cb(companyData)
|
||||
end)
|
||||
end)
|
||||
|
||||
function DepositMoney(amount, cb)
|
||||
TriggerServerCallbackSync('qb-banking:server:deposit', {
|
||||
amount = amount,
|
||||
accountName = GetJobName()
|
||||
})
|
||||
TriggerServerCallback('phone:market:getAccountBalance', cb, GetPlayerData().job.name)
|
||||
end
|
||||
|
||||
function WithdrawMoney(amount, cb)
|
||||
TriggerServerCallbackSync('qb-banking:server:withdraw', {
|
||||
amount = amount,
|
||||
accountName = GetJobName()
|
||||
})
|
||||
TriggerServerCallback('phone:market:getAccountBalance', cb, GetJobName())
|
||||
end
|
||||
|
||||
function HireEmployee(source, cb)
|
||||
TriggerServerEvent('qb-bossmenu:server:HireEmployee', source)
|
||||
TriggerServerCallback('phone:market:getPlayerData', function(playerData)
|
||||
cb({
|
||||
name = playerData.name,
|
||||
id = playerData.id
|
||||
})
|
||||
end, source)
|
||||
end
|
||||
|
||||
function FireEmployee(source, cb)
|
||||
TriggerServerEvent('qb-bossmenu:server:FireEmployee', source)
|
||||
cb(GetPlayerData().job.isboss)
|
||||
end
|
||||
|
||||
function SetGrade(identifier, newGrade, cb)
|
||||
local maxGrade = 0
|
||||
for grade, _ in pairs(ESX.Shared.Jobs[GetPlayerData().job.name].grades) do
|
||||
grade = tonumber(grade)
|
||||
if grade and grade > maxGrade then
|
||||
maxGrade = grade
|
||||
end
|
||||
end
|
||||
|
||||
if newGrade > maxGrade then
|
||||
return cb(false)
|
||||
end
|
||||
|
||||
TriggerServerEvent('qb-bossmenu:server:GradeUpdate', {
|
||||
cid = identifier,
|
||||
grade = newGrade,
|
||||
gradename = ESX.Shared.Jobs[GetPlayerData().job.name].grades[tostring(newGrade)].name
|
||||
})
|
||||
cb(true)
|
||||
end
|
||||
|
||||
function ToggleHud(bool)
|
||||
if bool then
|
||||
Debug('Event to show the hud [client/custom/framework/esx.lua line 335]')
|
||||
DisplayRadar(false) -- You can enable or disable mini-map here
|
||||
if GetResourceState('qs-interface') == 'started' then
|
||||
exports['qs-interface']:ToggleHud(false)
|
||||
end
|
||||
else
|
||||
Debug('Event to hide the hud [client/custom/framework/esx.lua line 335]')
|
||||
DisplayRadar(true) -- You can enable or disable mini-map here
|
||||
if GetResourceState('qs-interface') == 'started' then
|
||||
exports['qs-interface']:ToggleHud(true)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,331 @@
|
||||
--[[
|
||||
Hi dear customer or developer, here you can fully configure your server's
|
||||
framework or you could even duplicate this file to create your own framework.
|
||||
|
||||
If you do not have much experience, we recommend you download the base version
|
||||
of the framework that you use in its latest version and it will work perfectly.
|
||||
]]
|
||||
|
||||
if Config.Framework ~= 'qbx' then
|
||||
return
|
||||
end
|
||||
|
||||
ESX = nil
|
||||
|
||||
Citizen.CreateThread(function()
|
||||
ESX = exports['qb-core']:GetCoreObject()
|
||||
end)
|
||||
|
||||
function TriggerServerCallback(name, cb, ...)
|
||||
ESX.Functions.TriggerCallback(name, cb, ...)
|
||||
end
|
||||
|
||||
exports('TriggerServerCallback', TriggerServerCallback)
|
||||
|
||||
RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function()
|
||||
TriggerServerEvent('qb-crypto:server:FetchWorth')
|
||||
TriggerServerEvent('qb-crypto:server:GetRebootState')
|
||||
end)
|
||||
|
||||
RegisterNetEvent('QBCore:Client:OnJobUpdate', function(JobInfo)
|
||||
SendNUIMessage({
|
||||
action = 'UpdateApplications',
|
||||
jobName = JobInfo.name,
|
||||
applications = PhoneApplications
|
||||
})
|
||||
end)
|
||||
|
||||
RegisterNetEvent('QBCore:Client:OnPlayerUnload', function()
|
||||
Logout()
|
||||
end)
|
||||
|
||||
function GetPlayerData()
|
||||
return exports.qbx_core:GetPlayerData()
|
||||
end
|
||||
|
||||
local brutalDead = GetResourceState('brutal_ambulancejob') == 'started'
|
||||
function isDead()
|
||||
if brutalDead then
|
||||
return exports.brutal_ambulancejob:IsDead()
|
||||
end
|
||||
return GetPlayerData().metadata['ishandcuffed'] or GetPlayerData().metadata['inlaststand'] or GetPlayerData().metadata['isdead'] or IsPauseMenuActive() or LocalPlayer.state.dead
|
||||
end
|
||||
|
||||
function GetIdentifier()
|
||||
return GetPlayerData().citizenid
|
||||
end
|
||||
|
||||
function GetHungry()
|
||||
return GetPlayerData().metadata.hunger
|
||||
end
|
||||
|
||||
function GetThirsty()
|
||||
return GetPlayerData().metadata.thirst
|
||||
end
|
||||
|
||||
function GetInventory()
|
||||
return GetPlayerData().items
|
||||
end
|
||||
|
||||
function GetJobName()
|
||||
return GetPlayerData().job.name
|
||||
end
|
||||
|
||||
function GetMoney()
|
||||
return GetPlayerData().money.bank or 0
|
||||
end
|
||||
|
||||
function FrameworkGetClosestVehicle()
|
||||
return lib.getClosestVehicle(GetEntityCoords(cache.ped), 2.0, true)
|
||||
end
|
||||
|
||||
function FrameworkSpawnVehicle(model, coords, heading, cb)
|
||||
ESX.Functions.SpawnVehicle(model, cb, coords, true)
|
||||
end
|
||||
|
||||
function FrameworkSetVehicleProperties(vehicle, props)
|
||||
lib.setVehicleProperties(vehicle, props)
|
||||
end
|
||||
|
||||
function FrameworkGetVehicles(cb)
|
||||
return GetGamePool('CVehicle', cb)
|
||||
end
|
||||
|
||||
function GetPlayerMoney()
|
||||
return GetPlayerData().money['cash']
|
||||
end
|
||||
|
||||
function SendTextMessage(msg, type)
|
||||
if GetResourceState('qs-interface') == 'started' then
|
||||
if type == 'inform' then
|
||||
exports['qs-interface']:AddNotify(msg, 'Inform', 2500, 'fas fa-file')
|
||||
elseif type == 'error' then
|
||||
exports['qs-interface']:AddNotify(msg, 'Error', 2500, 'fas fa-bug')
|
||||
elseif type == 'success' then
|
||||
exports['qs-interface']:AddNotify(msg, 'Success', 2500, 'fas fa-thumbs-up')
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
exports.qbx_core:Notify(message, type, 5000)
|
||||
end
|
||||
|
||||
local texts = {}
|
||||
if GetResourceState('qs-textui') == 'started' then
|
||||
function DrawText3D(x, y, z, text, id, key)
|
||||
local _id = id
|
||||
if not texts[_id] then
|
||||
CreateThread(function()
|
||||
texts[_id] = 5
|
||||
while texts[_id] > 0 do
|
||||
texts[_id] = texts[_id] - 1
|
||||
Wait(0)
|
||||
end
|
||||
texts[_id] = nil
|
||||
exports['qs-textui']:DeleteDrawText3D(id)
|
||||
Debug('Deleted text', id)
|
||||
end)
|
||||
TriggerEvent('textui:DrawText3D', x, y, z, text, id, key)
|
||||
end
|
||||
texts[_id] = 5
|
||||
end
|
||||
else
|
||||
function DrawText3D(x, y, z, text)
|
||||
SetTextScale(0.35, 0.35)
|
||||
SetTextFont(4)
|
||||
SetTextProportional(1)
|
||||
SetTextColour(255, 255, 255, 215)
|
||||
SetTextEntry('STRING')
|
||||
SetTextCentre(true)
|
||||
AddTextComponentString(text)
|
||||
SetDrawOrigin(x, y, z, 0)
|
||||
DrawText(0.0, 0.0)
|
||||
local factor = text:len() / 370
|
||||
DrawRect(0.0, 0.0 + 0.0125, 0.017 + factor, 0.03, 0, 0, 0, 75)
|
||||
ClearDrawOrigin()
|
||||
end
|
||||
end
|
||||
|
||||
function DrawText3Ds(x, y, z, text)
|
||||
SetTextScale(0.35, 0.35)
|
||||
SetTextFont(4)
|
||||
SetTextProportional(1)
|
||||
SetTextColour(255, 255, 255, 215)
|
||||
SetTextEntry('STRING')
|
||||
SetTextCentre(true)
|
||||
AddTextComponentString(text)
|
||||
SetDrawOrigin(x, y, z, 0)
|
||||
DrawText(0.0, 0.0)
|
||||
local factor = text:len() / 370
|
||||
DrawRect(0.0, 0.0 + 0.0125, 0.017 + factor, 0.03, 0, 0, 0, 75)
|
||||
ClearDrawOrigin()
|
||||
end
|
||||
|
||||
function DrawGenericText(text)
|
||||
SetTextFont(4)
|
||||
SetTextProportional(0)
|
||||
SetTextScale(0.65, 0.65)
|
||||
SetTextDropShadow(0, 0, 0, 0, 255)
|
||||
SetTextEdge(1, 0, 0, 0, 255)
|
||||
SetTextEntry('STRING')
|
||||
AddTextComponentString(text)
|
||||
DrawText(0.825, 0.90)
|
||||
end
|
||||
|
||||
function ProgressBar(name, label, duration, useWhileDead, canCancel, disableControls, animation, prop, propTwo, onFinish, onCancel)
|
||||
if GetResourceState('qs-interface') == 'started' then
|
||||
local success = exports['qs-interface']:ProgressBar({
|
||||
duration = duration,
|
||||
label = label,
|
||||
position = 'bottom',
|
||||
useWhileDead = useWhileDead,
|
||||
canCancel = canCancel,
|
||||
disable = disableControls,
|
||||
anim = {
|
||||
dict = animation.animDict,
|
||||
clip = animation.anim,
|
||||
flag = animation?.flags
|
||||
},
|
||||
prop = prop
|
||||
})
|
||||
if success then
|
||||
onFinish()
|
||||
else
|
||||
onCancel()
|
||||
end
|
||||
return
|
||||
end
|
||||
if lib.progressCircle({
|
||||
duration = duration,
|
||||
label = label,
|
||||
position = 'bottom',
|
||||
useWhileDead = useWhileDead,
|
||||
canCancel = canCancel,
|
||||
disable = disableControls,
|
||||
anim = {
|
||||
dict = animation.animDict,
|
||||
clip = animation.anim,
|
||||
flag = animation?.flags
|
||||
},
|
||||
prop = prop
|
||||
}) then
|
||||
onFinish()
|
||||
else
|
||||
onCancel()
|
||||
end
|
||||
end
|
||||
|
||||
function GetCompanyData(cb)
|
||||
local playerJob = GetPlayerData().job
|
||||
local jobData = {
|
||||
job = playerJob.name,
|
||||
jobLabel = playerJob.label,
|
||||
isBoss = playerJob.isboss,
|
||||
}
|
||||
|
||||
if jobData.isBoss then
|
||||
local moneyPromise = promise.new()
|
||||
TriggerServerCallback('qb-bossmenu:server:GetAccount', function(money)
|
||||
moneyPromise:resolve(money)
|
||||
end, jobData.job)
|
||||
jobData.balance = Citizen.Await(moneyPromise)
|
||||
|
||||
local employeesPromise = promise.new()
|
||||
TriggerServerCallback('qb-bossmenu:server:GetEmployees', function(employees)
|
||||
for i = 1, #employees do
|
||||
local employee = employees[i]
|
||||
employees[i] = {
|
||||
name = employee.name,
|
||||
id = employee.empSource,
|
||||
|
||||
gradeLabel = employee.grade.name,
|
||||
grade = employee.grade.level,
|
||||
|
||||
canInteract = not employee.isboss
|
||||
}
|
||||
end
|
||||
employeesPromise:resolve(employees)
|
||||
end, jobData.job)
|
||||
jobData.employees = Citizen.Await(employeesPromise)
|
||||
|
||||
jobData.grades = {}
|
||||
for k, v in pairs(exports.qbx_core:GetJobs()[jobData.job].grades) do
|
||||
jobData.grades[#jobData.grades + 1] = {
|
||||
key = tonumber(k),
|
||||
value = v.name,
|
||||
}
|
||||
end
|
||||
|
||||
table.sort(jobData.grades, function(a, b)
|
||||
return a.grade < b.grade
|
||||
end)
|
||||
end
|
||||
|
||||
cb(jobData)
|
||||
end
|
||||
|
||||
function DepositMoney(amount, cb)
|
||||
TriggerServerEvent('qb-bossmenu:server:depositMoney', amount)
|
||||
SetTimeout(1500, function()
|
||||
TriggerServerCallback('qb-bossmenu:server:GetAccount', cb, GetPlayerData().job.name)
|
||||
end)
|
||||
end
|
||||
|
||||
function WithdrawMoney(amount, cb)
|
||||
TriggerServerEvent('qb-bossmenu:server:withdrawMoney', amount)
|
||||
SetTimeout(1500, function()
|
||||
TriggerServerCallback('qb-bossmenu:server:GetAccount', cb, GetPlayerData().job.name)
|
||||
end)
|
||||
end
|
||||
|
||||
function HireEmployee(source, cb)
|
||||
TriggerServerEvent('qb-bossmenu:server:HireEmployee', source)
|
||||
TriggerServerCallback('phone:market:getPlayerData', function(playerData)
|
||||
cb({
|
||||
name = playerData.name,
|
||||
id = playerData.id
|
||||
})
|
||||
end, source)
|
||||
end
|
||||
|
||||
function FireEmployee(source, cb)
|
||||
TriggerServerEvent('qb-bossmenu:server:FireEmployee', source)
|
||||
cb(GetPlayerData().job.isboss)
|
||||
end
|
||||
|
||||
function SetGrade(identifier, newGrade, cb)
|
||||
local maxGrade = 0
|
||||
for grade, _ in pairs(exports.qbx_core:GetJobs()[GetPlayerData().job.name].grades) do
|
||||
grade = tonumber(grade)
|
||||
if grade and grade > maxGrade then
|
||||
maxGrade = grade
|
||||
end
|
||||
end
|
||||
|
||||
if newGrade > maxGrade then
|
||||
return cb(false)
|
||||
end
|
||||
|
||||
TriggerServerEvent('qb-bossmenu:server:GradeUpdate', {
|
||||
cid = identifier,
|
||||
grade = newGrade,
|
||||
gradename = exports.qbx_core:GetJobs()[GetPlayerData().job.name].grades[tostring(newGrade)].name
|
||||
})
|
||||
cb(true)
|
||||
end
|
||||
|
||||
function ToggleHud(bool)
|
||||
if bool then
|
||||
Debug('Event to show the hud [client/custom/framework/esx.lua line 317]')
|
||||
DisplayRadar(false) -- You can enable or disable mini-map here
|
||||
if GetResourceState('qs-interface') == 'started' then
|
||||
exports['qs-interface']:ToggleHud(false)
|
||||
end
|
||||
else
|
||||
Debug('Event to hide the hud [client/custom/framework/esx.lua line 317]')
|
||||
DisplayRadar(true) -- You can enable or disable mini-map here
|
||||
if GetResourceState('qs-interface') == 'started' then
|
||||
exports['qs-interface']:ToggleHud(true)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,334 @@
|
||||
--[[
|
||||
Hi dear customer or developer, here you can fully configure your server's
|
||||
framework or you could even duplicate this file to create your own framework.
|
||||
|
||||
If you do not have much experience, we recommend you download the base version
|
||||
of the framework that you use in its latest version and it will work perfectly.
|
||||
]]
|
||||
|
||||
if Config.Framework ~= 'standalone' then
|
||||
return
|
||||
end
|
||||
local RequestId = 0
|
||||
local serverRequests = {}
|
||||
|
||||
local clientCallbacks = {}
|
||||
|
||||
---@param eventName string
|
||||
---@param callback function
|
||||
---@param ... any
|
||||
TriggerServerCallback = function(eventName, callback, ...)
|
||||
serverRequests[RequestId] = callback
|
||||
|
||||
TriggerServerEvent('qs-smartphone-pro:triggerServerCallback', eventName, RequestId, GetInvokingResource() or 'unknown', ...)
|
||||
|
||||
RequestId = RequestId + 1
|
||||
end
|
||||
|
||||
exports('TriggerServerCallback', TriggerServerCallback)
|
||||
|
||||
RegisterNetEvent('qs-smartphone-pro:serverCallback', function(requestId, invoker, ...)
|
||||
if not serverRequests[requestId] then
|
||||
return print(('[^1ERROR^7] Server Callback with requestId ^5%s^7 Was Called by ^5%s^7 but does not exist.'):format(requestId, invoker))
|
||||
end
|
||||
|
||||
serverRequests[requestId](...)
|
||||
serverRequests[requestId] = nil
|
||||
end)
|
||||
|
||||
---@param eventName string
|
||||
---@param callback function
|
||||
_RegisterClientCallback = function(eventName, callback)
|
||||
clientCallbacks[eventName] = callback
|
||||
end
|
||||
|
||||
RegisterNetEvent('qs-smartphone-pro:triggerClientCallback', function(eventName, requestId, invoker, ...)
|
||||
if not clientCallbacks[eventName] then
|
||||
return print(('[^1ERROR^7] Client Callback not registered, name: ^5%s^7, invoker resource: ^5%s^7'):format(eventName, invoker))
|
||||
end
|
||||
|
||||
clientCallbacks[eventName](function(...)
|
||||
TriggerServerEvent('qs-smartphone-pro:clientCallback', requestId, invoker, ...)
|
||||
end, ...)
|
||||
end)
|
||||
|
||||
function isDead()
|
||||
return IsPedDeadOrDying(PlayerPedId(), false) or IsEntityDead(PlayerPedId()) or IsPauseMenuActive() or LocalPlayer.state.dead
|
||||
end
|
||||
|
||||
function GetHungry()
|
||||
Debug('GetHungry is used with standalone')
|
||||
return 100
|
||||
end
|
||||
|
||||
function GetThirsty()
|
||||
Debug('GetThirsty is used with standalone')
|
||||
return 100
|
||||
end
|
||||
|
||||
function GetPlayerData()
|
||||
return {}
|
||||
end
|
||||
|
||||
function GetJobName()
|
||||
Debug('GetJobName is used with standalone')
|
||||
return 'unemployed'
|
||||
end
|
||||
|
||||
function GetMoney()
|
||||
Debug('GetMoney is used with standalone')
|
||||
return 0
|
||||
end
|
||||
|
||||
function GetVehicles() -- Leave the function for compatibility
|
||||
return GetGamePool('CVehicle')
|
||||
end
|
||||
|
||||
function GetClosestEntity(entities, isPlayerEntities, coords, modelFilter)
|
||||
local closestEntity, closestEntityDistance, filteredEntities = -1, -1, nil
|
||||
|
||||
if coords then
|
||||
coords = vector3(coords.x, coords.y, coords.z)
|
||||
else
|
||||
local playerPed = PlayerPedId()
|
||||
coords = GetEntityCoords(playerPed)
|
||||
end
|
||||
|
||||
if modelFilter then
|
||||
filteredEntities = {}
|
||||
|
||||
for k, entity in pairs(entities) do
|
||||
if modelFilter[GetEntityModel(entity)] then
|
||||
filteredEntities[#filteredEntities + 1] = entity
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for k, entity in pairs(filteredEntities or entities) do
|
||||
local distance = #(coords - GetEntityCoords(entity))
|
||||
|
||||
if closestEntityDistance == -1 or distance < closestEntityDistance then
|
||||
closestEntity, closestEntityDistance = isPlayerEntities and k or entity, distance
|
||||
end
|
||||
end
|
||||
|
||||
return closestEntity, closestEntityDistance
|
||||
end
|
||||
|
||||
function FrameworkGetClosestVehicle()
|
||||
return GetClosestEntity(GetVehicles(), false, coords, modelFilter)
|
||||
end
|
||||
|
||||
function _RequestModel(modelHash, cb)
|
||||
modelHash = (type(modelHash) == 'number' and modelHash or joaat(modelHash))
|
||||
|
||||
if not HasModelLoaded(modelHash) and IsModelInCdimage(modelHash) then
|
||||
RequestModel(modelHash)
|
||||
|
||||
while not HasModelLoaded(modelHash) do
|
||||
Wait(0)
|
||||
end
|
||||
end
|
||||
|
||||
if cb ~= nil then
|
||||
cb()
|
||||
end
|
||||
end
|
||||
|
||||
function FrameworkSpawnVehicle(vehicle, coords, heading, cb)
|
||||
local model = type(vehicle) == 'number' and vehicle or joaat(vehicle)
|
||||
local vector = type(coords) == 'vector3' and coords or vec(coords.x, coords.y, coords.z)
|
||||
networked = networked == nil and true or networked
|
||||
|
||||
local playerCoords = GetEntityCoords(PlayerPedId())
|
||||
if not vector or not playerCoords then
|
||||
return
|
||||
end
|
||||
local dist = #(playerCoords - vector)
|
||||
if dist > 424 then -- Onesync infinity Range (https://docs.fivem.net/docs/scripting-reference/onesync/)
|
||||
local executingResource = GetInvokingResource() or 'Unknown'
|
||||
return print(('[^1ERROR^7] Resource ^5%s^7 Tried to spawn vehicle on the client but the position is too far away (Out of onesync range).'):format(executing_resource))
|
||||
end
|
||||
|
||||
CreateThread(function()
|
||||
_RequestModel(model)
|
||||
|
||||
local vehicle = CreateVehicle(model, vector.xyz, heading, networked, true)
|
||||
|
||||
if networked and NetworkGetEntityIsNetworked(vehicle) then
|
||||
local id = NetworkGetNetworkIdFromEntity(vehicle)
|
||||
SetNetworkIdCanMigrate(id, true)
|
||||
SetEntityAsMissionEntity(vehicle, true, true)
|
||||
end
|
||||
SetVehicleHasBeenOwnedByPlayer(vehicle, true)
|
||||
SetVehicleNeedsToBeHotwired(vehicle, false)
|
||||
SetModelAsNoLongerNeeded(model)
|
||||
SetVehRadioStation(vehicle, 'OFF')
|
||||
|
||||
RequestCollisionAtCoord(vector.xyz)
|
||||
while not HasCollisionLoadedAroundEntity(vehicle) do
|
||||
Wait(0)
|
||||
end
|
||||
|
||||
if cb then
|
||||
cb(vehicle)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function FrameworkSetVehicleProperties(vehicle, props)
|
||||
Debug('FrameworkSetVehicleProperties is used with standalone')
|
||||
return true
|
||||
end
|
||||
|
||||
function FrameworkGetVehicles(cb)
|
||||
return GetVehicles()
|
||||
end
|
||||
|
||||
function GetIdentifier()
|
||||
return TriggerServerCallbackSync('qs-smartphone-pro:GetIdentifier')
|
||||
end
|
||||
|
||||
function GetPlayerMoney()
|
||||
Debug('GetPlayerMoney is used with standalone')
|
||||
return 100
|
||||
end
|
||||
|
||||
function SendTextMessage(msg, type)
|
||||
if GetResourceState('qs-interface') == 'started' then
|
||||
if type == 'inform' then
|
||||
exports['qs-interface']:AddNotify(msg, 'Inform', 2500, 'fas fa-file')
|
||||
elseif type == 'error' then
|
||||
exports['qs-interface']:AddNotify(msg, 'Error', 2500, 'fas fa-bug')
|
||||
elseif type == 'success' then
|
||||
exports['qs-interface']:AddNotify(msg, 'Success', 2500, 'fas fa-thumbs-up')
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
if type == 'inform' then
|
||||
lib.notify({
|
||||
title = 'Smartphone',
|
||||
description = msg,
|
||||
type = 'inform'
|
||||
})
|
||||
elseif type == 'error' then
|
||||
lib.notify({
|
||||
title = 'Smartphone',
|
||||
description = msg,
|
||||
type = 'error'
|
||||
})
|
||||
elseif type == 'success' then
|
||||
lib.notify({
|
||||
title = 'Smartphone',
|
||||
description = msg,
|
||||
type = 'success'
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
local texts = {}
|
||||
if GetResourceState('qs-textui') == 'started' then
|
||||
function DrawText3D(x, y, z, text, id, key)
|
||||
local _id = id
|
||||
if not texts[_id] then
|
||||
CreateThread(function()
|
||||
texts[_id] = 5
|
||||
while texts[_id] > 0 do
|
||||
texts[_id] = texts[_id] - 1
|
||||
Wait(0)
|
||||
end
|
||||
texts[_id] = nil
|
||||
exports['qs-textui']:DeleteDrawText3D(id)
|
||||
Debug('Deleted text', id)
|
||||
end)
|
||||
TriggerEvent('textui:DrawText3D', x, y, z, text, id, key)
|
||||
end
|
||||
texts[_id] = 5
|
||||
end
|
||||
else
|
||||
function DrawText3D(x, y, z, text)
|
||||
SetTextScale(0.35, 0.35)
|
||||
SetTextFont(4)
|
||||
SetTextProportional(1)
|
||||
SetTextColour(255, 255, 255, 215)
|
||||
SetTextEntry('STRING')
|
||||
SetTextCentre(true)
|
||||
AddTextComponentString(text)
|
||||
SetDrawOrigin(x, y, z, 0)
|
||||
DrawText(0.0, 0.0)
|
||||
local factor = text:len() / 370
|
||||
DrawRect(0.0, 0.0 + 0.0125, 0.017 + factor, 0.03, 0, 0, 0, 75)
|
||||
ClearDrawOrigin()
|
||||
end
|
||||
end
|
||||
|
||||
function DrawGenericText(text)
|
||||
SetTextFont(4)
|
||||
SetTextProportional(0)
|
||||
SetTextScale(0.65, 0.65)
|
||||
SetTextDropShadow(0, 0, 0, 0, 255)
|
||||
SetTextEdge(1, 0, 0, 0, 255)
|
||||
SetTextEntry('STRING')
|
||||
AddTextComponentString(text)
|
||||
DrawText(0.825, 0.90)
|
||||
end
|
||||
|
||||
function ProgressBar(name, label, duration, useWhileDead, canCancel, disableControls, animation, prop, propTwo, onFinish, onCancel)
|
||||
if GetResourceState('qs-interface') == 'started' then
|
||||
local success = exports['qs-interface']:ProgressBar({
|
||||
duration = duration,
|
||||
label = label,
|
||||
position = 'bottom',
|
||||
useWhileDead = useWhileDead,
|
||||
canCancel = canCancel,
|
||||
disable = disableControls,
|
||||
anim = {
|
||||
dict = animation.animDict,
|
||||
clip = animation.anim,
|
||||
flag = animation?.flags
|
||||
},
|
||||
prop = prop
|
||||
})
|
||||
if success then
|
||||
onFinish()
|
||||
else
|
||||
onCancel()
|
||||
end
|
||||
return
|
||||
end
|
||||
if lib.progressCircle({
|
||||
duration = duration,
|
||||
label = label,
|
||||
position = 'bottom',
|
||||
useWhileDead = useWhileDead,
|
||||
canCancel = canCancel,
|
||||
disable = disableControls,
|
||||
anim = {
|
||||
dict = animation.animDict,
|
||||
clip = animation.anim,
|
||||
flag = animation?.flags
|
||||
},
|
||||
prop = prop
|
||||
}) then
|
||||
onFinish()
|
||||
else
|
||||
onCancel()
|
||||
end
|
||||
end
|
||||
|
||||
function ToggleHud(bool)
|
||||
if bool then
|
||||
Debug('Event to show the hud [client/custom/framework/esx.lua line 320]')
|
||||
DisplayRadar(false) -- You can enable or disable mini-map here
|
||||
if GetResourceState('qs-interface') == 'started' then
|
||||
exports['qs-interface']:ToggleHud(false)
|
||||
end
|
||||
else
|
||||
Debug('Event to hide the hud [client/custom/framework/esx.lua line 320]')
|
||||
DisplayRadar(true) -- You can enable or disable mini-map here
|
||||
if GetResourceState('qs-interface') == 'started' then
|
||||
exports['qs-interface']:ToggleHud(true)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,235 @@
|
||||
if Config.Menu ~= 'nh-context' then
|
||||
return
|
||||
end
|
||||
|
||||
function openRecipeMenu()
|
||||
TriggerServerCallback('phone:CheckExistRecipe', function(exist)
|
||||
local method = exist?.method or ''
|
||||
local moment_header = ([[
|
||||
Moment %s
|
||||
]]):format(method == 'moment' and '<span style="color:green; margin-left: 4px"> - ' .. Lang('PHONE_MENU_RECIPES_OPTION_CURRENTLY') .. exist?.amount .. '</span>' or '')
|
||||
local daily_header = ([[
|
||||
Daily %s
|
||||
]]):format(method == 'daily' and ' - ' .. Lang('PHONE_MENU_RECIPES_OPTION_CURRENTLY') or '')
|
||||
local data = {
|
||||
{
|
||||
header = Lang('PHONE_MENU_RECIPES_TITLE'),
|
||||
},
|
||||
{
|
||||
header = daily_header,
|
||||
context = Lang('PHONE_MENU_RECIPES_UPDATED'),
|
||||
event = 'phone:recipeSelectMethod',
|
||||
args = { 'daily' }
|
||||
},
|
||||
{
|
||||
header = moment_header,
|
||||
context = Lang('PHONE_MENU_RECIPES_CONTOUR'),
|
||||
event = 'phone:recipeSelectMethod',
|
||||
args = { 'moment' }
|
||||
},
|
||||
}
|
||||
if exist then
|
||||
table.insert(data, {
|
||||
header = "<span style='color: gray'>" .. Lang('PHONE_MENU_RECIPES_OPTION_CANCEL') .. '</span>',
|
||||
context = Lang('PHONE_MENU_RECIPES_CANCEL'),
|
||||
event = 'phone:CancelRecipe',
|
||||
server = true,
|
||||
args = {}
|
||||
})
|
||||
end
|
||||
TriggerEvent('nh-context:createMenu', data)
|
||||
end)
|
||||
end
|
||||
|
||||
function openPhoneBoothMenu(isNearPB)
|
||||
local data = {
|
||||
{
|
||||
header = Lang('PHONE_MENU_BOOTH_CALL_TITLE'),
|
||||
},
|
||||
{
|
||||
header = Lang('PHONE_MENU_BOOTH_CALL_POLICE'),
|
||||
context = 'police',
|
||||
event = 'phone:boothCall',
|
||||
args = { 'police' }
|
||||
},
|
||||
{
|
||||
header = Lang('PHONE_MENU_BOOTH_CALL_AMBULANCE'),
|
||||
context = 'ambulance',
|
||||
event = 'phone:boothCall',
|
||||
args = { 'ambulance' }
|
||||
},
|
||||
{
|
||||
header = Lang('PHONE_MENU_BOOTH_CALL_MECHANIC'),
|
||||
context = 'mechanic',
|
||||
event = 'phone:boothCall',
|
||||
args = { 'mechanic' }
|
||||
},
|
||||
{
|
||||
header = Lang('PHONE_MENU_BOOTH_CALL_NUMBER'),
|
||||
context = 'othercall',
|
||||
event = 'phone:boothCall',
|
||||
args = { 'othercall' }
|
||||
}
|
||||
}
|
||||
|
||||
TriggerEvent('nh-context:createMenu', data)
|
||||
end
|
||||
|
||||
function openRentalMenu(key)
|
||||
local data = {
|
||||
{
|
||||
header = Lang('PHONE_MENU_RENTEL_TITLE')
|
||||
}
|
||||
}
|
||||
local coords = { x = Config.RentelLocations[key]['coords'].x, y = Config.RentelLocations[key]['coords'].y, z = Config.RentelLocations[key]['coords'].z, h = Config.RentelLocations[key]['coords'].w }
|
||||
for model, v in pairs(Config.RentelVehicles) do
|
||||
if v.stored then
|
||||
table.insert(data, {
|
||||
header = v.label .. ' - ' .. Lang('PHONE_MENU_RENTEL_STORED'),
|
||||
context = 'Rentel',
|
||||
event = 'phone:server:spawnVehicle',
|
||||
server = true,
|
||||
args = { {
|
||||
model = model, price = 0, coords = coords
|
||||
} }
|
||||
})
|
||||
else
|
||||
table.insert(data, {
|
||||
header = v.label .. ' - ' .. Lang('PHONE_MENU_RENTEL_MONEY') .. v.price,
|
||||
context = 'Rentel',
|
||||
event = 'phone:server:spawnVehicle',
|
||||
server = true,
|
||||
args = { {
|
||||
model = model, price = v.price, coords = coords
|
||||
} }
|
||||
})
|
||||
end
|
||||
end
|
||||
TriggerEvent('nh-context:createMenu', data)
|
||||
end
|
||||
|
||||
function resetPasswordMenu()
|
||||
local data = {
|
||||
{
|
||||
header = Lang('PHONE_MENU_PHONE_TITLE')
|
||||
},
|
||||
{
|
||||
header = Lang('PHONE_MENU_PHONE_RESET_PASSWORD') .. Config.ResetPassword.money,
|
||||
context = 'Reset Password',
|
||||
event = 'phone:ResetPassword'
|
||||
}
|
||||
}
|
||||
TriggerEvent('nh-context:createMenu', data)
|
||||
end
|
||||
|
||||
RegisterNetEvent('phone:openPhoneMenu', function(event, ...)
|
||||
local items = GetInventory()
|
||||
local data = {
|
||||
{
|
||||
header = Lang('PHONE_MENU_BATTERY_TITLE')
|
||||
}
|
||||
}
|
||||
if not Config.UniquePhone then
|
||||
local userData = TriggerServerCallbackSync('phone:getUserData')
|
||||
if not userData then
|
||||
Debug('phone', 'userData is nil')
|
||||
return
|
||||
end
|
||||
table.insert(data, {
|
||||
header = Lang('PHONE_MENU_BATTERY_PHONE_NUMBER') .. ' ' .. userData.phoneNumber,
|
||||
context = 'Phone',
|
||||
event = 'phone:selectPhone',
|
||||
args = { { name = 'phone', info = { phoneNumber = userData.phoneNumber } }, event, ... }
|
||||
})
|
||||
end
|
||||
if Config.UniquePhone then
|
||||
for phoneName in pairs(Config.Phones) do
|
||||
for k, v in pairs(items) do
|
||||
local meta = v.info or v.metadata
|
||||
if v.name == phoneName and meta?.phoneNumber then
|
||||
table.insert(data, {
|
||||
header = Lang('PHONE_MENU_BATTERY_PHONE_NUMBER') .. ' ' .. meta.phoneNumber,
|
||||
context = 'Phone',
|
||||
event = 'phone:selectPhone',
|
||||
args = { v, event, ... }
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if #data < 2 then return SendTextMessage(Lang('PHONE_NOTIFICATION_PHONE_NO_PHONE'), 'error') end
|
||||
TriggerEvent('nh-context:createMenu', data)
|
||||
end)
|
||||
|
||||
RegisterNetEvent('phone:client:openChannelMenu', function()
|
||||
if not MetaData then return SendTextMessage(Lang('PHONE_NOTIFICATION_RECIPES_USE_PHONE_FIRST'), 'inform') end
|
||||
local input = lib.inputDialog(Lang('PHONE_MENU_DISCORD_CHANNEL_TITLE'), {
|
||||
Lang('PHONE_MENU_DISCORD_SELECT_NAME'),
|
||||
Lang('PHONE_MENU_DISCORD_SELECT_PASSWORD')
|
||||
})
|
||||
if not input then return end
|
||||
local channelName = input[1]
|
||||
local passcode = input[2]
|
||||
|
||||
Debug('phone', 'channelName', channelName, 'passcode', passcode)
|
||||
|
||||
local roomData = {
|
||||
room_owner_name = MetaData.charinfo.firstname .. ' ' .. MetaData.charinfo.lastname
|
||||
}
|
||||
|
||||
local allGood = false
|
||||
|
||||
if channelName then
|
||||
roomData.room_name = channelName
|
||||
allGood = true
|
||||
end
|
||||
|
||||
if passcode then
|
||||
roomData.room_pin = passcode
|
||||
end
|
||||
|
||||
if allGood then
|
||||
TriggerServerCallback('phone:server:PurchaseRoom', function(status)
|
||||
if status then
|
||||
local source = GetPlayerServerId(PlayerId())
|
||||
TriggerServerEvent('phone:server:CreateRoom', source, roomData)
|
||||
end
|
||||
end, 250)
|
||||
end
|
||||
end)
|
||||
|
||||
RegisterNetEvent('phone:client:openChannelHackedMenu', function()
|
||||
if not MetaData then return SendTextMessage(Lang('PHONE_NOTIFICATION_RECIPES_USE_PHONE_FIRST'), 'inform') end
|
||||
|
||||
local keyboard, channelName, passcode = exports['nh-keyboard']:Keyboard({
|
||||
header = Lang('PHONE_MENU_DISCORD_SECURE_TITLE'),
|
||||
rows = { Lang('PHONE_MENU_DISCORD_SELECT_NAME'), Lang('PHONE_MENU_DISCORD_SELECT_PASSWORD') }
|
||||
})
|
||||
|
||||
if keyboard then
|
||||
local roomData = {
|
||||
room_owner_name = MetaData.charinfo.firstname .. ' ' .. MetaData.charinfo.lastname
|
||||
}
|
||||
|
||||
local allGood = false
|
||||
|
||||
if channelName then
|
||||
roomData.room_name = channelName
|
||||
allGood = true
|
||||
end
|
||||
|
||||
if passcode then
|
||||
roomData.room_pin = passcode
|
||||
end
|
||||
|
||||
if allGood then
|
||||
TriggerServerCallback('phone:server:PurchaseRoom', function(status)
|
||||
if status then
|
||||
local source = GetPlayerServerId(PlayerId())
|
||||
TriggerServerEvent('phone:server:CreateRoom', source, roomData, true)
|
||||
end
|
||||
end, 5000)
|
||||
end
|
||||
end
|
||||
end)
|
||||
@@ -0,0 +1,239 @@
|
||||
if Config.Menu ~= 'ox_lib' then
|
||||
return
|
||||
end
|
||||
|
||||
function openRecipeMenu()
|
||||
TriggerServerCallback('phone:CheckExistRecipe', function(recipe)
|
||||
print(json.encode(recipe))
|
||||
local method = recipe and recipe.method or ''
|
||||
local isMoment = method == 'moment'
|
||||
local isDaily = method == 'daily'
|
||||
|
||||
local momentHeader = isMoment and (' - ' .. Lang('PHONE_MENU_RECIPES_OPTION_CURRENTLY') .. " " .. recipe.amount) or ''
|
||||
local dailyHeader = isDaily and (' - ' .. Lang('PHONE_MENU_RECIPES_OPTION_CURRENTLY') .. " " .. recipe.amount) or ''
|
||||
|
||||
local options = {
|
||||
{
|
||||
title = ("%s $%s"):format(Lang('PHONE_MENU_RECIPES_UPDATED'), Config.BuyRecipe.prices["daily"]),
|
||||
description = dailyHeader,
|
||||
onSelect = function()
|
||||
TriggerEvent('phone:recipeSelectMethod', 'daily')
|
||||
end
|
||||
},
|
||||
{
|
||||
title = ("%s $%s"):format(Lang('PHONE_MENU_RECIPES_CONTOUR'), Config.BuyRecipe.prices["moment"]),
|
||||
description = momentHeader,
|
||||
onSelect = function()
|
||||
TriggerEvent('phone:recipeSelectMethod', 'moment')
|
||||
end
|
||||
}
|
||||
}
|
||||
|
||||
if recipe then
|
||||
table.insert(options, {
|
||||
title = Lang('PHONE_MENU_RECIPES_CANCEL'),
|
||||
onSelect = function()
|
||||
TriggerServerEvent('phone:CancelRecipe')
|
||||
end
|
||||
})
|
||||
end
|
||||
|
||||
lib.registerContext({
|
||||
id = 'recipe_spot',
|
||||
title = Lang('PHONE_MENU_RECIPES_TITLE'),
|
||||
options = options
|
||||
})
|
||||
|
||||
lib.showContext('recipe_spot')
|
||||
end)
|
||||
end
|
||||
|
||||
function openPhoneBoothMenu(isNearPB)
|
||||
local data = {
|
||||
{
|
||||
title = Lang('PHONE_MENU_BOOTH_CALL_POLICE'),
|
||||
onSelect = function(args)
|
||||
TriggerEvent('phone:boothCall', 'police')
|
||||
end
|
||||
},
|
||||
{
|
||||
title = Lang('PHONE_MENU_BOOTH_CALL_AMBULANCE'),
|
||||
onSelect = function(args)
|
||||
TriggerEvent('phone:boothCall', 'police')
|
||||
end
|
||||
},
|
||||
{
|
||||
title = Lang('PHONE_MENU_BOOTH_CALL_MECHANIC'),
|
||||
onSelect = function(args)
|
||||
TriggerEvent('phone:boothCall', 'police')
|
||||
end
|
||||
},
|
||||
{
|
||||
title = Lang('PHONE_MENU_BOOTH_CALL_NUMBER'),
|
||||
onSelect = function(args)
|
||||
TriggerEvent('phone:boothCall', 'othercall')
|
||||
end
|
||||
},
|
||||
}
|
||||
lib.registerContext({
|
||||
id = 'phone_booth',
|
||||
title = Lang('PHONE_MENU_BOOTH_CALL_TITLE'),
|
||||
options = data
|
||||
})
|
||||
lib.showContext('phone_booth')
|
||||
end
|
||||
|
||||
function openRentalMenu(key)
|
||||
local coords = { x = Config.RentelLocations[key]['coords'].x, y = Config.RentelLocations[key]['coords'].y, z = Config.RentelLocations[key]['coords'].z, h = Config.RentelLocations[key]['coords'].w }
|
||||
local data = {}
|
||||
for model, v in pairs(Config.RentelVehicles) do
|
||||
if v.stored then
|
||||
table.insert(data, {
|
||||
title = v.label .. ' - ' .. Lang('PHONE_MENU_RENTEL_STORED'),
|
||||
onSelect = function(args)
|
||||
TriggerServerEvent('phone:server:spawnVehicle', { model = model, price = 0, coords = coords })
|
||||
end
|
||||
})
|
||||
else
|
||||
table.insert(data, {
|
||||
title = v.label .. ' - ' .. Lang('PHONE_MENU_RENTEL_MONEY') .. v.price,
|
||||
onSelect = function(args)
|
||||
TriggerServerEvent('phone:server:spawnVehicle', { model = model, price = v.price, coords = coords })
|
||||
end
|
||||
})
|
||||
end
|
||||
end
|
||||
lib.registerContext({
|
||||
id = 'rentel_spot',
|
||||
title = Lang('PHONE_MENU_RENTEL_TITLE'),
|
||||
options = data
|
||||
})
|
||||
lib.showContext('rentel_spot')
|
||||
end
|
||||
|
||||
function resetPasswordMenu()
|
||||
local data = {
|
||||
{
|
||||
title = Lang('PHONE_MENU_PHONE_RESET_PASSWORD') .. Config.ResetPassword.money,
|
||||
onSelect = function(args)
|
||||
TriggerEvent('phone:ResetPassword')
|
||||
end
|
||||
}
|
||||
}
|
||||
lib.registerContext({
|
||||
id = 'reset_password',
|
||||
title = Lang('PHONE_MENU_PHONE_TITLE'),
|
||||
options = data
|
||||
})
|
||||
lib.showContext('reset_password')
|
||||
end
|
||||
|
||||
RegisterNetEvent('phone:openPhoneMenu', function(event, ...)
|
||||
local items = GetInventory()
|
||||
local data = {}
|
||||
local varargs = { ... }
|
||||
if not Config.UniquePhone then
|
||||
local userData = TriggerServerCallbackSync('phone:getUserData')
|
||||
if userData then
|
||||
table.insert(data, {
|
||||
title = Lang('PHONE_MENU_BATTERY_PHONE_NUMBER') .. ' ' .. userData.phoneNumber,
|
||||
onSelect = function(args)
|
||||
TriggerServerEvent(event, {
|
||||
name = 'phone',
|
||||
info = { phoneNumber = userData.phoneNumber }
|
||||
}, table.unpack(varargs))
|
||||
end,
|
||||
})
|
||||
end
|
||||
else
|
||||
for phoneName in pairs(Config.Phones) do
|
||||
for k, v in pairs(items) do
|
||||
local meta = v.info or v.metadata
|
||||
if v.name == phoneName and meta?.phoneNumber then
|
||||
table.insert(data, {
|
||||
title = Lang('PHONE_MENU_BATTERY_PHONE_NUMBER') .. ' ' .. meta.phoneNumber,
|
||||
onSelect = function(args)
|
||||
TriggerServerEvent(event, v, table.unpack(varargs))
|
||||
end,
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if #data < 1 then return SendTextMessage(Lang('PHONE_NOTIFICATION_PHONE_NO_PHONE'), 'error') end
|
||||
lib.registerContext({
|
||||
id = 'charger_spot',
|
||||
title = Lang('PHONE_MENU_BATTERY_TITLE'),
|
||||
options = data
|
||||
})
|
||||
lib.showContext('charger_spot')
|
||||
end)
|
||||
|
||||
RegisterNetEvent('phone:client:openChannelMenu', function()
|
||||
if not MetaData then return SendTextMessage(Lang('PHONE_NOTIFICATION_RECIPES_USE_PHONE_FIRST'), 'inform') end
|
||||
local input = lib.inputDialog(Lang('PHONE_MENU_DISCORD_CHANNEL_TITLE'), {
|
||||
{ type = 'input', label = Lang('PHONE_MENU_DISCORD_SELECT_NAME'), description = Lang('PHONE_MENU_DISCORD_SELECT_NAME_INFO'), required = true },
|
||||
{ type = 'number', label = Lang('PHONE_MENU_DISCORD_SELECT_PASSWORD'), description = Lang('PHONE_MENU_DISCORD_SELECT_PASSWORD_INFO'), required = false },
|
||||
})
|
||||
|
||||
if input and input[1] then
|
||||
local roomData = {
|
||||
room_owner_name = MetaData.charinfo.firstname .. ' ' .. MetaData.charinfo.lastname
|
||||
}
|
||||
|
||||
local allGood = false
|
||||
|
||||
if input[1] then
|
||||
roomData.room_name = input[1]
|
||||
allGood = true
|
||||
end
|
||||
|
||||
if input[2] then
|
||||
roomData.room_pin = input[2]
|
||||
end
|
||||
|
||||
if allGood then
|
||||
TriggerServerCallback('phone:server:PurchaseRoom', function(status)
|
||||
if status then
|
||||
local source = GetPlayerServerId(PlayerId())
|
||||
TriggerServerEvent('phone:server:CreateRoom', source, roomData)
|
||||
end
|
||||
end, 250)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
RegisterNetEvent('phone:client:openChannelHackedMenu', function()
|
||||
if not MetaData then return SendTextMessage(Lang('PHONE_NOTIFICATION_RECIPES_USE_PHONE_FIRST'), 'inform') end
|
||||
local input = lib.inputDialog(Lang('PHONE_MENU_DISCORD_SECURE_TITLE'), {
|
||||
{ type = 'input', label = Lang('PHONE_MENU_DISCORD_SELECT_NAME'), description = Lang('PHONE_MENU_DISCORD_SELECT_NAME_INFO'), required = true },
|
||||
{ type = 'number', label = Lang('PHONE_MENU_DISCORD_SELECT_PASSWORD'), description = Lang('PHONE_MENU_DISCORD_SELECT_PASSWORD_INFO'), required = false },
|
||||
})
|
||||
|
||||
if input and input[1] then
|
||||
local roomData = {
|
||||
room_owner_name = MetaData.charinfo.firstname .. ' ' .. MetaData.charinfo.lastname
|
||||
}
|
||||
|
||||
local allGood = false
|
||||
|
||||
if input[1] then
|
||||
roomData.room_name = input[1]
|
||||
allGood = true
|
||||
end
|
||||
|
||||
if input[2] then
|
||||
roomData.room_pin = input[2]
|
||||
end
|
||||
|
||||
if allGood then
|
||||
TriggerServerCallback('phone:server:PurchaseRoom', function(status)
|
||||
if status then
|
||||
local source = GetPlayerServerId(PlayerId())
|
||||
TriggerServerEvent('phone:server:CreateRoom', source, roomData, true)
|
||||
end
|
||||
end, 250)
|
||||
end
|
||||
end
|
||||
end)
|
||||
@@ -0,0 +1,76 @@
|
||||
function DisableControlActions()
|
||||
-- Disables mouse actions
|
||||
DisableControlAction(0, 18, true) -- Disable mouse
|
||||
DisableControlAction(0, 69, true) -- Disable mouse
|
||||
DisableControlAction(0, 92, true) -- Disable mouse
|
||||
DisableControlAction(0, 106, true) -- Disable mouse
|
||||
DisableControlAction(0, 122, true) -- Disable mouse
|
||||
|
||||
-- Disables mouse look actions
|
||||
if not KeepInput then
|
||||
DisableControlAction(0, 12, true) -- Disable mouse look
|
||||
DisableControlAction(0, 13, true) -- Disable mouse look
|
||||
DisableControlAction(0, 1, true) -- Disable mouse look
|
||||
DisableControlAction(0, 2, true) -- Disable mouse look
|
||||
DisableControlAction(0, 3, true) -- Disable mouse look
|
||||
DisableControlAction(0, 4, true) -- Disable mouse look
|
||||
DisableControlAction(0, 5, true) -- Disable mouse look
|
||||
DisableControlAction(0, 6, true) -- Disable mouse look
|
||||
end
|
||||
|
||||
-- Disables melee combat actions
|
||||
DisableControlAction(0, 263, true) -- Disable melee
|
||||
DisableControlAction(0, 264, true) -- Disable melee
|
||||
DisableControlAction(0, 257, true) -- Disable melee
|
||||
DisableControlAction(0, 140, true) -- Disable melee
|
||||
DisableControlAction(0, 141, true) -- Disable melee
|
||||
DisableControlAction(0, 142, true) -- Disable melee
|
||||
DisableControlAction(0, 143, true) -- Disable melee
|
||||
|
||||
-- Disables escape and chat actions
|
||||
DisableControlAction(0, 177, true) -- Disable escape
|
||||
DisableControlAction(0, 200, true) -- Disable escape
|
||||
DisableControlAction(0, 202, true) -- Disable escape
|
||||
DisableControlAction(0, 322, true) -- Disable escape
|
||||
DisableControlAction(0, 245, true) -- Disable chat
|
||||
DisableControlAction(0, 199, true) -- Disable chat
|
||||
|
||||
-- Disables aiming and shooting actions
|
||||
DisableControlAction(0, 25, true) -- Disable aim
|
||||
DisableControlAction(0, 24, true) -- Disable shoot
|
||||
|
||||
-- Disables other specific actions
|
||||
DisableControlAction(0, 45, true) -- Disable Reload (R)
|
||||
DisableControlAction(0, 44, true) -- Disable Cover (Q)
|
||||
DisableControlAction(0, 0, true) -- Disable Camera (V)
|
||||
DisableControlAction(0, 26, true) -- Disable Camera Back (C)
|
||||
DisableControlAction(0, 20, true) -- Disable Z
|
||||
DisableControlAction(0, 236, true) -- Disable V
|
||||
|
||||
-- Disables numerical actions
|
||||
DisableControlAction(0, 157, true) -- Disable 1
|
||||
DisableControlAction(0, 158, true) -- Disable 2
|
||||
DisableControlAction(0, 160, true) -- Disable 3
|
||||
DisableControlAction(0, 164, true) -- Disable 4
|
||||
DisableControlAction(0, 165, true) -- Disable 5
|
||||
DisableControlAction(0, 159, true) -- Disable 6
|
||||
DisableControlAction(0, 161, true) -- Disable 7
|
||||
DisableControlAction(0, 162, true) -- Disable 8
|
||||
DisableControlAction(0, 163, true) -- Disable 9
|
||||
|
||||
-- Other specific disablements
|
||||
DisableControlAction(0, 73, true) -- Disable X
|
||||
DisableControlAction(0, 47, true) -- Disable G
|
||||
DisableControlAction(0, 58, true) -- Disable G
|
||||
DisableControlAction(0, 74, true) -- Disable H
|
||||
|
||||
-- Disables control action for second player
|
||||
DisableControlAction(1, 18, true) -- Enter / Exit vehicle
|
||||
DisableControlAction(1, 24, true) -- Change weapon
|
||||
DisableControlAction(1, 69, true) -- Fire
|
||||
DisableControlAction(1, 92, true) -- Aim
|
||||
DisableControlAction(1, 106, true) -- Jump
|
||||
DisableControlAction(1, 122, true) -- Sprint
|
||||
DisableControlAction(1, 135, true) -- Duck / Cover
|
||||
-- ... (continues the list for the second player)
|
||||
end
|
||||
@@ -0,0 +1,39 @@
|
||||
---@param emergency? boolean
|
||||
---@return boolean
|
||||
function TogglePhone(emergency)
|
||||
if not emergency and (isDead() or not canOpenPhone) then return false end
|
||||
if not Config.UniquePhone then
|
||||
local hasData = lib.callback.await('phone:server:HasPhone', 0)
|
||||
if not hasData.phone then
|
||||
SendTextMessage(Lang('PHONE_NOTIFICATION_PHONE_NO_PHONE'), 'error')
|
||||
return false
|
||||
end
|
||||
local meta = TriggerServerCallbackSync('phone:GetPhoneDataForWithoutMeta')
|
||||
OpenPhone(hasData.phone, Config.PhonesProps[hasData.name], meta)
|
||||
return true
|
||||
end
|
||||
if not MetaData then
|
||||
TriggerServerEvent('phone:server:openRandomItemPhone')
|
||||
return true
|
||||
end
|
||||
local phoneData, name = TriggerServerCallbackSync('phone:server:checkHasPhoneWithUniqueId', MetaData.uniqueId)
|
||||
if not phoneData then
|
||||
if MetaData then
|
||||
MetaData = nil
|
||||
TriggerServerEvent('phone:server:openRandomItemPhone')
|
||||
-- SendTextMessage('Your phone is fucked up', 'inform')
|
||||
return true
|
||||
end
|
||||
SendTextMessage(Lang('PHONE_NOTIFICATION_PHONE_NO_PHONE'), 'error')
|
||||
return false
|
||||
end
|
||||
OpenPhone(CurrentPhoneData.type, CurrentPhoneData.phoneColor, MetaData)
|
||||
return true
|
||||
end
|
||||
|
||||
if not Config.OpenPhoneByPress and Config.UniquePhone then return end
|
||||
RegisterKeyMapping('TooglePhone', 'Open phone', 'keyboard', Config.OpenPhone)
|
||||
|
||||
RegisterCommand('TooglePhone', function()
|
||||
TogglePhone()
|
||||
end, false)
|
||||
@@ -0,0 +1,256 @@
|
||||
if not Config.UseTarget then
|
||||
return
|
||||
end
|
||||
|
||||
TargetName = GetResourceState('ox_target'):find('started') and 'qtarget' or 'qb-target'
|
||||
|
||||
local hasHackedPhone = false
|
||||
|
||||
function UberEatsDoors(uberChoosenAdress)
|
||||
exports[TargetName]:AddBoxZone('uber_eats_zone', vec3(Config.UberDelivery[uberChoosenAdress]['x'], Config.UberDelivery[uberChoosenAdress]['y'], Config.UberDelivery[uberChoosenAdress]['z'] - 1), 2.5, 2.5, {
|
||||
name = 'uber_eats_zone',
|
||||
heading = 90.0,
|
||||
debugPoly = Config.ZoneDebug,
|
||||
minZ = Config.UberDelivery[uberChoosenAdress]['z'] - 1,
|
||||
maxZ = Config.UberDelivery[uberChoosenAdress]['z'] + 1,
|
||||
}, {
|
||||
options = {
|
||||
{
|
||||
icon = 'fa-solid fa-door-open',
|
||||
label = Lang('PHONE_TARGET_UBEREATS_DELIVER_DELIVERY'),
|
||||
action = function()
|
||||
TriggerServerCallback('phone:checkItem', function(qtty)
|
||||
if qtty > 0 then
|
||||
TriggerServerEvent('phone:removeItem', Config.UberItems[uberChoosenItem]['item'])
|
||||
doorKnocked = true
|
||||
npcHome = math.random(1, 2)
|
||||
PlayAnimation(PlayerPedId(), 'timetable@jimmy@doorknock@', 'knockdoor_idle')
|
||||
Citizen.Wait(3000)
|
||||
|
||||
if npcHome == 1 then
|
||||
Citizen.Wait(2000)
|
||||
packagePoint = false
|
||||
UberReward()
|
||||
else
|
||||
Citizen.Wait(2000)
|
||||
UberReward()
|
||||
end
|
||||
-- Después de la acción, eliminar el target
|
||||
RemoveUberTarget()
|
||||
uberTargeted = false
|
||||
else
|
||||
SendTextMessage(Lang('PHONE_NOTIFICATION_UBEREATS_NO_ITEM') .. ' ' .. Config.UberItems[uberChoosenItem]['name'], 'error')
|
||||
end
|
||||
end, Config.UberItems[uberChoosenItem]['item'])
|
||||
end,
|
||||
},
|
||||
},
|
||||
distance = 2.5
|
||||
})
|
||||
end
|
||||
|
||||
function RemoveUberTarget()
|
||||
exports[TargetName]:RemoveZone('uber_eats_zone')
|
||||
end
|
||||
|
||||
CreateThread(function()
|
||||
exports[TargetName]:AddTargetModel(Config.ChatSeller, {
|
||||
options = {
|
||||
{
|
||||
type = 'client',
|
||||
event = 'phone:client:openChannelMenu',
|
||||
icon = 'fas fa-comment-dots',
|
||||
label = Lang('PHONE_TARGET_DISCORD_PURCHASE_CHAT_CHANNEL'),
|
||||
targeticon = 'fas fa-comments',
|
||||
},
|
||||
{
|
||||
type = 'client',
|
||||
event = 'phone:client:openChannelHackedMenu',
|
||||
icon = 'fas fa-user-secret',
|
||||
label = Lang('PHONE_TARGET_DISCORD_PURCHASE_SECURE_CHANNEL'),
|
||||
targeticon = 'fas fa-comments',
|
||||
canInteract = function()
|
||||
TriggerServerCallback('phone:server:hasHackedPhone', function(result)
|
||||
hasHackedPhone = result
|
||||
end)
|
||||
Citizen.Wait(500)
|
||||
|
||||
return hasHackedPhone
|
||||
end
|
||||
}
|
||||
},
|
||||
distance = 5.0
|
||||
})
|
||||
|
||||
exports[TargetName]:AddBoxZone('crypto_spot', vec3(Crypto.Exchange.coords.x, Crypto.Exchange.coords.y, Crypto.Exchange.coords.z), 1.5, 1.5, {
|
||||
name = 'crypto_spot',
|
||||
heading = 90.0,
|
||||
debugPoly = Config.ZoneDebug,
|
||||
minZ = Crypto.Exchange.coords.z - 1,
|
||||
maxZ = Crypto.Exchange.coords.z + 1,
|
||||
}, {
|
||||
options = {
|
||||
{
|
||||
icon = 'fa-solid fa-coins',
|
||||
label = Lang('PHONE_TARGET_STOCK_ENTER_USB'),
|
||||
canInteract = function()
|
||||
HasItem = TriggerServerCallbackSync('qb-crypto:server:HasSticky')
|
||||
return HasItem
|
||||
end,
|
||||
action = function()
|
||||
TriggerEvent('mhacking:show')
|
||||
TriggerEvent('mhacking:start', math.random(4, 6), 45, HackingSuccess)
|
||||
end,
|
||||
},
|
||||
},
|
||||
distance = 2.5
|
||||
})
|
||||
|
||||
exports[TargetName]:AddTargetModel('a_m_m_afriamer_01', {
|
||||
options = {
|
||||
{
|
||||
icon = 'fa-solid fa-gun',
|
||||
label = Lang('PHONE_TARGET_DARKWEB_TAKE_ORDER'),
|
||||
canInteract = function()
|
||||
return waitingDarkWebData
|
||||
end,
|
||||
action = function()
|
||||
TriggerServerCallbackSync('phone:darkweb:buyItem', waitingDarkWebData.item, waitingDarkWebData.amount)
|
||||
SendTempNotificationOld({
|
||||
app = 'darkweb',
|
||||
title = Lang('PHONE_NOTIFICATION_DARKWEB_TITLE'),
|
||||
text = Lang('PHONE_NOTIFICATION_DARKWEB_SUCCESS'),
|
||||
timeout = 2500,
|
||||
})
|
||||
darkWebSuccess = true
|
||||
waitingDarkWebData = nil
|
||||
end,
|
||||
},
|
||||
},
|
||||
distance = 5.0
|
||||
})
|
||||
|
||||
for k, v in pairs(Config.RentelLocations) do
|
||||
exports[TargetName]:AddBoxZone('rentel', vec3(v['coords'][1], v['coords'][2], v['coords'][3] - 1), 2.5, 2.5, {
|
||||
name = 'rentel',
|
||||
heading = 90.0,
|
||||
debugPoly = Config.ZoneDebug,
|
||||
minZ = v['coords'][3] - 1,
|
||||
maxZ = v['coords'][3] + 1,
|
||||
}, {
|
||||
options = {
|
||||
{
|
||||
icon = 'fa-solid fa-bicycle',
|
||||
label = Lang('PHONE_DRAWTEXT_RENTEL_TARGET_RENTAL'),
|
||||
action = function()
|
||||
if not IsPedInAnyVehicle(PlayerPedId(), false) then
|
||||
openRentalMenu(k)
|
||||
else
|
||||
local veh = GetVehiclePedIsIn(PlayerPedId(), false)
|
||||
local model = GetDisplayNameFromVehicleModel(GetEntityModel(veh))
|
||||
model = string.lower(model)
|
||||
if Config.RentelVehicles[model] then
|
||||
local keysQs = GetResourceState('qs-vehiclekeys') == 'started'
|
||||
if keysQs then
|
||||
local plate = GetVehicleNumberPlateText(veh)
|
||||
exports['qs-vehiclekeys']:RemoveKeys(plate, model)
|
||||
end
|
||||
TaskLeaveVehicle(PlayerPedId(), veh, 256)
|
||||
DeleteVehicle(veh)
|
||||
SendTempNotificationOld({
|
||||
app = 'rentel',
|
||||
title = Lang('PHONE_NOTIFICATION_RENTEL_TITLE'),
|
||||
text = Lang('PHONE_NOTIFICATION_RENTEL_RETURN_VEHICLE_POST'),
|
||||
timeout = 2500,
|
||||
disableBadge = true,
|
||||
})
|
||||
else
|
||||
SendTextMessage(Lang('PHONE_NOTIFICATION_RENTEL_VEHICLE_INVALID'), 'error')
|
||||
end
|
||||
end
|
||||
end,
|
||||
},
|
||||
},
|
||||
distance = 2.5
|
||||
})
|
||||
end
|
||||
|
||||
InitChargeTarget()
|
||||
|
||||
exports[TargetName]:AddTargetModel(Config.ResetPassword.ped.model, {
|
||||
options = {
|
||||
{
|
||||
type = 'client',
|
||||
event = 'phone:client:openChannelMenu',
|
||||
icon = 'fas fa-comment-dots',
|
||||
label = Lang('PHONE_TARGET_PHONE_RESET_PASSWORD'),
|
||||
action = function()
|
||||
resetPasswordMenu()
|
||||
end,
|
||||
},
|
||||
},
|
||||
distance = 5.0
|
||||
})
|
||||
|
||||
InitBoothTarget()
|
||||
|
||||
if Config.EnableRecipe then
|
||||
for _, recipeShop in ipairs(Config.BuyRecipe.coords) do
|
||||
exports[TargetName]:AddBoxZone('booth_zone', vec3(recipeShop.x, recipeShop.y, recipeShop.z - 1), 1.5, 1.5, {
|
||||
name = 'booth_zone',
|
||||
heading = recipeShop.w or 0.0,
|
||||
debugPoly = Config.ZoneDebug,
|
||||
minZ = recipeShop.z - 1,
|
||||
maxZ = recipeShop.z + 1,
|
||||
}, {
|
||||
options = {
|
||||
{
|
||||
icon = 'fa-solid fa-phone',
|
||||
label = Lang('PHONE_TARGET_RECIPES_BUY'),
|
||||
action = function()
|
||||
if MetaData then
|
||||
openRecipeMenu()
|
||||
else
|
||||
SendTextMessage(Lang('PHONE_NOTIFICATION_RECIPES_USE_PHONE_FIRST'), 'inform')
|
||||
end
|
||||
end,
|
||||
},
|
||||
},
|
||||
distance = 2.5
|
||||
})
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
function InitChargeTarget()
|
||||
exports[TargetName]:RemoveZone('charger_spots')
|
||||
for k, v in pairs(Config.ChargeCoords) do
|
||||
local coords = v.coords
|
||||
exports[TargetName]:AddBoxZone('charger_spots', vec3(coords.x, coords.y, coords.z - 1), 2.5, 2.5, {
|
||||
name = 'charger_spots',
|
||||
heading = 90.0,
|
||||
debugPoly = Config.ZoneDebug,
|
||||
minZ = v['coords'][3] - 1,
|
||||
maxZ = v['coords'][3] + 1,
|
||||
}, {
|
||||
options = {
|
||||
{
|
||||
icon = 'fa-solid fa-battery-full',
|
||||
label = Lang('PHONE_TARGET_BATTERY_CHARGE_PHONE'),
|
||||
action = function()
|
||||
if Config.ChargeCoords[k].isAvailable then
|
||||
TriggerEvent('phone:openPhoneMenu', 'phone:ChargePhone', k)
|
||||
else
|
||||
if Config.ChargeCoords[k].takeable ~= GetIdentifier() then
|
||||
SendTextMessage(Lang('PHONE_NOTIFICATION_BATTERY_NOT_OWNER'), 'error')
|
||||
else
|
||||
TriggerServerEvent('phone:TakeBackPhoneFromCharging', k)
|
||||
end
|
||||
end
|
||||
end,
|
||||
},
|
||||
},
|
||||
distance = 2.5
|
||||
})
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,7 @@
|
||||
if Config.Vehiclekeys ~= 'mk_vehiclekeys' then
|
||||
return
|
||||
end
|
||||
|
||||
function AddVehiclekeys(vehicle)
|
||||
exports['mk_vehiclekeys']:AddKey(vehicle)
|
||||
end
|
||||
@@ -0,0 +1,8 @@
|
||||
if Config.Vehiclekeys ~= 'mono_carkeys' then
|
||||
return
|
||||
end
|
||||
|
||||
function AddVehiclekeys(vehicle)
|
||||
local plate = GetVehicleNumberPlateText(vehicle)
|
||||
TriggerServerEvent('mono_carkeys:CreateKey', plate)
|
||||
end
|
||||
@@ -0,0 +1,7 @@
|
||||
if Config.Vehiclekeys ~= 'none' then
|
||||
return
|
||||
end
|
||||
|
||||
function AddVehiclekeys(vehicle)
|
||||
return Debug('Vehiclekeys', 'AddVehiclekeys', 'Vehiclekeys is set to none')
|
||||
end
|
||||
@@ -0,0 +1,8 @@
|
||||
if Config.Vehiclekeys ~= 'okokGarage' then
|
||||
return
|
||||
end
|
||||
|
||||
function AddVehiclekeys(vehicle)
|
||||
local plate = GetVehicleNumberPlateText(vehicle)
|
||||
TriggerServerEvent('okokGarage:GiveKeys', plate)
|
||||
end
|
||||
@@ -0,0 +1,7 @@
|
||||
if Config.Vehiclekeys ~= 'qb-vehiclekeys' then
|
||||
return
|
||||
end
|
||||
|
||||
function AddVehiclekeys(vehicle)
|
||||
TriggerEvent('vehiclekeys:client:SetOwner', ESX.Functions.GetPlate(vehicle))
|
||||
end
|
||||
@@ -0,0 +1,9 @@
|
||||
if Config.Vehiclekeys ~= 'qs-vehiclekeys' then
|
||||
return
|
||||
end
|
||||
|
||||
function AddVehiclekeys(vehicle)
|
||||
local plate = GetVehicleNumberPlateText(vehicle)
|
||||
local model = GetDisplayNameFromVehicleModel(GetEntityModel(vehicle))
|
||||
exports['qs-vehiclekeys']:GiveKeys(plate, model)
|
||||
end
|
||||
@@ -0,0 +1,8 @@
|
||||
if Config.Vehiclekeys ~= 'vehicles_keys' then
|
||||
return
|
||||
end
|
||||
|
||||
function AddVehiclekeys(vehicle)
|
||||
local plate = GetVehicleNumberPlateText(vehicle)
|
||||
TriggerServerEvent('vehicles_keys:selfGiveVehicleKeys', plate)
|
||||
end
|
||||
@@ -0,0 +1,8 @@
|
||||
if Config.Vehiclekeys ~= 'wasabi_carlock' then
|
||||
return
|
||||
end
|
||||
|
||||
function AddVehiclekeys(vehicle)
|
||||
local plate = GetVehicleNumberPlateText(vehicle)
|
||||
exports.wasabi_carlock:GiveKey(plate)
|
||||
end
|
||||
@@ -0,0 +1,28 @@
|
||||
local pma = exports['pma-voice']
|
||||
local mumble = exports['mumble-voip']
|
||||
local toko = exports['tokovoip_script']
|
||||
|
||||
function AddToCall(callId)
|
||||
if Config.Voice == 'pma' then
|
||||
Debug('callId', callId)
|
||||
pma:addPlayerToCall(callId)
|
||||
elseif Config.Voice == 'mumble' then
|
||||
mumble:addPlayerToCall(callId)
|
||||
elseif Config.Voice == 'salty' then
|
||||
TriggerServerEvent('phone:addToCall', callId)
|
||||
elseif Config.Voice == 'toko' then
|
||||
toko:addPlayerToRadio(callId)
|
||||
end
|
||||
end
|
||||
|
||||
function RemoveFromCall(callId)
|
||||
if Config.Voice == 'pma' then
|
||||
pma:removePlayerFromCall()
|
||||
elseif Config.Voice == 'mumble' then
|
||||
mumble:removePlayerFromCall()
|
||||
elseif Config.Voice == 'salty' then
|
||||
TriggerServerEvent('phone:removeFromCall', callId)
|
||||
elseif Config.Voice == 'toko' then
|
||||
toko:removePlayerFromRadio(callId)
|
||||
end
|
||||
end
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user