401 lines
13 KiB
Lua
401 lines
13 KiB
Lua
local config = require 'config.client'
|
|
local sharedConfig = require 'config.shared'
|
|
local route = 1
|
|
local max = #sharedConfig.npcLocations.locations
|
|
local busBlip = nil
|
|
local vehicleZone
|
|
local deliverZone
|
|
local pickupZone
|
|
|
|
local NpcData = {
|
|
Active = false,
|
|
LastNpc = nil,
|
|
LastDeliver = nil,
|
|
Npc = nil,
|
|
NpcBlip = nil,
|
|
DeliveryBlip = nil,
|
|
NpcTaken = false,
|
|
NpcDelivered = false,
|
|
CountDown = 180
|
|
}
|
|
|
|
local BusData = {
|
|
Active = false,
|
|
}
|
|
|
|
-- Functions
|
|
local function resetNpcTask()
|
|
NpcData = {
|
|
Active = false,
|
|
LastNpc = nil,
|
|
LastDeliver = nil,
|
|
Npc = nil,
|
|
NpcBlip = nil,
|
|
DeliveryBlip = nil,
|
|
NpcTaken = false,
|
|
NpcDelivered = false,
|
|
}
|
|
end
|
|
|
|
local function removeBusBlip()
|
|
if not busBlip then return end
|
|
RemoveBlip(busBlip)
|
|
busBlip = nil
|
|
end
|
|
|
|
local function removeNPCBlip()
|
|
if NpcData.DeliveryBlip then
|
|
RemoveBlip(NpcData.DeliveryBlip)
|
|
NpcData.DeliveryBlip = nil
|
|
end
|
|
|
|
if NpcData.NpcBlip then
|
|
RemoveBlip(NpcData.NpcBlip)
|
|
NpcData.NpcBlip = nil
|
|
end
|
|
end
|
|
|
|
local function updateBlip()
|
|
if table.type(QBX.PlayerData) == 'empty' or (QBX.PlayerData.job.name ~= "bus" and busBlip) then
|
|
removeBusBlip()
|
|
return
|
|
elseif (QBX.PlayerData.job.name == "bus" and not busBlip) then
|
|
local coords = sharedConfig.location
|
|
busBlip = AddBlipForCoord(coords.x, coords.y, coords.z)
|
|
SetBlipSprite(busBlip, 513)
|
|
SetBlipDisplay(busBlip, 4)
|
|
SetBlipScale(busBlip, 0.6)
|
|
SetBlipAsShortRange(busBlip, true)
|
|
SetBlipColour(busBlip, 49)
|
|
BeginTextCommandSetBlipName("STRING")
|
|
AddTextComponentSubstringPlayerName(locale('info.bus_depot'))
|
|
EndTextCommandSetBlipName(busBlip)
|
|
return
|
|
end
|
|
end
|
|
|
|
local function isPlayerVehicleABus()
|
|
if not cache.vehicle then return false end
|
|
local veh = GetEntityModel(cache.vehicle)
|
|
|
|
for i = 1, #config.allowedVehicles, 1 do
|
|
if veh == config.allowedVehicles[i].model then
|
|
return true
|
|
end
|
|
end
|
|
|
|
if veh == `dynasty` then
|
|
return true
|
|
end
|
|
|
|
return false
|
|
end
|
|
|
|
local function nextStop()
|
|
route = route <= (max - 1) and route + 1 or 1
|
|
end
|
|
|
|
local function removePed(ped)
|
|
SetTimeout(60000, function()
|
|
DeletePed(ped)
|
|
end)
|
|
end
|
|
|
|
local function getDeliveryLocation()
|
|
nextStop()
|
|
removeNPCBlip()
|
|
NpcData.DeliveryBlip = AddBlipForCoord(sharedConfig.npcLocations.locations[route].x, sharedConfig.npcLocations.locations[route].y, sharedConfig.npcLocations.locations[route].z)
|
|
SetBlipColour(NpcData.DeliveryBlip, 3)
|
|
SetBlipRoute(NpcData.DeliveryBlip, true)
|
|
SetBlipRouteColour(NpcData.DeliveryBlip, 3)
|
|
NpcData.LastDeliver = route
|
|
local inRange = false
|
|
local shownTextUI = false
|
|
deliverZone = lib.zones.sphere({
|
|
name = "qbx_busjob_bus_deliver",
|
|
coords = vec3(sharedConfig.npcLocations.locations[route].x, sharedConfig.npcLocations.locations[route].y, sharedConfig.npcLocations.locations[route].z),
|
|
radius = 5,
|
|
debug = config.debugPoly,
|
|
onEnter = function()
|
|
inRange = true
|
|
if not shownTextUI then
|
|
lib.showTextUI(locale('info.busstop_text'))
|
|
shownTextUI = true
|
|
end
|
|
CreateThread(function()
|
|
repeat
|
|
Wait(0)
|
|
if IsControlJustPressed(0, 38) then
|
|
TaskLeaveVehicle(NpcData.Npc, cache.vehicle, 0)
|
|
SetEntityAsMissionEntity(NpcData.Npc, false, true)
|
|
SetEntityAsNoLongerNeeded(NpcData.Npc)
|
|
local targetCoords = sharedConfig.npcLocations.locations[NpcData.LastNpc]
|
|
TaskGoStraightToCoord(NpcData.Npc, targetCoords.x, targetCoords.y, targetCoords.z, 1.0, -1, 0.0, 0.0)
|
|
lib.notify({
|
|
title = locale('info.bus_job'),
|
|
description = locale('info.dropped_off'),
|
|
type = 'success'
|
|
})
|
|
removeNPCBlip()
|
|
removePed(NpcData.Npc)
|
|
resetNpcTask()
|
|
nextStop()
|
|
TriggerEvent('qbx_busjob:client:DoBusNpc')
|
|
lib.hideTextUI()
|
|
shownTextUI = false
|
|
deliverZone:remove()
|
|
deliverZone = nil
|
|
break
|
|
end
|
|
until not inRange
|
|
end)
|
|
end,
|
|
onExit = function()
|
|
lib.hideTextUI()
|
|
shownTextUI = false
|
|
inRange = false
|
|
end
|
|
})
|
|
end
|
|
|
|
local function busGarage()
|
|
local vehicleMenu = {}
|
|
for _, v in pairs(config.allowedVehicles) do
|
|
vehicleMenu[#vehicleMenu + 1] = {
|
|
title = locale('info.bus'),
|
|
event = "qbx_busjob:client:TakeVehicle",
|
|
args = v
|
|
}
|
|
end
|
|
lib.registerContext({
|
|
id = 'qbx_busjob_open_garage_context_menu',
|
|
title = locale('info.bus_header'),
|
|
options = vehicleMenu
|
|
})
|
|
lib.showContext('qbx_busjob_open_garage_context_menu')
|
|
end
|
|
|
|
local function updateZone()
|
|
if vehicleZone then
|
|
vehicleZone:remove()
|
|
vehicleZone = nil
|
|
end
|
|
|
|
if table.type(QBX.PlayerData) == 'empty' or QBX.PlayerData.job.name ~= 'bus' then return end
|
|
|
|
local inRange = false
|
|
local shownTextUI = false
|
|
vehicleZone = lib.zones.sphere({
|
|
name = "qbx_busjob_bus_main",
|
|
coords = sharedConfig.location.xyz,
|
|
radius = 5,
|
|
debug = config.debugPoly,
|
|
onEnter = function()
|
|
inRange = true
|
|
CreateThread(function()
|
|
repeat
|
|
Wait(0)
|
|
if not isPlayerVehicleABus() then
|
|
if not shownTextUI then
|
|
lib.showTextUI(locale('info.bus_job_vehicles'))
|
|
shownTextUI = true
|
|
end
|
|
if IsControlJustReleased(0, 38) then
|
|
busGarage()
|
|
lib.hideTextUI()
|
|
shownTextUI = false
|
|
break
|
|
end
|
|
else
|
|
if not shownTextUI then
|
|
lib.showTextUI(locale('info.bus_stop_work'))
|
|
shownTextUI = true
|
|
end
|
|
if IsControlJustReleased(0, 38) then
|
|
if not NpcData.Active or NpcData.Active and not NpcData.NpcTaken then
|
|
if cache.vehicle then
|
|
BusData.Active = false
|
|
DeleteVehicle(cache.vehicle)
|
|
removeNPCBlip()
|
|
lib.hideTextUI()
|
|
shownTextUI = false
|
|
resetNpcTask()
|
|
break
|
|
end
|
|
else
|
|
lib.notify({
|
|
title = locale('info.bus_job'),
|
|
description = locale('error.drop_off_passengers'),
|
|
type = 'error'
|
|
})
|
|
end
|
|
end
|
|
end
|
|
until not inRange
|
|
end)
|
|
end,
|
|
onExit = function()
|
|
shownTextUI = false
|
|
inRange = false
|
|
Wait(1000)
|
|
lib.hideTextUI()
|
|
end
|
|
})
|
|
end
|
|
|
|
-- onExit()
|
|
|
|
RegisterNetEvent("qbx_busjob:client:TakeVehicle", function(data)
|
|
if BusData.Active then
|
|
lib.notify({
|
|
title = locale('info.bus_job'),
|
|
description = locale('error.one_bus_active'),
|
|
type = 'error'
|
|
})
|
|
return
|
|
end
|
|
|
|
local netId = lib.callback.await('qbx_busjob:server:spawnBus', false, data.model)
|
|
Wait(300)
|
|
if not netId or netId == 0 or not NetworkDoesEntityExistWithNetworkId(netId) then
|
|
lib.notify({
|
|
title = locale('info.bus_job'),
|
|
description = locale('error.failed_to_spawn'),
|
|
type = 'error'
|
|
})
|
|
return
|
|
end
|
|
|
|
local veh = NetToVeh(netId)
|
|
if veh == 0 then
|
|
lib.notify({
|
|
title = locale('info.bus_job'),
|
|
description = locale('error.failed_to_spawn'),
|
|
type = 'error'
|
|
})
|
|
return
|
|
end
|
|
|
|
SetVehicleFuelLevel(veh, 100.0)
|
|
SetVehicleEngineOn(veh, true, true, false)
|
|
lib.hideContext()
|
|
TriggerEvent('qbx_busjob:client:DoBusNpc')
|
|
end)
|
|
|
|
-- Events
|
|
AddEventHandler('onResourceStart', function(resourceName)
|
|
-- handles script restarts
|
|
if GetCurrentResourceName() ~= resourceName then return end
|
|
|
|
updateBlip()
|
|
updateZone()
|
|
end)
|
|
|
|
RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function()
|
|
updateBlip()
|
|
updateZone()
|
|
end)
|
|
|
|
RegisterNetEvent('QBCore:Client:OnPlayerUnload', function()
|
|
|
|
updateBlip()
|
|
updateZone()
|
|
end)
|
|
|
|
RegisterNetEvent('QBCore:Player:SetPlayerData', function()
|
|
|
|
updateBlip()
|
|
updateZone()
|
|
end)
|
|
|
|
RegisterNetEvent('qbx_busjob:client:DoBusNpc', function()
|
|
if not isPlayerVehicleABus() then
|
|
lib.notify({
|
|
title = locale('info.bus_job'),
|
|
description = locale('error.not_in_bus'),
|
|
type = 'error'
|
|
})
|
|
return
|
|
end
|
|
|
|
if not NpcData.Active then
|
|
local Gender = math.random(1, #config.npcSkins)
|
|
local PedSkin = math.random(1, #config.npcSkins[Gender])
|
|
local model = joaat(config.npcSkins[Gender][PedSkin])
|
|
lib.requestModel(model, 10000)
|
|
NpcData.Npc = CreatePed(3, model, sharedConfig.npcLocations.locations[route].x, sharedConfig.npcLocations.locations[route].y, sharedConfig.npcLocations.locations[route].z - 0.98, sharedConfig.npcLocations.locations[route].w, false, true)
|
|
SetModelAsNoLongerNeeded(model)
|
|
PlaceObjectOnGroundProperly(NpcData.Npc)
|
|
FreezeEntityPosition(NpcData.Npc, true)
|
|
removeNPCBlip()
|
|
NpcData.NpcBlip = AddBlipForCoord(sharedConfig.npcLocations.locations[route].x, sharedConfig.npcLocations.locations[route].y, sharedConfig.npcLocations.locations[route].z)
|
|
SetBlipColour(NpcData.NpcBlip, 3)
|
|
SetBlipRoute(NpcData.NpcBlip, true)
|
|
SetBlipRouteColour(NpcData.NpcBlip, 3)
|
|
NpcData.LastNpc = route
|
|
NpcData.Active = true
|
|
local inRange = false
|
|
local shownTextUI = false
|
|
pickupZone = lib.zones.sphere({
|
|
name = "qbx_busjob_bus_pickup",
|
|
coords = vec3(sharedConfig.npcLocations.locations[route].x, sharedConfig.npcLocations.locations[route].y, sharedConfig.npcLocations.locations[route].z),
|
|
radius = 5,
|
|
debug = config.debugPoly,
|
|
onEnter = function()
|
|
inRange = true
|
|
if not shownTextUI then
|
|
lib.showTextUI(locale('info.busstop_text'))
|
|
shownTextUI = true
|
|
end
|
|
CreateThread(function()
|
|
repeat
|
|
Wait(0)
|
|
if IsControlJustPressed(0, 38) then
|
|
local maxSeats, freeSeat = GetVehicleModelNumberOfSeats(GetEntityModel(cache.vehicle))
|
|
|
|
for i = maxSeats - 1, 0, -1 do
|
|
if IsVehicleSeatFree(cache.vehicle, i) then
|
|
freeSeat = i
|
|
break
|
|
end
|
|
end
|
|
|
|
if not freeSeat then return end
|
|
|
|
ClearPedTasksImmediately(NpcData.Npc)
|
|
FreezeEntityPosition(NpcData.Npc, false)
|
|
TaskEnterVehicle(NpcData.Npc, cache.vehicle, -1, freeSeat, 1.0, 0)
|
|
Wait(3000)
|
|
lib.notify({
|
|
title = locale('info.bus_job'),
|
|
description = locale('info.goto_busstop'),
|
|
type = 'info'
|
|
})
|
|
removeNPCBlip()
|
|
getDeliveryLocation()
|
|
NpcData.NpcTaken = true
|
|
TriggerServerEvent('qbx_busjob:server:NpcPay')
|
|
lib.hideTextUI()
|
|
shownTextUI = false
|
|
pickupZone:remove()
|
|
pickupZone = nil
|
|
break
|
|
end
|
|
until not inRange
|
|
end)
|
|
end,
|
|
onExit = function()
|
|
lib.hideTextUI()
|
|
shownTextUI = false
|
|
inRange = false
|
|
end
|
|
})
|
|
else
|
|
lib.notify({
|
|
title = locale('info.bus_job'),
|
|
description = locale('error.already_driving_bus'),
|
|
type = 'info'
|
|
})
|
|
end
|
|
end)
|