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.

929 lines
32 KiB

--lua
local unpack, select, type, pairs, tostring, wipe, tinsert, tsort
= unpack, select, type, pairs, tostring, wipe, table.insert, table.sort
local BabbleInventory = LibStub("LibBabble-Inventory-3.0"):GetLookupTable()
-- WoW API
local UnitName, GetGuildInfo, IsInGuild
= UnitName, GetGuildInfo, IsInGuild
local BestInSlot, L, AceGUI = unpack(select(2, ...))
local RequestBiS = BestInSlot:GetMenuPrototype(L["Request BiS"])
RequestBiS.Width = 700
RequestBiS.Height = 600
local dropdownSelection, dropdownRequestFrom, dropdownDifficulty, dropdownFilter
local whisperTarget
local whisperTo
local requestButton
local responseContainer
local selectedChannel
local normalColor = "|cffb5ffb4"
local history = {}
local filter = {}
local inQueue = {}
local queueTimer
local showObtainedItems = true
local showCached = false
local classTokens = {
VANQUISHER = {"ROGUE", "DEATHKNIGHT", "MAGE", "DRUID"},
PROTECTOR = {"WARRIOR", "HUNTER", "SHAMAN", "MONK"},
CONQUEROR = {"PALADIN", "PRIEST", "WARLOCK", "DEMONHUNTER"},
}
local armorClasses = {
[BabbleInventory.Cloth] = {"MAGE", "PRIES", "WARLOCK"},
[BabbleInventory.Leather] = {"ROGUE", "DEMONHUNTER", "DRUID", "MONK"},
[BabbleInventory.Mail] = {"HUNTER", "SHAMAN"},
[BabbleInventory.Plate] = {"DEATHKNIGHT", "WARRIOR", "PALADIN"}
}
local guildName
---
-- Helper function to format the labels properly
---
function RequestBiS:SetText(label)
local itemLink = label:GetUserData("itemlink")
local chars = label:GetUserData("chars")
local str = itemLink
local first = true
for player,specs in pairs(chars) do
if first then --comma or colon
str = str..": "
first = false
else
str = str..", "
end
if #specs == 1 then
str = str..self:GetPlayerString(player)
elseif #specs > 1 then
local addStr = self:GetClassColor(self:GetPlayerClass(player))..player.." ("
for i=1,#specs do
local specName = select(2, GetSpecializationInfoByID(specs[i]))
addStr = addStr..specName..(i == #specs and "" or "/")
end
str = str..addStr..")|r"
end
end
label:SetText(str)
end
function RequestBiS:FillBossGroups()
local bosses = responseContainer:GetUserData("bosses")
for i=1,bosses do
local group = AceGUI:Create("SimpleGroup")
group:SetFullWidth(true)
local header = AceGUI:Create("Heading")
header:SetFullWidth(true)
header:SetText(self:GetDescription(self.BOSS, responseContainer:GetUserData("selection"), i))
group:AddChild(header)
responseContainer:AddChild(group)
responseContainer:SetUserData("boss"..i, group)
end
end
function RequestBiS:ResetRaidTier()
responseContainer:ReleaseChildren()
self:FillBossGroups()
end
function RequestBiS:RegisterRaidTier(name, bis, specId)
if type(bis) ~= "table" then return end
for i,_ in pairs(bis) do
local itemid, obtained, customitem = bis[i].item, bis[i].obtained, bis[i].customitem
if showObtainedItems or not obtained then
local item = self:GetItem(itemid)
if not customitem and item and item.dungeon == responseContainer:GetUserData("selection") then --item should be from this instance
local bossGroup = responseContainer:GetUserData("boss"..tostring(item.bossid))
if bossGroup then
local label = bossGroup:GetUserData(itemid)
if not label then
local label = self:GetItemLinkLabel(itemid, self:GetSelected(self.DIFFICULTY))
label:SetUserData("chars", {[name] = {specId}})
label:SetFullWidth(true)
self:SetText(label)
bossGroup:AddChild(label)
bossGroup:SetUserData(itemid, label)
else
local chars = label:GetUserData("chars")
chars[name] = chars[name] or {}
chars[name][#chars[name] + 1] = specId
self:SetText(label)
end
end
end
end
end
end
function RequestBiS:PopulateRaidTier()
responseContainer:SetLayout("List")
local bosses = RequestBiS:GetInstanceBosses(responseContainer:GetUserData("selection"))
responseContainer:SetUserData("bosses", #bosses)
self:ResetRaidTier()
end
function RequestBiS:ProcessQueueItems()
self.console:Add("Processing queued responses")
for source, itemlist in pairs(inQueue) do
self:DoRegister(source, itemlist)
end
inQueue = {}
self:SetFilterOptions()
responseContainer:DoLayout()
self:ShowTutorial(L["Request BiS"], 4)
end
function RequestBiS:QueueRegister(source, itemlist)
if queueTimer == nil or queueTimer._remainingIterations == 0 then
self.console:Add("Queueing up responses")
queueTimer = C_Timer.NewTimer(1, function() RequestBiS:ProcessQueueItems() end)
end
if not inQueue then
inQueue = {}
end
inQueue[source] = itemlist
end
---Called when the actual request button is pressed, or to simulate it being pressed at startup
function RequestBiS:DoRequest()
history = {}
filter = {}
if not responseContainer then return end
responseContainer:ReleaseChildren()
local selected = self:GetSelected()
local msg = self:GetSelected()
msg = {selection = selected.instance, difficulty = selected.difficulty}
responseContainer:SetUserData("selection", selected.instance)
responseContainer:SetUserData("channel", selectedChannel)
responseContainer:SetUserData("difficulty", selected.difficulty)
self:PopulateRaidTier()
local raidtier = self:GetSelected(self.RAIDTIER)
self:SendAddonMessage("requestRaidInstance", msg, selectedChannel, whisperTo)
if selectedChannel ~= "WHISPER" then
local player = UnitName("player")
self:QueueRegister(player, self:GetBestInSlotItems(raidtier, selected.difficulty))
filter[player] = {show = true, [self:GetSelected(self.SPECIALIZATION)] = true}
end
end
function RequestBiS:CanRequest()
if selectedChannel and (selectedChannel ~= "WHISPER" or whisperTo) then
requestButton:SetDisabled(false)
else
requestButton:SetDisabled(true)
end
end
local function dropdownRequestFromOnValueChanged(_,_,value)
selectedChannel = value
if value == "WHISPER" then
whisperTarget:SetDisabled(false)
RequestBiS:ShowTutorial(L["Request BiS"], 3)
else
whisperTarget:SetDisabled(true)
end
RequestBiS:CanRequest()
end
local function requestButtonOnClick()
RequestBiS:DoRequest()
end
local function whisperToEnterPressed(_,_,value)
whisperTo = value
RequestBiS:CanRequest()
end
function RequestBiS:Draw(container)
dropdownSelection = self:GetDropdown(self.INSTANCE, nil, self.CanRequest)
dropdownSelection:SetRelativeWidth(0.33)
container:AddChild(dropdownSelection)
dropdownDifficulty = self:GetDropdown(self.DIFFICULTY, nil, self.CanRequest)
dropdownDifficulty:SetRelativeWidth(0.33)
container:AddChild(dropdownDifficulty)
dropdownRequestFrom = AceGUI:Create("Dropdown")
dropdownRequestFrom:SetLabel(L["Request from"])
dropdownRequestFrom:SetRelativeWidth(0.33)
dropdownRequestFrom:SetList({
RAID = ("%s/%s"):format(_G["PARTY"], _G["RAID"]),
GUILD = _G["GUILD"],
WHISPER = _G["WHISPER"],
})
container:SetUserData("request", dropdownRequestFrom)
if not IsInGuild() then
dropdownRequestFrom:SetItemDisabled("GUILD", true)
end
if not IsInGroup() then
dropdownRequestFrom:SetItemDisabled("RAID", true)
end
dropdownRequestFrom:SetText(L["Select a channel"])
dropdownRequestFrom:SetCallback("OnValueChanged", dropdownRequestFromOnValueChanged)
container:AddChild(dropdownRequestFrom)
whisperTarget = AceGUI:Create("EditBox")
whisperTarget:SetLabel(L["Whisper target"])
whisperTarget:SetRelativeWidth(0.245)
whisperTarget:SetDisabled(true)
whisperTarget:SetCallback("OnEnterPressed", whisperToEnterPressed)
container:AddChild(whisperTarget)
container:SetUserData("wtarget", whisperTarget)
requestButton = AceGUI:Create("Button")
requestButton:SetText(L["Request"])
requestButton:SetRelativeWidth(0.245)
requestButton:SetDisabled(true)
requestButton:SetCallback("OnClick", requestButtonOnClick)
container:AddChild(requestButton)
dropdownRequestFrom:SetValue(selectedChannel)
if selectedChannel == "WHISPER" then
whisperTarget:SetDisabled(false)
end
whisperTarget:SetText(whisperTo)
dropdownFilter = AceGUI:Create("Dropdown")
dropdownFilter:SetDisabled(true)
dropdownFilter.dropdown.obj:SetDisabled(true)
dropdownFilter:SetRelativeWidth(0.49)
dropdownFilter:SetList({})
dropdownFilter:SetLabel(FILTER)
container:AddChild(dropdownFilter)
container:SetUserData("filter", dropdownFilter)
responseContainer = AceGUI:Create("ScrollFrame")
responseContainer:SetLayout("List")
responseContainer:SetFullWidth(true)
responseContainer:SetFullHeight(true)
responseContainer:SetPoint("BOTTOMRIGHT", container.frame, "BOTTOMRIGHT")
container:AddChild(responseContainer)
self:CanRequest()
end
function RequestBiS:Close()
dropdownSelection = nil
dropdownRequestFrom = nil
dropdownDifficulty = nil
dropdownFilter = nil
whisperTarget = nil
requestButton = nil
responseContainer = nil
history = nil
inQueue = nil
if queueTimer ~= nil then
queueTimer:Cancel()
end
end
local function sendRaidTierReply(raidTier, difficulty, source, version)
local bisList
if version >= 1 and version <= 96 then -- The >= 1 is ment for development versions
local specId = GetSpecializationInfo(RequestBiS:GetSpecialization())
bisList = RequestBiS:GetBestInSlotItems(raidTier, difficulty, specId)
else
bisList = RequestBiS:GetBestInSlotItems(raidTier, difficulty)
end
RequestBiS:SendAddonMessage("requestRaidTierReply", bisList, "WHISPER", source)
end
local function requestRaidTier(data, channel, source, version)
if not data.selection or not data.difficulty then RequestBiS.console:AddError("Invalid data received for requestRaidTier") return end
local raidTier = data.selection
local difficulty = data.difficulty
sendRaidTierReply(raidTier, difficulty, source, version)
end
local function requestRaidInstance(data, channel, source, version)
if not data.selection or not data.difficulty then RequestBiS.console:AddError("Invalid data received for requestRaidInstance") return end
local instance = data.selection
local difficulty = data.difficulty
local raidTier = RequestBiS:GetRaidTiers(RequestBiS.INSTANCE, instance)
sendRaidTierReply(raidTier, difficulty, source, version)
end
local function emptySetValue() end --Not used for dropdown-item-menu, therefore a filler empty function
function RequestBiS:ApplyNewFilter()
self:ResetRaidTier()
for char,data in pairs(history) do
if filter[char].show then
if data.spec then
for specId, specData in pairs(data) do
if specId ~= "spec" and filter[char][specId] then
self:RegisterRaidTier(char, data[specId], specId)
end
end
end
end
end
end
function RequestBiS:CheckArmorDisable()
for i,armorType in pairs({BabbleInventory.Cloth, BabbleInventory.Leather, BabbleInventory.Mail, BabbleInventory.Plate}) do
local armorSelector = dropdownFilter:GetUserData("Armor"..i)
if armorSelector then
local enabled = false
for i=1,#armorClasses[armorType] do
local class = armorClasses[armorType][i]
local classSelector = dropdownFilter:GetUserData(class)
if classSelector and classSelector:GetValue() then
enabled = true
break
end
end
armorSelector:SetValue(enabled)
end
end
end
---Verifies the token filter menu with what is actually in the filter table
function RequestBiS:CheckTokenDisable()
for tokenType, tokenClasses in pairs(classTokens) do
local tokenSelector = dropdownFilter:GetUserData(tokenType)
if tokenSelector then
local tokenEnabled = false
for i=1,#tokenClasses do
local classSelector = dropdownFilter:GetUserData(tokenClasses[i])
if classSelector and classSelector:GetValue() then
tokenEnabled = true
break
end
end
tokenSelector:SetValue(tokenEnabled)
end
end
end
---Verifies the class filter menu with what is actually in the filter table
function RequestBiS:CheckClassDisable(recursive)
recursive = recursive or true
local hasChanged = false
for class in pairs(RAID_CLASS_COLORS) do -- we use the RAID_CLASS_COLORS global since that contains all the classes
local classWidget = dropdownFilter:GetUserData(class)
if classWidget then
local shouldShowClass = false
for char in pairs(filter) do
if RequestBiS:GetPlayerClass(char) == class then
if filter[char].show then
shouldShowClass = true
break
end
end
end
if classWidget:GetValue() ~= shouldShowClass then
hasChanged = true
classWidget:SetValue(shouldShowClass)
end
end
end
if hasChanged and recursive then
self:CheckTokenDisable()
end
end
---Verifies the guild ranks filter menu with what is actually in the filter table
function RequestBiS:CheckGuildRankDisable(recursive)
recursive = recursive or (recursive == nil and true)
for i=1,GuildControlGetNumRanks() do
local guildWidget = dropdownFilter:GetUserData("GuildRank"..i)
if guildWidget then
guildWidget:SetValue(false)
guildWidget:SetDisabled(true)
end --Disable it before looping through the roster
end
for i=1,GetNumGuildMembers() do
local fullName, _, rankIndex = GetGuildRosterInfo(i)
rankIndex = rankIndex + 1
local playerName = (fullName):match("(%D+)-(%D+)")
if filter[playerName] then --Player is known in our filter
local guildWidget = dropdownFilter:GetUserData("GuildRank"..rankIndex) --get the widget for the player's guild rank
if guildWidget then
if filter[playerName].show then
guildWidget:SetValue(true) -- Tick the box if we have a player shown off this guild rank
end
guildWidget:SetDisabled(false) --Enable the tickbox for use
end
end
end
end
---Verifies the character filter menu with what is actually in the filter table
function RequestBiS:CheckPlayerDisable(recursive)
recursive = recursive or (recursive == nil and true)
local hasChanged = false
for char, charFilter in pairs(filter) do
local charGroup = dropdownFilter:GetUserData(char)
local widgetGroup = charGroup:GetUserDataTable()
for widgetDescr,widget in pairs(widgetGroup) do
if widgetDescr == "visible" then --if it's the show widget
if widget:GetValue() ~= (charFilter.show or false) then
hasChanged = true
end
widget:SetValue(charFilter.show or false)
elseif widget then --if it's a spec widget
widget:SetValue(charFilter[widgetDescr] or false)
end
end
end
if hasChanged and recursive then
self:CheckClassDisable()
end
end
function RequestBiS:VerifyCheckBoxes()
self:CheckPlayerDisable(false)
self:CheckGuildRankDisable(false)
self:CheckClassDisable(false)
self:CheckTokenDisable(false)
self:CheckArmorDisable(false)
end
--- Simply (un)ticks all the options in the filter
-- @param #boolean value Wether to tick, or untick everything
-- @param #boolean ignoreApply Optional, if true then doesn't apply the filter afterwards.
function RequestBiS:SetAllFilter(value, ignoreApply)
local userData = dropdownFilter:GetUserDataTable()
for char, charFilter in pairs(filter) do
charFilter.show = value
end
self:VerifyCheckBoxes()
if not ignoreApply then
self:ApplyNewFilter()
end
end
--- Untick the character, and checks if other tickboxes should be unticked as a result
-- @param #string char Character name
-- @param #boolean value Was the character enabled (true) or disabled (false)
-- @param #boolean ignoreApply Optional, if true then doesn't apply the filter afterwards.
function RequestBiS:SetCharFilter(char, value, ignoreApply)
local userData = dropdownFilter:GetUserDataTable()
for filterType in pairs(filter[char]) do
if filterType == "show" then
filter[char][filterType] = value
elseif (not value) or (history[char] and history[char].spec == filterType) then --Set all specs to false when unticked, set active spec to true when ticked
filter[char][filterType] = value
end
end
filter[char].show = value
local class = self:GetPlayerClass(char)
local playerClassTickerEnabled = false
for char, charData in pairs(filter) do
if self:GetPlayerClass(char) == class and charData.show then --There is still a char with the same class enabled
playerClassTickerEnabled = true
break
end
end
if userData[class] then userData[class]:SetValue(playerClassTickerEnabled) end
self:CheckClassDisable()
self:CheckGuildRankDisable()
if not ignoreApply then
self:ApplyNewFilter()
end
end
function RequestBiS:SetSpecFilter(char, spec, value, ignoreApply)
local shouldRefresh = not value --when ticking a box, it defualts to not show
filter[char][spec] = value
if value then
filter[char].show = true
shouldRefresh = true
else
for k,v in pairs(filter[char]) do
if k ~= "show" and v then -- Check if a spec is still selected, if none
shouldRefresh = false
break
end
end
if shouldRefresh then
filter[char].show = false
end
end
if shouldRefresh then
self:VerifyCheckBoxes()
end
if not ignoreApply then
self:ApplyNewFilter()
end
end
--- Untick the class, and check if other tickboxes should be unticked as a result
-- @param #string class Unlocalized class string
-- @param #boolean value Was the class enabled (true) or disabled (false)
-- @param #boolean ignoreApply Optional, if true then doesn't apply the filter afterwards.
function RequestBiS:SetClassFilter(class, value, ignoreApply)
local userData = dropdownFilter:GetUserDataTable()
for char, data in pairs(filter) do
if self:GetPlayerClass(char) == class then
data.show = value
if userData[char] then
local visible = userData[char]:GetUserData("visible")
visible:SetValue(value)
end
end
end
if not ignoreApply then
self:ApplyNewFilter()
end
self:CheckTokenDisable()
self:CheckGuildRankDisable()
end
--- On clicking a guild filter it'll update the filter according to the guild rank that has been unticked
-- @param #number guildRank the number of the guildrank that is to be unticked
-- @param #boolean value True if enabled, otherwise false
-- @param #boolean ignoreApply Optional, if true then doesn't apply the filter afterwards.
function RequestBiS:SetGuildFilter(guildRank, value, ignoreApply)
for i=1,GetNumGuildMembers() do
local fullName, _, rankIndex = GetGuildRosterInfo(i)
rankIndex = rankIndex + 1
if rankIndex == guildRank then
local playerName = (fullName):match("(%D+)-(%D+)")
if filter[playerName] then
filter[playerName].show = value
end
end
end
if not ignoreApply then
self:ApplyNewFilter()
end
self:CheckPlayerDisable()
end
function RequestBiS:SetArmorFilter(armorType, value)
for i=1,#armorClasses[armorType] do
self:SetClassFilter(armorClasses[armorType][i], value, #armorClasses[armorType] < i)
end
self:CheckClassDisable()
end
local function onClassSelect(widget, _, value)
local class = widget:GetUserData("class")
RequestBiS:SetClassFilter(class, value)
end
local function onTokenSelect(widget, _, value)
local token = widget:GetUserData("token")
for i=1,#classTokens[token] do
local classSelect = dropdownFilter:GetUserData(classTokens[token][i])
if classSelect then
classSelect:SetValue(value)
RequestBiS:SetClassFilter(classTokens[token][i], value, true) --simulate that we're clicking all 3 or 4 class tokens buttons
end
end
RequestBiS:ApplyNewFilter()
end
local function onClickSelectAll(widget)
local selected = widget:GetUserData("select") or false
RequestBiS:SetAllFilter(selected)
end
local function onCharacterView(widget, _, value)
local char = widget:GetUserData("char")
local specFilter = widget:GetUserData("specFilters")
if not value then
for i=1,#specFilter do
specFilter[i]:SetValue(false)
end
else
for i=1,#specFilter do
if specFilter[i]:GetUserData("spec") == history[widget:GetUserData("char")].spec then
specFilter[i]:SetValue(true)
end
end
end
RequestBiS:SetCharFilter(char, value)
end
local function onSpecChanged(widget, _, value)
local char = widget:GetUserData("char")
local spec = widget:GetUserData("spec")
RequestBiS:SetSpecFilter(char, spec, value)
end
local function onGuildRankSelect(widget, _, value)
local guildRankId = widget:GetUserData("rank")
RequestBiS:SetGuildFilter(guildRankId, value)
end
local function onArmorSelect(widget, _, value)
local armorType = widget:GetUserData("type")
RequestBiS:SetArmorFilter(armorType, value)
end
function RequestBiS:GetDropdownSeperator()
local seperator = AceGUI:Create("Dropdown-Item-Separator")
seperator.SetValue = emptySetValue
return seperator
end
local function onShowObtainedValue(widget, _, value)
showObtainedItems = value
RequestBiS:ApplyNewFilter()
end
local function showCacheOnValue(widget, _, value)
showCached = value
RequestBiS:ApplyNewFilter()
end
function RequestBiS:MakeStandardOptions(submenu)
local hasItems = false
for _ in pairs(filter) do
hasItems = true
break
end
local isGuildRequest = responseContainer:GetUserData("channel") == "GUILD" or not responseContainer:GetUserData("channel")
if not hasItems or not isGuildRequest then
if not isGuildRequest then --Don't show anything for party/whisper requests
return
end
local header = AceGUI:Create("Dropdown-Item-Header")
header:SetText(L["Not enough data to filter"])
header.SetValue = emptySetValue
submenu:AddItem(header)
return
end
-- Add Select All button
local selectAll = AceGUI:Create("Dropdown-Item-Execute")
selectAll:SetText(L["Select all"])
selectAll:SetCallback("OnClick", onClickSelectAll)
selectAll.SetValue = emptySetValue
selectAll:SetUserData("select", true)
submenu:AddItem(selectAll)
--Add Deselect All button
local deselectAll = AceGUI:Create("Dropdown-Item-Execute")
deselectAll:SetText(L["Deselect all"])
deselectAll:SetCallback("OnClick", onClickSelectAll)
deselectAll.SetValue = emptySetValue
submenu:AddItem(deselectAll)
local showObtained = AceGUI:Create("Dropdown-Item-Toggle")
showObtained:SetText(L["Show obtained items"])
showObtained:SetCallback("OnValueChanged", onShowObtainedValue)
submenu:AddItem(showObtained)
showObtained:SetValue(showObtainedItems)
submenu:AddItem(self:GetDropdownSeperator())
--Add the class Menu
local classMenu = AceGUI:Create("Dropdown-Item-Menu")
classMenu:SetText(L["Class filter"])
classMenu.SetValue = emptySetValue
local classSubMenu = AceGUI:Create("Dropdown-Pullout")
classSubMenu.SetValue = emptySetValue
local classesDone = {}
for charName, charData in pairs(filter) do
local class, localizedClass = self:GetPlayerClass(charName)
if class and not classesDone[class] then
local classToggle = AceGUI:Create("Dropdown-Item-Toggle")
classToggle:SetUserData("class", class)
classToggle:SetText(self:GetClassString(class))
classToggle:SetCallback("OnValueChanged", onClassSelect)
dropdownFilter:SetUserData(class, classToggle)
classesDone[class] = classToggle
classSubMenu:AddItem(classToggle)
end
end
classMenu:SetMenu(classSubMenu)
submenu:AddItem(classMenu)
--Add the token menu
local tokenMenu = AceGUI:Create("Dropdown-Item-Menu")
tokenMenu:SetText(L["Token filter"])
tokenMenu.SetValue = emptySetValue
local tokenSubMenu = AceGUI:Create("Dropdown-Pullout")
tokenSubMenu.SetValue = emptySetValue
tokenSubMenu:SetWidth(300)
local tokensDone = {}
for tokenType, classes in pairs(classTokens) do
for i=1, #classes do
if classesDone[classes[i]] then
local tokenToggle = tokensDone[tokenType] or AceGUI:Create("Dropdown-Item-Toggle")
if not tokensDone[tokenType] then
tokenToggle:SetUserData("token", tokenType)
local text = L[tokenType].." ("
for j=1,#classes do
if j ~= 1 then
text = text.." / "
end
text = text..self:GetClassString(classes[j])
end
text = text..")"
tokenToggle:SetText(text)
tokenToggle:SetCallback("OnValueChanged", onTokenSelect)
dropdownFilter:SetUserData(tokenType, tokenToggle)
tokensDone[tokenType] = tokenToggle
tokenSubMenu:AddItem(tokenToggle)
break
end
end
end
end
tokenMenu:SetMenu(tokenSubMenu)
submenu:AddItem(tokenMenu)
--Adds the armor filter
local armorMenu = AceGUI:Create("Dropdown-Item-Menu")
armorMenu:SetText(L["Armor filter"])
armorMenu.SetValue = emptySetValue
local armorSubMenu = AceGUI:Create("Dropdown-Pullout")
armorSubMenu.SetValue = emptySetValue
for i,armorType in pairs({BabbleInventory.Cloth, BabbleInventory.Leather, BabbleInventory.Mail, BabbleInventory.Plate}) do
local armorToggle = AceGUI:Create("Dropdown-Item-Toggle")
armorToggle:SetText(armorType)
armorToggle:SetUserData("type", armorType)
armorToggle:SetCallback("OnValueChanged", onArmorSelect)
armorSubMenu:AddItem(armorToggle)
dropdownFilter:SetUserData("Armor"..i, armorToggle)
end
armorMenu:SetMenu(armorSubMenu)
submenu:AddItem(armorMenu)
--Adds the guild filter
if responseContainer:GetUserData("channel") == "GUILD" or not responseContainer:GetUserData("channel") then -- if the guild window is shown
local guildMenu = AceGUI:Create("Dropdown-Item-Menu")
guildMenu:SetText(GUILDCONTROL_GUILDRANKS)
guildMenu.SetValue = emptySetValue
local guildSubMenu = AceGUI:Create("Dropdown-Pullout")
guildSubMenu.SetValue = emptySetValue
for i=1, GuildControlGetNumRanks() do
local guildRank = AceGUI:Create("Dropdown-Item-Toggle")
guildRank:SetText(GuildControlGetRankName(i))
guildRank:SetUserData("rank", i)
guildRank:SetCallback("OnValueChanged", onGuildRankSelect)
guildSubMenu:AddItem(guildRank)
dropdownFilter:SetUserData("GuildRank"..i, guildRank)
end
guildMenu:SetMenu(guildSubMenu)
submenu:AddItem(guildMenu)
end
submenu:AddItem(self:GetDropdownSeperator())
end
function RequestBiS:MakeCharSpecificOptions(submenu, char)
local header = AceGUI:Create("Dropdown-Item-Header")
header:SetText(self:GetPlayerString(char))
submenu:AddItem(header)
local visibleItem = AceGUI:Create("Dropdown-Item-Toggle")
visibleItem:SetText(SHOW)
visibleItem:SetUserData("char", char)
visibleItem:SetCallback("OnValueChanged", onCharacterView)
submenu:SetUserData("visible", visibleItem)
submenu:AddItem(visibleItem)
local specFilters = {}
if history[char] and history[char].spec then
submenu:AddItem(self:GetDropdownSeperator())
for specId in pairs(history[char]) do
if type(tonumber(specId)) == "number" then
local _, specName = GetSpecializationInfoByID(specId)
local specOptions = AceGUI:Create("Dropdown-Item-Toggle")
specOptions:SetText(specName)
specOptions:SetUserData("spec", tonumber(specId))
specOptions:SetUserData("char", char)
specOptions:SetValue(history[char].spec == specId)
specOptions:SetCallback("OnValueChanged", onSpecChanged)
tinsert(specFilters, specOptions)
submenu:AddItem(specOptions)
end
end
end
visibleItem:SetUserData("specFilters", specFilters)
end
function RequestBiS:ValidateFilters()
for k,v in pairs(filter) do
if not history[k] then
filter[k] = nil
end
end
end
function RequestBiS:SetFilterOptions()
dropdownFilter:SetList({})
self:ValidateFilters()
wipe(dropdownFilter:GetUserDataTable())
self:MakeStandardOptions(dropdownFilter.pullout)
local disabled = true
local orderedList = {}
for char in pairs(filter) do
if not history[char] then
filter[char] = nil
else
tinsert(orderedList, char)
end
end
tsort(orderedList)
for i,char in pairs(orderedList) do
disabled = false
local submenu = AceGUI:Create("Dropdown-Pullout")
self:MakeCharSpecificOptions(submenu, char)
local dropdownGroup = AceGUI:Create("Dropdown-Item-Menu")
dropdownGroup:SetText(self:GetPlayerString(char))
dropdownGroup:SetMenu(submenu)
dropdownGroup.SetValue = emptySetValue
dropdownFilter.pullout:AddItem(dropdownGroup)
dropdownFilter:SetUserData(char, submenu)
end
dropdownFilter:SetDisabled(disabled)
self:VerifyCheckBoxes()
end
function RequestBiS:FormatResponse(source, bisList)
guildName = guildName or GetGuildInfo("player")
if bisList.spec then
local activeSpec = bisList.spec or self.db.factionrealm[guildName][source].activeSpec or bisList.spec
history[source] = bisList
filter[source] = filter[source] or {show = true, [activeSpec] = true}
return bisList[bisList.spec], bisList.spec
else
self.console:AddError("Invalid data for registering responsecontainer. Is user using an outdated version of BestInSlot?", source, bisList)
end
return {}
end
function RequestBiS:DoRegister(source, bisList)
local bisList, filteredSpec = self:FormatResponse(source, bisList)
self:RegisterRaidTier(source, bisList, filteredSpec)
end
function RequestBiS:HasSpecsFilledIn(itemlist)
for k,v in pairs(itemlist) do
if k ~= "spec" then
return true
end
end
return false
end
---
-- Itemlist format:
-- {
-- [specId1] = {{item = item1, obtained = false}, {item = item2, obtained = true}}
-- [specId2] = {{item = item1, obtained = false}, {item = item2, obtained = true}}
-- spec = CurrentSpec (used for the other client to define what to show)
-- }
---
local function hasEntries(tbl)
for k,v in pairs(tbl) do
return true
end
return false
end
local function requestRaidTierReply(itemlist, channel, source, version)
RequestBiS:Print(itemlist)
guildName = guildName or GetGuildInfo("player")
for k,v in pairs(itemlist) do
if k ~= "spec" then
if not hasEntries(v) then
itemlist[k] = nil
end
end
end
RequestBiS:Print(itemlist)
if not itemlist or type(itemlist) ~= "table" then return end
local selected = RequestBiS:GetSelected()
if not responseContainer then return end
if not RequestBiS:HasSpecsFilledIn(itemlist) then return end
local responseChannel = responseContainer:GetUserData("channel")
if responseChannel == "GUILD" then
RequestBiS:SaveGuildBestInSlotList(guildName, source, itemlist, selected.raidtier, selected.difficulty, nil, version)
elseif responseChannel == "WHISPER" then
local list = RequestBiS:GetCacheData()
if #list ~= 0 and list[source] and list[source].guild == guildName then
RequestBiS:SaveGuildBestInSlotList(guildName, source, itemlist, selected.raidtier, selected.difficulty, nil, version)
end
end
RequestBiS:Print(itemlist)
RequestBiS:QueueRegister(source, itemlist)
end
RequestBiS:RegisterCommFunction("requestRaidTier", requestRaidTier)
RequestBiS:RegisterCommFunction("requestRaidInstance", requestRaidInstance)
RequestBiS:RegisterCommFunction("requestRaidTierReply", requestRaidTierReply)
RequestBiS:RegisterEvent("PLAYER_GUILD_UPDATE", function()
if IsInGuild() then
guildName = GetGuildInfo("player")
else
guildName = nil
end
end)
RequestBiS:RegisterTutorials(L["Request BiS"], {
[1] = {text = L["On this page you can request BestInSlot lists from your friends, guildmembers or raidmembers."], xOffset = 0, yOffset = -50, container = "content"},
[2] = {text = (L["Use the '%s' dropdown to pick where you would like to request lists from."]):format(L["Request from"]), xOffset = 0, yOffset = -10, container = "content", element = "request", UpArrow = true},
[3] = {text = L["When picking the whisper target, make sure you also fill in a recipient!"], xOffset = 0, yOffset = -10, container = "content", element = "wtarget", onRequest = true, UpArrow = true},
[4] = {text = L["When you have successfully received BestInSlot lists you can use the filter to filter lists."], xOffset = 0, yOffset = -10, container = "content", element = "filter", onRequest = true, UpArrow = true}
})