Mercurial > wow > askmrrobot
view Loot.lua @ 101:ec6f0938932f v46
Removed tag v46
author | yellowfive |
---|---|
date | Tue, 25 Oct 2016 10:00:40 -0700 |
parents | cf2b6b9a8337 |
children |
line wrap: on
line source
local Amr = LibStub("AceAddon-3.0"):GetAddon("AskMrRobot") local L = LibStub("AceLocale-3.0"):GetLocale("AskMrRobot", true) local AceGUI = LibStub("AceGUI-3.0") local _frameLoot local _panelLoot local _selectedIndex local _disenchant = {} local _rankPanels local _lootButtons local _widthItemList = 220 local _widthRankList = 640 local _widthSpacing = 10 local _widthRank = 48 local _widthRankBar = 195 local _widthRollType = 45 local _widthColPadding = 8 local _widthRollExtraSpacing = 4 local _rollTypePos = { Need = 1, Off = 2, Greed = 3, Pass = 4 } -- get the index of the loot item that matches up to the specified item local function getLootIndex(itemIndex) local ranking = Amr.db.global.TeamOpt.Rankings[itemIndex] if not ranking then return nil end local itemUniqueId = Amr.GetItemUniqueId(ranking.item) for i = 1, GetNumLootItems() do --local texture, item, quantity, quality, locked = GetLootSlotInfo(i) local lootType = GetLootSlotType(i) if lootType == 1 then local link = GetLootSlotLink(i) local lootItem = Amr.ParseItemLink(link) if Amr.GetItemUniqueId(lootItem) == itemUniqueId then return i, link end end end end local function getLootCandidateIndex(lootIndex, realm, name) -- remove spaces to ensure proper matches, and make all lower realm = string.gsub(realm, "%s+", "") realm = string.lower(realm) name = string.lower(name) local nameMatches = {} for i = 1, 40 do local candidate = GetMasterLootCandidate(lootIndex, i) if candidate then local candidateName = candidate local candidateRealm = GetRealmName() -- see if realm is in the name local splitPos = string.find(candidateName, "-") if splitPos ~= nil then candidateRealm = string.sub(candidateName, splitPos + 1) candidateName = string.sub(candidateName, 1, splitPos - 1) end -- remove spaces to ensure proper matches, and make all lower candidateRealm = string.gsub(candidateRealm, "%s+", "") candidateRealm = string.lower(candidateRealm) candidateName = string.lower(candidateName) -- if perfect match then we are done if candidateRealm == realm and candidateName == name then return i end if candidateName == name then table.insert(nameMatches, i) end end end -- only one player with same name, must be the player of interest if #nameMatches == 1 then return nameMatches[1] end -- could not be found or ambiguous return nil end -- helper to send a message telling everyone that an item was just given out local function sendGiveLootMessage(itemLink, unitId, isDisenchant) -- some display info local cls, clsEn = UnitClass(unitId) local name = UnitName(unitId) local result = isDisenchant and "Disenchant" or (roll and roll.rollType or nil) if result == nil then result = "??" end local msg = string.format("%s\n%d\n%s\n%s\n%s\n%s", Amr.LootMessagePrefixes.Give, _selectedIndex, itemLink, result, clsEn, name) Amr:SendAmrCommMessage(msg) end local function onGiveLootClick(widget) local rollIndex = widget:GetUserData("index") local rankings = Amr.db.global.TeamOpt.Rankings local ranking = rankings[_selectedIndex] local rank = ranking and ranking.ranks[rollIndex] or nil if rank then local roll = Amr.db.char.TeamOpt.Rolls[_selectedIndex][rollIndex] local isDisenchant = not not _disenchant[_selectedIndex] local unitId = Amr:GetUnitId(rank.realm, rank.name) if unitId then -- find the item and loot candidate index local itemIndex, itemLink = getLootIndex(_selectedIndex) -- for debugging when don't actually have any loot --itemLink = Amr.CreateItemLink(ranking.item) local playerIndex = itemIndex and getLootCandidateIndex(itemIndex, rank.realm, rank.name) or nil if itemIndex and playerIndex then GiveMasterLoot(itemIndex, playerIndex) sendGiveLootMessage(itemLink, unitId, isDisenchant) return end end end -- if we make it here, we could not give out the item for some reason Amr:Print(L.LootMasterGiveFail) end function Amr:OnLootGiveReceived(parts) if not parts or #parts < 6 then return end local rankings = Amr.db.global.TeamOpt.Rankings -- index of the item that was given, flag it to hide it from the ui now local index = tonumber(parts[2]) local ranking = rankings[index] if ranking then ranking.given = true end -- change the selected item index to the next ungiven item for i, obj in ipairs(rankings) do if not obj.given then _selectedIndex = i break end end -- add a loot history entry local entry = { link = parts[3], result = parts[4], class = parts[5], name = parts[6] } table.insert(Amr.db.char.TeamOpt.History, entry) -- redraw any open windows Amr:RefreshTeamUi() Amr:RefreshLootWindow() Amr:RefreshLootRolls() -- if this is the master looter, check if all items have been given out if IsMasterLooter() then local allDone = true for i, ranking in ipairs(rankings) do if not ranking.given then allDone = false break end end if allDone then -- send a message indicating that looting is done Amr:SendAmrCommMessage(Amr.LootMessagePrefixes.Finish) end end end local function onDisenchantClick() local val = not _disenchant[_selectedIndex] _disenchant[_selectedIndex] = val Amr:RefreshLootWindow() Amr:RefreshLootRolls() end local function onRollClick() -- generate a roll for everyone on the current item local rands = {} local ranking = Amr.db.global.TeamOpt.Rankings[_selectedIndex] for i, rank in ipairs(ranking.ranks) do local r = math.random(100) rands[i] = r end -- transmit the roll data to all group members local msg = string.format("%s\n%d\n%s", Amr.LootMessagePrefixes.Rand, _selectedIndex, Amr:Serialize(rands)) Amr:SendAmrCommMessage(msg) end function Amr:OnLootRandReceived(parts) if not parts or #parts < 3 then return end local index = tonumber(parts[2]) local success, rands = Amr:Deserialize(parts[3]) if not index or not success then return end local rolls = Amr.db.char.TeamOpt.Rolls[index] for i, r in pairs(rands) do local roll = rolls[i] if not roll then roll = {} rolls[i] = roll end roll.rand = r end Amr:RefreshLootRolls() end local function onVetoClick(widget) local rollIndex = widget:GetUserData("rollIndex") local rollType = widget:GetUserData("rollType") -- acts like a toggle local roll = Amr.db.char.TeamOpt.Rolls[_selectedIndex][rollIndex] local veto = not roll or not roll.vetoes or not roll.vetoes[rollType] -- send a message that a veto has been changed local msg = string.format("%s\n%d\n%d\n%s\n%s", Amr.LootMessagePrefixes.Veto, _selectedIndex, rollIndex, rollType, veto and "t" or "f") Amr:SendAmrCommMessage(msg) end function Amr:OnLootVetoReceived(parts) if not parts or #parts < 5 then return end local itemIndex = tonumber(parts[2]) local rollIndex = tonumber(parts[3]) local rollType = parts[4] local veto = parts[5] == "t" if itemIndex and rollIndex then local roll = Amr.db.char.TeamOpt.Rolls[itemIndex][rollIndex] if not roll then roll = {} Amr.db.char.TeamOpt.Rolls[itemIndex][rollIndex] = roll end if not roll.vetoes then roll.vetoes = {} end roll.vetoes[rollType] = veto -- if the player chose this option, have to remove it because it has been vetoed if veto and roll.rollType == rollType then roll.rollType = nil end Amr:RefreshLootRolls() end end -- a user choice for what they want to do on an item local function doRoll(rollType) local msg = string.format("%s\n%d\n%s\n%s\n%s", Amr.LootMessagePrefixes.Roll, _selectedIndex, rollType, GetRealmName(), UnitName("player")) Amr:SendAmrCommMessage(msg) end function Amr:OnLootRollReceived(parts) local index = tonumber(parts[2]) local rollType = parts[3] local realm = parts[4] local name = parts[5] -- for now, this code matches up name/realm to one in the rankings -- TODO: more robust handling of players with same name but different realms in the same group on non-english clients local nameMatches = {} local ranking = Amr.db.global.TeamOpt.Rankings[index] for i, rank in ipairs(ranking.ranks) do if name == rank.name and realm == rank.realm then nameMatches = {} break end if name == rank.name then table.insert(nameMatches, rank) end end if #nameMatches == 1 then realm = nameMatches[1].realm name = nameMatches[1].name end -- find index of the ranking local rankIndex = nil for i, rank in ipairs(ranking.ranks) do if name == rank.name and realm == rank.realm then rankIndex = i break end end if rankIndex then local obj = Amr.db.char.TeamOpt.Rolls[index][rankIndex] if not obj then obj = {} Amr.db.char.TeamOpt.Rolls[index][rankIndex] = obj end obj.rollType = rollType end Amr:RefreshLootRolls() end local function renderRollType(rp, rollType, roll, index) local icon = rp:GetUserData(rollType) if not icon and roll then -- create icon if we need one icon = AceGUI:Create("AmrUiTextButton") icon:SetWidth(16) icon:SetHeight(16) local pos = _rollTypePos[rollType] local left = _widthRank + _widthColPadding + _widthRankBar + (pos * _widthColPadding) + ((pos - 1) * _widthRollType) + ((_widthRollType - 16) / 2) icon:SetPoint("LEFT", rp.content, "LEFT", left, 0) rp:AddChild(icon) rp:SetUserData(rollType, icon) icon:SetUserData("rollType", rollType) icon:SetUserData("rollIndex", index) icon:SetVisible(false) icon:SetCallback("OnClick", onVetoClick) end if icon then if roll and roll.rollType == rollType then icon:SetVisible(true) icon:SetBackgroundImage("Interface\\AddOns\\" .. Amr.ADDON_NAME .. "\\Media\\IconCheck") icon:SetHoverBackgroundImage("Interface\\AddOns\\" .. Amr.ADDON_NAME .. "\\Media\\IconCheck") elseif roll and roll.vetoes and roll.vetoes[rollType] then icon:SetVisible(true) icon:SetBackgroundImage("Interface\\AddOns\\" .. Amr.ADDON_NAME .. "\\Media\\IconX") icon:SetHoverBackgroundImage("Interface\\AddOns\\" .. Amr.ADDON_NAME .. "\\Media\\IconX") else icon:SetVisible(false) end icon:SetDisabled(not IsMasterLooter()) end -- update button state for this roll type if _lootButtons and _lootButtons[rollType] then _lootButtons[rollType]:SetDisabled(roll and roll.vetoes and roll.vetoes[rollType]) end end -- gets the current winner based on rolls and currently selected roll type for each user (returns index into rankings for item, or -1 if no winner yet) local function getWinner(itemIndex) local rolls = Amr.db.char.TeamOpt.Rolls[itemIndex] if not rolls then return -1 end -- go through and find the highest priority roll type local bestRollType local bestTypePos = 100 for i, roll in pairs(rolls) do if roll.rollType then local rollPos = _rollTypePos[roll.rollType] if rollPos < bestTypePos and rollPos < _rollTypePos["Pass"] then bestRollType = roll.rollType bestTypePos = rollPos end end end -- nobody has chosen anything yet if not bestRollType then return -1 end -- find highest roll in the highest priority roll type local maxRoll = -1 local bestRoll = -1 for i, roll in pairs(rolls) do if roll.rollType == bestRollType and roll.rand and roll.rand > maxRoll then bestRoll = i maxRoll = roll.rand end end return bestRoll end function Amr:RefreshLootRolls() if not _rankPanels then return end local ranking = Amr.db.global.TeamOpt.Rankings[_selectedIndex] local rolls = Amr.db.char.TeamOpt.Rolls[_selectedIndex] local isDisenchant = _disenchant[_selectedIndex] local winnerIndex = getWinner(_selectedIndex) for i, rp in pairs(_rankPanels) do local rank = ranking.ranks[i] local roll = rolls[i] if isDisenchant then roll = nil end -- clear or set the value of each roll column renderRollType(rp, "Need", roll, i) renderRollType(rp, "Off", roll, i) renderRollType(rp, "Greed", roll, i) renderRollType(rp, "Pass", roll, i) -- render the random roll local lbl = rp:GetUserData("randLabel") if roll and roll.rand then if not lbl then lbl = AceGUI:Create("AmrUiLabel") lbl:SetJustifyH("RIGHT") local left = _widthRank + _widthColPadding + _widthRankBar + (5 * _widthColPadding) + (5 * _widthRollType) lbl:SetPoint("RIGHT", rp.content, "LEFT", left, 0) rp:AddChild(lbl) rp:SetUserData("randLabel", lbl) end -- highlight this roll if winner, otherwise unhighlight if i == winnerIndex then lbl:SetFont(Amr.CreateFont("Bold", 18, Amr.Colors.BrightGreen)) else lbl:SetFont(Amr.CreateFont("Regular", 14, Amr.Colors.White)) end lbl:SetText(roll.rand) else if lbl then lbl:SetVisible(false) end end -- if this person does not have the addon, show a message (except in DE mode) local hasAddon = true local unitId = Amr:GetUnitId(rank.realm, rank.name) if unitId then local realm, name = Amr:GetRealmAndName(unitId) if realm then local ver = Amr:GetAddonVersion(realm, name) hasAddon = ver >= Amr.MIN_ADDON_VERSION end end lbl = rp:GetUserData("noaddonLabel") if not hasAddon and not isDisenchant then if not lbl then lbl = AceGUI:Create("AmrUiLabel") lbl:SetFont(Amr.CreateFont("Italic", 14, Amr.Colors.Red)) lbl:SetText(L.LootRankLabelNoAddon) lbl:SetPoint("LEFT", rp.content, "LEFT", _widthRank + _widthColPadding + _widthRankBar + _widthColPadding + 5, 0) rp:AddChild(lbl) rp:SetUserData("noaddonLabel", lbl) end else if lbl then lbl:SetVisible(false) end end end end -- helper to create the column bg and header for rank list local function createLootRankColumn(container, prevColumn, width, txt, txtAlign, extraPadding) extraPadding = extraPadding and extraPadding or 0 local panel = AceGUI:Create("AmrUiPanel") panel:SetBackgroundColor(Amr.Colors.Black, 0.3) container:AddChild(panel) if prevColumn then -- pad a bit to right of previous column panel:SetPoint("TOPLEFT", prevColumn.content, "TOPRIGHT", _widthColPadding + extraPadding, 0) panel:SetPoint("BOTTOMRIGHT", prevColumn.content, "BOTTOMRIGHT", _widthColPadding + extraPadding + width, 0) else -- first column abs position in the main ranking panel panel:SetPoint("TOPLEFT", container.content, "TOPLEFT", _widthItemList + _widthSpacing, -115) panel:SetPoint("BOTTOMRIGHT", container.content, "BOTTOMLEFT", _widthItemList + _widthSpacing + width, 0) end lbl = AceGUI:Create("AmrUiLabel") lbl:SetWordWrap(false) lbl:SetFont(Amr.CreateFont("Regular", 12, Amr.Colors.TextHeaderDisabled)) lbl:SetText(txt) lbl:SetJustifyH(txtAlign) lbl:SetWidth(width) lbl:SetPoint("BOTTOMLEFT", panel.content, "TOPLEFT", 0, 5) container:AddChild(lbl) return panel, lbl end function Amr:RefreshLootWindow() if not _panelLoot then return end -- clear out any children of the main loot frame and re-render _panelLoot:ReleaseChildren() _rankPanels = {} _lootButtons = {} local ml = IsMasterLooter() local myUnitId = Amr:GetUnitId(GetRealmName(), UnitName("player")) local rankings = Amr.db.global.TeamOpt.Rankings if rankings and #rankings > 0 then -- make sure that an item is selected if not _selectedIndex then for i, ranking in ipairs(rankings) do if not ranking.given then _selectedIndex = i break end end end -- render list of items local panelItems = AceGUI:Create("AmrUiPanel") panelItems:SetLayout("Fill") panelItems:SetWidth(_widthItemList) panelItems:SetBackgroundColor(Amr.Colors.Black, 0) panelItems:SetPoint("TOPLEFT", _panelLoot.content, "TOPLEFT", 0, 0) panelItems:SetPoint("BOTTOMLEFT", _panelLoot.content, "BOTTOMLEFT") _panelLoot:AddChild(panelItems) local scrollItems = AceGUI:Create("AmrUiScrollFrame") scrollItems:SetLayout("List") panelItems:AddChild(scrollItems) -- render the divider between items and ranks local divider = AceGUI:Create("AmrUiPanel") divider:SetBackgroundColor(Amr.Colors.Black, 0.5) divider:SetPoint("TOPLEFT", _panelLoot.content, "TOPLEFT", _widthItemList, 0) divider:SetPoint("BOTTOMRIGHT", _panelLoot.content, "BOTTOMLEFT", _widthItemList + 5, 0) _panelLoot:AddChild(divider) local btn, btn2, lbl, lbl2, panel, panel2, chk local remainingItems = {} for i, ranking in ipairs(rankings) do if not ranking.given then remainingItems[i] = ranking end end for i, ranking in pairs(remainingItems) do btn = AceGUI:Create("AmrUiTextButton") btn:SetWidth(_widthItemList) btn:SetHeight(50) btn:SetJustifyH("LEFT") btn:SetJustifyV("TOP") btn:SetTextPadding(9, nil, nil, 2) btn:SetWordWrap(false) btn:SetUserData("index", i) local f if _selectedIndex == i then f = Amr.CreateFont("Bold", 16, Amr.Colors.Text) btn:SetBackgroundColor(Amr.Colors.Black, 0.5) btn:SetHoverBackgroundColor(Amr.Colors.Black, 0.5) else f = Amr.CreateFont("Regular", 14, Amr.Colors.Text) btn:SetHoverBackgroundColor(Amr.Colors.Black, 0.2) end btn:SetFont(f) btn:SetHoverFont(f) scrollItems:AddChild(btn) btn:SetCallback("OnClick", function(widget) Amr:SelectLootItem(widget:GetUserData("index")) end) local rankLink = Amr.CreateItemLink(ranking.item) Amr.GetItemInfo(rankLink, function(obj, name, link) -- set item name, tooltip obj:SetText(" " .. link:gsub("%[", ""):gsub("%]", "")) Amr:SetItemTooltip(obj, link, "ANCHOR_BOTTOMLEFT", 0, obj.frame:GetHeight()) end, btn) -- add a label for slot, armor type local slotText = Amr.SlotEnumDisplayText[ranking.itemInfo.slot] if ranking.itemInfo.slot == 'MainHand' then slotText = ranking.itemInfo.subclass == 'TwoHand' and L.TwoHand or L.OneHand elseif ranking.itemInfo.slot == 'OffHand' then slotText = L.OffHand end if ranking.itemInfo.armorType == 'None' and ranking.itemInfo.weaponType ~= 'None' then if ranking.itemInfo.weaponType ~= 'OffHand' then slotText = slotText .. ", " .. L.WeaponTypes[ranking.itemInfo.weaponType] end elseif ranking.itemInfo.armorType ~= 'None' then slotText = slotText .. ", " .. L.ArmorTypes[ranking.itemInfo.armorType] end btn:SetSubtextFont(Amr.CreateFont("Regular", 13, Amr.Colors.TextGray)) btn:SetSubtextJustifyH("LEFT") btn:SetSubtextJustifyV("BOTTOM") btn:SetSubtextPadding(nil, nil, 9, 7) btn:SetSubtextWordWrap(false) btn:SetSubtext(slotText) local isDisenchant = not not _disenchant[i] if _selectedIndex == i then -- see if I am in the list local canLoot = false for j, rank in ipairs(ranking.ranks) do local unitId = Amr:GetUnitId(rank.realm, rank.name) if unitId == myUnitId then canLoot = not rank.notRanked or rank.offspec break end end -- render loot options if canLoot then btn = AceGUI:Create("AmrUiButton") btn:SetWidth(120) btn:SetHeight(26) btn:SetFont(Amr.CreateFont("Bold", 15, Amr.Colors.White)) btn:SetBackgroundColor(Amr.Colors.Green) btn:SetText(L.TeamLootOptionNeed) btn:SetPoint("TOPLEFT", _panelLoot.content, "TOPLEFT", _widthItemList + _widthSpacing, -7) btn:SetCallback("OnClick", function(widget) doRoll("Need") end) _panelLoot:AddChild(btn) _lootButtons["Need"] = btn btn2 = AceGUI:Create("AmrUiButton") btn2:SetWidth(120) btn2:SetHeight(26) btn2:SetFont(Amr.CreateFont("Bold", 15, Amr.Colors.White)) btn2:SetBackgroundColor(Amr.Colors.Orange) btn2:SetText(L.TeamLootOptionPass) btn2:SetPoint("TOPLEFT", btn.frame, "BOTTOMLEFT", 0, -15) btn2:SetCallback("OnClick", function(widget) doRoll("Pass") end) _panelLoot:AddChild(btn2) _lootButtons["Pass"] = btn2 btn = AceGUI:Create("AmrUiButton") btn:SetWidth(120) btn:SetHeight(26) btn:SetFont(Amr.CreateFont("Bold", 15, Amr.Colors.White)) btn:SetBackgroundColor(Amr.Colors.Blue) btn:SetText(L.TeamLootOptionOff) btn:SetPoint("BOTTOMLEFT", btn2.frame, "TOPRIGHT", 15, 15) btn:SetCallback("OnClick", function(widget) doRoll("Off") end) _panelLoot:AddChild(btn) _lootButtons["Off"] = btn btn2 = AceGUI:Create("AmrUiButton") btn2:SetWidth(120) btn2:SetHeight(26) btn2:SetFont(Amr.CreateFont("Bold", 15, Amr.Colors.White)) btn2:SetBackgroundColor(Amr.Colors.Blue) btn2:SetText(L.TeamLootOptionGreed) btn2:SetPoint("TOPLEFT", btn.frame, "BOTTOMLEFT", 0, -15) btn2:SetCallback("OnClick", function(widget) doRoll("Greed") end) _panelLoot:AddChild(btn2) _lootButtons["Greed"] = btn2 else lbl = AceGUI:Create("AmrUiLabel") lbl:SetFont(Amr.CreateFont("Italic", 14, Amr.Colors.TextTan)) lbl:SetText(L.LootIneligible) lbl:SetWidth(255) lbl:SetPoint("TOPLEFT", _panelLoot.content, "TOPLEFT", _widthItemList + _widthSpacing, -7) _panelLoot:AddChild(lbl) end -- master loot options if ml then chk = AceGUI:Create("AmrUiCheckBox") chk:SetText(L.LootMasterDisenchantText) chk:SetPoint("TOPRIGHT", _panelLoot.content, "TOPRIGHT", -18, -12) chk:SetCallback("OnClick", onDisenchantClick) chk:SetChecked(_disenchant[i]) _panelLoot:AddChild(chk) lbl = AceGUI:Create("AmrUiLabel") lbl:SetWidth(120) lbl:SetJustifyH("CENTER") lbl:SetText(L.LootMasterDisenchantLabel) lbl:SetFont(Amr.CreateFont("Italic", 12, Amr.Colors.TextTan)) lbl:SetPoint("TOP", chk.frame, "BOTTOM", 0, -5) _panelLoot:AddChild(lbl) btn2 = AceGUI:Create("AmrUiButton") btn2:SetWidth(120) btn2:SetHeight(26) btn2:SetFont(Amr.CreateFont("Bold", 15, Amr.Colors.White)) btn2:SetBackgroundColor(Amr.Colors.Green) btn2:SetText(L.LootMasterRollText) btn2:SetPoint("RIGHT", chk.frame, "LEFT", -50, 0) btn2:SetCallback("OnClick", onRollClick) _panelLoot:AddChild(btn2) lbl = AceGUI:Create("AmrUiLabel") lbl:SetWidth(120) lbl:SetJustifyH("CENTER") lbl:SetText(L.LootMasterRollLabel) lbl:SetFont(Amr.CreateFont("Italic", 12, Amr.Colors.TextTan)) lbl:SetPoint("TOP", btn2.frame, "BOTTOM", 0, -5) _panelLoot:AddChild(lbl) end -- backgrounds for the rank list and headers panel = createLootRankColumn(_panelLoot, nil, _widthRank, isDisenchant and "" or L.LootRankHeaderRank, "RIGHT") panel = createLootRankColumn(_panelLoot, panel, _widthRankBar, isDisenchant and L.LootRankHeaderScoreDisenchant or L.LootRankHeaderScore, "LEFT") if not isDisenchant then panel = createLootRankColumn(_panelLoot, panel, _widthRollType, L.LootRankHeaderNeed, "CENTER") panel = createLootRankColumn(_panelLoot, panel, _widthRollType, L.LootRankHeaderOff, "CENTER") panel = createLootRankColumn(_panelLoot, panel, _widthRollType, L.LootRankHeaderGreed, "CENTER") panel = createLootRankColumn(_panelLoot, panel, _widthRollType, L.LootRankHeaderPass, "CENTER") panel = createLootRankColumn(_panelLoot, panel, _widthRollType, L.LootRankHeaderRoll, "RIGHT", _widthRollExtraSpacing) end -- rank list for selected item panel = AceGUI:Create("AmrUiPanel") panel:SetLayout("Fill") panel:SetBackgroundColor(Amr.Colors.Black, 0) panel:SetPoint("TOPLEFT", _panelLoot.content, "TOPLEFT", _widthItemList + _widthSpacing, -115) panel:SetPoint("BOTTOMRIGHT", _panelLoot.content, "BOTTOMRIGHT") _panelLoot:AddChild(panel) local scrollRanks = AceGUI:Create("AmrUiScrollFrame") scrollRanks:SetLayout("List") panel:AddChild(scrollRanks) -- find min and max value, used for sizing the bars local rankMin = -0.02 local rankMax = 0.02 for j, rank in ipairs(ranking.ranks) do if rank.score < rankMin then rankMin = rank.score end if rank.score > rankMax then rankMax = rank.score end end -- just make min less than max if they are the same, doesn't really matter what it is, would be a wacky case if rankMin == rankMax then rankMin = rankMax - 1 end local minWidth = 10 local maxWidth = _widthRankBar - 36 - 65 - 2 -- reserve 36 for icon, 65 for bar label, and 2 for a border around the bar local rankCount = 0 for j, rank in ipairs(ranking.ranks) do local unitId = Amr:GetUnitId(rank.realm, rank.name) if unitId then local skip = false if isDisenchant then skip = true if rank.isMasterLooter or (rank.enchantingSkill and rank.enchantingSkill > 0) then skip = false end end if not skip then rankCount = rankCount + 1 local rp = AceGUI:Create("AmrUiPanel") rp:SetLayout("None") rp:SetBackgroundColor(Amr.Colors.Black, 0) rp:SetWidth(_widthRankList) rp:SetHeight(45) scrollRanks:AddChild(rp) _rankPanels[j] = rp if not isDisenchant then panel = AceGUI:Create("AmrUiPanel") panel:SetBackgroundColor(Amr.Colors.Black, 1) panel:SetPoint("TOPLEFT", rp.content, "BOTTOMLEFT", 0, 0) panel:SetPoint("BOTTOMRIGHT", rp.content, "BOTTOMRIGHT", -120, -1) rp:AddChild(panel) end lbl = AceGUI:Create("AmrUiLabel") lbl:SetFont(Amr.CreateFont("Bold", 32, Amr.Colors.White)) lbl:SetText(rankCount) lbl:SetWidth(_widthRank - 6) lbl:SetJustifyH("RIGHT") lbl:SetPoint("BOTTOMLEFT", rp.content, "BOTTOMLEFT", 0, 3) rp:AddChild(lbl) local cls, clsEn = UnitClass(unitId) local color = clsEn and Amr.Colors.Classes[clsEn] or Amr.Colors.TextHeaderDisabled local icon = AceGUI:Create("AmrUiIcon") icon:SetIconBorderColor(color) icon:SetWidth(36) icon:SetHeight(36) icon:SetIcon("Interface\\Icons\\" .. Amr.SpecIcons[rank.specId]) icon:SetPoint("BOTTOMLEFT", rp.content, "BOTTOMLEFT", 48 + 8, 0) rp:AddChild(icon) lbl = AceGUI:Create("AmrUiLabel") lbl:SetFont(Amr.CreateFont("Bold", 16, color)) lbl:SetText(UnitName(unitId)) lbl:SetWidth(_widthRankBar - 36 - 8) -- 4px on left and right side lbl:SetPoint("TOPLEFT", icon.frame, "TOPRIGHT", 4, -2) rp:AddChild(lbl) if isDisenchant or rank.notRanked then lbl = AceGUI:Create("AmrUiLabel") lbl:SetFont(Amr.CreateFont("Italic", 13, Amr.Colors.TextHeaderDisabled)) lbl:SetWidth(_widthRankBar - 36 - 4) -- 4px on left side lbl:SetWordWrap(false) lbl:SetPoint("BOTTOMLEFT", icon.frame, "BOTTOMRIGHT", 4, 2) rp:AddChild(lbl) if isDisenchant then -- will be disenchanter or ML if we are DEing the item lbl:SetText((rank.enchantingSkill and rank.enchantingSkill > 0) and string.format(L.LootRankLabelDisenchant .. " (%d)", rank.enchantingSkill) or L.LootRankLabelMasterLooter) else -- if this is off spec or just a disenchanter, no score bar just description text lbl:SetText(rank.offspec and L.LootRankLabelOff or ((rank.enchantingSkill and rank.enchantingSkill > 0) and string.format(L.LootRankLabelDisenchant .. " (%d)", rank.enchantingSkill) or L.LootRankLabelMasterLooter)) end else local scoreText = rank.score .. "%" local val = rank.score; if rank.isEquipped then scoreText = "E" val = 0 elseif val >= 0 then scoreText = "+" .. scoreText end local per = (val - rankMin) / (rankMax - rankMin); local w = minWidth + (per * (maxWidth - minWidth)); color = val > 0 and Amr.Colors.BarHigh or (val == 0 and Amr.Colors.BarMed or Amr.Colors.BarLow) panel = AceGUI:Create("AmrUiPanel") panel:SetLayout("None") panel:SetWidth(w + 2) panel:SetHeight(16) panel:SetBackgroundColor(Amr.Colors.Black, 1) panel:SetPoint("BOTTOMLEFT", icon.frame, "BOTTOMRIGHT", 0, -1) rp:AddChild(panel) panel2 = AceGUI:Create("AmrUiPanel") panel2:SetLayout("None") panel2:SetWidth(w) panel2:SetHeight(14) panel2:SetBackgroundColor(color, 1) panel2:SetPoint("TOPLEFT", panel.content, "TOPLEFT", 1, -1) panel:AddChild(panel2) lbl = AceGUI:Create("AmrUiLabel") lbl:SetFont(Amr.CreateFont("Bold", 13, color)) lbl:SetText(scoreText) lbl:SetWidth(63) lbl:SetWordWrap(false) lbl:SetPoint("LEFT", panel.content, "RIGHT", 2, 0) rp:AddChild(lbl) end if ml then btn2 = AceGUI:Create("AmrUiButton") btn2:SetHeight(24) btn2:SetFont(Amr.CreateFont("Regular", 13, Amr.Colors.White)) btn2:SetBackgroundColor(Amr.Colors.Green) if isDisenchant then btn2:SetWidth(200) btn2:SetText(L.LootMasterGiveDisenchant) btn2:SetPoint("LEFT", rp.content, "LEFT", _widthRank + _widthRankBar + (3 * _widthColPadding), 0) else btn2:SetWidth(85) btn2:SetText(L.LootMasterGiveLoot) btn2:SetPoint("RIGHT", rp.content, "RIGHT", -30, 0) end btn2:SetUserData("index", j) btn2:SetCallback("OnClick", onGiveLootClick) rp:AddChild(btn2) end end end end end end else local lbl = AceGUI:Create("AmrUiLabel") lbl:SetFont(Amr.CreateFont("Italic", 16, Amr.Colors.TextTan)) lbl:SetWidth(800) lbl:SetText(L.LootEmpty) lbl:SetPoint("CENTER", _panelLoot.content, "CENTER") _panelLoot:AddChild(lbl) end end -- select a particular loot item to display function Amr:SelectLootItem(index) _selectedIndex = index self:RefreshLootWindow() self:RefreshLootRolls() end local function onLootFrameClose(widget) AceGUI:Release(widget) _frameLoot = nil _panelLoot = nil _rankPanels = nil _lootButtons = nil end function Amr:HideLootWindow() if not _frameLoot then return end _frameLoot:Hide() end function Amr:ShowLootWindow() if not _frameLoot then _frameLoot = AceGUI:Create("AmrUiFrame") _frameLoot:SetStatusTable(Amr.db.profile.lootWindow) -- window position is remembered in db _frameLoot:SetCallback("OnClose", onLootFrameClose) _frameLoot:SetLayout("None") _frameLoot:SetWidth(900) _frameLoot:SetHeight(600) _frameLoot:SetBorderColor(Amr.Colors.BorderBlue) _frameLoot:SetBackgroundColor(Amr.Colors.Bg) if Amr.db.profile.options.uiScale ~= 1 then local scale = tonumber(Amr.db.profile.options.uiScale) _frameLoot:SetScale(scale) end local lbl = AceGUI:Create("AmrUiLabel") lbl:SetWidth(600) lbl:SetFont(Amr.CreateFont("Bold", 28, Amr.Colors.White)) lbl:SetText(L.LootTitle) lbl:SetWordWrap(false) lbl:SetJustifyH("CENTER") lbl:SetPoint("TOP", _frameLoot.content, "TOP", 0, 30) _frameLoot:AddChild(lbl) lbl:SetCallback("OnMouseDown", function(widget) _frameLoot:StartMove() end) lbl:SetCallback("OnMouseUp", function(widget) _frameLoot:EndMove() end) lbl = AceGUI:Create("AmrUiLabel") lbl:SetWidth(_widthItemList) lbl:SetFont(Amr.CreateFont("Regular", 18, Amr.Colors.TextHeaderActive)) lbl:SetText(L.LootHelpItems) lbl:SetPoint("TOPLEFT", _frameLoot.content, "TOPLEFT", 0, -10) _frameLoot:AddChild(lbl) lbl = AceGUI:Create("AmrUiLabel") lbl:SetWidth(_widthItemList) lbl:SetFont(Amr.CreateFont("Regular", 18, Amr.Colors.TextHeaderActive)) lbl:SetText(L.LootHelpRanks) lbl:SetPoint("TOPLEFT", _frameLoot.content, "TOPLEFT", _widthItemList + _widthSpacing, -10) _frameLoot:AddChild(lbl) if IsMasterLooter() then lbl = AceGUI:Create("AmrUiLabel") lbl:SetWidth(_widthItemList) lbl:SetFont(Amr.CreateFont("Regular", 18, Amr.Colors.TextHeaderActive)) lbl:SetText(L.LootHelpMaster) lbl:SetPoint("TOPLEFT", _frameLoot.content, "TOPLEFT", _widthItemList + _widthSpacing + _widthRank + _widthRankBar + _widthRollType + (_widthColPadding * 3), -10) _frameLoot:AddChild(lbl) end _panelLoot = AceGUI:Create("AmrUiPanel") _panelLoot:SetLayout("None") _panelLoot:SetBackgroundColor(Amr.Colors.Black, 0) _panelLoot:SetPoint("TOPLEFT", _frameLoot.content, "TOPLEFT", 0, -40) _panelLoot:SetPoint("BOTTOMRIGHT", _frameLoot.content, "BOTTOMRIGHT", 0, 0) _frameLoot:AddChild(_panelLoot) else _frameLoot:Show() end _frameLoot:Raise() end function Amr:OnStartLootReceived(parts) local data = {} for i = 2, #parts do table.insert(data, parts[i]) end data = table.concat(data, "\n") -- reset rankings to the new data sent out by person in control local rankings = Amr:ParseRankingString(data) Amr.db.global.TeamOpt.Rankings = rankings -- reset disenchant state _disenchant = {} -- reset roll information when loot is started local rolls = {} for i = 1, #rankings do table.insert(rolls, {}) end Amr.db.char.TeamOpt.Rolls = rolls -- select first item by default _selectedIndex = #rankings > 0 and 1 or nil -- begin looting Amr.db.char.TeamOpt.LootInProgress = true Amr:RefreshTeamUi() Amr:ShowLootWindow() Amr:RefreshLootWindow() end