Police Zone Creation Script, Performance problem

Hello Guys i have a Police Zone Creation Script and the idle performance is 0.00 msec, when i create one zone its 0.02 msec and then when i delete the zone the idle stays at 0.02 msec. and when i repeet that cycle the resmon msec can go up to 2.0 msec or something. it goes higher for every zone added and deletet afterwarts. here is a video: Watch 2024-10-03 10-27-11 | Streamable

everybody who has an ideo how to fix that please help, i tried everything i know of. :pray:

Here is the client code:
client.lua (2.4 KB)

Here is the server code:
server.lua (2.0 KB)

Here is the config:
config.lua (1.2 KB)

Here is the fxmanifest:
fxmanifest.lua (291 Bytes)

I do see some things that you could correct/optimize.

fxmanifest:

shared_script {
	'@es_extended/imports.lua',
	'config.lua',
}

server_scripts {
	'server.lua'
}

client_scripts {
	'client.lua'
}


client.lua:
Each time you are adding a zone, you are creating a while that never ends. You need to break this when it’s not needed. For optimization, never allow whiles to run without a condition to break them or without a break/return within the body unless it’s absolutely needed.

CreateThread(function()
    while true do
      local vehicle = GetRandomVehicleInSphere(blipcoords.x, blipcoords.y, blipcoords.z, radius, 0, 70)
      if DoesEntityExist(vehicle) then
        local driver = GetPedInVehicleSeat(vehicle, -1)
        if DoesEntityExist(driver) and not IsPedAPlayer(driver) then
          TaskVehicleTempAction(driver, vehicle, 6, 1000)
          table.insert(stoppedVehicles, { driver = driver, vehicle = vehicle })         -- Store stopped vehicle
        end
      end
      Wait(0)
    end
  end)
1 Like

could you please tell me how i can implement that in this specific script / client code? Because i don’t know how, i’m sorry. i’m not that advanced :smiling_face_with_tear:

Try this. What it does is sets the current blip local to the event and if the current blip is not the same as the local locationBlip variable when it’s called again then it will stop. I also cleaned up some of the code.

local stoppedVehicles = {}  -- Table to store stopped vehicles
-- New variables
local radiusBlip
local locationBlip
-- End new variables

-- Add blips when "bsc_conclusionzone:addZone" event is triggered
RegisterNetEvent("bsc_conclusionzone:addZone")
AddEventHandler("bsc_conclusionzone:addZone", function(blipcoords, radius)
  -- Remove existing blips
  if radiusBlip ~= nil or locationBlip ~= nil then
    RemoveBlip(radiusBlip)
    RemoveBlip(locationBlip)
  end

  -- Set default radius if none provided
  radius = radius or blipRadius

  -- Create location blip
  locationBlip = AddBlipForCoord(blipcoords.x, blipcoords.y, blipcoords.z)
  SetBlipSprite(locationBlip, 161)
  SetBlipAsShortRange(locationBlip, true)
  SetBlipColour(locationBlip, Config.Color)
  SetBlipScale(locationBlip, 1.0)
  BeginTextCommandSetBlipName('STRING')
  AddTextComponentString(Config.Blipname)
  EndTextCommandSetBlipName(locationBlip)

  -- Create radius blip
  radiusBlip = AddBlipForRadius(blipcoords.x, blipcoords.y, blipcoords.z, radius)
  SetBlipAlpha(radiusBlip, 150)
  SetBlipColour(radiusBlip, Config.Color)

  -- Play sound
  if Config.Sounds then
    PlaySoundFrontend(-1, "BASE_JUMP_PASSED", "HUD_AWARDS", 0, 1)
  end

  -- Reset stopped vehicles
  stoppedVehicles = {}

  local currentLocationBlip = locationBlip

  CreateThread(function()
    while true do
      -- Check if locationBlip has changed
      if locationBlip ~= currentLocationBlip then
        break
      end

      local vehicle = GetRandomVehicleInSphere(blipcoords.x, blipcoords.y, blipcoords.z, radius, 0, 70)
      if DoesEntityExist(vehicle) then
        local driver = GetPedInVehicleSeat(vehicle, -1)
        if DoesEntityExist(driver) and not IsPedAPlayer(driver) then
          TaskVehicleTempAction(driver, vehicle, 6, 1000)
          table.insert(stoppedVehicles, { driver = driver, vehicle = vehicle })  -- Store stopped vehicle
        end
      end
      Wait(5)
    end
  end)
end)
1 Like

after i implemented your modified client.lua i can’t delete zones anymore. :sweat_smile:

Ah yeah. I updated it so that the new zones are stored in a table. The identifier will be the players source ID. If a player that already has a zone made tries to create a new one, the old one will be removed.

client.lua

local stoppedVehicles = {}  -- Table to store stopped vehicles
-- New variables
local radiusBlip = {}
local locationBlip = {}
-- End new variables

