structura foldere
mutat kq- folders in un singur folder [kq]
This commit is contained in:
@@ -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
|
||||
Reference in New Issue
Block a user