-- Copyright 2023 -- -- This file is part of Omicron Frames -- -- Omicron Frames is free software: you can redistribute it and/or modify it -- under the terms of the GNU General Public License as published by the Free -- Software Foundation, either version 3 of the License, or (at your option) -- any later version. -- -- Omicron Frames is distributed in the hope that it will be useful, but -- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -- more details. -- -- You should have received a copy of the GNU General Public License along with -- Omicron Frames. If not, see . local omi = select(2, ...) local types = omi.GetModule("types") local UnitGroup = types.CreateClass("UnitGroup") types.UnitGroup = UnitGroup local function RoleValue(role) if role == "TANK" then return 0 elseif role == "HEALER" then return 1 elseif role == "DAMAGER" then return 2 else return 3 end end local function UnitFrameDefaultCompare(lhs, rhs) -- visible < invisible if lhs.secureFrame:IsShown() ~= rhs.secureFrame:IsShown() then return lhs.secureFrame:IsShown() end local lunit, runit = lhs.unit, rhs.unit -- players < non-players local player = UnitIsPlayer(lunit) if UnitIsPlayer(lunit) ~= UnitIsPlayer(runit) then return player end if player then -- you < others if UnitIsUnit(lunit, "player") ~= UnitIsUnit(runit, "player") then return UnitIsUnit(lunit, "player") end -- tank < healer < damage < ? local lrole = RoleValue(UnitGroupRolesAssigned(lunit)) local rrole = RoleValue(UnitGroupRolesAssigned(runit)) if lrole ~= rrole then return lrole < rrole end end return lunit < runit end function UnitGroup:Init(left, top, width, height) self.width = width self.height = height self.top = top self.left = left self.units = {} self.sortAfterCombat = false self:RegisterEvents() end function UnitGroup:RegisterEvents() local frame = CreateFrame("Frame") self.frame = frame frame:SetScript("OnEvent", function(frame, event, ...) self[event](self, ...) end) frame:RegisterEvent("GROUP_ROSTER_UPDATE") frame:RegisterEvent("PLAYER_REGEN_ENABLED") frame:RegisterEvent("PLAYER_ENTERING_WORLD") end function UnitGroup:GROUP_ROSTER_UPDATE() self:OnRosterUpdate() end function UnitGroup:PLAYER_ENTERING_WORLD() self:OnRosterUpdate() end function UnitGroup:PLAYER_REGEN_ENABLED() self:OnLeaveCombat() end function UnitGroup:OnLeaveCombat() if self.sortAfterCombat then self:Sort() self.sortAfterCombat = false end end function UnitGroup:OnRosterUpdate() if InCombatLockdown() then self.sortAfterCombat = true else self:Sort() end end function UnitGroup:AddUnitFrame(unit) table.insert(self.units, unit) end function UnitGroup:Sort() table.sort(self.units, UnitFrameDefaultCompare) local left, top, width, height = self.left, self.top, self.width, self.height local maxFrameIndex = #self.units for y = 0, 5 do for x = 0, 4 do local num = y * 5 + x + 1 if num > maxFrameIndex then return end local frame = self.units[num] frame:SetPosition(left + (x - 2) * width, top - y * height) end end end