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
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
|