local ns = oUF local oUF = ns.oUF assert(oUF, "oUF not loaded"); local cos, sin, sqrt2, max, atan2 = math.cos, math.sin, math.sqrt(2), math.max, math.atan2; local getn, tinsert, tremove = table.getn, table.insert, table.remove; local pi2 = 3.141592653589793 / 2; local GetPlayerMapPosition = GetPlayerMapPosition local UnitInParty = UnitInParty local UnitInRaid = UnitInRaid local UnitIsConnected = UnitIsConnected local UnitIsUnit = UnitIsUnit local _FRAMES, OnUpdateFrame = {}; local function CalculateCorner(r) return .5 + cos(r) / sqrt2, .5 + sin(r) / sqrt2; end local function RotateTexture(texture, angle) local LRx, LRy = CalculateCorner(angle + 0.785398163); local LLx, LLy = CalculateCorner(angle + 2.35619449); local ULx, ULy = CalculateCorner(angle + 3.92699082); local URx, URy = CalculateCorner(angle - 0.785398163); texture:SetTexCoord(ULx, ULy, LLx, LLy, URx, URy, LRx, LRy); end local GetAngle = function(unit1, unit2) local x1, y1 = GetPlayerMapPosition(unit1); if(x1 <= 0 and y1 <= 0) then return nil; end local x2, y2 = GetPlayerMapPosition(unit2) if(x2 <= 0 and y2 <= 0) then return nil; end return -pi2 - GetPlayerFacing() - atan2(y2 - y1, x2 - x1); end local minThrottle = 0.02 local numArrows, inRange, unit, GPS local Update = function(self, elapsed) if(self.elapsed and self.elapsed > (self.throttle or minThrottle)) then numArrows = 0; for _, object in next, _FRAMES do if(object:IsShown()) then GPS = object.GPS; unit = object.unit; if(unit) then if(unit and GPS.outOfRange) then inRange = CheckInteractDistance(unit, 4); end if(not unit or not (UnitInParty(unit) or UnitInRaid(unit)) or UnitIsUnit(unit, "player") or not UnitIsConnected(unit) or (GPS.onMouseOver and (GetMouseFocus() ~= object)) or (GPS.outOfRange and inRange)) then GPS:Hide() else local angle = GetAngle("player", unit); if(angle == nil) then GPS:Hide(); else GPS:Show(); RotateTexture(GPS.Texture, angle); numArrows = numArrows + 1; end end else GPS:Hide(); end end end self.elapsed = 0; self.throttle = max(minThrottle, 0.005 * numArrows); else self.elapsed = (self.elapsed or 0) + elapsed; end end local Enable = function(self) local GPS = self.GPS; if(GPS) then tinsert(_FRAMES, self); if(not OnUpdateFrame) then OnUpdateFrame = CreateFrame("Frame"); OnUpdateFrame:SetScript("OnUpdate", function() Update(this, arg1) end); end OnUpdateFrame:Show(); return true; end end local Disable = function(self) local GPS = self.GPS; if(GPS) then for k, frame in next, _FRAMES do if(frame == self) then tremove(_FRAMES, k); GPS:Hide(); break end end if(getn(_FRAMES) == 0 and OnUpdateFrame) then OnUpdateFrame:Hide(); end end end oUF:AddElement("GPS", nil, Enable, Disable);