Files
red-valley/resources/[framework]/[addons]/[kq]/kq_carheist/client/functions.lua

1053 lines
32 KiB
Lua
Raw Normal View History

2026-03-29 21:41:17 +03:00
----------------------
-- SYNCING
----------------------
function SetNetworkShared(netId)
Citizen.CreateThread(function()
local timeout = 0
while not NetworkDoesEntityExistWithNetworkId(netId) and timeout < 10 do
Citizen.Wait(10)
timeout = timeout + 1
end
local entity = NetworkGetEntityFromNetworkId(netId)
SetEntityAsMissionEntity(entity, 1, 1)
NetworkAllowLocalEntityAttachment(entity, true)
SetEntityLoadCollisionFlag(entity, not Config.experimentalSync)
SetNetworkIdExistsOnAllMachines(netId, true)
if Config.experimentalSync then
SetNetworkIdAlwaysExistsForPlayer(netId, PlayerId(), true)
if IsEntityAVehicle(entity) then
SetNetworkVehiclePositionUpdateMultiplier(entity, 2.0)
SetNetworkEnableVehiclePositionCorrection(entity, true)
end
if tonumber(Config.experimentalSync) == 111 then
NetworkUseHighPrecisionBlending(netId, false)
SetNetworkIdCanMigrate(netId, false)
end
end
--NetworkUseHighPrecisionBlending(netId, true)
--SetNetworkIdCanMigrate(netId, false)
end)
end
function SyncToServer()
TriggerServerEvent('kq_carheist:heistCreated', heist)
end
RegisterNetEvent('kq_carheist:syncHeist')
AddEventHandler('kq_carheist:syncHeist', function(newHeist)
heist = newHeist
RemoveRelationshipGroup('kq_carheist_ped')
RemoveRelationshipGroup(robberRelationship)
SetPedRelationshipGroupDefaultHash(PlayerPedId(), GetHashKey('PLAYER'))
AddRelationshipGroup('kq_carheist_ped')
_, robberRelationship = AddRelationshipGroup('kq_carheist_robber' .. heist.hash)
RemovePoliceTrailerBlip()
SetPedsRelationships()
Debug(heist.truck)
Debug(GetTruck())
Debug(GetEntityCoords(GetTruck()))
end)
RegisterNetEvent('kq_carheist:syncSellableVehicles')
AddEventHandler('kq_carheist:syncSellableVehicles', function(newSellable)
sellableVehicles = newSellable
end)
----------------------
-- ALARM
----------------------
function CheckAlertness()
Debug('Checking alertness')
for k, ped in pairs(GetAllHeistPeds()) do
if GetPedAlertness(ped) >= 2 then
Debug('Peds were alerted. Setting off the alarm')
SetOffAlarm()
return
end
end
end
function SetOffAlarm()
if not heist.alarm then
heist.alarm = true
if Config.useVehicleAlarm then
SetVehicleAlarm(GetTrailer(), true)
SetVehicleAlarmTimeLeft(GetTruck(), 120000)
end
TriggerServerEvent('kq_carheist:startAlarm')
end
for k, ped in pairs(GetAllHeistPeds()) do
if ped ~= GetNPC() then
local veh = GetSupportVehicle()
if GetPedInVehicleSeat(veh, -1) ~= ped then
TaskCombatPed(ped, PlayerPedId(), 0, 16)
end
end
end
SetRelationshipBetweenGroups(5, 'kq_carheist_ped', robberRelationship)
end
RegisterNetEvent('kq_carheist:setAlarm')
AddEventHandler('kq_carheist:setAlarm', function(trailerCoords)
heist.alarm = true
if IsPolice() then
RefreshPoliceTrailerAlarm(trailerCoords)
SendDispatchMessage(L('Our car transport is under attack! Coordinates have been shared!'), L('Robbery in progress'))
end
end)
RegisterNetEvent('kq_carheist:truckArrived')
AddEventHandler('kq_carheist:truckArrived', function()
if heist.alarm then
EndPoliceAlarm()
end
end)
function DoSparkParticle()
local dict = 'core'
if not HasNamedPtfxAssetLoaded(dict) then
RequestNamedPtfxAsset(dict)
while not HasNamedPtfxAssetLoaded(dict) do
Citizen.Wait(1)
end
end
SetPtfxAssetNextCall(dict)
local sparks = StartParticleFxLoopedOnEntityBone("ent_brk_sparking_wires", grinder, 0.0, 0.0, 0.1, 0.0, 0.0, 0.0, 0, 1.3, 1, 1, 1)
end
----------------------
-- RAMP OPENING
----------------------
RegisterNetEvent('kq_carheist:startOpeningRamp')
AddEventHandler('kq_carheist:startOpeningRamp', function()
StartOpeningRamp()
end)
function StartOpeningRamp()
openingRamp = true
progress = 0
SetOffAlarm()
OnStartOpeningTrailer()
local playerPed = PlayerPedId()
local playerCoords = GetEntityCoords(playerPed)
SetPedRelationshipGroupHash(playerPed, robberRelationship)
local bootCoords = GetWorldPositionOfEntityBone(GetTrailer(), GetEntityBoneIndexByName(GetTrailer(), 'boot'))
local grinderModel = 'imp_prop_grinder_01a'
DoRequestModel(grinderModel)
grinder = CreateObject(grinderModel, playerCoords.x, playerCoords.y, playerCoords.z, true, true, 1)
local handBone = 6286
local grinderOffset = vector3(0.2, 0.065, -0.015)
local grinderRot = vector3(200.0, 265.0, -40.0)
local handBoneIndex = GetPedBoneIndex(playerPed, handBone)
AttachEntityToEntity(grinder, playerPed, handBoneIndex, grinderOffset.x, grinderOffset.y, grinderOffset.z, grinderRot.x, grinderRot.y, grinderRot.z, true, false, false, false, 2, true)
local heading = GetHeadingFromVector_2d(playerCoords.x - bootCoords.x, playerCoords.y - bootCoords.y) + 200
SetEntityHeading(playerPed, heading)
TaskStartScenarioInPlace(PlayerPedId(), 'WORLD_HUMAN_WELDING', 10, true)
end
function FinishOpeningRamp()
StopOpeningRamp()
heist.rampDown = true
Citizen.Wait(1000)
OpenTrailer()
end
function StopOpeningRamp()
cutting = false
openingRamp = false
local playerPed = PlayerPedId()
local playerCoords = GetEntityCoords(playerPed)
ClearPedTasks(playerPed)
Citizen.Wait(50)
local welder = GetClosestObjectOfType(playerCoords, 5.0, GetHashKey('prop_weld_torch'), false, false, false)
SetEntityAsMissionEntity(welder, true)
DeleteEntity(welder)
DeleteObject(grinder)
end
function OpenTrailer()
TriggerServerEvent('kq_carheist:openTrailer', heist.trailer)
if openingRamp then
StopOpeningRamp()
end
end
RegisterNetEvent('kq_carheist:openTrailer')
AddEventHandler('kq_carheist:openTrailer', function(networkVehicle)
heist.rampDown = true
if NetworkDoesEntityExistWithNetworkId(networkVehicle) then
SetVehicleDoorOpen(NetworkGetEntityFromNetworkId(networkVehicle), 5, false, false)
end
if heist.vehicles[3] then
DetachVehicle(3, true)
end
for k, vehicle in pairs(heist.vehicles) do
if NetworkDoesEntityExistWithNetworkId(vehicle.vehicle) then
local veh = NetworkGetEntityFromNetworkId(vehicle.vehicle)
SetVehicleDoorsLocked(veh, 0)
SetVehicleDoorsLockedForAllPlayers(veh, false)
end
end
OnTrailerOpened()
end)
function DetachVehicle(vehicleKey, falling)
Citizen.CreateThread(function()
if falling then
Citizen.Wait(1000)
end
if NetworkDoesEntityExistWithNetworkId(heist.vehicles[vehicleKey].vehicle) and NetworkHasControlOfEntity(NetworkGetEntityFromNetworkId(heist.vehicles[vehicleKey].vehicle)) then
local vehicle = NetworkGetEntityFromNetworkId(heist.vehicles[vehicleKey].vehicle)
if Config.useVehicleAlarm then
SetVehicleAlarm(vehicle, true)
SetVehicleAlarmTimeLeft(vehicle, math.random(25000, 60000))
end
DetachEntity(vehicle, 1, 1)
SetVehicleSuspensionHeight(vehicle, 0.0)
Entity(vehicle).state.ignoreLocks = true
OnVehicleDetach(vehicle)
if falling then
Citizen.Wait(1000)
end
TriggerServerEvent('kq_carheist:enableCollisions', heist.vehicles[vehicleKey].vehicle)
if falling then
local falls = 0
while falls < 45 do
local vel = GetEntityVelocity(vehicle)
SetEntityVelocity(vehicle, vel.x * 0.98, vel.y * 0.98, vel.z + 0.24)
falls = falls + 1
Citizen.Wait(100)
end
end
end
end)
end
RegisterNetEvent('kq_carheist:enableCollisions')
AddEventHandler('kq_carheist:enableCollisions', function(netVehicle)
local vehicle = NetworkGetEntityFromNetworkId(netVehicle)
for k, veh in pairs(heist.vehicles) do
if NetworkDoesEntityExistWithNetworkId(veh.vehicle) then
local otherVeh = NetworkGetEntityFromNetworkId(veh.vehicle)
if otherVeh ~= vehicle then
SetEntityNoCollisionEntity(vehicle, otherVeh, true)
end
end
end
end)
----------------------
-- HEIST CREATION
----------------------
RegisterNetEvent('kq_carheist:startDriver')
AddEventHandler('kq_carheist:startDriver', function()
StartDriver()
end)
function StartDriver()
if not heist.endLocation then
return
end
local endLoc = heist.endLocation
--TaskVehicleDriveWander(GetNPC(), GetTruck(), Config.truckDriveSpeed + 0.0, Config.truckDriveStyle)
local coords = GetEntityCoords(GetTruck())
RequestAdditionalCollisionAtCoord(coords)
RequestCollisionAtCoord(coords)
AddNavmeshRequiredRegion(coords.x, coords.y, 100.0)
if GetDistanceBetweenCoords(GetEntityCoords(GetTruck()), endLoc.x, endLoc.y, endLoc.z, true) > 15.0 then
TaskVehicleDriveToCoordLongrange(GetNPC(), GetTruck(), endLoc.x, endLoc.y, endLoc.z, Config.truckDriveSpeed + 0.0, Config.truckDriveStyle, 10.0)
end
end
RegisterNetEvent('kq_carheist:createHeist')
AddEventHandler('kq_carheist:createHeist', function(newHeist)
heist = newHeist
CreateHeist()
end)
function CreateHeist()
Citizen.CreateThread(function()
heist.truck = NetworkGetNetworkIdFromEntity(CreateTruck())
heist.trailer = NetworkGetNetworkIdFromEntity(CreateTrailer())
heist.npc = NetworkGetNetworkIdFromEntity(CreateDriver())
if heist.passengerEnabled then
heist.passenger = NetworkGetNetworkIdFromEntity(CreatePassenger())
end
if heist.supportEnabled then
Debug('create support')
heist.support = CreateSupport()
end
Citizen.Wait(10)
Debug('attach trailer')
AttachVehicleToTrailer(GetTruck(), GetTrailer(), 10.0)
Citizen.Wait(1000)
SyncToServer()
end)
end
function CreateTruck()
local availableTrucks = Config.events[heist.event].trucks
local model = availableTrucks[math.random(1, #availableTrucks)]
DoRequestModel(model)
local veh = CreateVehicle(model, heist.startLocation.truck.x, heist.startLocation.truck.y, heist.startLocation.truck.z, heist.startLocation.truck.h, 1, 0)
SetEntityAsMissionEntity(veh, true, true)
SetNetworkShared(NetworkGetNetworkIdFromEntity(veh), true)
if heist.bulletproofTiresEnabled then
SetVehicleTyresCanBurst(veh, false)
end
SetVehicleDoorsLocked(veh, 2)
SetVehicleDoorsLockedForAllPlayers(veh, true)
SetVehicleCustomPrimaryColour(veh, Config.truckColor.r, Config.truckColor.g, Config.truckColor.b)
SetVehicleCustomSecondaryColour(veh, Config.truckColor.r, Config.truckColor.g, Config.truckColor.b)
AfterTruckCreated(veh)
return veh
end
function CreateTrailer()
local model = Settings.trailer
DoRequestModel(model)
local veh = CreateVehicle(model, heist.startLocation.truck.x, heist.startLocation.truck.y, heist.startLocation.truck.z + 4.0, 0.0, 1, 0)
SetEntityAsMissionEntity(veh, true, true)
SetNetworkShared(NetworkGetNetworkIdFromEntity(veh), true)
FreezeEntityPosition(veh, true)
SetEntityProofs(veh, false, true, true, false, false, true, 1, false)
SetVehicleDoorCanBreak(veh, 5, false)
SetVehicleDoorCanBreak(veh, 4, false)
CreateTrailerVehicles(veh)
FreezeEntityPosition(veh, false)
if heist.bulletproofTiresEnabled then
SetVehicleTyresCanBurst(veh, false)
end
AfterTrailerCreated(veh)
return veh
end
function CreateTrailerVehicles(trailer)
local lastVeh = nil
for k, slot in pairs(Settings.trailerSlots) do
if heist.vehicles[k] then
local vehicle = heist.vehicles[k].data
if IsModelValid(vehicle.model) then
Debug('created trailer vehicle ' .. vehicle.model)
DoRequestModel(vehicle.model)
local coords = slot.coords
local rot = slot.rot
local veh = CreateVehicle(vehicle.model, heist.startLocation.truck.x + coords.x, heist.startLocation.truck.y + coords.y, heist.startLocation.truck.z + 4.0 + coords.z + 0.6, 0.0, 1, 0)
SetEntityAsMissionEntity(veh, true, true)
SetNetworkShared(NetworkGetNetworkIdFromEntity(veh), true)
SetVehicleModKit(veh, 0)
SetVehicleLivery(veh, math.random(0, 8))
SetVehicleMod(veh, 48, math.random(0, 8), 1)
FreezeEntityPosition(veh, true)
heist.vehicles[k] = { data = vehicle, vehicle = NetworkGetNetworkIdFromEntity(veh), tracker = true, trackerLocation = math.random(1,6), slot = slot, hash = heist.hash }
SetEntityCoords(veh, heist.startLocation.truck.x + coords.x, heist.startLocation.truck.y + coords.y, heist.startLocation.truck.z + 4.0 + coords.z + 0.5, 0, 0, 0, 0)
if DoesEntityExist(veh) then
SetVehicleSuspensionHeight(veh, 0.075)
end
local offset = GetOffsetFromEntityGivenWorldCoords(trailer, GetEntityCoords(veh))
AttachEntityToEntity(veh, trailer, 0, offset.x, offset.y, offset.z, rot.x, rot.y, rot.z, 1, 1, 1, 0, 0, 1)
SetVehicleDoorsLocked(veh, 2)
SetVehicleDoorsLockedForAllPlayers(veh, true)
AfterTrailerVehicleCreated(veh)
FreezeEntityPosition(veh, false)
if lastVeh then
SetEntityNoCollisionEntity(veh, lastVeh, false)
end
lastVeh = veh
end
end
end
Debug('created trailer vehicles')
return true
end
function CreateDriver()
local availableNPCs = Config.events[heist.event].npcs
local model = availableNPCs[math.random(1, #availableNPCs)]
DoRequestModel(model)
local driver = CreatePedInsideVehicle(GetTruck(), 0, model, -1, 1, 1)
SetNetworkShared(NetworkGetNetworkIdFromEntity(driver), true)
SetPedBaseConfig(driver)
SetBlockingOfNonTemporaryEvents(driver, true)
SetPedMaxHealth(driver, Config.npcHealth)
SetEntityHealth(driver, Config.npcHealth)
SetPedSuffersCriticalHits(driver, Config.npcSuffersCriticalHits)
AfterDriverCreated(driver)
return driver
end
function CreatePassenger()
local availableNPCs = Config.events[heist.event].npcs
local model = availableNPCs[math.random(1, #availableNPCs)]
DoRequestModel(model)
local passenger = CreatePedInsideVehicle(GetTruck(), 0, model, 0, 1, 0)
SetNetworkShared(NetworkGetNetworkIdFromEntity(passenger), true)
SetPedBaseConfig(passenger)
SetPedMaxHealth(passenger, 150)
SetEntityHealth(passenger, 150)
SetPedSuffersCriticalHits(passenger, false)
if heist.weaponsEnabled then
GiveWeaponToPed(passenger, Config.weapons[math.random(1, #Config.weapons)], 120, false, true)
end
AfterPassengerCreated(passenger)
return passenger
end
function CreateSupport()
local model = Config.supportVehicles[math.random(1, #Config.supportVehicles)]
DoRequestModel(model)
local veh = CreateVehicle(model, heist.startLocation.support.x, heist.startLocation.support.y, heist.startLocation.support.z, heist.startLocation.support.h, 1, 0)
SetEntityAsMissionEntity(veh, true, true)
SetNetworkShared(NetworkGetNetworkIdFromEntity(veh), true)
if heist.bulletproofTiresEnabled then
SetVehicleTyresCanBurst(veh, false)
end
SetVehicleDoorsLocked(veh, 2)
SetVehicleDoorsLockedForAllPlayers(veh, true)
SetVehicleModKit(veh, 0)
SetVehicleWindowTint(veh, 2)
SetVehicleModColor_1(veh, 3, 0, 0)
SetVehicleModColor_2(veh, 3, 0, 0)
SetVehicleCustomPrimaryColour(veh, Config.supportColor.r, Config.supportColor.g, Config.supportColor.b)
SetVehicleCustomSecondaryColour(veh, Config.supportColor.r, Config.supportColor.g, Config.supportColor.b)
local supportAmount = math.random(2, GetVehicleModelNumberOfSeats(model))
AfterSupportVehicleCreated(veh)
local peds = {}
for i = 1, supportAmount, 1 do
local pedModel = Config.supportPeds[math.random(1, #Config.supportPeds)]
DoRequestModel(pedModel)
local ped = CreatePedInsideVehicle(veh, 0, pedModel, i - 2, 1, 1)
SetNetworkShared(NetworkGetNetworkIdFromEntity(ped), true)
if i == 1 then
TaskVehicleEscort(ped, veh, GetTrailer(), -1, Config.truckDriveSpeed * 1.2, Config.truckDriveStyle, 25.0, 25.0)
SetBlockingOfNonTemporaryEvents(ped, true)
end
GiveWeaponToPed(ped, Config.weapons[math.random(1, #Config.weapons)], 120, false, true)
SetPedBaseConfig(ped)
SetPedMaxHealth(ped, 200)
SetEntityHealth(ped, 200)
SetPedSuffersCriticalHits(ped, false)
table.insert(peds, NetworkGetNetworkIdFromEntity(ped))
AfterSupportPedCreated(ped)
end
return { vehicle = NetworkGetNetworkIdFromEntity(veh), peds = peds }
end
function SetPedBaseConfig(ped)
SetEntityAlwaysPrerender(ped, true)
SetDriverAbility(ped, 100.0)
SetDriverAggressiveness(ped, 0.1)
SetPedAllowedToDuck(ped, 1)
SetPedArmour(ped, 100)
SetPedCombatAttributes(ped, 2, true)
SetPedCombatAttributes(ped, 3, true)
SetTaskVehicleChaseBehaviorFlag(ped, 32, true)
SetPedCanBeDraggedOut(ped, false)
SetPedKeepTask(ped, true)
SetPedCombatRange(ped, 0)
SetPedCombatAbility(ped, 0)
if Config.npcShootingAccuracy > 30 then
SetPedCombatAbility(ped, 1)
end
if Config.npcShootingAccuracy > 80 then
SetPedCombatAbility(ped, 2)
end
SetPedAccuracy(ped, Config.npcShootingAccuracy)
SetPedDropsWeaponsWhenDead(ped, false)
end
function SetPedsRelationships()
SetRelationshipBetweenGroups(0, 'kq_carheist_ped', 'kq_carheist_ped')
SetRelationshipBetweenGroups(5, 'kq_carheist_ped', robberRelationship)
local friendlyTo = { 'COP', 'SECURITY_GUARD', 'PRIVATE_SECURITY', 'FIREMAN', 'ARMY', 'CIVMALE', 'CIVFEMALE' }
for _, group in pairs(friendlyTo) do
SetRelationshipBetweenGroups(2, 'kq_carheist_ped', GetHashKey(group))
SetRelationshipBetweenGroups(2, GetHashKey(group), 'kq_carheist_ped')
end
for k, ped in pairs(GetAllHeistPeds()) do
SetPedRelationshipGroupHash(ped, 'kq_carheist_ped')
SetPedDropsWeaponsWhenDead(ped, false)
end
SetRelationshipBetweenGroups(3, 'kq_carheist_ped', GetHashKey('PLAYER'))
SetRelationshipBetweenGroups(3, GetHashKey('PLAYER'), 'kq_carheist_ped')
SetRelationshipBetweenGroups(1, GetHashKey('PLAYER'), robberRelationship)
SetRelationshipBetweenGroups(1, robberRelationship, GetHashKey('PLAYER'))
end
RegisterNetEvent('kq_carheist:announceHeist')
AddEventHandler('kq_carheist:announceHeist', function(coords)
if not IsPolice() then
SendAnnouncementMessage(L('Car transport truck is currently departing.\nI\'ll pay top dollar if you can get them'), L('Car collector'), coords)
end
end)
function CreateTemporaryBlip(coords, sprite, color, alpha, scale, message, shortRange, noLegend)
Citizen.CreateThread(function()
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)
if noLegend then
SetBlipDisplay(blip, 8)
end
Citizen.Wait(Config.announcementBlip.duration or 15000)
RemoveBlip(blip)
end)
end
----------------------
-- TRACKERS
----------------------
function CheckForTracker(vehKey, trackerKey, textCoords, veh)
local playerPed = PlayerPedId()
local vehCoords = GetEntityCoords(veh)
Debug(vehCoords)
local playerCoords = GetEntityCoords(playerPed)
Debug(playerCoords)
local heading = GetHeadingFromVector_2d(playerCoords.x - vehCoords.x, playerCoords.y - vehCoords.y) + 180.0
SetEntityHeading(playerPed, heading)
PlayAnim('anim@amb@clubhouse@tutorial@bkr_tut_ig3@', 'machinic_loop_mechandplayer')
local searching = true
Citizen.CreateThread(function()
while searching do
Draw3DText(textCoords.x, textCoords.y, textCoords.z + 0.2, L('~w~Searching for a tracking device'), 4, 0.04, 0.04)
Draw3DText(textCoords.x, textCoords.y, textCoords.z + 0.1, L('~w~Press [~r~E~w~] to cancel'), 4, 0.035, 0.035)
if IsControlJustReleased(0, Keys['E']) or IsPedRagdoll(playerPed) or GetDistanceBetweenCoords(textCoords, playerCoords, true) > 3.0 then
searching = false
end
Citizen.Wait(1)
end
end)
local waits = Config.tracker.searchDuration / 1000
while waits > 0 and searching do
Citizen.Wait(1000)
waits = waits - 1
end
if not searching then
ClearPedTasks(playerPed)
end
if searching then
searching = false
if sellableVehicles[vehKey].trackerLocation == trackerKey then
local removing = true
local removalKeybinds = Config.tracker.removalKeybinds
local keyKey = #removalKeybinds
local progress = 0
while progress < Config.tracker.removalLength and sellableVehicles[vehKey].tracker and removing do
local currentKey = Config.tracker.removalKeybinds[keyKey]
local text = '~w~'
for k, key in pairs(removalKeybinds) do
if key ~= currentKey then
text = text .. '~w~' .. key
if IsControlJustReleased(0, Keys[key]) then
progress = progress - 2
currentKey = nil
local display = true
Citizen.CreateThread(function()
while display and removing do
Draw3DText(textCoords.x, textCoords.y, textCoords.z, L('~r~You dropped the screwdriver'), 4, 0.04, 0.04)
Draw3DText(textCoords.x, textCoords.y, textCoords.z - 0.1, L('~w~Press [~r~E~w~] to cancel'), 4, 0.035, 0.035)
if IsControlJustReleased(0, Keys['E']) or IsPedRagdoll(playerPed) or GetDistanceBetweenCoords(textCoords, playerCoords, true) > 3.0 then
removing = false
ClearPedTasks(playerPed)
end
Citizen.Wait(1)
end
end)
Citizen.Wait(Config.tracker.removalMessedUpDuration)
display = false
end
else
text = text .. '~r~' .. currentKey
end
end
if IsControlJustReleased(0, Keys[currentKey]) then
progress = progress + 1
keyKey = keyKey - 1
if keyKey < 1 then
keyKey = #removalKeybinds
end
end
Draw3DText(textCoords.x, textCoords.y, textCoords.z + 0.2, L('~g~Tracking device found!'), 4, 0.04, 0.04)
Draw3DText(textCoords.x, textCoords.y, textCoords.z, '~w~' .. (L('Press ~w~[{keybinds}~w~] to unscrew')):gsub('{keybinds}', text), 4, 0.04, 0.04)
Draw3DText(textCoords.x, textCoords.y, textCoords.z - 0.1, L('~w~Press [~r~E~w~] to cancel'), 4, 0.035, 0.035)
if IsControlJustReleased(0, Keys['E']) or IsPedRagdoll(playerPed) or GetDistanceBetweenCoords(textCoords, playerCoords, true) > 3.0 then
removing = false
ClearPedTasks(playerPed)
end
Citizen.Wait(1)
end
if removing then
removing = false
if sellableVehicles[vehKey].tracker then
TriggerServerEvent('kq_carheist:removeTracker', vehKey, textCoords)
CreateTrackerObject()
end
end
end
end
ClearPedTasks(playerPed)
end
function CreateTrackerObject()
local trackerModel = 'prop_cs_mini_tv'
DoRequestModel(trackerModel)
local playerPed = PlayerPedId()
local playerCoords = GetEntityCoords(playerPed)
local trackerObj = CreateObject(trackerModel, playerCoords.x, playerCoords.y, playerCoords.z, true, true, 1)
SetEntityDynamic(trackerObj, true)
end
----------------------
-- DROP OFF
----------------------
function RemoveDropOffs()
RemoveDropOffBlips()
currentDropOffs = {}
end
function CreateNewDropOffs(hash)
Debug('create dropoff')
math.randomseed(hash)
local amount = math.random(Config.dropOff.minLocations, Config.dropOff.maxLocations)
currentDropOffs = {}
while #currentDropOffs < amount do
local newLoc = Config.dropOff.locations[math.random(1, #Config.dropOff.locations)]
if not Contains(currentDropOffs, newLoc) then
table.insert(currentDropOffs, newLoc)
end
Citizen.Wait(1)
end
Debug('Got ' .. #currentDropOffs)
RemoveDropOffBlips()
for k, dropOff in pairs(currentDropOffs) do
Debug(json.encode(dropOff))
local blipConf = Config.dropOff.blips.primary
local primBlip = CreateDropOffBlip(vector3(dropOff.x, dropOff.y, dropOff.z), blipConf.sprite, blipConf.color, blipConf.alpha, blipConf.scale, L('Stolen vehicle drop off point'), blipConf.shortRange)
SetBlipDisplay(primBlip, 8)
table.insert(dropOffBlips, primBlip)
blipConf = Config.dropOff.blips.secondary
local secBlip = CreateDropOffBlip(vector3(dropOff.x, dropOff.y, dropOff.z), blipConf.sprite, blipConf.color, blipConf.alpha, blipConf.scale, L('Stolen vehicle drop off point'), blipConf.shortRange)
table.insert(dropOffBlips, secBlip)
end
math.randomseed(GetGameTimer())
end
function RemoveDropOffBlips()
for b, blip in pairs(dropOffBlips) do
RemoveBlip(blip)
end
dropOffBlips = {}
end
function CreateDropOffBlip(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 DropOffVehicle(vehicle, dropCoords)
if DoesEntityExist(vehicle) then
TriggerServerEvent('kq_carheist:dropOffVehicle', NetworkGetNetworkIdFromEntity(vehicle), dropCoords)
if DoesEntityExist(vehicle) then
SetVehicleDoorsLocked(vehicle, 2)
SetVehicleUndriveable(vehicle, true)
SetVehicleAsNoLongerNeeded(vehicle)
SetEntityCleanupByEngine(vehicle, true)
end
end
end
----------------------
-- GETTERS
----------------------
function GetTruck()
return GetSomething('truck')
end
function GetTrailer()
return GetSomething('trailer')
end
function GetNPC()
return GetSomething('npc')
end
function GetPassenger()
return GetSomething('passenger')
end
function GetSomething(key)
if not heist[key] then
return nil
end
if not NetworkDoesEntityExistWithNetworkId(heist[key]) then
return nil
end
local entity = NetworkGetEntityFromNetworkId(heist[key])
if DoesEntityExist(entity) then
return entity
end
return false
end
function GetSupportVehicle()
if not heist.supportEnabled or not heist.support then
return nil
end
if not NetworkDoesEntityExistWithNetworkId(heist.support.vehicle) then
return nil
end
local entity = NetworkGetEntityFromNetworkId(heist.support.vehicle)
if DoesEntityExist(entity) then
return entity
end
return nil
end
function GetAllHeistPeds()
local peds = { GetNPC() }
if GetPassenger() then
table.insert(peds, GetPassenger())
end
if heist.supportEnabled and heist.support and #heist.support.peds then
for k, netId in pairs(heist.support.peds) do
if NetworkDoesEntityExistWithNetworkId(netId) then
local ped = NetworkGetEntityFromNetworkId(netId)
table.insert(peds, ped)
end
end
end
return peds
end
function IsHeistVehicle(veh)
for k, vehicle in pairs(heist.vehicles) do
if NetworkDoesEntityExistWithNetworkId(vehicle.vehicle) then
local hVeh = NetworkGetEntityFromNetworkId(vehicle.vehicle)
if veh == hVeh then
return true
end
end
end
return false
end
function IsOnBike()
if IsPedInAnyVehicle(PlayerPedId()) then
local veh = GetVehiclePedIsIn(PlayerPedId())
if GetVehicleClass(veh) == 8 or GetVehicleClass(veh) == 13 then
return true
end
end
end
function IsInsideATunnel(coords)
local tunnels = {9, 12, 6, 15, 7, 3, 21, 4, 18, 5}
return Contains(tunnels, GetInteriorGroupId(GetInteriorAtCoords(coords)))
end
----------------------
-- HELPERS
----------------------
function DoRequestModel(model)
local hash = GetHashKey(model)
RequestModel(hash)
local timeout = 0
while not HasModelLoaded(hash) and timeout < 100 do
Citizen.Wait(100)
timeout = timeout + 1
end
end
function Contains(tab, val)
for index, value in ipairs(tab) do
if value == val then
return true
end
end
return false
end
function DoRequestAnimDict(dict)
RequestAnimDict(dict)
local timeout = 0
while not HasAnimDictLoaded(dict) do
Citizen.Wait(50)
timeout = timeout + 1
if timeout > 100 then
return
end
end
end
function PlayAnim(dict, anim, flag)
Citizen.CreateThread(function()
RequestAnimDict(dict)
local timeout = 0
while not HasAnimDictLoaded(dict) do
Citizen.Wait(50)
timeout = timeout + 1
if timeout > 100 then
return
end
end
TaskPlayAnim(PlayerPedId(), dict, anim, 4.0, 8.0, 5.0, flag or 1, 0, false, false, false)
RemoveAnimDict(dict)
end)
end
function Shuffle(tbl)
-- suffles numeric indices
local len, random = #tbl, math.random;
for i = len, 2, -1 do
local j = random(1, i);
tbl[i], tbl[j] = tbl[j], tbl[i];
end
return tbl;
end
function string.insert(str1, str2, pos)
return str1:sub(1, pos) .. str2 .. str1:sub(pos + 1)
end
function myDot(a, b)
return (a[1] * b[1]) + (a[2] * b[2]) + (a[3] * b[3])
end
function myMag(a)
return math.sqrt((a[1] * a[1]) + (a[2] * a[2]) + (a[3] * a[3]))
end
RegisterNetEvent('kq_carheist:notify')
AddEventHandler('kq_carheist:notify', function(message)
ShowTooltip(message)
end)
function Debug(message)
if Config.debug then
print(message)
end
end
local alertTitle = nil
local alertMessage = nil
local alertActive = false
function Alert(title, message, duration)
Citizen.CreateThread(function()
alertTitle = title
alertMessage = message
alertActive = true
Citizen.Wait(duration)
alertActive = false
end)
end
Citizen.CreateThread(function()
while true do
local sleep = 500
if alertActive then
sleep = 1
local scaleform = RequestScaleformMovie('MP_BIG_MESSAGE_FREEMODE')
while not HasScaleformMovieLoaded(scaleform) do
Citizen.Wait(1)
end
PushScaleformMovieFunction(scaleform, 'SHOW_SHARD_WASTED_MP_MESSAGE')
PushScaleformMovieFunctionParameterString(alertTitle)
PushScaleformMovieFunctionParameterString(alertMessage)
PopScaleformMovieFunctionVoid()
DrawScaleformMovieFullscreen(scaleform, 255, 255, 255, 255, 0)
end
Citizen.Wait(sleep)
end
end)
function L(text)
if Locale and Locale[text] then
return Locale[text]
end
return text
end