structura foldere
mutat kq- folders in un singur folder [kq]
This commit is contained in:
BIN
resources/[framework]/[addons]/[kq]/kq_carheist/.fxap
Normal file
BIN
resources/[framework]/[addons]/[kq]/kq_carheist/.fxap
Normal file
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 64 KiB |
@@ -0,0 +1 @@
|
||||
INSERT INTO `items` (`name`, `label`, `weight`, `rare`, `can_remove`) VALUES ('kq_angle_grinder', 'Angle grinder', 3, 0, 1);
|
||||
@@ -0,0 +1 @@
|
||||
["kq_angle_grinder"] = {["name"] = "kq_angle_grinder", ["label"] = "Angle Grinder", ["weight"] = 1000, ["type"] = "item", ["image"] = "kq_angle_grinder.png", ["unique"] = false, ["useable"] = false, ["shouldClose"] = false, ["combinable"] = nil, ["description"] = "Used to cut metals"},
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 64 KiB |
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,130 @@
|
||||
-- Gang and police check variables
|
||||
local heistAllowed = true
|
||||
local gangCheckDone = false
|
||||
|
||||
-- Check if the player meets requirements to participate in the heist
|
||||
function CheckHeistRequirements()
|
||||
if Config.requireGang then
|
||||
if not IsInGang() then
|
||||
ShowTooltip(L('~r~You must be in a gang to participate in this heist'))
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function AfterTruckCreated(vehicle)
|
||||
|
||||
end
|
||||
|
||||
function AfterTrailerCreated(vehicle)
|
||||
|
||||
end
|
||||
|
||||
function AfterTrailerVehicleCreated(vehicle)
|
||||
|
||||
end
|
||||
|
||||
function AfterDriverCreated(ped)
|
||||
|
||||
end
|
||||
|
||||
function AfterPassengerCreated(ped)
|
||||
|
||||
end
|
||||
|
||||
function AfterSupportVehicleCreated(vehicle)
|
||||
|
||||
end
|
||||
|
||||
function AfterSupportPedCreated(ped)
|
||||
|
||||
end
|
||||
|
||||
function OnStartOpeningTrailer()
|
||||
if not CheckHeistRequirements() then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
function OnTrailerOpened()
|
||||
|
||||
end
|
||||
|
||||
function OnVehicleDetach(vehicle)
|
||||
|
||||
end
|
||||
|
||||
function DrawCustomMarker(dropCoords)
|
||||
DrawMarker(36, dropCoords.x, dropCoords.y, dropCoords.z + 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3.0, 3.0, 3.0, 210, 232, 7, 50, 0, 1, 0, 0)
|
||||
end
|
||||
|
||||
RegisterNetEvent('kq_carheist:dropOffCompleted')
|
||||
AddEventHandler('kq_carheist:dropOffCompleted', function(reward, losses, vehName)
|
||||
if losses > 0 then
|
||||
Alert(L('{vehicle} dropped off'):gsub('{vehicle}', vehName), (L('You made ~g~${reward}\n~r~${losses} deducted due to vehicle damage')):gsub('{reward}', reward):gsub('{losses}', losses), 5000)
|
||||
else
|
||||
Alert(L('{vehicle} dropped off'):gsub('{vehicle}', vehName), (L('You made ~g~${reward}')):gsub('{reward}', reward), 5000)
|
||||
end
|
||||
PlaySoundFrontend(-1, 'PROPERTY_PURCHASE', 'HUD_AWARDS', false)
|
||||
end)
|
||||
|
||||
|
||||
function SendAnnouncementMessage(message, subtitle, coords)
|
||||
BeginTextCommandThefeedPost("STRING")
|
||||
AddTextComponentSubstringPlayerName(message)
|
||||
|
||||
-- Set the notification icon, title and subtitle.
|
||||
local title = L('Martin')
|
||||
local iconType = 0
|
||||
local flash = false -- Flash doesn't seem to work no matter what.
|
||||
EndTextCommandThefeedPostMessagetext("CHAR_MARTIN", "CHAR_MARTIN", flash, iconType, title, subtitle)
|
||||
|
||||
-- Draw the notification
|
||||
local showInBrief = true
|
||||
local blink = false -- blink doesn't work when using icon notifications.
|
||||
EndTextCommandThefeedPostTicker(blink, showInBrief)
|
||||
|
||||
local blipConf = Config.announcementBlip.primary
|
||||
CreateTemporaryBlip(coords, blipConf.sprite, blipConf.color, blipConf.alpha, blipConf.scale, L('Car transport'), blipConf.shortRange, true)
|
||||
|
||||
blipConf = Config.announcementBlip.secondary
|
||||
CreateTemporaryBlip(coords, blipConf.sprite, blipConf.color, blipConf.alpha, blipConf.scale, L('Car transport'), blipConf.shortRange)
|
||||
end
|
||||
|
||||
-- This function is responsible for creating the text shown on the bottom of the screen
|
||||
function DrawMissionText(text, time)
|
||||
SetTextEntry_2("STRING")
|
||||
AddTextComponentString(text)
|
||||
DrawSubtitleTimed(time or 30000, 1)
|
||||
end
|
||||
|
||||
-- This function is responsible for all the tooltips displayed on top right of the screen, you could
|
||||
-- replace it with a custom notification etc.
|
||||
function ShowTooltip(message)
|
||||
SetTextComponentFormat("STRING")
|
||||
AddTextComponentString(message)
|
||||
EndTextCommandDisplayHelp(0, 0, 0, -1)
|
||||
end
|
||||
|
||||
-- This function is responsible for drawing all the 3d texts ('Press [E] to prepare for an engine swap' e.g)
|
||||
function Draw3DText(x, y, z, textInput, fontId, scaleX, scaleY)
|
||||
local px, py, pz = table.unpack(GetGameplayCamCoords())
|
||||
local dist = GetDistanceBetweenCoords(px, py, pz, x, y, z, true)
|
||||
local scale = (1 / dist) * 20
|
||||
local fov = (1 / GetGameplayCamFov()) * 100
|
||||
local scale = scale * fov
|
||||
SetTextScale(scaleX * scale, scaleY * scale)
|
||||
SetTextFont(fontId)
|
||||
SetTextProportional(1)
|
||||
SetTextDropshadow(1, 1, 1, 1, 255)
|
||||
SetTextEdge(2, 0, 0, 0, 150)
|
||||
SetTextDropShadow()
|
||||
SetTextOutline()
|
||||
SetTextEntry("STRING")
|
||||
SetTextCentre(1)
|
||||
AddTextComponentString(textInput)
|
||||
SetDrawOrigin(x, y, z, 0)
|
||||
DrawText(0.0, 0.0)
|
||||
ClearDrawOrigin()
|
||||
end
|
||||
@@ -0,0 +1,39 @@
|
||||
if Config.esxSettings.enabled then
|
||||
ESX = nil
|
||||
|
||||
|
||||
if Config.esxSettings.useNewESXExport then
|
||||
ESX = exports['es_extended']:getSharedObject()
|
||||
else
|
||||
Citizen.CreateThread(function()
|
||||
while ESX == nil do
|
||||
TriggerEvent('esx:getSharedObject', function(obj)
|
||||
ESX = obj
|
||||
end)
|
||||
Citizen.Wait(0)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
Citizen.CreateThread(function()
|
||||
while ESX == nil or ESX.GetPlayerData().job == nil do
|
||||
Citizen.Wait(10)
|
||||
end
|
||||
|
||||
ESX.PlayerData = ESX.GetPlayerData()
|
||||
TriggerServerEvent('kq_carheist:playerLoaded')
|
||||
end)
|
||||
|
||||
RegisterNetEvent('esx:setJob')
|
||||
AddEventHandler('esx:setJob', function(job)
|
||||
ESX.PlayerData.job = job
|
||||
ClearPoliceBlips()
|
||||
end)
|
||||
|
||||
function IsPolice()
|
||||
if not ESX.PlayerData.job then
|
||||
return false
|
||||
end
|
||||
return Contains(Config.policeJobNames, ESX.PlayerData.job.name)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,135 @@
|
||||
----------------------
|
||||
-- BLIPS
|
||||
----------------------
|
||||
local policeBlips = {}
|
||||
|
||||
RegisterNetEvent('kq_carheist:refreshPoliceAlarm')
|
||||
AddEventHandler('kq_carheist:refreshPoliceAlarm', function(trailerCoords, vehiclesCoords)
|
||||
ClearPoliceBlips()
|
||||
|
||||
if trailerCoords then
|
||||
RefreshPoliceTrailerAlarm(trailerCoords)
|
||||
end
|
||||
RefreshPoliceVehiclesAlarm(vehiclesCoords, trailerCoords)
|
||||
end)
|
||||
|
||||
function RefreshPoliceTrailerAlarm(trailerCoords)
|
||||
if trailerBlip ~= nil then
|
||||
RemoveBlip(trailerBlip)
|
||||
end
|
||||
|
||||
local blipConf = Config.policeBlip.truck.primary
|
||||
local primBlip = CreatePoliceBlip(trailerCoords, blipConf.sprite, blipConf.color, blipConf.alpha, blipConf.scale, L('Car transport robbery'), blipConf.shortRange)
|
||||
SetBlipDisplay(primBlip, 8)
|
||||
table.insert(policeBlips, primBlip)
|
||||
|
||||
blipConf = Config.policeBlip.truck.secondary
|
||||
local secBlip = CreatePoliceBlip(trailerCoords, blipConf.sprite, blipConf.color, blipConf.alpha, blipConf.scale, L('Car transport robbery'), blipConf.shortRange)
|
||||
table.insert(policeBlips, secBlip)
|
||||
|
||||
end
|
||||
|
||||
|
||||
function RefreshPoliceVehiclesAlarm(vehiclesCoords, trailerCoords)
|
||||
for k, veh in pairs(vehiclesCoords) do
|
||||
if not trailerCoords or GetDistanceBetweenCoords(trailerCoords, veh.coords, false) > 25.0 then
|
||||
|
||||
local blipConf = Config.policeBlip.vehicles.primary
|
||||
|
||||
|
||||
local distance = GetDistanceBetweenCoords(GetEntityCoords(PlayerPedId()), veh.coords, true)
|
||||
|
||||
local _, z = GetGroundZFor_3dCoord(veh.coords.x, veh.coords.y, 900.0, true)
|
||||
if z == 0.0 then
|
||||
z = GetHeightmapTopZForPosition(veh.coords.x, veh.coords.y)
|
||||
end
|
||||
|
||||
z = z - 6.0
|
||||
|
||||
if Config.policeBlip.makeTunnelsLowerSignal and distance > 10.0 and (IsInsideATunnel(veh.coords) or (Config.policeBlip.unknownTunnelChecking and z > veh.coords.z)) then
|
||||
math.randomseed(math.floor((veh.coords.x / 10) + (veh.coords.y / 10)))
|
||||
local newCoords = vector3(veh.coords.x + math.random(-130, 130), veh.coords.y + math.random(-130, 130), veh.coords.z)
|
||||
veh.coords = newCoords
|
||||
math.randomseed(GetGameTimer())
|
||||
|
||||
local tunnelBlip = CreateTunnelPoliceBlip(veh.coords, blipConf.color, blipConf.alpha)
|
||||
table.insert(policeBlips, tunnelBlip)
|
||||
else
|
||||
local primBlip = CreatePoliceBlip(veh.coords, blipConf.sprite, blipConf.color, blipConf.alpha, blipConf.scale, L('Stolen vehicle: ') .. veh.name, blipConf.shortRange)
|
||||
SetBlipDisplay(primBlip, 8)
|
||||
table.insert(policeBlips, primBlip)
|
||||
end
|
||||
|
||||
blipConf = Config.policeBlip.vehicles.secondary
|
||||
local secBlip = CreatePoliceBlip(veh.coords, blipConf.sprite, blipConf.color, blipConf.alpha, blipConf.scale, L('Stolen vehicle: ') .. veh.name, blipConf.shortRange)
|
||||
table.insert(policeBlips, secBlip)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function ClearPoliceBlips()
|
||||
for k, blip in pairs(policeBlips) do
|
||||
RemoveBlip(blip)
|
||||
end
|
||||
policeBlips = {}
|
||||
end
|
||||
|
||||
function RemovePoliceTrailerBlip()
|
||||
if trailerBlip then
|
||||
RemoveBlip(trailerBlip)
|
||||
end
|
||||
end
|
||||
|
||||
function CreatePoliceBlip(coords, sprite, color, alpha, scale, message, shortRange)
|
||||
local blip = AddBlipForCoord(coords)
|
||||
|
||||
SetBlipSprite(blip, sprite)
|
||||
SetBlipHighDetail(blip, true)
|
||||
SetBlipColour(blip, color)
|
||||
SetBlipAlpha(blip, alpha)
|
||||
SetBlipScale(blip, scale)
|
||||
BeginTextCommandSetBlipName('STRING')
|
||||
AddTextComponentString(message)
|
||||
EndTextCommandSetBlipName(blip)
|
||||
SetBlipAsShortRange(blip, shortRange)
|
||||
return blip
|
||||
end
|
||||
|
||||
|
||||
function CreateTunnelPoliceBlip(coords, color, alpha)
|
||||
local blip = AddBlipForRadius(coords, 300.0)
|
||||
|
||||
SetBlipHighDetail(blip, true)
|
||||
SetBlipColour(blip, color)
|
||||
SetBlipAlpha(blip, alpha)
|
||||
SetBlipAsShortRange(blip, true)
|
||||
return blip
|
||||
end
|
||||
|
||||
|
||||
----------------------
|
||||
-- DISPATCH MESSAGES
|
||||
----------------------
|
||||
|
||||
function EndPoliceAlarm()
|
||||
if trailerBlip ~= nil then
|
||||
RemovePoliceTrailerBlip()
|
||||
SendDispatchMessage(L('Our truck has arrived to its destination. Thank you for your assistance'), L('Truck arrived'))
|
||||
end
|
||||
end
|
||||
|
||||
function SendDispatchMessage(message, subtitle)
|
||||
BeginTextCommandThefeedPost("STRING")
|
||||
AddTextComponentSubstringPlayerName(message)
|
||||
|
||||
-- Set the notification icon, title and subtitle.
|
||||
local title = L('Car Transports Inc.')
|
||||
local iconType = 0
|
||||
local flash = false -- Flash doesn't seem to work no matter what.
|
||||
EndTextCommandThefeedPostMessagetext("CHAR_CARSITE", "CHAR_CARSITE", flash, iconType, title, subtitle)
|
||||
|
||||
-- Draw the notification
|
||||
local showInBrief = true
|
||||
local blink = false -- blink doesn't work when using icon notifications.
|
||||
EndTextCommandThefeedPostTicker(blink, showInBrief)
|
||||
end
|
||||
@@ -0,0 +1,40 @@
|
||||
if Config.qbSettings.enabled then
|
||||
if Config.qbSettings.useNewQBExport then
|
||||
QBCore = exports['qb-core']:GetCoreObject()
|
||||
end
|
||||
|
||||
job = QBCore.Functions.GetPlayerData().job
|
||||
gang = QBCore.Functions.GetPlayerData().gang
|
||||
|
||||
RegisterNetEvent('QBCore:Client:OnPlayerLoaded')
|
||||
AddEventHandler('QBCore:Client:OnPlayerLoaded', function()
|
||||
job = QBCore.Functions.GetPlayerData().job
|
||||
gang = QBCore.Functions.GetPlayerData().gang
|
||||
TriggerServerEvent('kq_carheist:playerLoaded')
|
||||
end)
|
||||
|
||||
|
||||
RegisterNetEvent('QBCore:Client:OnJobUpdate')
|
||||
AddEventHandler('QBCore:Client:OnJobUpdate', function(JobInfo)
|
||||
job = JobInfo
|
||||
end)
|
||||
|
||||
RegisterNetEvent('QBCore:Client:OnGangUpdate')
|
||||
AddEventHandler('QBCore:Client:OnGangUpdate', function(GangInfo)
|
||||
gang = GangInfo
|
||||
end)
|
||||
|
||||
function IsPolice()
|
||||
if not job then
|
||||
return false
|
||||
end
|
||||
return Contains(Config.policeJobNames, job.name)
|
||||
end
|
||||
|
||||
function IsInGang()
|
||||
if not gang then
|
||||
return false
|
||||
end
|
||||
return gang.name ~= nil and gang.name ~= 'none' and gang.name ~= ''
|
||||
end
|
||||
end
|
||||
1052
resources/[framework]/[addons]/[kq]/kq_carheist/client/functions.lua
Normal file
1052
resources/[framework]/[addons]/[kq]/kq_carheist/client/functions.lua
Normal file
File diff suppressed because it is too large
Load Diff
687
resources/[framework]/[addons]/[kq]/kq_carheist/config.lua
Normal file
687
resources/[framework]/[addons]/[kq]/kq_carheist/config.lua
Normal file
@@ -0,0 +1,687 @@
|
||||
Config = {}
|
||||
|
||||
-- Enables debug statements which will print in consoles
|
||||
-- Also enabled a command /cheist which will forcefully spawn a new heist even if one is already happening
|
||||
-- Do not enable this unless asked to by a KuzQuality staff member or you know what you're doing
|
||||
Config.debug = false
|
||||
|
||||
-- Experimental method of syncing the trucks between players
|
||||
Config.experimentalSync = false
|
||||
|
||||
--------------------------------------------------------
|
||||
--------------------------------------------------------
|
||||
--- MAKE SURE THAT THE CORRECT FRAMEWORK IS ENABLED ! --
|
||||
--------------------------------------------------------
|
||||
--------------------------------------------------------
|
||||
|
||||
--- SETTINGS FOR ESX
|
||||
Config.esxSettings = {
|
||||
enabled = false,
|
||||
-- Whether or not to use the new ESX export method
|
||||
useNewESXExport = true,
|
||||
-- Account on which players will receive their money after successfully dropping off their vehicle
|
||||
moneyAccount = 'black_money',
|
||||
}
|
||||
|
||||
--- SETTINGS FOR QBCORE
|
||||
Config.qbSettings = {
|
||||
enabled = true,
|
||||
-- If you're using an old QBCore version set this to 'false' and uncomment the old export in fxmanifest.lua
|
||||
useNewQBExport = true,
|
||||
-- Account on which players will receive their money after successfully dropping off their vehicle
|
||||
-- Using 'crypto' for dirty money feel; change to 'cash' or 'bank' as needed
|
||||
moneyAccount = 'cash'
|
||||
}
|
||||
|
||||
-- Minimum police officers that have to be online to allow spawning of the heist truck
|
||||
Config.minimumOfficers = 3
|
||||
|
||||
-- Whether the player must be in a gang to interact with the heist
|
||||
Config.requireGang = true
|
||||
|
||||
|
||||
-- How often the truck should be spawned (In minutes)
|
||||
-- If any players are still near the old truck new one won't be spawned
|
||||
-- Set to 45 minutes for RP pacing - prevents heist spam
|
||||
Config.heistSpawnTime = 45
|
||||
|
||||
-- Whether or not to announce the truck spawning to all players (Besides police officers)
|
||||
Config.announceTruckDepartureToPlayers = true
|
||||
|
||||
-- Announcement blip
|
||||
Config.announcementBlip = {
|
||||
-- How long the blip will stay on the map
|
||||
duration = 15000,
|
||||
primary = {
|
||||
sprite = 161,
|
||||
color = 47,
|
||||
scale = 2.0,
|
||||
alpha = 150,
|
||||
shortRange = true,
|
||||
},
|
||||
secondary = {
|
||||
sprite = 477,
|
||||
color = 47,
|
||||
scale = 1.3,
|
||||
alpha = 255,
|
||||
shortRange = true,
|
||||
},
|
||||
}
|
||||
|
||||
-- Whether or not to use audible vehicle alarms
|
||||
Config.useVehicleAlarm = true
|
||||
|
||||
-- Bike jump config
|
||||
Config.bikeJump = {
|
||||
enabled = true,
|
||||
keybind = 'X'
|
||||
}
|
||||
|
||||
|
||||
-- Whether or not to require a item to open the trailer
|
||||
Config.requireTool = true
|
||||
-- item names that will allow players to open the ramp of the trailer
|
||||
Config.cuttingTools = {
|
||||
'kq_angle_grinder'
|
||||
}
|
||||
-- Amount of key presses required to open the latch/ramp (Set it higher to make it take longer)
|
||||
Config.latchCuttingDuration = 15
|
||||
-- Keys used for the angle grinder / cutting the latches
|
||||
Config.grinderKeys = { 'W', 'A', 'S', 'D', 'G' }
|
||||
|
||||
Config.tracker = {
|
||||
-- How long it will take to search one spot on the vehicle (in ms)
|
||||
searchDuration = 15000,
|
||||
-- How many times the player has to press the keys to unscrew the tracker
|
||||
removalLength = 50,
|
||||
-- Time that players will need to wait when they misclick "drop the screwdriver" (in ms)
|
||||
removalMessedUpDuration = 6000,
|
||||
-- Keys used to unscrew the tracker
|
||||
removalKeybinds = {
|
||||
'A',
|
||||
'W',
|
||||
'D',
|
||||
'S'
|
||||
},
|
||||
-- For how long the GPS location is going to be visible for police after tracker gets removed (in ms)
|
||||
stayOnMapAfterRemovalTime = 90000,
|
||||
}
|
||||
|
||||
-- Name of the job(s) which will receive the alerts
|
||||
Config.policeJobNames = {
|
||||
'police'
|
||||
}
|
||||
|
||||
Config.policeBlip = {
|
||||
-- How often the trackers locations should be updated (Don't recommend putting it too low) (in ms)
|
||||
refreshTime = 5000,
|
||||
-- Whether or not to allow tunnels and underground areas to lower the accuracy of the tracker
|
||||
makeTunnelsLowerSignal = true,
|
||||
-- Check which works better for detection of tunnels but makes all trackers which are far away
|
||||
-- from the officer display as if the tracker is in a tunnel (Still recommended)
|
||||
unknownTunnelChecking = true,
|
||||
truck = {
|
||||
primary = {
|
||||
sprite = 161,
|
||||
color = 47,
|
||||
scale = 2.0,
|
||||
alpha = 150,
|
||||
shortRange = false,
|
||||
},
|
||||
secondary = {
|
||||
sprite = 477,
|
||||
color = 47,
|
||||
scale = 1.3,
|
||||
alpha = 255,
|
||||
shortRange = false,
|
||||
}
|
||||
},
|
||||
vehicles = {
|
||||
primary = {
|
||||
sprite = 161,
|
||||
color = 49,
|
||||
scale = 1.0,
|
||||
alpha = 150,
|
||||
shortRange = false,
|
||||
},
|
||||
secondary = {
|
||||
sprite = 595,
|
||||
color = 49,
|
||||
scale = 1.0,
|
||||
alpha = 255,
|
||||
shortRange = false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-- ADVANCED! If you don't know what this does. Do not change it.
|
||||
Config.truckDriveStyle = 1074528293
|
||||
|
||||
-- Speed the truck will drive at (I don't recommend putting it above 30.0)
|
||||
Config.truckDriveSpeed = 20.0
|
||||
-- Color of the heist truck
|
||||
Config.truckColor = { r = 255, g = 60, b = 10 }
|
||||
|
||||
|
||||
-- All possible routes that the truck can spawn on and take
|
||||
-- (Be careful when adding new ones. Make sure that the NPC knows how to drive the route (test it))
|
||||
Config.startLocations = {
|
||||
{
|
||||
truck = { x = 1541.56, y = 854.07, z = 77.5, h = 329.0 },
|
||||
support = { x = 1524.74, y = 822.16, z = 77.5, h = 328.0 },
|
||||
finish = { x = 138.46, y = 6414.1, z = 26.13, h = 261.80 },
|
||||
},
|
||||
{
|
||||
truck = { x = -2875.27, y = 2188.37, z = 35.23, h = 129.0 },
|
||||
support = { x = -2841.30, y = 2207.92, z = 31.11, h = 121.19 },
|
||||
finish = { x = 2506.23, y = -280.09, z = 93.05, h = 91.77 },
|
||||
},
|
||||
{
|
||||
truck = { x = -1947.37, y = -337.79, z = 46.23, h = 280.77 },
|
||||
support = { x = -1980.10, y = -311.63, z = 43.65, h = 231.09 },
|
||||
finish = { x = -680.03, y = 5761.55, z = 16.88, h = 304.37 },
|
||||
},
|
||||
{
|
||||
truck = { x = 1156.20, y = -1695.16, z = 35.65, h = 164.31 },
|
||||
support = { x = 1165.83, y = -1669.85, z = 36.45, h = 150.35 },
|
||||
finish = { x = 138.46, y = 6414.1, z = 26.13, h = 261.80 },
|
||||
},
|
||||
{
|
||||
truck = { x = 2666.48, y = 3454.13, z = 55.73, h = 247.0 },
|
||||
support = { x = 2636.36, y = 3462.57, z = 55.37, h = 244.77 },
|
||||
finish = { x = 1379.78, y = -2068.52, z = 51.99, h = 156.80 },
|
||||
},
|
||||
}
|
||||
|
||||
-- Whether or not to reduce the drop off reward based on how damaged the vehicle is
|
||||
Config.reduceRewardByVehicleDamage = true
|
||||
-- How much percentage to remove off the vehicle price based on damage (0% nothing, 100% cars which have 0 health will pay $0)
|
||||
-- Set to 80% - forces careful driving for RP; damaged cars are worth much less
|
||||
Config.reduceByDamagePercentage = 80
|
||||
Config.dropOff = {
|
||||
-- Minimum amount of available drop off locations per heist
|
||||
minLocations = 2,
|
||||
-- Maximum amount of available drop off locations per heist
|
||||
maxLocations = 3,
|
||||
-- Whether or not to (almost) instantly delete the vehicle when dropping it off
|
||||
instantlyDeleteVehicle = false,
|
||||
blips = {
|
||||
primary = {
|
||||
sprite = 161,
|
||||
color = 46,
|
||||
scale = 1.0,
|
||||
alpha = 150,
|
||||
shortRange = false,
|
||||
},
|
||||
secondary = {
|
||||
sprite = 524,
|
||||
color = 46,
|
||||
scale = 1.0,
|
||||
alpha = 255,
|
||||
shortRange = false,
|
||||
}
|
||||
},
|
||||
-- All available drop off locations
|
||||
locations = {
|
||||
{ x = 1274.95, y = -3239.77, z = 5.88 },
|
||||
{ x = -302.86, y = -2723.41, z = 6.01 },
|
||||
{ x = -371.68, y = -2273.67, z = 7.60 },
|
||||
{ x = 452.45, y = -2755.19, z = 6.05 },
|
||||
{ x = -450.44, y = -2442.52, z = 6.00 },
|
||||
{ x = 489.70, y = -2227.92, z = 5.91 },
|
||||
{ x = -161.13, y = 928.02, z = 235.65 },
|
||||
{ x = 2469.17, y = 1589.04, z = 32.72 },
|
||||
{ x = 363.70, y = 3411.08, z = 36.40 },
|
||||
{ x = 3803.85, y = 4451.05, z = 4.25 },
|
||||
{ x = 2150.34, y = 4797.62, z = 41.13 },
|
||||
{ x = 1905.25, y = 4924.22, z = 48.87 },
|
||||
{ x = -197.12, y = 6536.59, z = 11.09 },
|
||||
{ x = -1585.75, y = 5157.74, z = 19.57 },
|
||||
{ x = 143.53, y = -2445.9, z = 5.99 },
|
||||
{ x = -38.46, y = -2547.16, z = 6.00 },
|
||||
{ x = -224.98, y = -2657.44, z = 6.00 },
|
||||
{ x = -566.59, y = -2341.45, z = 13.83 },
|
||||
{ x = -853.87, y = -1257.78, z = 4.99 },
|
||||
{ x = -81.51, y = 361.99, z = 112.46 },
|
||||
{ x = -1558.67, y = -247,35, z = 48.28 },
|
||||
},
|
||||
}
|
||||
|
||||
-- Color of the support vehicle
|
||||
Config.supportColor = { r = 0, g = 0, b = 0 }
|
||||
|
||||
-- Possible vehicle models for the support vehicle
|
||||
Config.supportVehicles = {
|
||||
'baller2',
|
||||
'kuruma',
|
||||
'buffalo2',
|
||||
'dubsta2',
|
||||
'stanier',
|
||||
'tailgater',
|
||||
}
|
||||
|
||||
-- Ped models that the support can have
|
||||
Config.supportPeds = {
|
||||
's_m_m_chemsec_01'
|
||||
}
|
||||
|
||||
|
||||
-- How much health all the npcs will have (normal npc's have 100)
|
||||
-- Increased for RP difficulty - guards are trained professionals
|
||||
Config.npcHealth = 250
|
||||
|
||||
-- Whether or not all the npcs suffer from critical hits (aka headshots)
|
||||
-- Enabled for realism - headshots should matter in RP
|
||||
Config.npcSuffersCriticalHits = true
|
||||
|
||||
-- Integer between 0 and 100
|
||||
-- Below 20 they barely hit, above 80 incredible aim
|
||||
-- Set to 55 for challenging but fair RP encounters
|
||||
Config.npcShootingAccuracy = 55
|
||||
|
||||
-- Chance of NPC's having a weapon (100% - armed transport convoy)
|
||||
Config.weaponChance = 100
|
||||
|
||||
Config.weapons = {
|
||||
'weapon_minismg',
|
||||
'weapon_snspistol',
|
||||
'weapon_combatpistol'
|
||||
}
|
||||
|
||||
|
||||
|
||||
------------------------------------------------------------------------
|
||||
-- chance = the chance of the event spawning
|
||||
-- trucks = list of all truck models that can be used
|
||||
-- npcs = list of all npc models that can be used (driver and passenger)
|
||||
-- passengerChance = the chance of the truck having a passenger
|
||||
-- bulletproofTiresChance = the chance of all heist vehicles having bullet proof tires
|
||||
-- vehicleSlotChance = the chance of a vehicle spawning in a trailer slot (there always is at least 1 vehicle)
|
||||
-- supportChance = the chance of the support vehicle spawning
|
||||
-- minimumVehicles = the minimum amount of the vehicles on the trailer (max 3)
|
||||
-- vehicles = {
|
||||
-- name = Vehicle name
|
||||
-- model = Vehicle model
|
||||
-- price = The max amount of money the players will get for dropping off the vehicle
|
||||
-- }
|
||||
---------------------------------------------------------------------------
|
||||
--- Chances of all events must add up to 100 !
|
||||
Config.events = {
|
||||
{
|
||||
chance = 20,
|
||||
trucks = {
|
||||
'phantom3'
|
||||
},
|
||||
npcs = {
|
||||
's_m_m_chemsec_01'
|
||||
},
|
||||
passengerChance = 100,
|
||||
bulletproofTiresChance = 100,
|
||||
vehicleSlotChance = 70,
|
||||
supportChance = 100,
|
||||
minimumVehicles = 1,
|
||||
vehicles = {
|
||||
{
|
||||
name = 'Adder',
|
||||
model = 'adder',
|
||||
price = 40000,
|
||||
},
|
||||
{
|
||||
name = 'Entity XF',
|
||||
model = 'entityxf',
|
||||
price = 35000,
|
||||
},
|
||||
{
|
||||
name = 'Furia',
|
||||
model = 'furia',
|
||||
price = 45000,
|
||||
},
|
||||
{
|
||||
name = 'Nero Custom',
|
||||
model = 'nero2',
|
||||
price = 52000,
|
||||
},
|
||||
{
|
||||
name = 'Nero',
|
||||
model = 'nero',
|
||||
price = 44000,
|
||||
},
|
||||
{
|
||||
name = 'Cyclone',
|
||||
model = 'cyclone',
|
||||
price = 45000,
|
||||
},
|
||||
{
|
||||
name = 'T20',
|
||||
model = 't20',
|
||||
price = 40000,
|
||||
},
|
||||
{
|
||||
name = 'Vacca',
|
||||
model = 'vacca',
|
||||
price = 29000,
|
||||
},
|
||||
{
|
||||
name = 'Bullet',
|
||||
model = 'bullet',
|
||||
price = 28000,
|
||||
},
|
||||
{
|
||||
name = 'Itali GTB',
|
||||
model = 'italigtb',
|
||||
price = 33000,
|
||||
},
|
||||
{
|
||||
name = 'Itali GTB Custom',
|
||||
model = 'italigtb2',
|
||||
price = 38000,
|
||||
},
|
||||
{
|
||||
name = 'Visione',
|
||||
model = 'visione',
|
||||
price = 49000,
|
||||
},
|
||||
{
|
||||
name = 'SC1',
|
||||
model = 'SC1',
|
||||
price = 40000,
|
||||
},
|
||||
{
|
||||
name = 'Taipan',
|
||||
model = 'taipan',
|
||||
price = 47000,
|
||||
},
|
||||
{
|
||||
name = 'Thrax',
|
||||
model = 'thrax',
|
||||
price = 55000,
|
||||
},
|
||||
{
|
||||
name = 'Emerus',
|
||||
model = 'emerus',
|
||||
price = 51000,
|
||||
},
|
||||
{
|
||||
name = 'Entity XXR',
|
||||
model = 'entity2',
|
||||
price = 54000,
|
||||
},
|
||||
{
|
||||
name = 'Reaper',
|
||||
model = 'reaper',
|
||||
price = 41000,
|
||||
},
|
||||
{
|
||||
name = 'Voltic',
|
||||
model = 'voltic',
|
||||
price = 30000,
|
||||
},
|
||||
{
|
||||
name = '811',
|
||||
model = 'pfister811',
|
||||
price = 39000,
|
||||
},
|
||||
{
|
||||
name = 'Lynx',
|
||||
model = 'lynx',
|
||||
price = 32000,
|
||||
},
|
||||
{
|
||||
name = 'Autarch',
|
||||
model = 'autarch',
|
||||
price = 44000,
|
||||
},
|
||||
{
|
||||
name = 'XA-21',
|
||||
model = 'xa21',
|
||||
price = 40000,
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
chance = 35,
|
||||
trucks = {
|
||||
'phantom3',
|
||||
'phantom',
|
||||
'hauler',
|
||||
'packer',
|
||||
},
|
||||
npcs = {
|
||||
's_m_m_chemsec_01'
|
||||
},
|
||||
passengerChance = 80,
|
||||
bulletproofTiresChance = 40,
|
||||
vehicleSlotChance = 70,
|
||||
supportChance = 40,
|
||||
minimumVehicles = 2,
|
||||
vehicles = {
|
||||
{
|
||||
name = 'Sultan RS',
|
||||
model = 'sultanrs',
|
||||
price = 25000,
|
||||
},
|
||||
{
|
||||
name = 'Schlagen',
|
||||
model = 'schlagen',
|
||||
price = 30000,
|
||||
},
|
||||
{
|
||||
name = 'Jester Classic',
|
||||
model = 'jester3',
|
||||
price = 28000,
|
||||
},
|
||||
{
|
||||
name = 'Comet',
|
||||
model = 'comet2',
|
||||
price = 22000,
|
||||
},
|
||||
{
|
||||
name = 'Comet Retro',
|
||||
model = 'comet3',
|
||||
price = 27000,
|
||||
},
|
||||
{
|
||||
name = 'Verlierer',
|
||||
model = 'verlierer2',
|
||||
price = 30000,
|
||||
},
|
||||
{
|
||||
name = 'Omnis',
|
||||
model = 'omnis',
|
||||
price = 33000,
|
||||
},
|
||||
{
|
||||
name = 'Kuruma',
|
||||
model = 'kuruma',
|
||||
price = 24000,
|
||||
},
|
||||
{
|
||||
name = 'Space Monkey Blista',
|
||||
model = 'blista3',
|
||||
price = 25000,
|
||||
},
|
||||
{
|
||||
name = 'Coquette',
|
||||
model = 'coquette',
|
||||
price = 25000,
|
||||
},
|
||||
{
|
||||
name = 'Banshee',
|
||||
model = 'banshee',
|
||||
price = 26000,
|
||||
},
|
||||
{
|
||||
name = '9F',
|
||||
model = 'ninef',
|
||||
price = 26000,
|
||||
},
|
||||
{
|
||||
name = 'Massacro',
|
||||
model = 'massacro',
|
||||
price = 26000,
|
||||
},
|
||||
{
|
||||
name = 'Massacro Race car',
|
||||
model = 'massacro2',
|
||||
price = 33000,
|
||||
},
|
||||
{
|
||||
name = 'Dominator GTX',
|
||||
model = 'dominator3',
|
||||
price = 29000,
|
||||
},
|
||||
{
|
||||
name = 'Brioso R/A',
|
||||
model = 'brioso',
|
||||
price = 22000,
|
||||
},
|
||||
{
|
||||
name = 'F620',
|
||||
model = 'f620',
|
||||
price = 23000,
|
||||
},
|
||||
{
|
||||
name = 'Elegy Classic',
|
||||
model = 'elegy',
|
||||
price = 30000,
|
||||
},
|
||||
{
|
||||
name = 'Ruston',
|
||||
model = 'ruston',
|
||||
price = 26000,
|
||||
},
|
||||
{
|
||||
name = 'Flash GT',
|
||||
model = 'flashgt',
|
||||
price = 27000,
|
||||
},
|
||||
{
|
||||
name = 'Elegy RH8',
|
||||
model = 'elegy2',
|
||||
price = 32000,
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
chance = 25,
|
||||
trucks = {
|
||||
'phantom3'
|
||||
},
|
||||
npcs = {
|
||||
's_m_m_chemsec_01'
|
||||
},
|
||||
passengerChance = 100,
|
||||
bulletproofTiresChance = 100,
|
||||
vehicleSlotChance = 40,
|
||||
supportChance = 100,
|
||||
minimumVehicles = 1,
|
||||
vehicles = {
|
||||
{
|
||||
name = 'Turismo Classic',
|
||||
model = 'turismo2',
|
||||
price = 60000,
|
||||
},
|
||||
{
|
||||
name = 'JB700W',
|
||||
model = 'jb7002',
|
||||
price = 53000,
|
||||
},
|
||||
{
|
||||
name = 'Torero',
|
||||
model = 'torero',
|
||||
price = 54000,
|
||||
},
|
||||
{
|
||||
name = 'Cheburek',
|
||||
model = 'cheburek',
|
||||
price = 15000,
|
||||
},
|
||||
{
|
||||
name = 'Dynasty',
|
||||
model = 'dynasty',
|
||||
price = 42000,
|
||||
},
|
||||
{
|
||||
name = 'Monroe',
|
||||
model = 'monroe',
|
||||
price = 40000,
|
||||
},
|
||||
{
|
||||
name = 'Swinger',
|
||||
model = 'swinger',
|
||||
price = 44000,
|
||||
},
|
||||
{
|
||||
name = 'Cheetah Classic',
|
||||
model = 'cheetah2',
|
||||
price = 62000,
|
||||
},
|
||||
{
|
||||
name = 'Infernus Classic',
|
||||
model = 'infernus2',
|
||||
price = 61000,
|
||||
},
|
||||
{
|
||||
name = 'Rapid GT Classic',
|
||||
model = 'rapidgt3',
|
||||
price = 26000,
|
||||
},
|
||||
{
|
||||
name = 'Savestra',
|
||||
model = 'savestra',
|
||||
price = 27000,
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
chance = 20,
|
||||
trucks = {
|
||||
'phantom3'
|
||||
},
|
||||
npcs = {
|
||||
's_m_m_chemsec_01'
|
||||
},
|
||||
passengerChance = 100,
|
||||
bulletproofTiresChance = 100,
|
||||
vehicleSlotChance = 45,
|
||||
supportChance = 80,
|
||||
minimumVehicles = 1,
|
||||
vehicles = {
|
||||
{
|
||||
name = 'Comet Safari',
|
||||
model = 'comet4',
|
||||
price = 45000,
|
||||
},
|
||||
{
|
||||
name = 'Drag Tornado',
|
||||
model = 'tornado6',
|
||||
price = 47000,
|
||||
},
|
||||
{
|
||||
name = 'Apocalypse Issi',
|
||||
model = 'issi4',
|
||||
price = 37000,
|
||||
},
|
||||
{
|
||||
name = 'Drift Yosemite',
|
||||
model = 'yosemite2',
|
||||
price = 51000,
|
||||
},
|
||||
{
|
||||
name = 'Lowrider Primo',
|
||||
model = 'primo2',
|
||||
price = 42000,
|
||||
},
|
||||
{
|
||||
name = 'JB700',
|
||||
model = 'jb700',
|
||||
price = 58000,
|
||||
},
|
||||
{
|
||||
name = 'Raptor',
|
||||
model = 'raptor',
|
||||
price = 35000,
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
fx_version 'cerulean'
|
||||
games { 'gta5' }
|
||||
lua54 'yes'
|
||||
|
||||
author 'KuzQuality | Kuzkay'
|
||||
description 'Car Heist by KuzQuality'
|
||||
version '1.0.14'
|
||||
|
||||
|
||||
-- UNCOMMENT IF YOU'RE USING OLD QB CORE EXPORT
|
||||
--shared_script '@qb-core/import.lua'
|
||||
|
||||
|
||||
--
|
||||
-- Server
|
||||
--
|
||||
|
||||
server_scripts {
|
||||
'locale/locale.lua',
|
||||
'config.lua',
|
||||
'shared/settings.lua',
|
||||
'server/editable/esx.lua',
|
||||
'server/editable/qb.lua',
|
||||
'server/server.lua',
|
||||
'server/functions.lua',
|
||||
'server/editable/editable.lua',
|
||||
}
|
||||
|
||||
--
|
||||
-- Client
|
||||
--
|
||||
|
||||
client_scripts {
|
||||
'locale/locale.lua',
|
||||
'config.lua',
|
||||
'shared/settings.lua',
|
||||
'client/editable/esx.lua',
|
||||
'client/editable/qb.lua',
|
||||
'client/functions.lua',
|
||||
'client/client.lua',
|
||||
'client/bikeJump.lua',
|
||||
'client/editable/editable.lua',
|
||||
'client/editable/policeAlert.lua',
|
||||
}
|
||||
|
||||
escrow_ignore {
|
||||
'config.lua',
|
||||
'locale/locale.lua',
|
||||
'client/editable/editable.lua',
|
||||
'client/editable/policeAlert.lua',
|
||||
'client/editable/qb.lua',
|
||||
'client/editable/esx.lua',
|
||||
'client/functions.lua',
|
||||
'server/editable/editable.lua',
|
||||
'server/editable/esx.lua',
|
||||
'server/editable/qb.lua',
|
||||
'server/server.lua',
|
||||
}
|
||||
|
||||
dependency '/assetpacks'
|
||||
@@ -0,0 +1,41 @@
|
||||
-- To edit the messages edit the ones on the right side, not the ones inside the square brackets.
|
||||
-- ~r~ e.g. are colors. ~r~ being red, ~b~ being blue, ~y~ yellow etc.
|
||||
|
||||
|
||||
Locale = {
|
||||
['Car transport truck is currently departing.\nI\'ll pay top dollar if you can get them'] = 'Un transport de masini tocmai a plecat.\nPlatesc bine daca reusesti sa le aduci',
|
||||
['Martin'] = 'Martin',
|
||||
['Car collector'] = 'Colectionar de masini',
|
||||
['Car transport'] = 'Transport de masini',
|
||||
['Press ~w~[{keybinds}~w~] to unscrew'] = 'Apasa ~w~[{keybinds}~w~] pentru a desuruba',
|
||||
['~r~You dropped the screwdriver'] = '~r~Ai scapat surubelnita',
|
||||
['~w~Press [~r~E~w~] to force the ramp down'] = '~w~Apasa [~r~E~w~] pentru a forta rampa',
|
||||
['~w~Press [~r~E~w~] to cancel'] = '~w~Apasa [~r~E~w~] pentru a anula',
|
||||
['Cutting the latches...'] = 'Se taie incuietorile...',
|
||||
['~w~Press [~r~{keybinds}~w~] to continue cutting'] = '~w~Apasa [~r~{keybinds}~w~] pentru a continua taierea',
|
||||
['~w~Press [~r~E~w~] to climb up'] = '~w~Apasa [~r~E~w~] pentru a urca',
|
||||
['~w~Press [~r~{keybind}~w~] to attempt a jump'] = '~w~Apasa [~r~{keybind}~w~] pentru a incerca o saritura',
|
||||
['~y~! DANGEROUS !'] = '~y~! PERICULOS !',
|
||||
['Car transport robbery'] = 'Jaf transport de masini',
|
||||
['~r~You don\'t have anything that could be used to open this'] = '~r~Nu ai nimic cu care sa deschizi asta',
|
||||
['Our car transport is under attack! Coordinates have been shared!'] = 'Transportul nostru de masini este atacat! Coordonatele au fost distribuite!',
|
||||
['Car Transports Inc.'] = 'Car Transports Inc.',
|
||||
['Robbery in progress'] = 'Jaf in desfasurare',
|
||||
['Truck arrived'] = 'Camionul a ajuns',
|
||||
['Our truck has arrived to its destination. Thank you for your assistance'] = 'Camionul nostru a ajuns la destinatie. Va multumim pentru asistenta',
|
||||
['You need to remove the vehicle ~r~tracker ~w~before you sell it'] = 'Trebuie sa scoti ~r~trackerul ~w~de pe vehicul inainte sa il vinzi',
|
||||
['Stolen vehicle: '] = 'Vehicul furat: ',
|
||||
['~w~Press [~r~E~w~] to check for a tracker'] = '~w~Apasa [~r~E~w~] pentru a cauta un tracker',
|
||||
['~w~Searching for a tracking device'] = '~w~Se cauta un dispozitiv de urmarire',
|
||||
['~g~Tracking device found!'] = '~g~Dispozitiv de urmarire gasit!',
|
||||
['Deliver the ~g~{vehicle}~w~ to one of the drop off points'] = 'Livreaza ~g~{vehicle}~w~ la unul dintre punctele de predare',
|
||||
['Stolen vehicle drop off point'] = 'Punct de predare vehicul furat',
|
||||
['Vehicle dropped off'] = 'Vehicul predat',
|
||||
['You made ~g~${reward}'] = 'Ai castigat ~g~${reward}',
|
||||
['You made ~g~${reward}\n~r~${losses} deducted due to vehicle damage'] = 'Ai castigat ~g~${reward}\n~r~${losses} deduse din cauza daunelor vehiculului',
|
||||
['~w~Press [~r~E~w~] to drop off the vehicle'] = '~w~Apasa [~r~E~w~] pentru a preda vehiculul',
|
||||
|
||||
-- Gang & police requirement messages
|
||||
['~r~You must be in a gang to participate in this heist'] = '~r~Trebuie sa faci parte dintr-un gang pentru a participa la acest jaf',
|
||||
['~r~Not enough police officers online (minimum: {count})'] = '~r~Nu sunt suficienti politisti online (minim: {count})',
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
function OnHeistCreated()
|
||||
|
||||
end
|
||||
|
||||
function OnVehicleStartDroppingOff(source, vehEntity)
|
||||
-- Server-side gang check: prevent non-gang members from dropping off stolen vehicles
|
||||
if Config.requireGang and not IsInGang(source) then
|
||||
TriggerClientEvent('kq_carheist:gangCheckFailed', source)
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
function OnVehicleDroppedOff(source, vehicle, reward)
|
||||
|
||||
end
|
||||
|
||||
function OnTrackerRemoved(source, coords)
|
||||
|
||||
end
|
||||
|
||||
|
||||
----------------------
|
||||
-- TRACKERS
|
||||
----------------------
|
||||
RegisterServerEvent('kq_carheist:removeTracker')
|
||||
AddEventHandler('kq_carheist:removeTracker', function(vehKey, coords)
|
||||
sellableVehicles[vehKey].tracker = false
|
||||
sellableVehicles[vehKey].trackerCoords = coords
|
||||
TriggerClientEvent('kq_carheist:syncSellableVehicles', -1, sellableVehicles)
|
||||
Citizen.CreateThread(function()
|
||||
Citizen.Wait(Config.tracker.stayOnMapAfterRemovalTime)
|
||||
if sellableVehicles[vehKey] then
|
||||
sellableVehicles[vehKey].trackerCoords = nil
|
||||
end
|
||||
end)
|
||||
|
||||
OnTrackerRemoved(source, coords)
|
||||
end)
|
||||
@@ -0,0 +1,45 @@
|
||||
if Config.esxSettings.enabled then
|
||||
ESX = nil
|
||||
|
||||
if Config.esxSettings.useNewESXExport then
|
||||
ESX = exports['es_extended']:getSharedObject()
|
||||
else
|
||||
TriggerEvent('esx:getSharedObject', function(obj) ESX = obj end)
|
||||
end
|
||||
|
||||
function HasItem(player, item)
|
||||
local xPlayer = ESX.GetPlayerFromId(player)
|
||||
|
||||
return xPlayer.getInventoryItem(item).count >= 1
|
||||
end
|
||||
|
||||
function IsPolice(player)
|
||||
local xPlayer = ESX.GetPlayerFromId(player)
|
||||
if not xPlayer then
|
||||
return false
|
||||
end
|
||||
local job = xPlayer.getJob()
|
||||
|
||||
return Contains(Config.policeJobNames, job.name)
|
||||
end
|
||||
|
||||
function GetPoliceCount()
|
||||
local currentOfficers = 0
|
||||
for _, playerId in ipairs(GetPlayers()) do
|
||||
playerId = tonumber(playerId)
|
||||
if IsPolice(playerId) then
|
||||
currentOfficers = currentOfficers + 1
|
||||
end
|
||||
end
|
||||
return currentOfficers
|
||||
end
|
||||
|
||||
function AddMoney(player, amount)
|
||||
local xPlayer = ESX.GetPlayerFromId(player)
|
||||
if not xPlayer then
|
||||
return false
|
||||
end
|
||||
|
||||
xPlayer.addAccountMoney(Config.esxSettings.moneyAccount, amount)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,57 @@
|
||||
if Config.qbSettings.enabled then
|
||||
if Config.qbSettings.useNewQBExport then
|
||||
QBCore = exports['qb-core']:GetCoreObject()
|
||||
end
|
||||
|
||||
function HasItem(player, item)
|
||||
local xPlayer = QBCore.Functions.GetPlayer(player)
|
||||
|
||||
return xPlayer.Functions.GetItemByName(item)
|
||||
end
|
||||
|
||||
function IsPolice(player)
|
||||
local xPlayer = QBCore.Functions.GetPlayer(player)
|
||||
if not xPlayer then
|
||||
return false
|
||||
end
|
||||
|
||||
local job = xPlayer.PlayerData.job
|
||||
|
||||
return Contains(Config.policeJobNames, job.name)
|
||||
end
|
||||
|
||||
function IsInGang(player)
|
||||
local xPlayer = QBCore.Functions.GetPlayer(player)
|
||||
if not xPlayer then
|
||||
return false
|
||||
end
|
||||
|
||||
local gang = xPlayer.PlayerData.gang
|
||||
if not gang then
|
||||
return false
|
||||
end
|
||||
|
||||
return gang.name ~= nil and gang.name ~= 'none' and gang.name ~= ''
|
||||
end
|
||||
|
||||
function GetPoliceCount()
|
||||
local currentOfficers = 0
|
||||
for _, playerId in ipairs(GetPlayers()) do
|
||||
playerId = tonumber(playerId)
|
||||
if IsPolice(playerId) then
|
||||
currentOfficers = currentOfficers + 1
|
||||
end
|
||||
end
|
||||
return currentOfficers
|
||||
end
|
||||
|
||||
function AddMoney(player, amount)
|
||||
local xPlayer = QBCore.Functions.GetPlayer(player)
|
||||
|
||||
if not xPlayer then
|
||||
return false
|
||||
end
|
||||
|
||||
xPlayer.Functions.AddMoney(Config.qbSettings.moneyAccount, amount)
|
||||
end
|
||||
end
|
||||
Binary file not shown.
@@ -0,0 +1,252 @@
|
||||
if Config.esxSettings.enabled and Config.qbSettings.enabled then
|
||||
print('^1BOTH FRAMEWORKS ENABLED!! MAKE SURE TO ONLY ENABLE ONE FRAMEWORK IN THE CONFIG FILE!')
|
||||
end
|
||||
if not Config.esxSettings.enabled and not Config.qbSettings.enabled then
|
||||
print('^1NO FRAMEWORK ENABLED!! MAKE SURE TO ENABLE ONE FRAMEWORK IN THE CONFIG FILE!')
|
||||
end
|
||||
|
||||
-- Do not remove this!
|
||||
sellableVehicles = {}
|
||||
|
||||
newHeist = {
|
||||
player = nil,
|
||||
truck = nil,
|
||||
trailer = nil,
|
||||
npc = nil,
|
||||
passenger = nil,
|
||||
support = nil,
|
||||
supportEnabled = nil,
|
||||
weaponsEnabled = nil,
|
||||
passengerEnabled = nil,
|
||||
bulletproofTiresEnabled = nil,
|
||||
touches = 0,
|
||||
vehicles = {}
|
||||
}
|
||||
|
||||
heist = {}
|
||||
|
||||
function AttemptCreateHeist()
|
||||
EndHeist()
|
||||
|
||||
heist = json.decode(json.encode(newHeist))
|
||||
|
||||
heist.hash = math.random(1, 99999)
|
||||
|
||||
heist.startLocation = Config.startLocations[math.random(1, #Config.startLocations)]
|
||||
heist.endLocation = heist.startLocation.finish
|
||||
|
||||
local closestPlayer = nil
|
||||
local closestDistance = 99999.9
|
||||
|
||||
for _, playerId in ipairs(GetPlayers()) do
|
||||
playerId = tonumber(playerId)
|
||||
local playerCoords = GetEntityCoords(GetPlayerPed(playerId))
|
||||
|
||||
local distance = GetDistanceBetweenCoords(playerCoords.x, playerCoords.y, playerCoords.z, heist.startLocation.truck.x, heist.startLocation.truck.y, heist.startLocation.truck.z)
|
||||
|
||||
if distance < 120 then
|
||||
return false
|
||||
end
|
||||
|
||||
if closestDistance > distance then
|
||||
closestPlayer = playerId
|
||||
closestDistance = distance
|
||||
end
|
||||
end
|
||||
|
||||
if not closestPlayer then
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
heist.weaponsEnabled = true
|
||||
if math.random(0, 100) > Config.weaponChance then
|
||||
heist.weaponsEnabled = false
|
||||
end
|
||||
|
||||
local odds = 0
|
||||
local eventKey = nil
|
||||
local hit = math.random(0, 100)
|
||||
for k, event in pairs(Config.events) do
|
||||
if event.chance + odds > hit and not eventKey then
|
||||
eventKey = k
|
||||
else
|
||||
odds = odds + event.chance
|
||||
end
|
||||
end
|
||||
if not eventKey then
|
||||
eventKey = math.random(1, #Config.events)
|
||||
end
|
||||
|
||||
heist.event = eventKey
|
||||
local event = Config.events[eventKey]
|
||||
|
||||
local empty = 0
|
||||
for k, slot in pairs(Settings.trailerSlots) do
|
||||
if math.random(0, 100) <= event.vehicleSlotChance or (empty + event.minimumVehicles == #Settings.trailerSlots) then
|
||||
local vehicle = event.vehicles[math.random(1, #event.vehicles)]
|
||||
heist.vehicles[k] = { data = vehicle, vehicle = nil }
|
||||
else
|
||||
empty = empty + 1
|
||||
end
|
||||
end
|
||||
|
||||
heist.passengerEnabled = true
|
||||
if math.random(0, 100) > event.passengerChance then
|
||||
heist.passengerEnabled = false
|
||||
end
|
||||
|
||||
heist.bulletproofTiresEnabled = true
|
||||
if math.random(0, 100) > event.bulletproofTiresChance then
|
||||
heist.bulletproofTiresEnabled = false
|
||||
end
|
||||
|
||||
heist.supportEnabled = true
|
||||
if math.random(0, 100) > event.supportChance then
|
||||
heist.supportEnabled = false
|
||||
end
|
||||
|
||||
heist.player = closestPlayer
|
||||
Debug('starting heist, initiator: ' .. closestPlayer)
|
||||
TriggerClientEvent('kq_carheist:createHeist', closestPlayer, heist)
|
||||
|
||||
OnHeistCreated()
|
||||
return true
|
||||
end
|
||||
|
||||
function EndHeist()
|
||||
DeleteIfExists(heist.truck)
|
||||
DeleteIfExists(heist.trailer)
|
||||
DeleteIfExists(heist.npc)
|
||||
DeleteIfExists(heist.passenger)
|
||||
|
||||
if heist.supportEnabled and heist.support then
|
||||
DeleteIfExists(heist.support.vehicle)
|
||||
for k, ped in pairs(heist.support.peds) do
|
||||
DeleteIfExists(ped)
|
||||
end
|
||||
end
|
||||
|
||||
TriggerClientEvent('kq_carheist:endHeist', -1)
|
||||
|
||||
heist = json.decode(json.encode(newHeist))
|
||||
end
|
||||
|
||||
RegisterServerEvent('kq_carheist:heistCreated')
|
||||
AddEventHandler('kq_carheist:heistCreated', function(syncedHeist)
|
||||
if source ~= heist.player then
|
||||
return
|
||||
end
|
||||
|
||||
heist = syncedHeist
|
||||
|
||||
TriggerClientEvent('kq_carheist:startDriver', -1)
|
||||
TriggerClientEvent('kq_carheist:syncHeist', -1, heist)
|
||||
|
||||
if Config.announceTruckDepartureToPlayers then
|
||||
TriggerClientEvent('kq_carheist:announceHeist', -1, vector3(heist.startLocation.truck.x, heist.startLocation.truck.y, heist.startLocation.truck.z))
|
||||
end
|
||||
end)
|
||||
|
||||
if Config.debug then
|
||||
RegisterCommand('cheist', function(source, args)
|
||||
AttemptCreateHeist()
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
Citizen.CreateThread(function()
|
||||
while true do
|
||||
local sleep = 20000
|
||||
if heist.player and heist.truck then
|
||||
sleep = 4000
|
||||
|
||||
local truckCoords = GetEntityCoords(NetworkGetEntityFromNetworkId(heist.truck))
|
||||
local trailerCoords = GetEntityCoords(NetworkGetEntityFromNetworkId(heist.trailer))
|
||||
local ended = false
|
||||
|
||||
Debug('Truck Owner: ' .. NetworkGetEntityOwner(NetworkGetEntityFromNetworkId(heist.truck)))
|
||||
Debug(truckCoords)
|
||||
|
||||
Debug('Trailer Owner: ' .. NetworkGetEntityOwner(NetworkGetEntityFromNetworkId(heist.trailer)))
|
||||
Debug(trailerCoords)
|
||||
|
||||
if not DoesEntityExist(NetworkGetEntityFromNetworkId(heist.truck)) or not DoesEntityExist(NetworkGetEntityFromNetworkId(heist.trailer)) or not DoesEntityExist(NetworkGetEntityFromNetworkId(heist.npc)) then
|
||||
Debug('Ending heist')
|
||||
EndHeist()
|
||||
ended = true
|
||||
end
|
||||
|
||||
if not ended then
|
||||
Debug('Remaining distance: ' .. GetDistanceBetweenCoords(truckCoords.x, truckCoords.y, truckCoords.z, heist.endLocation.x, heist.endLocation.y, heist.endLocation.z))
|
||||
|
||||
if GetDistanceBetweenCoords(truckCoords.x, truckCoords.y, truckCoords.z, heist.endLocation.x, heist.endLocation.y, heist.endLocation.z) < 18.0 and GetDistanceBetweenCoords(trailerCoords.x, trailerCoords.y, trailerCoords.z, heist.endLocation.x, heist.endLocation.y, heist.endLocation.z) < 25.0 then
|
||||
Debug('Truck arrived to its destination. Ending heist')
|
||||
TriggerClientEvent('kq_carheist:truckArrived', -1)
|
||||
EndHeist()
|
||||
end
|
||||
end
|
||||
end
|
||||
Citizen.Wait(sleep)
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
Citizen.CreateThread(function()
|
||||
Citizen.Wait(30000)
|
||||
while true do
|
||||
if Config.minimumOfficers > 0 then
|
||||
local enough = false
|
||||
while not enough do
|
||||
local currentOfficers = GetPoliceCount()
|
||||
|
||||
if currentOfficers >= Config.minimumOfficers then
|
||||
enough = true
|
||||
else
|
||||
Debug('Couldn\'t start a new heist. Not enough police online')
|
||||
Citizen.Wait(120000)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if heist.player ~= nil and heist.trailer and DoesEntityExist(NetworkGetEntityFromNetworkId(heist.trailer)) and not Config.ignoreDistances then
|
||||
Citizen.Wait(20000)
|
||||
|
||||
local tooClose = true
|
||||
while tooClose do
|
||||
local closestDistance = 99999.9
|
||||
|
||||
for _, playerId in ipairs(GetPlayers()) do
|
||||
playerId = tonumber(playerId)
|
||||
local playerCoords = GetEntityCoords(GetPlayerPed(playerId))
|
||||
|
||||
local trailerCoords = GetEntityCoords(NetworkGetEntityFromNetworkId(heist.trailer))
|
||||
|
||||
local distance = GetDistanceBetweenCoords(playerCoords.x, playerCoords.y, playerCoords.z, trailerCoords.x, trailerCoords.y, trailerCoords.z)
|
||||
|
||||
Debug('Distance: ' .. distance)
|
||||
if closestDistance > distance then
|
||||
closestDistance = distance
|
||||
end
|
||||
end
|
||||
|
||||
if closestDistance > 100.0 then
|
||||
tooClose = false
|
||||
else
|
||||
Debug('Couldn\'t start a new heist. Someone is too near the old trailer')
|
||||
Citizen.Wait(60000)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local success = false
|
||||
while not success do
|
||||
success = AttemptCreateHeist()
|
||||
if not success then
|
||||
Debug('Couldn\'t start a new heist. Someone is too close the spawn location')
|
||||
Citizen.Wait(60000)
|
||||
end
|
||||
end
|
||||
Citizen.Wait(Config.heistSpawnTime * 60000)
|
||||
end
|
||||
end)
|
||||
Binary file not shown.
Reference in New Issue
Block a user