PTUtil.SetEnvironment(Puppeteer) local _G = getfenv(0) UnitTrackerFrame = CreateFrame("Frame", "PTUnitTrackerFrame", UIParent) local util = PTUtil local GetTime = GetTime local compost = PTPool local TRACKING_EVAL_INTERVAL = 1.25 local RANGE_MIN_DIST = 20 local RANGE_MAX_DIST = 60 local SIGHT_MAX_DIST = 80 local DISTANCE_UPDATE_INTERVAL = 0.1 local SIGHT_UPDATE_INTERVAL = 0.1 local AllUnits = util.AllUnits local distanceTrackedUnits = {} local sightTrackedUnits = {} local prevSightTrackedUnits = {} -- Swapped with sightTrackedUnits on every evaluation, so no tables are created local preciseDistance = util.CanClientGetPreciseDistance() local sightTrackingEnabled = util.CanClientSightCheck() local nextEval = GetTime() + 0.5 local nextRangeUpdate = GetTime() + 0.6 local nextSightUpdate = GetTime() + 0.6 if not preciseDistance then nextRangeUpdate = nextRangeUpdate + 99999999 -- Effectively disable updates end if not sightTrackingEnabled then nextSightUpdate = nextSightUpdate + 99999999 end function LoadTrackingOptions() local opts = PTOptions.Tracking TRACKING_EVAL_INTERVAL = opts.EvaluateInterval RANGE_MIN_DIST = opts.MinDistanceTracking RANGE_MAX_DIST = opts.MaxDistanceTracking SIGHT_MAX_DIST = opts.MaxSightTracking DISTANCE_UPDATE_INTERVAL = opts.DistanceUpdateInterval SIGHT_UPDATE_INTERVAL = opts.SightUpdateInterval end function RunTrackingScan() local UnitFrames = UnitFrames local time = GetTime() if time > nextEval then --StartTiming("TrackingEval") nextEval = time + TRACKING_EVAL_INTERVAL compost:Erase(distanceTrackedUnits) local previous = sightTrackedUnits sightTrackedUnits = compost:Erase(prevSightTrackedUnits) prevSightTrackedUnits = previous if PTGuidRoster then for guid, cache in pairs(PTUnit.GetAllUnits()) do EvaluateTracking(guid) end else for _, unit in ipairs(AllUnits) do EvaluateTracking(unit) end end for _, unit in ipairs(prevSightTrackedUnits) do for ui in UnitFrames(unit) do ui:UpdateSight() end end --EndTiming("TrackingEval") end if time > nextRangeUpdate then nextRangeUpdate = time + DISTANCE_UPDATE_INTERVAL for _, unit in ipairs(distanceTrackedUnits) do local cache = PTUnit.Get(unit) if cache and cache:UpdateDistance() then for ui in UnitFrames(unit) do ui:UpdateRange() end end end end if time > nextSightUpdate then nextSightUpdate = time + SIGHT_UPDATE_INTERVAL for _, unit in ipairs(sightTrackedUnits) do local cache = PTUnit.Get(unit) --StartTiming("SightScan") if cache and cache:UpdateSight() then for ui in UnitFrames(unit) do ui:UpdateSight() end end --EndTiming("SightScan") end end end function EvaluateTracking(unit, update) local UnitFrames = UnitFrames local cache = PTUnit.Get(unit) local distanceChanged = cache:UpdateDistance() local sightChanged = cache:UpdateSight() local new = cache:CheckNew() local dist = cache:GetDistance() if distanceChanged or sightChanged or new then for ui in UnitFrames(unit) do if distanceChanged or new then ui:UpdateRange() end if sightChanged or new then ui:UpdateSight() end end end if cache:UpdatePVP() then for ui in UnitFrames(unit) do ui:UpdatePVP() end end local isTarget = UnitIsUnit(unit, "target") if PTGuidRoster then unit = PTGuidRoster.ResolveUnitGuid(unit) end -- Only closely track units that are close to the range threshold if isTarget or (dist <= RANGE_MAX_DIST and dist >= RANGE_MIN_DIST) then if not update or not util.ArrayContains(distanceTrackedUnits, unit) then table.insert(distanceTrackedUnits, unit) end end if sightTrackingEnabled and (isTarget or (dist > 0 and dist < SIGHT_MAX_DIST)) then if not update or not util.ArrayContains(sightTrackedUnits, unit) then table.insert(sightTrackedUnits, unit) end end end function StartUnitTracker() LoadTrackingOptions() UnitTrackerFrame:SetScript("OnUpdate", RunTrackingScan) end