Scripts/resources/[qb]/[qb_extras]/qb-cityhall/client/main.lua

344 lines
12 KiB
Lua
Raw Normal View History

2024-12-29 20:07:50 +00:00
local QBCore = exports['qb-core']:GetCoreObject()
local PlayerData = QBCore.Functions.GetPlayerData()
local isLoggedIn = LocalPlayer.state.isLoggedIn
local playerPed = PlayerPedId()
local playerCoords = GetEntityCoords(playerPed)
local closestCityhall = nil
local closestDrivingSchool = nil
local inCityhallPage = false
local inRangeCityhall = false
local inRangeDrivingSchool = false
local pedsSpawned = false
local blips = {}
-- Functions
local function getClosestHall()
local distance = #(playerCoords - Config.Cityhalls[1].coords)
local closest = 1
for i = 1, #Config.Cityhalls do
local hall = Config.Cityhalls[i]
local dist = #(playerCoords - hall.coords)
if dist < distance then
distance = dist
closest = i
end
end
return closest
end
local function getClosestSchool()
local distance = #(playerCoords - Config.DrivingSchools[1].coords)
local closest = 1
for i = 1, #Config.DrivingSchools do
local school = Config.DrivingSchools[i]
local dist = #(playerCoords - school.coords)
if dist < distance then
distance = dist
closest = i
end
end
return closest
end
local function getJobs()
QBCore.Functions.TriggerCallback('qb-cityhall:server:receiveJobs', function(result)
SendNUIMessage({
action = 'setJobs',
jobs = result
})
end)
end
local function setCityhallPageState(bool, message)
getJobs()
if message then
local action = bool and "open" or "close"
SendNUIMessage({
action = action
})
end
SetNuiFocus(bool, bool)
inCityhallPage = bool
if not Config.UseTarget or bool then return end
inRangeCityhall = false
end
local function createBlip(options)
if not options.coords or type(options.coords) ~= 'table' and type(options.coords) ~= 'vector3' then return error(('createBlip() expected coords in a vector3 or table but received %s'):format(options.coords)) end
local blip = AddBlipForCoord(options.coords.x, options.coords.y, options.coords.z)
SetBlipSprite(blip, options.sprite or 1)
SetBlipDisplay(blip, options.display or 4)
SetBlipScale(blip, options.scale or 1.0)
SetBlipColour(blip, options.colour or 1)
SetBlipAsShortRange(blip, options.shortRange or false)
BeginTextCommandSetBlipName("STRING")
AddTextComponentSubstringPlayerName(options.title or 'No Title Given')
EndTextCommandSetBlipName(blip)
return blip
end
local function deleteBlips()
if not next(blips) then return end
for i = 1, #blips do
local blip = blips[i]
if DoesBlipExist(blip) then
RemoveBlip(blip)
end
end
blips = {}
end
local function initBlips()
for i = 1, #Config.Cityhalls do
local hall = Config.Cityhalls[i]
if hall.showBlip then
blips[#blips + 1] = createBlip({
coords = hall.coords,
sprite = hall.blipData.sprite,
display = hall.blipData.display,
scale = hall.blipData.scale,
colour = hall.blipData.colour,
shortRange = true,
title = hall.blipData.title
})
end
end
for i = 1, #Config.DrivingSchools do
local school = Config.DrivingSchools[i]
if school.showBlip then
blips[#blips + 1] = createBlip({
coords = school.coords,
sprite = school.blipData.sprite,
display = school.blipData.display,
scale = school.blipData.scale,
colour = school.blipData.colour,
shortRange = true,
title = school.blipData.title
})
end
end
end
local function spawnPeds()
if not Config.Peds or not next(Config.Peds) or pedsSpawned then return end
for i = 1, #Config.Peds do
local current = Config.Peds[i]
current.model = type(current.model) == 'string' and joaat(current.model) or current.model
RequestModel(current.model)
while not HasModelLoaded(current.model) do
Wait(0)
end
local ped = CreatePed(0, current.model, current.coords.x, current.coords.y, current.coords.z, current.coords.w, false, false)
FreezeEntityPosition(ped, true)
SetEntityInvincible(ped, true)
SetBlockingOfNonTemporaryEvents(ped, true)
TaskStartScenarioInPlace(ped, current.scenario, true, true)
current.pedHandle = ped
if Config.UseTarget then
local opts = nil
if current.drivingschool then
opts = {
label = 'Tag køretimer',
icon = 'fa-solid fa-car-side',
action = function()
TriggerServerEvent('qb-cityhall:server:sendDriverTest', Config.DrivingSchools[closestDrivingSchool].instructors)
end
}
elseif current.cityhall then
opts = {
label = 'Åben borgerservice',
icon = 'fa-solid fa-city',
action = function()
inRangeCityhall = true
setCityhallPageState(true, true)
end
}
end
if opts then
exports['qb-target']:AddTargetEntity(ped, {
options = { opts },
distance = 2.0
})
end
else
local options = current.zoneOptions
if options then
local zone = BoxZone:Create(current.coords.xyz, options.length, options.width, {
name = "zone_cityhall_" .. ped,
heading = current.coords.w,
debugPoly = false,
minZ = current.coords.z - 3.0,
maxZ = current.coords.z + 2.0
})
zone:onPlayerInOut(function(inside)
if isLoggedIn and closestCityhall and closestDrivingSchool then
if inside then
if current.drivingschool then
inRangeDrivingSchool = true
exports['qb-core']:DrawText('[E] Tag køretimer', 'top')
elseif current.cityhall then
inRangeCityhall = true
exports['qb-core']:DrawText('[E] Åben borgerservice', 'top')
end
else
exports['qb-core']:HideText()
if current.drivingschool then
inRangeDrivingSchool = false
elseif current.cityhall then
inRangeCityhall = false
end
end
end
end)
end
end
end
pedsSpawned = true
end
local function deletePeds()
if not Config.Peds or not next(Config.Peds) or not pedsSpawned then return end
for i = 1, #Config.Peds do
local current = Config.Peds[i]
if current.pedHandle then
DeletePed(current.pedHandle)
end
end
pedsSpawned = false
end
-- Events
RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function()
PlayerData = QBCore.Functions.GetPlayerData()
isLoggedIn = true
spawnPeds()
end)
RegisterNetEvent('QBCore:Client:OnPlayerUnload', function()
PlayerData = {}
isLoggedIn = false
deletePeds()
end)
RegisterNetEvent('QBCore:Player:SetPlayerData', function(val)
PlayerData = val
end)
RegisterNetEvent('qb-cityhall:Client:AddCityJob', function()
getJobs()
end)
RegisterNetEvent('qb-cityhall:client:getIds', function()
TriggerServerEvent('qb-cityhall:server:getIDs')
end)
RegisterNetEvent('qb-cityhall:client:sendDriverEmail', function(charinfo)
SetTimeout(math.random(2500, 4000), function()
local gender = Lang:t('email.mr')
if PlayerData.charinfo.gender == 1 then
gender = Lang:t('email.mrs')
end
TriggerServerEvent('qb-phone:server:sendNewMail', {
sender = Lang:t('email.sender'),
subject = Lang:t('email.subject'),
message = Lang:t('email.message', { gender = gender, lastname = charinfo.lastname, firstname = charinfo.firstname, phone = charinfo.phone }),
button = {}
})
end)
end)
AddEventHandler('onResourceStop', function(resource)
if resource ~= GetCurrentResourceName() then return end
deleteBlips()
deletePeds()
end)
-- NUI Callbacks
RegisterNUICallback('close', function(_, cb)
setCityhallPageState(false, false)
if not Config.UseTarget and inRangeCityhall then exports['qb-core']:DrawText('[E] Åben borgerservice', 'top') end
cb('ok')
end)
RegisterNUICallback('requestId', function(id, cb)
local license = Config.Cityhalls[closestCityhall].licenses[id.type]
if inRangeCityhall and license and id.cost == license.cost then
TriggerServerEvent('qb-cityhall:server:requestId', id.type, closestCityhall)
QBCore.Functions.Notify(('Du har modtaget %s for $%s'):format(license.label, id.cost), 'success', 3500)
else
QBCore.Functions.Notify(Lang:t('error.not_in_range'), 'error')
end
cb('ok')
end)
RegisterNUICallback('requestLicenses', function(_, cb)
local licensesMeta = PlayerData.metadata["licences"]
local availableLicenses = Config.Cityhalls[closestCityhall].licenses
for license, data in pairs(availableLicenses) do
if data.metadata and not licensesMeta[data.metadata] then
availableLicenses[license] = nil
end
end
cb(availableLicenses)
end)
RegisterNUICallback('applyJob', function(job, cb)
if inRangeCityhall then
TriggerServerEvent('qb-cityhall:server:ApplyJob', job, Config.Cityhalls[closestCityhall].coords)
else
QBCore.Functions.Notify(Lang:t('error.not_in_range'), 'error')
end
cb('ok')
end)
-- Threads
CreateThread(function()
while true do
if isLoggedIn then
playerPed = PlayerPedId()
playerCoords = GetEntityCoords(playerPed)
closestCityhall = getClosestHall()
closestDrivingSchool = getClosestSchool()
end
Wait(1000)
end
end)
CreateThread(function()
initBlips()
spawnPeds()
if not Config.UseTarget then
while true do
local sleep = 1000
if isLoggedIn and closestCityhall and closestDrivingSchool then
if inRangeCityhall then
if not inCityhallPage then
sleep = 0
if IsControlJustPressed(0, 38) then
setCityhallPageState(true, true)
exports['qb-core']:KeyPressed()
Wait(500)
exports['qb-core']:HideText()
sleep = 1000
end
end
elseif inRangeDrivingSchool then
sleep = 0
if IsControlJustPressed(0, 38) then
TriggerServerEvent('qb-cityhall:server:sendDriverTest', Config.DrivingSchools[closestDrivingSchool].instructors)
sleep = 5000
exports['qb-core']:KeyPressed()
Wait(500)
exports['qb-core']:HideText()
end
end
end
Wait(sleep)
end
end
end)