149 lines
		
	
	
	
		
			4.8 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			149 lines
		
	
	
	
		
			4.8 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
Utils.Zones = Utils.Zones or {}
 | 
						|
 | 
						|
-- We'll store all zones in a dictionary keyed by zone id
 | 
						|
local zones = {}
 | 
						|
 | 
						|
-- Generates a random, unused zone ID
 | 
						|
local function generateRandomZoneID()
 | 
						|
    while true do
 | 
						|
        -- e.g., "zone_123456789"
 | 
						|
        local attempt = "zone_" .. math.random(1, 999999999)
 | 
						|
        if not zones[attempt] then
 | 
						|
            return attempt
 | 
						|
        end
 | 
						|
    end
 | 
						|
end
 | 
						|
 | 
						|
--[[
 | 
						|
A zone looks like this internally:
 | 
						|
zones[id] = {
 | 
						|
    id             = string (unique)
 | 
						|
    coords         = vector3
 | 
						|
    radius         = number
 | 
						|
    onEnter        = function() end (optional)
 | 
						|
    onExit         = function() end (optional)
 | 
						|
    enabled        = bool (active or not)
 | 
						|
    isPlayerInside = bool (internal, tracks if player was inside last check)
 | 
						|
}
 | 
						|
]]
 | 
						|
 | 
						|
----------------------------------------------------------------------
 | 
						|
-- Create a zone
 | 
						|
-- Example usage:
 | 
						|
--   Utils.Zones.createZone({
 | 
						|
--       id             = "my_zone",  -- optional
 | 
						|
--       coords         = vector3(100.0, 200.0, 30.0),
 | 
						|
--       radius         = 50.0,
 | 
						|
--       onEnter        = function() ... end,
 | 
						|
--       onExit         = function() ... end,
 | 
						|
--   })
 | 
						|
----------------------------------------------------------------------
 | 
						|
function Utils.Zones.createZone(opts)
 | 
						|
    opts = opts or {}
 | 
						|
 | 
						|
    local zoneId = opts.id
 | 
						|
    if not zoneId or zoneId == "" then
 | 
						|
        -- If the user didn't provide an id, generate one
 | 
						|
        zoneId = generateRandomZoneID()
 | 
						|
    end
 | 
						|
 | 
						|
    zones[zoneId] = {
 | 
						|
        id = zoneId,
 | 
						|
        coords = opts.coords or vector3(0.0, 0.0, 0.0),
 | 
						|
        radius = opts.radius or 50.0,
 | 
						|
        onEnter = opts.onEnter,
 | 
						|
        onExit = opts.onExit,
 | 
						|
        enabled = true,         -- zones are enabled by default
 | 
						|
        isPlayerInside = false,       -- internal tracking
 | 
						|
    }
 | 
						|
 | 
						|
    return zoneId -- Return the final ID so the caller knows what was assigned
 | 
						|
end
 | 
						|
 | 
						|
----------------------------------------------------------------------
 | 
						|
-- Enable a zone by ID (it will begin checking distances, etc.)
 | 
						|
----------------------------------------------------------------------
 | 
						|
function Utils.Zones.enableZone(id)
 | 
						|
    local zone = zones[id]
 | 
						|
    if zone then
 | 
						|
        zone.enabled = true
 | 
						|
    end
 | 
						|
end
 | 
						|
 | 
						|
----------------------------------------------------------------------
 | 
						|
-- Disable a zone by ID (temporarily stops checks and triggers onExit if inside)
 | 
						|
----------------------------------------------------------------------
 | 
						|
function Utils.Zones.disableZone(id)
 | 
						|
    local zone = zones[id]
 | 
						|
    if zone and zone.enabled then
 | 
						|
        zone.enabled = false
 | 
						|
        if zone.isPlayerInside then
 | 
						|
            zone.isPlayerInside = false
 | 
						|
            if zone.onExit then
 | 
						|
                zone.onExit()
 | 
						|
            end
 | 
						|
        end
 | 
						|
    end
 | 
						|
end
 | 
						|
 | 
						|
----------------------------------------------------------------------
 | 
						|
-- Remove a zone by ID entirely (triggers onExit if the player is inside)
 | 
						|
----------------------------------------------------------------------
 | 
						|
function Utils.Zones.removeZone(id)
 | 
						|
    local zone = zones[id]
 | 
						|
    if zone then
 | 
						|
        if zone.isPlayerInside and zone.onExit then
 | 
						|
            zone.onExit()
 | 
						|
        end
 | 
						|
        zones[id] = nil
 | 
						|
    end
 | 
						|
end
 | 
						|
 | 
						|
----------------------------------------------------------------------
 | 
						|
-- Update a zone's properties by ID. 
 | 
						|
-- For example:
 | 
						|
--   Utils.Zones.updateZone("my_zone", { radius = 80.0 })
 | 
						|
----------------------------------------------------------------------
 | 
						|
function Utils.Zones.updateZone(id, newValues)
 | 
						|
    local zone = zones[id]
 | 
						|
    if not zone then return end
 | 
						|
    for k, v in pairs(newValues) do
 | 
						|
        zone[k] = v
 | 
						|
    end
 | 
						|
end
 | 
						|
 | 
						|
----------------------------------------------------------------------
 | 
						|
-- Main loop: checks each enabled zone for player enter/exit, calls callbacks
 | 
						|
----------------------------------------------------------------------
 | 
						|
CreateThread(function()
 | 
						|
    while true do
 | 
						|
        local playerPed = PlayerPedId()
 | 
						|
        local playerCoords = GetEntityCoords(playerPed)
 | 
						|
 | 
						|
        for _, zone in pairs(zones) do
 | 
						|
            if zone.enabled then
 | 
						|
                local dist = #(playerCoords - zone.coords)
 | 
						|
 | 
						|
                if dist < zone.radius then
 | 
						|
                    -- Player is inside this zone
 | 
						|
                    if not zone.isPlayerInside then
 | 
						|
                        zone.isPlayerInside = true
 | 
						|
                        if zone.onEnter then
 | 
						|
                            zone.onEnter()
 | 
						|
                        end
 | 
						|
                    end
 | 
						|
                else
 | 
						|
                    -- Player is outside this zone
 | 
						|
                    if zone.isPlayerInside then
 | 
						|
                        zone.isPlayerInside = false
 | 
						|
                        if zone.onExit then
 | 
						|
                            zone.onExit()
 | 
						|
                        end
 | 
						|
                    end
 | 
						|
                end
 | 
						|
            end
 | 
						|
        end
 | 
						|
 | 
						|
        Wait(1000)
 | 
						|
    end
 | 
						|
end)
 |