You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1045 lines
29 KiB

local GlobalAddonName, ExRT = ...
local module = ExRT:New("RaidGroups",ExRT.L.RaidGroups)
local ELib,L = ExRT.lib,ExRT.L
local LibDeflate = LibStub:GetLibrary("LibDeflate")
local UnitGroupRolesAssigned = UnitGroupRolesAssigned or ExRT.NULLfunc
local VMRT = nil
function module.main:ADDON_LOADED()
VMRT = _G.VMRT
VMRT.RaidGroups = VMRT.RaidGroups or {}
VMRT.RaidGroups.profiles = VMRT.RaidGroups.profiles or {}
if not VMRT.RaidGroups.upd4550 then
VMRT.RaidGroups.KeepPosInGroup = true
VMRT.RaidGroups.upd4550 = true
end
module:RegisterSlash()
end
function module.options:Load()
self:CreateTilte()
local function EditOnDragStart(self)
if self:IsMovable() then
self:StartMoving()
end
end
local function EditOnDragStop(self)
self:StopMovingOrSizing()
for i=1,#module.options.edits do
local edit2 = module.options.edits[i]
if edit2:IsMouseOver() and edit2 ~= self then
local textSelf = self:GetText()
local textMO = edit2:GetText()
self:SetText(textMO)
edit2:SetText(textSelf)
self:SetCursorPosition(1)
edit2:SetCursorPosition(1)
break
end
end
self:NewPoint("TOPLEFT",module.options,10+((self.index-1) % 10 < 5 and 0 or 165),-40-((self.index-1) % 5)*22-floor((self.index-1)/10)*132)
self:ClearFocus()
end
local function EditOnDragStopNotInList(self)
self:StopMovingOrSizing()
for i=1,#module.options.edits do
local edit2 = module.options.edits[i]
if edit2:IsMouseOver() and edit2 ~= self then
local textSelf = self.preName or self:GetText()
edit2:SetText(textSelf)
edit2:SetCursorPosition(1)
break
end
end
self:NewPoint("TOPLEFT",module.options,355,-40-(self.index-1)*14)
self:ClearFocus()
module.options:UpdateNotInList()
end
local function EditOnChange(self,isUser)
local name = self:GetText()
if name and UnitName(name) then
local r,g,b = ExRT.F.classColorNum(select(2,UnitClass(name)))
self:SetTextColor(r,g,b,1)
self:ColorBorder()
elseif self.preclass then
local r,g,b = ExRT.F.classColorNum(self.preclass)
self:SetTextColor(r,g,b,1)
self:ColorBorder()
else
self:SetTextColor(.7,.7,.7,1)
if name and #name > 0 then
self:ColorBorder(0.5,0.25,0.3,1)
else
self:ColorBorder()
end
end
if name and UnitName(name) and UnitGroupRolesAssigned(name) then
local role = UnitGroupRolesAssigned(name)
if role == "HEALER" then
self.roleIcon:SetAtlas("groupfinder-icon-role-large-heal")
self.roleIcon:Show()
elseif role == "DAMAGER" then
self.roleIcon:SetAtlas("groupfinder-icon-role-large-dps")
self.roleIcon:Show()
elseif role == "TANK" then
self.roleIcon:SetAtlas("groupfinder-icon-role-large-tank")
self.roleIcon:Show()
else
self.roleIcon:Hide()
end
else
self.roleIcon:Hide()
end
if isUser then
module.options:UpdateNotInList()
end
end
function self:UpdateTextColors()
for i=1,40 do
EditOnChange(self.edits[i],false)
end
end
self.edits = {}
for i=1,40 do
local edit = ELib:Edit(self):Size(150,18)
self.edits[i] = edit
edit:SetText(i)
edit.index = i
edit:Point("TOPLEFT",10+((i-1) % 10 < 5 and 0 or 165),-40-((i-1) % 5)*22-floor((i-1)/10)*132):OnChange(EditOnChange)
edit.roleIcon = edit:CreateTexture(nil, "BACKGROUND")
edit.roleIcon:SetPoint("RIGHT")
edit.roleIcon:SetSize(16,16)
edit.roleIcon:Hide()
edit:SetMovable(true)
edit:RegisterForDrag("LeftButton")
edit:SetScript("OnDragStart", EditOnDragStart)
edit:SetScript("OnDragStop", EditOnDragStop)
end
for i=1,4 do
for j=1,2 do
ELib:Text(self,GROUP.." "..((i-1)*2+j)):Point("TOPLEFT",10+(j == 1 and 0 or 165)+3,-40-(i-1)*132+14):Color():Shadow()
end
end
ELib:Text(self,L.RaidGroupsTextMovable,8):Point("TOPLEFT",12,-547):Color():Shadow()
self.scrollNotInList = ELib:ScrollBar(self):Point("TOPLEFT",478,-40):Size(12,558):SetMinMaxValues(0,1):SetValue(0):SetObey(true):OnChange(function()
self:UpdateNotInList()
end)
self.edits_notinlist = {}
function self:UpdateNotInList()
local inList,notInList = {},{}
local scrollShow
for i=1,40 do
local name = module.options.edits[i]:GetText()
if name then
inList[name] = true
end
end
if self.isGuild then
local myLvl = UnitLevel("player")
local guildList = {}
for i=1, GetNumGuildMembers() do
local name, _, rankIndex, level, _, _, _, _, _, _, class = GetGuildRosterInfo(i)
if select(2,strsplit("-",name)) == ExRT.SDB.realmKey then
name = strsplit("-",name)
end
if not inList[name] and (level or 0) >= myLvl then
guildList[#guildList+1] = {name,class,rankIndex,"|cffbbbbbb["..rankIndex.."]|r "..name}
end
end
sort(guildList,function(a,b)
if a[3] == b[3] then
return a[1] < b[1]
else
return a[3] < b[3]
end
end)
local start = floor(self.scrollNotInList:GetValue()+0.5)
for i=start+1,#guildList do
notInList[#notInList+1] = guildList[i]
end
if #guildList > 40 then
scrollShow = #guildList - 40
end
else
for i=1,GetNumGroupMembers() do
local name = GetRaidRosterInfo(i)
if not inList[name] then
notInList[#notInList+1] = name
end
end
end
if scrollShow then
self.scrollNotInList:SetMinMaxValues(0,scrollShow)
end
self.scrollNotInList:SetShown(scrollShow and true or false)
for i=1,min(#notInList,40) do
local edit = self.edits_notinlist[i]
if not edit then
edit = ELib:Edit(self):Size(120,12)
self.edits_notinlist[i] = edit
edit.index = i
edit:Point("TOPLEFT",355,-40-(i-1)*14):OnChange(EditOnChange)
edit.roleIcon = edit:CreateTexture(nil, "BACKGROUND")
edit.roleIcon:SetPoint("RIGHT")
edit.roleIcon:SetSize(10,10)
edit.roleIcon:Hide()
edit:SetFont(edit:GetFont(),10,"")
edit:SetEnabled(false)
edit:SetMovable(true)
edit:RegisterForDrag("LeftButton")
edit:SetScript("OnDragStart", EditOnDragStart)
edit:SetScript("OnDragStop", EditOnDragStopNotInList)
end
if type(notInList[i]) == "table" then
edit:SetText("")
edit:SetText(notInList[i][4])
edit.preclass = notInList[i][2]
edit.preName = notInList[i][1]
else
edit:SetText("")
edit:SetText(notInList[i])
edit.preclass = nil
edit.preName = nil
end
edit:SetCursorPosition(1)
edit:Show()
end
for i=#notInList+1,#self.edits_notinlist do
self.edits_notinlist[i]:Hide()
end
end
self.chk_raid = ELib:Radio(self,RAID,true):Point("TOPLEFT",355,-20):OnClick(function(self)
module.options.isGuild = false
self:SetChecked(true)
module.options.chk_guild:SetChecked(false)
module.options:UpdateNotInList()
end)
self.chk_guild = ELib:Radio(self,GUILD):Point("BOTTOM",self.chk_raid,"TOP",0,-2):OnClick(function(self)
module.options.isGuild = true
self:SetChecked(true)
module.options.chk_raid:SetChecked(false)
C_GuildInfo.GuildRoster()
module.options:UpdateNotInList()
C_Timer.After(1,function()
module.options:UpdateNotInList()
end)
end)
self.updateRoster = ELib:Button(self,L.RaidGroupsCurrentRoster):Size(315,20):Point("TOPLEFT",10,-565):OnClick(function()
local roster = {}
for i=1,8 do roster[i] = {} end
for i=1,GetNumGroupMembers() do
local name, rank, subgroup = GetRaidRosterInfo(i)
tinsert(roster[subgroup],name)
end
for i=1,8 do
for j=1,5 do
local edit = module.options.edits[(i-1)*5+j]
edit:SetText(roster[i][j] or "")
edit:SetCursorPosition(1)
end
end
module.options:UpdateNotInList()
end)
self.processRoster = ELib:Button(self,L.RaidGroupsSetGroups):Size(315,30):Point("TOP",self.updateRoster,"BOTTOM",0,-5):OnClick(function(self)
local list = {}
for i=1,40 do
list[i] = module.options.edits[i]:GetText()
end
module:ApplyGroups(list)
end)
self.keepPosCheck = ELib:Check(self,L.RaidGroupsKeepPosInGroup,VMRT.RaidGroups.KeepPosInGroup):Point("BOTTOMLEFT",self.processRoster,"BOTTOMRIGHT",5,0):OnClick(function(self)
if self:GetChecked() then
VMRT.RaidGroups.KeepPosInGroup = true
else
VMRT.RaidGroups.KeepPosInGroup = nil
end
end):Shown(ExRT.isClassic)
self.presetList = ELib:ScrollList(self):Size(190,505):Point("TOPRIGHT",-10,-40):AddDrag()
ELib:Text(self,L.RaidGroupsQuickLoad..":"):Point("BOTTOMLEFT",self.presetList,"TOPLEFT",5,3):Color():Shadow()
self.presetList.ButtonRemove = CreateFrame("Button",nil,self.presetList)
self.presetList.ButtonRemove:Hide()
self.presetList.ButtonRemove:SetSize(8,8)
self.presetList.ButtonRemove:SetScript("OnClick",function(self)
for i=#VMRT.RaidGroups.profiles,1,-1 do
local entry = VMRT.RaidGroups.profiles[i]
if entry == self.data then
tremove(VMRT.RaidGroups.profiles,i)
break
end
end
module.options:UpdateList()
end)
self.presetList.ButtonRemove:SetScript("OnEnter",function(self)
GameTooltip:SetOwner(self,"ANCHOR_RIGHT")
GameTooltip:AddLine(DELETE)
GameTooltip:Show()
end)
self.presetList.ButtonRemove:SetScript("OnLeave",function(self)
GameTooltip_Hide()
end)
self.presetList.ButtonRemove.i = self.presetList.ButtonRemove:CreateTexture()
self.presetList.ButtonRemove.i:SetPoint("CENTER")
self.presetList.ButtonRemove.i:SetSize(16,16)
self.presetList.ButtonRemove.i:SetTexture("Interface\\AddOns\\"..GlobalAddonName.."\\media\\DiesalGUIcons16x256x128")
self.presetList.ButtonRemove.i:SetTexCoord(0.5,0.5625,0.5,0.625)
self.presetList.ButtonRemove.i:SetVertexColor(.8,0,0,1)
function self.presetList:SetListValue(index)
local data = self.L[index][2]
for i=1,40 do
local edit = module.options.edits[i]
if data[i] then
edit:SetText(data[i])
edit:SetCursorPosition(1)
else
edit:SetText("")
end
end
module.options:UpdateNotInList()
module.options.presetList.selected = nil
module.options.presetList:Update()
end
function self.presetList:HoverListValue(isEnter,index,obj)
if not isEnter then
GameTooltip_Hide()
if not self.ButtonRemove:IsMouseOver() then
self.ButtonRemove:Hide()
end
else
local data = obj.table[2]
GameTooltip:SetOwner(obj,"ANCHOR_CURSOR")
GameTooltip:AddLine(data.name)
GameTooltip:AddLine(date("%x %X",data.time))
GameTooltip:Show()
self.ButtonRemove.data = data
self.ButtonRemove:SetPoint("RIGHT",obj,"RIGHT",-5,0)
self.ButtonRemove:SetParent(obj)
self.ButtonRemove:Show()
end
end
function self.presetList:OnDragFunction(obj1,obj2)
local data1,data2 = obj1.table[2],obj2.table[2]
local tmp
if obj1.index < obj2.index then
for i=#VMRT.RaidGroups.profiles,1,-1 do
if VMRT.RaidGroups.profiles[i] == data1 then
tmp = VMRT.RaidGroups.profiles[i]
VMRT.RaidGroups.profiles[i] = VMRT.RaidGroups.profiles[i-1]
elseif VMRT.RaidGroups.profiles[i] == data2 then
VMRT.RaidGroups.profiles[i] = tmp
break
elseif tmp then
VMRT.RaidGroups.profiles[i] = VMRT.RaidGroups.profiles[i-1]
end
end
else
for i=1,#VMRT.RaidGroups.profiles do
if VMRT.RaidGroups.profiles[i] == data1 then
tmp = VMRT.RaidGroups.profiles[i]
VMRT.RaidGroups.profiles[i] = VMRT.RaidGroups.profiles[i+1]
elseif VMRT.RaidGroups.profiles[i] == data2 then
VMRT.RaidGroups.profiles[i] = tmp
break
elseif tmp then
VMRT.RaidGroups.profiles[i] = VMRT.RaidGroups.profiles[i+1]
end
end
end
module.options:UpdateList()
end
function self:UpdateList()
local list = {}
for i=#VMRT.RaidGroups.profiles,1,-1 do
local entry = VMRT.RaidGroups.profiles[i]
list[#list+1] = {entry.name,entry}
end
module.options.presetList.L = list
module.options.presetList:Update()
end
local function SaveData(_,name)
if not name or string.trim(name) == "" then
return
end
local new = {
name = name,
time = time(),
}
for i=1,40 do
local text = module.options.edits[i]:GetText()
if text and string.trim(text) ~= "" then
new[i] = text
end
end
VMRT.RaidGroups.profiles[#VMRT.RaidGroups.profiles+1] = new
module.options:UpdateList()
end
local function SaveInputOnEdit(self)
local text = self:GetText()
if text and string.trim(text) ~= "" then
self:GetParent().OK:Enable()
else
self:GetParent().OK:Disable()
end
end
self.presetListSave = ELib:Button(self,L.RaidGroupsSave):Size(192,20):Point("TOP",self.presetList,"BOTTOM",0,-5):OnClick(function(self)
ExRT.F.ShowInput(L.RaidGroupsEnterName,SaveData,nil,nil,nil,SaveInputOnEdit)
end)
self.importWindow, self.exportWindow = ExRT.F.CreateImportExportWindows()
do
self.importWindow:SetHeight(180)
self.importWindow.Edit:Point("TOP",0,-100)
ELib:DecorationLine(self.importWindow):Point("TOPLEFT",0,-17):Point("BOTTOMRIGHT",'x',"TOPRIGHT",0,-18)
ELib:DecorationLine(self.importWindow):Point("TOPLEFT",0,-95):Point("BOTTOMRIGHT",'x',"TOPRIGHT",0,-96)
local importWindow = self.importWindow
local function ButtonOnClick(self)
local index = 1
local c = importWindow["c"..index]
while c do
c:Enable()
if self == c then
importWindow.importType = index
VMRT.RaidGroups.importType = index
end
index = index + 1
c = importWindow["c"..index]
end
self:Disable()
end
local function CreateButton()
local self = ELib:Template("ExRTButtonTransparentTemplate",importWindow)
self:SetSize(importWindow:GetWidth()/4,77)
self.DisabledTexture = self:CreateTexture()
self.DisabledTexture:SetColorTexture(0.20,0.21,0.25,0.5)
self.DisabledTexture:SetPoint("TOPLEFT")
self.DisabledTexture:SetPoint("BOTTOMRIGHT")
self:SetDisabledTexture(self.DisabledTexture)
self:SetScript("OnClick",ButtonOnClick)
return self
end
importWindow.c1 = CreateButton()
importWindow.c1:SetPoint("TOPLEFT",0,-18)
importWindow.c1:SetText("G1 G2\nG3 G4\nG5 G6\nG7 G8")
importWindow.c2 = CreateButton()
importWindow.c2:SetPoint("LEFT",importWindow.c1,"RIGHT",0,0)
importWindow.c2:SetText("G1 G2 G3 G4 G5")
importWindow.c3 = CreateButton()
importWindow.c3:SetPoint("LEFT",importWindow.c2,"RIGHT",0,0)
importWindow.c3:SetText("G1\nG2\nG3\nG4\nG5")
importWindow.c4 = CreateButton()
importWindow.c4:SetPoint("LEFT",importWindow.c3,"RIGHT",0,0)
importWindow.c4:SetText("From ExRT export string")
local importType = VMRT.RaidGroups.importType or 4
local c = importWindow["c"..importType]
if c then
c:Click()
end
end
do
self.exportWindow:SetHeight(130)
self.exportWindow.Edit:Point("TOP",0,-100)
ELib:DecorationLine(self.exportWindow):Point("TOPLEFT",0,-17):Point("BOTTOMRIGHT",'x',"TOPRIGHT",0,-18)
ELib:DecorationLine(self.exportWindow):Point("TOPLEFT",0,-95):Point("BOTTOMRIGHT",'x',"TOPRIGHT",0,-96)
local exportWindow = self.exportWindow
local function ButtonOnClick(self)
local index = 1
local c = exportWindow["c"..index]
while c do
c:Enable()
if self == c then
exportWindow.exportType = index
VMRT.RaidGroups.exportType = index
end
index = index + 1
c = exportWindow["c"..index]
end
self:Disable()
module.options:RecordToText()
if exportWindow:IsShown() then
exportWindow.Edit:SetFocus()
exportWindow.Edit:HighlightText()
end
end
local function CreateButton()
local self = ELib:Template("ExRTButtonTransparentTemplate",exportWindow)
self:SetSize(exportWindow:GetWidth()/4,77)
self.DisabledTexture = self:CreateTexture()
self.DisabledTexture:SetColorTexture(0.20,0.21,0.25,0.5)
self.DisabledTexture:SetPoint("TOPLEFT")
self.DisabledTexture:SetPoint("BOTTOMRIGHT")
self:SetDisabledTexture(self.DisabledTexture)
self:SetScript("OnClick",ButtonOnClick)
return self
end
exportWindow.c1 = CreateButton()
exportWindow.c1:SetPoint("TOPLEFT",0,-18)
exportWindow.c1:SetText("G1 G2\nG3 G4\nG5 G6\nG7 G8")
exportWindow.c2 = CreateButton()
exportWindow.c2:SetPoint("LEFT",exportWindow.c1,"RIGHT",0,0)
exportWindow.c2:SetText("G1 G2 G3 G4 G5")
exportWindow.c3 = CreateButton()
exportWindow.c3:SetPoint("LEFT",exportWindow.c2,"RIGHT",0,0)
exportWindow.c3:SetText("G1\nG2\nG3\nG4\nG5")
exportWindow.c4 = CreateButton()
exportWindow.c4:SetPoint("LEFT",exportWindow.c3,"RIGHT",0,0)
exportWindow.c4:SetText("MRT export string")
local exportType = VMRT.RaidGroups.exportType or 4
local c = exportWindow["c"..exportType]
if c then
c:Disable()
end
exportWindow.exportType = exportType
end
local function SaveDataFromTable(rec,name)
if not name or string.trim(name) == "" then
return
end
rec.name = name
rec.time = time()
VMRT.RaidGroups.profiles[#VMRT.RaidGroups.profiles+1] = rec
module.options:UpdateList()
end
function self.importWindow:ImportFunc(str)
if self.importType == 4 then
local headerLen = str:sub(1,4) == "EXRT" and 8 or 7
local header = str:sub(1,headerLen)
if (header:sub(1,headerLen-1) ~= "EXRTRGR" and header:sub(1,headerLen-1) ~= "MRTRGR") or (header:sub(headerLen,headerLen) ~= "0" and header:sub(headerLen,headerLen) ~= "1") then
StaticPopupDialogs["EXRT_RAIDGROUP_IMPORT"] = {
text = "|cffff0000"..ERROR_CAPS.."|r "..L.ProfilesFail3,
button1 = OKAY,
timeout = 0,
whileDead = true,
hideOnEscape = true,
preferredIndex = 3,
}
StaticPopup_Show("EXRT_RAIDGROUP_IMPORT")
return
end
module.options:TextToRecord(str:sub(headerLen+1),header:sub(headerLen,headerLen)=="0")
elseif self.importType == 1 then
local res = {}
local group = 1
local posInGroup = 0
local lines = {strsplit("\n",str)}
for i=1,#lines do
local left,right = strsplit(" ",lines[i]:gsub(" +"," "):gsub('"',''),nil)
if left and left:trim() ~= "" then
left = left:trim()
else
left = nil
end
if right and right:trim() ~= "" then
right = right:trim()
else
right = nil
end
posInGroup = posInGroup + 1
if posInGroup > 5 and (left or right) then
posInGroup = 1
group = group + 2
end
if posInGroup <= 5 and group <= 8 then
res[(group-1)*5+posInGroup] = left
res[(group-0)*5+posInGroup] = right
end
end
ExRT.F.ShowInput(L.RaidGroupsEnterName,SaveDataFromTable,res,nil,nil,SaveInputOnEdit)
elseif self.importType == 3 then
local res = {}
local group = 1
local posInGroup = 0
local lines = {strsplit("\n",str)}
for i=1,#lines do
local left = lines[i]
if left and left:trim() ~= "" then
left = left:trim():gsub('"','')
else
left = nil
end
posInGroup = posInGroup + 1
if posInGroup > 5 and left then
posInGroup = 1
group = group + 1
end
if posInGroup <= 5 and group <= 8 then
res[(group-1)*5+posInGroup] = left
end
end
ExRT.F.ShowInput(L.RaidGroupsEnterName,SaveDataFromTable,res,nil,nil,SaveInputOnEdit)
elseif self.importType == 2 then
local res = {}
local lines = {strsplit("\n",str)}
for i=1,#lines do
local group = 0
local name,line = strsplit(" ",lines[i]:gsub(" +"," "):gsub('"',''),2)
while name do
group = group + 1
if i <= 5 and group <= 8 then
res[(group-1)*5+i] = name:trim()
end
if line then
name,line = strsplit(" ",line,2)
else
break
end
end
end
ExRT.F.ShowInput(L.RaidGroupsEnterName,SaveDataFromTable,res,nil,nil,SaveInputOnEdit)
end
end
function self:TextToRecord(str,uncompressed)
local decoded = LibDeflate:DecodeForPrint(str)
local decompressed
if uncompressed then
decompressed = decoded
else
decompressed = LibDeflate:DecompressDeflate(decoded)
end
decoded = nil
local _,tableData = strsplit(",",decompressed,2)
decompressed = nil
local successful, res = pcall(ExRT.F.TextToTable,tableData)
if ExRT.isDev then
module.db.lastImportDB = res
if module.db.exportTable and type(res)=="table" then
module.db.diffTable = {}
print("Compare table",ExRT.F.table_compare(res,module.db.exportTable,module.db.diffTable))
end
end
if successful and res then
ExRT.F.ShowInput(L.RaidGroupsEnterName,SaveDataFromTable,res,nil,nil,SaveInputOnEdit)
else
StaticPopupDialogs["EXRT_RAIDGROUP_IMPORT"] = {
text = L.ProfilesFail1..(res and "\nError code: "..res or ""),
button1 = OKAY,
timeout = 0,
whileDead = true,
hideOnEscape = true,
preferredIndex = 3,
}
StaticPopup_Show("EXRT_RAIDGROUP_IMPORT")
end
end
function self:RecordToText()
local new = {}
for i=1,40 do
local text = module.options.edits[i]:GetText()
if text and string.trim(text) ~= "" then
new[i] = text
end
end
local exportWindow = module.options.exportWindow
if exportWindow.exportType == 1 then
local text = ""
for i=1,8,2 do
for j=1,5 do
text = text .. (new[(i-1)*5+j] or "") .. "\t" .. (new[(i-0)*5+j] or "") .. "\n"
end
end
exportWindow.Edit:SetText(text)
elseif exportWindow.exportType == 2 then
local text = ""
for j=1,5 do
for i=1,8 do
text = text .. (new[(i-1)*5+j] or "") .. "\t"
end
text = text .. "\n"
end
exportWindow.Edit:SetText(text)
elseif exportWindow.exportType == 3 then
local text = ""
for i=1,8 do
for j=1,5 do
text = text .. (new[(i-1)*5+j] or "") .. "\n"
end
end
exportWindow.Edit:SetText(text)
else
local strlist = ExRT.F.TableToText(new)
strlist[1] = "0,"..strlist[1]
local str = table.concat(strlist)
local compressed
if #str < 1000000 then
compressed = LibDeflate:CompressDeflate(str,{level = 5})
end
local encoded = "MRTRGR"..(compressed and "1" or "0")..LibDeflate:EncodeForPrint(compressed or str)
ExRT.F.dprint("Str len:",#str,"Encoded len:",#encoded)
if ExRT.isDev then
module.db.exportTable = new
end
exportWindow.Edit:SetText(encoded)
end
exportWindow:Show()
end
self.butExport = ELib:Button(self,L.RaidGroupsExport):Size(192,20):Point("TOP",self.presetListSave,"BOTTOM",0,-5):OnClick(function(self)
module.options:RecordToText()
end)
self.butImport = ELib:Button(self,L.Import):Size(192,20):Point("TOP",self.butExport,"BOTTOM",0,-5):OnClick(function(self)
module.options.importWindow:NewPoint("CENTER",UIParent,0,0)
module.options.importWindow:Show()
end)
self:UpdateList()
self.updateRoster:Click()
function self:OnShow()
module.options:UpdateTextColors()
module.options:UpdateNotInList()
end
local GRU = CreateFrame("Frame",nil,self)
GRU:SetPoint("TOPLEFT")
GRU:SetSize(1,1)
GRU:RegisterEvent("GROUP_ROSTER_UPDATE")
GRU:SetScript("OnEvent",function()
if not self:IsVisible() then
return
end
module.options:UpdateTextColors()
module.options:UpdateNotInList()
end)
end
function module:ApplyGroups(list)
if not IsInRaid() then
return
end
local UnitsInCombat
for i=1,40 do
local unit = "raid"..i
if UnitAffectingCombat(unit) then
UnitsInCombat = (UnitsInCombat or "") .. (UnitsInCombat and "," or "") .. UnitName(unit)
end
end
if UnitsInCombat then
print("|cffff0000"..ERROR_CAPS..".|r "..L.RaidGroupsPlayersInCombat..": "..UnitsInCombat)
return
end
local needGroup = {}
local needPosInGroup = {}
local lockedUnit = {}
local RLName,_,RLGroup = GetRaidRosterInfo(1)
local isRLfound = false
for i=1,8 do
local pos = 1
for j=1,5 do
local name = list[(i-1)*5+j]
if name == RLName then
needGroup[name] = i
needPosInGroup[name] = pos
pos = pos + 1
isRLfound = true
break
end
end
for j=1,5 do
local name = list[(i-1)*5+j]
if name and name ~= RLName and UnitName(name) then
needGroup[name] = i
needPosInGroup[name] = pos
pos = pos + 1
end
end
end
--reports saying that too many swap events can trigger disconnect on classic, unconfirmed cause: other addons or pure swap events
if ExRT.isClassic and not VMRT.RaidGroups.KeepPosInGroup then
wipe(needPosInGroup)
end
module.db.needGroup = needGroup
module.db.needPosInGroup = needPosInGroup
module.db.lockedUnit = lockedUnit
module.db.groupsReady = false
module.db.groupWithRL = isRLfound and 0 or RLGroup
if module.options.processRoster then
module.options.processRoster:Disable()
end
module:ProcessRoster()
end
local function Debug(currentGroup,currentPos,needGroup,needPosInGroup)
local s = ""
for k,v in pairs(currentGroup) do
s = s..k.."["..v..":"..currentPos[k]..","..(needGroup[k] or "")..":"..(needPosInGroup[k] or "").."]"
end
print(s)
end
function module:ProcessRoster()
local UnitsInCombat
for i=1,40 do
local unit = "raid"..i
if UnitAffectingCombat(unit) then
UnitsInCombat = (UnitsInCombat or "") .. (UnitsInCombat and "," or "") .. UnitName(unit)
end
end
if UnitsInCombat then
print("|cffff0000"..ERROR_CAPS..".|r "..L.RaidGroupsCombatStarted..": "..UnitsInCombat)
module.db.needGroup = nil
if module.options.processRoster then
module.options.processRoster:Enable()
end
module:UnregisterEvents('GROUP_ROSTER_UPDATE')
return
end
local needGroup = module.db.needGroup
local needPosInGroup = module.db.needPosInGroup
local lockedUnit = module.db.lockedUnit
if not needGroup then
return
end
module:RegisterEvents('GROUP_ROSTER_UPDATE')
local currentGroup = {}
local currentPos = {}
local nameToID = {}
local groupSize = {}
wipe(currentGroup)
for i=1,8 do groupSize[i] = 0 end
for i=1,GetNumGroupMembers() do
local name, rank, subgroup = GetRaidRosterInfo(i)
currentGroup[name] = subgroup
nameToID[name] = i
groupSize[subgroup] = groupSize[subgroup] + 1
currentPos[name] = groupSize[subgroup]
end
--Debug(currentGroup,currentPos,needGroup,needPosInGroup)
if not module.db.groupsReady then
local WaitForGroup = false
for unit,group in pairs(needGroup) do
if currentGroup[unit] and currentGroup[unit] ~= needGroup[unit] then
local currGroupUnit = currentGroup[unit]
local needGroupUnit = needGroup[unit]
if groupSize[ needGroupUnit ] < 5 then
SetRaidSubgroup(nameToID[unit],needGroupUnit)
groupSize[ currGroupUnit ] = groupSize[ currGroupUnit ] - 1
groupSize[ needGroupUnit ] = groupSize[ needGroupUnit ] + 1
WaitForGroup = true
end
end
end
if WaitForGroup then
return
end
local SetToSwap = {}
local WaitForSwap = false
for unit,group in pairs(needGroup) do
if not SetToSwap[unit] and currentGroup[unit] and currentGroup[unit] ~= group then
local currGroupUnit = currentGroup[unit]
local unitToSwap
for unit2,group2 in pairs(currentGroup) do
if not SetToSwap[unit2] and group2 == group and needGroup[unit2] ~= group2 then
unitToSwap = unit2
break
end
end
if unitToSwap then
SwapRaidSubgroup(nameToID[unit], nameToID[unitToSwap])
WaitForSwap = true
SetToSwap[unit] = true
SetToSwap[unitToSwap] = true
end
end
end
if WaitForSwap then
return
end
module.db.groupsReady = true
end
do
local SetToSwap = {}
local WaitForSwap = false
for unit,pos in pairs(needPosInGroup) do
if currentGroup[unit] == module.db.groupWithRL then
pos = pos + 1
end
if not lockedUnit[unit] and currentPos[unit] and currentPos[unit] ~= pos and nameToID[unit] ~= 1 and not SetToSwap[unit] then
local currGroupUnit = currentGroup[unit]
local unitToSwapBridge
for unit2,group2 in pairs(currentGroup) do
if group2 ~= currentGroup[unit] and nameToID[unit2] ~= 1 and not SetToSwap[unit2] then
unitToSwapBridge = unit2
break
end
end
local unitToSwap
for unit2,pos2 in pairs(currentPos) do
if currentGroup[unit2] == currentGroup[unit] and pos2 == pos and nameToID[unit2] ~= 1 and not SetToSwap[unit2] then
unitToSwap = unit2
break
end
end
if unitToSwap and unitToSwapBridge then
lockedUnit[unit] = true
SwapRaidSubgroup(nameToID[unit], nameToID[unitToSwapBridge])
SwapRaidSubgroup(nameToID[unitToSwapBridge], nameToID[unitToSwap])
SwapRaidSubgroup(nameToID[unit], nameToID[unitToSwapBridge])
WaitForSwap = true
SetToSwap[unit] = true
SetToSwap[unitToSwap] = true
SetToSwap[unitToSwapBridge] = true
end
end
end
if WaitForSwap then
return
end
end
module.db.needGroup = nil
if module.options.processRoster then
module.options.processRoster:Enable()
end
module:UnregisterEvents('GROUP_ROSTER_UPDATE')
end
function module.main:GROUP_ROSTER_UPDATE()
if self.timer then
self.timer:Cancel()
end
self.timer = C_Timer.NewTimer(0.5,function()
self.timer = nil
module:ProcessRoster()
end)
end
function module:slash(arg)
if arg and arg:find("^raidgroup ") then
local name = arg:match("^raidgroup (.-)$")
if name then
for i=#VMRT.RaidGroups.profiles,1,-1 do
local entry = VMRT.RaidGroups.profiles[i]
if entry.name == name then
module:ApplyGroups(entry)
return
end
end
end
elseif arg == "help" then
print("|cff00ff00/rt raidgroup |cffffff00GROUPNAME|r|r - apply raid groups with name GROUPNAME")
end
end