From 7f50bca869f522fcab57270ca999b277c120fe0f Mon Sep 17 00:00:00 2001 From: Marshular's Development <78507312+marshular@users.noreply.github.com> Date: Sun, 21 Jan 2024 00:47:52 -0800 Subject: [PATCH 1/6] Update fxmanifest.lua --- fxmanifest.lua | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/fxmanifest.lua b/fxmanifest.lua index 6194898..dcb0045 100644 --- a/fxmanifest.lua +++ b/fxmanifest.lua @@ -8,13 +8,16 @@ fx_version "cerulean" game "gta5" lua54 "yes" +shared_script "@ND_Core/init.lua" + server_scripts { "config_server.lua", "source/server.lua" } + client_scripts { "config_client.lua", "source/client.lua" } -dependency "ND_Core" \ No newline at end of file +dependency "ND_Core" From 6ce6bffcbc67fabc4bbdcc1c6940e19baf47dfc4 Mon Sep 17 00:00:00 2001 From: Marshular's Development <78507312+marshular@users.noreply.github.com> Date: Sun, 21 Jan 2024 00:48:14 -0800 Subject: [PATCH 2/6] Update config_server.lua --- config_server.lua | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/config_server.lua b/config_server.lua index fd0cae7..cbafcd6 100644 --- a/config_server.lua +++ b/config_server.lua @@ -1,4 +1,3 @@ server_config = { - useDiscordLogging = true, - discordWebhook = "https://discord.com/api/webhooks/873744008122335252/zk53XWv0ZfD-BD2Su6VYGPzUgNW0NjLrj7hVBQFVgp_ByO0f0rpMwx7fsNNNjyVp4GUT", -} \ No newline at end of file + discordWebhook = "https://discord.com/api/webhooks/873744008122335252/zk53XWv0ZfD-BD2Su6VYGPzUgNW0NjLrj7hVBQFVgp_ByO0f0rpMwx7fsNNNjyVp4GUT" +} From 3431f28907ffc993abdb222ca60b3281243da139 Mon Sep 17 00:00:00 2001 From: Marshular's Development <78507312+marshular@users.noreply.github.com> Date: Sun, 21 Jan 2024 00:49:23 -0800 Subject: [PATCH 3/6] Update client.lua --- source/client.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/source/client.lua b/source/client.lua index b3cc3d5..7846f62 100644 --- a/source/client.lua +++ b/source/client.lua @@ -1,6 +1,5 @@ -- For support join my discord: https://discord.gg/Z9Mxu72zZ6 -NDCore = exports["ND_Core"]:GetCoreObject() local alreadyShot = false local setRoute = false local route = false From 1d4713e6793dd0fc2f578ad8dc4fd4b7b438a6ef Mon Sep 17 00:00:00 2001 From: Marshular's Development <78507312+marshular@users.noreply.github.com> Date: Sun, 21 Jan 2024 00:49:33 -0800 Subject: [PATCH 4/6] Update server.lua --- source/server.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/source/server.lua b/source/server.lua index 07206c7..1780b18 100644 --- a/source/server.lua +++ b/source/server.lua @@ -1,6 +1,5 @@ -- For support join my discord: https://discord.gg/Z9Mxu72zZ6 -NDCore = exports["ND_Core"]:GetCoreObject() NDCore.Functions.VersionChecker("ND_ShotSpotter", GetCurrentResourceName(), "https://github.com/ND-Framework/ND_ShotSpotter", "https://raw.githubusercontent.com/ND-Framework/ND_ShotSpotter/main/fxmanifest.lua") RegisterNetEvent("ND_ShotSpotter:Trigger", function(street, pedCoords, postal, zoneName) From f449396424ec44f5caf681be18a7dcbba6e11903 Mon Sep 17 00:00:00 2001 From: Marshular's Development <78507312+marshular@users.noreply.github.com> Date: Sun, 21 Jan 2024 00:50:09 -0800 Subject: [PATCH 5/6] Update server.lua --- source/server.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/server.lua b/source/server.lua index 1780b18..89b4b7d 100644 --- a/source/server.lua +++ b/source/server.lua @@ -3,7 +3,7 @@ NDCore.Functions.VersionChecker("ND_ShotSpotter", GetCurrentResourceName(), "https://github.com/ND-Framework/ND_ShotSpotter", "https://raw.githubusercontent.com/ND-Framework/ND_ShotSpotter/main/fxmanifest.lua") RegisterNetEvent("ND_ShotSpotter:Trigger", function(street, pedCoords, postal, zoneName) - if server_config.useDiscordLogging then + if server_config.discordWebhook then local embed = { { title = "ShotSpotter Alert", From b12e71f7d0e5e68d367b26eeecf67b532ebf424a Mon Sep 17 00:00:00 2001 From: Marshular Date: Mon, 29 Jan 2024 19:16:58 -0800 Subject: [PATCH 6/6] rework, add v2 support & mdt support --- config_client.lua | 61 ---------------- config_server.lua | 3 - data/configuration.lua | 49 +++++++++++++ fxmanifest.lua | 34 ++++----- source/client.lua | 155 ----------------------------------------- source/client/main.lua | 72 +++++++++++++++++++ source/server.lua | 37 ---------- source/server/main.lua | 17 +++++ 8 files changed, 156 insertions(+), 272 deletions(-) delete mode 100644 config_client.lua delete mode 100644 config_server.lua create mode 100644 data/configuration.lua delete mode 100644 source/client.lua create mode 100644 source/client/main.lua delete mode 100644 source/server.lua create mode 100644 source/server/main.lua diff --git a/config_client.lua b/config_client.lua deleted file mode 100644 index 37a0cf0..0000000 --- a/config_client.lua +++ /dev/null @@ -1,61 +0,0 @@ --- For support join my discord: https://discord.gg/Z9Mxu72zZ6 - -config = { - shotSpotterDelay = 10, -- delay (in seconds) when cops will receive a notification after there has been a shooting. - shotSpotterTimer = 120, -- How long should the shot spotter stay on the map. - shotSpotterCooldown = 30, -- Cooldown for the next time a player can trigger it again. - - shotSpotterUsePostal = true, -- if you're using the nearest postal script turn this to true. - postalResourceName = "nearest-postal", -- the resource name of the nearest postal script, this is used for the export. - - -- This is the departments that will receive the shot spotter alerts. - receiveAlerts = { - "SAHP", - "LSPD", - "BCSO" - }, - - -- Weapon that won't be triggered by the shot spotter. - weaponBlackList = { - "weapon_flaregun", - "weapon_stungun_mp", - "weapon_grenade", - "weapon_bzgas", - "weapon_molotov", - "weapon_stickybomb", - "weapon_proxmine", - "weapon_snowball", - "weapon_pipebomb", - "weapon_ball", - "weapon_smokegrenade", - "weapon_flare", - "weapon_petrolcan", - "weapon_fireextinguisher", - "weapon_hazardcan", - "weapon_fertilizercan" - }, - - useRealisticShotSpotter = false, -- this is if you want to enable the shot spotter only when the player is inside one of the zones below. The zones are in the city and a little around it. - realisticShotSpotterLocations = { - {x = 653.4214, y = -648.7440, z = 57.1897}, - {x = 1015.9837, y = -255.2573, z = 85.5857}, - {x = 329.9973, y = 288.9604, z = 120.1029}, - {x = -202.7689, y = -327.3490, z = 66.0497}, - {x = 31.3205, y = -875.2959, z = 31.4629}, - {x = 70.1372, y = -1718.3291, z = 34.2056}, - {x = 1196.9178, y = -1624.6641, z = 50.3403}, - {x = -852.9095, y = -1215.8782, z = 9.2463}, - {x = -932.7648, y = -448.8844, z = 42.9436}, - {x = -1713.6848, y = 478.4267, z = 130.3795}, - {x = -596.5602, y = 515.0753, z = 109.675}, - {x = 716.6274, y = -1958.7434, z = 44.7564} - }, - - testing = false -- if you're adding zones above and want to enable the blips on the map to see where the zone is then turn this on, otherwise turn it off. -} - -function notify(message) - BeginTextCommandThefeedPost("STRING") - AddTextComponentSubstringPlayerName(message) - EndTextCommandThefeedPostTicker(0,1) -end \ No newline at end of file diff --git a/config_server.lua b/config_server.lua deleted file mode 100644 index cbafcd6..0000000 --- a/config_server.lua +++ /dev/null @@ -1,3 +0,0 @@ -server_config = { - discordWebhook = "https://discord.com/api/webhooks/873744008122335252/zk53XWv0ZfD-BD2Su6VYGPzUgNW0NjLrj7hVBQFVgp_ByO0f0rpMwx7fsNNNjyVp4GUT" -} diff --git a/data/configuration.lua b/data/configuration.lua new file mode 100644 index 0000000..43858c9 --- /dev/null +++ b/data/configuration.lua @@ -0,0 +1,49 @@ +return { + shotSpotterDelay = 10, -- delay (in seconds) when cops will receive a notification after there has been a shooting. + shotSpotterCooldown = 30, -- Cooldown for the next time a player can trigger it again. + + postalResourceName = 'nearest-postal', -- set to false to disable, the resource name of the nearest postal script, this is used for the export. + + whitelistedJobs = { -- jobs that won't trigger shot spotter + ["lspd"] = true, + ["bcso"] = true, + ["sahp"] = true + }, + + -- Weapon that won't be triggered by the shot spotter. + weaponBlackList = { + `weapon_flaregun`, + `weapon_stungun_mp`, + `weapon_grenade`, + `weapon_bzgas`, + `weapon_molotov`, + `weapon_stickybomb`, + `weapon_proxmine`, + `weapon_snowball`, + `weapon_pipebomb`, + `weapon_ball`, + `weapon_smokegrenade`, + `weapon_flare`, + `weapon_petrolcan`, + `weapon_fireextinguisher`, + `weapon_hazardcan`, + `weapon_fertilizercan` + }, + + realisticShotSpotter = { -- set to false to disable, this is if you want to enable the shot spotter only when the player is inside one of the zones below. The zones are in the city and a little around it. + {x = 653.4214, y = -648.7440, z = 57.1897}, + {x = 1015.9837, y = -255.2573, z = 85.5857}, + {x = 329.9973, y = 288.9604, z = 120.1029}, + {x = -202.7689, y = -327.3490, z = 66.0497}, + {x = 31.3205, y = -875.2959, z = 31.4629}, + {x = 70.1372, y = -1718.3291, z = 34.2056}, + {x = 1196.9178, y = -1624.6641, z = 50.3403}, + {x = -852.9095, y = -1215.8782, z = 9.2463}, + {x = -932.7648, y = -448.8844, z = 42.9436}, + {x = -1713.6848, y = 478.4267, z = 130.3795}, + {x = -596.5602, y = 515.0753, z = 109.675}, + {x = 716.6274, y = -1958.7434, z = 44.7564} + }, + + testing = false -- if you're adding zones above and want to enable the blips on the map to see where the zone is then turn this on, otherwise turn it off. +} \ No newline at end of file diff --git a/fxmanifest.lua b/fxmanifest.lua index dcb0045..b6a5396 100644 --- a/fxmanifest.lua +++ b/fxmanifest.lua @@ -1,23 +1,25 @@ -- For support join my discord: https://discord.gg/Z9Mxu72zZ6 -author "Andyyy#7666, N1K0#0001" -description "Shot Spotter Script (ND Framework)" -version "2.1.0" +fx_version 'cerulean' +game 'gta5' +lua54 'yes' -fx_version "cerulean" -game "gta5" -lua54 "yes" +author 'Andyyy#7666, N1K0#0001' +description 'Shot Spotter Script (ND Framework)' +version '2.1.0' -shared_script "@ND_Core/init.lua" +shared_scripts { + '@ND_Core/init.lua', + '@ox_lib/init.lua', + 'data/configuration.lua' +} -server_scripts { - "config_server.lua", - "source/server.lua" -} +server_script 'source/server/main.lua' -client_scripts { - "config_client.lua", - "source/client.lua" -} +client_script 'source/client/main.lua' -dependency "ND_Core" +dependencies { + 'ND_Core', + 'ND_MDT', + 'ox_lib' +} \ No newline at end of file diff --git a/source/client.lua b/source/client.lua deleted file mode 100644 index 7846f62..0000000 --- a/source/client.lua +++ /dev/null @@ -1,155 +0,0 @@ --- For support join my discord: https://discord.gg/Z9Mxu72zZ6 - -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() - local job = NDCore.Functions.GetSelectedCharacter().job - for _, department in pairs(config.receiveAlerts) do - if department == job then - 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 - 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) - Wait(config.shotSpotterCooldown * 1000) - alreadyShot = false -end - --- Check if the player is shooting. -CreateThread(function() - while true do - Wait(0) - local ped = PlayerPedId() - if IsPedShooting(ped) then - triggerShotSpotter(ped) - end - end -end) - -RegisterNetEvent("ND_ShotSpotter:Report", function(street, pedCoords, postal) - -- 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) - Wait(config.shotSpotterTimer * 1000) - RemoveBlip(blip) - setRoute = false - route = false -end) - --- set route to latest shot spotter location. -RegisterNetEvent("ND_shotSpotter:setRoute", function() - while setRoute do - 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 - CreateThread(function() - 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 diff --git a/source/client/main.lua b/source/client/main.lua new file mode 100644 index 0000000..55cc398 --- /dev/null +++ b/source/client/main.lua @@ -0,0 +1,72 @@ +-- For support join my discord: https://discord.gg/Z9Mxu72zZ6 + +local alreadyShot = false +local config = lib.load("data.configuration") + +-- 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. +local function isInShotSpotterLocation(coords) + for _, location in pairs(config.realisticShotSpotter) do + if #(coords - vector3(location.x, location.y, location.z)) < 450.0 then return true end + end + return false +end + +function triggerShotSpotter(ped) + local player = NDCore.getPlayer() + local job = player.job.name + local coords = GetEntityCoords(ped) + local suppressed = IsPedCurrentWeaponSilenced(ped) + local currentWeapon = cache.weapon + local zoneName = GetLabelText(GetNameOfZone(coords.x, coords.y, coords.z)) + local street = GetStreetNameAtCoord(coords.x, coords.y, coords.z) + local streetHash = GetStreetNameFromHashKey(street) + + if config.postalResourceName then postal = exports[config.postalResourceName]:getPostal() + else postal = false end + + if config.realisticShotSpotter and not isInShotSpotterLocation(coords) then return end -- if the player isn't in the realistic shot spotter locations then the shot spotter won't trigger. + + for _, weapon in pairs(config.weaponBlackList) do -- if the player has a blacklisted weapon then the shot spotter won't trigger. + if weapon == currentWeapon then return end + end + + if suppressed then return end -- if the player has a suppresor attached to their weapon then the shot spotter won't trigger. + + if config.whitelistedJobs[job] then return end -- if the player has the job then they won't trigger the shotspotter. + + if alreadyShot 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. + + alreadyShot = true + Wait(config.shotSpotterDelay * 1000) + TriggerServerEvent('ND_ShotSpotter:Trigger', streetHash, coords, postal, zoneName) + Wait(config.shotSpotterCooldown * 1000) + alreadyShot = false +end + +-- +-- NEED TO FIND BETTER METHOD OF THESE THREADS +-- + +CreateThread(function() -- Check if the player is shooting. + while true do + Wait(0) + local ped = cache.ped + if IsPedShooting(ped) then + triggerShotSpotter(ped) + end + end +end) + +if config.testing then + CreateThread(function() + 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 + +-- +-- NEED TO FIND BETTER METHOD OF THESE THREADS +-- \ No newline at end of file diff --git a/source/server.lua b/source/server.lua deleted file mode 100644 index 89b4b7d..0000000 --- a/source/server.lua +++ /dev/null @@ -1,37 +0,0 @@ --- For support join my discord: https://discord.gg/Z9Mxu72zZ6 - -NDCore.Functions.VersionChecker("ND_ShotSpotter", GetCurrentResourceName(), "https://github.com/ND-Framework/ND_ShotSpotter", "https://raw.githubusercontent.com/ND-Framework/ND_ShotSpotter/main/fxmanifest.lua") - -RegisterNetEvent("ND_ShotSpotter:Trigger", function(street, pedCoords, postal, zoneName) - if server_config.discordWebhook then - local embed = { - { - title = "ShotSpotter Alert", - description = "Gunshots detected on " .. zoneName .. ", " .. street .. "." , - fields = { - { - name = "Location:", - value = zoneName .. ", **" .. street .. "**" - } - }, - footer = { - icon_url = "https://i.imgur.com/notBtrZ.png", - text = "Created by Andyyy#7666" - }, - thumbnail = { - url = "https://i.imgur.com/BTbxJZu.png" - }, - color = 16722976 - } - } - if postal then - embed[1].description = "Gunshots detected on " .. zoneName .. ", " .. street .. " (" .. postal .. ")." - embed[1].fields[2] = { - name = "Postal:", - value = postal - } - end - PerformHttpRequest(server_config.discordWebhook, function(err, text, headers) end, 'POST', json.encode({username = "ND Shotspotter", embeds = embed}), {["Content-Type"] = "application/json"}) - end - TriggerClientEvent("ND_ShotSpotter:Report", -1, street, pedCoords, postal) -end) diff --git a/source/server/main.lua b/source/server/main.lua new file mode 100644 index 0000000..4bf3b23 --- /dev/null +++ b/source/server/main.lua @@ -0,0 +1,17 @@ +-- For support join my discord: https://discord.gg/Z9Mxu72zZ6 + +lib.versionCheck('ND-Framework/ND_ShotSpotter') + +RegisterNetEvent("ND_ShotSpotter:Trigger", function(street, pedCoords, postal, zoneName) + local mdt = exports["ND_MDT"] + local location = "" + + if postal then location = postal .. ' ' .. street .. ', ' .. zoneName + else location = street .. ', ' .. zoneName end + + mdt:createDispatch({ + location = location, + callDescription = "Shots fired", + coords = vec3(pedCoords.x, pedCoords.y, pedCoords.z) + }) +end)