Radius and area blips in FiveM: drawing zones, territories and danger areas
Some things on a map are not a point. A red zone, a gang's turf, a search area for a missing person, a no-fly zone around the prison, the ring of a battle-royale storm: all of them are areas, and GTA V can draw areas on both the radar and the pause map. There are two natives for it, a circle and a rectangle, plus a handful of styling options that make the difference between a clean overlay and a smeared colour wash. This guide covers both shapes, how to build a territory grid, and how to make the gameplay check match exactly what the map shows.
Short answer: AddBlipForRadius(x, y, z, radius) draws a filled circle and AddBlipForArea(x, y, z, width, height) draws a filled rectangle, both scaled in world units. Colour them with SetBlipColour, soften them with SetBlipAlpha (around 80–128), turn a circle into an outline with SetRadiusBlipEdge(blip, true) and rotate a rectangle with SetBlipRotation. Area blips carry no name in a useful way, so pair each zone with an ordinary centre blip for the legend, and make your server-side zone check use the same numbers as the blip.

#Radius blips: circles
A radius blip is a filled circle whose size is given in metres, so it covers exactly the part of the world you asked for at every zoom level. It is the natural shape for red zones, robbery alarms and search areas.
local zone = AddBlipForRadius(1373.0, 3616.0, 34.9, 150.0)
SetBlipColour(zone, 1)
SetBlipAlpha(zone, 110)
local label = AddBlipForCoord(1373.0, 3616.0, 34.9)
SetBlipSprite(label, 84)
SetBlipColour(label, 1)
SetBlipScale(label, 0.9)
BeginTextCommandSetBlipName('STRING')
AddTextComponentSubstringPlayerName('Red Zone')
EndTextCommandSetBlipName(label)The fill uses the blip colour, so the ordinary colour ids apply: 1 red, 2 green, 3 blue, 5 yellow, 17 orange, 27 purple. Without SetBlipAlpha the circle is fully opaque and hides the roads beneath it, which is almost never what you want. Values around 80 to 128 keep the map readable.
The second blip is not decoration. Radius blips are poor legend entries and have no useful icon, so a normal blip at the centre gives players something to hover, a name in the legend and a point to route to. Sprite 84 is radar_rampage, a skull-style icon that suits a danger area.
#Outlines instead of fills
SetRadiusBlipEdge(blip, true) renders a radius blip as a ring instead of a disc. Rings are better when several zones overlap, when the area is large, or when the map underneath needs to stay fully visible, such as a police perimeter around a bank.
local perimeter = AddBlipForRadius(254.0, 225.0, 101.9, 250.0)
SetBlipColour(perimeter, 3)
SetBlipAlpha(perimeter, 200)
SetRadiusBlipEdge(perimeter, true)#Area blips: rectangles
AddBlipForArea(x, y, z, width, height) draws a filled rectangle centred on the coordinates. Width runs along the world X axis and height along Y before any rotation. The Cfx native reference recommends setting a rotation and colour explicitly so the rectangle does not turn with the camera on the radar.
local yard = AddBlipForArea(1180.0, -3200.0, 6.0, 260.0, 120.0)
SetBlipRotation(yard, 0)
SetBlipColour(yard, 17)
SetBlipAlpha(yard, 100)
local docks = AddBlipForArea(-60.0, -2500.0, 6.0, 300.0, 140.0)
SetBlipRotation(docks, 55)
SetBlipColour(docks, 5)
SetBlipAlpha(docks, 100)SetBlipRotation takes whole degrees. When you derive the angle from a heading, round it with math.floor(heading + 0.5); fractional values are truncated and small misalignments show on long rectangles. For fractional angles there is also SetBlipSquaredRotation(blip, heading), which accepts a float.
When the area is outside the current radar view, the game shows it as a regular blip clamped to the radar edge, using the blip's sprite and colour. That is useful for "the zone is that way" hints, and another reason to give the zone a sensible colour.
#Building a gang territory grid
The classic San Andreas style turf map is a grid of squares, each coloured by its owner. Area blips make this straightforward. Keep ownership on the server, send the grid state to clients, and recolour squares when ownership changes rather than recreating them.
local CELL = 200.0
local ORIGIN = vector2(-600.0, -2000.0)
local COLS, ROWS = 8, 10
local OWNER_COLOURS = { ballas = 27, families = 2, vagos = 5, none = 4 }
local cells = {}
local function cellCentre(col, row)
return ORIGIN.x + (col - 0.5) * CELL, ORIGIN.y + (row - 0.5) * CELL
end
local function buildGrid()
for col = 1, COLS do
for row = 1, ROWS do
local x, y = cellCentre(col, row)
local blip = AddBlipForArea(x, y, 0.0, CELL, CELL)
SetBlipRotation(blip, 0)
SetBlipColour(blip, OWNER_COLOURS.none)
SetBlipAlpha(blip, 60)
SetBlipDisplay(blip, 3)
cells[col .. ':' .. row] = blip
end
end
end
RegisterNetEvent('turf:owners', function(owners)
for key, owner in pairs(owners) do
local blip = cells[key]
if blip then
SetBlipColour(blip, OWNER_COLOURS[owner] or OWNER_COLOURS.none)
SetBlipAlpha(blip, owner == 'none' and 40 or 110)
end
end
end)
CreateThread(buildGrid)Display mode 3 keeps the grid on the pause map only, which is where players plan; the radar stays clean for driving. Eighty cells is comfortable. Keep grid sizes in the low hundreds of blips at most: the radar and the pause map process every blip, and very large grids can make the pause map sluggish on weaker PCs.
| Choice | Recommendation |
|---|---|
| Cell size | 150–250 m; smaller cells need many more blips |
| Unowned cells | White (4) at low alpha, or no blip at all |
| Contested cells | Flash the cell with SetBlipFlashes for the duration of the war |
| Visibility | Pause map only (display 3) unless turf is core gameplay |
| Source of truth | Server; clients only render what they are sent |
#Making the check match the map
The fastest way to lose players' trust in a zone is a mismatch: the map says you are outside the red zone and the script says you are inside. Use one config for both the blip and the check.
function InsideRadius(pos, centre, radius)
return #(pos.xy - centre.xy) <= radius
end
function InsideRotatedArea(pos, centre, width, height, degrees)
local r = math.rad(-degrees)
local dx, dy = pos.x - centre.x, pos.y - centre.y
local lx = dx * math.cos(r) - dy * math.sin(r)
local ly = dx * math.sin(r) + dy * math.cos(r)
return math.abs(lx) <= width / 2 and math.abs(ly) <= height / 2
endDo the authoritative check on the server with GetEntityCoords(GetPlayerPed(src)). Client checks are fine for showing UI, but anything that grants loot, removes safety or triggers PvP rules has to be decided server-side. Test the rotation direction once in game with a debug marker on each corner; blip rotation and trigonometry conventions are easy to get mirrored.
Irregular shapes are better handled by a polygon zone library on the gameplay side. On the map you can approximate them with several rectangles, or draw the outline with a GPS custom route (see GPS routes), bearing in mind there is only one custom-route slot.
#Moving and shrinking zones
The simplest reliable way to shrink a zone such as a battle-royale storm is to remove the radius blip and create a new one at each step, because the radius you pass at creation is exactly the world size you get. That is cheap when it happens every few seconds. For a smooth effect, step the radius down in small increments rather than trying to animate every frame.
local storm
local function setStorm(centre, radius)
if storm and DoesBlipExist(storm) then RemoveBlip(storm) end
storm = AddBlipForRadius(centre.x, centre.y, centre.z, radius)
SetBlipColour(storm, 1)
SetBlipAlpha(storm, 90)
SetRadiusBlipEdge(storm, true)
end
RegisterNetEvent('storm:update', setStorm)Moving an area blip is simpler: SetBlipCoords(blip, x, y, z) moves it without recreating it.
#Common problems
| Symptom | Cause | Fix |
|---|---|---|
| Zone covers the roads completely | No alpha set | SetBlipAlpha(blip, 80) to 128 |
| Rectangle turns when the radar rotates | No explicit rotation | Call SetBlipRotation(blip, 0) or your angle after creating it |
| Zone visible to players who should not see it | Blip created for everyone at resource start | Create zone blips from a server event sent only to the right players |
| Zones duplicate after a restart | Old blips not removed | Remove them in onResourceStop |
| Map says outside, script says inside | Check uses different numbers or ignores rotation | Share one config and rotate the point into the zone frame |
| Grid is slow to open on the pause map | Thousands of cells | Larger cells, or skip blips for unowned cells |
Most of these come from the same root: the blip and the gameplay rule were written separately. A single shared config file that both the client drawing code and the server check read from removes the whole class of bugs. Put zone definitions in a shared_script so the numbers exist once.
Zones = {
redzone_sandy = { type = 'radius', centre = vector3(1373.0, 3616.0, 34.9), radius = 150.0, colour = 1 },
docks_turf = { type = 'area', centre = vector3(-60.0, -2500.0, 6.0), width = 300.0, height = 140.0, rotation = 55, colour = 5 },
}#Readability on custom maps
- Zones stack. Two overlapping 100-alpha circles look like one 180-alpha blob; use outlines when overlap is expected.
- Match zone colours to meaning and stick to it: red for danger, blue for police control, gang colours for turf.
- A dark minimap makes low-alpha zones hard to see; raise alpha a little or use outlines on dark themes.
- Keep the centre label blip short range if many zones exist, so the radar does not fill with skull icons.
Zone overlays sit on top of whatever map texture the server uses, so it is worth testing them on the actual map players see. Flat, low-noise styles such as those in the minimap catalogue or the NoPixel-style minimap keep translucent zones legible where the satellite map turns them muddy. For redzone-heavy servers, the redzone map guide covers layout choices in more depth.
Questions
How do I draw a circle on the FiveM map?
AddBlipForRadius(x, y, z, radius) with the radius in metres, then set a colour and an alpha around 100.How do I draw only the outline of a zone?
SetRadiusBlipEdge(blip, true) on a radius blip. It does not work on area rectangles.How do I rotate an area blip?
SetBlipRotation(blip, degrees) with a whole number, or SetBlipSquaredRotation for a fractional angle.Why is my zone blip hiding the map?
SetBlipAlpha(blip, 80) to SetBlipAlpha(blip, 128).How do I name a radius blip?
Can I show a zone only to one gang or job?
Ready to pick a map?
Twelve themes on three base map styles, $8 each, instant download.
Relevant to what you just read