function ZoneController.updateDetection(S)local z={enterDetection="\095\099\117\114\114\101\110\116\069\110\116\101\114\068\101\116\101\099\116\105\111\110";exitDetection="\095\099\117\114\114\101\110\116\069\120\105\116\068\101\116\101\099\116\105\111\110"}for z,J in pairs(z)do local U=S[z]if U==enum.Detection.Automatic then if charactersTotalVolume>WHOLE_BODY_DETECTION_LIMIT then U=enum.Detection.Centre else U=enum.Detection.WholeBody end end S[J]=U end end function ZoneController._formHeartbeat(S)local z=heartbeatConnections[S]if z then return end local J=0 z=heartbeat:Connect(function()local z=os.clock()if z>=J then local U local K for z,J in pairs(activeZones)do if z.activeTriggers[S]then local S=z.accuracy if U==nil or S<U then U=S end ZoneController.updateDetection(z)local J=z._currentEnterDetection if K==nil or J<K then K=J end end end local t=U local v=heartbeatActions[S](K)for z,J in pairs(activeZones)do if z.activeTriggers[S]then local J=z.accuracy local U=v[z]or{}local K=false for S,z in pairs(U)do K=true break end if K and J>t then t=J end z:_updateOccupants(S,U)end end local Q=enum.Accuracy.getProperty(t)J=z+Q end end)heartbeatConnections[S]=z end function ZoneController._deregisterConnection(S,z)activeConnections-=1 if activeTriggers[z]==1 then activeTriggers[z]=nil local S=heartbeatConnections[z]if S then heartbeatConnections[z]=nil S:Disconnect()end else activeTriggers[z]-=1 end S.activeTriggers[z]=nil if dictLength(S.activeTriggers)==0 then activeZones[S]=nil ZoneController._updateZoneDetails()end if S.touchedConnectionActions[z]then S:_disconnectTouchedConnection(z)end end function ZoneController._updateZoneDetails()activeParts={}activePartToZone={}allParts={}allPartToZone={}activeZonesTotalVolume=0 for S,z in pairs(registeredZones)do local J=activeZones[S]if J then activeZonesTotalVolume+=S.volume end for z,U in pairs(S.groupParts)do if J then table.insert(activeParts,U)activePartToZone[U]=S end table.insert(allParts,U)allPartToZone[U]=S end end end function ZoneController._getZonesAndPlayers(S,z,J,U)local K=z if not K then for S,z in pairs(S)do K+=S.volume end end local t={}if charactersTotalVolume<K then for S,z in pairs(players:GetPlayers())do local K=ZoneController.getTouchingZones(z,J,U)for S,U in pairs(K)do if not J or U.activeTriggers.player then fillOccupants(t,U,z)end end end else for S,z in pairs(S)do if not J or S.activeTriggers.player then local z=workspace:FindPartsInRegion3WithWhiteList(S.region,bodyParts,#bodyParts)local J={}for S,z in pairs(z)do local U=z.Parent.Name if not J[U]then J[U]=players:GetPlayerFromCharacter(z.Parent)end end for z,J in pairs(J)do if J and S:findPlayer(J)then fillOccupants(t,S,J)end end end end end return t end
-- This decides what to do if detection is 'Automatic'
-- This is placed in ZoneController instead of the Zone object due to the ZoneControllers all-knowing group-minded logic
function ZoneController.updateDetection(zone)
	local detectionTypes = {
		["enterDetection"] = "_currentEnterDetection",
		["exitDetection"] = "_currentExitDetection",
	}
	for detectionType, currentDetectionName in pairs(detectionTypes) do
		local detection = zone[detectionType]
		if detection == enum.Detection.Automatic then
			if charactersTotalVolume > WHOLE_BODY_DETECTION_LIMIT then
				detection = enum.Detection.Centre
			else
				detection = enum.Detection.WholeBody
			end
		end
		zone[currentDetectionName] = detection
	end
end

function ZoneController._formHeartbeat(registeredTriggerType)
	local heartbeatConnection = heartbeatConnections[registeredTriggerType]
	if heartbeatConnection then
		return
	end
	-- This will only ever connect once per triggerType per server
	-- This means instead of initiating a loop per-zone we can handle everything within
	-- a singular connection. This is particularly beneficial for player-orinetated
	-- raycasting, where a raycast only needs to be cast once per interval, as apposed
	-- to every zone per interval
	-- I utilise heartbeat with os.clock() to provide precision (where needed) and flexibility
	local nextCheck = 0
	heartbeatConnection = heartbeat:Connect(function()
		local clockTime = os.clock()
		if clockTime >= nextCheck then
			local lowestAccuracy
			local lowestDetection
			for zone, _ in pairs(activeZones) do
				if zone.activeTriggers[registeredTriggerType] then
					local zAccuracy = zone.accuracy
					if lowestAccuracy == nil or zAccuracy < lowestAccuracy then
						lowestAccuracy = zAccuracy
					end
					ZoneController.updateDetection(zone)
					local zDetection = zone._currentEnterDetection
					if lowestDetection == nil or zDetection < lowestDetection then
						lowestDetection = zDetection
					end
				end
			end
			local highestAccuracy = lowestAccuracy
			local zonesAndOccupants = heartbeatActions[registeredTriggerType](lowestDetection)
			for zone, _ in pairs(activeZones) do
				if zone.activeTriggers[registeredTriggerType] then
					local zAccuracy = zone.accuracy
					local occupantsDict = zonesAndOccupants[zone] or {}
					local occupantsPresent = false
					for k, v in pairs(occupantsDict) do
						occupantsPresent = true
						break
					end
					if occupantsPresent and zAccuracy > highestAccuracy then
						highestAccuracy = zAccuracy
					end
					zone:_updateOccupants(registeredTriggerType, occupantsDict)
				end
			end
			----
			local cooldown = enum.Accuracy.getProperty(highestAccuracy)
			nextCheck = clockTime + cooldown
			----
		end
	end)
	heartbeatConnections[registeredTriggerType] = heartbeatConnection
end

function ZoneController._deregisterConnection(registeredZone, registeredTriggerType)
	activeConnections -= 1
	if activeTriggers[registeredTriggerType] == 1 then
		activeTriggers[registeredTriggerType] = nil
		local heartbeatConnection = heartbeatConnections[registeredTriggerType]
		if heartbeatConnection then
			heartbeatConnections[registeredTriggerType] = nil
			heartbeatConnection:Disconnect()
		end
	else
		activeTriggers[registeredTriggerType] -= 1
	end
	registeredZone.activeTriggers[registeredTriggerType] = nil
	if dictLength(registeredZone.activeTriggers) == 0 then
		activeZones[registeredZone] = nil
		ZoneController._updateZoneDetails()
	end
	if registeredZone.touchedConnectionActions[registeredTriggerType] then
		registeredZone:_disconnectTouchedConnection(registeredTriggerType)
	end
end

function ZoneController._updateZoneDetails()
	activeParts = {}
	activePartToZone = {}
	allParts = {}
	allPartToZone = {}
	activeZonesTotalVolume = 0
	for zone, _ in pairs(registeredZones) do
		local isActive = activeZones[zone]
		if isActive then
			activeZonesTotalVolume += zone.volume
		end
		for _, zonePart in pairs(zone.groupParts) do
			if isActive then
				table.insert(activeParts, zonePart)
				activePartToZone[zonePart] = zone
			end
			table.insert(allParts, zonePart)
			allPartToZone[zonePart] = zone
		end
	end
end

function ZoneController._getZonesAndPlayers(zonesDictToCheck, zoneCustomVolume, onlyActiveZones, recommendedDetection)
	local totalZoneVolume = zoneCustomVolume
	if not totalZoneVolume then
		for zone, _ in pairs(zonesDictToCheck) do
			totalZoneVolume += zone.volume
		end
	end
	local zonesAndOccupants = {}
	if charactersTotalVolume < totalZoneVolume then
		-- If the volume of all *characters* within the server is *less than* the total
		-- volume of all active zones (i.e. zones which listen for .playerEntered)
		-- then it's more efficient cast regions and rays within each character and
		-- then determine the zones they belong to
		for _, plr in pairs(players:GetPlayers()) do
			local touchingZones = ZoneController.getTouchingZones(plr, onlyActiveZones, recommendedDetection)
			for _, zone in pairs(touchingZones) do
				if not onlyActiveZones or zone.activeTriggers["player"] then
					fillOccupants(zonesAndOccupants, zone, plr)
				end
			end
		end
	else
		-- If the volume of all *active zones* within the server is *less than* the total
		-- volume of all characters, then it's more efficient to perform the region and raycast
		-- checks directly within each zone to determine players inside
		for zone, _ in pairs(zonesDictToCheck) do
			if not onlyActiveZones or zone.activeTriggers["player"] then
				local result = workspace:FindPartsInRegion3WithWhiteList(zone.region, bodyParts, #bodyParts)
				local playersDict = {}
				for _, bodyPart in pairs(result) do
					local parentName = bodyPart.Parent.Name
					if not playersDict[parentName] then
						playersDict[parentName] = players:GetPlayerFromCharacter(bodyPart.Parent)
					end
				end
				for _, plr in pairs(playersDict) do
					if plr and zone:findPlayer(plr) then
						fillOccupants(zonesAndOccupants, zone, plr)
					end
				end
			end
		end
	end
	return zonesAndOccupants
end
