2022-07-08 23:16:36 +02:00
|
|
|
-- For support join my discord: https://discord.gg/Z9Mxu72zZ6
|
|
|
|
|
|
2022-07-16 04:46:27 +02:00
|
|
|
NDCore = exports["ND_Core"]:GetCoreObject()
|
2022-07-08 23:16:36 +02:00
|
|
|
local alreadyShot = false
|
|
|
|
|
local setRoute = false
|
|
|
|
|
local route = false
|
|
|
|
|
|
|
|
|
|
-- Suppressors hash, if a weapon has these then it won't trigger the shot spotter.
|
|
|
|
|
local suppresors = {
|
|
|
|
|
"0x65EA7EBB", -- Pistol.
|
|
|
|
|
"0x837445AA", -- Carbine Rifle, Advanced Rifle, Bullpup Rifle, Assault Shotgun, Marksman Rifle.
|
|
|
|
|
"0xA73D4664", -- .50 Pistol, Micro SMG, Assault SMG, Assault Rifle, Special Carbine, Bullpup Shotgun, Heavy Shotgun, Sniper Rifle.
|
|
|
|
|
"0xC304849A", -- Combat Pistol, AP Pistol, Heavy Pistol, Vintage Pistol, SMG.
|
|
|
|
|
"0xE608B35E" -- Pump Shotgun.
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
-- check if the players location is inside the shot spotter locations, this will only be used in the code when realistic shot spotter is turned on.
|
|
|
|
|
function isInShotSpotterLocation(pedCoords)
|
|
|
|
|
for _, location in pairs(config.realisticShotSpotterLocations) do
|
|
|
|
|
if #(pedCoords - vector3(location.x, location.y, location.z)) < 450.0 then
|
|
|
|
|
return true
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
return false
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- check if the players department can receive shot spotter alerts.
|
|
|
|
|
function isCop()
|
2022-07-16 00:12:02 -04:00
|
|
|
local job = NDCore.Functions.GetSelectedCharacter().job
|
2022-07-08 23:16:36 +02:00
|
|
|
for _, department in pairs(config.receiveAlerts) do
|
2022-07-16 04:46:27 +02:00
|
|
|
if department == job then
|
2022-07-08 23:16:36 +02:00
|
|
|
return true
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
return false
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function triggerShotSpotter(ped)
|
|
|
|
|
local pedCoords = GetEntityCoords(ped)
|
|
|
|
|
if config.shotSpotterUsePostal then
|
|
|
|
|
postal = exports[config.postalResourceName]:getPostal()
|
|
|
|
|
else
|
|
|
|
|
postal = false
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- if the player isn't in the realistic shot spotter locations then the shot spotter won't trigger.
|
|
|
|
|
if config.useRealisticShotSpotter and not isInShotSpotterLocation(pedCoords) then
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- if the player has a blacklisted weapon then the shot spotter won't trigger.
|
|
|
|
|
local selectedWeapon = GetSelectedPedWeapon(ped)
|
|
|
|
|
for _, weapon in pairs(config.weaponBlackList) do
|
|
|
|
|
if GetHashKey(weapon) == selectedWeapon then
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- if the player has a suppresor attached to their weapon then the shot spotter won't trigger.
|
|
|
|
|
for _, suppresor in pairs(suppresors) do
|
|
|
|
|
if HasPedGotWeaponComponent(ped, selectedWeapon, tonumber(suppresor)) then
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- if the player is a cop then they won't trigger the shotspotter.
|
|
|
|
|
if isCop() then
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- the alreadyShot variable is used for checking if the player has already shot and to add a cooldown until it turns to false.
|
|
|
|
|
if alreadyShot then return end
|
|
|
|
|
alreadyShot = true
|
|
|
|
|
Citizen.Wait(config.shotSpotterDelay * 1000)
|
|
|
|
|
local zoneName = GetLabelText(GetNameOfZone(pedCoords.x, pedCoords.y, pedCoords.z))
|
|
|
|
|
local street = GetStreetNameFromHashKey(GetStreetNameAtCoord(pedCoords.x, pedCoords.y, pedCoords.z))
|
|
|
|
|
TriggerServerEvent("ND_ShotSpotter:Trigger", street, pedCoords, postal, zoneName)
|
|
|
|
|
Citizen.Wait(config.shotSpotterCooldown * 1000)
|
|
|
|
|
alreadyShot = false
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Check if the player is shooting.
|
|
|
|
|
Citizen.CreateThread(function()
|
|
|
|
|
while true do
|
|
|
|
|
Citizen.Wait(0)
|
|
|
|
|
local ped = PlayerPedId()
|
|
|
|
|
if IsPedShooting(ped) then
|
|
|
|
|
triggerShotSpotter(ped)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end)
|
|
|
|
|
|
2022-09-01 04:11:48 -04:00
|
|
|
RegisterNetEvent("ND_ShotSpotter:Report", function(street, pedCoords, postal)
|
2022-07-08 23:16:36 +02:00
|
|
|
-- if the player isn't a cop then they won't receive the alert.
|
|
|
|
|
if not isCop() then
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- if the player is close to the shots then they won't receive a shot spotter alert.
|
|
|
|
|
if #(GetEntityCoords(PlayerPedId()) - pedCoords) < 50.0 then
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
blip = AddBlipForCoord(pedCoords.x, pedCoords.y, pedCoords.z)
|
|
|
|
|
setRoute = true
|
|
|
|
|
route = false
|
|
|
|
|
TriggerEvent("ND_shotSpotter:setRoute")
|
|
|
|
|
notify("~w~Press ~g~G ~w~to respond to the latest shot spotter.")
|
|
|
|
|
SetBlipSprite(blip, 161)
|
|
|
|
|
SetBlipAsShortRange(blip, true)
|
|
|
|
|
BeginTextCommandSetBlipName("STRING")
|
|
|
|
|
SetBlipColour(blip, 1)
|
|
|
|
|
if not postal then
|
|
|
|
|
msg = "Shotspotter detected in " .. street .. "."
|
|
|
|
|
AddTextComponentString("Shot Spotter: " .. street)
|
|
|
|
|
else
|
|
|
|
|
msg = "Shotspotter detected in " .. street .. ", postal: " .. postal .. "."
|
|
|
|
|
AddTextComponentString("Shot Spotter: " .. street .. ", postal: " .. postal)
|
|
|
|
|
end
|
|
|
|
|
TriggerEvent("chat:addMessage", {
|
|
|
|
|
color = {255, 0, 0},
|
|
|
|
|
args = {"^*Dispatch ", msg}
|
|
|
|
|
})
|
|
|
|
|
EndTextCommandSetBlipName(blip)
|
|
|
|
|
Citizen.Wait(config.shotSpotterTimer * 1000)
|
|
|
|
|
RemoveBlip(blip)
|
|
|
|
|
setRoute = false
|
|
|
|
|
route = false
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
-- set route to latest shot spotter location.
|
2022-09-01 04:11:48 -04:00
|
|
|
RegisterNetEvent("ND_shotSpotter:setRoute", function()
|
2022-07-08 23:16:36 +02:00
|
|
|
while setRoute do
|
|
|
|
|
Citizen.Wait(0)
|
|
|
|
|
if IsControlJustPressed(0, 113) then
|
|
|
|
|
if route then
|
|
|
|
|
route = false
|
|
|
|
|
SetBlipRoute(blip, route)
|
|
|
|
|
else
|
|
|
|
|
route = true
|
|
|
|
|
SetBlipRoute(blip, route)
|
|
|
|
|
SetBlipRouteColour(blip, 1)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
if config.testing then
|
|
|
|
|
Citizen.CreateThread(function()
|
|
|
|
|
Citizen.Wait(0)
|
|
|
|
|
for k, v in pairs(config.realisticShotSpotterLocations) do
|
|
|
|
|
k = AddBlipForRadius(v.x, v.y, v.z, 450.0)
|
|
|
|
|
SetBlipAlpha(k, 100)
|
|
|
|
|
end
|
|
|
|
|
end)
|
|
|
|
|
end
|