forked from Simnation/Main
2445 lines
No EOL
141 KiB
Lua
2445 lines
No EOL
141 KiB
Lua
local CoreName = nil
|
|
local nuiLoaded = false
|
|
local vehicleEntity = nil
|
|
local vehicleBlip = nil
|
|
local vehicleCamera = nil
|
|
local isCameraActive = false
|
|
local RotSync = true
|
|
local controllerProp = nil
|
|
local firstAwayNotification = false
|
|
local secondAwayNotification = false
|
|
local threeAwayNotification = false
|
|
local NoSignal = false
|
|
local LowBattery = false
|
|
local fakePlayerPed = nil
|
|
local DataShow = false
|
|
local ActivePlayer = {
|
|
type = nil,
|
|
ped = nil,
|
|
name = nil,
|
|
image = nil,
|
|
plate = nil,
|
|
birthDate = nil
|
|
}
|
|
local storeBlips = {}
|
|
local chargingStationBlips = {}
|
|
local storePed = {}
|
|
local chargingStationPed = {}
|
|
local storeProducts = {}
|
|
local activeVehicle = {}
|
|
local activePlugins = {}
|
|
local PlayerData = nil
|
|
local firstOpenCam = true
|
|
local maxFov = 100.0
|
|
local batteryProtector = false
|
|
local signalBooster = 1.0
|
|
local batteryLevel = 100
|
|
local activePlugin = nil
|
|
local usedChargingStation = nil
|
|
local usedChargingStationItem = nil
|
|
local lastCoordsPlayer = nil
|
|
|
|
Citizen.CreateThread(function()
|
|
if GetResourceState('qb-core') == 'started' and Config.Framework == 'qb-core' then
|
|
QBCore = exports['qb-core']:GetCoreObject()
|
|
PlayerData = QBCore.Functions.GetPlayerData()
|
|
CoreName = 'qb-core'
|
|
elseif GetResourceState('qbx_core') == 'started' and Config.Framework == 'qbx_core' then
|
|
QBX = exports['qbx_core']
|
|
PlayerData = QBX:GetPlayerData()
|
|
CoreName = 'qbx_core'
|
|
elseif GetResourceState('es_extended') == 'started' and Config.Framework == 'es_extended' then
|
|
ESX = exports['es_extended']:getSharedObject()
|
|
PlayerData = ESX.GetPlayerData()
|
|
CoreName = 'es_extended'
|
|
end
|
|
end)
|
|
|
|
-- ███████╗██╗ ██╗███╗ ██╗ ██████╗████████╗██╗ ██████╗ ███╗ ██╗███████╗
|
|
-- ██╔════╝██║ ██║████╗ ██║██╔════╝╚══██╔══╝██║██╔═══██╗████╗ ██║██╔════╝
|
|
-- █████╗ ██║ ██║██╔██╗ ██║██║ ██║ ██║██║ ██║██╔██╗ ██║███████╗
|
|
-- ██╔══╝ ██║ ██║██║╚██╗██║██║ ██║ ██║██║ ██║██║╚██╗██║╚════██║
|
|
-- ██║ ╚██████╔╝██║ ╚████║╚██████╗ ██║ ██║╚██████╔╝██║ ╚████║███████║
|
|
-- ╚═╝ ╚═════╝ ╚═╝ ╚═══╝ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝╚══════╝
|
|
|
|
-- ██████╗██╗ ██╗███████╗ ██████╗██╗ ██╗ ███╗ ██╗██╗ ██╗██╗
|
|
-- ██╔════╝██║ ██║██╔════╝██╔════╝██║ ██╔╝ ████╗ ██║██║ ██║██║
|
|
-- ██║ ███████║█████╗ ██║ █████╔╝ ██╔██╗ ██║██║ ██║██║
|
|
-- ██║ ██╔══██║██╔══╝ ██║ ██╔═██╗ ██║╚██╗██║██║ ██║██║
|
|
-- ╚██████╗██║ ██║███████╗╚██████╗██║ ██╗ ██║ ╚████║╚██████╔╝██║
|
|
-- ╚═════╝╚═╝ ╚═╝╚══════╝ ╚═════╝╚═╝ ╚═╝ ╚═╝ ╚═══╝ ╚═════╝ ╚═╝
|
|
|
|
local function CheckNui()
|
|
while not nuiLoaded do
|
|
Citizen.Wait(100)
|
|
end
|
|
end
|
|
|
|
-- ███╗ ██╗██╗ ██╗██╗ ███╗ ███╗███████╗███████╗███████╗ █████╗ ██████╗ ███████╗
|
|
-- ████╗ ██║██║ ██║██║ ████╗ ████║██╔════╝██╔════╝██╔════╝██╔══██╗██╔════╝ ██╔════╝
|
|
-- ██╔██╗ ██║██║ ██║██║ ██╔████╔██║█████╗ ███████╗███████╗███████║██║ ███╗█████╗
|
|
-- ██║╚██╗██║██║ ██║██║ ██║╚██╔╝██║██╔══╝ ╚════██║╚════██║██╔══██║██║ ██║██╔══╝
|
|
-- ██║ ╚████║╚██████╔╝██║ ██║ ╚═╝ ██║███████╗███████║███████║██║ ██║╚██████╔╝███████╗
|
|
-- ╚═╝ ╚═══╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝╚══════╝╚══════╝╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚══════╝
|
|
|
|
local function NuiMessage(action, payload)
|
|
CheckNui()
|
|
SendNUIMessage({
|
|
action = action,
|
|
payload = payload
|
|
})
|
|
end
|
|
|
|
-- ██████╗ ██╗ █████╗ ██╗ ██╗ █████╗ ███╗ ██╗██╗███╗ ███╗ █████╗ ████████╗██╗ ██████╗ ███╗ ██╗
|
|
-- ██╔══██╗██║ ██╔══██╗╚██╗ ██╔╝ ██╔══██╗████╗ ██║██║████╗ ████║██╔══██╗╚══██╔══╝██║██╔═══██╗████╗ ██║
|
|
-- ██████╔╝██║ ███████║ ╚████╔╝ ███████║██╔██╗ ██║██║██╔████╔██║███████║ ██║ ██║██║ ██║██╔██╗ ██║
|
|
-- ██╔═══╝ ██║ ██╔══██║ ╚██╔╝ ██╔══██║██║╚██╗██║██║██║╚██╔╝██║██╔══██║ ██║ ██║██║ ██║██║╚██╗██║
|
|
-- ██║ ███████╗██║ ██║ ██║ ██║ ██║██║ ╚████║██║██║ ╚═╝ ██║██║ ██║ ██║ ██║╚██████╔╝██║ ╚████║
|
|
-- ╚═╝ ╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═══╝╚═╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝
|
|
|
|
local function PlayAnimation(animationName)
|
|
local playerPed = PlayerPedId()
|
|
local playerCoords = GetEntityCoords(playerPed)
|
|
local playerHeading = GetEntityHeading(playerPed)
|
|
local animDict = Config.Animation[animationName].dict
|
|
local animName = Config.Animation[animationName].anim
|
|
|
|
RequestAnimDict(animDict)
|
|
|
|
while not HasAnimDictLoaded(animDict) do
|
|
Citizen.Wait(0)
|
|
end
|
|
|
|
TaskPlayAnim(playerPed, animDict, animName, 33.0, 33.0, -1, 50, 0, false, false, false)
|
|
SetTimeout(700, function()
|
|
ClearPedTasks(playerPed)
|
|
end)
|
|
RemoveAnimDict(animDict)
|
|
end
|
|
|
|
-- ██████╗ ██████╗ █████╗ ██╗ ██╗ ████████╗███████╗██╗ ██╗████████╗ ██████╗ ██████╗
|
|
-- ██╔══██╗██╔══██╗██╔══██╗██║ ██║ ╚══██╔══╝██╔════╝╚██╗██╔╝╚══██╔══╝ ╚════██╗██╔══██╗
|
|
-- ██║ ██║██████╔╝███████║██║ █╗ ██║ ██║ █████╗ ╚███╔╝ ██║ █████╔╝██║ ██║
|
|
-- ██║ ██║██╔══██╗██╔══██║██║███╗██║ ██║ ██╔══╝ ██╔██╗ ██║ ╚═══██╗██║ ██║
|
|
-- ██████╔╝██║ ██║██║ ██║╚███╔███╔╝ ██║ ███████╗██╔╝ ██╗ ██║ ██████╔╝██████╔╝
|
|
-- ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚══╝╚══╝ ╚═╝ ╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═════╝
|
|
|
|
local function DrawText3D(x, y, z, text)
|
|
local onScreen,_x,_y = GetScreenCoordFromWorldCoord(x, y, z)
|
|
local px,py,pz=table.unpack(GetFinalRenderedCamCoord())
|
|
SetTextScale(0.35, 0.35)
|
|
SetTextFont(4)
|
|
SetTextProportional(true)
|
|
SetTextColour(255, 255, 255, 215)
|
|
BeginTextCommandDisplayText("STRING")
|
|
SetTextCentre(true)
|
|
AddTextComponentSubstringPlayerName(text)
|
|
EndTextCommandDisplayText(_x,_y)
|
|
local factor = (string.len(text)) / 370
|
|
DrawRect(_x,_y+0.0125, 0.015+ factor, 0.03, 0, 0, 0, 100)
|
|
end
|
|
|
|
-- ██████╗ ██╗ █████╗ ██╗ ██╗ ██████╗ ██████╗ ███╗ ██╗████████╗██████╗ ██████╗ ██╗ ██╗ ███████╗██████╗ █████╗ ███╗ ██╗██╗███╗ ███╗
|
|
-- ██╔══██╗██║ ██╔══██╗╚██╗ ██╔╝ ██╔════╝██╔═══██╗████╗ ██║╚══██╔══╝██╔══██╗██╔═══██╗██║ ██║ ██╔════╝██╔══██╗ ██╔══██╗████╗ ██║██║████╗ ████║
|
|
-- ██████╔╝██║ ███████║ ╚████╔╝ ██║ ██║ ██║██╔██╗ ██║ ██║ ██████╔╝██║ ██║██║ ██║ █████╗ ██████╔╝ ███████║██╔██╗ ██║██║██╔████╔██║
|
|
-- ██╔═══╝ ██║ ██╔══██║ ╚██╔╝ ██║ ██║ ██║██║╚██╗██║ ██║ ██╔══██╗██║ ██║██║ ██║ ██╔══╝ ██╔══██╗ ██╔══██║██║╚██╗██║██║██║╚██╔╝██║
|
|
-- ██║ ███████╗██║ ██║ ██║ ╚██████╗╚██████╔╝██║ ╚████║ ██║ ██║ ██║╚██████╔╝███████╗███████╗███████╗██║ ██║ ██║ ██║██║ ╚████║██║██║ ╚═╝ ██║
|
|
-- ╚═╝ ╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═══╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚══════╝╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═══╝╚═╝╚═╝ ╚═╝
|
|
|
|
local function PlayControllerAnimation()
|
|
local playerCoords = GetEntityCoords(fakePlayerPed)
|
|
local playerHeading = GetEntityHeading(fakePlayerPed)
|
|
local animDict = Config.Animation['controller'].dict
|
|
local animName = Config.Animation['controller'].anim
|
|
local prop = Config.ControllerObject
|
|
|
|
RequestAnimDict(animDict)
|
|
while not HasAnimDictLoaded(animDict) do
|
|
Citizen.Wait(0)
|
|
end
|
|
|
|
RequestModel(prop)
|
|
while not HasModelLoaded(prop) do
|
|
Citizen.Wait(0)
|
|
end
|
|
|
|
controllerProp = CreateObject(prop, playerCoords, true, true, false)
|
|
AttachEntityToEntity(controllerProp, fakePlayerPed, GetPedBoneIndex(fakePlayerPed, 18905), 0.15, 0.02, 0.09, -136.30, -54.8,
|
|
5.4, true, true, false, true, 1, true)
|
|
SetModelAsNoLongerNeeded(prop)
|
|
|
|
TaskPlayAnim(fakePlayerPed, animDict, animName, 3.0, -8, -1, 63, 0, 0, 0, 0)
|
|
|
|
Citizen.CreateThread(function()
|
|
while vehicleEntity and DoesEntityExist(vehicleEntity) and not NoSignal and not LowBattery and isCameraActive do
|
|
if not IsEntityPlayingAnim(fakePlayerPed, animDict, animName, 3) then
|
|
TaskPlayAnim(fakePlayerPed, animDict, animName, 3.0, -8, -1, 63, 0, 0, 0, 0)
|
|
end
|
|
Citizen.Wait(1000)
|
|
end
|
|
end)
|
|
|
|
Citizen.CreateThread(function()
|
|
while vehicleEntity and DoesEntityExist(vehicleEntity) and not NoSignal and not LowBattery and isCameraActive do
|
|
if RotSync then
|
|
SetCamRot(vehicleCamera, GetEntityRotation(vehicleEntity))
|
|
else
|
|
if IsDisabledControlPressed(0, Config.Controls.ResetCamera) then
|
|
RotSync = true
|
|
end
|
|
end
|
|
Citizen.Wait(5)
|
|
end
|
|
end)
|
|
end
|
|
|
|
-- ██████╗██╗ ██╗ █████╗ ███╗ ██╗ ██████╗ ███████╗ ██████╗ █████╗ ███╗ ███╗ ██████╗ ██████╗ ████████╗ █████╗ ████████╗██╗ ██████╗ ███╗ ██╗
|
|
-- ██╔════╝██║ ██║██╔══██╗████╗ ██║██╔════╝ ██╔════╝ ██╔════╝██╔══██╗████╗ ████║ ██╔══██╗██╔═══██╗╚══██╔══╝██╔══██╗╚══██╔══╝██║██╔═══██╗████╗ ██║
|
|
-- ██║ ███████║███████║██╔██╗ ██║██║ ███╗█████╗ ██║ ███████║██╔████╔██║ ██████╔╝██║ ██║ ██║ ███████║ ██║ ██║██║ ██║██╔██╗ ██║
|
|
-- ██║ ██╔══██║██╔══██║██║╚██╗██║██║ ██║██╔══╝ ██║ ██╔══██║██║╚██╔╝██║ ██╔══██╗██║ ██║ ██║ ██╔══██║ ██║ ██║██║ ██║██║╚██╗██║
|
|
-- ╚██████╗██║ ██║██║ ██║██║ ╚████║╚██████╔╝███████╗ ╚██████╗██║ ██║██║ ╚═╝ ██║ ██║ ██║╚██████╔╝ ██║ ██║ ██║ ██║ ██║╚██████╔╝██║ ╚████║
|
|
-- ╚═════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚══════╝ ╚═════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝
|
|
|
|
local function ChangeCamRotation()
|
|
Citizen.CreateThread(function()
|
|
while vehicleEntity and DoesEntityExist(vehicleEntity) and not NoSignal and not LowBattery and isCameraActive do
|
|
Citizen.Wait(25)
|
|
if IsDisabledControlPressed(0, Config.Controls.CameraRotations.up) then
|
|
RotSync = false
|
|
SetCamRot(vehicleCamera, GetCamRot(vehicleCamera) + vector3(1.0, 0.0, 0.0))
|
|
end
|
|
if IsDisabledControlPressed(0, Config.Controls.CameraRotations.down) then
|
|
RotSync = false
|
|
SetCamRot(vehicleCamera, GetCamRot(vehicleCamera) - vector3(1.0, 0.0, 0.0))
|
|
end
|
|
if IsDisabledControlPressed(0, Config.Controls.CameraRotations.left) then
|
|
RotSync = false
|
|
SetCamRot(vehicleCamera, GetCamRot(vehicleCamera) + vector3(0.0, 0.0, 1.0))
|
|
end
|
|
if IsDisabledControlPressed(0, Config.Controls.CameraRotations.right) then
|
|
RotSync = false
|
|
SetCamRot(vehicleCamera, GetCamRot(vehicleCamera) - vector3(0.0, 0.0, 1.0))
|
|
end
|
|
end
|
|
end)
|
|
end
|
|
|
|
-- ██████╗██╗ ██╗███████╗ ██████╗██╗ ██╗ ███████╗██╗ ██████╗ ███╗ ██╗ █████╗ ██╗
|
|
-- ██╔════╝██║ ██║██╔════╝██╔════╝██║ ██╔╝ ██╔════╝██║██╔════╝ ████╗ ██║██╔══██╗██║
|
|
-- ██║ ███████║█████╗ ██║ █████╔╝ ███████╗██║██║ ███╗██╔██╗ ██║███████║██║
|
|
-- ██║ ██╔══██║██╔══╝ ██║ ██╔═██╗ ╚════██║██║██║ ██║██║╚██╗██║██╔══██║██║
|
|
-- ╚██████╗██║ ██║███████╗╚██████╗██║ ██╗ ███████║██║╚██████╔╝██║ ╚████║██║ ██║███████╗
|
|
-- ╚═════╝╚═╝ ╚═╝╚══════╝ ╚═════╝╚═╝ ╚═╝ ╚══════╝╚═╝ ╚═════╝ ╚═╝ ╚═══╝╚═╝ ╚═╝╚══════╝
|
|
|
|
local function CheckSignal()
|
|
Citizen.CreateThread(function()
|
|
while vehicleEntity and DoesEntityExist(vehicleEntity) and not NoSignal and not LowBattery and isCameraActive do
|
|
if fakePlayerPed then
|
|
local playerPed = PlayerPedId()
|
|
local playerCoords = GetEntityCoords(fakePlayerPed)
|
|
local carCoords = GetEntityCoords(vehicleEntity)
|
|
local distance = #(playerCoords - carCoords)
|
|
local maxDistance = Config.LoseConnectionDistance * signalBooster
|
|
|
|
if distance > maxDistance then
|
|
NuiMessage('Notification', { header = Locales[Config.Locale].WEB['error'], message = Locales[Config.Locale].LUA['vehicle_signal_destroyed'] })
|
|
NuiMessage('NoSignal', { type = 3 })
|
|
NoSignal = true
|
|
|
|
Citizen.SetTimeout(5000, function()
|
|
DoScreenFadeOut(1000)
|
|
Wait(1000)
|
|
RenderScriptCams(false, false, 0, true, true)
|
|
DestroyCam(vehicleCamera, true)
|
|
Config.SetInvBusy(false)
|
|
Config.SetHudDisplay(false)
|
|
NuiMessage('Close')
|
|
SetSeethrough(false)
|
|
SetNightvision(false)
|
|
RenderScriptCams(false, false, 0, true, true)
|
|
isCameraActive = false
|
|
NuiMessage('SetCamera', { active = false })
|
|
ClearPedTasksImmediately(PlayerPedId())
|
|
SetEntityVisible(PlayerPedId(), false, false)
|
|
TaskLeaveVehicle(PlayerPedId(), vehicleEntity, 0)
|
|
local pedCoords = nil
|
|
|
|
if DoesEntityExist(fakePlayerPed) then
|
|
pedCoords = GetEntityCoords(fakePlayerPed)
|
|
else
|
|
pedCoords = lastCoordsPlayer
|
|
end
|
|
|
|
SetEntityCoords(PlayerPedId(), pedCoords)
|
|
DeleteEntity(fakePlayerPed)
|
|
SetEntityVisible(PlayerPedId(), true, false)
|
|
fakePlayerPed = nil
|
|
DoScreenFadeIn(1000)
|
|
end)
|
|
break
|
|
end
|
|
|
|
if distance > maxDistance - 5 then
|
|
if not threeAwayNotification then
|
|
NuiMessage('NoSignal', { type = 2 })
|
|
threeAwayNotification = true
|
|
end
|
|
elseif distance > maxDistance - 15 then
|
|
if not secondAwayNotification then
|
|
NuiMessage('NoSignal', { type = 1 })
|
|
secondAwayNotification = true
|
|
end
|
|
elseif distance > maxDistance - 25 then
|
|
if not firstAwayNotification then
|
|
firstAwayNotification = true
|
|
NuiMessage('Notification', { header = Locales[Config.Locale].WEB['error'], message = Locales[Config.Locale].LUA['vehicle_too_away'] })
|
|
end
|
|
|
|
NuiMessage('NoSignal', { type = 0 })
|
|
else
|
|
firstAwayNotification = false
|
|
secondAwayNotification = false
|
|
threeAwayNotification = false
|
|
NuiMessage('NoSignal', { type = 0 })
|
|
end
|
|
|
|
NuiMessage('UpdateDistance', math.floor(distance))
|
|
end
|
|
|
|
Citizen.Wait(1000)
|
|
end
|
|
end)
|
|
end
|
|
|
|
-- █████╗ ██████╗████████╗██╗██╗ ██╗███████╗ ██████╗ ██╗ █████╗ ██╗ ██╗███████╗██████╗ ███████╗██╗ ██╗██╗███████╗████████╗
|
|
-- ██╔══██╗██╔════╝╚══██╔══╝██║██║ ██║██╔════╝ ██╔══██╗██║ ██╔══██╗╚██╗ ██╔╝██╔════╝██╔══██╗ ██╔════╝╚██╗██╔╝██║██╔════╝╚══██╔══╝
|
|
-- ███████║██║ ██║ ██║██║ ██║█████╗ ██████╔╝██║ ███████║ ╚████╔╝ █████╗ ██████╔╝ █████╗ ╚███╔╝ ██║███████╗ ██║
|
|
-- ██╔══██║██║ ██║ ██║╚██╗ ██╔╝██╔══╝ ██╔═══╝ ██║ ██╔══██║ ╚██╔╝ ██╔══╝ ██╔══██╗ ██╔══╝ ██╔██╗ ██║╚════██║ ██║
|
|
-- ██║ ██║╚██████╗ ██║ ██║ ╚████╔╝ ███████╗ ██║ ███████╗██║ ██║ ██║ ███████╗██║ ██║ ███████╗██╔╝ ██╗██║███████║ ██║
|
|
-- ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═══╝ ╚══════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝ ╚═╝ ╚══════╝╚═╝ ╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝╚══════╝ ╚═╝
|
|
|
|
local function ActivePlayerExist(hit)
|
|
if ActivePlayer.ped == hit then
|
|
return true
|
|
end
|
|
end
|
|
|
|
-- ██╗ ██╗ █████╗ ███╗ ██╗██████╗ ██╗ ███████╗ ███████╗ ██████╗ ██████╗ ███╗ ███╗
|
|
-- ██║ ██║██╔══██╗████╗ ██║██╔══██╗██║ ██╔════╝ ╚══███╔╝██╔═══██╗██╔═══██╗████╗ ████║
|
|
-- ███████║███████║██╔██╗ ██║██║ ██║██║ █████╗ ███╔╝ ██║ ██║██║ ██║██╔████╔██║
|
|
-- ██╔══██║██╔══██║██║╚██╗██║██║ ██║██║ ██╔══╝ ███╔╝ ██║ ██║██║ ██║██║╚██╔╝██║
|
|
-- ██║ ██║██║ ██║██║ ╚████║██████╔╝███████╗███████╗ ███████╗╚██████╔╝╚██████╔╝██║ ╚═╝ ██║
|
|
-- ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═══╝╚═════╝ ╚══════╝╚══════╝ ╚══════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝
|
|
|
|
local function HandleZoom(cam)
|
|
Citizen.CreateThread(function()
|
|
while vehicleEntity and DoesEntityExist(vehicleEntity) and not NoSignal and not LowBattery and isCameraActive do
|
|
if IsControlJustPressed(0, Config.Controls.CameraZoom.zoom) then
|
|
if maxFov > GetCamFov(cam) - 1.0 then
|
|
SetCamFov(cam, GetCamFov(cam) + 1.0)
|
|
end
|
|
end
|
|
|
|
if IsControlJustPressed(0, Config.Controls.CameraZoom.out) then
|
|
SetCamFov(cam, GetCamFov(cam) - 1.0)
|
|
end
|
|
Citizen.Wait(0)
|
|
end
|
|
end)
|
|
end
|
|
|
|
-- ██████╗██████╗ ███████╗ █████╗ ████████╗███████╗ ███████╗██╗ ██╗ ██████╗ ██████╗ ███████╗
|
|
-- ██╔════╝██╔══██╗██╔════╝██╔══██╗╚══██╔══╝██╔════╝ ██╔════╝██║ ██║██╔═══██╗██╔══██╗██╔════╝
|
|
-- ██║ ██████╔╝█████╗ ███████║ ██║ █████╗ ███████╗███████║██║ ██║██████╔╝███████╗
|
|
-- ██║ ██╔══██╗██╔══╝ ██╔══██║ ██║ ██╔══╝ ╚════██║██╔══██║██║ ██║██╔═══╝ ╚════██║
|
|
-- ╚██████╗██║ ██║███████╗██║ ██║ ██║ ███████╗ ███████║██║ ██║╚██████╔╝██║ ███████║
|
|
-- ╚═════╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═╝ ╚══════╝ ╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚══════╝
|
|
|
|
function CreateShops()
|
|
for k, data in pairs(Config.Stores) do
|
|
if data.blip.active then
|
|
storeBlips[k] = AddBlipForCoord(data.coords.x, data.coords.y, data.coords.z)
|
|
SetBlipSprite(storeBlips[k], data.blip.sprite)
|
|
SetBlipColour(storeBlips[k], data.blip.color)
|
|
SetBlipScale(storeBlips[k], data.blip.scale)
|
|
SetBlipAsShortRange(storeBlips[k], true)
|
|
BeginTextCommandSetBlipName("STRING")
|
|
AddTextComponentSubstringPlayerName(data.blip.name)
|
|
EndTextCommandSetBlipName(storeBlips[k])
|
|
end
|
|
|
|
local current = type(data.ped) == 'number' and data.ped or joaat(data.ped)
|
|
|
|
RequestModel(current)
|
|
while not HasModelLoaded(current) do
|
|
Wait(1)
|
|
end
|
|
|
|
storePed[k] = CreatePed(0, current, data.coords.x, data.coords.y, data.coords.z-1, data.coords.w, false, false)
|
|
FreezeEntityPosition(storePed[k], true)
|
|
SetEntityInvincible(storePed[k], true)
|
|
SetBlockingOfNonTemporaryEvents(storePed[k], true)
|
|
|
|
if Config.Interaction == 'qb-target' then
|
|
exports['qb-target']:AddTargetEntity(storePed[k], {
|
|
options = {
|
|
{
|
|
label = Locales[Config.Locale].LUA['open_store'],
|
|
icon = 'fas fa-shop',
|
|
action = function(entity)
|
|
if data.items == 'all' then
|
|
NuiMessage('OpenStore', { cars = Config.RCCars, categorys = Config.Categorys, crafts = Config.RCCrafts })
|
|
SetNuiFocus(true, true)
|
|
else
|
|
if storeProducts[k] then
|
|
NuiMessage('OpenStore', { cars = Config.RCCars, categorys = Config.Categorys, crafts = Config.RCCrafts })
|
|
SetNuiFocus(true, true)
|
|
else
|
|
print('No products found!')
|
|
end
|
|
end
|
|
end,
|
|
canInteract = function(entity, distance)
|
|
local PlayerData = nil
|
|
local Job = nil
|
|
|
|
if CoreName == 'qb-core' then
|
|
PlayerData = QBCore.Functions.GetPlayerData()
|
|
Job = PlayerData.job.name
|
|
elseif CoreName == 'qbx_core' then
|
|
PlayerData = QBX:GetPlayerData()
|
|
Job = PlayerData.job.name
|
|
elseif CoreName == 'es_extended' then
|
|
PlayerData = ESX.GetPlayerData()
|
|
Job = PlayerData.job.name
|
|
end
|
|
|
|
if data.jobs == 'all' then
|
|
return true
|
|
else
|
|
if data.jobs[Job] then
|
|
return true
|
|
else
|
|
return false
|
|
end
|
|
end
|
|
end,
|
|
}
|
|
},
|
|
distance = 2.5,
|
|
})
|
|
elseif Config.Interaction == 'ox_target' then
|
|
exports.ox_target:addLocalEntity(storePed[k], {
|
|
name = k .. '_store',
|
|
label = Locales[Config.Locale].LUA['open_store'],
|
|
icon = 'fas fa-shop',
|
|
onSelect = function()
|
|
if data.items == 'all' then
|
|
NuiMessage('OpenStore', { cars = Config.RCCars, categorys = Config.Categorys, crafts = Config.RCCrafts })
|
|
SetNuiFocus(true, true)
|
|
else
|
|
if storeProducts[k] then
|
|
NuiMessage('OpenStore', { cars = Config.RCCars, categorys = Config.Categorys, crafts = Config.RCCrafts })
|
|
SetNuiFocus(true, true)
|
|
else
|
|
print('No products found!')
|
|
end
|
|
end
|
|
end,
|
|
canInteract = function()
|
|
local PlayerData = nil
|
|
local Job = nil
|
|
|
|
if CoreName == 'qb-core' then
|
|
PlayerData = QBCore.Functions.GetPlayerData()
|
|
Job = PlayerData.job.name
|
|
elseif CoreName == 'qbx_core' then
|
|
PlayerData = QBX:GetPlayerData()
|
|
Job = PlayerData.job.name
|
|
elseif CoreName == 'es_extended' then
|
|
PlayerData = ESX.GetPlayerData()
|
|
Job = PlayerData.job.name
|
|
end
|
|
|
|
if data.jobs == 'all' then
|
|
return true
|
|
else
|
|
if data.jobs[Job] then
|
|
return true
|
|
else
|
|
return false
|
|
end
|
|
end
|
|
end
|
|
})
|
|
elseif Config.Interaction == 'drawtext' then
|
|
Citizen.CreateThread(function()
|
|
while true do
|
|
local playerPed = PlayerPedId()
|
|
local playerCoords = GetEntityCoords(playerPed)
|
|
local distance = #(playerCoords - vector3(data.coords.x, data.coords.y, data.coords.z))
|
|
|
|
if distance < 1.5 and (data.jobs == 'all' or data.jobs[PlayerData.job.name]) then
|
|
sleep = 0
|
|
DrawText3D(data.coords.x, data.coords.y, data.coords.z, '[~g~' .. Config.Controls.InteractionKey.text .. '~w~] - ' .. Locales[Config.Locale].LUA['open_store'])
|
|
if IsControlJustPressed(0, Config.Controls.InteractionKey.key) then
|
|
if data.items == 'all' then
|
|
NuiMessage('OpenStore', { cars = Config.RCCars, categorys = Config.Categorys, crafts = Config.RCCrafts })
|
|
SetNuiFocus(true, true)
|
|
else
|
|
if storeProducts[k] then
|
|
NuiMessage('OpenStore', { cars = Config.RCCars, categorys = Config.Categorys, crafts = Config.RCCrafts })
|
|
SetNuiFocus(true, true)
|
|
else
|
|
print('No products found!')
|
|
end
|
|
end
|
|
end
|
|
end
|
|
Citizen.Wait(0)
|
|
end
|
|
end)
|
|
end
|
|
end
|
|
end
|
|
|
|
function CreateChargingStation()
|
|
for k, data in pairs(Config.Charges) do
|
|
if data.blip.active then
|
|
chargingStationBlips[k] = AddBlipForCoord(data.coords.x, data.coords.y, data.coords.z)
|
|
SetBlipSprite(chargingStationBlips[k], data.blip.sprite)
|
|
SetBlipColour(chargingStationBlips[k], data.blip.color)
|
|
SetBlipScale(chargingStationBlips[k], data.blip.scale)
|
|
SetBlipAsShortRange(chargingStationBlips[k], true)
|
|
BeginTextCommandSetBlipName("STRING")
|
|
AddTextComponentSubstringPlayerName(data.blip.name)
|
|
EndTextCommandSetBlipName(chargingStationBlips[k])
|
|
end
|
|
|
|
local current = type(data.ped) == 'number' and data.ped or joaat(data.ped)
|
|
|
|
RequestModel(current)
|
|
while not HasModelLoaded(current) do
|
|
Wait(1)
|
|
end
|
|
|
|
chargingStationPed[k] = CreatePed(0, current, data.coords.x, data.coords.y, data.coords.z-1, data.coords.w, false, false)
|
|
FreezeEntityPosition(chargingStationPed[k], true)
|
|
SetEntityInvincible(chargingStationPed[k], true)
|
|
SetBlockingOfNonTemporaryEvents(chargingStationPed[k], true)
|
|
|
|
if Config.Interaction == 'qb-target' then
|
|
exports['qb-target']:AddTargetEntity(chargingStationPed[k], {
|
|
options = {
|
|
{
|
|
label = Locales[Config.Locale].LUA['open_charging_station'],
|
|
icon = 'fas fa-bolt',
|
|
action = function(entity)
|
|
lib.registerContext({
|
|
id = 'charging_station_menu',
|
|
title = Locales[Config.Locale].LUA['charging_station'],
|
|
options = {
|
|
{
|
|
title = Locales[Config.Locale].LUA['charge_vehicle_header'],
|
|
description = Locales[Config.Locale].LUA['charge_vehicle_desc'],
|
|
onSelect = function()
|
|
local myVehicle = {}
|
|
local vehicleData = nil
|
|
local isLoading = false
|
|
|
|
lib.callback('0r-rccar:server:getVehicleForCharge', false, function(vehicle)
|
|
vehicleData = vehicle
|
|
isLoading = true
|
|
end)
|
|
|
|
while not isLoading do
|
|
Wait(100)
|
|
end
|
|
|
|
if vehicleData then
|
|
if vehicleData ~= '[]' then
|
|
for k, v in pairs(vehicleData) do
|
|
local batteryLevel = tonumber(v.battery) or 0
|
|
|
|
table.insert(myVehicle, {
|
|
title = v.label,
|
|
description = Locales[Config.Locale].LUA['battery'] ..': ' .. batteryLevel .. '%' .. ' | ' .. Locales[Config.Locale].LUA['price'] .. ': $' .. Config.ChargePrice .. '' .. ' | ' .. Locales[Config.Locale].LUA['serie_number'] .. ': ' .. v.serie .. '',
|
|
onSelect = function()
|
|
|
|
local isLoading = false
|
|
|
|
lib.callback('0r-rccar:server:checkMoney', false, function(result)
|
|
if not result then
|
|
if CoreName == 'qb-core' then
|
|
QBCore.Functions.Notify(Locales[Config.Locale].LUA['not_enough_money'], 'error')
|
|
elseif CoreName == 'qbx_core' then
|
|
QBX:Notify(Locales[Config.Locale].LUA['not_enough_money'], 'error')
|
|
elseif CoreName == 'es_extended' then
|
|
ESX.ShowNotification(Locales[Config.Locale].LUA['not_enough_money'])
|
|
end
|
|
return
|
|
end
|
|
isLoading = true
|
|
end, Config.ChargePrice)
|
|
|
|
while not isLoading do
|
|
Wait(100)
|
|
end
|
|
|
|
local chargeTime = 1000 * Config.ChargingProcess.Charging.Time
|
|
local chargeBatteryLevel = batteryLevel
|
|
usedChargingStation = true
|
|
TriggerServerEvent('0r-rccar:server:chargeVehicle', v.serie, v.name)
|
|
usedChargingStationItem = v
|
|
|
|
Citizen.CreateThread(function()
|
|
while chargeTime > 0 and usedChargingStation and chargeBatteryLevel < 100 do
|
|
|
|
chargeBatteryLevel = chargeBatteryLevel + 1
|
|
|
|
usedChargingStationItem.battery = chargeBatteryLevel
|
|
|
|
if chargeBatteryLevel >= 100 then
|
|
chargeBatteryLevel = 100
|
|
if CoreName == 'qb-core' then
|
|
QBCore.Functions.Notify(Locales[Config.Locale].LUA['vehicle_charge_full'], 'success')
|
|
elseif CoreName == 'qbx_core' then
|
|
QBX:Notify(Locales[Config.Locale].LUA['vehicle_charge_full'], 'success')
|
|
elseif CoreName == 'es_extended' then
|
|
ESX.ShowNotification(Locales[Config.Locale].LUA['vehicle_charge_full'], 'success')
|
|
end
|
|
end
|
|
|
|
Wait(chargeTime)
|
|
end
|
|
end)
|
|
end,
|
|
})
|
|
end
|
|
else
|
|
table.insert(myVehicle, {
|
|
title = Locales[Config.Locale].LUA['no_vehicle_found'],
|
|
})
|
|
end
|
|
|
|
table.insert(myVehicle, {
|
|
title = Locales[Config.Locale].LUA['return_back'],
|
|
menu = 'charging_station_menu',
|
|
})
|
|
|
|
lib.registerContext({
|
|
id = 'charging_station_vehicle',
|
|
title = Locales[Config.Locale].LUA['charge_vehicle_header'],
|
|
options = myVehicle,
|
|
})
|
|
|
|
lib.hideContext(true)
|
|
lib.showContext('charging_station_vehicle')
|
|
end
|
|
end,
|
|
},
|
|
{
|
|
title = Locales[Config.Locale].LUA['check_vehicle_header'],
|
|
description = Locales[Config.Locale].LUA['check_vehicle_desc'],
|
|
onSelect = function()
|
|
if usedChargingStation then
|
|
lib.registerContext({
|
|
id = 'charging_station_vehicle',
|
|
title = Locales[Config.Locale].LUA['check_vehicle_header'],
|
|
options = {
|
|
{
|
|
title = usedChargingStationItem.label,
|
|
description = Locales[Config.Locale].LUA['battery'] ..': ' .. usedChargingStationItem.battery .. '%' .. ' | ' .. Locales[Config.Locale].LUA['serie_number'] .. ': ' .. usedChargingStationItem.serie .. '',
|
|
onSelect = function()
|
|
usedChargingStation = false
|
|
local response = lib.callback.await('0r-rccar:server:undoChargeVehicle', false, usedChargingStationItem.serie, usedChargingStationItem.name, usedChargingStationItem.battery)
|
|
usedChargingStationItem = nil
|
|
end,
|
|
},
|
|
{
|
|
title = Locales[Config.Locale].LUA['return_back'],
|
|
menu = 'charging_station_menu',
|
|
},
|
|
},
|
|
})
|
|
|
|
lib.hideContext(true)
|
|
lib.showContext('charging_station_vehicle')
|
|
else
|
|
if CoreName == 'qb-core' then
|
|
QBCore.Functions.Notify(Locales[Config.Locale].LUA['vehicle_not_charged'], 'error')
|
|
elseif CoreName == 'qbx_core' then
|
|
QBX:Notify(Locales[Config.Locale].LUA['vehicle_not_charged'], 'error')
|
|
elseif CoreName == 'es_extended' then
|
|
ESX.ShowNotification(Locales[Config.Locale].LUA['vehicle_not_charged'])
|
|
end
|
|
end
|
|
end,
|
|
},
|
|
},
|
|
})
|
|
|
|
lib.showContext('charging_station_menu')
|
|
end,
|
|
canInteract = function(entity, distance)
|
|
local PlayerData = nil
|
|
local Job = nil
|
|
|
|
if CoreName == 'qb-core' then
|
|
PlayerData = QBCore.Functions.GetPlayerData()
|
|
Job = PlayerData.job.name
|
|
elseif CoreName == 'qbx_core' then
|
|
PlayerData = QBX:GetPlayerData()
|
|
Job = PlayerData.job.name
|
|
elseif CoreName == 'es_extended' then
|
|
PlayerData = ESX.GetPlayerData()
|
|
Job = PlayerData.job.name
|
|
end
|
|
|
|
if data.jobs == 'all' then
|
|
return true
|
|
else
|
|
if data.jobs[Job] then
|
|
return true
|
|
else
|
|
return false
|
|
end
|
|
end
|
|
end,
|
|
}
|
|
},
|
|
distance = 2.5,
|
|
})
|
|
elseif Config.Interaction == 'ox_target' then
|
|
exports.ox_target:addLocalEntity(chargingStationPed[k], {
|
|
name = k.. '_charging_station',
|
|
label = Locales[Config.Locale].LUA['open_charging_station'],
|
|
icon = 'fas fa-bolt',
|
|
onSelect = function()
|
|
lib.registerContext({
|
|
id = 'charging_station_menu',
|
|
title = Locales[Config.Locale].LUA['charging_station'],
|
|
options = {
|
|
{
|
|
title = Locales[Config.Locale].LUA['charge_vehicle_header'],
|
|
description = Locales[Config.Locale].LUA['charge_vehicle_desc'],
|
|
onSelect = function()
|
|
local myVehicle = {}
|
|
local vehicleData = nil
|
|
local isLoading = false
|
|
|
|
lib.callback('0r-rccar:server:getVehicleForCharge', false, function(vehicle)
|
|
vehicleData = vehicle
|
|
isLoading = true
|
|
end)
|
|
|
|
while not isLoading do
|
|
Wait(100)
|
|
end
|
|
|
|
if vehicleData then
|
|
if vehicleData ~= '[]' then
|
|
for k, v in pairs(vehicleData) do
|
|
local batteryLevel = tonumber(v.battery) or 0
|
|
|
|
table.insert(myVehicle, {
|
|
title = v.label,
|
|
description = Locales[Config.Locale].LUA['battery'] ..': ' .. batteryLevel .. '%' .. ' | ' .. Locales[Config.Locale].LUA['price'] .. ': $' .. Config.ChargePrice .. '' .. ' | ' .. Locales[Config.Locale].LUA['serie_number'] .. ': ' .. v.serie .. '',
|
|
onSelect = function()
|
|
|
|
local isLoading = false
|
|
|
|
lib.callback('0r-rccar:server:checkMoney', false, function(result)
|
|
if not result then
|
|
if CoreName == 'qb-core' then
|
|
QBCore.Functions.Notify(Locales[Config.Locale].LUA['not_enough_money'], 'error')
|
|
elseif CoreName == 'qbx_core' then
|
|
QBX:Notify(Locales[Config.Locale].LUA['not_enough_money'], 'error')
|
|
elseif CoreName == 'es_extended' then
|
|
ESX.ShowNotification(Locales[Config.Locale].LUA['not_enough_money'])
|
|
end
|
|
return
|
|
end
|
|
isLoading = true
|
|
end, Config.ChargePrice)
|
|
|
|
while not isLoading do
|
|
Wait(100)
|
|
end
|
|
|
|
local chargeTime = 1000 * Config.ChargingProcess.Charging.Time
|
|
local chargeBatteryLevel = batteryLevel
|
|
usedChargingStation = true
|
|
TriggerServerEvent('0r-rccar:server:chargeVehicle', v.serie, v.name)
|
|
usedChargingStationItem = v
|
|
|
|
Citizen.CreateThread(function()
|
|
while chargeTime > 0 and usedChargingStation and chargeBatteryLevel < 100 do
|
|
|
|
chargeBatteryLevel = chargeBatteryLevel + 1
|
|
|
|
usedChargingStationItem.battery = chargeBatteryLevel
|
|
|
|
if chargeBatteryLevel >= 100 then
|
|
chargeBatteryLevel = 100
|
|
if CoreName == 'qb-core' then
|
|
QBCore.Functions.Notify(Locales[Config.Locale].LUA['vehicle_charge_full'], 'success')
|
|
elseif CoreName == 'qbx_core' then
|
|
QBX:Notify(Locales[Config.Locale].LUA['vehicle_charge_full'], 'success')
|
|
elseif CoreName == 'es_extended' then
|
|
ESX.ShowNotification(Locales[Config.Locale].LUA['vehicle_charge_full'], 'success')
|
|
end
|
|
end
|
|
|
|
Wait(chargeTime)
|
|
end
|
|
end)
|
|
end,
|
|
})
|
|
end
|
|
else
|
|
table.insert(myVehicle, {
|
|
title = Locales[Config.Locale].LUA['no_vehicle_found'],
|
|
})
|
|
end
|
|
|
|
table.insert(myVehicle, {
|
|
title = Locales[Config.Locale].LUA['return_back'],
|
|
menu = 'charging_station_menu',
|
|
})
|
|
|
|
lib.registerContext({
|
|
id = 'charging_station_vehicle',
|
|
title = Locales[Config.Locale].LUA['charge_vehicle_header'],
|
|
options = myVehicle,
|
|
})
|
|
|
|
lib.hideContext(true)
|
|
lib.showContext('charging_station_vehicle')
|
|
end
|
|
end,
|
|
},
|
|
{
|
|
title = Locales[Config.Locale].LUA['check_vehicle_header'],
|
|
description = Locales[Config.Locale].LUA['check_vehicle_desc'],
|
|
onSelect = function()
|
|
if usedChargingStation then
|
|
lib.registerContext({
|
|
id = 'charging_station_vehicle',
|
|
title = Locales[Config.Locale].LUA['check_vehicle_header'],
|
|
options = {
|
|
{
|
|
title = usedChargingStationItem.label,
|
|
description = Locales[Config.Locale].LUA['battery'] ..': ' .. usedChargingStationItem.battery .. '%' .. ' | ' .. Locales[Config.Locale].LUA['serie_number'] .. ': ' .. usedChargingStationItem.serie .. '',
|
|
onSelect = function()
|
|
usedChargingStation = false
|
|
local response = lib.callback.await('0r-rccar:server:undoChargeVehicle', false, usedChargingStationItem.serie, usedChargingStationItem.name, usedChargingStationItem.battery)
|
|
usedChargingStationItem = nil
|
|
end,
|
|
},
|
|
{
|
|
title = Locales[Config.Locale].LUA['return_back'],
|
|
menu = 'charging_station_menu',
|
|
},
|
|
},
|
|
})
|
|
|
|
lib.hideContext(true)
|
|
lib.showContext('charging_station_vehicle')
|
|
else
|
|
if CoreName == 'qb-core' then
|
|
QBCore.Functions.Notify(Locales[Config.Locale].LUA['vehicle_not_charged'], 'error')
|
|
elseif CoreName == 'qbx_core' then
|
|
QBX:Notify(Locales[Config.Locale].LUA['vehicle_not_charged'], 'error')
|
|
elseif CoreName == 'es_extended' then
|
|
ESX.ShowNotification(Locales[Config.Locale].LUA['vehicle_not_charged'])
|
|
end
|
|
end
|
|
end,
|
|
},
|
|
},
|
|
})
|
|
|
|
lib.showContext('charging_station_menu')
|
|
end,
|
|
canInteract = function()
|
|
local PlayerData = nil
|
|
local Job = nil
|
|
|
|
if CoreName == 'qb-core' then
|
|
PlayerData = QBCore.Functions.GetPlayerData()
|
|
Job = PlayerData.job.name
|
|
elseif CoreName == 'qbx_core' then
|
|
PlayerData = QBX:GetPlayerData()
|
|
Job = PlayerData.job.name
|
|
elseif CoreName == 'es_extended' then
|
|
PlayerData = ESX.GetPlayerData()
|
|
Job = PlayerData.job.name
|
|
end
|
|
|
|
if data.jobs == 'all' then
|
|
return true
|
|
else
|
|
if data.jobs[Job] then
|
|
return true
|
|
else
|
|
return false
|
|
end
|
|
end
|
|
end
|
|
})
|
|
elseif Config.Interaction == 'drawtext' then
|
|
Citizen.CreateThread(function()
|
|
while true do
|
|
local playerPed = PlayerPedId()
|
|
local playerCoords = GetEntityCoords(playerPed)
|
|
local distance = #(playerCoords - vector3(data.coords.x, data.coords.y, data.coords.z))
|
|
local sleep = 1000
|
|
|
|
if distance < 1.5 and (data.jobs == 'all' or data.jobs[PlayerData.job.name]) then
|
|
sleep = 0
|
|
DrawText3D(data.coords.x, data.coords.y, data.coords.z, '[~g~' .. Config.Controls.InteractionKey.text .. '~w~] - ' .. Locales[Config.Locale].LUA['open_charging_station'])
|
|
if IsControlJustPressed(0, Config.Controls.InteractionKey.key) then
|
|
lib.registerContext({
|
|
id = 'charging_station_menu',
|
|
title = Locales[Config.Locale].LUA['charging_station'],
|
|
options = {
|
|
{
|
|
title = Locales[Config.Locale].LUA['charge_vehicle_header'],
|
|
description = Locales[Config.Locale].LUA['charge_vehicle_desc'],
|
|
onSelect = function()
|
|
local myVehicle = {}
|
|
local vehicleData = nil
|
|
local isLoading = false
|
|
|
|
lib.callback('0r-rccar:server:getVehicleForCharge', false, function(vehicle)
|
|
vehicleData = vehicle
|
|
isLoading = true
|
|
end)
|
|
|
|
while not isLoading do
|
|
Wait(100)
|
|
end
|
|
|
|
if vehicleData then
|
|
if vehicleData ~= '[]' then
|
|
for k, v in pairs(vehicleData) do
|
|
local batteryLevel = tonumber(v.battery) or 0
|
|
|
|
table.insert(myVehicle, {
|
|
title = v.label,
|
|
description = Locales[Config.Locale].LUA['battery'] ..': ' .. batteryLevel .. '%' .. ' | ' .. Locales[Config.Locale].LUA['price'] .. ': $' .. Config.ChargePrice .. '' .. ' | ' .. Locales[Config.Locale].LUA['serie_number'] .. ': ' .. v.serie .. '',
|
|
onSelect = function()
|
|
|
|
local isLoading = false
|
|
|
|
lib.callback('0r-rccar:server:checkMoney', false, function(result)
|
|
if not result then
|
|
if CoreName == 'qb-core' then
|
|
QBCore.Functions.Notify(Locales[Config.Locale].LUA['not_enough_money'], 'error')
|
|
elseif CoreName == 'qbx_core' then
|
|
QBX:Notify(Locales[Config.Locale].LUA['not_enough_money'], 'error')
|
|
elseif CoreName == 'es_extended' then
|
|
ESX.ShowNotification(Locales[Config.Locale].LUA['not_enough_money'])
|
|
end
|
|
return
|
|
end
|
|
isLoading = true
|
|
end, Config.ChargePrice)
|
|
|
|
while not isLoading do
|
|
Wait(100)
|
|
end
|
|
|
|
local chargeTime = 1000 * Config.ChargingProcess.Charging.Time
|
|
local chargeBatteryLevel = batteryLevel
|
|
usedChargingStation = true
|
|
TriggerServerEvent('0r-rccar:server:chargeVehicle', v.serie, v.name)
|
|
usedChargingStationItem = v
|
|
|
|
Citizen.CreateThread(function()
|
|
while chargeTime > 0 and usedChargingStation and chargeBatteryLevel < 100 do
|
|
|
|
chargeBatteryLevel = chargeBatteryLevel + 1
|
|
|
|
usedChargingStationItem.battery = chargeBatteryLevel
|
|
|
|
if chargeBatteryLevel >= 100 then
|
|
chargeBatteryLevel = 100
|
|
if CoreName == 'qb-core' then
|
|
QBCore.Functions.Notify(Locales[Config.Locale].LUA['vehicle_charge_full'], 'success')
|
|
elseif CoreName == 'qbx_core' then
|
|
QBX:Notify(Locales[Config.Locale].LUA['vehicle_charge_full'], 'success')
|
|
elseif CoreName == 'es_extended' then
|
|
ESX.ShowNotification(Locales[Config.Locale].LUA['vehicle_charge_full'], 'success')
|
|
end
|
|
end
|
|
|
|
Wait(chargeTime)
|
|
end
|
|
end)
|
|
end,
|
|
})
|
|
end
|
|
else
|
|
table.insert(myVehicle, {
|
|
title = Locales[Config.Locale].LUA['no_vehicle_found'],
|
|
})
|
|
end
|
|
|
|
table.insert(myVehicle, {
|
|
title = Locales[Config.Locale].LUA['return_back'],
|
|
menu = 'charging_station_menu',
|
|
})
|
|
|
|
lib.registerContext({
|
|
id = 'charging_station_vehicle',
|
|
title = Locales[Config.Locale].LUA['charge_vehicle_header'],
|
|
options = myVehicle,
|
|
})
|
|
|
|
lib.hideContext(true)
|
|
lib.showContext('charging_station_vehicle')
|
|
end
|
|
end,
|
|
},
|
|
{
|
|
title = Locales[Config.Locale].LUA['check_vehicle_header'],
|
|
description = Locales[Config.Locale].LUA['check_vehicle_desc'],
|
|
onSelect = function()
|
|
if usedChargingStation then
|
|
lib.registerContext({
|
|
id = 'charging_station_vehicle',
|
|
title = Locales[Config.Locale].LUA['check_vehicle_header'],
|
|
options = {
|
|
{
|
|
title = usedChargingStationItem.label,
|
|
description = Locales[Config.Locale].LUA['battery'] ..': ' .. usedChargingStationItem.battery .. '%' .. ' | ' .. Locales[Config.Locale].LUA['serie_number'] .. ': ' .. usedChargingStationItem.serie .. '',
|
|
onSelect = function()
|
|
usedChargingStation = false
|
|
local response = lib.callback.await('0r-rccar:server:undoChargeVehicle', false, usedChargingStationItem.serie, usedChargingStationItem.name, usedChargingStationItem.battery)
|
|
usedChargingStationItem = nil
|
|
end,
|
|
},
|
|
{
|
|
title = Locales[Config.Locale].LUA['return_back'],
|
|
menu = 'charging_station_menu',
|
|
},
|
|
},
|
|
})
|
|
|
|
lib.hideContext(true)
|
|
lib.showContext('charging_station_vehicle')
|
|
else
|
|
if CoreName == 'qb-core' then
|
|
QBCore.Functions.Notify(Locales[Config.Locale].LUA['vehicle_not_charged'], 'error')
|
|
elseif CoreName == 'qbx_core' then
|
|
QBX:Notify(Locales[Config.Locale].LUA['vehicle_not_charged'], 'error')
|
|
elseif CoreName == 'es_extended' then
|
|
ESX.ShowNotification(Locales[Config.Locale].LUA['vehicle_not_charged'])
|
|
end
|
|
end
|
|
end,
|
|
},
|
|
},
|
|
})
|
|
|
|
lib.showContext('charging_station_menu')
|
|
end
|
|
end
|
|
Citizen.Wait(sleep)
|
|
end
|
|
end)
|
|
end
|
|
end
|
|
end
|
|
|
|
-- ██████╗ ███████╗ ██████╗ ██╗███████╗████████╗███████╗██████╗ ██████╗ ██████╗ ███╗ ██╗████████╗███████╗██╗ ██╗████████╗ ███╗ ███╗███████╗███╗ ██╗██╗ ██╗
|
|
-- ██╔══██╗██╔════╝██╔════╝ ██║██╔════╝╚══██╔══╝██╔════╝██╔══██╗ ██╔════╝██╔═══██╗████╗ ██║╚══██╔══╝██╔════╝╚██╗██╔╝╚══██╔══╝ ████╗ ████║██╔════╝████╗ ██║██║ ██║
|
|
-- ██████╔╝█████╗ ██║ ███╗██║███████╗ ██║ █████╗ ██████╔╝ ██║ ██║ ██║██╔██╗ ██║ ██║ █████╗ ╚███╔╝ ██║ ██╔████╔██║█████╗ ██╔██╗ ██║██║ ██║
|
|
-- ██╔══██╗██╔══╝ ██║ ██║██║╚════██║ ██║ ██╔══╝ ██╔══██╗ ██║ ██║ ██║██║╚██╗██║ ██║ ██╔══╝ ██╔██╗ ██║ ██║╚██╔╝██║██╔══╝ ██║╚██╗██║██║ ██║
|
|
-- ██║ ██║███████╗╚██████╔╝██║███████║ ██║ ███████╗██║ ██║ ╚██████╗╚██████╔╝██║ ╚████║ ██║ ███████╗██╔╝ ██╗ ██║ ██║ ╚═╝ ██║███████╗██║ ╚████║╚██████╔╝
|
|
-- ╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═╝╚══════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═══╝ ╚═╝ ╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═══╝ ╚═════╝
|
|
|
|
local function RegisterContextMenu()
|
|
lib.registerContext({
|
|
id = 'manage_rccar_menu',
|
|
title = Locales[Config.Locale].LUA['manage_rc_car'],
|
|
options = {
|
|
{
|
|
title = Locales[Config.Locale].LUA['open_camera_header'],
|
|
description = Locales[Config.Locale].LUA['open_camera_desc'],
|
|
onSelect = function()
|
|
lib.hideContext(true)
|
|
NoSignal = false
|
|
DoScreenFadeOut(1000)
|
|
Wait(1000)
|
|
SpawnPed()
|
|
SetCam()
|
|
isCameraActive = true
|
|
Config.SetInvBusy(true)
|
|
Config.SetHudDisplay(true)
|
|
PlayControllerAnimation()
|
|
SetPedIntoVehicle(PlayerPedId(), vehicleEntity, -1)
|
|
CheckPlugins()
|
|
ChangeCamRotation()
|
|
CheckSignal()
|
|
HandleZoom(vehicleCamera)
|
|
maxFov = GetCamFov(vehicleCamera)
|
|
HideHUDThisFrame()
|
|
NuiMessage('UpdateBattery', batteryLevel)
|
|
ChargingProcess()
|
|
OpenPluginsMenu()
|
|
|
|
RenderScriptCams(true, false, 0, true, true)
|
|
|
|
Citizen.CreateThread(function()
|
|
local wasDead = false
|
|
|
|
while vehicleEntity and DoesEntityExist(vehicleEntity) and not NoSignal and not LowBattery and isCameraActive and not wasDead do
|
|
Citizen.Wait(1000)
|
|
|
|
if DoesEntityExist(fakePlayerPed) then
|
|
if IsEntityDead(fakePlayerPed) then
|
|
if not wasDead then
|
|
wasDead = true
|
|
DoScreenFadeOut(1000)
|
|
Wait(1000)
|
|
isCameraActive = false
|
|
Config.SetInvBusy(false)
|
|
Config.SetHudDisplay(false)
|
|
SetSeethrough(false)
|
|
SetNightvision(false)
|
|
RenderScriptCams(false, false, 0, true, true)
|
|
NuiMessage('SetCamera', { active = false })
|
|
ClearPedTasksImmediately(PlayerPedId())
|
|
SetEntityVisible(PlayerPedId(), false, false)
|
|
TaskLeaveVehicle(PlayerPedId(), vehicleEntity, 0)
|
|
local pedCoords = nil
|
|
|
|
if DoesEntityExist(fakePlayerPed) then
|
|
pedCoords = GetEntityCoords(fakePlayerPed)
|
|
else
|
|
pedCoords = lastCoordsPlayer
|
|
end
|
|
|
|
SetEntityCoords(PlayerPedId(), pedCoords)
|
|
DeleteEntity(fakePlayerPed)
|
|
DeleteEntity(controllerProp)
|
|
SetEntityVisible(PlayerPedId(), true, false)
|
|
SetEntityHealth(PlayerPedId(), 0)
|
|
fakePlayerPed = nil
|
|
DoScreenFadeIn(1000)
|
|
TriggerServerEvent('0r-rccar:server:saveVehicle', activeVehicle, batteryLevel)
|
|
break
|
|
end
|
|
else
|
|
wasDead = false
|
|
end
|
|
end
|
|
end
|
|
end)
|
|
|
|
Citizen.CreateThread(function()
|
|
while vehicleEntity and DoesEntityExist(vehicleEntity) and not NoSignal and not LowBattery and isCameraActive do
|
|
Citizen.Wait(0)
|
|
|
|
local playerPed = PlayerPedId()
|
|
local vehicle = GetVehiclePedIsIn(playerPed, false)
|
|
|
|
if vehicle ~= 0 then
|
|
if IsPedArmed(playerPed, 6) then
|
|
SetCurrentPedWeapon(playerPed, GetHashKey("WEAPON_UNARMED"), true)
|
|
end
|
|
end
|
|
|
|
Citizen.Wait(500)
|
|
end
|
|
end)
|
|
|
|
Citizen.CreateThread(function()
|
|
while vehicleEntity and DoesEntityExist(vehicleEntity) and not NoSignal and not LowBattery and isCameraActive do
|
|
local ped = PlayerPedId()
|
|
local coords = GetEntityCoords(ped)
|
|
local streetName, crossingRoad = GetStreetNameAtCoord(coords.x, coords.y, coords.z)
|
|
|
|
NuiMessage('UpdateStreet', GetStreetNameFromHashKey(streetName))
|
|
|
|
Wait(1000)
|
|
end
|
|
end)
|
|
|
|
|
|
if firstOpenCam then
|
|
local playerdata = {
|
|
fullName = nil,
|
|
job = nil,
|
|
grade = nil,
|
|
}
|
|
|
|
if CoreName == 'qb-core' then
|
|
local PlayerData = QBCore.Functions.GetPlayerData()
|
|
|
|
playerdata.fullName = PlayerData.charinfo.firstname .. ' ' .. PlayerData.charinfo.lastname
|
|
playerdata.job = PlayerData.job.name
|
|
playerdata.grade = PlayerData.job.grade.name
|
|
elseif CoreName == 'qbx_core' then
|
|
local PlayerData = QBX:GetPlayerData()
|
|
|
|
playerdata.Fullname = PlayerData.charinfo.firstname .. ' ' .. PlayerData.charinfo.lastname
|
|
playerdata.job = PlayerData.job.name
|
|
playerdata.grade = PlayerData.job.grade.name
|
|
elseif CoreName == 'es_extended' then
|
|
local PlayerData = ESX.GetPlayerData()
|
|
|
|
playerdata.Fullname = PlayerData.firstName .. ' ' .. PlayerData.lastName
|
|
playerdata.job = PlayerData.job.name
|
|
playerdata.grade = PlayerData.job.grade_name
|
|
end
|
|
|
|
firstOpenCam = true
|
|
NuiMessage('SetCamera', { active = true, first = true, playerData = playerdata, carName = activeVehicle.item.label })
|
|
else
|
|
NuiMessage('SetCamera', { active = true, first = false })
|
|
end
|
|
|
|
Citizen.CreateThread(function()
|
|
while vehicleEntity and DoesEntityExist(vehicleEntity) and not NoSignal and not LowBattery do
|
|
if IsControlJustPressed(0, Config.Controls.ToggleCamera) then
|
|
if isCameraActive then
|
|
DoScreenFadeOut(1000)
|
|
Wait(1000)
|
|
isCameraActive = false
|
|
Config.SetInvBusy(false)
|
|
Config.SetHudDisplay(false)
|
|
SetSeethrough(false)
|
|
SetNightvision(false)
|
|
RenderScriptCams(false, false, 0, true, true)
|
|
NuiMessage('SetCamera', { active = false })
|
|
ClearPedTasksImmediately(PlayerPedId())
|
|
SetEntityVisible(PlayerPedId(), false, false)
|
|
TaskLeaveVehicle(PlayerPedId(), vehicleEntity, 0)
|
|
local pedCoords = nil
|
|
|
|
if DoesEntityExist(fakePlayerPed) then
|
|
pedCoords = GetEntityCoords(fakePlayerPed)
|
|
else
|
|
pedCoords = lastCoordsPlayer
|
|
end
|
|
|
|
SetEntityCoords(PlayerPedId(), pedCoords)
|
|
DeleteEntity(fakePlayerPed)
|
|
DeleteEntity(controllerProp)
|
|
SetEntityVisible(PlayerPedId(), true, false)
|
|
fakePlayerPed = nil
|
|
DoScreenFadeIn(1000)
|
|
TriggerServerEvent('0r-rccar:server:saveVehicle', activeVehicle, batteryLevel)
|
|
break
|
|
end
|
|
end
|
|
Citizen.Wait(0)
|
|
end
|
|
end)
|
|
|
|
Citizen.CreateThread(function()
|
|
while true do
|
|
Citizen.Wait(0)
|
|
|
|
if not vehicleEntity and not DoesEntityExist(vehicleEntity) and NoSignal and LowBattery and not isCameraActive then
|
|
if DoesEntityExist(fakePlayerPed) then
|
|
DeleteEntity(fakePlayerPed)
|
|
fakePlayerPed = nil
|
|
break
|
|
else
|
|
break
|
|
end
|
|
end
|
|
end
|
|
end)
|
|
|
|
DoScreenFadeIn(1000)
|
|
end
|
|
},
|
|
{
|
|
title = Locales[Config.Locale].LUA['pick_up_vehicle_header'],
|
|
description = Locales[Config.Locale].LUA['pick_up_vehicle_desc'],
|
|
onSelect = function()
|
|
if vehicleEntity and DoesEntityExist(vehicleEntity) then
|
|
local playerPed = PlayerPedId()
|
|
local playerCoords = GetEntityCoords(playerPed)
|
|
local carCoords = GetEntityCoords(vehicleEntity)
|
|
local distance = #(playerCoords - carCoords)
|
|
|
|
if distance < 5 then
|
|
PlayAnimation('pickup_object')
|
|
Citizen.Wait(750)
|
|
DeleteEntity(vehicleEntity)
|
|
RemoveBlip(vehicleBlip)
|
|
NuiMessage('ResetExtensions')
|
|
vehicleEntity = nil
|
|
vehicleBlip = nil
|
|
vehicleCamera = nil
|
|
isCameraActive = false
|
|
RotSync = true
|
|
controllerProp = nil
|
|
firstAwayNotification = false
|
|
secondAwayNotification = false
|
|
threeAwayNotification = false
|
|
NoSignal = false
|
|
LowBattery = false
|
|
fakePlayerPed = nil
|
|
DataShow = false
|
|
ActivePlayer = {
|
|
type = nil,
|
|
ped = nil,
|
|
name = nil,
|
|
image = nil,
|
|
plate = nil,
|
|
birthDate = nil
|
|
}
|
|
storeBlips = {}
|
|
chargingStationBlips = {}
|
|
storePed = {}
|
|
chargingStationPed = {}
|
|
storeProducts = {}
|
|
activeVehicle = {}
|
|
activePlugins = {}
|
|
firstOpenCam = true
|
|
maxFov = 100.0
|
|
batteryProtector = false
|
|
signalBooster = 1.0
|
|
batteryLevel = 100
|
|
activePlugin = nil
|
|
usedChargingStation = nil
|
|
usedChargingStationItem = nil
|
|
end
|
|
end
|
|
end,
|
|
},
|
|
{
|
|
title = Locales[Config.Locale].LUA['manage_vehicle_ext_header'],
|
|
description = Locales[Config.Locale].LUA['manage_vehicle_ext_desc'],
|
|
onSelect = function()
|
|
lib.hideContext(true)
|
|
GetExtensions()
|
|
end,
|
|
},
|
|
}
|
|
})
|
|
|
|
lib.showContext('manage_rccar_menu')
|
|
end
|
|
|
|
local function tableLength(t)
|
|
local count = 0
|
|
for _ in pairs(t) do
|
|
count = count + 1
|
|
end
|
|
return count
|
|
end
|
|
|
|
function GetExtensions()
|
|
|
|
local extensions = {}
|
|
|
|
local temp_extensions = promise.new()
|
|
|
|
lib.callback('0r-rccar:server:getActivePlugins', false, function(data)
|
|
temp_extensions:resolve(data)
|
|
end, activeVehicle)
|
|
local resolved_extensions = Citizen.Await(temp_extensions)
|
|
|
|
local data = json.decode(resolved_extensions)
|
|
|
|
if data and type(data) == "table" and tableLength(data) > 0 then
|
|
for k, v in pairs(data) do
|
|
table.insert(extensions, {
|
|
title = v.label,
|
|
description = v.description,
|
|
onSelect = function()
|
|
lib.hideContext(true)
|
|
RemoveExtension(activeVehicle, v)
|
|
end
|
|
})
|
|
end
|
|
else
|
|
extensions = {
|
|
{
|
|
title = Locales[Config.Locale].LUA['no_extensions_found'],
|
|
}
|
|
}
|
|
end
|
|
|
|
table.insert(extensions, {
|
|
title = Locales[Config.Locale].LUA['add_extension'],
|
|
onSelect = function()
|
|
lib.hideContext(true)
|
|
AddExtension(activeVehicle)
|
|
end
|
|
})
|
|
|
|
table.insert(extensions, {
|
|
title = Locales[Config.Locale].LUA['return_back'],
|
|
menu = 'manage_rccar_menu',
|
|
})
|
|
|
|
lib.registerContext({
|
|
id = 'manage_rccar_extensions',
|
|
title = Locales[Config.Locale].LUA['manage_vehicle_ext_header'],
|
|
options = extensions
|
|
})
|
|
|
|
lib.showContext('manage_rccar_extensions')
|
|
end
|
|
|
|
function RemoveExtension(data, removedExtension)
|
|
lib.registerContext({
|
|
id = 'remove_rccar_extensions',
|
|
title = string.format(Locales[Config.Locale].LUA['remove_extension'], removedExtension.label),
|
|
options = {
|
|
{
|
|
title = Locales[Config.Locale].LUA['yes'],
|
|
onSelect = function()
|
|
local temp_remove = promise.new()
|
|
|
|
lib.callback('0r-rccar:server:removeExtension', false, function(data)
|
|
temp_remove:resolve(data)
|
|
end, data, removedExtension)
|
|
local resolved_remove = Citizen.Await(temp_remove)
|
|
|
|
if resolved_remove then
|
|
GetExtensions()
|
|
end
|
|
end,
|
|
},
|
|
{
|
|
title = Locales[Config.Locale].LUA['no'],
|
|
onSelect = function()
|
|
lib.hideContext(true)
|
|
GetExtensions()
|
|
end,
|
|
},
|
|
}
|
|
})
|
|
|
|
lib.showContext('remove_rccar_extensions')
|
|
end
|
|
|
|
function AddExtension(activeVehicle)
|
|
|
|
local extensions = {}
|
|
|
|
local temp_extensions = promise.new()
|
|
|
|
lib.callback('0r-rccar:server:getNewExtensions', false, function(data)
|
|
temp_extensions:resolve(data)
|
|
end, activeVehicle)
|
|
local resolved_extensions = Citizen.Await(temp_extensions)
|
|
|
|
if resolved_extensions and type(resolved_extensions) == "table" and tableLength(resolved_extensions) > 0 then
|
|
for k, v in pairs(resolved_extensions) do
|
|
table.insert(extensions, {
|
|
title = v.item.label,
|
|
description = v.item.description,
|
|
onSelect = function()
|
|
local temp_add = promise.new()
|
|
|
|
lib.callback('0r-rccar:server:addExtension', false, function(x)
|
|
temp_add:resolve(x)
|
|
end, activeVehicle, v)
|
|
local resolved_add = Citizen.Await(temp_add)
|
|
|
|
if resolved_add then
|
|
GetExtensions()
|
|
end
|
|
end
|
|
})
|
|
end
|
|
else
|
|
extensions = {
|
|
{
|
|
title = Locales[Config.Locale].LUA['no_extensions_found'],
|
|
}
|
|
}
|
|
end
|
|
|
|
table.insert(extensions, {
|
|
title = Locales[Config.Locale].LUA['return_back'],
|
|
menu = 'manage_rccar_extensions',
|
|
})
|
|
|
|
lib.registerContext({
|
|
id = 'add_rccar_extensions',
|
|
title = Locales[Config.Locale].LUA['add_extension'],
|
|
options = extensions
|
|
})
|
|
|
|
lib.showContext('add_rccar_extensions')
|
|
end
|
|
|
|
-- ██████╗ ███████╗████████╗ ███████╗████████╗██████╗ ███████╗███████╗████████╗ ███╗ ██╗ █████╗ ███╗ ███╗███████╗
|
|
-- ██╔════╝ ██╔════╝╚══██╔══╝ ██╔════╝╚══██╔══╝██╔══██╗██╔════╝██╔════╝╚══██╔══╝ ████╗ ██║██╔══██╗████╗ ████║██╔════╝
|
|
-- ██║ ███╗█████╗ ██║ ███████╗ ██║ ██████╔╝█████╗ █████╗ ██║ ██╔██╗ ██║███████║██╔████╔██║█████╗
|
|
-- ██║ ██║██╔══╝ ██║ ╚════██║ ██║ ██╔══██╗██╔══╝ ██╔══╝ ██║ ██║╚██╗██║██╔══██║██║╚██╔╝██║██╔══╝
|
|
-- ╚██████╔╝███████╗ ██║ ███████║ ██║ ██║ ██║███████╗███████╗ ██║ ██║ ╚████║██║ ██║██║ ╚═╝ ██║███████╗
|
|
-- ╚═════╝ ╚══════╝ ╚═╝ ╚══════╝ ╚═╝ ╚═╝ ╚═╝╚══════╝╚══════╝ ╚═╝ ╚═╝ ╚═══╝╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝
|
|
|
|
local function GetStreetName()
|
|
local playerPed = PlayerPedId()
|
|
local playerCoords = GetEntityCoords(playerPed)
|
|
local streetName, crossing = GetStreetNameAtCoord(playerCoords.x, playerCoords.y, playerCoords.z)
|
|
local streetName = GetStreetNameFromHashKey(streetName)
|
|
|
|
return streetName
|
|
end
|
|
|
|
-- ██████╗██████╗ ███████╗ █████╗ ████████╗█████`██╗ ████████╗██╗ ██╗██████╗ ███████╗ █████╗ ██████╗
|
|
-- ██╔════╝██╔══██╗██╔════╝██╔══██╗╚══██╔══╝██╔════╝ ╚══██╔══╝██║ ██║██╔══██╗██╔════╝██╔══██╗██╔══██╗
|
|
-- ██║ ██████╔╝█████╗ ███████║ ██║ █████╗ ██║ ███████║██████╔╝█████╗ ███████║██║ ██║
|
|
-- ██║ ██╔══██╗██╔══╝ ██╔══██║ ██║ ██╔══╝ ██║ ██╔══██║██╔══██╗██╔══╝ ██╔══██║██║ ██║
|
|
-- ╚██████╗██║ ██║███████╗██║ ██║ ██║ ███████╗ ██║ ██║ ██║██║ ██║███████╗██║ ██║██████╔╝
|
|
-- ╚═════╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═╝ ╚══════╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚═════╝
|
|
-- ██████╗██╗ ██╗███████╗ ██████╗██╗ ██╗ ███╗ ██╗██╗ ██╗██╗
|
|
-- ██╔════╝██║ ██║██╔════╝██╔════╝██║ ██╔╝ ████╗ ██║██║ ██║██║
|
|
-- ██║ ███████║█████╗ ██║ █████╔╝ ██╔██╗ ██║██║ ██║██║
|
|
-- ██║ ██╔══██║██╔══╝ ██║ ██╔═██╗ ██║╚██╗██║██║ ██║██║
|
|
-- ╚██████╗██║ ██║███████╗╚██████╗██║ ██╗ ██║ ╚████║╚██████╔╝██║
|
|
-- ╚═════╝╚═╝ ╚═╝╚══════╝ ╚═════╝╚═╝ ╚═╝ ╚═╝ ╚═══╝ ╚═════╝ ╚═╝
|
|
|
|
Citizen.CreateThread(function()
|
|
while not nuiLoaded do
|
|
if NetworkIsSessionStarted() then
|
|
SendNUIMessage({
|
|
action = "CheckNui",
|
|
})
|
|
end
|
|
Citizen.Wait(2000)
|
|
end
|
|
end)
|
|
|
|
Citizen.CreateThread(function()
|
|
for k, v in pairs(Config.Stores) do
|
|
if not storeProducts[k] then
|
|
storeProducts[k] = {}
|
|
end
|
|
|
|
if v.items ~= "all" then
|
|
for _, car in pairs(Config.RCCars) do
|
|
if v.items and v.items[car.item.name] then
|
|
table.insert(storeProducts[k], car)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end)
|
|
|
|
Citizen.CreateThread(function()
|
|
NuiMessage('SetLocale', Locales[Config.Locale].WEB)
|
|
end)
|
|
|
|
-- ██████╗ ███████╗ ██████╗ ██╗███████╗████████╗███████╗██████╗ ███████╗██╗ ██╗███████╗███╗ ██╗████████╗
|
|
-- ██╔══██╗██╔════╝██╔════╝ ██║██╔════╝╚══██╔══╝██╔════╝██╔══██╗ ██╔════╝██║ ██║██╔════╝████╗ ██║╚══██╔══╝
|
|
-- ██████╔╝█████╗ ██║ ███╗██║███████╗ ██║ █████╗ ██████╔╝ █████╗ ██║ ██║█████╗ ██╔██╗ ██║ ██║
|
|
-- ██╔══██╗██╔══╝ ██║ ██║██║╚════██║ ██║ ██╔══╝ ██╔══██╗ ██╔══╝ ╚██╗ ██╔╝██╔══╝ ██║╚██╗██║ ██║
|
|
-- ██║ ██║███████╗╚██████╔╝██║███████║ ██║ ███████╗██║ ██║ ███████╗ ╚████╔╝ ███████╗██║ ╚████║ ██║
|
|
-- ╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═╝╚══════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝ ╚══════╝ ╚═══╝ ╚══════╝╚═╝ ╚═══╝ ╚═╝
|
|
|
|
RegisterNetEvent('onResourceStart')
|
|
AddEventHandler('onResourceStart', function(resource)
|
|
if resource == GetCurrentResourceName() then
|
|
CreateShops()
|
|
|
|
if Config.ChargeSystem then
|
|
CreateChargingStation()
|
|
end
|
|
end
|
|
end)
|
|
|
|
-- ██████╗ ███╗ ██╗ ██████╗ ███████╗███████╗ ██████╗ ██╗ ██╗██████╗ ██████╗███████╗ ███████╗████████╗ ██████╗ ██████╗
|
|
-- ██╔═══██╗████╗ ██║ ██╔══██╗██╔════╝██╔════╝██╔═══██╗██║ ██║██╔══██╗██╔════╝██╔════╝ ██╔════╝╚══██╔══╝██╔═══██╗██╔══██╗
|
|
-- ██║ ██║██╔██╗ ██║ ██████╔╝█████╗ ███████╗██║ ██║██║ ██║██████╔╝██║ █████╗ ███████╗ ██║ ██║ ██║██████╔╝
|
|
-- ██║ ██║██║╚██╗██║ ██╔══██╗██╔══╝ ╚════██║██║ ██║██║ ██║██╔══██╗██║ ██╔══╝ ╚════██║ ██║ ██║ ██║██╔═══╝
|
|
-- ╚██████╔╝██║ ╚████║ ██║ ██║███████╗███████║╚██████╔╝╚██████╔╝██║ ██║╚██████╗███████╗ ███████║ ██║ ╚██████╔╝██║
|
|
-- ╚═════╝ ╚═╝ ╚═══╝ ╚═╝ ╚═╝╚══════╝╚══════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝╚══════╝ ╚══════╝ ╚═╝ ╚═════╝ ╚═╝
|
|
|
|
RegisterNetEvent('onResourceStop')
|
|
AddEventHandler('onResourceStop', function(resource)
|
|
if resource == GetCurrentResourceName() then
|
|
DoScreenFadeIn(1000)
|
|
if vehicleEntity or DoesEntityExist(vehicleEntity) then
|
|
DeleteEntity(vehicleEntity)
|
|
end
|
|
|
|
if vehicleBlip or DoesBlipExist(vehicleBlip) then
|
|
RemoveBlip(vehicleBlip)
|
|
end
|
|
|
|
if vehicleCamera or DoesCamExist(vehicleCamera) then
|
|
DestroyCam(vehicleCamera)
|
|
end
|
|
|
|
if controllerProp or DoesEntityExist(controllerProp) then
|
|
DeleteEntity(controllerProp)
|
|
end
|
|
|
|
if fakePlayerPed or DoesEntityExist(fakePlayerPed) then
|
|
DeleteEntity(fakePlayerPed)
|
|
DoScreenFadeIn(1000)
|
|
end
|
|
|
|
if #storeBlips > 0 then
|
|
for k, v in pairs(storeBlips) do
|
|
if DoesBlipExist(v) then
|
|
RemoveBlip(v)
|
|
end
|
|
end
|
|
end
|
|
|
|
if #storePed > 0 then
|
|
for k, v in pairs(storePed) do
|
|
if DoesEntityExist(v) then
|
|
DeleteEntity(v)
|
|
end
|
|
end
|
|
end
|
|
|
|
if #chargingStationBlips > 0 then
|
|
for k, v in pairs(chargingStationBlips) do
|
|
if DoesBlipExist(v) then
|
|
RemoveBlip(v)
|
|
end
|
|
end
|
|
end
|
|
|
|
if #chargingStationPed > 0 then
|
|
for k, v in pairs(chargingStationPed) do
|
|
if DoesEntityExist(v) then
|
|
DeleteEntity(v)
|
|
end
|
|
end
|
|
end
|
|
|
|
SetSeethrough(false)
|
|
SetNightvision(false)
|
|
|
|
ClearPedTasks(PlayerPedId())
|
|
end
|
|
end)
|
|
|
|
RegisterNetEvent('QBCore:Client:OnPlayerLoaded')
|
|
AddEventHandler('QBCore:Client:OnPlayerLoaded', function()
|
|
if CoreName == 'qb-core' then
|
|
PlayerData = QBCore.Functions.GetPlayerData()
|
|
elseif CoreName == 'qbx_core' then
|
|
PlayerData = QBX:GetPlayerData()
|
|
end
|
|
CreateShops()
|
|
|
|
if Config.ChargeSystem then
|
|
CreateChargingStation()
|
|
end
|
|
end)
|
|
|
|
RegisterNetEvent('esx:playerLoaded')
|
|
AddEventHandler('esx:playerLoaded',function(xPlayer, isNew, skin)
|
|
PlayerData = xPlayer
|
|
CreateShops()
|
|
|
|
if Config.ChargeSystem then
|
|
CreateChargingStation()
|
|
end
|
|
end)
|
|
|
|
RegisterNetEvent('esx:setJob')
|
|
AddEventHandler('esx:setJob',function(job, lastJob)
|
|
PlayerData.job = job
|
|
end)
|
|
|
|
RegisterNetEvent('QBCore:Client:OnJobUpdate', function(job)
|
|
PlayerData.job = job
|
|
end)
|
|
|
|
-- ███████╗██████╗ █████╗ ██╗ ██╗███╗ ██╗ ██╗ ██╗███████╗██╗ ██╗██╗ ██████╗██╗ ███████╗
|
|
-- ██╔════╝██╔══██╗██╔══██╗██║ ██║████╗ ██║ ██║ ██║██╔════╝██║ ██║██║██╔════╝██║ ██╔════╝
|
|
-- ███████╗██████╔╝███████║██║ █╗ ██║██╔██╗ ██║ ██║ ██║█████╗ ███████║██║██║ ██║ █████╗
|
|
-- ╚════██║██╔═══╝ ██╔══██║██║███╗██║██║╚██╗██║ ╚██╗ ██╔╝██╔══╝ ██╔══██║██║██║ ██║ ██╔══╝
|
|
-- ███████║██║ ██║ ██║╚███╔███╔╝██║ ╚████║ ╚████╔╝ ███████╗██║ ██║██║╚██████╗███████╗███████╗
|
|
-- ╚══════╝╚═╝ ╚═╝ ╚═╝ ╚══╝╚══╝ ╚═╝ ╚═══╝ ╚═══╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═════╝╚══════╝╚══════╝
|
|
|
|
function SpawnVehicle(type)
|
|
local playerPed = PlayerPedId()
|
|
local playerCoords = GetEntityCoords(playerPed)
|
|
vehicleEntity = nil
|
|
|
|
RequestModel(type)
|
|
local time = GetGameTimer()
|
|
while not HasModelLoaded(type) do
|
|
Citizen.Wait(0)
|
|
if GetGameTimer() - time > 5000 then
|
|
print(string.format(Locales[Config.Locale].LUA['failed_to_load_model'], type))
|
|
return
|
|
end
|
|
end
|
|
|
|
PlayAnimation('put_object')
|
|
Wait(700)
|
|
local frontCoords = GetOffsetFromEntityInWorldCoords(playerPed, 0.0, 1.0, 0.0)
|
|
vehicleEntity = CreateVehicle(type, frontCoords, GetEntityHeading(playerPed), true, false)
|
|
SetModelAsNoLongerNeeded(type)
|
|
SetVehicleOnGroundProperly(vehicleEntity)
|
|
SetVehicleEngineOn(vehicleEntity, true, true, false)
|
|
SetVehicleModKit(vehicleEntity, 0)
|
|
SetVehicleMod(vehicleEntity, 433, math.random(0, GetNumVehicleMods(vehicleEntity, 433)), false)
|
|
SetEntityAsMissionEntity(vehicleEntity, true, true)
|
|
SetVehicleHasBeenOwnedByPlayer(vehicleEntity, true)
|
|
SetVehicleDoorsLocked(vehicleEntity, 2)
|
|
|
|
if activeVehicle.item.name == 'rc_bandito_offroad' then
|
|
SetVehicleMod(vehicleEntity, 5, 3)
|
|
elseif activeVehicle.item.name == 'rc_bandito_trophy' then
|
|
SetVehicleMod(vehicleEntity, 5, 7)
|
|
elseif activeVehicle.item.name == 'rc_bandito_gang' then
|
|
SetVehicleMod(vehicleEntity, 5, 11)
|
|
elseif activeVehicle.item.name == 'rc_bandito_big' then
|
|
SetVehicleMod(vehicleEntity, 5, 15)
|
|
SetVehicleCustomPrimaryColour(vehicleEntity, 3, 36, 252)
|
|
SetVehicleCustomSecondaryColour(vehicleEntity, 3, 36, 252)
|
|
elseif activeVehicle.item.name == 'rc_bandito_midnight' then
|
|
SetVehicleMod(vehicleEntity, 5, 19)
|
|
end
|
|
|
|
Config.GiveKeys(GetVehicleNumberPlateText(vehicleEntity), vehicleEntity)
|
|
|
|
if Config.DisableCollision then
|
|
SetEntityNoCollisionEntity(vehicleEntity, playerPed, false)
|
|
Citizen.CreateThread(function()
|
|
while DoesEntityExist(vehicleEntity) do
|
|
Citizen.Wait(5000)
|
|
local players = GetActivePlayers()
|
|
for _, player in pairs(players) do
|
|
local playerPed = GetPlayerPed(player)
|
|
SetEntityNoCollisionEntity(vehicleEntity, playerPed, false)
|
|
end
|
|
end
|
|
end)
|
|
end
|
|
end
|
|
|
|
-- ███████╗██████╗ █████╗ ██╗ ██╗███╗ ██╗ ██████╗ ███████╗██████╗
|
|
-- ██╔════╝██╔══██╗██╔══██╗██║ ██║████╗ ██║ ██╔══██╗██╔════╝██╔══██╗
|
|
-- ███████╗██████╔╝███████║██║ █╗ ██║██╔██╗ ██║ ██████╔╝█████╗ ██║ ██║
|
|
-- ╚════██║██╔═══╝ ██╔══██║██║███╗██║██║╚██╗██║ ██╔═══╝ ██╔══╝ ██║ ██║
|
|
-- ███████║██║ ██║ ██║╚███╔███╔╝██║ ╚████║ ██║ ███████╗██████╔╝
|
|
-- ╚══════╝╚═╝ ╚═╝ ╚═╝ ╚══╝╚══╝ ╚═╝ ╚═══╝ ╚═╝ ╚══════╝╚═════╝
|
|
|
|
function SpawnPed()
|
|
local playerPed = PlayerPedId()
|
|
local playerCoords = GetEntityCoords(playerPed)
|
|
local playerModel = GetEntityModel(playerPed)
|
|
|
|
RequestModel(playerModel)
|
|
while not HasModelLoaded(playerModel) do
|
|
Wait(0)
|
|
end
|
|
|
|
lastCoordsPlayer = playerCoords
|
|
local spawnCoords = vector3(playerCoords.x, playerCoords.y, playerCoords.z)
|
|
|
|
local temp_model = promise.new()
|
|
local temp_data = promise.new()
|
|
|
|
lib.callback('0r-rccar:server:getSkin', false, function(model, data)
|
|
temp_model:resolve(model)
|
|
temp_data:resolve(data)
|
|
end)
|
|
local resolved_model = Citizen.Await(temp_model)
|
|
local resolved_data = Citizen.Await(temp_data)
|
|
|
|
skinData = { model = resolved_model, data = resolved_data }
|
|
|
|
fakePlayerPed = CreatePed(4, playerModel, spawnCoords.x, spawnCoords.y, spawnCoords.z, 0.0, true, false)
|
|
SetBlockingOfNonTemporaryEvents(fakePlayerPed, true)
|
|
SetEntityHeading(fakePlayerPed, GetEntityHeading(playerPed))
|
|
SetEntityVisible(fakePlayerPed, false, false)
|
|
|
|
SetModelAsNoLongerNeeded(playerModel)
|
|
SetEntityAsMissionEntity(fakePlayerPed, true, true)
|
|
SetEntityVisible(fakePlayerPed, true, false)
|
|
ApplyCharacterCustomization(fakePlayerPed, skinData.data)
|
|
end
|
|
|
|
-- ███████╗███████╗████████╗ ██████╗ ██╗ ██╗██████╗
|
|
-- ██╔════╝██╔════╝╚══██╔══╝ ██╔══██╗██║ ██║██╔══██╗
|
|
-- ███████╗█████╗ ██║ ██████╔╝██║ ██║██████╔╝
|
|
-- ╚════██║██╔══╝ ██║ ██╔══██╗██║ ██║██╔═══╝
|
|
-- ███████║███████╗ ██║ ██████╔╝███████╗██║██║
|
|
-- ╚══════╝╚══════╝ ╚═╝ ╚═════╝ ╚══════╝╚═╝╚═╝
|
|
|
|
function SetBlip()
|
|
if DoesEntityExist(vehicleEntity) and Config.BlipSettings.Vehicle.active then
|
|
local vehicleCoords = GetEntityCoords(vehicleEntity, true)
|
|
vehicleBlip = AddBlipForCoord(vehicleCoords.x, vehicleCoords.y, vehicleCoords.z)
|
|
SetBlipSprite(vehicleBlip, Config.BlipSettings.Vehicle.sprite)
|
|
SetBlipColour(vehicleBlip, Config.BlipSettings.Vehicle.color)
|
|
SetBlipScale(vehicleBlip, Config.BlipSettings.Vehicle.scale)
|
|
SetBlipAsShortRange(vehicleBlip, true)
|
|
BeginTextCommandSetBlipName("STRING")
|
|
AddTextComponentSubstringPlayerName(Config.BlipSettings.Vehicle.name)
|
|
EndTextCommandSetBlipName(vehicleBlip)
|
|
end
|
|
|
|
Citizen.CreateThread(function()
|
|
while vehicleEntity do
|
|
if DoesEntityExist(vehicleEntity) and Config.BlipSettings.Vehicle.active then
|
|
local updatedCoords = GetEntityCoords(vehicleEntity, true)
|
|
SetBlipCoords(vehicleBlip, updatedCoords.x, updatedCoords.y, updatedCoords.z)
|
|
else
|
|
RemoveBlip(vehicleBlip)
|
|
vehicleBlip = nil
|
|
break
|
|
end
|
|
Citizen.Wait(2000)
|
|
end
|
|
end)
|
|
end
|
|
|
|
-- ███████╗███████╗████████╗ ██████╗ █████╗ ███╗ ███╗
|
|
-- ██╔════╝██╔════╝╚══██╔══╝ ██╔════╝██╔══██╗████╗ ████║
|
|
-- ███████╗█████╗ ██║ ██║ ███████║██╔████╔██║
|
|
-- ╚════██║██╔══╝ ██║ ██║ ██╔══██║██║╚██╔╝██║
|
|
-- ███████║███████╗ ██║ ╚██████╗██║ ██║██║ ╚═╝ ██║
|
|
-- ╚══════╝╚══════╝ ╚═╝ ╚═════╝╚═╝ ╚═╝╚═╝ ╚═╝
|
|
|
|
function SetCam()
|
|
vehicleCamera = CreateCam("DEFAULT_SCRIPTED_CAMERA", true)
|
|
AttachCamToEntity(vehicleCamera, vehicleEntity, 0.0, 0.0, 0.4, true)
|
|
SetCamRot(vehicleCamera, GetEntityRotation(vehicleEntity))
|
|
end
|
|
|
|
-- ██████╗██╗ ██╗███████╗ ██████╗██╗ ██╗ ██████╗ ██╗ ██╗ ██╗ ██████╗ ██╗███╗ ██╗███████╗
|
|
-- ██╔════╝██║ ██║██╔════╝██╔════╝██║ ██╔╝ ██╔══██╗██║ ██║ ██║██╔════╝ ██║████╗ ██║██╔════╝
|
|
-- ██║ ███████║█████╗ ██║ █████╔╝ ██████╔╝██║ ██║ ██║██║ ███╗██║██╔██╗ ██║███████╗
|
|
-- ██║ ██╔══██║██╔══╝ ██║ ██╔═██╗ ██╔═══╝ ██║ ██║ ██║██║ ██║██║██║╚██╗██║╚════██║
|
|
-- ╚██████╗██║ ██║███████╗╚██████╗██║ ██╗ ██║ ███████╗╚██████╔╝╚██████╔╝██║██║ ╚████║███████║
|
|
-- ╚═════╝╚═╝ ╚═╝╚══════╝ ╚═════╝╚═╝ ╚═╝ ╚═╝ ╚══════╝ ╚═════╝ ╚═════╝ ╚═╝╚═╝ ╚═══╝╚══════╝
|
|
|
|
function CheckPlugins()
|
|
if activePlugins then
|
|
for k, v in pairs(activePlugins) do
|
|
if v.name == 'rc_advancedcamera' then
|
|
StartPlugins('AdvancedCamera')
|
|
end
|
|
|
|
if v.name == 'rc_nitrous' then
|
|
StartPlugins('Nitrous')
|
|
end
|
|
|
|
if v.name == 'rc_battery' then
|
|
StartPlugins('BatteryProtector')
|
|
end
|
|
|
|
if v.name == 'rc_signal' then
|
|
StartPlugins('SignalBooster')
|
|
end
|
|
|
|
if v.name == 'rc_bomb' then
|
|
NuiMessage('StartPlugins', { type = 'Bomb', status = true })
|
|
end
|
|
|
|
if v.name == 'rc_jump' then
|
|
StartPlugins('Jump')
|
|
end
|
|
|
|
if v.name == 'rc_teaser' then
|
|
NuiMessage('StartPlugins', { type = 'Teaser', status = true })
|
|
end
|
|
end
|
|
end
|
|
|
|
if activeVehicle and activeVehicle.item and activeVehicle.item.type and activeVehicle.item.type == 'emergency' then
|
|
NuiMessage('StartPlugins', { type = 'ScanIdentifier', status = true })
|
|
end
|
|
end
|
|
|
|
function StartPlugins(type)
|
|
if type == 'AdvancedCamera' then
|
|
local activeFilter = 'NRM'
|
|
Citizen.CreateThread(function()
|
|
while vehicleEntity and DoesEntityExist(vehicleEntity) and not NoSignal and not LowBattery and isCameraActive do
|
|
if IsControlJustPressed(0, Config.Controls.ChangeCameraFilter) then
|
|
if activeFilter == 'NRM' then
|
|
activeFilter = 'NGTV'
|
|
SetNightvision(true)
|
|
elseif activeFilter == 'NGTV' then
|
|
activeFilter = 'THRML'
|
|
SetNightvision(false)
|
|
SetSeethrough(true)
|
|
elseif activeFilter == 'THRML' then
|
|
activeFilter = 'NRM'
|
|
SetSeethrough(false)
|
|
end
|
|
|
|
NuiMessage('ChangeCameraType', activeFilter)
|
|
end
|
|
|
|
Citizen.Wait(0)
|
|
end
|
|
end)
|
|
end
|
|
|
|
if type == 'Nitrous' then
|
|
local nitrousActive = false
|
|
local usableNitro = true
|
|
|
|
Citizen.CreateThread(function()
|
|
while vehicleEntity and DoesEntityExist(vehicleEntity) and not NoSignal and not LowBattery and isCameraActive do
|
|
Citizen.Wait(0)
|
|
|
|
local ped = PlayerPedId()
|
|
if IsPedInAnyVehicle(ped, false) then
|
|
local vehicle = GetVehiclePedIsIn(ped, false)
|
|
|
|
if IsControlPressed(0, Config.Controls.NitrousKey) and usableNitro then
|
|
SetVehicleEngineTorqueMultiplier(vehicle, Config.NitrousPower)
|
|
|
|
ModifyVehicleTopSpeed(vehicle, 50.0)
|
|
SetVehicleReduceGrip(vehicle, false)
|
|
|
|
nitrousActive = true
|
|
else
|
|
SetVehicleEngineTorqueMultiplier(vehicle, 1.0)
|
|
ModifyVehicleTopSpeed(vehicle, 0.0)
|
|
SetVehicleReduceGrip(vehicle, false)
|
|
|
|
nitrousActive = false
|
|
end
|
|
else
|
|
SetVehicleEngineTorqueMultiplier(GetVehiclePedIsIn(ped, true), 1.0)
|
|
|
|
nitrousActive = false
|
|
end
|
|
end
|
|
end)
|
|
|
|
local usedTime = 0
|
|
Citizen.CreateThread(function()
|
|
|
|
while vehicleEntity and DoesEntityExist(vehicleEntity) and not NoSignal and not LowBattery and isCameraActive do
|
|
Citizen.Wait(1000)
|
|
|
|
if nitrousActive then
|
|
usedTime = usedTime + 1000
|
|
if usedTime >= 5000 then
|
|
usableNitro = false
|
|
|
|
SetTimeout(30000, function()
|
|
usableNitro = true
|
|
usedTime = 0
|
|
end)
|
|
end
|
|
end
|
|
end
|
|
end)
|
|
end
|
|
|
|
if type == 'BatteryProtector' then
|
|
batteryProtector = true
|
|
end
|
|
|
|
if type == 'SignalBooster' then
|
|
signalBooster = Config.SignalBooster
|
|
end
|
|
|
|
if type == 'Bomb' then
|
|
return true
|
|
end
|
|
|
|
if type == 'Jump' then
|
|
local lastUsed = 0
|
|
Citizen.CreateThread(function()
|
|
while vehicleEntity and DoesEntityExist(vehicleEntity) and not NoSignal and not LowBattery and isCameraActive do
|
|
Citizen.Wait(0)
|
|
|
|
local ped = PlayerPedId()
|
|
if IsPedInAnyVehicle(ped, false) then
|
|
local vehicle = GetVehiclePedIsIn(ped, false)
|
|
|
|
if IsControlJustPressed(1, Config.Controls.JumpKey) and (GetGameTimer() - lastUsed > 2000) then
|
|
lastUsed = GetGameTimer()
|
|
|
|
ApplyForceToEntity(vehicle, 1, 0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0, true, true, true, true, true)
|
|
end
|
|
end
|
|
end
|
|
end)
|
|
end
|
|
|
|
if type == 'ScanIdentifier' then
|
|
Citizen.CreateThread(function()
|
|
while vehicleEntity and DoesEntityExist(vehicleEntity) and not NoSignal and not LowBattery and isCameraActive and activePlugin == 'ScanIdentifier' do
|
|
local sleep = 1000
|
|
if isCameraActive then
|
|
local camCoords = GetCamCoord(vehicleCamera)
|
|
local camRot = GetCamRot(vehicleCamera, 2)
|
|
|
|
local forwardVector = vector3(
|
|
-math.sin(math.rad(camRot.z)) * math.abs(math.cos(math.rad(camRot.x))),
|
|
math.cos(math.rad(camRot.z)) * math.abs(math.cos(math.rad(camRot.x))),
|
|
math.sin(math.rad(camRot.x))
|
|
)
|
|
|
|
local distance = 300.0
|
|
|
|
local shape = StartExpensiveSynchronousShapeTestLosProbe(
|
|
camCoords.x, camCoords.y, camCoords.z,
|
|
camCoords.x + forwardVector.x * distance,
|
|
camCoords.y + forwardVector.y * distance,
|
|
camCoords.z + forwardVector.z * distance,
|
|
10, PlayerPedId(), 0
|
|
)
|
|
|
|
local shapeTestHandle, hit, endCoords, surfaceNormal, entityHit = GetShapeTestResult(shape)
|
|
|
|
if hit ~= 0 and entityHit ~= 0 then
|
|
if not ActivePlayerExist(entityHit) then
|
|
if IsEntityAPed(entityHit) then
|
|
local result = nil
|
|
local mugshot = nil
|
|
|
|
result = GetBase64(entityHit)
|
|
|
|
if result.success then
|
|
mugshot = result.base64
|
|
end
|
|
|
|
if IsPedAPlayer(entityHit) then
|
|
lib.callback('0r-rccar:server:scanPlayer', false, function(data)
|
|
ActivePlayer = {
|
|
type = 'player',
|
|
ped = entityHit,
|
|
name = data.name or 'Unknown',
|
|
image = mugshot or 'assets/image/avatar.png',
|
|
birthDate = data.birthDate or 'Unknown',
|
|
}
|
|
|
|
DataShow = true
|
|
NuiMessage('ShowData', ActivePlayer)
|
|
end, NetworkGetNetworkIdFromEntity(entityHit))
|
|
else
|
|
ActivePlayer = {
|
|
type = 'player',
|
|
ped = entityHit,
|
|
name = 'Unknown',
|
|
image = mugshot or 'assets/image/avatar.png',
|
|
birthDate = 'Unknown',
|
|
}
|
|
|
|
DataShow = true
|
|
NuiMessage('ShowData', ActivePlayer)
|
|
end
|
|
elseif IsEntityAVehicle(entityHit) then
|
|
ActivePlayer = {
|
|
type = 'vehicle',
|
|
ped = entityHit,
|
|
name = GetDisplayNameFromVehicleModel(GetEntityModel(entityHit)),
|
|
plate = GetVehicleNumberPlateText(entityHit),
|
|
}
|
|
|
|
DataShow = true
|
|
NuiMessage('ShowData', ActivePlayer)
|
|
end
|
|
else
|
|
if not DataShow then
|
|
DataShow = true
|
|
|
|
NuiMessage('ShowData', ActivePlayer)
|
|
end
|
|
end
|
|
sleep = 5
|
|
else
|
|
if DataShow then
|
|
DataShow = false
|
|
NuiMessage('HideData')
|
|
end
|
|
end
|
|
end
|
|
|
|
Citizen.Wait(sleep)
|
|
end
|
|
end)
|
|
end
|
|
|
|
if type == 'Teaser' then
|
|
CreateThread(function()
|
|
RequestWeaponAsset(GetHashKey('WEAPON_STUNGUN'))
|
|
while not HasWeaponAssetLoaded(GetHashKey('WEAPON_STUNGUN')) do
|
|
Wait(10)
|
|
end
|
|
|
|
while vehicleEntity and DoesEntityExist(vehicleEntity) and not NoSignal and not LowBattery and isCameraActive and activePlugin == 'Teaser' do
|
|
local ped = PlayerPedId()
|
|
|
|
if IsControlJustPressed(0, 24) then
|
|
|
|
local camCoords = GetCamCoord(vehicleCamera)
|
|
local camRot = GetCamRot(vehicleCamera, 2)
|
|
|
|
local forwardVector = vector3(
|
|
-math.sin(math.rad(camRot.z)) * math.abs(math.cos(math.rad(camRot.x))),
|
|
math.cos(math.rad(camRot.z)) * math.abs(math.cos(math.rad(camRot.x))),
|
|
math.sin(math.rad(camRot.x))
|
|
)
|
|
|
|
local distance = 300.0
|
|
|
|
local shape = StartExpensiveSynchronousShapeTestLosProbe(
|
|
camCoords.x, camCoords.y, camCoords.z,
|
|
camCoords.x + forwardVector.x * distance,
|
|
camCoords.y + forwardVector.y * distance,
|
|
camCoords.z + forwardVector.z * distance,
|
|
10, PlayerPedId(), 0
|
|
)
|
|
|
|
local shapeTestHandle, hit, endCoords, surfaceNormal, entityHit = GetShapeTestResult(shape)
|
|
|
|
if hit == 1 and DoesEntityExist(entityHit) and IsEntityAPed(entityHit) then
|
|
if IsPedAPlayer(entityHit) then
|
|
local targetCoords = GetEntityCoords(entityHit)
|
|
ShootSingleBulletBetweenCoords(camCoords.x, camCoords.y, camCoords.z, targetCoords.x, targetCoords.y, targetCoords.z, 0, true, GetHashKey('WEAPON_STUNGUN'), ped, true, false, 1000.0)
|
|
end
|
|
end
|
|
end
|
|
Wait(0)
|
|
end
|
|
end)
|
|
end
|
|
end
|
|
|
|
function HideHUDThisFrame()
|
|
Citizen.CreateThread(function()
|
|
while vehicleEntity and DoesEntityExist(vehicleEntity) and not NoSignal and not LowBattery and isCameraActive do
|
|
Wait(0)
|
|
HideHelpTextThisFrame()
|
|
HideHudAndRadarThisFrame()
|
|
HideHudComponentThisFrame(19) -- weapon wheel
|
|
HideHudComponentThisFrame(1) -- Wanted Stars
|
|
HideHudComponentThisFrame(2) -- Weapon icon
|
|
HideHudComponentThisFrame(3) -- Cash
|
|
HideHudComponentThisFrame(4) -- MP CASH
|
|
HideHudComponentThisFrame(13) -- Cash Change
|
|
HideHudComponentThisFrame(11) -- Floating Help Text
|
|
HideHudComponentThisFrame(12) -- more floating help text
|
|
HideHudComponentThisFrame(15) -- Subtitle Text
|
|
HideHudComponentThisFrame(18) -- Game Stream
|
|
|
|
if IsPauseMenuActive() then
|
|
SetFrontendActive(false)
|
|
end
|
|
|
|
DisableControlAction(0, 75, true)
|
|
DisableControlAction(0, 322, true)
|
|
DisableControlAction(0, 73, true)
|
|
DisableControlAction(0, 178, true)
|
|
DisableControlAction(0, 23, true)
|
|
end
|
|
end)
|
|
end
|
|
|
|
function ChargingProcess()
|
|
Citizen.CreateThread(function()
|
|
while vehicleEntity and DoesEntityExist(vehicleEntity) and not NoSignal and not LowBattery and Config.ChargeSystem do
|
|
Wait(1000 * Config.ChargingProcess.Disappearing.Time)
|
|
|
|
local DecreasingAmount = Config.ChargingProcess.Disappearing.Decreasing
|
|
if batteryProtector then
|
|
DecreasingAmount = DecreasingAmount * Config.BatterySaving
|
|
end
|
|
|
|
if batteryLevel - DecreasingAmount < 0 then
|
|
batteryLevel = 0
|
|
else
|
|
batteryLevel = batteryLevel - DecreasingAmount
|
|
end
|
|
|
|
NuiMessage('UpdateBattery', batteryLevel)
|
|
|
|
if batteryLevel == 0 then
|
|
LowBattery = true
|
|
break
|
|
end
|
|
|
|
end
|
|
end)
|
|
end
|
|
|
|
function OpenPluginsMenu()
|
|
Citizen.CreateThread(function()
|
|
while vehicleEntity and DoesEntityExist(vehicleEntity) and not NoSignal and not LowBattery do
|
|
if IsControlJustPressed(0, Config.Controls.OpenPluginsMenu) then
|
|
NuiMessage('OpenPluginsMenu')
|
|
SetNuiFocus(true, true)
|
|
end
|
|
|
|
Citizen.Wait(0)
|
|
end
|
|
end)
|
|
end
|
|
|
|
local timeoutActive = false
|
|
|
|
local function CheckVehicleStatus()
|
|
Citizen.CreateThread(function()
|
|
while vehicleEntity and DoesEntityExist(vehicleEntity) and not NoSignal and not LowBattery do
|
|
Wait(1000)
|
|
local engineHealth = GetVehicleEngineHealth(vehicleEntity) / 10.0
|
|
|
|
NuiMessage('UpdateDamage', engineHealth)
|
|
|
|
if engineHealth <= 84.0 then
|
|
SetVehicleEngineHealth(vehicleEntity, 0.0)
|
|
SetVehicleUndriveable(vehicleEntity, true)
|
|
NuiMessage('Notification', { header = Locales[Config.Locale].WEB['error'], message = Locales[Config.Locale].LUA['engine_broken'] })
|
|
local coords = GetEntityCoords(vehicleEntity)
|
|
local retval = StartScriptFire(coords.x, coords.y, coords.z, 25, false)
|
|
|
|
if not timeoutActive then
|
|
timeoutActive = true
|
|
SetTimeout(3000, function()
|
|
if isCameraActive then
|
|
DoScreenFadeOut(1000)
|
|
Wait(1000)
|
|
isCameraActive = false
|
|
Config.SetInvBusy(false)
|
|
Config.SetHudDisplay(false)
|
|
SetSeethrough(false)
|
|
SetNightvision(false)
|
|
RenderScriptCams(false, false, 0, true, true)
|
|
NuiMessage('SetCamera', { active = false })
|
|
ClearPedTasksImmediately(PlayerPedId())
|
|
SetEntityVisible(PlayerPedId(), false, false)
|
|
TaskLeaveVehicle(PlayerPedId(), vehicleEntity, 0)
|
|
local pedCoords = nil
|
|
|
|
if DoesEntityExist(fakePlayerPed) then
|
|
pedCoords = GetEntityCoords(fakePlayerPed)
|
|
else
|
|
pedCoords = lastCoordsPlayer
|
|
end
|
|
|
|
SetEntityCoords(PlayerPedId(), pedCoords)
|
|
DeleteEntity(fakePlayerPed)
|
|
DeleteEntity(controllerProp)
|
|
RemoveScriptFire(retval)
|
|
DeleteEntity(vehicleEntity)
|
|
vehicleEntity = nil
|
|
SetEntityVisible(PlayerPedId(), true, false)
|
|
fakePlayerPed = nil
|
|
DoScreenFadeIn(1000)
|
|
TriggerServerEvent('0r-rccar:server:saveVehicle', activeVehicle, batteryLevel)
|
|
else
|
|
Config.SetInvBusy(false)
|
|
Config.SetHudDisplay(false)
|
|
DeleteEntity(vehicleEntity)
|
|
vehicleEntity = nil
|
|
SetSeethrough(false)
|
|
SetNightvision(false)
|
|
NuiMessage('SetCamera', { active = false })
|
|
RemoveScriptFire(retval)
|
|
TriggerServerEvent('0r-rccar:server:saveVehicle', activeVehicle, batteryLevel)
|
|
end
|
|
timeoutActive = false
|
|
end)
|
|
end
|
|
end
|
|
end
|
|
end)
|
|
end
|
|
|
|
-- ██╗ ██╗███████╗███████╗ ██████╗ ██████╗ ██████╗ █████╗ ██████╗
|
|
-- ██║ ██║██╔════╝██╔════╝ ██╔══██╗██╔════╝ ██╔════╝██╔══██╗██╔══██╗
|
|
-- ██║ ██║███████╗█████╗ ██████╔╝██║ ██║ ███████║██████╔╝
|
|
-- ██║ ██║╚════██║██╔══╝ ██╔══██╗██║ ██║ ██╔══██║██╔══██╗
|
|
-- ╚██████╔╝███████║███████╗ ██║ ██║╚██████╗ ╚██████╗██║ ██║██║ ██║
|
|
-- ╚═════╝ ╚══════╝╚══════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═════╝╚═╝ ╚═╝╚═╝ ╚═╝
|
|
|
|
RegisterNetEvent('0r-rccar:client:useRcCar')
|
|
AddEventHandler('0r-rccar:client:useRcCar', function(data)
|
|
if DoesEntityExist(vehicleEntity) and vehicleEntity then
|
|
if CoreName == 'qb-core' then
|
|
QBCore.Functions.Notify(Locales[Config.Locale].LUA['already_have_car'], 'error')
|
|
elseif CoreName == 'qbx_core' then
|
|
QBX:Notify(Locales[Config.Locale].LUA['already_have_car'], 'error')
|
|
elseif CoreName == 'es_extended' then
|
|
ESX.ShowNotification(Locales[Config.Locale].LUA['already_have_car'], 'error')
|
|
end
|
|
|
|
return
|
|
end
|
|
|
|
activeVehicle = data
|
|
SpawnVehicle(data.vehicle.prop)
|
|
SetBlip()
|
|
CheckVehicleStatus()
|
|
|
|
if Config.Interaction == 'ox_target' then
|
|
exports.ox_target:addLocalEntity(vehicleEntity, {
|
|
name = 'manage_vehicle',
|
|
label = Locales[Config.Locale].LUA['manage_vehicle'],
|
|
icon = 'fas fa-car',
|
|
distance = 3.0,
|
|
onSelect = function(entity)
|
|
RegisterContextMenu()
|
|
end
|
|
})
|
|
elseif Config.Interaction == 'qb-target' then
|
|
exports['qb-target']:AddTargetEntity(vehicleEntity, {
|
|
options = {
|
|
{
|
|
icon = 'fas fa-car',
|
|
label = Locales[Config.Locale].LUA['manage_vehicle'],
|
|
action = function(entity)
|
|
RegisterContextMenu()
|
|
end,
|
|
}
|
|
},
|
|
distance = 2.5,
|
|
})
|
|
elseif Config.Interaction == 'drawtext' then
|
|
Citizen.CreateThread(function()
|
|
while DoesEntityExist(vehicleEntity) do
|
|
local sleep = 1000
|
|
local playerCoords = GetEntityCoords(PlayerPedId())
|
|
local carCoords = GetEntityCoords(vehicleEntity)
|
|
local distance = #(playerCoords - carCoords)
|
|
|
|
if distance < 2.5 and not isCameraActive then
|
|
DrawText3D(carCoords.x, carCoords.y, carCoords.z + 1.0, '[~g~' .. Config.Controls.InteractionKey.text .. '~w~] - ' .. Locales[Config.Locale].LUA['manage_vehicle'])
|
|
sleep = 3
|
|
if IsControlJustPressed(0, Config.Controls.InteractionKey.key) then
|
|
RegisterContextMenu()
|
|
end
|
|
end
|
|
Citizen.Wait(sleep)
|
|
end
|
|
end)
|
|
end
|
|
|
|
activePlugins = {}
|
|
isLoading = false
|
|
|
|
lib.callback('0r-rccar:server:getActivePlugins', false, function(result)
|
|
activePlugins = json.decode(result)
|
|
isLoading = true
|
|
end, data)
|
|
|
|
while not isLoading do
|
|
Wait(100)
|
|
end
|
|
|
|
batteryLevel = 100
|
|
isLoading = false
|
|
|
|
lib.callback('0r-rccar:server:getBatteryLevel', false, function(result)
|
|
batteryLevel = result
|
|
isLoading = true
|
|
end, data)
|
|
|
|
while not isLoading do
|
|
Wait(100)
|
|
end
|
|
end)
|
|
|
|
RegisterNetEvent('0r-rccar:client:refreshExtension')
|
|
AddEventHandler('0r-rccar:client:refreshExtension', function(data)
|
|
activePlugins = data
|
|
end)
|
|
|
|
-- ██████╗ ███████╗ ██████╗ ██╗███████╗████████╗███████╗██████╗ ███╗ ██╗██╗ ██╗██╗ ██████╗ █████╗ ██╗ ██╗ ██████╗ █████╗ ██████╗██╗ ██╗
|
|
-- ██╔══██╗██╔════╝██╔════╝ ██║██╔════╝╚══██╔══╝██╔════╝██╔══██╗ ████╗ ██║██║ ██║██║ ██╔════╝██╔══██╗██║ ██║ ██╔══██╗██╔══██╗██╔════╝██║ ██╔╝
|
|
-- ██████╔╝█████╗ ██║ ███╗██║███████╗ ██║ █████╗ ██████╔╝ ██╔██╗ ██║██║ ██║██║ ██║ ███████║██║ ██║ ██████╔╝███████║██║ █████╔╝
|
|
-- ██╔══██╗██╔══╝ ██║ ██║██║╚════██║ ██║ ██╔══╝ ██╔══██╗ ██║╚██╗██║██║ ██║██║ ██║ ██╔══██║██║ ██║ ██╔══██╗██╔══██║██║ ██╔═██╗
|
|
-- ██║ ██║███████╗╚██████╔╝██║███████║ ██║ ███████╗██║ ██║ ██║ ╚████║╚██████╔╝██║ ╚██████╗██║ ██║███████╗███████╗██████╔╝██║ ██║╚██████╗██║ ██╗
|
|
-- ╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═╝╚══════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═══╝ ╚═════╝ ╚═╝ ╚═════╝╚═╝ ╚═╝╚══════╝╚══════╝╚═════╝ ╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝
|
|
|
|
-- ██████╗██╗ ██╗███████╗ ██████╗██╗ ██╗ ███╗ ██╗██╗ ██╗██╗
|
|
-- ██╔════╝██║ ██║██╔════╝██╔════╝██║ ██╔╝ ████╗ ██║██║ ██║██║
|
|
-- ██║ ███████║█████╗ ██║ █████╔╝ ██╔██╗ ██║██║ ██║██║
|
|
-- ██║ ██╔══██║██╔══╝ ██║ ██╔═██╗ ██║╚██╗██║██║ ██║██║
|
|
-- ╚██████╗██║ ██║███████╗╚██████╗██║ ██╗ ██║ ╚████║╚██████╔╝██║
|
|
-- ╚═════╝╚═╝ ╚═╝╚══════╝ ╚═════╝╚═╝ ╚═╝ ╚═╝ ╚═══╝ ╚═════╝ ╚═╝
|
|
|
|
RegisterNUICallback('CloseMenu', function()
|
|
SetNuiFocus(false, false)
|
|
end)
|
|
|
|
RegisterNUICallback('CheckNui', function()
|
|
nuiLoaded = true
|
|
end)
|
|
|
|
RegisterNUICallback('BuyCar', function(data, cb)
|
|
lib.callback('0r-rccar:server:buyCar', false, function(res)
|
|
cb(res)
|
|
end, data)
|
|
end)
|
|
|
|
RegisterNUICallback('Crafting', function(data, cb)
|
|
lib.callback('0r-rccar:server:crafting', false, function(res)
|
|
cb(res)
|
|
end, data)
|
|
end)
|
|
|
|
RegisterNUICallback('GetCraftResources', function(data, cb)
|
|
lib.callback('0r-rccar:server:getItemCount', false, function(res)
|
|
cb(res)
|
|
end, data)
|
|
end)
|
|
|
|
RegisterNUICallback('CraftingFinish', function(data)
|
|
lib.callback('0r-rccar:server:craftingFinish', false, function(res)
|
|
return true
|
|
end, data)
|
|
end)
|
|
|
|
RegisterNUICallback('ActivePlugin', function(data)
|
|
activePlugin = data
|
|
StartPlugins(data)
|
|
end)
|
|
|
|
RegisterNUICallback('LastTimerSecond', function()
|
|
if isCameraActive then
|
|
DoScreenFadeOut(1000)
|
|
Wait(1000)
|
|
isCameraActive = false
|
|
Config.SetInvBusy(false)
|
|
Config.SetHudDisplay(false)
|
|
SetSeethrough(false)
|
|
SetNightvision(false)
|
|
RenderScriptCams(false, false, 0, true, true)
|
|
NuiMessage('SetCamera', { active = false })
|
|
ClearPedTasksImmediately(PlayerPedId())
|
|
SetEntityVisible(PlayerPedId(), false, false)
|
|
TaskLeaveVehicle(PlayerPedId(), vehicleEntity, 0)
|
|
local pedCoords = nil
|
|
|
|
if DoesEntityExist(fakePlayerPed) then
|
|
pedCoords = GetEntityCoords(fakePlayerPed)
|
|
else
|
|
pedCoords = lastCoordsPlayer
|
|
end
|
|
|
|
SetEntityCoords(PlayerPedId(), pedCoords)
|
|
DeleteEntity(fakePlayerPed)
|
|
DeleteEntity(controllerProp)
|
|
SetEntityVisible(PlayerPedId(), true, false)
|
|
fakePlayerPed = nil
|
|
DoScreenFadeIn(1000)
|
|
end
|
|
end)
|
|
|
|
RegisterNUICallback('TimerFinish', function()
|
|
local coords = GetEntityCoords(vehicleEntity)
|
|
AddExplosion(coords.x, coords.y, coords.z, 0, 20.0, true, false, true)
|
|
DeleteEntity(vehicleEntity)
|
|
vehicleEntity = nil
|
|
TriggerServerEvent('0r-rccar:server:bombVehicle', activeVehicle)
|
|
end) |