-- Add blips when "bsc_conclusionzone:addZone" event is triggered
RegisterNetEvent("bsc_conclusionzone:addZone")
AddEventHandler("bsc_conclusionzone:addZone", function(blipcoords, radius, id)
  -- Remove existing blips
  if radiusBlip[id] ~= nil or locationBlip[id] ~= nil then
    RemoveBlip(radiusBlip[id])
    RemoveBlip(locationBlip[id])
  end

  -- Set default radius if none provided
  radius = radius or blipRadius

  -- Create location blip
  locationBlip[id] = AddBlipForCoord(blipcoords.x, blipcoords.y, blipcoords.z)
  SetBlipSprite(locationBlip[id], 161)
  SetBlipAsShortRange(locationBlip[id], true)
  SetBlipColour(locationBlip[id], Config.Color)
  SetBlipScale(locationBlip[id], 1.0)
  BeginTextCommandSetBlipName('STRING')
  AddTextComponentString(Config.Blipname)
  EndTextCommandSetBlipName(locationBlip[id])

  -- Create radius blip
  radiusBlip[id] = AddBlipForRadius(blipcoords.x, blipcoords.y, blipcoords.z, radius)
  SetBlipAlpha(radiusBlip[id], 150)
  SetBlipColour(radiusBlip[id], Config.Color)

  -- Play sound
  if Config.Sounds then
    PlaySoundFrontend(-1, "BASE_JUMP_PASSED", "HUD_AWARDS", 0, 1)
  end

  -- Reset stopped vehicles
  stoppedVehicles = {}

  local currentLocationBlip = locationBlip[id]

  CreateThread(function()
    while true do
      -- Check if locationBlip has changed
      if locationBlip[id] ~= currentLocationBlip then
        break
      end

      local vehicle = GetRandomVehicleInSphere(blipcoords.x, blipcoords.y, blipcoords.z, radius, 0, 70)
      if DoesEntityExist(vehicle) then
        local driver = GetPedInVehicleSeat(vehicle, -1)
        if DoesEntityExist(driver) and not IsPedAPlayer(driver) then
          TaskVehicleTempAction(driver, vehicle, 6, 1000)
          table.insert(stoppedVehicles, { driver = driver, vehicle = vehicle })  -- Store stopped vehicle
        end
      end
      Wait(5)
    end
  end)
end)


-- Clear blips when "bsc_conclusionzone:clearZone" event is triggered
RegisterNetEvent('bsc_conclusionzone:clearZone')
AddEventHandler("bsc_conclusionzone:clearZone", function(id)
  if radiusBlip[id] ~= nil or locationBlip[id] ~= nil then
    RemoveBlip(radiusBlip[id])
    RemoveBlip(locationBlip[id])
  end

  for i, data in ipairs(stoppedVehicles) do
    if DoesEntityExist(data.vehicle) then
      if DoesEntityExist(data.driver) and not IsPedAPlayer(data.driver) then
        TaskVehicleDriveWander(data.driver, data.vehicle, 20.0, 786603)     -- Make NPC drive again
      end
    end
  end

  -- Play sound
  if Config.Sounds then
    PlaySoundFrontend(-1, "PEYOTE_COMPLETED", "HUD_AWARDS", 0, 1)
  end
end)

server.lua

-- Handles the "zoneAdd" command
RegisterCommand(Config.CreateCommand, function(source, args, rawCommand)
    -- Get the radius of the zone from the command arguments
    local radius = tonumber(args[1])
    local xPlayer = ESX.GetPlayerFromId(source)
    if isallowed(source) then
          local location = xPlayer.getCoords(true)
          
          -- I commented out this event trigger since it's already being triggered in the for loop
          --TriggerClientEvent("bsc_conclusionzone:addZone", -1, location, radius, source)
            -- Show a notification to the player
          TriggerClientEvent('esx:showAdvancedNotification', -1, Config.NotifyTitle, '~r~', Config.NotifyMessage, Config.NotifyPicture, 3)
          
          --make same blip for all players under jobs in config.jobs

          local xPlayers = ESX.GetPlayers()

          for i=1, #xPlayers, 1 do
            local xPlayer = ESX.GetPlayerFromId(xPlayers[i])
          
            xPlayer.triggerEvent('bsc_conclusionzone:addZone', location, radius, source)
          end

    end
            
end)
  
  -- Handles the "zoneRemove" command
  RegisterCommand(Config.RemoveCommand, function(source, args, rawCommand)
    -- Get the player who sent the command
    local xPlayer = ESX.GetPlayerFromId(source)
  
    -- Check if the player has an allowed job
      if isallowed(source) then
        -- Trigger an event to remove the zone on the client
        TriggerClientEvent("bsc_conclusionzone:clearZone", -1, source)
  
        -- Show a notification to the player
        TriggerClientEvent('esx:showAdvancedNotification', -1, Config.NotifyTitle,  '~r~',  Config.NotifyMessageRemoved, Config.NotifyPicture, 3)
      end   
  end)
   


function isallowed(source)
    local xPlayer = ESX.GetPlayerFromId(source)
    local job = xPlayer.getJob().name
    local allowed = false

    for k,v in pairs(Config.Jobs) do

      if job == v then
          allowed = true
          break
      else
          allowed = false
      end
    end
    
    return allowed
end
2 Likes

Also. In server.lua you can remove TriggerClientEvent("bsc_conclusionzone:addZone", -1, location, radius, source) since it’s already being triggered in the for loop.

2 Likes

Thank you very much. :innocent: i marked your latest modifcation as the SOLUTION :white_check_mark:. you are a great person, doing such things for free. :+1:

2 Likes