-
Notifications
You must be signed in to change notification settings - Fork 192
ComboZone
An ComboZone is a collection of other zones, which allows you to take actions on all the zones at once. It is created by invoking the ComboZone:Create()
method, and passing in a table of zones, and a table of options:
local circleA = CircleZone:Create(vector3(314.94, -239.82, 54.0), 1.5, {
name="a",
data={foo=1}
})
local circleB = CircleZone:Create(vector3(315.41, -238.25, 54.03), 1.5, {
name="b",
data={foo=2}
})
local circleC = CircleZone:Create(vector3(316.8, -239.51, 54.0), 1.5, {
name="c",
data={foo=3}
})
local combo = ComboZone:Create({circleA, circleB, circleC}, {name="combo", debugPoly=true})
combo:onPlayerInOut(function(isPointInside, point, zone)
print("combo: isPointInside is", isPointInside, " for point", point)
if zone then
print(zone.data.foo)
end
end)
Notes:
- ComboZones are most useful when you have a large set of zones that all do the same thing. For example you want a circle zone around every atm in the city that when a player is inside, you can trigger some UI or allow the player to press a button to open their bank account.
- ComboZones can handle tens of thousands of zones just fine with the grid optimization, as long as they are not all clustered together. The "soft" limit you'll hit first is FiveM's memory warning banner, at 50 MiBs. This happens at 20k BoxZones and 40k CircleZones respectively. But that can be avoided by spreading the zones out into multiple resources, if you really need to.
Property | Type | Default | Required | Description |
---|---|---|---|---|
name | String | nil | false | Name of the zone |
useGrid | Boolean | true | false | If true, enables the optimization grid for the ComboZone, which can greatly increase the amount of zones it can handle. This is only compatible with zones that never move or change size. |
debugPoly | Boolean | false | false | If true, draws all zones in the ComboZone |
data | table | {} | false | A table that can hold any arbitrary data on the zone |
Allows you to add zones to the ComboZone after initial creation. You should generally try to avoid using this after resource load if possible, because it has a non-zero cost.
ComboZones have access to methods like isPointInside() and helpers like onPointInOut() and onPlayerInOut(), but there is one thing that is different about them for ComboZones: they pass back the zone that was entered (and exited for onPointInOut and onPlayerInOut).
-- insideZone=the zone the point is in (or nil if isInside=false)
local isInside, insideZone = comboZone:isPointInside(GetEntityCoords(PlayerPedId()))
-- For the onPointInOut and onPlayerInOut helpers this additional value is passed to the callback
comboZone:onPlayerInOut(function(isPointInside, point, zone)
-- zone can be nil if the player/point starts OUTSIDE of the comboZone
if zone then
if isPointInside then
-- zone=zone player just entered
else
-- zone=last zone player entered (aka zone player just left)
end
end
end)
Exhaustiveness determines whether the ComboZone will stop checking after the first zone is found to contain the point, or if it will check all the zones. This could be useful if some of the zones overlap, but is more expensive (when inside at least one zone) and has a small memory churn (when inside at least one zone) because it has to always go through all the zones and allocate space to hold all the inside zones.
-- insideZones is a table of ALL zones the point is inside
local isInside, insideZones = comboZone:isPointInsideExhaustive(GetEntityCoords(PlayerPedId()))
onPointInOut() and onPlayerInOut() have this same option, and insideZones
is passed to the callback function, as well as enteredZones
and leftZones
. All three of these will be nil if there are zero zones that apply to them, so do a nil check if you are going to use them. enteredZones
holds all zones the player/point just entered, and leftZones
holds all zones the player/point just left.
combo:onPlayerInOutExhaustive(function(isPointInside, point, insideZones, enteredZones, leftZones)
print("combo: isPointInside is", isPointInside, " for point", point)
if insideZones then
print("Inside Zones")
for i=1, #insideZones do
print(" data.foo=" .. tostring(insideZones[i].data.foo))
end
end
if enteredZones then
print("Entered Zones")
for i=1, #enteredZones do
print(" data.foo=" .. tostring(enteredZones[i].data.foo))
end
end
if leftZones then
print("Left Zones")
for i=1, #leftZones do
print(" data.foo=" .. tostring(leftZones[i].data.foo))
end
end
end)