diff --git a/reference/AddOns/Blizzard_AchievementUI/Blizzard_AchievementUI.lua b/reference/AddOns/Blizzard_AchievementUI/Blizzard_AchievementUI.lua new file mode 100644 index 0000000..217687a --- /dev/null +++ b/reference/AddOns/Blizzard_AchievementUI/Blizzard_AchievementUI.lua @@ -0,0 +1,2889 @@ +UIPanelWindows["AchievementFrame"] = { area = "doublewide", pushable = 0, width = 840, xoffset = 80, whileDead = 1 }; + +ACHIEVEMENTUI_CATEGORIES = {}; + +ACHIEVEMENTUI_GOLDBORDER_R = 1; +ACHIEVEMENTUI_GOLDBORDER_G = 0.675; +ACHIEVEMENTUI_GOLDBORDER_B = 0.125; +ACHIEVEMENTUI_GOLDBORDER_A = 1; + +ACHIEVEMENTUI_REDBORDER_R = 0.7; +ACHIEVEMENTUI_REDBORDER_G = 0.15; +ACHIEVEMENTUI_REDBORDER_B = 0.05; +ACHIEVEMENTUI_REDBORDER_A = 1; + +ACHIEVEMENTUI_CATEGORIESWIDTH = 175; + +ACHIEVEMENTUI_PROGRESSIVEHEIGHT = 50; +ACHIEVEMENTUI_PROGRESSIVEWIDTH = 42; + +ACHIEVEMENTUI_MAX_SUMMARY_ACHIEVEMENTS = 4; + +ACHIEVEMENTUI_MAXCONTENTWIDTH = 330; +local ACHIEVEMENTUI_FONTHEIGHT; -- set in AchievementButton_OnLoad +local ACHIEVEMENTUI_MAX_LINES_COLLAPSED = 3; -- can show 3 lines of text when achievement is collapsed + +ACHIEVEMENTUI_DEFAULTSUMMARYACHIEVEMENTS = {6, 503, 116, 545, 1017}; + +ACHIEVEMENT_CATEGORY_NORMAL_R = 0; +ACHIEVEMENT_CATEGORY_NORMAL_G = 0; +ACHIEVEMENT_CATEGORY_NORMAL_B = 0; +ACHIEVEMENT_CATEGORY_NORMAL_A = .9; + +ACHIEVEMENT_CATEGORY_HIGHLIGHT_R = 0; +ACHIEVEMENT_CATEGORY_HIGHLIGHT_G = .6; +ACHIEVEMENT_CATEGORY_HIGHLIGHT_B = 0; +ACHIEVEMENT_CATEGORY_HIGHLIGHT_A = .65; + +ACHIEVEMENTBUTTON_LABELWIDTH = 320; + +ACHIEVEMENT_COMPARISON_SUMMARY_ID = -1 +ACHIEVEMENT_COMPARISON_STATS_SUMMARY_ID = -2 + +ACHIEVEMENT_FILTER_ALL = 1; +ACHIEVEMENT_FILTER_COMPLETE = 2; +ACHIEVEMENT_FILTER_INCOMPLETE = 3; + +local FEAT_OF_STRENGTH_ID = 81; + +local trackedAchievements = {}; +local function updateTrackedAchievements (...) + local count = select("#", ...); + + for i = 1, count do + trackedAchievements[select(i, ...)] = true; + end +end + + +-- [[ AchievementFrame ]] -- + +function AchievementFrame_ToggleAchievementFrame(toggleStatFrame) + AchievementFrameComparison:Hide(); + AchievementFrameTab_OnClick = AchievementFrameBaseTab_OnClick; + if ( not toggleStatFrame ) then + if ( AchievementFrame:IsShown() and AchievementFrame.selectedTab == 1 ) then + HideUIPanel(AchievementFrame); + else + ShowUIPanel(AchievementFrame); + AchievementFrameTab_OnClick(1); + end + return; + end + if ( AchievementFrame:IsShown() and AchievementFrame.selectedTab == 2 ) then + HideUIPanel(AchievementFrame); + else + ShowUIPanel(AchievementFrame); + AchievementFrameTab_OnClick(2); + end +end + +function AchievementFrame_DisplayComparison (unit) + AchievementFrame.wasShown = nil; + AchievementFrameTab_OnClick = AchievementFrameComparisonTab_OnClick; + AchievementFrameTab_OnClick(1); + ShowUIPanel(AchievementFrame); + --AchievementFrame_ShowSubFrame(AchievementFrameComparison, AchievementFrameSummary); + AchievementFrameComparison_SetUnit(unit); + AchievementFrameComparison_ForceUpdate(); +end + +function AchievementFrame_OnLoad (self) + PanelTemplates_SetNumTabs(self, 2); + self.selectedTab = 1; + PanelTemplates_UpdateTabs(self); +end + +function AchievementFrame_OnShow (self) + PlaySound("AchievementMenuOpen"); + AchievementFrameHeaderPoints:SetText(GetTotalAchievementPoints()); + if ( not AchievementFrame.wasShown ) then + AchievementFrame.wasShown = true; + AchievementCategoryButton_OnClick(AchievementFrameCategoriesContainerButton1); + end + UpdateMicroButtons(); + AchievementFrame_LoadTextures(); +end + +function AchievementFrame_OnHide (self) + PlaySound("AchievementMenuClose"); + UpdateMicroButtons(); + AchievementFrame_ClearTextures(); +end + +function AchievementFrame_ForceUpdate () + if ( AchievementFrameAchievements:IsShown() ) then + AchievementFrameAchievements_ForceUpdate(); + elseif ( AchievementFrameStats:IsShown() ) then + AchievementFrameStats_Update(); + elseif ( AchievementFrameComparison:IsShown() ) then + AchievementFrameComparison_ForceUpdate(); + end +end + +function AchievementFrameBaseTab_OnClick (id) + PanelTemplates_Tab_OnClick(_G["AchievementFrameTab"..id], AchievementFrame); + + local isSummary = false + if ( id == 1 ) then + achievementFunctions = ACHIEVEMENT_FUNCTIONS; + AchievementFrameCategories_GetCategoryList(ACHIEVEMENTUI_CATEGORIES); -- This needs to happen before AchievementFrame_ShowSubFrame (fix for bug 157885) + if ( achievementFunctions.selectedCategory == "summary" ) then + isSummary = true; + AchievementFrame_ShowSubFrame(AchievementFrameSummary); + else + AchievementFrame_ShowSubFrame(AchievementFrameAchievements); + end + AchievementFrameWaterMark:SetTexture("Interface\\AchievementFrame\\UI-Achievement-AchievementWatermark"); + else + achievementFunctions = STAT_FUNCTIONS; + AchievementFrameCategories_GetCategoryList(ACHIEVEMENTUI_CATEGORIES); + if ( achievementFunctions.selectedCategory == "summary" ) then + AchievementFrame_ShowSubFrame(AchievementFrameStats); + achievementFunctions.selectedCategory = ACHIEVEMENT_COMPARISON_STATS_SUMMARY_ID; + AchievementFrameStatsContainerScrollBar:SetValue(0); + else + AchievementFrame_ShowSubFrame(AchievementFrameStats); + end + AchievementFrameWaterMark:SetTexture("Interface\\AchievementFrame\\UI-Achievement-StatWatermark"); + end + + AchievementFrameCategories_Update(); + + if ( not isSummary ) then + achievementFunctions.updateFunc(); + end +end + +AchievementFrameTab_OnClick = AchievementFrameBaseTab_OnClick; + +function AchievementFrameComparisonTab_OnClick (id) + if ( id == 1 ) then + achievementFunctions = COMPARISON_ACHIEVEMENT_FUNCTIONS; + AchievementFrame_ShowSubFrame(AchievementFrameComparison, AchievementFrameComparisonContainer); + AchievementFrameWaterMark:SetTexture("Interface\\AchievementFrame\\UI-Achievement-AchievementWatermark"); + else + achievementFunctions = COMPARISON_STAT_FUNCTIONS; + AchievementFrame_ShowSubFrame(AchievementFrameComparison, AchievementFrameComparisonStatsContainer); + AchievementFrameWaterMark:SetTexture("Interface\\AchievementFrame\\UI-Achievement-StatWatermark"); + end + + AchievementFrameCategories_GetCategoryList(ACHIEVEMENTUI_CATEGORIES); + AchievementFrameCategories_Update(); + PanelTemplates_Tab_OnClick(_G["AchievementFrameTab"..id], AchievementFrame); + + achievementFunctions.updateFunc(); +end + +ACHIEVEMENTFRAME_SUBFRAMES = { + "AchievementFrameSummary", + "AchievementFrameAchievements", + "AchievementFrameStats", + "AchievementFrameComparison", + "AchievementFrameComparisonContainer", + "AchievementFrameComparisonStatsContainer" +}; + +function AchievementFrame_ShowSubFrame(...) + local subFrame, show; + for _, name in next, ACHIEVEMENTFRAME_SUBFRAMES do + subFrame = _G[name]; + show = false; + for i=1, select("#", ...) do + if ( subFrame == select(i, ...)) then + show = true + end + end + if ( show ) then + subFrame:Show(); + else + subFrame:Hide(); + end + end +end + +-- [[ AchievementFrameCategories ]] -- + +function AchievementFrameCategories_OnLoad (self) + self:SetBackdropBorderColor(ACHIEVEMENTUI_GOLDBORDER_R, ACHIEVEMENTUI_GOLDBORDER_G, ACHIEVEMENTUI_GOLDBORDER_B, ACHIEVEMENTUI_GOLDBORDER_A); + self.buttons = {}; + self:RegisterEvent("ADDON_LOADED"); + self:SetScript("OnEvent", AchievementFrameCategories_OnEvent); +end + +function AchievementFrameCategories_OnEvent (self, event, ...) + if ( event == "ADDON_LOADED" ) then + local addonName = ...; + if ( addonName and addonName ~= "Blizzard_AchievementUI" ) then + return; + end + + AchievementFrameCategories_GetCategoryList(ACHIEVEMENTUI_CATEGORIES); + + AchievementFrameCategoriesContainerScrollBar.Show = + function (self) + ACHIEVEMENTUI_CATEGORIESWIDTH = 175; + AchievementFrameCategories:SetWidth(175); + AchievementFrameCategoriesContainer:GetScrollChild():SetWidth(175); + AchievementFrameAchievements:SetPoint("TOPLEFT", "$parentCategories", "TOPRIGHT", 22, 0); + AchievementFrameStats:SetPoint("TOPLEFT", "$parentCategories", "TOPRIGHT", 22, 0); + AchievementFrameComparison:SetPoint("TOPLEFT", "$parentCategories", "TOPRIGHT", 22, 0) + AchievementFrameWaterMark:SetWidth(145); + AchievementFrameWaterMark:SetTexCoord(0, 145/256, 0, 1); + for _, button in next, AchievementFrameCategoriesContainer.buttons do + AchievementFrameCategories_DisplayButton(button, button.element) + end + getmetatable(self).__index.Show(self); + end + + AchievementFrameCategoriesContainerScrollBar.Hide = + function (self) + ACHIEVEMENTUI_CATEGORIESWIDTH = 197; + AchievementFrameCategories:SetWidth(197); + AchievementFrameCategoriesContainer:GetScrollChild():SetWidth(197); + AchievementFrameAchievements:SetPoint("TOPLEFT", "$parentCategories", "TOPRIGHT", 0, 0); + AchievementFrameStats:SetPoint("TOPLEFT", "$parentCategories", "TOPRIGHT", 0, 0); + AchievementFrameComparison:SetPoint("TOPLEFT", "$parentCategories", "TOPRIGHT", 0, 0) + AchievementFrameWaterMark:SetWidth(167); + AchievementFrameWaterMark:SetTexCoord(0, 167/256, 0, 1); + for _, button in next, AchievementFrameCategoriesContainer.buttons do + AchievementFrameCategories_DisplayButton(button, button.element); + end + getmetatable(self).__index.Hide(self); + end + + AchievementFrameCategoriesContainerScrollBarBG:Show(); + AchievementFrameCategoriesContainer.update = AchievementFrameCategories_Update; + HybridScrollFrame_CreateButtons(AchievementFrameCategoriesContainer, "AchievementCategoryTemplate", 0, 0, "TOP", "TOP", 0, 0, "TOP", "BOTTOM"); + AchievementFrameCategories_Update(); + self:UnregisterEvent(event) + end +end + +function AchievementFrameCategories_OnShow (self) + AchievementFrameCategories_Update(); +end + +function AchievementFrameCategories_GetCategoryList (categories) + local cats = achievementFunctions.categoryAccessor(); + + for i in next, categories do + categories[i] = nil; + end + -- Insert the fake Summary category + tinsert(categories, { ["id"] = "summary" }); + + for i, id in next, cats do + local _, parent = GetCategoryInfo(id); + if ( parent == -1 ) then + tinsert(categories, { ["id"] = id }); + end + end + + local _, parent; + for i = #cats, 1, -1 do + _, parent = GetCategoryInfo(cats[i]); + for j, category in next, categories do + if ( category.id == parent ) then + category.parent = true; + category.collapsed = true; + tinsert(categories, j+1, { ["id"] = cats[i], ["parent"] = category.id, ["hidden"] = true}); + end + end + end +end + +local displayCategories = {}; +function AchievementFrameCategories_Update () + local scrollFrame = AchievementFrameCategoriesContainer + + local categories = ACHIEVEMENTUI_CATEGORIES; + local offset = HybridScrollFrame_GetOffset(scrollFrame); + local buttons = scrollFrame.buttons; + + local displayCategories = displayCategories; + + for i in next, displayCategories do + displayCategories[i] = nil; + end + + local selection = achievementFunctions.selectedCategory; + if ( selection == ACHIEVEMENT_COMPARISON_SUMMARY_ID or selection == ACHIEVEMENT_COMPARISON_STATS_SUMMARY_ID ) then + selection = "summary"; + end + + local parent; + if ( selection ) then + for i, category in next, categories do + if ( category.id == selection ) then + parent = category.parent; + end + end + end + + for i, category in next, categories do + if ( not category.hidden ) then + tinsert(displayCategories, category); + elseif ( parent and category.id == parent ) then + category.collapsed = false; + tinsert(displayCategories, category); + elseif ( parent and category.parent and category.parent == parent ) then + category.hidden = false; + tinsert(displayCategories, category); + end + end + + local numCategories = #displayCategories; + local numButtons = #buttons; + + local totalHeight = numCategories * buttons[1]:GetHeight(); + local displayedHeight = 0; + + local element + for i = 1, numButtons do + element = displayCategories[i + offset]; + displayedHeight = displayedHeight + buttons[i]:GetHeight(); + if ( element ) then + AchievementFrameCategories_DisplayButton(buttons[i], element); + if ( selection and element.id == selection ) then + buttons[i]:LockHighlight(); + else + buttons[i]:UnlockHighlight(); + end + buttons[i]:Show(); + else + buttons[i].element = nil; + buttons[i]:Hide(); + end + end + + HybridScrollFrame_Update(scrollFrame, totalHeight, displayedHeight); + + return displayCategories; +end + +function AchievementFrameCategories_DisplayButton (button, element) + if ( not element ) then + button.element = nil; + button:Hide(); + return; + end + + button:Show(); + if ( type(element.parent) == "number" ) then + button:SetWidth(ACHIEVEMENTUI_CATEGORIESWIDTH - 25); + button.label:SetFontObject("GameFontHighlight"); + button.parentID = element.parent; + button.background:SetVertexColor(0.6, 0.6, 0.6); + else + button:SetWidth(ACHIEVEMENTUI_CATEGORIESWIDTH - 10); + button.label:SetFontObject("GameFontNormal"); + button.parentID = element.parent; + button.background:SetVertexColor(1, 1, 1); + end + + local categoryName, parentID, flags; + local numAchievements, numCompleted; + + local id = element.id; + + -- kind of janky + if ( id == "summary" ) then + categoryName = ACHIEVEMENT_SUMMARY_CATEGORY; + numAchievements, numCompleted = GetNumCompletedAchievements(); + else + categoryName, parentID, flags = GetCategoryInfo(id); + numAchievements, numCompleted = AchievementFrame_GetCategoryTotalNumAchievements(id, true); + end + button.label:SetText(categoryName); + button.categoryID = id; + button.flags = flags; + button.element = element; + + -- For the tooltip + button.name = categoryName; + if ( id == FEAT_OF_STRENGTH_ID ) then + -- This is the feat of strength category since it's sorted to the end of the list + button.text = FEAT_OF_STRENGTH_DESCRIPTION; + button.showTooltipFunc = AchievementFrameCategory_FeatOfStrengthTooltip; + elseif ( AchievementFrame.selectedTab == 1 ) then + button.text = nil; + button.numAchievements = numAchievements; + button.numCompleted = numCompleted; + button.numCompletedText = numCompleted.."/"..numAchievements; + button.showTooltipFunc = AchievementFrameCategory_StatusBarTooltip; + else + button.showTooltipFunc = nil; + end +end + +function AchievementFrameCategory_StatusBarTooltip(self) + GameTooltip_SetDefaultAnchor(GameTooltip, self); + GameTooltip:SetMinimumWidth(128, 1); + GameTooltip:SetText(self.name, 1, 1, 1, nil, 1); + GameTooltip_ShowStatusBar(GameTooltip, 0, self.numAchievements, self.numCompleted, self.numCompletedText); + GameTooltip:Show(); +end + +function AchievementFrameCategory_FeatOfStrengthTooltip(self) + GameTooltip_SetDefaultAnchor(GameTooltip, self); + GameTooltip:SetText(self.name, 1, 1, 1); + GameTooltip:AddLine(self.text, nil, nil, nil, 1); + GameTooltip:Show(); +end + +function AchievementFrameCategories_UpdateTooltip() + local container = AchievementFrameCategoriesContainer; + if ( not container:IsVisible() or not container.buttons ) then + return; + end + + for _, button in next, AchievementFrameCategoriesContainer.buttons do + if ( button:IsMouseOver() and button.showTooltipFunc ) then + button:showTooltipFunc(); + break; + end + end +end + +function AchievementFrameCategories_SelectButton (button) + local id = button.element.id; + + if ( type(button.element.parent) ~= "number" ) then + -- Is top level category (can expand/contract) + if ( button.isSelected and button.element.collapsed == false ) then + button.element.collapsed = true; + for i, category in next, ACHIEVEMENTUI_CATEGORIES do + if ( category.parent == id ) then + category.hidden = true; + end + end + else + for i, category in next, ACHIEVEMENTUI_CATEGORIES do + if ( category.parent == id ) then + category.hidden = false; + elseif ( category.parent == true ) then + category.collapsed = true; + elseif ( category.parent ) then + category.hidden = true; + end + end + button.element.collapsed = false; + end + end + + local buttons = AchievementFrameCategoriesContainer.buttons; + for _, button in next, buttons do + button.isSelected = nil; + end + + button.isSelected = true; + + if ( id == achievementFunctions.selectedCategory ) then + -- If this category was selected already, bail after changing collapsed states + return + end + + --Intercept "summary" category + if ( id == "summary" ) then + if ( achievementFunctions == ACHIEVEMENT_FUNCTIONS ) then + AchievementFrame_ShowSubFrame(AchievementFrameSummary); + achievementFunctions.selectedCategory = id; + return; + elseif ( achievementFunctions == STAT_FUNCTIONS ) then + AchievementFrame_ShowSubFrame(AchievementFrameStats); + achievementFunctions.selectedCategory = ACHIEVEMENT_COMPARISON_STATS_SUMMARY_ID; + AchievementFrameStatsContainerScrollBar:SetValue(0); + elseif ( achievementFunctions == COMPARISON_ACHIEVEMENT_FUNCTIONS ) then + -- Put the summary stuff for comparison here, Derek! + AchievementFrame_ShowSubFrame(AchievementFrameComparison, AchievementFrameComparisonContainer); + achievementFunctions.selectedCategory = ACHIEVEMENT_COMPARISON_SUMMARY_ID; + AchievementFrameComparisonContainerScrollBar:SetValue(0); + AchievementFrameComparison_UpdateStatusBars(ACHIEVEMENT_COMPARISON_SUMMARY_ID); + elseif ( achievementFunctions == COMPARISON_STAT_FUNCTIONS ) then + AchievementFrame_ShowSubFrame(AchievementFrameComparison, AchievementFrameComparisonStatsContainer); + achievementFunctions.selectedCategory = ACHIEVEMENT_COMPARISON_STATS_SUMMARY_ID; + AchievementFrameComparisonStatsContainerScrollBar:SetValue(0); + end + + else + if ( achievementFunctions == STAT_FUNCTIONS ) then + AchievementFrame_ShowSubFrame(AchievementFrameStats); + AchievementFrameStatsContainerScrollBar:SetValue(0); + elseif ( achievementFunctions == ACHIEVEMENT_FUNCTIONS ) then + AchievementFrame_ShowSubFrame(AchievementFrameAchievements); + AchievementFrameAchievementsContainerScrollBar:SetValue(0); + if ( id == FEAT_OF_STRENGTH_ID ) then + AchievementFrameFilterDropDown:Hide(); + AchievementFrameHeaderRightDDLInset:Hide(); + else + AchievementFrameFilterDropDown:Show(); + AchievementFrameHeaderRightDDLInset:Show(); + end + elseif ( achievementFunctions == COMPARISON_ACHIEVEMENT_FUNCTIONS ) then + AchievementFrame_ShowSubFrame(AchievementFrameComparison, AchievementFrameComparisonContainer); + AchievementFrameComparisonContainerScrollBar:SetValue(0); + AchievementFrameComparison_UpdateStatusBars(id); + else + AchievementFrame_ShowSubFrame(AchievementFrameComparison, AchievementFrameComparisonStatsContainer); + AchievementFrameComparisonStatsContainerScrollBar:SetValue(0); + end + achievementFunctions.selectedCategory = id; + end + + if ( achievementFunctions.clearFunc ) then + achievementFunctions.clearFunc(); + end + + achievementFunctions.updateFunc(); +end + +function AchievementFrameAchievements_OnShow() + if ( achievementFunctions.selectedCategory == FEAT_OF_STRENGTH_ID ) then + AchievementFrameFilterDropDown:Hide(); + AchievementFrameHeaderRightDDLInset:Hide(); + else + AchievementFrameFilterDropDown:Show(); + AchievementFrameHeaderRightDDLInset:Show(); + end +end + +function AchievementFrameCategories_ClearSelection () + local buttons = AchievementFrameCategoriesContainer.buttons; + for _, button in next, buttons do + button.isSelected = nil; + button:UnlockHighlight(); + end + + for i, category in next, ACHIEVEMENTUI_CATEGORIES do + if ( category.parent == true ) then + category.collapsed = true; + elseif ( category.parent ) then + category.hidden = true; + end + end +end + +function AchievementFrameComparison_UpdateStatusBars (id) + local numAchievements, numCompleted = GetCategoryNumAchievements(id); + local name = GetCategoryInfo(id); + + if ( id == ACHIEVEMENT_COMPARISON_SUMMARY_ID ) then + name = ACHIEVEMENT_SUMMARY_CATEGORY; + end + + local statusBar = AchievementFrameComparisonSummaryPlayerStatusBar; + statusBar:SetMinMaxValues(0, numAchievements); + statusBar:SetValue(numCompleted); + statusBar.title:SetText(string.format(ACHIEVEMENTS_COMPLETED_CATEGORY, name)); + statusBar.text:SetText(numCompleted.."/"..numAchievements); + + local friendCompleted = GetComparisonCategoryNumAchievements(id); + + statusBar = AchievementFrameComparisonSummaryFriendStatusBar; + statusBar:SetMinMaxValues(0, numAchievements); + statusBar:SetValue(friendCompleted); + statusBar.text:SetText(friendCompleted.."/"..numAchievements); +end + +-- [[ AchievementCategoryButton ]] -- + +function AchievementCategoryButton_OnLoad (button) + button:EnableMouse(true); + button:EnableMouseWheel(true); + + local buttonName = button:GetName(); + + button.label = _G[buttonName .. "Label"]; + button.background = _G[buttonName.."Background"]; +end + +function AchievementCategoryButton_OnClick (button) + AchievementFrameCategories_SelectButton(button); + AchievementFrameCategories_Update(); +end + +-- [[ AchievementFrameAchievements ]] -- + +function AchievementFrameAchievements_OnLoad (self) + AchievementFrameAchievementsContainerScrollBar.Show = + function (self) + AchievementFrameAchievements:SetWidth(504); + for _, button in next, AchievementFrameAchievements.buttons do + button:SetWidth(496); + end + getmetatable(self).__index.Show(self); + end + + AchievementFrameAchievementsContainerScrollBar.Hide = + function (self) + AchievementFrameAchievements:SetWidth(530); + for _, button in next, AchievementFrameAchievements.buttons do + button:SetWidth(522); + end + getmetatable(self).__index.Hide(self); + end + + self:RegisterEvent("ADDON_LOADED"); + AchievementFrameAchievementsContainerScrollBarBG:Show(); + AchievementFrameAchievementsContainer.update = AchievementFrameAchievements_Update; + HybridScrollFrame_CreateButtons(AchievementFrameAchievementsContainer, "AchievementTemplate", 0, -2); +end + +function AchievementFrameAchievements_OnEvent (self, event, ...) + if ( event == "ADDON_LOADED" ) then + self:RegisterEvent("ACHIEVEMENT_EARNED"); + self:RegisterEvent("CRITERIA_UPDATE"); + self:RegisterEvent("TRACKED_ACHIEVEMENT_UPDATE"); + + updateTrackedAchievements(GetTrackedAchievements()); + elseif ( event == "ACHIEVEMENT_EARNED" ) then + local achievementID = ...; + AchievementFrameCategories_Update(); + AchievementFrameCategories_UpdateTooltip(); + -- This has to happen before AchievementFrameAchievements_ForceUpdate() in order to achieve the behavior we want, since it clears the selection for progressive achievements. + local selection = AchievementFrameAchievements.selection; + AchievementFrameAchievements_ForceUpdate(); + if ( AchievementFrameAchievementsContainer:IsShown() and selection == achievementID ) then + AchievementFrame_SelectAchievement(selection, true); + end + AchievementFrameHeaderPoints:SetText(GetTotalAchievementPoints()); + + elseif ( event == "CRITERIA_UPDATE" ) then + if ( AchievementFrameAchievements.selection ) then + local id = AchievementFrameAchievementsObjectives.id; + local button = AchievementFrameAchievementsObjectives:GetParent(); + AchievementFrameAchievementsObjectives.id = nil; + AchievementButton_DisplayObjectives(button, id, button.completed); + AchievementFrameAchievements_Update(); + else + AchievementFrameAchievementsObjectives.id = nil; -- Force redraw + end + elseif ( event == "TRACKED_ACHIEVEMENT_UPDATE" ) then + for k, v in next, trackedAchievements do + trackedAchievements[k] = nil; + end + + updateTrackedAchievements(GetTrackedAchievements()); + end + + if ( not AchievementMicroButton:IsShown() ) then + AchievementMicroButton_Update(); + end +end + +function AchievementFrameAchievementsBackdrop_OnLoad (self) + self:SetBackdropBorderColor(ACHIEVEMENTUI_GOLDBORDER_R, ACHIEVEMENTUI_GOLDBORDER_G, ACHIEVEMENTUI_GOLDBORDER_B, ACHIEVEMENTUI_GOLDBORDER_A); + self:SetFrameLevel(self:GetFrameLevel()+1); +end + +function AchievementFrameAchievements_Update () + local category = achievementFunctions.selectedCategory; + if ( category == "summary" ) then + return; + end + local scrollFrame = AchievementFrameAchievementsContainer + + local offset = HybridScrollFrame_GetOffset(scrollFrame); + local buttons = scrollFrame.buttons; + local numAchievements, numCompleted, completedOffset = ACHIEVEMENTUI_SELECTEDFILTER(category); + local numButtons = #buttons; + + -- If the current category is feats of strength and there are no entries then show the explanation text + if ( AchievementFrame_IsFeatOfStrength() and numAchievements == 0 ) then + AchievementFrameAchievementsFeatOfStrengthText:Show(); + else + AchievementFrameAchievementsFeatOfStrengthText:Hide(); + end + + local selection = AchievementFrameAchievements.selection; + if ( selection ) then + AchievementButton_ResetObjectives(); + end + + local extraHeight = scrollFrame.largeButtonHeight or ACHIEVEMENTBUTTON_COLLAPSEDHEIGHT + + local achievementIndex; + local displayedHeight = 0; + for i = 1, numButtons do + achievementIndex = i + offset + completedOffset; + if ( achievementIndex > numAchievements + completedOffset ) then + buttons[i]:Hide(); + else + AchievementButton_DisplayAchievement(buttons[i], category, achievementIndex, selection); + displayedHeight = displayedHeight + buttons[i]:GetHeight(); + end + end + + local totalHeight = numAchievements * ACHIEVEMENTBUTTON_COLLAPSEDHEIGHT; + totalHeight = totalHeight + (extraHeight - ACHIEVEMENTBUTTON_COLLAPSEDHEIGHT); + + HybridScrollFrame_Update(scrollFrame, totalHeight, displayedHeight); + + if ( selection ) then + AchievementFrameAchievements.selection = selection; + else + HybridScrollFrame_CollapseButton(scrollFrame); + end +end + +function AchievementFrameAchievements_ForceUpdate () + if ( AchievementFrameAchievements.selection ) then + local nextID = GetNextAchievement(AchievementFrameAchievements.selection); + local id, _, _, completed = GetAchievementInfo(AchievementFrameAchievements.selection); + if ( nextID and completed ) then + AchievementFrameAchievements.selection = nil; + end + end + AchievementFrameAchievementsObjectives:Hide(); + AchievementFrameAchievementsObjectives.id = nil; + + local buttons = AchievementFrameAchievementsContainer.buttons; + for i, button in next, buttons do + button.id = nil; + end + + AchievementFrameAchievements_Update(); +end + +function AchievementFrameAchievements_ClearSelection () + AchievementButton_ResetObjectives(); + for _, button in next, AchievementFrameAchievements.buttons do + button:Collapse(); + if ( not button:IsMouseOver() ) then + button.highlight:Hide(); + end + button.selected = nil; + if ( not button.tracked:GetChecked() ) then + button.tracked:Hide(); + end + button.description:Show(); + button.hiddenDescription:Hide(); + end + + AchievementFrameAchievements.selection = nil; +end + +-- [[ Achievement Icon ]] -- + +function AchievementIcon_Desaturate (self) + self.bling:SetVertexColor(.6, .6, .6, 1); + self.frame:SetVertexColor(.75, .75, .75, 1); + self.texture:SetVertexColor(.55, .55, .55, 1); +end + +function AchievementIcon_Saturate (self) + self.bling:SetVertexColor(1, 1, 1, 1); + self.frame:SetVertexColor(1, 1, 1, 1); + self.texture:SetVertexColor(1, 1, 1, 1); +end + +function AchievementIcon_OnLoad (self) + local name = self:GetName(); + self.bling = _G[name .. "Bling"]; + self.texture = _G[name .. "Texture"]; + self.frame = _G[name .. "Overlay"]; + + self.Desaturate = AchievementIcon_Desaturate; + self.Saturate = AchievementIcon_Saturate; +end + +-- [[ Achievement Shield ]] -- + +function AchievementShield_Desaturate (self) + self.icon:SetTexCoord(.5, 1, 0, 1); +end + +function AchievementShield_Saturate (self) + self.icon:SetTexCoord(0, .5, 0, 1); +end + +function AchievementShield_OnLoad (self) + local name = self:GetName(); + self.icon = _G[name .. "Icon"]; + self.points = _G[name .. "Points"]; + + self.Desaturate = AchievementShield_Desaturate; + self.Saturate = AchievementShield_Saturate; +end + +-- [[ AchievementButton ]] -- + +ACHIEVEMENTBUTTON_DESCRIPTIONHEIGHT = 20; +ACHIEVEMENTBUTTON_COLLAPSEDHEIGHT = 84; +ACHIEVEMENTBUTTON_CRITERIAROWHEIGHT = 15; +ACHIEVEMENTBUTTON_METAROWHEIGHT = 14; +ACHIEVEMENTBUTTON_MAXHEIGHT = 232; +ACHIEVEMENTBUTTON_TEXTUREHEIGHT = 128; + +function AchievementButton_UpdatePlusMinusTexture (button) + local id = button.id; + if ( not id ) then + return; -- This happens when we create buttons + end + + local display = false; + if ( GetAchievementNumCriteria(id) ~= 0 ) then + display = true; + elseif ( GetPreviousAchievement(id) and button.completed ) then + display = true; + end + + if ( display ) then + button.plusMinus:Show(); + if ( button.collapsed and button.saturated ) then + button.plusMinus:SetTexCoord(0, .5, 0, .5); + elseif ( button.collapsed ) then + button.plusMinus:SetTexCoord(.5, 1, 0, .5); + elseif ( button.saturated ) then + button.plusMinus:SetTexCoord(0, .5, .5, 1); + else + button.plusMinus:SetTexCoord(.5, 1, .5, 1); + end + else + button.plusMinus:Hide(); + end +end + +function AchievementButton_Collapse (self) + if ( self.collapsed ) then + return; + end + + self.collapsed = true; + AchievementButton_UpdatePlusMinusTexture(self); + self:SetHeight(ACHIEVEMENTBUTTON_COLLAPSEDHEIGHT); + _G[self:GetName() .. "Background"]:SetTexCoord(0, 1, 1-(ACHIEVEMENTBUTTON_COLLAPSEDHEIGHT / 256), 1); + _G[self:GetName() .. "Glow"]:SetTexCoord(0, 1, 0, ACHIEVEMENTBUTTON_COLLAPSEDHEIGHT / 128); + + if ( not self.tracked:GetChecked() ) then + self.tracked:Hide(); + end +end + +function AchievementButton_Expand (self, height) + if ( not self.collapsed ) then + return; + end + + self.collapsed = nil; + AchievementButton_UpdatePlusMinusTexture(self); + self:SetHeight(height); + _G[self:GetName() .. "Background"]:SetTexCoord(0, 1, max(0, 1-(height / 256)), 1); + _G[self:GetName() .. "Glow"]:SetTexCoord(0, 1, 0, (height+5) / 128); +end + +function AchievementButton_Saturate (self) + local name = self:GetName(); + self.saturated = true; + _G[name .. "TitleBackground"]:SetTexCoord(0, 0.9765625, 0, 0.3125); + _G[name .. "Background"]:SetTexture("Interface\\AchievementFrame\\UI-Achievement-Parchment-Horizontal"); + _G[name .. "Glow"]:SetVertexColor(1.0, 1.0, 1.0); + self.icon:Saturate(); + self.shield:Saturate(); + self.shield.points:SetVertexColor(1, 1, 1); + self.reward:SetVertexColor(1, .82, 0); + self.label:SetVertexColor(1, 1, 1); + self.description:SetTextColor(0, 0, 0, 1); + self.description:SetShadowOffset(0, 0); + AchievementButton_UpdatePlusMinusTexture(self); + self:SetBackdropBorderColor(ACHIEVEMENTUI_REDBORDER_R, ACHIEVEMENTUI_REDBORDER_G, ACHIEVEMENTUI_REDBORDER_B, ACHIEVEMENTUI_REDBORDER_A); +end + +function AchievementButton_Desaturate (self) + local name = self:GetName(); + self.saturated = nil; + _G[name .. "TitleBackground"]:SetTexCoord(0, 0.9765625, 0.34375, 0.65625); + _G[name .. "Background"]:SetTexture("Interface\\AchievementFrame\\UI-Achievement-Parchment-Horizontal-Desaturated"); + _G[name .. "Glow"]:SetVertexColor(.22, .17, .13); + self.icon:Desaturate(); + self.shield:Desaturate(); + self.shield.points:SetVertexColor(.65, .65, .65); + self.reward:SetVertexColor(.8, .8, .8); + self.label:SetVertexColor(.65, .65, .65); + self.description:SetTextColor(1, 1, 1, 1); + self.description:SetShadowOffset(1, -1); + AchievementButton_UpdatePlusMinusTexture(self); + self:SetBackdropBorderColor(.5, .5, .5); +end + +function AchievementButton_OnLoad (self) + local name = self:GetName(); + self.label = _G[name .. "Label"]; + self.description = _G[name .. "Description"]; + self.hiddenDescription = _G[name .. "HiddenDescription"]; + self.reward = _G[name .. "Reward"]; + self.rewardBackground = _G[name.."RewardBackground"]; + self.icon = _G[name .. "Icon"]; + self.shield = _G[name .. "Shield"]; + self.objectives = _G[name .. "Objectives"]; + self.highlight = _G[name .. "Highlight"]; + self.dateCompleted = _G[name .. "DateCompleted"] + self.tracked = _G[name .. "Tracked"]; + self.check = _G[name .. "Check"]; + self.plusMinus = _G[name .. "PlusMinus"]; + + self.dateCompleted:ClearAllPoints(); + self.dateCompleted:SetPoint("TOP", self.shield, "BOTTOM", -3, 6); + if ( not ACHIEVEMENTUI_FONTHEIGHT ) then + local _, fontHeight = self.description:GetFont(); + ACHIEVEMENTUI_FONTHEIGHT = fontHeight; + end + self.description:SetHeight(ACHIEVEMENTUI_FONTHEIGHT * ACHIEVEMENTUI_MAX_LINES_COLLAPSED); + self.description:SetWidth(ACHIEVEMENTUI_MAXCONTENTWIDTH); + self.hiddenDescription:SetWidth(ACHIEVEMENTUI_MAXCONTENTWIDTH); + + self:SetBackdropBorderColor(ACHIEVEMENTUI_REDBORDER_R, ACHIEVEMENTUI_REDBORDER_G, ACHIEVEMENTUI_REDBORDER_B, ACHIEVEMENTUI_REDBORDER_A); + self.Collapse = AchievementButton_Collapse; + self.Expand = AchievementButton_Expand; + self.Saturate = AchievementButton_Saturate; + self.Desaturate = AchievementButton_Desaturate; + + self:Collapse(); + self:Desaturate(); + + AchievementFrameAchievements.buttons = AchievementFrameAchievements.buttons or {}; + tinsert(AchievementFrameAchievements.buttons, self); +end + +function AchievementButton_OnClick (self, ignoreModifiers) + if(IsModifiedClick() and not ignoreModifiers) then + if ( IsModifiedClick("CHATLINK") and ChatEdit_GetActiveWindow() ) then + local achievementLink = GetAchievementLink(self.id); + if ( achievementLink ) then + ChatEdit_InsertLink(achievementLink); + end + elseif ( IsModifiedClick("QUESTWATCHTOGGLE") ) then + AchievementButton_ToggleTracking(self.id); + end + + return; + end + + if ( self.selected ) then + if ( not self:IsMouseOver() ) then + self.highlight:Hide(); + end + AchievementFrameAchievements_ClearSelection() + HybridScrollFrame_CollapseButton(AchievementFrameAchievementsContainer); + AchievementFrameAchievements_Update(); + return; + end + AchievementFrameAchievements_ClearSelection() + AchievementFrameAchievements_SelectButton(self); + AchievementButton_DisplayAchievement(self, achievementFunctions.selectedCategory, self.index, self.id); + HybridScrollFrame_ExpandButton(AchievementFrameAchievementsContainer, ((self.index - 1) * ACHIEVEMENTBUTTON_COLLAPSEDHEIGHT), self:GetHeight()); + AchievementFrameAchievements_Update(); + if ( not ignoreModifiers ) then + AchievementFrameAchievements_AdjustSelection(); + end +end + +function AchievementButton_ToggleTracking (id) + if ( trackedAchievements[id] ) then + RemoveTrackedAchievement(id); + AchievementFrameAchievements_ForceUpdate(); + WatchFrame_Update(); + return; + end + + local count = GetNumTrackedAchievements(); + + if ( count >= WATCHFRAME_MAXACHIEVEMENTS ) then + UIErrorsFrame:AddMessage(format(ACHIEVEMENT_WATCH_TOO_MANY, WATCHFRAME_MAXACHIEVEMENTS), 1.0, 0.1, 0.1, 1.0); + return; + end + + local _, _, _, completed = GetAchievementInfo(id) + if ( completed ) then + UIErrorsFrame:AddMessage(ERR_ACHIEVEMENT_WATCH_COMPLETED, 1.0, 0.1, 0.1, 1.0); + return; + end + + AddTrackedAchievement(id); + AchievementFrameAchievements_ForceUpdate(); + WatchFrame_Update(); + + return true; +end + +function AchievementButton_DisplayAchievement (button, category, achievement, selectionID) + local id, name, points, completed, month, day, year, description, flags, icon, rewardText = GetAchievementInfo(category, achievement); + if ( not id ) then + button:Hide(); + return; + else + button:Show(); + end + + button.index = achievement; + button.element = true; + + if ( button.id ~= id ) then + button.id = id; + button.label:SetWidth(ACHIEVEMENTBUTTON_LABELWIDTH); + button.label:SetText(name) + + if ( GetPreviousAchievement(id) ) then + -- If this is a progressive achievement, show the total score. + AchievementShield_SetPoints(AchievementButton_GetProgressivePoints(id), button.shield.points, AchievementPointsFont, AchievementPointsFontSmall); + else + AchievementShield_SetPoints(points, button.shield.points, AchievementPointsFont, AchievementPointsFontSmall); + end + + if ( points > 0 ) then + button.shield.icon:SetTexture([[Interface\AchievementFrame\UI-Achievement-Shields]]); + else + button.shield.icon:SetTexture([[Interface\AchievementFrame\UI-Achievement-Shields-NoPoints]]); + end + button.description:SetText(description); + button.hiddenDescription:SetText(description); + button.numLines = ceil(button.hiddenDescription:GetHeight() / ACHIEVEMENTUI_FONTHEIGHT); + button.icon.texture:SetTexture(icon); + if ( completed and not button.completed ) then + button.completed = true; + button.dateCompleted:SetText(string.format(SHORTDATE, day, month, year)); + button.dateCompleted:Show(); + button:Saturate(); + elseif ( completed ) then + button.dateCompleted:SetText(string.format(SHORTDATE, day, month, year)); + else + button.completed = nil; + button.dateCompleted:Hide(); + button:Desaturate(); + end + + if ( rewardText == "" ) then + button.reward:Hide(); + button.rewardBackground:Hide(); + else + button.reward:SetText(rewardText); + button.reward:Show(); + button.rewardBackground:Show(); + if ( button.completed ) then + button.rewardBackground:SetVertexColor(1, 1, 1); + else + button.rewardBackground:SetVertexColor(0.35, 0.35, 0.35); + end + end + + if ( IsTrackedAchievement(id) ) then + button.check:Show(); + button.label:SetWidth(button.label:GetStringWidth() + 4); -- This +4 here is to fudge around any string width issues that arize from resizing a string set to its string width. See bug 144418 for an example. + button.tracked:SetChecked(true); + button.tracked:Show(); + else + button.check:Hide(); + button.tracked:SetChecked(false); + button.tracked:Hide(); + end + + AchievementButton_UpdatePlusMinusTexture(button); + end + + if ( id == selectionID ) then + local achievements = AchievementFrameAchievements; + + achievements.selection = button.id; + achievements.selectionIndex = button.index; + button.selected = true; + button.highlight:Show(); + local height = AchievementButton_DisplayObjectives(button, button.id, button.completed); + if ( height == ACHIEVEMENTBUTTON_COLLAPSEDHEIGHT ) then + button:Collapse(); + else + button:Expand(height); + end + if ( not completed ) then + button.tracked:Show(); + end + elseif ( button.selected ) then + button.selected = nil; + if ( not button:IsMouseOver() ) then + button.highlight:Hide(); + end + button:Collapse(); + button.description:Show(); + button.hiddenDescription:Hide(); + end + + return id; +end + +function AchievementFrameAchievements_SelectButton (button) + local achievements = AchievementFrameAchievements; + + achievements.selection = button.id; + achievements.selectionIndex = button.index; + button.selected = true; +end + +function AchievementButton_ResetObjectives () + AchievementFrameAchievementsObjectives:Hide(); +end + +function AchievementButton_DisplayObjectives (button, id, completed) + local objectives = AchievementFrameAchievementsObjectives; + + objectives:ClearAllPoints(); + objectives:SetParent(button); + objectives:Show(); + objectives.completed = completed; + local height = 0; + if ( objectives.id == id ) then + local ACHIEVEMENTMODE_CRITERIA = 1; + if ( objectives.mode == ACHIEVEMENTMODE_CRITERIA ) then + if ( objectives:GetHeight() > 0 ) then + objectives:SetPoint("TOP", "$parentHiddenDescription", "BOTTOM", 0, -8); + objectives:SetPoint("LEFT", "$parentIcon", "RIGHT", -5, 0); + objectives:SetPoint("RIGHT", "$parentShield", "LEFT", -10, 0); + end + height = ACHIEVEMENTBUTTON_COLLAPSEDHEIGHT + objectives:GetHeight(); + else + objectives:SetPoint("TOP", "$parentHiddenDescription", "BOTTOM", 0, -8); + height = ACHIEVEMENTBUTTON_COLLAPSEDHEIGHT + objectives:GetHeight(); + end + elseif ( completed and GetPreviousAchievement(id) ) then + objectives:SetHeight(0); + AchievementButton_ResetCriteria(); + AchievementButton_ResetProgressBars(); + AchievementButton_ResetMiniAchievements(); + AchievementButton_ResetMetas(); + AchievementObjectives_DisplayProgressiveAchievement(objectives, id); + objectives:SetPoint("TOP", "$parentHiddenDescription", "BOTTOM", 0, -8); + height = ACHIEVEMENTBUTTON_COLLAPSEDHEIGHT + objectives:GetHeight(); + else + objectives:SetHeight(0); + AchievementButton_ResetCriteria(); + AchievementButton_ResetProgressBars(); + AchievementButton_ResetMiniAchievements(); + AchievementButton_ResetMetas(); + AchievementObjectives_DisplayCriteria(objectives, id); + if ( objectives:GetHeight() > 0 ) then + objectives:SetPoint("TOP", "$parentHiddenDescription", "BOTTOM", 0, -8); + objectives:SetPoint("LEFT", "$parentIcon", "RIGHT", -5, -25); + objectives:SetPoint("RIGHT", "$parentShield", "LEFT", -10, 0); + end + height = ACHIEVEMENTBUTTON_COLLAPSEDHEIGHT + objectives:GetHeight(); + end + + if ( height ~= ACHIEVEMENTBUTTON_COLLAPSEDHEIGHT or button.numLines > ACHIEVEMENTUI_MAX_LINES_COLLAPSED ) then + button.hiddenDescription:Show(); + button.description:Hide(); + local descriptionHeight = button.hiddenDescription:GetHeight(); + height = height + descriptionHeight - ACHIEVEMENTBUTTON_DESCRIPTIONHEIGHT; + if ( button.reward:IsShown() ) then + height = height + 4; + end + end + + objectives.id = id; + return height; +end + +function AchievementShield_SetPoints(points, pointString, normalFont, smallFont) + if ( points == 0 ) then + pointString:SetText(""); + return; + end + if ( points <= 100 ) then + pointString:SetFontObject(normalFont); + else + pointString:SetFontObject(smallFont); + end + pointString:SetText(points); +end + +function AchievementButton_ResetTable (t) + for k, v in next, t do + v:Hide(); + end +end + +local criteriaTable = {} + +function AchievementButton_ResetCriteria () + AchievementButton_ResetTable(criteriaTable); +end + +function AchievementButton_GetCriteria (index) + local criteriaTable = criteriaTable; + + if ( criteriaTable[index] ) then + return criteriaTable[index]; + end + + local frame = CreateFrame("FRAME", "AchievementFrameCriteria" .. index, AchievementFrameAchievements, "AchievementCriteriaTemplate"); + AchievementFrame_LocalizeCriteria(frame); + criteriaTable[index] = frame; + + return frame; +end + +-- The smallest table in WoW. +local miniTable = {} + +function AchievementButton_ResetMiniAchievements () + AchievementButton_ResetTable(miniTable); +end + +function AchievementButton_GetMiniAchievement (index) + local miniTable = miniTable; + if ( miniTable[index] ) then + return miniTable[index]; + end + + local frame = CreateFrame("FRAME", "AchievementFrameMiniAchievement" .. index, AchievementFrameAchievements, "MiniAchievementTemplate"); + AchievementButton_LocalizeMiniAchievement(frame); + miniTable[index] = frame; + + return frame; +end + +local progressBarTable = {}; + +function AchievementButton_ResetProgressBars () + AchievementButton_ResetTable(progressBarTable); +end + +function AchievementButton_GetProgressBar (index) + local progressBarTable = progressBarTable; + if ( progressBarTable[index] ) then + return progressBarTable[index]; + end + + local frame = CreateFrame("STATUSBAR", "AchievementFrameProgressBar" .. index, AchievementFrameAchievements, "AchievementProgressBarTemplate"); + AchievementButton_LocalizeProgressBar(frame); + progressBarTable[index] = frame; + + return frame; +end + +local metaCriteriaTable = {}; + +function AchievementButton_ResetMetas () + AchievementButton_ResetTable(metaCriteriaTable); +end + +function AchievementButton_GetMeta (index) + local metaCriteriaTable = metaCriteriaTable; + if ( metaCriteriaTable[index] ) then + return metaCriteriaTable[index]; + end + + local frame = CreateFrame("BUTTON", "AchievementFrameMeta" .. index, AchievementFrameAchievements, "MetaCriteriaTemplate"); + AchievementButton_LocalizeMetaAchievement(frame); + metaCriteriaTable[index] = frame; + + return frame; +end + +function AchievementButton_GetProgressivePoints(achievementID) + local points; + local _, _, progressivePoints, completed = GetAchievementInfo(achievementID); + + while GetPreviousAchievement(achievementID) do + achievementID = GetPreviousAchievement(achievementID); + _, _, points, completed = GetAchievementInfo(achievementID); + progressivePoints = progressivePoints+points; + end + + if ( progressivePoints ) then + return progressivePoints; + else + return 0; + end +end + +local achievementList = {}; + +function AchievementObjectives_DisplayProgressiveAchievement (objectivesFrame, id) + local ACHIEVEMENTMODE_PROGRESSIVE = 2; + local achievementID = id; + + local achievementList = achievementList; + for i in next, achievementList do + achievementList[i] = nil; + end + + tinsert(achievementList, 1, achievementID); + while GetPreviousAchievement(achievementID) do + tinsert(achievementList, 1, GetPreviousAchievement(achievementID)); + achievementID = GetPreviousAchievement(achievementID); + end + + local i = 0; + for index, achievementID in ipairs(achievementList) do + local _, achievementName, points, completed, month, day, year, description, flags, iconpath = GetAchievementInfo(achievementID); + + local miniAchievement = AchievementButton_GetMiniAchievement(index); + + miniAchievement:Show(); + miniAchievement:SetParent(objectivesFrame); + _G[miniAchievement:GetName() .. "Icon"]:SetTexture(iconpath); + if ( index == 1 ) then + miniAchievement:SetPoint("TOPLEFT", objectivesFrame, "TOPLEFT", -4, -4); + elseif ( index == 7 ) then + miniAchievement:SetPoint("TOPLEFT", miniTable[1], "BOTTOMLEFT", 0, -8); + else + miniAchievement:SetPoint("TOPLEFT", miniTable[index-1], "TOPRIGHT", 4, 0); + end + + miniAchievement.points:SetText(points); + + miniAchievement.numCriteria = 0; + if ( not ( bit.band(flags, ACHIEVEMENT_FLAGS_HAS_PROGRESS_BAR) == ACHIEVEMENT_FLAGS_HAS_PROGRESS_BAR ) ) then + for i = 1, GetAchievementNumCriteria(achievementID) do + local criteriaString, criteriaType, completed = GetAchievementCriteriaInfo(achievementID, i); + if ( completed == false ) then + criteriaString = "|CFF808080 - " .. criteriaString; + else + criteriaString = "|CFF00FF00 - " .. criteriaString; + end + miniAchievement["criteria" .. i] = criteriaString; + miniAchievement.numCriteria = i; + end + end + miniAchievement.name = achievementName; + miniAchievement.desc = description; + if ( month ) then + miniAchievement.date = string.format(SHORTDATE, day, month, year); + end + i = index; + end + + objectivesFrame:SetHeight(math.ceil(i/6) * ACHIEVEMENTUI_PROGRESSIVEHEIGHT); + objectivesFrame:SetWidth(min(i, 6) * ACHIEVEMENTUI_PROGRESSIVEWIDTH); + objectivesFrame.mode = ACHIEVEMENTMODE_PROGRESSIVE; +end + +function AchievementFrame_GetCategoryNumAchievements_All (categoryID) + local numAchievements, numCompleted = GetCategoryNumAchievements(categoryID); + + return numAchievements, numCompleted, 0; +end + +function AchievementFrame_GetCategoryNumAchievements_Complete (categoryID) + local numAchievements, numCompleted = GetCategoryNumAchievements(categoryID); + + return numCompleted, numCompleted, 0; +end + +function AchievementFrame_GetCategoryNumAchievements_Incomplete (categoryID) + local numAchievements, numCompleted = GetCategoryNumAchievements(categoryID); + + return numAchievements - numCompleted, 0, numCompleted +end + +ACHIEVEMENTUI_SELECTEDFILTER = AchievementFrame_GetCategoryNumAchievements_All; + +AchievementFrameFilters = { {text=ACHIEVEMENTFRAME_FILTER_ALL, func= AchievementFrame_GetCategoryNumAchievements_All}, + {text=ACHIEVEMENTFRAME_FILTER_COMPLETED, func=AchievementFrame_GetCategoryNumAchievements_Complete}, +{text=ACHIEVEMENTFRAME_FILTER_INCOMPLETE, func=AchievementFrame_GetCategoryNumAchievements_Incomplete} }; + +function AchievementFrameFilterDropDown_OnLoad (self) + self.relativeTo = "AchievementFrameFilterDropDown" + self.xOffset = -14; + self.yOffset = 10; + UIDropDownMenu_Initialize(self, AchievementFrameFilterDropDown_Initialize); +end + +function AchievementFrameFilterDropDown_Initialize (self) + local info = UIDropDownMenu_CreateInfo(); + for i, filter in ipairs(AchievementFrameFilters) do + info.text = filter.text; + info.value = i; + info.func = AchievementFrameFilterDropDownButton_OnClick; + if ( filter.func == ACHIEVEMENTUI_SELECTEDFILTER ) then + info.checked = 1; + UIDropDownMenu_SetText(self, filter.text); + else + info.checked = nil; + end + UIDropDownMenu_AddButton(info); + end +end + +function AchievementFrameFilterDropDownButton_OnClick (self) + AchievementFrame_SetFilter(self.value); +end + +function AchievementFrame_SetFilter(value) + local func = AchievementFrameFilters[value].func; + if ( func ~= ACHIEVEMENTUI_SELECTEDFILTER ) then + ACHIEVEMENTUI_SELECTEDFILTER = func; + UIDropDownMenu_SetText(AchievementFrameFilterDropDown, AchievementFrameFilters[value].text) + AchievementFrameAchievementsContainerScrollBar:SetValue(0); + AchievementFrameAchievements_ForceUpdate(); + end +end + +function AchievementObjectives_DisplayCriteria (objectivesFrame, id) + if ( not id ) then + return; + end + + local ACHIEVEMENTMODE_CRITERIA = 1; + local numCriteria = GetAchievementNumCriteria(id); + + if ( numCriteria == 0 ) then + objectivesFrame.mode = ACHIEVEMENTMODE_CRITERIA; + objectivesFrame:SetHeight(0); + return; + end + + local frameLevel = objectivesFrame:GetFrameLevel() + 1; + + -- Why textStrings? You try naming anything just "string" and see how happy you are. + local textStrings, progressBars, metas = 0, 0, 0; + + local numRows = 0; + local maxCriteriaWidth = 0; + local yPos; + for i = 1, numCriteria do + local criteriaString, criteriaType, completed, quantity, reqQuantity, charName, flags, assetID, quantityString = GetAchievementCriteriaInfo(id, i); + + if ( criteriaType == CRITERIA_TYPE_ACHIEVEMENT and assetID ) then + metas = metas + 1; + local metaCriteria = AchievementButton_GetMeta(metas); + + if ( metas == 1 ) then + metaCriteria:SetPoint("TOP", objectivesFrame, "TOP", 0, -4); + numRows = numRows + 2; + elseif ( math.fmod(metas, 2) == 0 ) then + yPos = -((metas/2 - 1) * 28) - 8; + metaCriteriaTable[metas-1]:SetPoint("TOPLEFT", objectivesFrame, "TOPLEFT", 20, yPos); + metaCriteria:SetPoint("TOPLEFT", objectivesFrame, "TOPLEFT", 210, yPos); + else + metaCriteria:SetPoint("TOPLEFT", objectivesFrame, "TOPLEFT", 20, -(math.ceil(metas/2 - 1) * 28) - 8); + numRows = numRows + 2; + end + + local id, achievementName, points, completed, month, day, year, description, flags, iconpath = GetAchievementInfo(assetID); + + if ( month ) then + metaCriteria.date = string.format(SHORTDATE, day, month, year); + else + metaCriteria.date = nil; + end + + metaCriteria.id = id; + metaCriteria.label:SetText(achievementName); + metaCriteria.icon:SetTexture(iconpath); + + if ( objectivesFrame.completed and completed ) then + metaCriteria.check:Show(); + metaCriteria.border:SetVertexColor(1, 1, 1, 1); + metaCriteria.icon:SetVertexColor(1, 1, 1, 1); + metaCriteria.label:SetShadowOffset(0, 0) + metaCriteria.label:SetTextColor(0, 0, 0, 1); + elseif ( completed ) then + metaCriteria.check:Show(); + metaCriteria.border:SetVertexColor(1, 1, 1, 1); + metaCriteria.icon:SetVertexColor(1, 1, 1, 1); + metaCriteria.label:SetShadowOffset(1, -1) + metaCriteria.label:SetTextColor(0, 1, 0, 1); + else + metaCriteria.check:Hide(); + metaCriteria.border:SetVertexColor(.75, .75, .75, 1); + metaCriteria.icon:SetVertexColor(.55, .55, .55, 1); + metaCriteria.label:SetShadowOffset(1, -1) + metaCriteria.label:SetTextColor(.6, .6, .6, 1); + end + + metaCriteria:SetParent(objectivesFrame); + metaCriteria:Show(); + elseif ( bit.band(flags, ACHIEVEMENT_CRITERIA_PROGRESS_BAR) == ACHIEVEMENT_CRITERIA_PROGRESS_BAR ) then + -- Display this criteria as a progress bar! + progressBars = progressBars + 1; + local progressBar = AchievementButton_GetProgressBar(progressBars); + + if ( progressBars == 1 ) then + progressBar:SetPoint("TOP", objectivesFrame, "TOP", 4, -4); + else + progressBar:SetPoint("TOP", progressBarTable[progressBars-1], "BOTTOM", 0, 0); + end + + progressBar.text:SetText(string.format("%s", quantityString)); + progressBar:SetMinMaxValues(0, reqQuantity); + progressBar:SetValue(quantity); + + progressBar:SetParent(objectivesFrame); + progressBar:Show(); + + numRows = numRows + 1; + else + textStrings = textStrings + 1; + local criteria = AchievementButton_GetCriteria(textStrings); + criteria:ClearAllPoints(); + if ( textStrings == 1 ) then + if ( numCriteria == 1 ) then + criteria:SetPoint("TOP", objectivesFrame, "TOP", -14, 0); + else + criteria:SetPoint("TOPLEFT", objectivesFrame, "TOPLEFT", 0, 0); + end + + else + criteria:SetPoint("TOPLEFT", criteriaTable[textStrings-1], "BOTTOMLEFT", 0, 0); + end + + if ( objectivesFrame.completed and completed ) then + criteria.name:SetTextColor(0, 0, 0, 1); + criteria.name:SetShadowOffset(0, 0); + elseif ( completed ) then + criteria.name:SetTextColor(0, 1, 0, 1); + criteria.name:SetShadowOffset(1, -1); + else + criteria.name:SetTextColor(.6, .6, .6, 1); + criteria.name:SetShadowOffset(1, -1); + end + + if ( completed ) then + criteria.check:SetPoint("LEFT", 18, -3); + criteria.name:SetPoint("LEFT", criteria.check, "RIGHT", 0, 2); + criteria.check:Show(); + criteria.name:SetText(criteriaString); + else + criteria.check:SetPoint("LEFT", 0, -3); + criteria.name:SetPoint("LEFT", criteria.check, "RIGHT", 5, 2); + criteria.check:Hide(); + criteria.name:SetText("- "..criteriaString); + end + + criteria:SetParent(objectivesFrame); + criteria:Show(); + local stringWidth = criteria.name:GetStringWidth() + criteria:SetWidth(stringWidth + criteria.check:GetWidth()); + maxCriteriaWidth = max(maxCriteriaWidth, stringWidth + criteria.check:GetWidth()); + + numRows = numRows + 1; + end + end + + if ( textStrings > 0 and progressBars > 0 ) then + -- If we have text criteria and progressBar criteria, display the progressBar criteria first and position the textStrings under them. + criteriaTable[1]:ClearAllPoints(); + if ( textStrings == 1 ) then + criteriaTable[1]:SetPoint("TOP", progressBarTable[progressBars], "BOTTOM", -14, -4); + else + criteriaTable[1]:SetPoint("TOP", progressBarTable[progressBars], "BOTTOM", 0, -4); + criteriaTable[1]:SetPoint("LEFT", objectivesFrame, "LEFT", 0, 0); + end + elseif ( textStrings > 1 ) then + -- Figure out if we can make multiple columns worth of criteria instead of one long one + local numColumns = floor(ACHIEVEMENTUI_MAXCONTENTWIDTH/maxCriteriaWidth); + if ( numColumns > 1 ) then + local step; + local rows = 1; + local position = 0; + for i=1, #criteriaTable do + position = position + 1; + if ( position > numColumns ) then + position = position - numColumns; + rows = rows + 1; + end + + if ( rows == 1 ) then + criteriaTable[i]:ClearAllPoints(); + criteriaTable[i]:SetPoint("TOPLEFT", objectivesFrame, "TOPLEFT", (position - 1)*(ACHIEVEMENTUI_MAXCONTENTWIDTH/numColumns), 0); + else + criteriaTable[i]:ClearAllPoints(); + criteriaTable[i]:SetPoint("TOPLEFT", criteriaTable[position + ((rows - 2) * numColumns)], "BOTTOMLEFT", 0, 0); + end + end + numRows = ceil(numRows/numColumns); + end + end + + if ( metas > 0 ) then + objectivesFrame:SetHeight(numRows * ACHIEVEMENTBUTTON_METAROWHEIGHT + 10); + else + objectivesFrame:SetHeight(numRows * ACHIEVEMENTBUTTON_CRITERIAROWHEIGHT); + end + objectivesFrame.mode = ACHIEVEMENTMODE_CRITERIA; +end + +-- [[ StatsFrames ]]-- + +function AchievementFrameStats_OnEvent (self, event, ...) + if ( event == "CRITERIA_UPDATE" and self:IsShown() ) then + AchievementFrameStats_Update(); + end +end + +function AchievementFrameStats_OnLoad (self) + AchievementFrameStatsContainerScrollBar.Show = + function (self) + AchievementFrameStats:SetWidth(504); + for _, button in next, AchievementFrameStats.buttons do + button:SetWidth(496); + end + getmetatable(self).__index.Show(self); + end + + AchievementFrameStatsContainerScrollBar.Hide = + function (self) + AchievementFrameStats:SetWidth(530); + for _, button in next, AchievementFrameStats.buttons do + button:SetWidth(522); + end + getmetatable(self).__index.Hide(self); + end + + self:RegisterEvent("CRITERIA_UPDATE"); + AchievementFrameStatsContainerScrollBarBG:Show(); + AchievementFrameStatsContainer.update = AchievementFrameStats_Update; + HybridScrollFrame_CreateButtons(AchievementFrameStatsContainer, "StatTemplate"); +end + +local displayStatCategories = {}; + +function AchievementFrameStats_Update () + local category = achievementFunctions.selectedCategory; + local scrollFrame = AchievementFrameStatsContainer; + local offset = HybridScrollFrame_GetOffset(scrollFrame); + local buttons = scrollFrame.buttons; + local numButtons = #buttons; + local statHeight = 24; + + local numStats, numCompleted = GetCategoryNumAchievements(category); + + local categories = ACHIEVEMENTUI_CATEGORIES; + -- clear out table + if ( achievementFunctions.lastCategory ~= category ) then + local statCat; + for i in next, displayStatCategories do + displayStatCategories[i] = nil; + end + -- build a list of shown category and stat id's + + tinsert(displayStatCategories, {id = category, header = true}); + for i=1, numStats do + tinsert(displayStatCategories, {id = GetAchievementInfo(category, i)}); + end + -- add all the subcategories and their stat id's + for i, cat in next, categories do + if ( cat.parent == category ) then + tinsert(displayStatCategories, {id = cat.id, header = true}); + numStats = GetCategoryNumAchievements(cat.id); + for k=1, numStats do + tinsert(displayStatCategories, {id = GetAchievementInfo(cat.id, k)}); + end + end + end + achievementFunctions.lastCategory = category; + end + + -- iterate through the displayStatCategories and display them + local selection = AchievementFrameStats.selection; + local statCount = #displayStatCategories; + local statIndex, id, button; + local stat; + + local totalHeight = statCount * statHeight; + local displayedHeight = numButtons * statHeight; + for i = 1, numButtons do + button = buttons[i]; + statIndex = offset + i; + if ( statIndex <= statCount ) then + stat = displayStatCategories[statIndex]; + if ( stat.header ) then + AchievementFrameStats_SetHeader(button, stat.id); + else + AchievementFrameStats_SetStat(button, stat.id, nil, statIndex); + end + button:Show(); + else + button:Hide(); + end + end + HybridScrollFrame_Update(scrollFrame, totalHeight, displayedHeight); +end + +function AchievementFrameStats_SetStat(button, category, index, colorIndex, isSummary) + --Remove these variables when we know for sure we don't need them + local id, name, points, completed, month, day, year, description, flags, icon; + if ( not isSummary ) then + if ( not index ) then + id, name, points, completed, month, day, year, description, flags, icon = GetAchievementInfo(category); + else + id, name, points, completed, month, day, year, description, flags, icon = GetAchievementInfo(category, index); + end + + else + -- This is on the summary page + id, name, points, completed, month, day, year, description, flags, icon = GetAchievementInfoFromCriteria(category); + end + + button.id = id; + + if ( not colorIndex ) then + if ( not index ) then + message("Error, need a color index or index"); + end + colorIndex = index; + end + button:SetText(name); + button.background:Show(); + -- Color every other line yellow + if ( mod(colorIndex, 2) == 1 ) then + button.background:SetTexCoord(0, 1, 0.1875, 0.3671875); + button.background:SetBlendMode("BLEND"); + button.background:SetAlpha(1.0); + button:SetHeight(24); + else + button.background:SetTexCoord(0, 1, 0.375, 0.5390625); + button.background:SetBlendMode("ADD"); + button.background:SetAlpha(0.5); + button:SetHeight(24); + end + + -- Figure out the criteria + local numCriteria = GetAchievementNumCriteria(id); + if ( numCriteria == 0 ) then + -- This is no good! + end + -- Just show the first criteria for now + local criteriaString, criteriaType, completed, quantityNumber, reqQuantity, charName, flags, assetID, quantity; + if ( not isSummary ) then + quantity = GetStatistic(id); + else + criteriaString, criteriaType, completed, quantityNumber, reqQuantity, charName, flags, assetID, quantity = GetAchievementCriteriaInfo(category); + end + if ( not quantity ) then + quantity = "--"; + end + button.value:SetText(quantity); + + -- Hide the header images + button.title:Hide(); + button.left:Hide(); + button.middle:Hide(); + button.right:Hide(); + button.isHeader = false; +end + +function AchievementFrameStats_SetHeader(button, id) + -- show header + button.left:Show(); + button.middle:Show(); + button.right:Show(); + local text; + if ( id == ACHIEVEMENT_COMPARISON_STATS_SUMMARY_ID ) then + text = ACHIEVEMENT_SUMMARY_CATEGORY; + else + text = GetCategoryInfo(id); + end + button.title:SetText(text); + button.title:Show(); + button.value:SetText(""); + button:SetText(""); + button:SetHeight(24); + button.background:Hide(); + button.isHeader = true; + button.id = id; +end + +function AchievementStatButton_OnLoad(self, parentFrame) + local name = self:GetName(); + self.background = _G[name.."BG"]; + self.left = _G[name.."HeaderLeft"]; + self.middle = _G[name.."HeaderMiddle"]; + self.right = _G[name.."HeaderRight"]; + self.text = _G[name.."Text"]; + self.title = _G[name.."Title"]; + self.value = _G[name.."Value"]; + self.value:SetVertexColor(1, 0.97, 0.6); + parentFrame.buttons = parentFrame.buttons or {}; + tinsert(parentFrame.buttons, self); +end + +function AchievementStatButton_OnClick(self) + if ( self.isHeader ) then + achievementFunctions.selectedCategory = self.id; + AchievementFrameCategories_Update(); + AchievementFrameStats_Update(); + elseif ( self.summary ) then + AchievementFrame_SelectSummaryStatistic(self.id); + end +end + +-- [[ Summary Frame ]] -- +function AchievementFrameSummary_OnShow() + if ( achievementFunctions ~= COMPARISON_ACHIEVEMENT_FUNCTIONS and achievementFunctions ~= COMPARISON_STAT_FUNCTIONS ) then + AchievementFrameSummary:SetWidth(530); + AchievementFrameSummary_Update(); + else + AchievementFrameComparisonDark:Hide(); + AchievementFrameComparisonWatermark:Hide(); + AchievementFrameComparison:SetWidth(650); + AchievementFrameSummary:SetWidth(650); + AchievementFrameSummary_Update(true); + end +end + +function AchievementFrameSummary_Update(isCompare) + AchievementFrameSummaryCategoriesStatusBar_Update(); + AchievementFrameSummary_UpdateAchievements(GetLatestCompletedAchievements()); +end + +function AchievementFrameSummary_UpdateAchievements(...) + local numAchievements = select("#", ...); + local id, name, points, completed, month, day, year, description, flags, icon; + local buttons = AchievementFrameSummaryAchievements.buttons; + local button, anchorTo, achievementID; + local defaultAchievementCount = 1; + + for i=1, ACHIEVEMENTUI_MAX_SUMMARY_ACHIEVEMENTS do + if ( buttons ) then + button = buttons[i]; + end + if ( not button ) then + button = CreateFrame("Button", "AchievementFrameSummaryAchievement"..i, AchievementFrameSummaryAchievements, "SummaryAchievementTemplate"); + + if ( i == 1 ) then + button:SetPoint("TOPLEFT",AchievementFrameSummaryAchievementsHeader, "BOTTOMLEFT", 18, 2 ); + button:SetPoint("TOPRIGHT",AchievementFrameSummaryAchievementsHeader, "BOTTOMRIGHT", -18, 2 ); + else + anchorTo = _G["AchievementFrameSummaryAchievement"..i-1]; + button:SetPoint("TOPLEFT",anchorTo, "BOTTOMLEFT", 0, 3 ); + button:SetPoint("TOPRIGHT",anchorTo, "BOTTOMRIGHT", 0, 3 ); + end + + if ( not buttons ) then + buttons = AchievementFrameSummaryAchievements.buttons; + end + AchievementFrameSummary_LocalizeButton(button); + end; + + if ( i <= numAchievements ) then + achievementID = select(i, ...); + id, name, points, completed, month, day, year, description, flags, icon = GetAchievementInfo(achievementID); + button.label:SetText(name); + button.description:SetText(description); + AchievementShield_SetPoints(points, button.shield.points, GameFontNormal, GameFontNormalSmall); + if ( points > 0 ) then + button.shield.icon:SetTexture([[Interface\AchievementFrame\UI-Achievement-Shields]]); + else + button.shield.icon:SetTexture([[Interface\AchievementFrame\UI-Achievement-Shields-NoPoints]]); + end + button.icon.texture:SetTexture(icon); + button.id = id; + + if ( completed ) then + button.dateCompleted:SetText(string.format(SHORTDATE, day, month, year)); + else + button.dateCompleted:SetText(""); + end + + button:Saturate(); + button.tooltipTitle = nil; + button:Show(); + else + for i=defaultAchievementCount, ACHIEVEMENTUI_MAX_SUMMARY_ACHIEVEMENTS do + achievementID = ACHIEVEMENTUI_DEFAULTSUMMARYACHIEVEMENTS[defaultAchievementCount]; + if ( not achievementID ) then + break; + end + id, name, points, completed, month, day, year, description, flags, icon = GetAchievementInfo(achievementID); + if ( completed ) then + defaultAchievementCount = defaultAchievementCount+1; + else + id, name, points, completed, month, day, year, description, flags, icon = GetAchievementInfo(achievementID); + button.label:SetText(name); + button.description:SetText(description); + AchievementShield_SetPoints(points, button.shield.points, GameFontNormal, GameFontNormalSmall); + if ( points > 0 ) then + button.shield.icon:SetTexture([[Interface\AchievementFrame\UI-Achievement-Shields]]); + else + button.shield.icon:SetTexture([[Interface\AchievementFrame\UI-Achievement-Shields-NoPoints]]); + end + button.icon.texture:SetTexture(icon); + button.id = id; + if ( month ) then + button.dateCompleted:SetText(string.format(SHORTDATE, day, month, year)); + else + button.dateCompleted:SetText(""); + end + button:Show(); + defaultAchievementCount = defaultAchievementCount+1; + button:Desaturate(); + button.tooltipTitle = SUMMARY_ACHIEVEMENT_INCOMPLETE; + button.tooltip = SUMMARY_ACHIEVEMENT_INCOMPLETE_TEXT; + break; + end + end + end + end + if ( numAchievements == 0 ) then + AchievementFrameSummaryAchievementsEmptyText:Show(); + else + AchievementFrameSummaryAchievementsEmptyText:Hide(); + end +end + +function AchievementFrameSummaryCategoriesStatusBar_Update() + local total, completed = GetNumCompletedAchievements(); + AchievementFrameSummaryCategoriesStatusBar:SetMinMaxValues(0, total); + AchievementFrameSummaryCategoriesStatusBar:SetValue(completed); + AchievementFrameSummaryCategoriesStatusBarText:SetText(completed.."/"..total); +end + +function AchievementFrameSummaryAchievement_OnLoad(self) + AchievementComparisonPlayerButton_OnLoad(self); + self.highlight = _G[self:GetName().."Highlight"]; + AchievementFrameSummaryAchievements.buttons = AchievementFrameSummaryAchievements.buttons or {}; + tinsert(AchievementFrameSummaryAchievements.buttons, self); + self:Saturate(); + self:SetBackdropBorderColor(ACHIEVEMENTUI_REDBORDER_R, ACHIEVEMENTUI_REDBORDER_G, ACHIEVEMENTUI_REDBORDER_B, 0.5); + self.titleBar:SetVertexColor(1,1,1,0.5); + self.dateCompleted:Show(); +end + +function AchievementFrameSummaryAchievement_OnClick(self) + local id = self.id + local nextID, completed = GetNextAchievement(id); + if ( nextID and completed ) then + local newID; + while ( nextID and completed ) do + newID, completed = GetNextAchievement(nextID); + if ( completed ) then + nextID = newID; + end + end + id = nextID; + end + + AchievementFrame_SelectAchievement(id); +end + +function AchievementFrameSummaryAchievement_OnEnter(self) + self.highlight:Show(); + if ( self.tooltipTitle ) then + GameTooltip:SetOwner(self, "ANCHOR_RIGHT"); + GameTooltip:SetText(self.tooltipTitle,1,1,1); + GameTooltip:AddLine(self.tooltip, nil, nil, nil, 1); + GameTooltip:Show(); + end +end + +function AchievementFrameSummaryCategoryButton_OnClick (self) + local id = self:GetParent():GetID(); + for _, button in next, AchievementFrameCategoriesContainer.buttons do + if ( button.categoryID == id ) then + button:Click(); + return; + end + end +end + +function AchievementFrameSummaryCategory_OnLoad (self) + self:SetMinMaxValues(0, 100); + self:SetValue(0); + local name = self:GetName(); + self.text = _G[name .. "Text"]; + + local categoryName = GetCategoryInfo(self:GetID()); + _G[name .. "Label"]:SetText(categoryName); +end + +function AchievementFrame_GetCategoryTotalNumAchievements (id, showAll) + -- Not recursive because we only have one deep and this saves time. + local totalAchievements, totalCompleted = 0, 0; + local numAchievements, numCompleted = GetCategoryNumAchievements(id, showAll); + totalAchievements = totalAchievements + numAchievements; + totalCompleted = totalCompleted + numCompleted; + + for _, category in next, ACHIEVEMENTUI_CATEGORIES do + if ( category.parent == id ) then + numAchievements, numCompleted = GetCategoryNumAchievements(category.id, showAll); + totalAchievements = totalAchievements + numAchievements; + totalCompleted = totalCompleted + numCompleted; + end + end + + return totalAchievements, totalCompleted; +end + +function AchievementFrameSummaryCategory_OnEvent (self, event, ...) + AchievementFrameSummaryCategory_OnShow(self); +end + +function AchievementFrameSummaryCategory_OnShow (self) + local totalAchievements, totalCompleted = AchievementFrame_GetCategoryTotalNumAchievements(self:GetID(), true); + + self.text:SetText(string.format("%d/%d", totalCompleted, totalAchievements)); + self:SetMinMaxValues(0, totalAchievements); + self:SetValue(totalCompleted); + self:RegisterEvent("ACHIEVEMENT_EARNED"); +end + +function AchievementFrameSummaryCategory_OnHide (self) + self:UnregisterEvent("ACHIEVEMENT_EARNED"); +end + +function AchievementFrame_SelectAchievement(id, forceSelect) + if ( not AchievementFrame:IsShown() and not forceSelect ) then + return; + end + + local _, _, _, achCompleted = GetAchievementInfo(id); + if ( achCompleted and (ACHIEVEMENTUI_SELECTEDFILTER == AchievementFrameFilters[ACHIEVEMENT_FILTER_INCOMPLETE].func) ) then + AchievementFrame_SetFilter(ACHIEVEMENT_FILTER_ALL); + elseif ( (not achCompleted) and (ACHIEVEMENTUI_SELECTEDFILTER == AchievementFrameFilters[ACHIEVEMENT_FILTER_COMPLETE].func) ) then + AchievementFrame_SetFilter(ACHIEVEMENT_FILTER_ALL); + end + + AchievementFrameTab_OnClick = AchievementFrameBaseTab_OnClick; + AchievementFrameTab_OnClick(1); + AchievementFrameSummary:Hide(); + AchievementFrameAchievements:Show(); + + -- Figure out if this is part of a progressive achievement; if it is and it's incomplete, make sure the previous level was completed. If not, find the first incomplete achievement in the chain and display that instead. + local _, _, _, completed = GetAchievementInfo(id); + if ( not completed and GetPreviousAchievement(id) ) then + local prevID = GetPreviousAchievement(id); + _, _, _, completed = GetAchievementInfo(prevID); + while ( prevID and not completed ) do + id = prevID; + prevID = GetPreviousAchievement(id); + if ( prevID ) then + _, _, _, completed = GetAchievementInfo(prevID); + end + end + elseif ( completed ) then + local nextID, completed = GetNextAchievement(id); + if ( nextID and completed ) then + local newID + while ( nextID and completed ) do + newID, completed = GetNextAchievement(nextID); + if ( completed ) then + nextID = newID; + end + end + id = nextID; + end + end + + AchievementFrameCategories_ClearSelection(); + local category = GetAchievementCategory(id); + + local categoryIndex, parent, hidden = 0; + for i, entry in next, ACHIEVEMENTUI_CATEGORIES do + if ( entry.id == category ) then + parent = entry.parent; + end + end + + for i, entry in next, ACHIEVEMENTUI_CATEGORIES do + if ( entry.id == parent ) then + entry.collapsed = false; + elseif ( entry.parent == parent ) then + entry.hidden = false; + elseif ( entry.parent == true ) then + entry.collapsed = true; + elseif ( entry.parent ) then + entry.hidden = true; + end + end + + achievementFunctions.selectedCategory = category; + AchievementFrameCategoriesContainerScrollBar:SetValue(0); + AchievementFrameCategories_Update(); + + local shown, i = false, 1; + while ( not shown ) do + for _, button in next, AchievementFrameCategoriesContainer.buttons do + if ( button.categoryID == category and math.ceil(button:GetBottom()) >= math.ceil(AchievementFrameAchievementsContainer:GetBottom())) then + shown = true; + end + end + + if ( not shown ) then + local _, maxVal = AchievementFrameCategoriesContainerScrollBar:GetMinMaxValues(); + if ( AchievementFrameCategoriesContainerScrollBar:GetValue() == maxVal ) then + --assert(false) + return; + else + HybridScrollFrame_OnMouseWheel(AchievementFrameCategoriesContainer, -1); + end + end + + -- Remove me if everything's working fine + i = i + 1; + if ( i > 100 ) then + --assert(false); + return; + end + end + + AchievementFrameAchievements_ClearSelection(); + AchievementFrameAchievementsContainerScrollBar:SetValue(0); + AchievementFrameAchievements_Update(); + + local shown = false; + while ( not shown ) do + for _, button in next, AchievementFrameAchievementsContainer.buttons do + if ( button.id == id and math.ceil(button:GetTop()) >= math.ceil(AchievementFrameAchievementsContainer:GetBottom())) then + -- The "True" here ignores modifiers, so you don't accidentally track or link this achievement. :P + AchievementButton_OnClick(button, true); + + -- We found the button! + shown = button; + break; + end + end + + local _, maxVal = AchievementFrameAchievementsContainerScrollBar:GetMinMaxValues(); + if ( shown ) then + -- If we can, move the achievement we're scrolling to to the top of the screen. + local newHeight = AchievementFrameAchievementsContainerScrollBar:GetValue() + AchievementFrameAchievementsContainer:GetTop() - shown:GetTop(); + newHeight = min(newHeight, maxVal); + AchievementFrameAchievementsContainerScrollBar:SetValue(newHeight); + else + if ( AchievementFrameAchievementsContainerScrollBar:GetValue() == maxVal ) then + --assert(false, "Failed to find achievement " .. id .. " while jumping!") + return; + else + HybridScrollFrame_OnMouseWheel(AchievementFrameAchievementsContainer, -1); + end + end + end +end + +function AchievementFrameAchievements_FindSelection() + local _, maxVal = AchievementFrameAchievementsContainerScrollBar:GetMinMaxValues(); + local scrollHeight = AchievementFrameAchievementsContainer:GetHeight(); + local newHeight = 0; + AchievementFrameAchievementsContainerScrollBar:SetValue(0); + while ( not shown ) do + for _, button in next, AchievementFrameAchievementsContainer.buttons do + if ( button.selected ) then + newHeight = AchievementFrameAchievementsContainerScrollBar:GetValue() + AchievementFrameAchievementsContainer:GetTop() - button:GetTop(); + newHeight = min(newHeight, maxVal); + AchievementFrameAchievementsContainerScrollBar:SetValue(newHeight); + return; + end + end + if ( AchievementFrameAchievementsContainerScrollBar:GetValue() == maxVal ) then + return; + else + newHeight = newHeight + scrollHeight; + newHeight = min(newHeight, maxVal); + AchievementFrameAchievementsContainerScrollBar:SetValue(newHeight); + end + end +end + +function AchievementFrameAchievements_AdjustSelection() + local selectedButton; + -- check if selection is visible + for _, button in next, AchievementFrameAchievementsContainer.buttons do + if ( button.selected ) then + selectedButton = button; + break; + end + end + + if ( not selectedButton ) then + AchievementFrameAchievements_FindSelection(); + else + local newHeight; + if ( selectedButton:GetTop() > AchievementFrameAchievementsContainer:GetTop() ) then + newHeight = AchievementFrameAchievementsContainerScrollBar:GetValue() + AchievementFrameAchievementsContainer:GetTop() - selectedButton:GetTop(); + elseif ( selectedButton:GetBottom() < AchievementFrameAchievementsContainer:GetBottom() ) then + if ( selectedButton:GetHeight() > AchievementFrameAchievementsContainer:GetHeight() ) then + newHeight = AchievementFrameAchievementsContainerScrollBar:GetValue() + AchievementFrameAchievementsContainer:GetTop() - selectedButton:GetTop(); + else + newHeight = AchievementFrameAchievementsContainerScrollBar:GetValue() + AchievementFrameAchievementsContainer:GetBottom() - selectedButton:GetBottom(); + end + end + if ( newHeight ) then + local _, maxVal = AchievementFrameAchievementsContainerScrollBar:GetMinMaxValues(); + newHeight = min(newHeight, maxVal); + AchievementFrameAchievementsContainerScrollBar:SetValue(newHeight); + end + end +end + +function AchievementFrame_SelectSummaryStatistic (criteriaId) + AchievementFrameTab_OnClick = AchievementFrameBaseTab_OnClick; + AchievementFrameTab_OnClick(2); + AchievementFrameStats:Show(); + AchievementFrameSummary:Hide(); + + AchievementFrameCategories_ClearSelection(); + + local id = GetAchievementInfoFromCriteria(criteriaId); + local category = GetAchievementCategory(id); + + local categoryIndex, parent, hidden = 0; + + local categoryIndex, parent, hidden = 0; + for i, entry in next, ACHIEVEMENTUI_CATEGORIES do + if ( entry.id == category ) then + parent = entry.parent; + end + end + + for i, entry in next, ACHIEVEMENTUI_CATEGORIES do + if ( entry.id == parent ) then + entry.collapsed = false; + elseif ( entry.parent == parent ) then + entry.hidden = false; + elseif ( entry.parent == true ) then + entry.collapsed = true; + elseif ( entry.parent ) then + entry.hidden = true; + end + end + + achievementFunctions.selectedCategory = category; + AchievementFrameCategories_Update(); + AchievementFrameCategoriesContainerScrollBar:SetValue(0); + + local shown, i = false, 1; + while ( not shown ) do + for _, button in next, AchievementFrameCategoriesContainer.buttons do + if ( button.categoryID == category and math.ceil(button:GetBottom()) >= math.ceil(AchievementFrameAchievementsContainer:GetBottom())) then + shown = true; + end + end + + if ( not shown ) then + local _, maxVal = AchievementFrameCategoriesContainerScrollBar:GetMinMaxValues(); + if ( AchievementFrameCategoriesContainerScrollBar:GetValue() == maxVal ) then + assert(false) + else + HybridScrollFrame_OnMouseWheel(AchievementFrameCategoriesContainer, -1); + end + end + + -- Remove me if everything's working fine + i = i + 1; + if ( i > 100 ) then + assert(false); + end + end + + AchievementFrameStats_Update(); + AchievementFrameStatsContainerScrollBar:SetValue(0); + + local shown, i = false, 1; + while ( not shown ) do + for _, button in next, AchievementFrameStatsContainer.buttons do + if ( button.id == id and math.ceil(button:GetBottom()) >= math.ceil(AchievementFrameStatsContainer:GetBottom())) then + AchievementStatButton_OnClick(button); + + -- We found the button! MAKE IT SHOWN ZOMG! + shown = button; + end + end + + if ( shown and AchievementFrameStatsContainerScrollBar:IsShown() ) then + -- If we can, move the achievement we're scrolling to to the top of the screen. + AchievementFrameStatsContainerScrollBar:SetValue(AchievementFrameStatsContainerScrollBar:GetValue() + AchievementFrameStatsContainer:GetTop() - shown:GetTop()); + elseif ( not shown ) then + local _, maxVal = AchievementFrameStatsContainerScrollBar:GetMinMaxValues(); + if ( AchievementFrameStatsContainerScrollBar:GetValue() == maxVal ) then + assert(false) + else + HybridScrollFrame_OnMouseWheel(AchievementFrameStatsContainer, -1); + end + end + + -- Remove me if everything's working fine. + i = i + 1; + if ( i > 100 ) then + assert(false); + end + end +end + +function AchievementFrameComparison_OnLoad (self) + AchievementFrameComparisonContainer_OnLoad(self); + AchievementFrameComparisonStatsContainer_OnLoad(self); + self:RegisterEvent("ACHIEVEMENT_EARNED"); + self:RegisterEvent("INSPECT_ACHIEVEMENT_READY"); +end + +function AchievementFrameComparisonContainer_OnLoad (parent) + AchievementFrameComparisonContainerScrollBar.Show = + function (self) + AchievementFrameComparison:SetWidth(626); + AchievementFrameComparisonSummaryPlayer:SetWidth(498); + for _, button in next, AchievementFrameComparisonContainer.buttons do + button:SetWidth(616); + button.player:SetWidth(498); + end + getmetatable(self).__index.Show(self); + end + + AchievementFrameComparisonContainerScrollBar.Hide = + function (self) + AchievementFrameComparison:SetWidth(650); + AchievementFrameComparisonSummaryPlayer:SetWidth(522); + for _, button in next, AchievementFrameComparisonContainer.buttons do + button:SetWidth(640); + button.player:SetWidth(522); + end + getmetatable(self).__index.Hide(self); + end + + AchievementFrameComparisonContainerScrollBarBG:Show(); + AchievementFrameComparisonContainer.update = AchievementFrameComparison_Update; + HybridScrollFrame_CreateButtons(AchievementFrameComparisonContainer, "ComparisonTemplate", 0, -2); +end + +function AchievementFrameComparisonStatsContainer_OnLoad (parent) + AchievementFrameComparisonStatsContainerScrollBar.Show = + function (self) + AchievementFrameComparison:SetWidth(626); + for _, button in next, AchievementFrameComparisonStatsContainer.buttons do + button:SetWidth(616); + end + getmetatable(self).__index.Show(self); + end + + AchievementFrameComparisonStatsContainerScrollBar.Hide = + function (self) + AchievementFrameComparison:SetWidth(650); + for _, button in next, AchievementFrameComparisonStatsContainer.buttons do + button:SetWidth(640); + end + getmetatable(self).__index.Hide(self); + end + + AchievementFrameComparisonStatsContainerScrollBarBG:Show(); + AchievementFrameComparisonStatsContainer.update = AchievementFrameComparison_UpdateStats; + HybridScrollFrame_CreateButtons(AchievementFrameComparisonStatsContainer, "ComparisonStatTemplate", 0, -2); +end + +function AchievementFrameComparison_OnShow () + AchievementFrameStats:Hide(); + AchievementFrameAchievements:Hide(); + AchievementFrame:SetWidth(890); + AchievementFrame:SetAttribute("UIPanelLayout-xOffset", 38); + UpdateUIPanelPositions(AchievementFrame); + AchievementFrame.isComparison = true; +end + +function AchievementFrameComparison_OnHide () + AchievementFrame.selectedTab = nil; + AchievementFrame:SetWidth(768); + AchievementFrame:SetAttribute("UIPanelLayout-xOffset", 80); + UpdateUIPanelPositions(AchievementFrame); + AchievementFrame.isComparison = false; + ClearAchievementComparisonUnit(); +end + +function AchievementFrameComparison_OnEvent (self, event, ...) + if ( event == "INSPECT_ACHIEVEMENT_READY" ) then + AchievementFrameComparisonHeaderPoints:SetText(GetComparisonAchievementPoints()); + AchievementFrameComparison_UpdateStatusBars(achievementFunctions.selectedCategory) + elseif ( event == "UNIT_PORTRAIT_UPDATE" ) then + local updateUnit = ...; + if ( updateUnit and updateUnit == AchievementFrameComparisonHeaderPortrait.unit and UnitName(updateUnit) == AchievementFrameComparisonHeaderName:GetText() ) then + SetPortraitTexture(AchievementFrameComparisonHeaderPortrait, updateUnit); + end + end + + AchievementFrameComparison_ForceUpdate(); +end + +function AchievementFrameComparison_SetUnit (unit) + ClearAchievementComparisonUnit(); + SetAchievementComparisonUnit(unit); + + AchievementFrameComparisonHeaderPoints:SetText(GetComparisonAchievementPoints()); + AchievementFrameComparisonHeaderName:SetText(UnitName(unit)); + SetPortraitTexture(AchievementFrameComparisonHeaderPortrait, unit); + AchievementFrameComparisonHeaderPortrait.unit = unit; + AchievementFrameComparisonHeaderPortrait.race = UnitRace(unit); + AchievementFrameComparisonHeaderPortrait.sex = UnitSex(unit); +end + +function AchievementFrameComparison_ClearSelection () + -- Doesn't do anything WHEE~! +end + +function AchievementFrameComparison_ForceUpdate () + if ( achievementFunctions == COMPARISON_ACHIEVEMENT_FUNCTIONS ) then + local buttons = AchievementFrameComparisonContainer.buttons; + for i, button in next, buttons do + button.id = nil; + end + + AchievementFrameComparison_Update(); + elseif ( achievementFunctions == COMPARISON_STAT_FUNCTIONS ) then + AchievementFrameComparison_UpdateStats(); + end +end + +function AchievementFrameComparison_Update () + local category = achievementFunctions.selectedCategory; + if ( not category or category == "summary" ) then + return; + end + local scrollFrame = AchievementFrameComparisonContainer + + local offset = HybridScrollFrame_GetOffset(scrollFrame); + local buttons = scrollFrame.buttons; + local numAchievements, numCompleted = GetCategoryNumAchievements(category); + local numButtons = #buttons; + + local achievementIndex; + local buttonHeight = buttons[1]:GetHeight(); + for i = 1, numButtons do + achievementIndex = i + offset; + AchievementFrameComparison_DisplayAchievement(buttons[i], category, achievementIndex); + end + + HybridScrollFrame_Update(scrollFrame, buttonHeight*numAchievements, buttonHeight*numButtons); +end + +ACHIEVEMENTCOMPARISON_PLAYERSHIELDFONT1 = GameFontNormal; +ACHIEVEMENTCOMPARISON_PLAYERSHIELDFONT2 = GameFontNormalSmall; +ACHIEVEMENTCOMPARISON_FRIENDSHIELDFONT1 = GameFontNormalSmall; +ACHIEVEMENTCOMPARISON_FRIENDSHIELDFONT2 = GameFontNormalSmall; + +function AchievementFrameComparison_DisplayAchievement (button, category, index) + local id, name, points, completed, month, day, year, description, flags, icon, rewardText = GetAchievementInfo(category, index); + if ( not id ) then + button:Hide(); + return; + else + button:Show(); + end + + if ( GetPreviousAchievement(id) ) then + -- If this is a progressive achievement, show the total score. + points = AchievementButton_GetProgressivePoints(id); + end + + if ( button.id ~= id ) then + button.id = id; + + local player = button.player; + local friend = button.friend; + + local friendCompleted, friendMonth, friendDay, friendYear = GetAchievementComparisonInfo(id); + player.label:SetText(name); + + player.description:SetText(description); + + player.icon.texture:SetTexture(icon); + friend.icon.texture:SetTexture(icon); + + if ( points > 0 ) then + player.shield.icon:SetTexture([[Interface\AchievementFrame\UI-Achievement-Shields]]); + friend.shield.icon:SetTexture([[Interface\AchievementFrame\UI-Achievement-Shields]]); + else + player.shield.icon:SetTexture([[Interface\AchievementFrame\UI-Achievement-Shields-NoPoints]]); + friend.shield.icon:SetTexture([[Interface\AchievementFrame\UI-Achievement-Shields-NoPoints]]); + end + AchievementShield_SetPoints(points, player.shield.points, ACHIEVEMENTCOMPARISON_PLAYERSHIELDFONT1, ACHIEVEMENTCOMPARISON_PLAYERSHIELDFONT2); + AchievementShield_SetPoints(points, friend.shield.points, ACHIEVEMENTCOMPARISON_FRIENDSHIELDFONT1, ACHIEVEMENTCOMPARISON_FRIENDSHIELDFONT2); + + if ( completed and not player.completed ) then + player.completed = true; + player.dateCompleted:SetText(string.format(SHORTDATE, day, month, year)); + player.dateCompleted:Show(); + player:Saturate(); + elseif ( completed ) then + player.dateCompleted:SetText(string.format(SHORTDATE, day, month, year)); + else + player.completed = nil; + player.dateCompleted:Hide(); + player:Desaturate(); + end + + if ( friendCompleted and not friend.completed ) then + friend.completed = true; + friend.status:SetText(string.format(SHORTDATE, friendDay, friendMonth, friendYear)); + friend:Saturate(); + elseif ( friendCompleted ) then + friend.status:SetText(string.format(SHORTDATE, friendDay, friendMonth, friendYear)); + else + friend.completed = nil; + friend.status:SetText(INCOMPLETE); + friend:Desaturate(); + end + end +end + +local displayStatCategories = {}; +function AchievementFrameComparison_UpdateStats () + local category = achievementFunctions.selectedCategory; + local scrollFrame = AchievementFrameComparisonStatsContainer; + local offset = HybridScrollFrame_GetOffset(scrollFrame); + local buttons = scrollFrame.buttons; + local numButtons = #buttons; + local headerHeight = 24; + local statHeight = 24; + local totalHeight = 0; + local numStats, numCompleted = GetCategoryNumAchievements(category); + + local categories = ACHIEVEMENTUI_CATEGORIES; + -- clear out table + if ( achievementFunctions.lastCategory ~= category ) then + local statCat; + for i in next, displayStatCategories do + displayStatCategories[i] = nil; + end + -- build a list of shown category and stat id's + + tinsert(displayStatCategories, {id = category, header = true}); + totalHeight = totalHeight+headerHeight; + + for i=1, numStats do + tinsert(displayStatCategories, {id = GetAchievementInfo(category, i)}); + totalHeight = totalHeight+statHeight; + end + achievementFunctions.lastCategory = category; + achievementFunctions.lastHeight = totalHeight; + else + totalHeight = achievementFunctions.lastHeight; + end + + -- add all the subcategories and their stat id's + for i, cat in next, categories do + if ( cat.parent == category ) then + tinsert(displayStatCategories, {id = cat.id, header = true}); + totalHeight = totalHeight+headerHeight; + numStats = GetCategoryNumAchievements(cat.id); + for k=1, numStats do + tinsert(displayStatCategories, {id = GetAchievementInfo(cat.id, k)}); + totalHeight = totalHeight+statHeight; + end + end + end + + -- iterate through the displayStatCategories and display them + local statCount = #displayStatCategories; + local statIndex, id, button; + local stat; + local displayedHeight = 0; + for i = 1, numButtons do + button = buttons[i]; + statIndex = offset + i; + if ( statIndex <= statCount ) then + stat = displayStatCategories[statIndex]; + if ( stat.header ) then + AchievementFrameComparisonStats_SetHeader(button, stat.id); + else + AchievementFrameComparisonStats_SetStat(button, stat.id, nil, statIndex); + end + button:Show(); + else + button:Hide(); + end + displayedHeight = displayedHeight+button:GetHeight(); + end + HybridScrollFrame_Update(scrollFrame, totalHeight, displayedHeight); +end + +function AchievementFrameComparisonStat_OnLoad (self) + local name = self:GetName(); + self.background = _G[name.."BG"]; + self.left = _G[name.."HeaderLeft"]; + self.middle = _G[name.."HeaderMiddle"]; + self.right = _G[name.."HeaderRight"]; + self.left2 = _G[name.."HeaderLeft2"]; + self.middle2 = _G[name.."HeaderMiddle2"]; + self.right2 = _G[name.."HeaderRight2"]; + self.text = _G[name.."Text"]; + self.title = _G[name.."Title"]; + self.value = _G[name.."Value"]; + self.value:SetVertexColor(1, 0.97, 0.6); + self.friendValue = _G[name.."ComparisonValue"]; + self.friendValue:SetVertexColor(1, 0.97, 0.6); + self.mouseover = _G[name.. "Mouseover"]; +end + +function AchievementFrameComparisonStats_SetStat (button, category, index, colorIndex, isSummary) +--Remove these variables when we know for sure we don't need them + local id, name, points, completed, month, day, year, description, flags, icon; + if ( not isSummary ) then + if ( not index ) then + id, name, points, completed, month, day, year, description, flags, icon = GetAchievementInfo(category); + else + id, name, points, completed, month, day, year, description, flags, icon = GetAchievementInfo(category, index); + end + + else + -- This is on the summary page + id, name, points, completed, month, day, year, description, flags, icon = GetAchievementInfoFromCriteria(category); + end + + button.id = id; + + if ( not colorIndex ) then + if ( not index ) then + message("Error, need a color index or index"); + end + colorIndex = index; + end + + button.background:Show(); + -- Color every other line yellow + if ( mod(colorIndex, 2) == 1 ) then + button.background:SetTexCoord(0, 1, 0.1875, 0.3671875); + button.background:SetBlendMode("BLEND"); + button.background:SetAlpha(1.0); + button:SetHeight(24); + else + button.background:SetTexCoord(0, 1, 0.375, 0.5390625); + button.background:SetBlendMode("ADD"); + button.background:SetAlpha(0.5); + button:SetHeight(24); + end + + -- Figure out the criteria + local numCriteria = GetAchievementNumCriteria(id); + if ( numCriteria == 0 ) then + -- This is no good! + end + -- Just show the first criteria for now + local criteriaString, criteriaType, completed, quantityNumber, reqQuantity, charName, flags, assetID, quantity, friendQuantity; + if ( not isSummary ) then + friendQuantity = GetComparisonStatistic(id); + quantity = GetStatistic(id); + else + criteriaString, criteriaType, completed, quantityNumber, reqQuantity, charName, flags, assetID, quantity = GetAchievementCriteriaInfo(category); + end + if ( not quantity ) then + quantity = "--"; + end + if ( not friendQuantity ) then + friendQuantity = "--"; + end + + button.value:SetText(quantity); + + -- We're gonna use button.text here to measure string width for friendQuantity. This saves us many strings! + button.text:SetText(friendQuantity); + local width = button.text:GetStringWidth(); + if ( width > button.friendValue:GetWidth() ) then + button.friendValue:SetFontObject("AchievementFont_Small"); + button.mouseover:Show(); + button.mouseover.tooltip = friendQuantity; + else + button.friendValue:SetFontObject("GameFontHighlightRight"); + button.mouseover:Hide(); + button.mouseover.tooltip = nil; + end + + button.text:SetText(name); + button.friendValue:SetText(friendQuantity); + + + -- Hide the header images + button.title:Hide(); + button.left:Hide(); + button.middle:Hide(); + button.right:Hide(); + button.left2:Hide(); + button.middle2:Hide(); + button.right2:Hide(); + button.isHeader = false; +end + +function AchievementFrameComparisonStats_SetHeader(button, id) + -- show header + button.left:Show(); + button.middle:Show(); + button.right:Show(); + button.left2:Show(); + button.middle2:Show(); + button.right2:Show(); + button.title:SetText(GetCategoryInfo(id)); + button.title:Show(); + button.friendValue:SetText(""); + button.value:SetText(""); + button.text:SetText(""); + button:SetHeight(24); + button.background:Hide(); + button.isHeader = true; + button.id = id; +end + +function AchievementComparisonPlayerButton_Saturate (self) + local name = self:GetName(); + _G[name .. "TitleBackground"]:SetTexCoord(0, 0.9765625, 0, 0.3125); + _G[name .. "Background"]:SetTexture("Interface\\AchievementFrame\\UI-Achievement-Parchment-Horizontal"); + _G[name .. "Glow"]:SetVertexColor(1.0, 1.0, 1.0); + self.icon:Saturate(); + self.shield:Saturate(); + self.shield.points:SetVertexColor(1, 1, 1); + self.label:SetVertexColor(1, 1, 1); + self.description:SetTextColor(0, 0, 0, 1); + self.description:SetShadowOffset(0, 0); + self:SetBackdropBorderColor(ACHIEVEMENTUI_REDBORDER_R, ACHIEVEMENTUI_REDBORDER_G, ACHIEVEMENTUI_REDBORDER_B, ACHIEVEMENTUI_REDBORDER_A); +end + +function AchievementComparisonPlayerButton_Desaturate (self) + local name = self:GetName(); + _G[name .. "TitleBackground"]:SetTexCoord(0, 0.9765625, 0.34375, 0.65625); + _G[name .. "Background"]:SetTexture("Interface\\AchievementFrame\\UI-Achievement-Parchment-Horizontal-Desaturated"); + _G[name .. "Glow"]:SetVertexColor(.22, .17, .13); + self.icon:Desaturate(); + self.shield:Desaturate(); + self.shield.points:SetVertexColor(.65, .65, .65); + self.label:SetVertexColor(.65, .65, .65); + self.description:SetTextColor(1, 1, 1, 1); + self.description:SetShadowOffset(1, -1); + self:SetBackdropBorderColor(.5, .5, .5); +end + +function AchievementComparisonPlayerButton_OnLoad (self) + local name = self:GetName(); + + self.label = _G[name .. "Label"]; + self.description = _G[name .. "Description"]; + self.icon = _G[name .. "Icon"]; + self.shield = _G[name .. "Shield"]; + self.dateCompleted = _G[name .. "DateCompleted"]; + self.titleBar = _G[name .. "TitleBackground"]; + + self:SetBackdropBorderColor(ACHIEVEMENTUI_REDBORDER_R, ACHIEVEMENTUI_REDBORDER_G, ACHIEVEMENTUI_REDBORDER_B, ACHIEVEMENTUI_REDBORDER_A); + self.Saturate = AchievementComparisonPlayerButton_Saturate; + self.Desaturate = AchievementComparisonPlayerButton_Desaturate; + + self:Desaturate(); + + -- AchievementFrameComparison.buttons = AchievementFrameComparison.buttons or {}; + -- tinsert(AchievementFrameComparison.buttons, self); +end + +function AchievementComparisonFriendButton_Saturate (self) + local name = self:GetName(); + _G[name .. "TitleBackground"]:SetTexCoord(0.3, 0.575, 0, 0.3125); + _G[name .. "Background"]:SetTexture("Interface\\AchievementFrame\\UI-Achievement-Parchment-Horizontal"); + _G[name .. "Glow"]:SetVertexColor(1.0, 1.0, 1.0); + self.icon:Saturate(); + self.shield:Saturate(); + self.shield.points:SetVertexColor(1, 1, 1); + self.status:SetVertexColor(1, .82, 0); + self:SetBackdropBorderColor(ACHIEVEMENTUI_REDBORDER_R, ACHIEVEMENTUI_REDBORDER_G, ACHIEVEMENTUI_REDBORDER_B, ACHIEVEMENTUI_REDBORDER_A); +end + +function AchievementComparisonFriendButton_Desaturate (self) + local name = self:GetName(); + _G[name .. "TitleBackground"]:SetTexCoord(0.3, 0.575, 0.34375, 0.65625); + _G[name .. "Background"]:SetTexture("Interface\\AchievementFrame\\UI-Achievement-Parchment-Horizontal-Desaturated"); + _G[name .. "Glow"]:SetVertexColor(.22, .17, .13); + self.icon:Desaturate(); + self.shield:Desaturate(); + self.shield.points:SetVertexColor(.65, .65, .65); + self.status:SetVertexColor(.65, .65, .65); + self:SetBackdropBorderColor(.5, .5, .5); +end + +function AchievementComparisonFriendButton_OnLoad (self) + local name = self:GetName(); + + self.status = _G[name .. "Status"]; + self.icon = _G[name .. "Icon"]; + self.shield = _G[name .. "Shield"]; + + self:SetBackdropBorderColor(ACHIEVEMENTUI_REDBORDER_R, ACHIEVEMENTUI_REDBORDER_G, ACHIEVEMENTUI_REDBORDER_B, ACHIEVEMENTUI_REDBORDER_A); + self.Saturate = AchievementComparisonFriendButton_Saturate; + self.Desaturate = AchievementComparisonFriendButton_Desaturate; + + self:Desaturate(); +end + +function AchievementFrame_IsComparison() + return AchievementFrame.isComparison; +end + +function AchievementFrame_IsFeatOfStrength() + if ( AchievementFrame.selectedTab == 1 and achievementFunctions.selectedCategory == displayCategories[#displayCategories].id ) then + return true; + end + return false; +end + +ACHIEVEMENT_FUNCTIONS = { + categoryAccessor = GetCategoryList, + clearFunc = AchievementFrameAchievements_ClearSelection, + updateFunc = AchievementFrameAchievements_Update, + selectedCategory = "summary"; +} + +STAT_FUNCTIONS = { + categoryAccessor = GetStatisticsCategoryList, + clearFunc = nil, + updateFunc = AchievementFrameStats_Update, + selectedCategory = "summary"; +} + +COMPARISON_ACHIEVEMENT_FUNCTIONS = { + categoryAccessor = GetCategoryList, + clearFunc = AchievementFrameComparison_ClearSelection, + updateFunc = AchievementFrameComparison_Update, + selectedCategory = -1, +} + +COMPARISON_STAT_FUNCTIONS = { + categoryAccessor = GetStatisticsCategoryList, + clearFunc = AchievementFrameComparison_ClearSelection, + updateFunc = AchievementFrameComparison_UpdateStats, + selectedCategory = -2, +} + +achievementFunctions = ACHIEVEMENT_FUNCTIONS; + + +ACHIEVEMENT_TEXTURES_TO_LOAD = { + { + name="AchievementFrameAchievementsBackground", + file="Interface\\AchievementFrame\\UI-Achievement-AchievementBackground", + }, + { + name="AchievementFrameSummaryBackground", + file="Interface\\AchievementFrame\\UI-Achievement-AchievementBackground", + }, + { + name="AchievementFrameComparisonBackground", + file="Interface\\AchievementFrame\\UI-Achievement-AchievementBackground", + }, + { + name="AchievementFrameCategoriesBG", + file="Interface\\AchievementFrame\\UI-Achievement-AchievementBackground", + }, + { + name="AchievementFrameWaterMark", + }, + { + name="AchievementFrameHeaderLeft", + file="Interface\\AchievementFrame\\UI-Achievement-Header", + }, + { + name="AchievementFrameHeaderRight", + file="Interface\\AchievementFrame\\UI-Achievement-Header", + }, + { + name="AchievementFrameHeaderPointBorder", + file="Interface\\AchievementFrame\\UI-Achievement-Header", + }, + { + name="AchievementFrameComparisonWatermark", + file="Interface\\AchievementFrame\\UI-Achievement-StatsComparisonBackground", + }, +} + +function AchievementFrame_ClearTextures() + for k, v in pairs(ACHIEVEMENT_TEXTURES_TO_LOAD) do + _G[v.name]:SetTexture(nil); + end +end + +function AchievementFrame_LoadTextures() + for k, v in pairs(ACHIEVEMENT_TEXTURES_TO_LOAD) do + if ( v.file ) then + _G[v.name]:SetTexture(v.file); + end + end +end \ No newline at end of file diff --git a/reference/AddOns/Blizzard_AchievementUI/Blizzard_AchievementUI.toc b/reference/AddOns/Blizzard_AchievementUI/Blizzard_AchievementUI.toc new file mode 100644 index 0000000..3bce478 --- /dev/null +++ b/reference/AddOns/Blizzard_AchievementUI/Blizzard_AchievementUI.toc @@ -0,0 +1,10 @@ +## Interface: 30300 +## Title: Blizzard_AchievementUI +## Notes: Hooray for Achievements! Everybody loves Achievements =D +## Secure: 1 +## Author: Blizzard Entertainment +## Version: 1.0 +## LoadOnDemand: 1 +Blizzard_AchievementUI.lua +Blizzard_AchievementUI.xml +Localization.lua \ No newline at end of file diff --git a/reference/AddOns/Blizzard_AchievementUI/Blizzard_AchievementUI.xml b/reference/AddOns/Blizzard_AchievementUI/Blizzard_AchievementUI.xml new file mode 100644 index 0000000..1b70db5 --- /dev/null +++ b/reference/AddOns/Blizzard_AchievementUI/Blizzard_AchievementUI.xml @@ -0,0 +1,3379 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AchievementFrameSummaryCategory_OnLoad(self); + + + AchievementFrameSummaryCategory_OnShow(self); + + + AchievementFrameSummaryCategory_OnHide(self); + + + AchievementFrameSummaryCategory_OnEvent(self, event, ...); + + + + + + + + + + + + + + + + + + + + + + + + + if ( self:GetChecked() ) then + PlaySound("igMainMenuOptionCheckBoxOn"); + else + PlaySound("igMainMenuOptionCheckBoxOff"); + end + local tracked = AchievementButton_ToggleTracking(self:GetParent().id); + if ( not tracked ) then + self:SetChecked(0); + end + + + GameTooltip:SetOwner(self, "ANCHOR_RIGHT"); + if ( self:GetChecked() ) then + GameTooltip:SetText(UNTRACK_ACHIEVEMENT_TOOLTIP, nil, nil, nil, nil, 1); + else + GameTooltip:SetText(TRACK_ACHIEVEMENT_TOOLTIP, nil, nil, nil, nil, 1); + end + + + GameTooltip:Hide(); + + + self:SetChecked(IsTrackedAchievement(self:GetParent().id)); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + local name = self:GetName(); + self.points = _G[name .. "Points"]; + self.icon = _G[name .. "Icon"]; + + + GameTooltip:SetOwner(self, "ANCHOR_RIGHT"); + if ( self.name ) then + GameTooltip:AddDoubleLine(self.name, self.date, nil, nil, nil, .5, .5, .5); + end + if ( self.desc ) then + GameTooltip:AddLine(self.desc, 1, 1, 1, 1); + end + if ( self.numCriteria ) then + for i = 1, self.numCriteria do + GameTooltip:AddLine(self["criteria"..i]); + end + end + GameTooltip:Show(); + + + GameTooltip:Hide(); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + self:SetStatusBarColor(0, .6, 0, 1); + self:SetMinMaxValues(0, 100); + self:SetValue(0); + self.text = _G[self:GetName() .. "Text"]; + self:GetStatusBarTexture():SetDrawLayer("BORDER"); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + local name = self:GetName(); + self.title = _G[name .. "Title"]; + self.text = _G[name .. "Text"]; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AchievementIcon_OnLoad(self); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + local name = self:GetName(); + self.name = _G[name .. "Name"]; + self.check = _G[name .. "Check"]; + + + if ( button == "LeftButton" ) then + self:GetParent():GetParent():Click(); + end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AchievementComparisonPlayerButton_OnLoad(self); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AchievementIcon_OnLoad(self); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AchievementShield_OnLoad(self); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AchievementFrameSummaryAchievement_OnLoad(self); + + + AchievementFrameSummaryAchievement_OnClick(self, button, down); + + + AchievementFrameSummaryAchievement_OnEnter(self, motion); + + + self.highlight:Hide(); + GameTooltip:Hide(); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AchievementComparisonFriendButton_OnLoad(self); + + + + + + + local name = self:GetName(); + self.player = _G[name .. "Player"]; + self.friend = _G[name .. "Friend"]; + + + + + + + + + + + + + + + + + + + + + + + local tooltip = self.tooltip; + if ( tooltip ) then + GameTooltip:SetOwner(self, "ANCHOR_RIGHT"); + GameTooltip:SetText(tooltip, nil, nil, nil, nil, 1); + end + + + GameTooltip:Hide(); + + + + + + + AchievementFrameComparisonStat_OnLoad(self); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AchievementFrameFilterDropDown:Hide(); + AchievementFrameHeaderRightDDLInset:Hide(); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + self:RegisterEvent("ACHIEVEMENT_EARNED"); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + --Temporaries + SetPortraitTexture(_G[self:GetName().."Portrait"], "player"); + self:SetFrameLevel(self:GetParent():GetFrameLevel() + 4); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + self:SetBackdropBorderColor(0.4, 0.2, 0, 1); + self.statusBar = _G[self:GetName().."StatusBar"]; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + self:SetBackdropBorderColor(0.4, 0.2, 0, 1); + self.statusBar = _G[self:GetName().."StatusBar"]; + self.statusBar.title:Hide(); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + local parentName = self:GetParent():GetName(); + _G[parentName .. "Summary"]:Show(); + _G[parentName .. "Watermark"]:Hide(); + _G[parentName .. "Dark"]:Show(); + + + local parentName = self:GetParent():GetName(); + _G[parentName .. "Summary"]:Hide(); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + CloseDropDownMenus() + + + + + + + + + + + + diff --git a/reference/AddOns/Blizzard_AchievementUI/Localization.lua b/reference/AddOns/Blizzard_AchievementUI/Localization.lua new file mode 100644 index 0000000..f4b6d1c --- /dev/null +++ b/reference/AddOns/Blizzard_AchievementUI/Localization.lua @@ -0,0 +1,21 @@ +-- This file is executed at the end of addon load + +function AchievementFrameSummary_LocalizeButton (button) + +end + +function AchievementButton_LocalizeMiniAchievement (frame) + +end + +function AchievementButton_LocalizeProgressBar (frame) + +end + +function AchievementButton_LocalizeMetaAchievement (frame) + +end + +function AchievementFrame_LocalizeCriteria (frame) + +end diff --git a/reference/AddOns/Blizzard_ArenaUI/Blizzard_ArenaUI.lua b/reference/AddOns/Blizzard_ArenaUI/Blizzard_ArenaUI.lua new file mode 100644 index 0000000..d72b6ec --- /dev/null +++ b/reference/AddOns/Blizzard_ArenaUI/Blizzard_ArenaUI.lua @@ -0,0 +1,335 @@ +MAX_ARENA_ENEMIES = 5; + +function ArenaEnemyFrames_OnLoad(self) + self:RegisterEvent("CVAR_UPDATE"); + self:RegisterEvent("VARIABLES_LOADED"); + self:RegisterEvent("PLAYER_ENTERING_WORLD"); + + if ( GetCVarBool("showArenaEnemyFrames") ) then + ArenaEnemyFrames_Enable(self); + else + ArenaEnemyFrames_Disable(self); + end + local showCastbars = GetCVarBool("showArenaEnemyCastbar"); + local castFrame; + for i = 1, MAX_ARENA_ENEMIES do + castFrame = _G["ArenaEnemyFrame"..i.."CastingBar"]; + castFrame.showCastbar = showCastbars; + CastingBarFrame_UpdateIsShown(castFrame); + end + + UpdateArenaEnemyBackground(GetCVarBool("showPartyBackground")); + ArenaEnemyBackground_SetOpacity(tonumber(GetCVar("partyBackgroundOpacity"))); +end + +function ArenaEnemyFrames_OnEvent(self, event, ...) + local arg1, arg2 = ...; + if ( (event == "CVAR_UPDATE") and (arg1 == "SHOW_ARENA_ENEMY_FRAMES_TEXT") ) then + if ( arg2 == "1" ) then + ArenaEnemyFrames_Enable(self); + else + ArenaEnemyFrames_Disable(self); + end + elseif ( event == "VARIABLES_LOADED" ) then + if ( GetCVarBool("showArenaEnemyFrames") ) then + ArenaEnemyFrames_Enable(self); + else + ArenaEnemyFrames_Disable(self); + end + local showCastbars = GetCVarBool("showArenaEnemyCastbar"); + local castFrame; + for i = 1, MAX_ARENA_ENEMIES do + castFrame = _G["ArenaEnemyFrame"..i.."CastingBar"]; + castFrame.showCastbar = showCastbars; + CastingBarFrame_UpdateIsShown(castFrame); + end + for i=1, MAX_ARENA_ENEMIES do + ArenaEnemyFrame_UpdatePet(_G["ArenaEnemyFrame"..i], i, true); + end + UpdateArenaEnemyBackground(GetCVarBool("showPartyBackground")); + ArenaEnemyBackground_SetOpacity(tonumber(GetCVar("partyBackgroundOpacity"))); + elseif ( event == "PLAYER_ENTERING_WORLD" ) then + ArenaEnemyFrames_UpdateVisible(); + end +end + +function ArenaEnemyFrames_OnShow(self) + --Set it up to hide stuff we don't want shown in an arena. + ArenaEnemyFrames_UpdateWatchFrame(); + + DurabilityFrame_SetAlerts(); + UIParent_ManageFramePositions(); +end + +function ArenaEnemyFrames_UpdateWatchFrame() + local ArenaEnemyFrames = ArenaEnemyFrames; + if ( not WatchFrame:IsUserPlaced() ) then + if ( ArenaEnemyFrames:IsShown() ) then + if ( WatchFrame_RemoveObjectiveHandler(WatchFrame_DisplayTrackedQuests) ) then + ArenaEnemyFrames.hidWatchedQuests = true; + end + else + if ( ArenaEnemyFrames.hidWatchedQuests ) then + WatchFrame_AddObjectiveHandler(WatchFrame_DisplayTrackedQuests); + ArenaEnemyFrames.hidWatchedQuests = false; + end + end + WatchFrame_ClearDisplay(); + WatchFrame_Update(); + elseif ( ArenaEnemyFrames.hidWatchedQuests ) then + WatchFrame_AddObjectiveHandler(WatchFrame_DisplayTrackedQuests); + ArenaEnemyFrames.hidWatchedQuests = false; + WatchFrame_ClearDisplay(); + WatchFrame_Update(); + end +end + +function ArenaEnemyFrames_OnHide(self) + --Make the stuff that needs to be shown shown again. + ArenaEnemyFrames_UpdateWatchFrame(); + + DurabilityFrame_SetAlerts(); + UIParent_ManageFramePositions(); +end + +function ArenaEnemyFrames_Enable(self) + self.show = true; + ArenaEnemyFrames_UpdateVisible(); +end + +function ArenaEnemyFrames_Disable(self) + self.show = false; + ArenaEnemyFrames_UpdateVisible(); +end + +function ArenaEnemyFrames_UpdateVisible() + local _, instanceType = IsInInstance(); + if ( ArenaEnemyFrames.show and (instanceType == "arena")) then + ArenaEnemyFrames:Show(); + else + ArenaEnemyFrames:Hide(); + end +end + +function ArenaEnemyFrame_OnLoad(self) + self.statusCounter = 0; + self.statusSign = -1; + self.unitHPPercent = 1; + + self.classPortrait = _G[self:GetName().."ClassPortrait"]; + ArenaEnemyFrame_UpdatePlayer(self, true); + self:RegisterEvent("UNIT_PET"); + self:RegisterEvent("ARENA_OPPONENT_UPDATE"); + self:RegisterEvent("UNIT_NAME_UPDATE"); + + UIDropDownMenu_Initialize(self.DropDown, ArenaEnemyDropDown_Initialize, "MENU"); + + local setfocus = function() + FocusUnit("arena"..self:GetID()); + end + SecureUnitButton_OnLoad(self, "arena"..self:GetID(), setfocus); + + local id = self:GetID(); + if ( UnitClass("arena"..id) and (not UnitExists("arena"..id))) then --It is possible for the unit itself to no longer exist on the client, but some of the information to remain (after reloading the UI) + self:Show(); + ArenaEnemyFrame_Lock(self); + elseif ( UnitExists("arenapet"..id) and ( not UnitClass("arena"..id) ) ) then --We use UnitClass because even if the unit doesn't exist on the client, we may still have enough info to populate the frame. + ArenaEnemyFrame_SetMysteryPlayer(self); + end +end + +function ArenaEnemyFrame_UpdatePlayer(self, useCVars)--At some points, we need to use CVars instead of UVars even though UVars are faster. + local id = self:GetID(); + if ( UnitGUID(self.unit) ) then --Use UnitGUID instead of UnitExists in case the unit is a remote update. + self:Show(); + UnitFrame_Update(self); + end + + local _, class = UnitClass(self.unit); + + if( class ) then + self.classPortrait:SetTexture("Interface\\TargetingFrame\\UI-Classes-Circles"); + self.classPortrait:SetTexCoord(unpack(CLASS_ICON_TCOORDS[class])); + end + + ArenaEnemyFrames_UpdateVisible(); +end + +function ArenaEnemyFrame_Lock(self) + self.healthbar:SetStatusBarColor(0.5, 0.5, 0.5); + self.healthbar.lockColor = true; + self.manabar:SetStatusBarColor(0.5, 0.5, 0.5); + self.manabar.lockColor = true; + self.hideStatusOnTooltip = true; +end + +function ArenaEnemyFrame_Unlock(self) + self.healthbar.lockColor = false; + self.healthbar.forceHideText = false; + self.manabar.lockColor = false; + self.manabar.forceHideText = false; + self.hideStatusOnTooltip = false; +end + +function ArenaEnemyFrame_SetMysteryPlayer(self) + self.healthbar:SetMinMaxValues(0,100); + self.healthbar:SetValue(100); + self.healthbar.forceHideText = true; + self.manabar:SetMinMaxValues(0,100); + self.manabar:SetValue(100); + self.manabar.forceHideText = true; + self.classPortrait:SetTexture("Interface\\CharacterFrame\\TempPortrait"); + self.classPortrait:SetTexCoord(0, 1, 0, 1); + self.name:SetText(""); + ArenaEnemyFrame_Lock(self); + self:Show(); +end + +function ArenaEnemyFrame_OnEvent(self, event, arg1, arg2) + if ( event == "ARENA_OPPONENT_UPDATE" and arg1 == self.unit ) then + if ( arg2 == "seen" or arg2 == "destroyed") then + ArenaEnemyFrame_Unlock(self); + ArenaEnemyFrame_UpdatePlayer(self); + + if ( self.healthbar.frequentUpdates and GetCVarBool("predictedHealth") ) then + self.healthbar:SetScript("OnUpdate", UnitFrameHealthBar_OnUpdate); + self.healthbar:UnregisterEvent("UNIT_HEALTH"); + end + if ( self.manabar.frequentUpdates and GetCVarBool("predictedPower") ) then + self.manabar:SetScript("OnUpdate", UnitFrameManaBar_OnUpdate); + UnitFrameManaBar_UnregisterDefaultEvents(self.manabar); + end + UpdateArenaEnemyBackground(); + UIParent_ManageFramePositions(); + elseif ( arg2 == "unseen" ) then + ArenaEnemyFrame_Lock(self); + + self.healthbar:RegisterEvent("UNIT_HEALTH"); + self.healthbar:SetScript("OnUpdate", nil); + UnitFrameManaBar_RegisterDefaultEvents(self.manabar); + self.manabar:SetScript("OnUpdate", nil); + elseif ( arg2 == "cleared" ) then + ArenaEnemyFrame_Unlock(self); + self:Hide(); + ArenaEnemyFrames_UpdateVisible(); + end + elseif ( event == "UNIT_PET" and arg1 == self.unit ) then + ArenaEnemyFrame_UpdatePet(self); + elseif ( event == "UNIT_NAME_UPDATE" and arg1 == self.unit ) then + ArenaEnemyFrame_UpdatePlayer(self); + end +end + +function ArenaEnemyFrame_UpdatePet(self, id, useCVars) --At some points, we need to use CVars instead of UVars even though UVars are faster. + if ( not id ) then + id = self:GetID(); + end + + local unitFrame = _G["ArenaEnemyFrame"..id]; + local petFrame = _G["ArenaEnemyFrame"..id.."PetFrame"]; + + local showArenaEnemyPets = (SHOW_ARENA_ENEMY_PETS == "1"); + if ( useCVars ) then + showArenaEnemyPets = GetCVarBool("showArenaEnemyPets"); + end + + if ( UnitGUID(petFrame.unit) and showArenaEnemyPets) then + petFrame:Show(); + else + petFrame:Hide(); + end + + UnitFrame_Update(petFrame); +end + +function ArenaEnemyPetFrame_OnLoad(self) + local id = self:GetParent():GetID(); + local prefix = "ArenaEnemyFrame"..id.."PetFrame"; + local unit = "arenapet"..id; + UnitFrame_Initialize(self, unit, _G[prefix.."Name"], _G[prefix.."Portrait"], + _G[prefix.."HealthBar"], _G[prefix.."HealthBarText"], _G[prefix.."ManaBar"], _G[prefix.."ManaBarText"]); + SetTextStatusBarTextZeroText(_G[prefix.."HealthBar"], DEAD); + _G[prefix.."Name"]:Hide(); + SecureUnitButton_OnLoad(self, unit); + self:SetID(id); + self:SetParent(ArenaEnemyFrames); + ArenaEnemyFrame_UpdatePet(self, id, true); + self:RegisterEvent("ARENA_OPPONENT_UPDATE"); + self:RegisterEvent("UNIT_CLASSIFICATION_CHANGED"); + + UIDropDownMenu_Initialize(self.DropDown, ArenaEnemyPetDropDown_Initialize, "MENU"); + + local setfocus = function() + FocusUnit("arenapet"..self:GetID()); + end + SecureUnitButton_OnLoad(self, "arenapet"..self:GetID(), setfocus); +end + +function ArenaEnemyPetFrame_OnEvent(self, event, ...) + local arg1, arg2 = ...; + if ( event == "ARENA_OPPONENT_UPDATE" and arg1 == self.unit ) then + if ( arg2 == "seen" or arg2 == "destroyed") then + ArenaEnemyFrame_Unlock(self); + ArenaEnemyFrame_UpdatePet(self); + UpdateArenaEnemyBackground(); + local ownerFrame = _G["ArenaEnemyFrame"..self:GetID()]; + if ( not ownerFrame:IsShown() ) then + ArenaEnemyFrame_SetMysteryPlayer(ownerFrame); + ownerFrame:Show(); + end + if ( self.healthbar.frequentUpdates and GetCVarBool("predictedHealth") ) then + self.healthbar:SetScript("OnUpdate", UnitFrameHealthBar_OnUpdate); + self.healthbar:UnregisterEvent("UNIT_HEALTH"); + end + if ( self.manabar.frequentUpdates and GetCVarBool("predictedPower") ) then + self.manabar:SetScript("OnUpdate", UnitFrameManaBar_OnUpdate); + UnitFrameManaBar_UnregisterDefaultEvents(self.manabar); + end + elseif ( arg2 == "unseen" ) then + ArenaEnemyFrame_Lock(self); + self.healthbar:RegisterEvent("UNIT_HEALTH"); + self.healthbar:SetScript("OnUpdate", nil); + UnitFrameManaBar_RegisterDefaultEvents(self.manabar); + self.manabar:SetScript("OnUpdate", nil); + elseif ( arg2 == "cleared" ) then + ArenaEnemyFrame_Unlock(self); + self:Hide() + end + elseif ( event == "UNIT_CLASSIFICATION_CHANGED" and arg1 == self.unit ) then + UnitFrame_Update(self); + end + UnitFrame_OnEvent(self, event, ...); +end + +function ArenaEnemyDropDown_Initialize(self) + UnitPopup_ShowMenu(self, "ARENAENEMY", "arena"..self:GetParent():GetID()); +end + +function ArenaEnemyPetDropDown_Initialize(self) + UnitPopup_ShowMenu(self, "ARENAENEMY", "arenapet"..self:GetParent():GetID()); +end + +function UpdateArenaEnemyBackground(force) + if ( (SHOW_PARTY_BACKGROUND == "1") or force ) then + ArenaEnemyBackground:Show(); + local numOpps = GetNumArenaOpponents(); + if ( numOpps > 0 ) then + ArenaEnemyBackground:SetPoint("BOTTOMLEFT", "ArenaEnemyFrame"..numOpps.."PetFrame", "BOTTOMLEFT", -15, -10); + else + ArenaEnemyBackground:Hide(); + end + else + ArenaEnemyBackground:Hide(); + end + +end + +function ArenaEnemyBackground_SetOpacity(opacity) + local alpha; + if ( not opacity ) then + alpha = 1.0 - OpacityFrameSlider:GetValue(); + else + alpha = 1.0 - opacity; + end + ArenaEnemyBackground:SetAlpha(alpha); +end diff --git a/reference/AddOns/Blizzard_ArenaUI/Blizzard_ArenaUI.toc b/reference/AddOns/Blizzard_ArenaUI/Blizzard_ArenaUI.toc new file mode 100644 index 0000000..01ad956 --- /dev/null +++ b/reference/AddOns/Blizzard_ArenaUI/Blizzard_ArenaUI.toc @@ -0,0 +1,6 @@ +## Interface: 30300 +## Title: Blizzard Arena UI +## Secure: 1 +## LoadOnDemand: 1 +Blizzard_ArenaUI.xml +Localization.lua diff --git a/reference/AddOns/Blizzard_ArenaUI/Blizzard_ArenaUI.xml b/reference/AddOns/Blizzard_ArenaUI/Blizzard_ArenaUI.xml new file mode 100644 index 0000000..e434e37 --- /dev/null +++ b/reference/AddOns/Blizzard_ArenaUI/Blizzard_ArenaUI.xml @@ -0,0 +1,577 @@ + + + diff --git a/reference/AddOns/Blizzard_RaidUI/Localization.lua b/reference/AddOns/Blizzard_RaidUI/Localization.lua new file mode 100644 index 0000000..e7b2086 --- /dev/null +++ b/reference/AddOns/Blizzard_RaidUI/Localization.lua @@ -0,0 +1 @@ +-- This file is executed at the end of addon load diff --git a/reference/AddOns/Blizzard_TalentUI/Blizzard_TalentUI.lua b/reference/AddOns/Blizzard_TalentUI/Blizzard_TalentUI.lua new file mode 100644 index 0000000..18e2e24 --- /dev/null +++ b/reference/AddOns/Blizzard_TalentUI/Blizzard_TalentUI.lua @@ -0,0 +1,1043 @@ + +StaticPopupDialogs["CONFIRM_LEARN_PREVIEW_TALENTS"] = { + text = CONFIRM_LEARN_PREVIEW_TALENTS, + button1 = YES, + button2 = NO, + OnAccept = function (self) + LearnPreviewTalents(PlayerTalentFrame.pet); + end, + OnCancel = function (self) + end, + hideOnEscape = 1, + timeout = 0, + exclusive = 1, +} + +UIPanelWindows["PlayerTalentFrame"] = { area = "left", pushable = 6, whileDead = 1 }; + + +-- global constants +GLYPH_TALENT_TAB = 4; + + +-- speed references +local next = next; +local ipairs = ipairs; + +-- local data +local specs = { + ["spec1"] = { + name = TALENT_SPEC_PRIMARY, + talentGroup = 1, + unit = "player", + pet = false, + tooltip = TALENT_SPEC_PRIMARY, + portraitUnit = "player", + defaultSpecTexture = "Interface\\Icons\\Ability_Marksmanship", + hasGlyphs = true, + glyphName = TALENT_SPEC_PRIMARY_GLYPH, + }, + ["spec2"] = { + name = TALENT_SPEC_SECONDARY, + talentGroup = 2, + unit = "player", + pet = false, + tooltip = TALENT_SPEC_SECONDARY, + portraitUnit = "player", + defaultSpecTexture = "Interface\\Icons\\Ability_Marksmanship", + hasGlyphs = true, + glyphName = TALENT_SPEC_SECONDARY_GLYPH, + }, + ["petspec1"] = { + name = TALENT_SPEC_PET_PRIMARY, + talentGroup = 1, + unit = "pet", + tooltip = TALENT_SPEC_PET_PRIMARY, + pet = true, + portraitUnit = "pet", + defaultSpecTexture = nil, + hasGlyphs = false, + glyphName = nil, + }, +}; + +local specTabs = { }; -- filled in by PlayerSpecTab_OnLoad +local numSpecTabs = 0; +local selectedSpec = nil; +local activeSpec = nil; + + +-- cache talent info so we can quickly display cool stuff like the number of points spent in each tab +local talentSpecInfoCache = { + ["spec1"] = { }, + ["spec2"] = { }, + ["petspec1"] = { }, +}; +-- cache talent tab widths so we can resize tabs to fit for localization +local talentTabWidthCache = { }; + + + +-- ACTIVESPEC_DISPLAYTYPE values: +-- "BLUE", "GOLD_INSIDE", "GOLD_BACKGROUND" +local ACTIVESPEC_DISPLAYTYPE = nil; + +-- SELECTEDSPEC_DISPLAYTYPE values: +-- "BLUE", "GOLD_INSIDE", "PUSHED_OUT", "PUSHED_OUT_CHECKED" +local SELECTEDSPEC_DISPLAYTYPE = "GOLD_INSIDE"; +local SELECTEDSPEC_OFFSETX; +if ( SELECTEDSPEC_DISPLAYTYPE == "PUSHED_OUT" or SELECTEDSPEC_DISPLAYTYPE == "PUSHED_OUT_CHECKED" ) then + SELECTEDSPEC_OFFSETX = 5; +else + SELECTEDSPEC_OFFSETX = 0; +end + + +-- PlayerTalentFrame + +function PlayerTalentFrame_Toggle(pet, suggestedTalentGroup) + local hidden; + local talentTabSelected = PanelTemplates_GetSelectedTab(PlayerTalentFrame) ~= GLYPH_TALENT_TAB; + if ( not PlayerTalentFrame:IsShown() ) then + ShowUIPanel(PlayerTalentFrame); + hidden = false; + else + local spec = selectedSpec and specs[selectedSpec]; + if ( spec and talentTabSelected ) then + -- if a talent tab is selected then toggle the frame off + HideUIPanel(PlayerTalentFrame); + hidden = true; + else + hidden = false; + end + end + if ( not hidden ) then + -- open the spec with the requested talent group (or the current talent group if the selected + -- spec has one) + if ( selectedSpec ) then + local spec = specs[selectedSpec]; + if ( spec.pet == pet ) then + suggestedTalentGroup = spec.talentGroup; + end + end + for _, index in ipairs(TALENT_SORT_ORDER) do + local spec = specs[index]; + if ( spec.pet == pet and spec.talentGroup == suggestedTalentGroup ) then + PlayerSpecTab_OnClick(specTabs[index]); + if ( not talentTabSelected ) then + PlayerTalentTab_OnClick(_G["PlayerTalentFrameTab"..PlayerTalentTab_GetBestDefaultTab(index)]); + end + break; + end + end + end +end + +function PlayerTalentFrame_Open(pet, talentGroup) + ShowUIPanel(PlayerTalentFrame); + -- open the spec with the requested talent group + for index, spec in next, specs do + if ( spec.pet == pet and spec.talentGroup == talentGroup ) then + PlayerSpecTab_OnClick(specTabs[index]); + break; + end + end +end + +function PlayerTalentFrame_ToggleGlyphFrame(suggestedTalentGroup) + GlyphFrame_LoadUI(); + if ( GlyphFrame ) then + local hidden; + if ( not PlayerTalentFrame:IsShown() ) then + ShowUIPanel(PlayerTalentFrame); + hidden = false; + else + local spec = selectedSpec and specs[selectedSpec]; + if ( spec and spec.hasGlyphs and + PanelTemplates_GetSelectedTab(PlayerTalentFrame) == GLYPH_TALENT_TAB ) then + -- if the glyph tab is selected then toggle the frame off + HideUIPanel(PlayerTalentFrame); + hidden = true; + else + hidden = false; + end + end + if ( not hidden ) then + -- open the spec with the requested talent group (or the current talent group if the selected + -- spec has one) + if ( selectedSpec ) then + local spec = specs[selectedSpec]; + if ( spec.hasGlyphs ) then + suggestedTalentGroup = spec.talentGroup; + end + end + for _, index in ipairs(TALENT_SORT_ORDER) do + local spec = specs[index]; + if ( spec.hasGlyphs and spec.talentGroup == suggestedTalentGroup ) then + PlayerSpecTab_OnClick(specTabs[index]); + PlayerTalentTab_OnClick(_G["PlayerTalentFrameTab"..GLYPH_TALENT_TAB]); + break; + end + end + end + end +end + +function PlayerTalentFrame_OpenGlyphFrame(talentGroup) + GlyphFrame_LoadUI(); + if ( GlyphFrame ) then + ShowUIPanel(PlayerTalentFrame); + -- open the spec with the requested talent group + for index, spec in next, specs do + if ( spec.hasGlyphs and spec.talentGroup == talentGroup ) then + PlayerSpecTab_OnClick(specTabs[index]); + PlayerTalentTab_OnClick(_G["PlayerTalentFrameTab"..GLYPH_TALENT_TAB]); + break; + end + end + end +end + +function PlayerTalentFrame_ShowGlyphFrame() + GlyphFrame_LoadUI(); + if ( GlyphFrame ) then + -- set the title text of the GlyphFrame + if ( selectedSpec and specs[selectedSpec].glyphName and GetNumTalentGroups() > 1 ) then + GlyphFrameTitleText:SetText(specs[selectedSpec].glyphName); + else + GlyphFrameTitleText:SetText(GLYPHS); + end + -- show/update the glyph frame + if ( GlyphFrame:IsShown() ) then + GlyphFrame_Update(); + else + GlyphFrame:Show(); + end + -- don't forget to hide the scroll button overlay or it may show up on top of the GlyphFrame! + UIFrameFlashStop(PlayerTalentFrameScrollButtonOverlay); + end +end + +function PlayerTalentFrame_HideGlyphFrame() + if ( not GlyphFrame or not GlyphFrame:IsShown() ) then + return; + end + + GlyphFrame_LoadUI(); + if ( GlyphFrame ) then + GlyphFrame:Hide(); + end +end + + +function PlayerTalentFrame_OnLoad(self) + self:RegisterEvent("ADDON_LOADED"); + self:RegisterEvent("PREVIEW_TALENT_POINTS_CHANGED"); + self:RegisterEvent("PREVIEW_PET_TALENT_POINTS_CHANGED"); + self:RegisterEvent("UNIT_PORTRAIT_UPDATE"); + self:RegisterEvent("UNIT_PET"); + self:RegisterEvent("PLAYER_LEVEL_UP"); + self:RegisterEvent("PLAYER_TALENT_UPDATE"); + self:RegisterEvent("PET_TALENT_UPDATE"); + self:RegisterEvent("ACTIVE_TALENT_GROUP_CHANGED"); + self.unit = "player"; + self.inspect = false; + self.pet = false; + self.talentGroup = 1; + self.updateFunction = PlayerTalentFrame_Update; + + TalentFrame_Load(self); + + -- setup talent buttons + local button; + for i = 1, MAX_NUM_TALENTS do + button = _G["PlayerTalentFrameTalent"..i]; + if ( button ) then + button:SetScript("OnClick", PlayerTalentFrameTalent_OnClick); + button:SetScript("OnEvent", PlayerTalentFrameTalent_OnEvent); + button:SetScript("OnEnter", PlayerTalentFrameTalent_OnEnter); + end + end + + -- setup tabs + PanelTemplates_SetNumTabs(self, MAX_TALENT_TABS + 1); -- add one for the GLYPH_TALENT_TAB + + -- initialize active spec as a fail safe + local activeTalentGroup = GetActiveTalentGroup(); + local numTalentGroups = GetNumTalentGroups(); + PlayerTalentFrame_UpdateActiveSpec(activeTalentGroup, numTalentGroups); + + -- setup active spec highlight + if ( ACTIVESPEC_DISPLAYTYPE == "BLUE" ) then + PlayerTalentFrameActiveSpecTabHighlight:SetDrawLayer("OVERLAY"); + PlayerTalentFrameActiveSpecTabHighlight:SetBlendMode("ADD"); + PlayerTalentFrameActiveSpecTabHighlight:SetTexture("Interface\\Buttons\\UI-Button-Outline"); + elseif ( ACTIVESPEC_DISPLAYTYPE == "GOLD_INSIDE" ) then + PlayerTalentFrameActiveSpecTabHighlight:SetDrawLayer("OVERLAY"); + PlayerTalentFrameActiveSpecTabHighlight:SetBlendMode("ADD"); + PlayerTalentFrameActiveSpecTabHighlight:SetTexture("Interface\\Buttons\\CheckButtonHilight"); + elseif ( ACTIVESPEC_DISPLAYTYPE == "GOLD_BACKGROUND" ) then + PlayerTalentFrameActiveSpecTabHighlight:SetDrawLayer("BACKGROUND"); + PlayerTalentFrameActiveSpecTabHighlight:SetWidth(74); + PlayerTalentFrameActiveSpecTabHighlight:SetHeight(86); + PlayerTalentFrameActiveSpecTabHighlight:SetTexture("Interface\\SpellBook\\SpellBook-SkillLineTab-Glow"); + end +end + +function PlayerTalentFrame_OnShow(self) + -- Stop buttons from flashing after skill up + SetButtonPulse(TalentMicroButton, 0, 1); + + PlaySound("TalentScreenOpen"); + UpdateMicroButtons(); + + if ( not selectedSpec ) then + -- if no spec was selected, try to select the active one + PlayerSpecTab_OnClick(activeSpec and specTabs[activeSpec] or specTabs[DEFAULT_TALENT_SPEC]); + else + PlayerTalentFrame_Refresh(); + end + + -- Set flag + if ( not GetCVarBool("talentFrameShown") ) then + SetCVar("talentFrameShown", 1); + UIFrameFlash(PlayerTalentFrameScrollButtonOverlay, 0.5, 0.5, 60); + end +end + +function PlayerTalentFrame_OnHide() + UpdateMicroButtons(); + PlaySound("TalentScreenClose"); + UIFrameFlashStop(PlayerTalentFrameScrollButtonOverlay); + -- clear caches + for _, info in next, talentSpecInfoCache do + wipe(info); + end + wipe(talentTabWidthCache); +end + +function PlayerTalentFrame_OnEvent(self, event, ...) + if ( event == "PLAYER_TALENT_UPDATE" or event == "PET_TALENT_UPDATE" ) then + PlayerTalentFrame_Refresh(); + elseif ( event == "PREVIEW_TALENT_POINTS_CHANGED" ) then + --local talentIndex, tabIndex, groupIndex, points = ...; + if ( selectedSpec and not specs[selectedSpec].pet ) then + PlayerTalentFrame_Refresh(); + end + elseif ( event == "PREVIEW_PET_TALENT_POINTS_CHANGED" ) then + --local talentIndex, tabIndex, groupIndex, points = ...; + if ( selectedSpec and specs[selectedSpec].pet ) then + PlayerTalentFrame_Refresh(); + end + elseif ( event == "UNIT_PORTRAIT_UPDATE" ) then + local unit = ...; + -- update the talent frame's portrait + if ( unit == PlayerTalentFramePortrait.unit ) then + SetPortraitTexture(PlayerTalentFramePortrait, unit); + end + -- update spec tabs' portraits + for _, frame in next, specTabs do + if ( frame.usingPortraitTexture ) then + local spec = specs[frame.specIndex]; + if ( unit == spec.unit and spec.portraitUnit ) then + SetPortraitTexture(frame:GetNormalTexture(), unit); + end + end + end + elseif ( event == "UNIT_PET" ) then + local summoner = ...; + if ( summoner == "player" ) then + if ( selectedSpec and specs[selectedSpec].pet ) then + -- if the selected spec is a pet spec... + local numTalentGroups = GetNumTalentGroups(false, true); + if ( numTalentGroups == 0 ) then + --...and a pet spec is not available, select the default spec + PlayerSpecTab_OnClick(activeSpec and specTabs[activeSpec] or specTabs[DEFAULT_TALENT_SPEC]); + return; + end + end + PlayerTalentFrame_Refresh(); + end + elseif ( event == "PLAYER_LEVEL_UP" ) then + if ( selectedSpec and not specs[selectedSpec].pet ) then + local level = ...; + PlayerTalentFrame_Update(level); + end + elseif ( event == "ACTIVE_TALENT_GROUP_CHANGED" ) then + MainMenuBar_ToPlayerArt(MainMenuBarArtFrame); + end +end + +function PlayerTalentFrame_Refresh() + local selectedTab = PanelTemplates_GetSelectedTab(PlayerTalentFrame); + if ( selectedTab == GLYPH_TALENT_TAB ) then + PlayerTalentFrame_ShowGlyphFrame(); + else + PlayerTalentFrame_HideGlyphFrame(); + end + TalentFrame_Update(PlayerTalentFrame); +end + +function PlayerTalentFrame_Update(playerLevel) + local activeTalentGroup, numTalentGroups = GetActiveTalentGroup(false, false), GetNumTalentGroups(false, false); + local activePetTalentGroup, numPetTalentGroups = GetActiveTalentGroup(false, true), GetNumTalentGroups(false, true); + + -- update specs + if ( not PlayerTalentFrame_UpdateSpecs(activeTalentGroup, numTalentGroups, activePetTalentGroup, numPetTalentGroups) ) then + -- the current spec is not selectable any more, discontinue updates + return; + end + + -- update tabs + if ( not PlayerTalentFrame_UpdateTabs(playerLevel) ) then + -- the current spec is not selectable any more, discontinue updates + return; + end + + -- set the frame portrait + SetPortraitTexture(PlayerTalentFramePortrait, PlayerTalentFrame.unit); + + -- update active talent group stuff + PlayerTalentFrame_UpdateActiveSpec(activeTalentGroup, numTalentGroups); + + -- update talent controls + PlayerTalentFrame_UpdateControls(activeTalentGroup, numTalentGroups); +end + +function PlayerTalentFrame_UpdateActiveSpec(activeTalentGroup, numTalentGroups) + -- set the active spec + activeSpec = DEFAULT_TALENT_SPEC; + for index, spec in next, specs do + if ( not spec.pet and spec.talentGroup == activeTalentGroup ) then + activeSpec = index; + break; + end + end + -- make UI adjustments + local spec = selectedSpec and specs[selectedSpec]; + + local hasMultipleTalentGroups = numTalentGroups > 1; + if ( spec and hasMultipleTalentGroups ) then + PlayerTalentFrameTitleText:SetText(spec.name); + else + PlayerTalentFrameTitleText:SetText(TALENTS); + end + + if ( selectedSpec == activeSpec and hasMultipleTalentGroups ) then + --PlayerTalentFrameActiveTalentGroupFrame:Show(); + else + PlayerTalentFrameActiveTalentGroupFrame:Hide(); + end +end + + +-- PlayerTalentFrameTalents + +function PlayerTalentFrameTalent_OnClick(self, button) + if ( IsModifiedClick("CHATLINK") ) then + local link = GetTalentLink(PanelTemplates_GetSelectedTab(PlayerTalentFrame), self:GetID(), + PlayerTalentFrame.inspect, PlayerTalentFrame.pet, PlayerTalentFrame.talentGroup, GetCVarBool("previewTalents")); + if ( link ) then + ChatEdit_InsertLink(link); + end + elseif ( selectedSpec and (activeSpec == selectedSpec or specs[selectedSpec].pet) ) then + -- only allow functionality if an active spec is selected + if ( button == "LeftButton" ) then + if ( GetCVarBool("previewTalents") ) then + AddPreviewTalentPoints(PanelTemplates_GetSelectedTab(PlayerTalentFrame), self:GetID(), 1, PlayerTalentFrame.pet, PlayerTalentFrame.talentGroup); + else + LearnTalent(PanelTemplates_GetSelectedTab(PlayerTalentFrame), self:GetID(), PlayerTalentFrame.pet, PlayerTalentFrame.talentGroup); + end + elseif ( button == "RightButton" ) then + if ( GetCVarBool("previewTalents") ) then + AddPreviewTalentPoints(PanelTemplates_GetSelectedTab(PlayerTalentFrame), self:GetID(), -1, PlayerTalentFrame.pet, PlayerTalentFrame.talentGroup); + end + end + end +end + +function PlayerTalentFrameTalent_OnEvent(self, event, ...) + if ( GameTooltip:IsOwned(self) ) then + GameTooltip:SetTalent(PanelTemplates_GetSelectedTab(PlayerTalentFrame), self:GetID(), + PlayerTalentFrame.inspect, PlayerTalentFrame.pet, PlayerTalentFrame.talentGroup, GetCVarBool("previewTalents")); + end +end + +function PlayerTalentFrameTalent_OnEnter(self) + GameTooltip:SetOwner(self, "ANCHOR_RIGHT"); + GameTooltip:SetTalent(PanelTemplates_GetSelectedTab(PlayerTalentFrame), self:GetID(), + PlayerTalentFrame.inspect, PlayerTalentFrame.pet, PlayerTalentFrame.talentGroup, GetCVarBool("previewTalents")); +end + + +-- Controls + +function PlayerTalentFrame_UpdateControls(activeTalentGroup, numTalentGroups) + local spec = selectedSpec and specs[selectedSpec]; + + local isActiveSpec = selectedSpec == activeSpec; + + -- show the multi-spec status frame if this is not a pet spec or we have more than one talent group + local showStatusFrame = not spec.pet and numTalentGroups > 1; + -- show the activate button if we were going to show the status frame but this is not the active spec + local showActivateButton = showStatusFrame and not isActiveSpec; + if ( showActivateButton ) then + PlayerTalentFrameActivateButton:Show(); + PlayerTalentFrameStatusFrame:Hide(); + else + PlayerTalentFrameActivateButton:Hide(); + if ( showStatusFrame ) then + PlayerTalentFrameStatusFrame:Show(); + else + PlayerTalentFrameStatusFrame:Hide(); + end + end + + local preview = GetCVarBool("previewTalents"); + + -- enable the control bar if this is the active spec, preview is enabled, and preview points were spent + local talentPoints = GetUnspentTalentPoints(false, spec.pet, spec.talentGroup); + if ( (spec.pet or isActiveSpec) and talentPoints > 0 and preview ) then + PlayerTalentFramePreviewBar:Show(); + -- enable accept/cancel buttons if preview talent points were spent + if ( GetGroupPreviewTalentPointsSpent(spec.pet, spec.talentGroup) > 0 ) then + PlayerTalentFrameLearnButton:Enable(); + PlayerTalentFrameResetButton:Enable(); + else + PlayerTalentFrameLearnButton:Disable(); + PlayerTalentFrameResetButton:Disable(); + end + -- squish all frames to make room for this bar + PlayerTalentFramePointsBar:SetPoint("BOTTOM", PlayerTalentFramePreviewBar, "TOP", 0, -4); + else + PlayerTalentFramePreviewBar:Hide(); + -- unsquish frames since the bar is now hidden + PlayerTalentFramePointsBar:SetPoint("BOTTOM", PlayerTalentFrame, "BOTTOM", 0, 81); + end +end + +function PlayerTalentFrameActivateButton_OnLoad(self) + self:SetWidth(self:GetTextWidth() + 40); +end + +function PlayerTalentFrameActivateButton_OnClick(self) + if ( selectedSpec ) then + local talentGroup = specs[selectedSpec].talentGroup; + if ( talentGroup ) then + SetActiveTalentGroup(talentGroup); + end + end +end + +function PlayerTalentFrameActivateButton_OnShow(self) + self:RegisterEvent("CURRENT_SPELL_CAST_CHANGED"); + PlayerTalentFrameActivateButton_Update(); +end + +function PlayerTalentFrameActivateButton_OnHide(self) + self:UnregisterEvent("CURRENT_SPELL_CAST_CHANGED"); +end + +function PlayerTalentFrameActivateButton_OnEvent(self, event, ...) + PlayerTalentFrameActivateButton_Update(); +end + +function PlayerTalentFrameActivateButton_Update() + local spec = selectedSpec and specs[selectedSpec]; + if ( spec and PlayerTalentFrameActivateButton:IsShown() ) then + -- if the activation spell is being cast currently, disable the activate button + if ( IsCurrentSpell(TALENT_ACTIVATION_SPELLS[spec.talentGroup]) ) then + PlayerTalentFrameActivateButton:Disable(); + else + PlayerTalentFrameActivateButton:Enable(); + end + end +end + +function PlayerTalentFrameResetButton_OnEnter(self) + GameTooltip:SetOwner(self, "ANCHOR_RIGHT"); + GameTooltip:SetText(TALENT_TOOLTIP_RESETTALENTGROUP); +end + +function PlayerTalentFrameResetButton_OnClick(self) + ResetGroupPreviewTalentPoints(PlayerTalentFrame.pet, PlayerTalentFrame.talentGroup); +end + +function PlayerTalentFrameLearnButton_OnEnter(self) + GameTooltip:SetOwner(self, "ANCHOR_RIGHT"); + GameTooltip:SetText(TALENT_TOOLTIP_LEARNTALENTGROUP); +end + +function PlayerTalentFrameLearnButton_OnClick(self) + StaticPopup_Show("CONFIRM_LEARN_PREVIEW_TALENTS"); +end + + +-- PlayerTalentFrameDownArrow + +function PlayerTalentFrameDownArrow_OnClick(self, button) + local parent = self:GetParent(); + parent:SetValue(parent:GetValue() + (parent:GetHeight() / 2)); + PlaySound("UChatScrollButton"); + UIFrameFlashStop(PlayerTalentFrameScrollButtonOverlay); +end + + +-- PlayerTalentFrameTab + +function PlayerTalentFrame_UpdateTabs(playerLevel) + local totalTabWidth = 0; + + local firstShownTab; + + -- setup talent tabs + local maxPointsSpent = 0; + local selectedTab = PanelTemplates_GetSelectedTab(PlayerTalentFrame); + local numTabs = GetNumTalentTabs(PlayerTalentFrame.inspect, PlayerTalentFrame.pet); + local tab; + for i = 1, MAX_TALENT_TABS do + -- clear cached widths + talentTabWidthCache[i] = 0; + tab = _G["PlayerTalentFrameTab"..i]; + if ( tab ) then + if ( i <= numTabs ) then + local name, icon, pointsSpent, background, previewPointsSpent = GetTalentTabInfo(i, PlayerTalentFrame.inspect, PlayerTalentFrame.pet, PlayerTalentFrame.talentGroup); + if ( i == selectedTab ) then + -- If tab is the selected tab set the points spent info + local displayPointsSpent = pointsSpent + previewPointsSpent; + PlayerTalentFrameSpentPointsText:SetFormattedText(MASTERY_POINTS_SPENT, name, HIGHLIGHT_FONT_COLOR_CODE..displayPointsSpent..FONT_COLOR_CODE_CLOSE); + PlayerTalentFrame.pointsSpent = pointsSpent; + PlayerTalentFrame.previewPointsSpent = previewPointsSpent; + end + tab:SetText(name); + PanelTemplates_TabResize(tab, 0); + -- record the text width to see if we need to display a tooltip + tab.textWidth = tab:GetTextWidth(); + -- record the tab widths for resizing later + talentTabWidthCache[i] = PanelTemplates_GetTabWidth(tab); + totalTabWidth = totalTabWidth + talentTabWidthCache[i]; + tab:Show(); + firstShownTab = firstShownTab or tab; + else + tab:Hide(); + tab.textWidth = 0; + end + end + end + + local spec = specs[selectedSpec]; + + -- setup glyph tabs, right now there is only one + playerLevel = playerLevel or UnitLevel("player"); + local meetsGlyphLevel = playerLevel >= SHOW_INSCRIPTION_LEVEL; + tab = _G["PlayerTalentFrameTab"..GLYPH_TALENT_TAB]; + if ( meetsGlyphLevel and spec.hasGlyphs ) then + tab:Show(); + firstShownTab = firstShownTab or tab; + PanelTemplates_TabResize(tab, 0); + talentTabWidthCache[GLYPH_TALENT_TAB] = PanelTemplates_GetTabWidth(tab); + totalTabWidth = totalTabWidth + talentTabWidthCache[GLYPH_TALENT_TAB]; + else + tab:Hide(); + talentTabWidthCache[GLYPH_TALENT_TAB] = 0; + end + local numGlyphTabs = 1; + + -- select the first shown tab if the selected tab does not exist for the selected spec + tab = _G["PlayerTalentFrameTab"..selectedTab]; + if ( tab and not tab:IsShown() ) then + if ( firstShownTab ) then + PlayerTalentFrameTab_OnClick(firstShownTab); + end + return false; + end + + -- readjust tab sizes to fit + local maxTotalTabWidth = PlayerTalentFrame:GetWidth(); + while ( totalTabWidth >= maxTotalTabWidth ) do + -- progressively shave 10 pixels off of the largest tab until they all fit within the max width + local largestTab = 1; + for i = 2, #talentTabWidthCache do + if ( talentTabWidthCache[largestTab] < talentTabWidthCache[i] ) then + largestTab = i; + end + end + -- shave the width + talentTabWidthCache[largestTab] = talentTabWidthCache[largestTab] - 10; + -- apply the shaved width + tab = _G["PlayerTalentFrameTab"..largestTab]; + PanelTemplates_TabResize(tab, 0, talentTabWidthCache[largestTab]); + -- now update the total width + totalTabWidth = totalTabWidth - 10; + end + + -- update the tabs + PanelTemplates_SetNumTabs(PlayerTalentFrame, numTabs + numGlyphTabs); + PanelTemplates_UpdateTabs(PlayerTalentFrame); + + return true; +end + +function PlayerTalentFrameTab_OnLoad(self) + self:SetFrameLevel(self:GetFrameLevel() + 2); +end + +function PlayerTalentFrameTab_OnClick(self) + local id = self:GetID(); + PanelTemplates_SetTab(PlayerTalentFrame, id); + PlayerTalentFrame_Refresh(); + PlaySound("igCharacterInfoTab"); +end + +function PlayerTalentFrameTab_OnEnter(self) + if ( self.textWidth and self.textWidth > self:GetFontString():GetWidth() ) then --We're ellipsizing. + GameTooltip:SetOwner(self, "ANCHOR_BOTTOM"); + GameTooltip:SetText(self:GetText()); + end +end + + +-- PlayerTalentTab + +function PlayerTalentTab_OnLoad(self) + PlayerTalentFrameTab_OnLoad(self); + + self:RegisterEvent("PLAYER_LEVEL_UP"); +end + +function PlayerTalentTab_OnClick(self) + PlayerTalentFrameTab_OnClick(self); + for i=1, MAX_TALENT_TABS do + SetButtonPulse(_G["PlayerTalentFrameTab"..i], 0, 0); + end +end + +function PlayerTalentTab_OnEvent(self, event, ...) + if ( UnitLevel("player") == (SHOW_TALENT_LEVEL - 1) and PanelTemplates_GetSelectedTab(PlayerTalentFrame) ~= self:GetID() ) then + SetButtonPulse(self, 60, 0.75); + end +end + +function PlayerTalentTab_GetBestDefaultTab(specIndex) + if ( not specIndex ) then + return DEFAULT_TALENT_TAB; + end + + local spec = specs[specIndex]; + if ( not spec ) then + return DEFAULT_TALENT_TAB; + end + + local specInfoCache = talentSpecInfoCache[specIndex]; + TalentFrame_UpdateSpecInfoCache(specInfoCache, false, spec.pet, spec.talentGroup); + if ( specInfoCache.primaryTabIndex > 0 ) then + return talentSpecInfoCache[specIndex].primaryTabIndex; + else + return DEFAULT_TALENT_TAB; + end +end + + +-- PlayerGlyphTab + +function PlayerGlyphTab_OnLoad(self) + PlayerTalentFrameTab_OnLoad(self); + + self:RegisterEvent("PLAYER_LEVEL_UP"); + GLYPH_TALENT_TAB = self:GetID(); + -- we can record the text width for the glyph tab now since it never changes + self.textWidth = self:GetTextWidth(); +end + +function PlayerGlyphTab_OnClick(self) + PlayerTalentFrameTab_OnClick(self); + SetButtonPulse(_G["PlayerTalentFrameTab"..GLYPH_TALENT_TAB], 0, 0); +end + +function PlayerGlyphTab_OnEvent(self, event, ...) + if ( UnitLevel("player") == (SHOW_INSCRIPTION_LEVEL - 1) and PanelTemplates_GetSelectedTab(PlayerTalentFrame) ~= self:GetID() ) then + SetButtonPulse(self, 60, 0.75); + end +end + + +-- Specs + +-- PlayerTalentFrame_UpdateSpecs is a helper function for PlayerTalentFrame_Update. +-- Returns true on a successful update, false otherwise. An update may fail if the currently +-- selected tab is no longer selectable. In this case, the first selectable tab will be selected. +function PlayerTalentFrame_UpdateSpecs(activeTalentGroup, numTalentGroups, activePetTalentGroup, numPetTalentGroups) + -- set the active spec highlight to be hidden initially, if a spec is the active one then it will + -- be shown in PlayerSpecTab_Update + PlayerTalentFrameActiveSpecTabHighlight:Hide(); + + -- update each of the spec tabs + local firstShownTab, lastShownTab; + local numShown = 0; + local offsetX = 0; + for i = 1, numSpecTabs do + local frame = _G["PlayerSpecTab"..i]; + local specIndex = frame.specIndex; + local spec = specs[specIndex]; + if ( PlayerSpecTab_Update(frame, activeTalentGroup, numTalentGroups, activePetTalentGroup, numPetTalentGroups) ) then + firstShownTab = firstShownTab or frame; + numShown = numShown + 1; + frame:ClearAllPoints(); + -- set an offsetX fudge if we're the selected tab, otherwise use the previous offsetX + offsetX = specIndex == selectedSpec and SELECTEDSPEC_OFFSETX or offsetX; + if ( numShown == 1 ) then + --...start the first tab off at a base location + frame:SetPoint("TOPLEFT", frame:GetParent(), "TOPRIGHT", -32 + offsetX, -65); + -- we'll need to negate the offsetX after the first tab so all subsequent tabs offset + -- to their default positions + offsetX = -offsetX; + else + --...offset subsequent tabs from the previous one + if ( spec.pet ~= specs[lastShownTab.specIndex].pet ) then + frame:SetPoint("TOPLEFT", lastShownTab, "BOTTOMLEFT", 0 + offsetX, -39); + else + frame:SetPoint("TOPLEFT", lastShownTab, "BOTTOMLEFT", 0 + offsetX, -22); + end + end + lastShownTab = frame; + else + -- if the selected tab is not shown then clear out the selected spec + if ( specIndex == selectedSpec ) then + selectedSpec = nil; + end + end + end + + if ( not selectedSpec ) then + if ( firstShownTab ) then + PlayerSpecTab_OnClick(firstShownTab); + end + return false; + end + + if ( numShown == 1 and lastShownTab ) then + -- if we're only showing one tab, we might as well hide it since it doesn't need to be there + lastShownTab:Hide(); + end + + return true; +end + +function PlayerSpecTab_Update(self, ...) + local activeTalentGroup, numTalentGroups, activePetTalentGroup, numPetTalentGroups = ...; + + local specIndex = self.specIndex; + local spec = specs[specIndex]; + + -- determine whether or not we need to hide the tab + local canShow; + if ( spec.pet ) then + canShow = spec.talentGroup <= numPetTalentGroups; + else + canShow = spec.talentGroup <= numTalentGroups; + end + if ( not canShow ) then + self:Hide(); + return false; + end + + local isSelectedSpec = specIndex == selectedSpec; + local isActiveSpec = not spec.pet and spec.talentGroup == activeTalentGroup; + local normalTexture = self:GetNormalTexture(); + + -- set the background based on whether or not we're selected + if ( isSelectedSpec and (SELECTEDSPEC_DISPLAYTYPE == "PUSHED_OUT" or SELECTEDSPEC_DISPLAYTYPE == "PUSHED_OUT_CHECKED") ) then + local name = self:GetName(); + local backgroundTexture = _G[name.."Background"]; + backgroundTexture:SetTexture("Interface\\TalentFrame\\UI-TalentFrame-SpecTab"); + backgroundTexture:SetPoint("TOPLEFT", self, "TOPLEFT", -13, 11); + if ( SELECTEDSPEC_DISPLAYTYPE == "PUSHED_OUT_CHECKED" ) then + self:GetCheckedTexture():Show(); + else + self:GetCheckedTexture():Hide(); + end + else + local name = self:GetName(); + local backgroundTexture = _G[name.."Background"]; + backgroundTexture:SetTexture("Interface\\SpellBook\\SpellBook-SkillLineTab"); + backgroundTexture:SetPoint("TOPLEFT", self, "TOPLEFT", -3, 11); + end + + -- update the active spec info + local hasMultipleTalentGroups = numTalentGroups > 1; + if ( isActiveSpec and hasMultipleTalentGroups ) then + PlayerTalentFrameActiveSpecTabHighlight:ClearAllPoints(); + if ( ACTIVESPEC_DISPLAYTYPE == "BLUE" ) then + PlayerTalentFrameActiveSpecTabHighlight:SetParent(self); + PlayerTalentFrameActiveSpecTabHighlight:SetPoint("TOPLEFT", self, "TOPLEFT", -13, 14); + PlayerTalentFrameActiveSpecTabHighlight:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", 15, -14); + PlayerTalentFrameActiveSpecTabHighlight:Show(); + elseif ( ACTIVESPEC_DISPLAYTYPE == "GOLD_INSIDE" ) then + PlayerTalentFrameActiveSpecTabHighlight:SetParent(self); + PlayerTalentFrameActiveSpecTabHighlight:SetAllPoints(self); + PlayerTalentFrameActiveSpecTabHighlight:Show(); + elseif ( ACTIVESPEC_DISPLAYTYPE == "GOLD_BACKGROUND" ) then + PlayerTalentFrameActiveSpecTabHighlight:SetParent(self); + PlayerTalentFrameActiveSpecTabHighlight:SetPoint("TOPLEFT", self, "TOPLEFT", -3, 20); + PlayerTalentFrameActiveSpecTabHighlight:Show(); + else + PlayerTalentFrameActiveSpecTabHighlight:Hide(); + end + end + +--[[ + if ( not spec.pet ) then + SetDesaturation(normalTexture, not isActiveSpec); + end +--]] + + -- update the spec info cache + TalentFrame_UpdateSpecInfoCache(talentSpecInfoCache[specIndex], false, spec.pet, spec.talentGroup); + + -- update spec tab icon + self.usingPortraitTexture = false; + if ( hasMultipleTalentGroups ) then + local specInfoCache = talentSpecInfoCache[specIndex]; + local primaryTabIndex = specInfoCache.primaryTabIndex; + if ( primaryTabIndex > 0 ) then + -- the spec had a primary tab, set the icon to that tab's icon + normalTexture:SetTexture(specInfoCache[primaryTabIndex].icon); + else + if ( specInfoCache.numTabs > 1 and specInfoCache.totalPointsSpent > 0 ) then + -- the spec is only considered a hybrid if the spec had more than one tab and at least + -- one point was spent in one of the tabs + normalTexture:SetTexture(TALENT_HYBRID_ICON); + else + if ( spec.defaultSpecTexture ) then + -- the spec is probably untalented...set to the default spec texture if we have one + normalTexture:SetTexture(spec.defaultSpecTexture); + elseif ( spec.portraitUnit ) then + -- last check...if there is no default spec texture, try the portrait unit + SetPortraitTexture(normalTexture, spec.portraitUnit); + self.usingPortraitTexture = true; + end + end + end + else + if ( spec.portraitUnit ) then + -- set to the portrait texture if we only have one talent group + SetPortraitTexture(normalTexture, spec.portraitUnit); + self.usingPortraitTexture = true; + end + end +--[[ + -- update overlay icon + local name = self:GetName(); + local overlayIcon = _G[name.."OverlayIcon"]; + if ( overlayIcon ) then + if ( hasMultipleTalentGroups ) then + overlayIcon:Show(); + else + overlayIcon:Hide(); + end + end +--]] + self:Show(); + return true; +end + +function PlayerSpecTab_Load(self, specIndex) + self.specIndex = specIndex; + specTabs[specIndex] = self; + numSpecTabs = numSpecTabs + 1; + + -- set the spec's portrait + local spec = specs[self.specIndex]; + if ( spec.portraitUnit ) then + SetPortraitTexture(self:GetNormalTexture(), spec.portraitUnit); + self.usingPortraitTexture = true; + else + self.usingPortraitTexture = false; + end + + -- set the checked texture + if ( SELECTEDSPEC_DISPLAYTYPE == "BLUE" ) then + local checkedTexture = self:GetCheckedTexture(); + checkedTexture:SetTexture("Interface\\Buttons\\UI-Button-Outline"); + checkedTexture:SetWidth(64); + checkedTexture:SetHeight(64); + checkedTexture:ClearAllPoints(); + checkedTexture:SetPoint("CENTER", self, "CENTER", 0, 0); + elseif ( SELECTEDSPEC_DISPLAYTYPE == "GOLD_INSIDE" ) then + local checkedTexture = self:GetCheckedTexture(); + checkedTexture:SetTexture("Interface\\Buttons\\CheckButtonHilight"); + end + + local activeTalentGroup, numTalentGroups = GetActiveTalentGroup(false, false), GetNumTalentGroups(false, false); + local activePetTalentGroup, numPetTalentGroups = GetActiveTalentGroup(false, true), GetNumTalentGroups(false, true); + PlayerSpecTab_Update(self, activeTalentGroup, numTalentGroups, activePetTalentGroup, numPetTalentGroups); +end + +function PlayerSpecTab_OnClick(self) + -- set all specs as unchecked initially + for _, frame in next, specTabs do + frame:SetChecked(nil); + end + + -- check ourselves (before we wreck ourselves) + self:SetChecked(1); + + -- update the selected to this spec + local specIndex = self.specIndex; + selectedSpec = specIndex; + + -- set data on the talent frame + local spec = specs[specIndex]; + PlayerTalentFrame.pet = spec.pet; + PlayerTalentFrame.unit = spec.unit; + PlayerTalentFrame.talentGroup = spec.talentGroup; + + -- select a tab if one is not already selected + if ( not PanelTemplates_GetSelectedTab(PlayerTalentFrame) ) then + PanelTemplates_SetTab(PlayerTalentFrame, PlayerTalentTab_GetBestDefaultTab(specIndex)); + end + + -- update the talent frame + PlayerTalentFrame_Refresh(); +end + +function PlayerSpecTab_OnEnter(self) + local specIndex = self.specIndex; + local spec = specs[specIndex]; + if ( spec.tooltip ) then + GameTooltip:SetOwner(self, "ANCHOR_RIGHT"); + -- name + if ( GetNumTalentGroups(false, true) <= 1 and GetNumTalentGroups(false, false) <= 1 ) then + -- set the tooltip to be the unit's name + GameTooltip:AddLine(UnitName(spec.unit), NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b); + else + -- set the tooltip to be the spec name + GameTooltip:AddLine(spec.tooltip); + if ( self.specIndex == activeSpec ) then + -- add text to indicate that this spec is active + GameTooltip:AddLine(TALENT_ACTIVE_SPEC_STATUS, GREEN_FONT_COLOR.r, GREEN_FONT_COLOR.g, GREEN_FONT_COLOR.b); + end + end + -- points spent + local pointsColor; + for index, info in ipairs(talentSpecInfoCache[specIndex]) do + if ( info.name ) then + -- assign a special color to a tab that surpasses the max points spent threshold + if ( talentSpecInfoCache[specIndex].primaryTabIndex == index ) then + pointsColor = GREEN_FONT_COLOR; + else + pointsColor = HIGHLIGHT_FONT_COLOR; + end + GameTooltip:AddDoubleLine( + info.name, + info.pointsSpent, + HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b, + pointsColor.r, pointsColor.g, pointsColor.b, + 1 + ); + end + end + GameTooltip:Show(); + end +end + diff --git a/reference/AddOns/Blizzard_TalentUI/Blizzard_TalentUI.toc b/reference/AddOns/Blizzard_TalentUI/Blizzard_TalentUI.toc new file mode 100644 index 0000000..37e1789 --- /dev/null +++ b/reference/AddOns/Blizzard_TalentUI/Blizzard_TalentUI.toc @@ -0,0 +1,6 @@ +## Interface: 30300 +## Title: Blizzard Talent UI +## Secure: 1 +## LoadOnDemand: 1 +Blizzard_TalentUI.xml +Localization.lua diff --git a/reference/AddOns/Blizzard_TalentUI/Blizzard_TalentUI.xml b/reference/AddOns/Blizzard_TalentUI/Blizzard_TalentUI.xml new file mode 100644 index 0000000..46bc3b8 --- /dev/null +++ b/reference/AddOns/Blizzard_TalentUI/Blizzard_TalentUI.xml @@ -0,0 +1,780 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/reference/FrameXML/BattlefieldFrame.lua b/reference/FrameXML/BattlefieldFrame.lua new file mode 100644 index 0000000..23d75fa --- /dev/null +++ b/reference/FrameXML/BattlefieldFrame.lua @@ -0,0 +1,807 @@ +-- MoonWell: returns display faction (opposite for traitors) +local function MoonWell_GetDisplayFaction() + local f = UnitFactionGroup("player"); + if MoonWell_IsTraitor and f then + return f == "Alliance" and "Horde" or "Alliance"; + end + return f; +end + +BATTLEFIELD_ZONES_DISPLAYED = 5; +BATTLEFIELD_ZONES_HEIGHT = 20; +BATTLEFIELD_SHUTDOWN_TIMER = 0; +BATTLEFIELD_TIMER_THRESHOLDS = {600, 300, 60, 15}; +BATTLEFIELD_TIMER_THRESHOLD_INDEX = 1; +PREVIOUS_BATTLEFIELD_MOD = 0; +BATTLEFIELD_TIMER_DELAY = 3; +BATTLEFIELD_MAP_WIDTH = 320; +BATTLEFIELD_MAP_HEIGHT = 213; +MAX_BATTLEFIELD_QUEUES = 2; +MAX_WORLD_PVP_QUEUES = 1; +CURRENT_BATTLEFIELD_QUEUES = {}; +PREVIOUS_BATTLEFIELD_QUEUES = {}; + +local BATTLEFIELD_FRAME_FADE_TIME = 0.15 + +function BattlefieldFrame_OnLoad (self) + self:RegisterEvent("PLAYER_ENTERING_WORLD"); + self:RegisterEvent("BATTLEFIELDS_SHOW"); + self:RegisterEvent("BATTLEFIELDS_CLOSED"); + self:RegisterEvent("UPDATE_BATTLEFIELD_STATUS"); + self:RegisterEvent("PARTY_LEADER_CHANGED"); + self:RegisterEvent("ZONE_CHANGED"); + self:RegisterEvent("ZONE_CHANGED_NEW_AREA"); + + self:RegisterEvent("BATTLEFIELD_MGR_QUEUE_REQUEST_RESPONSE"); + self:RegisterEvent("BATTLEFIELD_MGR_QUEUE_INVITE"); + self:RegisterEvent("BATTLEFIELD_MGR_ENTRY_INVITE"); + self:RegisterEvent("BATTLEFIELD_MGR_EJECT_PENDING"); + self:RegisterEvent("BATTLEFIELD_MGR_EJECTED"); + self:RegisterEvent("BATTLEFIELD_MGR_ENTERED"); + + BattlefieldFrame.timerDelay = 0; +end + +function BattlefieldFrame_OnEvent (self, event, ...) + if ( event == "PLAYER_ENTERING_WORLD" ) then + MiniMapBattlefieldDropDown_OnLoad(); + BattlefieldFrame_UpdateStatus(false, nil); + elseif ( event == "BATTLEFIELDS_SHOW" ) then + if ( not IsBattlefieldArena() ) then + ShowUIPanel(BattlefieldFrame); + + -- Default to first available + SetSelectedBattlefield(0); + + if ( not BattlefieldFrame:IsShown() ) then + CloseBattlefield(); + return; + end + UpdateMicroButtons(); + BattlefieldFrame_Update(); + end + elseif ( event == "BATTLEFIELDS_CLOSED" ) then + HideUIPanel(BattlefieldFrame); + elseif ( event == "UPDATE_BATTLEFIELD_STATUS" or event == "ZONE_CHANGED_NEW_AREA" or event == "ZONE_CHANGED") then + local arg1 = ... + BattlefieldFrame_UpdateStatus(false, arg1); + BattlefieldFrame_Update(); + elseif ( event == "BATTLEFIELD_MGR_QUEUE_REQUEST_RESPONSE" ) then + local battleID, accepted, warmup, inArea, loggingIn = ...; + if(not loggingIn) then + if(accepted) then + if(warmup) then + StaticPopup_Show("BFMGR_CONFIRM_WORLD_PVP_QUEUED_WARMUP", "Wintergrasp", nil, arg1); + elseif (inArea) then + StaticPopup_Show("BFMGR_EJECT_PENDING", "Wintergrasp", nil, arg1); + else + StaticPopup_Show("BFMGR_CONFIRM_WORLD_PVP_QUEUED", "Wintergrasp", nil, arg1); + end + else + StaticPopup_Show("BFMGR_DENY_WORLD_PVP_QUEUED", "Wintergrasp", nil, arg1); + end + end + BattlefieldFrame_UpdateStatus(false); + BattlefieldFrame_Update(); + elseif ( event == "BATTLEFIELD_MGR_EJECT_PENDING" ) then + local battleID, remote = ...; + if(remote) then + local dialog = StaticPopup_Show("BFMGR_EJECT_PENDING_REMOTE", "Wintergrasp", nil, arg1); + else + local dialog = StaticPopup_Show("BFMGR_EJECT_PENDING", "Wintergrasp", nil, arg1); + end + BattlefieldFrame_UpdateStatus(false); + BattlefieldFrame_Update(); + elseif ( event == "BATTLEFIELD_MGR_EJECTED" ) then + local battleID, playerExited, relocated, battleActive, lowLevel = ...; + StaticPopup_Hide("BFMGR_INVITED_TO_QUEUE"); + StaticPopup_Hide("BFMGR_INVITED_TO_QUEUE_WARMUP"); + StaticPopup_Hide("BFMGR_INVITED_TO_ENTER"); + StaticPopup_Hide("BFMGR_EJECT_PENDING"); + if(lowLevel) then + local dialog = StaticPopup_Show("BFMGR_PLAYER_LOW_LEVEL", "Wintergrasp", nil, arg1); + elseif (playerExited and battleActive and not relocated) then + local dialog = StaticPopup_Show("BFMGR_PLAYER_EXITED_BATTLE", "Wintergrasp", nil, arg1); + end + BattlefieldFrame_UpdateStatus(false); + BattlefieldFrame_Update(); + elseif ( event == "BATTLEFIELD_MGR_QUEUE_INVITE" ) then + local battleID, warmup = ...; + if(warmup) then + local dialog = StaticPopup_Show("BFMGR_INVITED_TO_QUEUE_WARMUP", "Wintergrasp", nil, arg1); + else + local dialog = StaticPopup_Show("BFMGR_INVITED_TO_QUEUE", "Wintergrasp", nil, arg1); + end + StaticPopup_Hide("BFMGR_EJECT_PENDING"); + BattlefieldFrame_UpdateStatus(false); + BattlefieldFrame_Update(); + elseif ( event == "BATTLEFIELD_MGR_ENTRY_INVITE" ) then + local battleID = ...; + local dialog = StaticPopup_Show("BFMGR_INVITED_TO_ENTER", "Wintergrasp", nil, arg1); + StaticPopup_Hide("BFMGR_EJECT_PENDING"); + BattlefieldFrame_UpdateStatus(false); + BattlefieldFrame_Update(); + elseif ( event == "BATTLEFIELD_MGR_ENTERED" ) then + StaticPopup_Hide("BFMGR_INVITED_TO_QUEUE"); + StaticPopup_Hide("BFMGR_INVITED_TO_QUEUE_WARMUP"); + StaticPopup_Hide("BFMGR_INVITED_TO_ENTER"); + StaticPopup_Hide("BFMGR_EJECT_PENDING"); + BattlefieldFrame_UpdateStatus(false); + BattlefieldFrame_Update(); + end + + if ( event == "PARTY_LEADER_CHANGED" ) then + BattlefieldFrame_Update(); + end +end + +function BattlefieldTimerFrame_OnUpdate(self, elapsed) + local keepUpdating = false; + if ( BATTLEFIELD_SHUTDOWN_TIMER > 0 ) then + keepUpdating = true; + BattlefieldIconText:Hide(); + else + local lowestExpiration = 0; + for i = 1, MAX_BATTLEFIELD_QUEUES do + local expiration = GetBattlefieldPortExpiration(i); + if ( expiration > 0 ) then + if( expiration < lowestExpiration or lowestExpiration == 0 ) then + lowestExpiration = expiration; + end + + keepUpdating = true; + end + end + + if( lowestExpiration > 0 and lowestExpiration <= 10 ) then + BattlefieldIconText:SetText(lowestExpiration); + BattlefieldIconText:Show(); + else + BattlefieldIconText:Hide(); + end + end + + if ( not keepUpdating ) then + BattlefieldTimerFrame:SetScript("OnUpdate", nil); + return; + end + + local frame = BattlefieldFrame + + BATTLEFIELD_SHUTDOWN_TIMER = BATTLEFIELD_SHUTDOWN_TIMER - elapsed; + -- Set the time for the score frame + WorldStateScoreFrameTimer:SetFormattedText(SecondsToTimeAbbrev(BATTLEFIELD_SHUTDOWN_TIMER)); + -- Check if I should send a message only once every 3 seconds (BATTLEFIELD_TIMER_DELAY) + frame.timerDelay = frame.timerDelay + elapsed; + if ( frame.timerDelay < BATTLEFIELD_TIMER_DELAY ) then + return; + else + frame.timerDelay = 0 + end + + local threshold = BATTLEFIELD_TIMER_THRESHOLDS[BATTLEFIELD_TIMER_THRESHOLD_INDEX]; + if ( BATTLEFIELD_SHUTDOWN_TIMER > 0 ) then + if ( BATTLEFIELD_SHUTDOWN_TIMER < threshold and BATTLEFIELD_TIMER_THRESHOLD_INDEX ~= #BATTLEFIELD_TIMER_THRESHOLDS ) then + -- If timer past current threshold advance to the next one + BATTLEFIELD_TIMER_THRESHOLD_INDEX = BATTLEFIELD_TIMER_THRESHOLD_INDEX + 1; + else + -- See if time should be posted + local currentMod = floor(BATTLEFIELD_SHUTDOWN_TIMER/threshold); + if ( PREVIOUS_BATTLEFIELD_MOD ~= currentMod ) then + -- Print message + local info = ChatTypeInfo["SYSTEM"]; + local string; + if ( GetBattlefieldWinner() ) then + local isArena = IsActiveBattlefieldArena(); + if ( isArena ) then + string = format(ARENA_COMPLETE_MESSAGE, SecondsToTime(ceil(BATTLEFIELD_SHUTDOWN_TIMER/threshold) * threshold)); + else + string = format(BATTLEGROUND_COMPLETE_MESSAGE, SecondsToTime(ceil(BATTLEFIELD_SHUTDOWN_TIMER/threshold) * threshold)); + end + else + string = format(INSTANCE_SHUTDOWN_MESSAGE, SecondsToTime(ceil(BATTLEFIELD_SHUTDOWN_TIMER/threshold) * threshold)); + end + DEFAULT_CHAT_FRAME:AddMessage(string, info.r, info.g, info.b, info.id); + PREVIOUS_BATTLEFIELD_MOD = currentMod; + end + end + else + BATTLEFIELD_SHUTDOWN_TIMER = 0; + end +end + +function BattlefieldFrame_UpdateStatus(tooltipOnly, mapIndex) + local status, mapName, instanceID, queueID, levelRangeMin, levelRangeMax, teamSize, registeredMatch; + local numberQueues = 0; + local waitTime, timeInQueue; + local tooltip; + local showRightClickText; + BATTLEFIELD_SHUTDOWN_TIMER = 0; + + -- Reset tooltip + MiniMapBattlefieldFrame.tooltip = nil; + MiniMapBattlefieldFrame.waitTime = {}; + MiniMapBattlefieldFrame.status = nil; + + -- Copy current queues into previous queues + if ( not tooltipOnly ) then + PREVIOUS_BATTLEFIELD_QUEUES = {}; + for index, value in pairs(CURRENT_BATTLEFIELD_QUEUES) do + tinsert(PREVIOUS_BATTLEFIELD_QUEUES, value); + end + CURRENT_BATTLEFIELD_QUEUES = {}; + end + + if ( CanHearthAndResurrectFromArea() ) then + if ( not MiniMapBattlefieldFrame.inWorldPVPArea ) then + MiniMapBattlefieldFrame.inWorldPVPArea = true; + UIFrameFadeIn(MiniMapBattlefieldFrame, BATTLEFIELD_FRAME_FADE_TIME); + BattlegroundShineFadeIn(); + end + else + MiniMapBattlefieldFrame.inWorldPVPArea = false; + end + + for i=1, MAX_BATTLEFIELD_QUEUES do + status, mapName, instanceID, levelRangeMin, levelRangeMax, teamSize, registeredMatch = GetBattlefieldStatus(i); + if ( mapName ) then + if ( instanceID ~= 0 ) then + mapName = mapName.." "..instanceID; + end + if ( teamSize ~= 0 ) then + if ( registeredMatch ) then + mapName = ARENA_RATED_MATCH.." "..format(PVP_TEAMSIZE, teamSize, teamSize); + else + mapName = ARENA_CASUAL.." "..format(PVP_TEAMSIZE, teamSize, teamSize); + end + end + end + tooltip = nil; + MiniMapBattlefieldFrame_isArena(); + if ( not tooltipOnly and (status ~= "confirm") ) then + StaticPopup_Hide("CONFIRM_BATTLEFIELD_ENTRY", i); + end + + if ( status ~= "none" ) then + numberQueues = numberQueues+1; + if ( status == "queued" ) then + -- Update queue info show button on minimap + waitTime = GetBattlefieldEstimatedWaitTime(i); + timeInQueue = GetBattlefieldTimeWaited(i)/1000; + if ( waitTime == 0 ) then + waitTime = QUEUE_TIME_UNAVAILABLE; + elseif ( waitTime < 60000 ) then + waitTime = LESS_THAN_ONE_MINUTE; + else + waitTime = SecondsToTime(waitTime/1000, 1); + end + MiniMapBattlefieldFrame.waitTime[i] = waitTime; + tooltip = format(BATTLEFIELD_IN_QUEUE, mapName, waitTime, SecondsToTime(timeInQueue)); + + if ( not tooltipOnly ) then + if ( not IsAlreadyInQueue(mapName) ) then + UIFrameFadeIn(MiniMapBattlefieldFrame, BATTLEFIELD_FRAME_FADE_TIME); + BattlegroundShineFadeIn(); + PlaySound("PVPENTERQUEUE"); + end + tinsert(CURRENT_BATTLEFIELD_QUEUES, mapName); + end + showRightClickText = 1; + elseif ( status == "confirm" ) then + -- Have been accepted show enter battleground dialog + local seconds = SecondsToTime(GetBattlefieldPortExpiration(i)); + if ( seconds ~= "" ) then + tooltip = format(BATTLEFIELD_QUEUE_CONFIRM, mapName, seconds); + else + tooltip = format(BATTLEFIELD_QUEUE_PENDING_REMOVAL, mapName); + end + if ( (i==mapIndex) and (not tooltipOnly) ) then + local dialog = StaticPopup_Show("CONFIRM_BATTLEFIELD_ENTRY", mapName, nil, i); + PlaySound("PVPTHROUGHQUEUE"); + MiniMapBattlefieldFrame:Show(); + end + showRightClickText = 1; + BattlefieldTimerFrame:SetScript("OnUpdate", BattlefieldTimerFrame_OnUpdate); + elseif ( status == "active" ) then + -- In the battleground + if ( teamSize ~= 0 ) then + tooltip = mapName; + else + tooltip = format(BATTLEFIELD_IN_BATTLEFIELD, mapName); + end + BATTLEFIELD_SHUTDOWN_TIMER = GetBattlefieldInstanceExpiration()/1000; + if ( BATTLEFIELD_SHUTDOWN_TIMER > 0 ) then + BattlefieldTimerFrame:SetScript("OnUpdate", BattlefieldTimerFrame_OnUpdate); + end + BATTLEFIELD_TIMER_THRESHOLD_INDEX = 1; + PREVIOUS_BATTLEFIELD_MOD = 0; + MiniMapBattlefieldFrame.status = status; + elseif ( status == "error" ) then + -- Should never happen haha + end + if ( tooltip ) then + if ( MiniMapBattlefieldFrame.tooltip ) then + MiniMapBattlefieldFrame.tooltip = MiniMapBattlefieldFrame.tooltip.."\n\n"..tooltip; + else + MiniMapBattlefieldFrame.tooltip = tooltip; + end + end + end + end + + for i=1, MAX_WORLD_PVP_QUEUES do + status, mapName, queueID = GetWorldPVPQueueStatus(i); + if ( status ~= "none" ) then + numberQueues = numberQueues + 1; + end + if ( status == "queued" or status == "confirm" ) then + if ( status == "queued" ) then + tooltip = format(BATTLEFIELD_IN_QUEUE_SIMPLE, mapName); + elseif ( status == "confirm" ) then + tooltip = format(BATTLEFIELD_QUEUE_CONFIRM_SIMPLE, mapName); + end + + if ( MiniMapBattlefieldFrame.tooltip ) then + MiniMapBattlefieldFrame.tooltip = MiniMapBattlefieldFrame.tooltip.."\n\n"..tooltip; + else + MiniMapBattlefieldFrame.tooltip = tooltip; + end + end + end + + -- See if should add right click message + if ( MiniMapBattlefieldFrame.tooltip and showRightClickText ) then + MiniMapBattlefieldFrame.tooltip = MiniMapBattlefieldFrame.tooltip.."\n"..RIGHT_CLICK_MESSAGE; + elseif ( MiniMapBattlefieldFrame_isArena() ) then + MiniMapBattlefieldFrame.tooltip = MiniMapBattlefieldFrame.tooltip; + end + + if ( not tooltipOnly ) then + MiniMapBattlefieldFrame_isArena(); + if ( numberQueues == 0 and (not CanHearthAndResurrectFromArea()) ) then + -- Clear everything out + MiniMapBattlefieldFrame:Hide(); + else + MiniMapBattlefieldFrame:Show(); + end + end + BattlefieldFrame.numQueues = numberQueues; +end + +function MiniMapBattlefieldFrame_isArena() + -- Set minimap icon here since it bugs out on login + local status, mapName, instanceID, levelRangeMin, levelRangeMax, teamSize, registeredMatch = GetBattlefieldStatus(1); + local isArena, isRegistered = IsActiveBattlefieldArena(); + if ( registeredMatch or isRegistered ) then + MiniMapBattlefieldIcon:SetTexture("Interface\\PVPFrame\\PVP-ArenaPoints-Icon"); + MiniMapBattlefieldIcon:SetWidth(19); + MiniMapBattlefieldIcon:SetHeight(19); + MiniMapBattlefieldIcon:SetPoint("CENTER", "MiniMapBattlefieldFrame", "CENTER", -1, 2); + elseif ( UnitFactionGroup("player") ) then + MiniMapBattlefieldIcon:SetTexture("Interface\\BattlefieldFrame\\Battleground-"..MoonWell_GetDisplayFaction()); + MiniMapBattlefieldIcon:SetTexCoord(0, 1, 0, 1); + MiniMapBattlefieldIcon:SetWidth(32); + MiniMapBattlefieldIcon:SetHeight(32); + MiniMapBattlefieldIcon:SetPoint("CENTER", "MiniMapBattlefieldFrame", "CENTER", -1, 0); + end +end + +function BattlefieldFrame_Update() + local zoneIndex; + local zoneOffset = FauxScrollFrame_GetOffset(BattlefieldListScrollFrame); + local playerLevel = UnitLevel("player"); + local button, buttonStatus; + local instanceID; + local mapName, mapDescription, maxGroup = GetBattlefieldInfo(); + local factionTexture = "Interface\\PVPFrame\\PVP-Currency-"..MoonWell_GetDisplayFaction(); + + if ( not mapName ) then + return; + end + + -- Set title text + BattlefieldFrameFrameLabel:SetText(mapName); + -- Set the Join as Group text based on the limits of which instances can join as group. + if ( maxGroup and maxGroup == 5 ) then + BattlefieldFrameGroupJoinButton:SetText(JOIN_AS_PARTY); + else + BattlefieldFrameGroupJoinButton:SetText(JOIN_AS_GROUP); + end + -- Setup instance buttons + -- add one to battlefields because of the fake "first available" button + local numBattlefields = GetNumBattlefields() + 1; + for i=1, BATTLEFIELD_ZONES_DISPLAYED, 1 do + zoneIndex = zoneOffset + i; + button = _G["BattlefieldZone"..i]; + + if ( zoneIndex == 1 ) then + -- The first entry in the list is always "first available" + button:SetText(FIRST_AVAILABLE); + -- Set tooltip + button.title = FIRST_AVAILABLE; + button.tooltip = NEWBIE_TOOLTIP_FIRST_AVAILABLE; + button:Show(); + elseif ( zoneIndex > numBattlefields ) then + button:Hide(); + else + instanceID = GetBattlefieldInstanceInfo(zoneIndex - 1); + button:SetText(mapName.." "..instanceID); + -- Set tooltip + button.title = mapName.." "..instanceID; + button.tooltip = NEWBIE_TOOLTIP_ENTER_BATTLEGROUND; + button:Show(); + end + + -- Set queued status + button.status:Hide(); + local queueStatus, queueMapName, queueInstanceID; + for i=1, MAX_BATTLEFIELD_QUEUES do + queueStatus, queueMapName, queueInstanceID = GetBattlefieldStatus(i); + if ( queueStatus ~= "none" and queueMapName.." "..queueInstanceID == button.title ) then + if ( queueStatus == "queued" ) then + button.status.texture:SetTexture(factionTexture); + button.status.texture:SetTexCoord(0.0, 1.0, 0.0, 1.0); + button.status.tooltip = BATTLEFIELD_QUEUE_STATUS; + button.status:Show(); + elseif ( queueStatus == "confirm" ) then + button.status.texture:SetTexture("Interface\\CharacterFrame\\UI-StateIcon"); + button.status.texture:SetTexCoord(0.45, 0.95, 0.0, 0.5); + button.status.tooltip = BATTLEFIELD_CONFIRM_STATUS; + button.status:Show(); + end + elseif ( button.title == FIRST_AVAILABLE and queueMapName == mapName and queueInstanceID == 0 ) then + if ( queueStatus == "queued" ) then + button.status.texture:SetTexture(factionTexture); + button.status.texture:SetTexCoord(0.0, 1.0, 0.0, 1.0); + button.status.tooltip = BATTLEFIELD_QUEUE_STATUS; + button.status:Show(); + end + end + end + + -- Set selected instance + if ( zoneIndex == 1 and GetSelectedBattlefield() == 0 ) then + button:LockHighlight(); + elseif ( zoneIndex - 1 == GetSelectedBattlefield() ) then + button:LockHighlight(); + else + button:UnlockHighlight(); + end + end + + local mapName, mapDescription, maxGroup, canEnter, isHoliday, isRandom = GetBattlefieldInfo(); + + if ( isRandom or isHoliday ) then + BattlefieldFrame_UpdateRandomInfo(); + BattlefieldFrameInfoScrollFrameChildFrameRewardsInfo:Show(); + BattlefieldFrameInfoScrollFrameChildFrameDescription:Hide(); + else + if ( mapDescription ~= BattlefieldFrameInfoScrollFrameChildFrameDescription:GetText() ) then + BattlefieldFrameInfoScrollFrameChildFrameDescription:SetText(mapDescription); + BattlefieldFrameInfoScrollFrame:SetVerticalScroll(0); + end + + BattlefieldFrameInfoScrollFrameChildFrameRewardsInfo:Hide(); + BattlefieldFrameInfoScrollFrameChildFrameDescription:Show(); + end + + -- Enable or disable the group join button + if ( CanJoinBattlefieldAsGroup() ) then + if ( ((GetNumPartyMembers() > 0) or (GetNumRaidMembers() > 0)) and IsPartyLeader() ) then + -- If this is true then can join as a group + BattlefieldFrameGroupJoinButton:Enable(); + else + BattlefieldFrameGroupJoinButton:Disable(); + end + BattlefieldFrameGroupJoinButton:Show(); + else + BattlefieldFrameGroupJoinButton:Hide(); + end + + if ( BattlefieldFrame.numQueues ) then + if ( BattlefieldFrame.numQueues <= 3 ) then + BattlefieldFrameJoinButton:Enable(); + else + BattlefieldFrameJoinButton:Disable(); + end + end + + FauxScrollFrame_Update(BattlefieldListScrollFrame, numBattlefields, BATTLEFIELD_ZONES_DISPLAYED, BATTLEFIELD_ZONES_HEIGHT, "BattlefieldZone", 293, 315); +end + +function PVPQueue_UpdateRandomInfo(base, infoFunc) + local BGname, canEnter, isHoliday, isRandom = infoFunc(); + + local hasWin, lossHonor, winHonor, winArena, lossArena; + + if ( isRandom ) then + hasWin, winHonor, winArena, lossHonor, lossArena = GetRandomBGHonorCurrencyBonuses(); + base.title:SetText(RANDOM_BATTLEGROUND); + base.description:SetText(RANDOM_BATTLEGROUND_EXPLANATION); + else + base.title:SetText(BATTLEGROUND_HOLIDAY); + base.description:SetText(BATTLEGROUND_HOLIDAY_EXPLANATION); + hasWin, winHonor, winArena, lossHonor, lossArena = GetHolidayBGHonorCurrencyBonuses(); + end + + if (winHonor ~= 0) then + base.winReward.honorSymbol:Show(); + base.winReward.honorAmount:Show(); + base.winReward.honorAmount:SetText(winHonor); + else + base.winReward.honorSymbol:Hide(); + base.winReward.honorAmount:Hide(); + end + + if (winArena ~= 0) then + base.winReward.arenaSymbol:Show(); + base.winReward.arenaAmount:Show(); + base.winReward.arenaAmount:SetText(winArena); + else + base.winReward.arenaSymbol:Hide(); + base.winReward.arenaAmount:Hide(); + end + + if (lossHonor ~= 0) then + base.lossReward.honorSymbol:Show(); + base.lossReward.honorAmount:Show(); + base.lossReward.honorAmount:SetText(lossHonor); + else + base.lossReward.honorSymbol:Hide(); + base.lossReward.honorAmount:Hide(); + end + + if (lossArena ~= 0) then + base.lossReward.arenaSymbol:Show(); + base.lossReward.arenaAmount:Show(); + base.lossReward.arenaAmount:SetText(lossArena); + else + base.lossReward.arenaSymbol:Hide(); + base.lossReward.arenaAmount:Hide(); + end + + local englishFaction = MoonWell_GetDisplayFaction(); + base.winReward.honorSymbol:SetTexture("Interface\\PVPFrame\\PVP-Currency-"..englishFaction); + base.lossReward.honorSymbol:SetTexture("Interface\\PVPFrame\\PVP-Currency-"..englishFaction); +end + +function BattlefieldFrame_GetSelectedBattlegroundInfo() + local BGname, description, groupSize, canEnter, isHoliday, isRandom = GetBattlefieldInfo(); + return BGname, canEnter, isHoliday, isRandom; +end + +function BattlefieldFrame_UpdateRandomInfo() + PVPQueue_UpdateRandomInfo(BattlefieldFrameInfoScrollFrameChildFrameRewardsInfo, BattlefieldFrame_GetSelectedBattlegroundInfo); +end + +function BattlefieldButton_OnClick(self) + local id = self:GetID(); + SetSelectedBattlefield(FauxScrollFrame_GetOffset(BattlefieldListScrollFrame) + id - 1); + BattlefieldFrame_Update(); +end + +function BattlefieldFrameJoinButton_OnClick(self) + local GROUPJOIN_BUTTONID = 2; + local id = self:GetID(); + if ( id == GROUPJOIN_BUTTONID ) then + JoinBattlefield(GetSelectedBattlefield(), 1); + else + JoinBattlefield(GetSelectedBattlefield()); + end + + HideUIPanel(BattlefieldFrame); +end + +function MiniMapBattlefieldDropDown_OnLoad() + UIDropDownMenu_Initialize(MiniMapBattlefieldDropDown, MiniMapBattlefieldDropDown_Initialize, "MENU"); +end + +function MiniMapBattlefieldDropDown_Initialize() + local info; + local status, mapName, instanceID, queueID, levelRangeMin, levelRangeMax, teamSize, registeredMatch; + local numQueued = 0; + local numShown = 0; + + local shownHearthAndRes; + + for i=1, MAX_BATTLEFIELD_QUEUES do + status, mapName, instanceID, levelRangeMin, levelRangeMax, teamSize, registeredMatch = GetBattlefieldStatus(i); + + -- Inserts a spacer if it's not the first option... to make it look nice. + if ( status ~= "none" ) then + numShown = numShown + 1; + if ( numShown > 1 ) then + info = UIDropDownMenu_CreateInfo(); + info.isTitle = 1; + info.notCheckable = 1; + UIDropDownMenu_AddButton(info); + end + end + + if ( status == "queued" or status == "confirm" ) then + numQueued = numQueued + 1; + -- Add a spacer if there were dropdown items before this + + info = UIDropDownMenu_CreateInfo(); + if ( teamSize ~= 0 ) then + if ( registeredMatch ) then + info.text = ARENA_RATED_MATCH.." "..format(PVP_TEAMSIZE, teamSize, teamSize); + else + info.text = ARENA_CASUAL.." "..format(PVP_TEAMSIZE, teamSize, teamSize); + end + else + info.text = mapName; + end + info.isTitle = 1; + info.notCheckable = 1; + UIDropDownMenu_AddButton(info); + + if ( CanHearthAndResurrectFromArea() and not shownHearthAndRes and GetRealZoneText() == mapName ) then + info = UIDropDownMenu_CreateInfo(); + info.text = format(LEAVE_ZONE, GetRealZoneText()); + + info.func = HearthAndResurrectFromArea; + info.notCheckable = 1; + UIDropDownMenu_AddButton(info); + shownHearthAndRes = true; + end + + if ( status == "queued" ) then + + info = UIDropDownMenu_CreateInfo(); + info.text = LEAVE_QUEUE; + info.func = function (self, ...) AcceptBattlefieldPort(...) end; + info.arg1 = i; + info.notCheckable = 1; + UIDropDownMenu_AddButton(info); + + elseif ( status == "confirm" ) then + + info = UIDropDownMenu_CreateInfo(); + info.text = ENTER_BATTLE; + info.func = function (self, ...) AcceptBattlefieldPort(...) end; + info.arg1 = i; + info.arg2 = 1; + info.notCheckable = 1; + UIDropDownMenu_AddButton(info); + + if ( teamSize == 0 ) then + info = UIDropDownMenu_CreateInfo(); + info.text = LEAVE_QUEUE; + info.func = function (self, ...) AcceptBattlefieldPort(...) end; + info.arg1 = i; + info.notCheckable = 1; + UIDropDownMenu_AddButton(info); + end + + end + + elseif ( status == "active" ) then + + info = UIDropDownMenu_CreateInfo(); + if ( teamSize ~= 0 ) then + info.text = mapName.." "..format(PVP_TEAMSIZE, teamSize, teamSize); + else + info.text = mapName; + end + info.isTitle = 1; + info.notCheckable = 1; + UIDropDownMenu_AddButton(info); + + info = UIDropDownMenu_CreateInfo(); + if ( IsActiveBattlefieldArena() ) then + info.text = LEAVE_ARENA; + else + info.text = LEAVE_BATTLEGROUND; + end + info.func = function (self, ...) LeaveBattlefield(...) end; + info.notCheckable = 1; + UIDropDownMenu_AddButton(info); + + end + end + + for i=1, MAX_WORLD_PVP_QUEUES do + status, mapName, queueID = GetWorldPVPQueueStatus(i); + + -- Inserts a spacer if it's not the first option... to make it look nice. + if ( status ~= "none" ) then + numShown = numShown + 1; + if ( numShown > 1 ) then + info = UIDropDownMenu_CreateInfo(); + info.isTitle = 1; + info.notCheckable = 1; + UIDropDownMenu_AddButton(info); + end + end + + if ( status == "queued" or status == "confirm" ) then + numQueued = numQueued + 1; + -- Add a spacer if there were dropdown items before this + + info = UIDropDownMenu_CreateInfo(); + info.text = mapName; + info.isTitle = 1; + info.notCheckable = 1; + UIDropDownMenu_AddButton(info); + + if ( CanHearthAndResurrectFromArea() and not shownHearthAndRes and GetRealZoneText() == mapName ) then + info = UIDropDownMenu_CreateInfo(); + info.text = format(LEAVE_ZONE, GetRealZoneText()); + + info.func = HearthAndResurrectFromArea; + info.notCheckable = 1; + UIDropDownMenu_AddButton(info); + shownHearthAndRes = true; + end + + if ( status == "queued" ) then + + info = UIDropDownMenu_CreateInfo(); + info.text = LEAVE_QUEUE; + info.func = function (self, ...) BattlefieldMgrExitRequest(...) end; + info.arg1 = queueID; + info.notCheckable = 1; + UIDropDownMenu_AddButton(info); + + elseif ( status == "confirm" ) then + + info = UIDropDownMenu_CreateInfo(); + info.text = ENTER_BATTLE; + info.func = function (self, ...) BattlefieldMgrEntryInviteResponse(...) end; + info.arg1 = queueID; + info.arg2 = 1; + info.notCheckable = 1; + UIDropDownMenu_AddButton(info); + + info = UIDropDownMenu_CreateInfo(); + info.text = LEAVE_QUEUE; + info.func = function (self, ...) BattlefieldMgrEntryInviteResponse(...) end; + info.arg1 = i; + info.notCheckable = 1; + UIDropDownMenu_AddButton(info); + end + end + end + + if ( CanHearthAndResurrectFromArea() and not shownHearthAndRes ) then + numShown = numShown + 1; + info = UIDropDownMenu_CreateInfo(); + info.text = GetRealZoneText(); + info.isTitle = 1; + info.notCheckable = 1; + UIDropDownMenu_AddButton(info); + + info = UIDropDownMenu_CreateInfo(); + info.text = format(LEAVE_ZONE, GetRealZoneText()); + + info.func = HearthAndResurrectFromArea; + info.notCheckable = 1; + UIDropDownMenu_AddButton(info); + end + +end + +function BattlegroundShineFadeIn() + -- Fade in the shine and then fade it out with the ComboPointShineFadeOut function + local fadeInfo = {}; + fadeInfo.mode = "IN"; + fadeInfo.timeToFade = 0.5; + fadeInfo.finishedFunc = BattlegroundShineFadeOut; + UIFrameFade(BattlegroundShine, fadeInfo); +end + +--hack since a frame can't have a reference to itself in it +function BattlegroundShineFadeOut() + UIFrameFadeOut(BattlegroundShine, 0.5); +end + +function IsAlreadyInQueue(mapName) + local inQueue = nil; + for index,value in pairs(PREVIOUS_BATTLEFIELD_QUEUES) do + if ( value == mapName ) then + inQueue = 1; + end + end + return inQueue; +end diff --git a/reference/FrameXML/BattlefieldFrame.xml b/reference/FrameXML/BattlefieldFrame.xml new file mode 100644 index 0000000..769af2c --- /dev/null +++ b/reference/FrameXML/BattlefieldFrame.xml @@ -0,0 +1,653 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/reference/FrameXML/FrameXML.toc b/reference/FrameXML/FrameXML.toc new file mode 100644 index 0000000..056d239 --- /dev/null +++ b/reference/FrameXML/FrameXML.toc @@ -0,0 +1,147 @@ +# Do not delete the following line! +## Interface: 30300 +##DebugHook.lua +GlobalStrings.lua +Constants.lua +Fonts.xml +FontStyles.xml +Localization.xml +## add new modules below here + +BasicControls.xml +WorldFrame.xml +UIParent.xml +AnimTimerFrame.xml +MoneyFrame.lua +MoneyFrame.xml +MoneyInputFrame.lua +MoneyInputFrame.xml +GameTooltip.xml +UIMenu.xml +UIDropDownMenu.xml +UIPanelTemplates.lua +UIPanelTemplates.xml +SecureTemplates.xml +SecureHandlerTemplates.xml +ItemButtonTemplate.xml +SparkleFrame.xml +HybridScrollFrame.lua +HybridScrollFrame.xml +GameMenuFrame.xml +CharacterFrameTemplates.xml +TextStatusBar.lua +TextStatusBar.xml +UIErrorsFrame.xml +AutoComplete.xml +StaticPopup.xml +Sound.lua +OptionsFrameTemplates.xml +OptionsPanelTemplates.xml +VideoOptionsFrame.xml +VideoOptionsPanels.xml +AudioOptionsFrame.xml +AudioOptionsPanels.xml +InterfaceOptionsFrame.xml +InterfaceOptionsPanels.xml +AlertFrames.xml +MirrorTimer.xml +CoinPickupFrame.xml +StackSplitFrame.xml +FadingFrame.xml +ZoneText.xml +BattlefieldFrame.xml +MainMenuBar.xml +MainMenuBarMicroButtons.xml +TutorialFrame.xml +Minimap.xml +GameTime.xml +Cooldown.xml +ActionButtonTemplate.xml +ActionBarFrame.xml +MultiActionBars.xml +##ActionWindow.xml +BuffFrame.xml +CombatFeedback.xml +CastingBarFrame.xml +UnitPopup.xml +UnitFrame.xml +BNet.xml +HistoryKeeper.lua +BNConversations.xml +ChatFrame.xml +FloatingChatFrame.xml +VoiceChat.xml +ReadyCheck.xml +PlayerFrame.xml +PartyFrame.xml +TargetFrame.xml +TotemFrame.xml +PetFrame.xml +StatsFrame.xml +SpellBookFrame.xml +CharacterFrame.xml +EquipmentManager.lua +PaperDollFrame.xml +PetPaperDollFrame.xml +SkillFrame.xml +ReputationFrame.xml +HonorFrame.xml +QuestFrame.xml +QuestPOI.xml +WatchFrame.xml +QuestLogFrame.xml +QuestInfo.xml +MerchantFrame.xml +TradeFrame.xml +ContainerFrame.xml +LootFrame.xml +ItemTextFrame.xml +TaxiFrame.xml +BankFrame.xml +FriendsFrame.xml +RaidFrame.xml +ChannelFrame.xml +PetActionBarFrame.xml +MultiCastActionBarFrame.xml +BonusActionBarFrame.xml +MainMenuBarBagButtons.xml +WorldMapFrame.xml +CinematicFrame.xml +ItemRef.xml +ComboFrame.xml +TabardFrame.xml +GuildRegistrarFrame.xml +PetitionFrame.xml +HelpFrame.xml +KnowledgeBaseFrame.xml +ColorPickerFrame.xml +GossipFrame.xml +MailFrame.xml +PetStable.xml +DurabilityFrame.xml +WorldStateFrame.xml +DressUpFrame.xml +RaidWarning.xml +ClassTrainerFrameTemplates.xml +PVPFrame.xml +PVPBattlegroundFrame.xml +ArenaFrame.xml +ArenaRegistrarFrame.xml +LFGFrame.xml +LFDFrame.xml +LFRFrame.xml +MovieRecordingProgress.xml +MacOptionsFrame.xml +RatingMenuFrame.xml +TalentFrameBase.lua +TalentFrameTemplates.xml +RuneFrame.xml +EasyMenu.lua +ChatConfigFrame.xml +MovieFrame.xml +VehicleMenuBar.xml +AlternatePowerBar.xml +AnimationSystem.lua + +## add new modules above here +LocalizationPost.xml diff --git a/reference/FrameXML/FriendsFrame.lua b/reference/FrameXML/FriendsFrame.lua new file mode 100644 index 0000000..8d70d9d --- /dev/null +++ b/reference/FrameXML/FriendsFrame.lua @@ -0,0 +1,2831 @@ +FRIENDS_TO_DISPLAY = 10; +FRIENDS_FRAME_FRIEND_HEIGHT = 34; +IGNORES_TO_DISPLAY = 19; +FRIENDS_FRAME_IGNORE_HEIGHT = 16; +PENDING_INVITES_TO_DISPLAY = 4; +PENDING_BUTTON_MIN_HEIGHT = 92; +FRIENDS_FRIENDS_TO_DISPLAY = 11; +FRIENDS_FRAME_FRIENDS_FRIENDS_HEIGHT = 16; +MAX_INVITE_MESSAGE_LINES = 10; +MAX_INVITE_MESSAGE_HEIGHT = 0; -- automatically set in FriendsFramePendingScrollFrame:OnLoad +WHOS_TO_DISPLAY = 17; +FRIENDS_FRAME_WHO_HEIGHT = 16; +GUILDMEMBERS_TO_DISPLAY = 13; +FRIENDS_FRAME_GUILD_HEIGHT = 14; +MAX_WHOS_FROM_SERVER = 50; +MAX_GUILDCONTROL_OPTIONS = 12; +CURRENT_GUILD_MOTD = ""; +GUILD_DETAIL_NORM_HEIGHT = 195 +GUILD_DETAIL_OFFICER_HEIGHT = 255 +MAX_GUILDBANK_TABS = 6; +MAX_GOLD_WITHDRAW = 1000; +GUILDEVENT_TRANSACTION_HEIGHT = 13; +MAX_EVENTS_SHOWN = 25; +MAX_GOLD_WITHDRAW_DIGITS = 9; +PENDING_GUILDBANK_PERMISSIONS = {}; +FRIENDS_BUTTON_HEADER_HEIGHT = 16; +FRIENDS_BUTTON_NORMAL_HEIGHT = 34; +FRIENDS_BUTTON_LARGE_HEIGHT = 48; +FRIENDS_BUTTON_TYPE_HEADER = 1; +FRIENDS_BUTTON_TYPE_BNET = 2; +FRIENDS_BUTTON_TYPE_WOW = 3; +FRIENDS_TEXTURE_ONLINE = "Interface\\FriendsFrame\\StatusIcon-Online"; +FRIENDS_TEXTURE_AFK = "Interface\\FriendsFrame\\StatusIcon-Away"; +FRIENDS_TEXTURE_DND = "Interface\\FriendsFrame\\StatusIcon-DnD"; +FRIENDS_TEXTURE_OFFLINE = "Interface\\FriendsFrame\\StatusIcon-Offline"; +FRIENDS_TEXTURE_BROADCAST = "Interface\\FriendsFrame\\BroadcastIcon"; +FRIENDS_BNET_NAME_COLOR = {r=0.510, g=0.773, b=1.0}; +FRIENDS_BNET_BACKGROUND_COLOR = {r=0, g=0.694, b=0.941, a=0.05}; +FRIENDS_WOW_NAME_COLOR = {r=0.996, g=0.882, b=0.361}; +FRIENDS_WOW_BACKGROUND_COLOR = {r=1.0, g=0.824, b=0.0, a=0.05}; +FRIENDS_GRAY_COLOR = {r=0.486, g=0.518, b=0.541}; +FRIENDS_OFFLINE_BACKGROUND_COLOR = {r=0.588, g=0.588, b=0.588, a=0.05}; +FRIENDS_PRESENCE_COLOR_CODE = "|cff7c848a"; +FRIENDS_BNET_NAME_COLOR_CODE = "|cff82c5ff"; +FRIENDS_BROADCAST_TIME_COLOR_CODE = "|cff4381a8" +FRIENDS_WOW_NAME_COLOR_CODE = "|cfffde05c"; +FRIENDS_OTHER_NAME_COLOR_CODE = "|cff7b8489"; +SQUELCH_TYPE_IGNORE = 1; +SQUELCH_TYPE_BLOCK_INVITE = 2; +SQUELCH_TYPE_MUTE = 3; +SQUELCH_TYPE_BLOCK_TOON = 4; +FRIENDS_FRIENDS_POTENTIAL = 1; +FRIENDS_FRIENDS_MUTUAL = 2; +FRIENDS_FRIENDS_ALL = 3; +BNET_CLIENT_WOW = "WoW"; +BNET_CLIENT_SC2 = "S2"; +FRIENDS_TOOLTIP_MAX_TOONS = 5; +FRIENDS_TOOLTIP_MAX_WIDTH = 200; +FRIENDS_TOOLTIP_MARGIN_WIDTH = 12; + +local FriendButtons = { }; +local BNetBroadcasts = { }; +local totalScrollHeight = 0; +local numOnlineBroadcasts = 0; +local numOfflineBroadcasts = 0; +local PendingInvitesNew = { }; +local playerRealmName; +local playerFactionGroup; + +WHOFRAME_DROPDOWN_LIST = { + {name = ZONE, sortType = "zone"}, + {name = GUILD, sortType = "guild"}, + {name = RACE, sortType = "race"} +}; + +FRIENDSFRAME_SUBFRAMES = { "FriendsListFrame", "IgnoreListFrame", "PendingListFrame", "WhoFrame", "GuildFrame", "ChannelFrame", "RaidFrame" }; +function FriendsFrame_ShowSubFrame(frameName) + for index, value in pairs(FRIENDSFRAME_SUBFRAMES) do + if ( value == frameName ) then + _G[value]:Show() + else + _G[value]:Hide(); + end + end +end + +function FriendsFrame_SummonButton_OnEvent (self, event, ...) + if ( event == "SPELL_UPDATE_COOLDOWN" and self:GetParent().id ) then + FriendsFrame_SummonButton_Update(self); + end +end + +function FriendsFrame_SummonButton_OnShow (self) + FriendsFrame_SummonButton_Update(self); +end + +function FriendsFrame_SummonButton_Update (self) + local id = self:GetParent().id; + if ( not id or (self:GetParent().buttonType ~= FRIENDS_BUTTON_TYPE_WOW) or not IsReferAFriendLinked(GetFriendInfo(id)) ) then + self:Hide(); + return; + end + + self:Show(); + + local start, duration = GetSummonFriendCooldown(); + + if ( duration > 0 ) then + self.duration = duration; + self.start = start; + else + self.duration = nil; + self.start = nil; + end + + local enable = CanSummonFriend(GetFriendInfo(id)); + + local icon = _G[self:GetName().."Icon"]; + local normalTexture = _G[self:GetName().."NormalTexture"]; + if ( enable ) then + icon:SetVertexColor(1.0, 1.0, 1.0); + normalTexture:SetVertexColor(1.0, 1.0, 1.0); + else + icon:SetVertexColor(0.4, 0.4, 0.4); + normalTexture:SetVertexColor(1.0, 1.0, 1.0); + end + CooldownFrame_SetTimer(_G[self:GetName().."Cooldown"], start, duration, ((enable and 0) or 1)); +end + +function FriendsFrame_ClickSummonButton (self) + local name = GetFriendInfo(self:GetParent().id); + if ( CanSummonFriend(name) ) then + SummonFriend(name); + end +end + +function FriendsFrame_ShowDropdown(name, connected, lineID, chatType, chatFrame, friendsList) + HideDropDownMenu(1); + if ( connected or friendsList ) then + if ( connected ) then + FriendsDropDown.initialize = FriendsFrameDropDown_Initialize; + else + FriendsDropDown.initialize = FriendsFrameOfflineDropDown_Initialize; + end + + FriendsDropDown.displayMode = "MENU"; + FriendsDropDown.name = name; + FriendsDropDown.friendsList = friendsList; + FriendsDropDown.lineID = lineID; + FriendsDropDown.chatType = chatType; + FriendsDropDown.chatTarget = name; + FriendsDropDown.chatFrame = chatFrame; + FriendsDropDown.presenceID = nil; + ToggleDropDownMenu(1, nil, FriendsDropDown, "cursor"); + end +end + +function FriendsFrame_ShowBNDropdown(name, connected, lineID, chatType, chatFrame, friendsList, presenceID) + if ( connected or friendsList ) then + if ( connected ) then + FriendsDropDown.initialize = FriendsFrameBNDropDown_Initialize; + else + FriendsDropDown.initialize = FriendsFrameBNOfflineDropDown_Initialize; + end + FriendsDropDown.displayMode = "MENU"; + FriendsDropDown.name = name; + FriendsDropDown.friendsList = friendsList; + FriendsDropDown.lineID = lineID; + FriendsDropDown.chatType = chatType; + FriendsDropDown.chatTarget = name; + FriendsDropDown.chatFrame = chatFrame; + FriendsDropDown.presenceID = presenceID; + ToggleDropDownMenu(1, nil, FriendsDropDown, "cursor"); + end +end + +function FriendsFrameDropDown_Initialize() + UnitPopup_ShowMenu(UIDROPDOWNMENU_OPEN_MENU, "FRIEND", nil, FriendsDropDown.name); +end + +function FriendsFrameOfflineDropDown_Initialize() + UnitPopup_ShowMenu(UIDROPDOWNMENU_OPEN_MENU, "FRIEND_OFFLINE", nil, FriendsDropDown.name); +end + +function FriendsFrameBNDropDown_Initialize() + UnitPopup_ShowMenu(UIDROPDOWNMENU_OPEN_MENU, "BN_FRIEND", nil, FriendsDropDown.name); +end + +function FriendsFrameBNOfflineDropDown_Initialize() + UnitPopup_ShowMenu(UIDROPDOWNMENU_OPEN_MENU, "BN_FRIEND_OFFLINE", nil, FriendsDropDown.name); +end + +function FriendsFrame_OnLoad(self) + PanelTemplates_SetNumTabs(self, 5); + self.selectedTab = 1; + PanelTemplates_UpdateTabs(self); + self:RegisterEvent("FRIENDLIST_SHOW"); + self:RegisterEvent("FRIENDLIST_UPDATE"); + self:RegisterEvent("IGNORELIST_UPDATE"); + self:RegisterEvent("MUTELIST_UPDATE"); + self:RegisterEvent("WHO_LIST_UPDATE"); + self:RegisterEvent("GUILD_ROSTER_UPDATE"); + self:RegisterEvent("PLAYER_GUILD_UPDATE"); + self:RegisterEvent("GUILD_MOTD"); + self:RegisterEvent("VOICE_CHAT_ENABLED_UPDATE"); + self:RegisterEvent("PARTY_MEMBERS_CHANGED"); + self:RegisterEvent("PLAYER_FLAGS_CHANGED"); + self:RegisterEvent("BN_FRIEND_LIST_SIZE_CHANGED"); + self:RegisterEvent("BN_FRIEND_INFO_CHANGED"); + self:RegisterEvent("BN_FRIEND_INVITE_LIST_INITIALIZED"); + self:RegisterEvent("BN_FRIEND_INVITE_ADDED"); + self:RegisterEvent("BN_FRIEND_INVITE_REMOVED"); + self:RegisterEvent("BN_CUSTOM_MESSAGE_CHANGED"); + self:RegisterEvent("BN_CUSTOM_MESSAGE_LOADED"); + self:RegisterEvent("BN_SELF_ONLINE"); + self:RegisterEvent("BN_BLOCK_LIST_UPDATED"); + self:RegisterEvent("PLAYER_ENTERING_WORLD"); + self:RegisterEvent("BN_CONNECTED"); + self:RegisterEvent("BN_DISCONNECTED"); + self.playersInBotRank = 0; + self.playerStatusFrame = 1; + self.selectedFriend = 1; + self.selectedIgnore = 1; + self.guildStatus = 0; + GuildFrame.notesToggle = 1; + GuildFrame.selectedGuildMember = 0; + SetGuildRosterSelection(0); + CURRENT_GUILD_MOTD = GetGuildRosterMOTD(); + GuildFrameNotesText:SetText(CURRENT_GUILD_MOTD); + GuildMemberDetailRankText:SetPoint("RIGHT", GuildFramePromoteButton, "LEFT"); + -- friends list + DynamicScrollFrame_CreateButtons(FriendsFrameFriendsScrollFrame, "FriendsFrameButtonTemplate", FRIENDS_BUTTON_HEADER_HEIGHT, FriendsFrame_SetButton, FriendsFrame_GetTopButton); + FriendsFrameOfflineHeader:SetParent(FriendsFrameFriendsScrollFrameScrollChild); + FriendsFrameBroadcastInputClearButton.icon:SetVertexColor(FRIENDS_BNET_NAME_COLOR.r, FRIENDS_BNET_NAME_COLOR.g, FRIENDS_BNET_NAME_COLOR.b); + if ( not BNFeaturesEnabled() ) then + FriendsTabHeaderTab3:Hide(); + FriendsFrameBroadcastInput:Hide(); + FriendsFrameBattlenetStatus:Hide(); + FriendsFrameStatusDropDown:Show(); + end +end + +function FriendsFrame_OnShow() + VoiceChat_Toggle(); + FriendsList_Update(); + FriendsFrame_Update(); + UpdateMicroButtons(); + PlaySound("igCharacterInfoTab"); + GuildFrame.selectedGuildMember = 0; + SetGuildRosterSelection(0); + InGuildCheck(); +end + +function FriendsFrame_Update() + if ( FriendsFrame.selectedTab == 1 ) then + FriendsTabHeader:Show(); + if ( FriendsTabHeader.selectedTab == 1 ) then + ShowFriends(); + FriendsFrameTopLeft:SetTexture("Interface\\FriendsFrame\\UI-FriendsFrame-TopLeft-bnet"); + FriendsFrameTopRight:SetTexture("Interface\\FriendsFrame\\UI-FriendsFrame-TopRight-bnet"); + FriendsFrameBottomLeft:SetTexture("Interface\\FriendsFrame\\UI-FriendsFrameMute-BotLeft-bnet"); + FriendsFrameBottomRight:SetTexture("Interface\\FriendsFrame\\UI-FriendsFrameMute-BotRight-bnet"); + FriendsFrameTitleText:SetText(FRIENDS_LIST); + FriendsFrame_ShowSubFrame("FriendsListFrame"); + elseif ( FriendsTabHeader.selectedTab == 3 ) then + FriendsFrameTopLeft:SetTexture("Interface\\FriendsFrame\\UI-FriendsFrame-TopLeft-bnet"); + FriendsFrameTopRight:SetTexture("Interface\\FriendsFrame\\UI-FriendsFrame-TopRight-bnet"); + FriendsFrameBottomRight:SetTexture("Interface\\FriendsFrame\\UI-FriendsFrame-Pending-BotRight"); + FriendsFrameBottomLeft:SetTexture("Interface\\FriendsFrame\\UI-FriendsFrame-Pending-BotLeft"); + FriendsFrameTitleText:SetText(PENDING_INVITE_LIST); + FriendsFrame_ShowSubFrame("PendingListFrame"); + else + FriendsFrameTopLeft:SetTexture("Interface\\FriendsFrame\\UI-FriendsFrame-TopLeft-bnet"); + FriendsFrameTopRight:SetTexture("Interface\\FriendsFrame\\UI-FriendsFrame-TopRight-bnet"); + if ( IsVoiceChatEnabled() ) then + FriendsFrameMutePlayerButton:Show(); + FriendsFrameBottomLeft:SetTexture("Interface\\FriendsFrame\\UI-FriendsFrameThree-BotLeft-bnet"); + FriendsFrameBottomRight:SetTexture("Interface\\FriendsFrame\\UI-FriendsFrameThree-BotRight-bnet"); + FriendsFrameIgnorePlayerButton:SetWidth(110); + FriendsFrameUnsquelchButton:SetWidth(111); + else + FriendsFrameMutePlayerButton:Hide(); + FriendsFrameBottomLeft:SetTexture("Interface\\FriendsFrame\\UI-FriendsFrameMute-BotLeft-bnet"); + FriendsFrameBottomRight:SetTexture("Interface\\FriendsFrame\\UI-FriendsFrameMute-BotRight-bnet"); + FriendsFrameIgnorePlayerButton:SetWidth(131); + FriendsFrameUnsquelchButton:SetWidth(134); + end + FriendsFrameTitleText:SetText(IGNORE_LIST); + FriendsFrame_ShowSubFrame("IgnoreListFrame"); + IgnoreList_Update(); + end + else + FriendsTabHeader:Hide(); + if ( FriendsFrame.selectedTab == 2 ) then + FriendsFrameTopLeft:SetTexture("Interface\\ClassTrainerFrame\\UI-ClassTrainer-TopLeft"); + FriendsFrameTopRight:SetTexture("Interface\\ClassTrainerFrame\\UI-ClassTrainer-TopRight"); + FriendsFrameBottomLeft:SetTexture("Interface\\FriendsFrame\\WhoFrame-BotLeft"); + FriendsFrameBottomRight:SetTexture("Interface\\FriendsFrame\\WhoFrame-BotRight"); + FriendsFrameTitleText:SetText(WHO_LIST); + FriendsFrame_ShowSubFrame("WhoFrame"); + WhoList_Update(); + elseif ( FriendsFrame.selectedTab == 3 ) then + FriendsFrameTopLeft:SetTexture("Interface\\ClassTrainerFrame\\UI-ClassTrainer-TopLeft"); + FriendsFrameTopRight:SetTexture("Interface\\ClassTrainerFrame\\UI-ClassTrainer-TopRight"); + FriendsFrameBottomLeft:SetTexture("Interface\\FriendsFrame\\GuildFrame-BotLeft"); + FriendsFrameBottomRight:SetTexture("Interface\\FriendsFrame\\GuildFrame-BotRight"); + local guildName, title, rank = GetGuildInfo("player"); + if ( guildName ) then + FriendsFrameTitleText:SetFormattedText(GUILD_TITLE_TEMPLATE, title, guildName); + else + FriendsFrameTitleText:SetText(""); + end + GuildStatus_Update(); + FriendsFrame_ShowSubFrame("GuildFrame"); + elseif ( FriendsFrame.selectedTab == 4 ) then + FriendsFrameTopLeft:SetTexture("Interface\\PaperDollInfoFrame\\UI-Character-General-TopLeft"); + FriendsFrameTopRight:SetTexture("Interface\\PaperDollInfoFrame\\UI-Character-General-TopRight"); + FriendsFrameBottomLeft:SetTexture("Interface\\FriendsFrame\\UI-ChannelFrame-BotLeft"); + FriendsFrameBottomRight:SetTexture("Interface\\FriendsFrame\\UI-ChannelFrame-BotRight"); + FriendsFrameTitleText:SetText(CHAT_CHANNELS); + FriendsFrame_ShowSubFrame("ChannelFrame"); + elseif ( FriendsFrame.selectedTab == 5 ) then + FriendsFrameTopLeft:SetTexture("Interface\\PaperDollInfoFrame\\UI-Character-General-TopLeft"); + FriendsFrameTopRight:SetTexture("Interface\\PaperDollInfoFrame\\UI-Character-General-TopRight"); + FriendsFrameBottomLeft:SetTexture("Interface\\PaperDollInfoFrame\\UI-Character-General-BottomLeft"); + FriendsFrameBottomRight:SetTexture("Interface\\PaperDollInfoFrame\\UI-Character-General-BottomRight"); + FriendsFrameTitleText:SetText(RAID); + FriendsFrame_ShowSubFrame("RaidFrame"); + end + end +end + +function FriendsFrame_OnHide() + UpdateMicroButtons(); + PlaySound("igMainMenuClose"); + SetGuildRosterSelection(0); + GuildFrame.selectedGuildMember = 0; + GuildFramePopup_HideAll(); + RaidInfoFrame:Hide(); + for index, value in pairs(FRIENDSFRAME_SUBFRAMES) do + _G[value]:Hide(); + end +end + +function FriendsList_Update() + local numBNetTotal, numBNetOnline = BNGetNumFriends(); + local numBNetOffline = numBNetTotal - numBNetOnline; + local numWoWTotal, numWoWOnline = GetNumFriends(); + local numWoWOffline = numWoWTotal - numWoWOnline; + + FriendsMicroButtonCount:SetText(numBNetOnline + numWoWOnline); + if ( not FriendsListFrame:IsShown() ) then + return; + end + + local buttonCount = numBNetTotal + numWoWTotal; + local haveHeader; + + totalScrollHeight = 0; + if ( numBNetOnline > 0 or numWoWOnline > 0 ) then + totalScrollHeight = totalScrollHeight + (numBNetOnline + numWoWOnline) * FRIENDS_BUTTON_NORMAL_HEIGHT + numOnlineBroadcasts * (FRIENDS_BUTTON_LARGE_HEIGHT - FRIENDS_BUTTON_NORMAL_HEIGHT); + end + if ( numBNetOffline > 0 or numWoWOffline > 0 ) then + totalScrollHeight = totalScrollHeight + (numBNetOffline + numWoWOffline) * FRIENDS_BUTTON_NORMAL_HEIGHT + numOfflineBroadcasts * (FRIENDS_BUTTON_LARGE_HEIGHT - FRIENDS_BUTTON_NORMAL_HEIGHT); + -- use a header if there are online and offline friends + if ( numBNetOnline > 0 or numWoWOnline > 0 ) then + haveHeader = true; + buttonCount = buttonCount + 1; + totalScrollHeight = totalScrollHeight + FRIENDS_BUTTON_HEADER_HEIGHT; + end + end + if ( buttonCount > #FriendButtons ) then + for i = #FriendButtons + 1, buttonCount do + FriendButtons[i] = { }; + end + end + + local index = 0; + -- online Battlenet friends + for i = 1, numBNetOnline do + index = index + 1; + FriendButtons[index].buttonType = FRIENDS_BUTTON_TYPE_BNET; + FriendButtons[index].id = i; + end + -- online WoW friends + for i = 1, numWoWOnline do + index = index + 1; + FriendButtons[index].buttonType = FRIENDS_BUTTON_TYPE_WOW; + FriendButtons[index].id = i; + end + -- offline header + if ( haveHeader ) then + index = index + 1; + FriendButtons[index].buttonType = FRIENDS_BUTTON_TYPE_HEADER; + end + -- offline Battlenet friends + for i = 1, numBNetOffline do + index = index + 1; + FriendButtons[index].buttonType = FRIENDS_BUTTON_TYPE_BNET; + FriendButtons[index].id = i + numBNetOnline; + end + -- offline WoW friends + for i = 1, numWoWOffline do + index = index + 1; + FriendButtons[index].buttonType = FRIENDS_BUTTON_TYPE_WOW; + FriendButtons[index].id = i + numWoWOnline; + end + + -- selection + local selectedFriend = 0; + -- check that we have at least 1 friend + if ( index > 0 ) then + -- get friend + if ( FriendsFrame.selectedFriendType == FRIENDS_BUTTON_TYPE_WOW ) then + selectedFriend = GetSelectedFriend(); + elseif ( FriendsFrame.selectedFriendType == FRIENDS_BUTTON_TYPE_BNET ) then + selectedFriend = BNGetSelectedFriend(); + end + -- set to first in list if no friend + if ( selectedFriend == 0 ) then + FriendsFrame_SelectFriend(FriendButtons[1].buttonType, 1); + selectedFriend = 1; + end + -- check if friend is online + local isOnline; + if ( FriendsFrame.selectedFriendType == FRIENDS_BUTTON_TYPE_WOW ) then + local name, level, class, area; + name, level, class, area, isOnline = GetFriendInfo(selectedFriend); + elseif ( FriendsFrame.selectedFriendType == FRIENDS_BUTTON_TYPE_BNET ) then + local presenceID, givenName, surname, toonName, toonID, client; + presenceID, givenName, surname, toonName, toonID, client, isOnline = BNGetFriendInfo(selectedFriend); + if ( not givenName or not surname ) then + isOnline = false; + end + end + if ( isOnline ) then + FriendsFrameSendMessageButton:Enable(); + else + FriendsFrameSendMessageButton:Disable(); + end + else + FriendsFrameSendMessageButton:Disable(); + end + FriendsFrame.selectedFriend = selectedFriend; + + DynamicScrollFrame_Update(FriendsFrameFriendsScrollFrame); +end + +function IgnoreList_Update() + local button; + local numIgnores = GetNumIgnores(); + local numBlocks = BNGetNumBlocked(); + local numToonBlocks = BNGetNumBlockedToons(); + local numMutes = 0; + if ( IsVoiceChatEnabled() ) then + numMutes = GetNumMutes(); + end + -- Headers stuff + local ignoredHeader, blockedHeader, mutedHeader, blockedToonHeader; + if ( numIgnores > 0 ) then + ignoredHeader = 1; + else + ignoredHeader = 0; + end + if ( numBlocks > 0 ) then + blockedHeader = 1; + else + blockedHeader = 0; + end + if ( numToonBlocks > 0 ) then + blockedToonHeader = 1; + else + blockedToonHeader = 0; + end + if ( numMutes > 0 ) then + mutedHeader = 1; + else + mutedHeader = 0; + end + + local lastIgnoredIndex = numIgnores + ignoredHeader; + local lastBlockedIndex = lastIgnoredIndex + numBlocks + blockedHeader; + local lastBlockedToonIndex = lastBlockedIndex + numToonBlocks + blockedToonHeader; + local lastMutedIndex = lastBlockedToonIndex + numMutes + mutedHeader; + local numEntries = lastMutedIndex; + + FriendsFrameIgnoredHeader:Hide(); + FriendsFrameBlockedInviteHeader:Hide(); + FriendsFrameBlockedToonHeader:Hide(); + FriendsFrameMutedHeader:Hide(); + + -- selection stuff + local selectedSquelchType = FriendsFrame.selectedSquelchType; + local selectedSquelchIndex = 0 ; + if ( selectedSquelchType == SQUELCH_TYPE_IGNORE ) then + selectedSquelchIndex = GetSelectedIgnore(); + elseif ( selectedSquelchType == SQUELCH_TYPE_BLOCK_INVITE ) then + selectedSquelchIndex = BNGetSelectedBlock(); + elseif ( selectedSquelchType == SQUELCH_TYPE_BLOCK_TOON ) then + selectedSquelchIndex = BNGetSelectedToonBlock(); + elseif ( selectedSquelchType == SQUELCH_TYPE_MUTE ) then + selectedSquelchIndex = GetSelectedMute(); + end + if ( selectedSquelchIndex == 0 ) then + if ( numIgnores > 0 ) then + FriendsFrame_SelectSquelched(SQUELCH_TYPE_IGNORE, 1); + selectedSquelchType = SQUELCH_TYPE_IGNORE; + selectedSquelchIndex = 1; + elseif ( numBlocks > 0 ) then + FriendsFrame_SelectSquelched(SQUELCH_TYPE_BLOCK_INVITE, 1); + selectedSquelchType = SQUELCH_TYPE_BLOCK_INVITE; + selectedSquelchIndex = 1; + elseif ( numToonBlocks > 0 ) then + FriendsFrame_SelectSquelched(SQUELCH_TYPE_BLOCK_TOON, 1); + selectedSquelchType = SQUELCH_TYPE_BLOCK_TOON; + selectedSquelchIndex = 1; + elseif ( numMutes > 0 ) then + FriendsFrame_SelectSquelched(SQUELCH_TYPE_MUTE, 1); + selectedSquelchType = SQUELCH_TYPE_MUTE; + selectedSquelchIndex = 1; + end + end + if ( selectedSquelchIndex > 0 ) then + FriendsFrameUnsquelchButton:Enable(); + else + FriendsFrameUnsquelchButton:Disable(); + end + + local scrollOffset = FauxScrollFrame_GetOffset(FriendsFrameIgnoreScrollFrame); + local squelchedIndex; + for i = 1, IGNORES_TO_DISPLAY, 1 do + squelchedIndex = i + scrollOffset; + button = _G["FriendsFrameIgnoreButton"..i]; + button.type = nil; + if ( squelchedIndex == ignoredHeader ) then + -- ignored header + IgnoreList_SetHeader(FriendsFrameIgnoredHeader, button); + elseif ( squelchedIndex <= lastIgnoredIndex ) then + -- ignored + button.index = squelchedIndex - ignoredHeader; + button.name:SetText(GetIgnoreName(button.index)); + button.type = SQUELCH_TYPE_IGNORE; + elseif ( blockedHeader == 1 and squelchedIndex == lastIgnoredIndex + 1 ) then + -- blocked header + IgnoreList_SetHeader(FriendsFrameBlockedInviteHeader, button); + elseif ( squelchedIndex <= lastBlockedIndex ) then + -- blocked + button.index = squelchedIndex - lastIgnoredIndex - blockedHeader; + local blockID, blockName = BNGetBlockedInfo(button.index); + button.name:SetText(blockName); + button.type = SQUELCH_TYPE_BLOCK_INVITE; + elseif ( blockedToonHeader == 1 and squelchedIndex == lastBlockedIndex + 1 ) then + -- blocked TOON header + IgnoreList_SetHeader(FriendsFrameBlockedToonHeader, button); + elseif ( squelchedIndex <= lastBlockedToonIndex ) then + -- blocked TOON + button.index = squelchedIndex - lastBlockedIndex - blockedToonHeader; + local blockID, blockName = BNGetBlockedToonInfo(button.index); + button.name:SetText(blockName); + button.type = SQUELCH_TYPE_BLOCK_TOON; + elseif ( mutedHeader == 1 and squelchedIndex == lastBlockedToonIndex + 1 ) then + -- muted header + IgnoreList_SetHeader(FriendsFrameMutedHeader, button); + elseif ( squelchedIndex <= lastMutedIndex ) then + -- muted + button.index = squelchedIndex - lastBlockedToonIndex - mutedHeader; + button.name:SetText(GetMuteName(button.index)); + button.type = SQUELCH_TYPE_MUTE; + end + if ( selectedSquelchType == button.type and selectedSquelchIndex == button.index ) then + button:LockHighlight(); + else + button:UnlockHighlight(); + end + if ( squelchedIndex > numEntries ) then + button:Hide(); + else + button:Show(); + end + end + -- ScrollFrame stuff + FauxScrollFrame_Update(FriendsFrameIgnoreScrollFrame, numEntries, IGNORES_TO_DISPLAY, FRIENDS_FRAME_IGNORE_HEIGHT ); +end + +function IgnoreList_SetHeader(header, parent) + parent.name:SetText(""); + header:SetParent(parent); + header:SetPoint("TOPLEFT", parent, 0, 0); + header:Show(); +end + +function PendingListFrame_OnShow(self) + PendingList_Update(); +end + +function PendingList_Update(newInvite) + local numPending = BNGetNumFriendInvites(); + + PendingList_UpdateTab(); + if ( numPending > 0 ) then + if ( not GetCVarBool("pendingInviteInfoShown") ) then + PendingListInfoFrame:SetFrameLevel(FriendsFramePendingButton1:GetFrameLevel() + 1); + PendingListInfoFrame:Show(); + end + + local scrollFrame = FriendsFramePendingScrollFrame; + local buttonHeight, message, _; + local heightLeft = scrollFrame.scrollHeight; + local scrollBar = scrollFrame.scrollBar; + + FriendsFramePendingButton1.message:SetHeight(0); + for i = numPending, 1, -1 do + buttonHeight = PENDING_BUTTON_MIN_HEIGHT; + _, _, _, message = BNGetFriendInviteInfo(i); + if ( message and message ~= "" ) then + FriendsFramePendingButton1.message:SetText(message); + local textHeight = min(FriendsFramePendingButton1.message:GetHeight(), MAX_INVITE_MESSAGE_HEIGHT); + buttonHeight = buttonHeight + textHeight; + end + heightLeft = heightLeft - buttonHeight; + if ( heightLeft <= 0 ) then + -- one less notch on the scrollbar if it's a perfect fit + if ( heightLeft == 0 ) then + i = i - 1; + end + local value = scrollBar:GetValue(); + scrollFrame.extraHeight = -heightLeft; + scrollFrame.max = i; + scrollBar:Show(); + scrollBar:SetMinMaxValues(0, i); + if ( newInvite ) then + -- adjust the scroll if the user is looking at the frame, otherwise jump it to the top + if ( PendingListFrame:IsShown() ) then + scrollBar:SetValue(value + 1); + else + scrollBar:SetValue(0) + end + elseif ( value <= i ) then + scrollBar:SetValue(value); + PendingList_Scroll(value); + end + return; + end + end + -- not enough buttons to have a scrollbar + scrollFrame.extraHeight = 0; + scrollFrame.max = numPending; + scrollBar:Hide(); + scrollBar:SetValue(0); + end + PendingList_Scroll(0); +end + +function PendingList_Scroll(offset) + local button, buttonHeight; + local name, surname, message; + local heightUsed = 0; + local scrollFrame = FriendsFramePendingScrollFrame; + local scrollHeight = scrollFrame.scrollHeight; + local max = scrollFrame.max; + local numPending = BNGetNumFriendInvites(); + offset = offset or scrollFrame.scrollBar:GetValue(); + -- if scrolled to the bottom and there would be a button partially showing, start with it and "scroll" it up + if ( offset == max and scrollFrame.extraHeight > 0 ) then + offset = offset - 1; + _G["FriendsFramePendingButton1"]:SetPoint("TOPLEFT", 0, scrollFrame.extraHeight); + heightUsed = heightUsed - scrollFrame.extraHeight; + else + _G["FriendsFramePendingButton1"]:SetPoint("TOPLEFT", 0, 0); + end + for i = 1, PENDING_INVITES_TO_DISPLAY do + button = _G["FriendsFramePendingButton"..i]; + offset = offset + 1; + if ( offset > numPending or heightUsed > scrollHeight ) then + button:Hide(); + else + inviteID, givenName, surname, message, timeSent, days = BNGetFriendInviteInfo(offset); + button.index = offset; + button.inviteID = inviteID; + buttonHeight = PENDING_BUTTON_MIN_HEIGHT; + if ( givenName and surname ) then + button.name:SetFormattedText(BATTLENET_NAME_FORMAT, givenName, surname); + else + button.name:SetText(UNKNOWN); + end + if ( message ) then + button.message:SetHeight(0); + button.message:SetText(message); + local textHeight = button.message:GetHeight(); + if ( textHeight > MAX_INVITE_MESSAGE_HEIGHT ) then + textHeight = MAX_INVITE_MESSAGE_HEIGHT; + button.message:SetHeight(textHeight); + end + buttonHeight = buttonHeight + textHeight; + else + button.message:SetText(""); + button.message:SetHeight(0); + end + if ( timeSent and timeSent ~= 0 ) then + button.sent:SetFormattedText(BNET_INVITE_SENT_TIME, FriendsFrame_GetLastOnline(timeSent)); + else + button.sent:SetText(""); + end + button:SetHeight(buttonHeight); + heightUsed = heightUsed + buttonHeight; + if ( PendingInvitesNew["all"] or PendingInvitesNew[inviteID] ) then + button.highlight:Show(); + else + button.highlight:Hide(); + end + button:Show(); + end + end +end + +function FriendsFramePendingScrollFrame_AdjustScroll(delta) + local scrollBar = FriendsFramePendingScrollFrame.scrollBar; + if ( scrollBar:IsShown() ) then + scrollBar:SetValue(scrollBar:GetValue() + delta); + end +end + +function PendingListFrame_OnHide() + table.wipe(PendingInvitesNew); + PendingList_UpdateTab(); +end + +function PendingListFrame_BlockCommunication(self) + local inviteID, name, surname, message = BNGetFriendInviteInfo(self:GetParent().index); + local dialog = StaticPopup_Show("CONFIRM_BLOCK_INVITES", string.format(BATTLENET_NAME_FORMAT, name, surname)); + if ( dialog ) then + dialog.data = inviteID; + end +end + +function PendingListFrame_ReportSpam(self) + local inviteID, name, surname, message = BNGetFriendInviteInfo(self:GetParent().index); + local dialog = StaticPopup_Show("CONFIRM_REPORT_SPAM_INVITE", string.format(BATTLENET_NAME_FORMAT, name, surname)); + if ( dialog ) then + dialog.data = inviteID; + end +end + +function PendingListFrame_ReportPlayer(self) + ToggleDropDownMenu(1, self:GetParent().index, PendingListFrameDropDown, "cursor", 3, -3) +end + +function PendingListFrameDropDown_OnLoad(self) + UIDropDownMenu_Initialize(self, PendingListFrameDropDown_Initialize, "MENU"); +end + +function PendingListFrameDropDown_Initialize(self) + UnitPopup_ShowMenu(self, "BN_REPORT", nil, BNET_REPORT); +end + +function PendingList_UpdateTab() + local numPending = BNGetNumFriendInvites(); + if ( numPending > 0 ) then + FriendsTabHeaderTab3:SetText(PENDING_INVITE.." ("..numPending..")"); + if ( next(PendingInvitesNew) and FriendsTabHeader.selectedTab ~= 3 and not FriendsTabHeaderTab3:IsMouseOver() ) then + FriendsTabHeaderInviteAlert:Show(); + else + FriendsTabHeaderInviteAlert:Hide(); + end + else + FriendsTabHeaderTab3:SetText(PENDING_INVITE); + FriendsTabHeaderInviteAlert:Hide(); + end + PanelTemplates_TabResize(FriendsTabHeaderTab3, 0); +end + +function WhoList_Update() + local numWhos, totalCount = GetNumWhoResults(); + local name, guild, level, race, class, zone; + local button, buttonText, classTextColor, classFileName; + local columnTable; + local whoOffset = FauxScrollFrame_GetOffset(WhoListScrollFrame); + local whoIndex; + local showScrollBar = nil; + if ( numWhos > WHOS_TO_DISPLAY ) then + showScrollBar = 1; + end + local displayedText = ""; + if ( totalCount > MAX_WHOS_FROM_SERVER ) then + displayedText = format(WHO_FRAME_SHOWN_TEMPLATE, MAX_WHOS_FROM_SERVER); + end + WhoFrameTotals:SetText(format(WHO_FRAME_TOTAL_TEMPLATE, totalCount).." "..displayedText); + for i=1, WHOS_TO_DISPLAY, 1 do + whoIndex = whoOffset + i; + button = _G["WhoFrameButton"..i]; + button.whoIndex = whoIndex; + name, guild, level, race, class, zone, classFileName = GetWhoInfo(whoIndex); + columnTable = { zone, guild, race }; + + if ( classFileName ) then + classTextColor = RAID_CLASS_COLORS[classFileName]; + else + classTextColor = HIGHLIGHT_FONT_COLOR; + end + buttonText = _G["WhoFrameButton"..i.."Name"]; + buttonText:SetText(name); + buttonText = _G["WhoFrameButton"..i.."Level"]; + buttonText:SetText(level); + buttonText = _G["WhoFrameButton"..i.."Class"]; + buttonText:SetText(class); + buttonText:SetTextColor(classTextColor.r, classTextColor.g, classTextColor.b); + local variableText = _G["WhoFrameButton"..i.."Variable"]; + variableText:SetText(columnTable[UIDropDownMenu_GetSelectedID(WhoFrameDropDown)]); + + -- If need scrollbar resize columns + if ( showScrollBar ) then + variableText:SetWidth(95); + else + variableText:SetWidth(110); + end + + -- Highlight the correct who + if ( WhoFrame.selectedWho == whoIndex ) then + button:LockHighlight(); + else + button:UnlockHighlight(); + end + + if ( whoIndex > numWhos ) then + button:Hide(); + else + button:Show(); + end + end + + if ( not WhoFrame.selectedWho ) then + WhoFrameGroupInviteButton:Disable(); + WhoFrameAddFriendButton:Disable(); + else + WhoFrameGroupInviteButton:Enable(); + WhoFrameAddFriendButton:Enable(); + WhoFrame.selectedName = GetWhoInfo(WhoFrame.selectedWho); + end + + -- If need scrollbar resize columns + if ( showScrollBar ) then + WhoFrameColumn_SetWidth(WhoFrameColumnHeader2, 105); + UIDropDownMenu_SetWidth(WhoFrameDropDown, 80); + else + WhoFrameColumn_SetWidth(WhoFrameColumnHeader2, 120); + UIDropDownMenu_SetWidth(WhoFrameDropDown, 95); + end + + -- ScrollFrame update + FauxScrollFrame_Update(WhoListScrollFrame, numWhos, WHOS_TO_DISPLAY, FRIENDS_FRAME_WHO_HEIGHT ); + + PanelTemplates_SetTab(FriendsFrame, 2); + ShowUIPanel(FriendsFrame); +end + +function GuildStatus_Update() + -- Set the tab + PanelTemplates_SetTab(FriendsFrame, 3); + -- Show the frame + ShowUIPanel(FriendsFrame); + -- Number of players in the lowest rank + FriendsFrame.playersInBotRank = 0; + + local numGuildMembers = GetNumGuildMembers(); + local name, rank, rankIndex, level, class, zone, note, officernote, online, status, classFileName; + local guildName, guildRankName, guildRankIndex = GetGuildInfo("player"); + local maxRankIndex = GuildControlGetNumRanks() - 1; + local button, buttonText, classTextColor; + local onlinecount = 0; + local guildIndex; + + -- Get selected guild member info + name, rank, rankIndex, level, class, zone, note, officernote, online = GetGuildRosterInfo(GetGuildRosterSelection()); + GuildFrame.selectedName = name; + -- If there's a selected guildmember + if ( GetGuildRosterSelection() > 0 ) then + -- Update the guild member details frame + GuildMemberDetailName:SetText(GuildFrame.selectedName); + GuildMemberDetailLevel:SetFormattedText(FRIENDS_LEVEL_TEMPLATE, level, class); + GuildMemberDetailZoneText:SetText(zone); + GuildMemberDetailRankText:SetText(rank); + if ( online ) then + GuildMemberDetailOnlineText:SetText(GUILD_ONLINE_LABEL); + else + GuildMemberDetailOnlineText:SetText(GuildFrame_GetLastOnline(GetGuildRosterSelection())); + end + -- Update public note + if ( CanEditPublicNote() ) then + PersonalNoteText:SetTextColor(1.0, 1.0, 1.0); + if ( (not note) or (note == "") ) then + note = GUILD_NOTE_EDITLABEL; + end + else + PersonalNoteText:SetTextColor(0.65, 0.65, 0.65); + end + GuildMemberNoteBackground:EnableMouse(CanEditPublicNote()); + PersonalNoteText:SetText(note); + -- Update officer note + if ( CanViewOfficerNote() ) then + if ( CanEditOfficerNote() ) then + if ( (not officernote) or (officernote == "") ) then + officernote = GUILD_OFFICERNOTE_EDITLABEL; + end + OfficerNoteText:SetTextColor(1.0, 1.0, 1.0); + else + OfficerNoteText:SetTextColor(0.65, 0.65, 0.65); + end + GuildMemberOfficerNoteBackground:EnableMouse(CanEditOfficerNote()); + OfficerNoteText:SetText(officernote); + + -- Resize detail frame + GuildMemberDetailOfficerNoteLabel:Show(); + GuildMemberOfficerNoteBackground:Show(); + GuildMemberDetailFrame:SetHeight(GUILD_DETAIL_OFFICER_HEIGHT); + else + GuildMemberDetailOfficerNoteLabel:Hide(); + GuildMemberOfficerNoteBackground:Hide(); + GuildMemberDetailFrame:SetHeight(GUILD_DETAIL_NORM_HEIGHT); + end + + -- Manage guild member related buttons + if ( CanGuildPromote() and ( rankIndex > 1 ) and ( rankIndex > (guildRankIndex + 1) ) ) then + GuildFramePromoteButton:Enable(); + else + GuildFramePromoteButton:Disable(); + end + if ( CanGuildDemote() and ( rankIndex >= 1 ) and ( rankIndex > guildRankIndex ) and ( rankIndex ~= maxRankIndex ) ) then + GuildFrameDemoteButton:Enable(); + else + GuildFrameDemoteButton:Disable(); + end + -- Hide promote/demote buttons if both disabled + if ( GuildFrameDemoteButton:IsEnabled() == 0 and GuildFramePromoteButton:IsEnabled() == 0 ) then + GuildFramePromoteButton:Hide(); + GuildFrameDemoteButton:Hide(); + else + GuildFramePromoteButton:Show(); + GuildFrameDemoteButton:Show(); + end + if ( CanGuildRemove() and ( rankIndex >= 1 ) and ( rankIndex > guildRankIndex ) ) then + GuildMemberRemoveButton:Enable(); + else + GuildMemberRemoveButton:Disable(); + end + if ( (UnitName("player") == name) or (not online) ) then + GuildMemberGroupInviteButton:Disable(); + else + GuildMemberGroupInviteButton:Enable(); + end + + GuildFrame.selectedName = GetGuildRosterInfo(GetGuildRosterSelection()); + else + GuildMemberDetailFrame:Hide(); + end + + -- Message of the day stuff + local guildMOTD = GetGuildRosterMOTD(); + if ( CanEditMOTD() ) then + if ( (not guildMOTD) or (guildMOTD == "") ) then + guildMOTD = GUILD_MOTD_EDITLABEL; + end + GuildFrameNotesText:SetTextColor(1.0, 1.0, 1.0); + GuildMOTDEditButton:Enable(); + else + GuildFrameNotesText:SetTextColor(0.65, 0.65, 0.65); + GuildMOTDEditButton:Disable(); + end + GuildFrameNotesText:SetText(CURRENT_GUILD_MOTD); + + -- Scrollbar stuff + local showScrollBar = nil; + if ( numGuildMembers > GUILDMEMBERS_TO_DISPLAY ) then + showScrollBar = 1; + end + + -- Get number of online members + for i=1, numGuildMembers, 1 do + name, rank, rankIndex, level, class, zone, note, officernote, online = GetGuildRosterInfo(i); + if ( online ) then + onlinecount = onlinecount + 1; + end + if ( rankIndex == maxRankIndex ) then + FriendsFrame.playersInBotRank = FriendsFrame.playersInBotRank + 1; + end + end + GuildFrameTotals:SetFormattedText(GUILD_TOTAL, numGuildMembers); + GuildFrameOnlineTotals:SetFormattedText(GUILD_TOTALONLINE, onlinecount); + + -- Update global guild frame buttons + if ( IsGuildLeader() ) then + GuildFrameControlButton:Enable(); + else + GuildFrameControlButton:Disable(); + end + if ( CanGuildInvite() ) then + GuildFrameAddMemberButton:Enable(); + else + GuildFrameAddMemberButton:Disable(); + end + + + if ( FriendsFrame.playerStatusFrame ) then + -- Player specific info + local guildOffset = FauxScrollFrame_GetOffset(GuildListScrollFrame); + + for i=1, GUILDMEMBERS_TO_DISPLAY, 1 do + guildIndex = guildOffset + i; + button = _G["GuildFrameButton"..i]; + button.guildIndex = guildIndex; + name, rank, rankIndex, level, class, zone, note, officernote, online, status, classFileName = GetGuildRosterInfo(guildIndex); + + if ( not online ) then + buttonText = _G["GuildFrameButton"..i.."Name"]; + buttonText:SetText(name); + buttonText:SetTextColor(0.5, 0.5, 0.5); + buttonText = _G["GuildFrameButton"..i.."Zone"]; + buttonText:SetText(zone); + buttonText:SetTextColor(0.5, 0.5, 0.5); + buttonText = _G["GuildFrameButton"..i.."Level"]; + buttonText:SetText(level); + buttonText:SetTextColor(0.5, 0.5, 0.5); + buttonText = _G["GuildFrameButton"..i.."Class"]; + buttonText:SetText(class); + buttonText:SetTextColor(0.5, 0.5, 0.5); + else + if ( classFileName ) then + classTextColor = RAID_CLASS_COLORS[classFileName]; + else + classTextColor = NORMAL_FONT_COLOR; + end + + buttonText = _G["GuildFrameButton"..i.."Name"]; + buttonText:SetText(name); + buttonText:SetTextColor(NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b); + buttonText = _G["GuildFrameButton"..i.."Zone"]; + buttonText:SetText(zone); + buttonText:SetTextColor(1.0, 1.0, 1.0); + buttonText = _G["GuildFrameButton"..i.."Level"]; + buttonText:SetText(level); + buttonText:SetTextColor(1.0, 1.0, 1.0); + buttonText = _G["GuildFrameButton"..i.."Class"]; + buttonText:SetText(class); + buttonText:SetTextColor(classTextColor.r, classTextColor.g, classTextColor.b); + end + + -- If need scrollbar resize columns + if ( showScrollBar ) then + _G["GuildFrameButton"..i.."Zone"]:SetWidth(95); + else + _G["GuildFrameButton"..i.."Zone"]:SetWidth(110); + end + + -- Highlight the correct who + if ( GetGuildRosterSelection() == guildIndex ) then + button:LockHighlight(); + else + button:UnlockHighlight(); + end + + if ( guildIndex > numGuildMembers ) then + button:Hide(); + else + button:Show(); + end + end + + GuildFrameGuildListToggleButton:SetText(PLAYER_STATUS); + -- If need scrollbar resize column headers + if ( showScrollBar ) then + WhoFrameColumn_SetWidth(GuildFrameColumnHeader2, 105); + GuildFrameGuildListToggleButton:SetPoint("LEFT", "GuildFrame", "LEFT", 284, -67); + else + WhoFrameColumn_SetWidth(GuildFrameColumnHeader2, 120); + GuildFrameGuildListToggleButton:SetPoint("LEFT", "GuildFrame", "LEFT", 307, -67); + end + -- ScrollFrame update + FauxScrollFrame_Update(GuildListScrollFrame, numGuildMembers, GUILDMEMBERS_TO_DISPLAY, FRIENDS_FRAME_GUILD_HEIGHT ); + + GuildPlayerStatusFrame:Show(); + GuildStatusFrame:Hide(); + else + -- Guild specific info + local year, month, day, hour; + local yearlabel, monthlabel, daylabel, hourlabel; + local guildOffset = FauxScrollFrame_GetOffset(GuildListScrollFrame); + local classFileName; + + for i=1, GUILDMEMBERS_TO_DISPLAY, 1 do + guildIndex = guildOffset + i; + button = _G["GuildFrameGuildStatusButton"..i]; + button.guildIndex = guildIndex; + name, rank, rankIndex, level, class, zone, note, officernote, online, status, classFileName = GetGuildRosterInfo(guildIndex); + + _G["GuildFrameGuildStatusButton"..i.."Name"]:SetText(name); + _G["GuildFrameGuildStatusButton"..i.."Rank"]:SetText(rank); + _G["GuildFrameGuildStatusButton"..i.."Note"]:SetText(note); + + if ( online ) then + if ( status == "" ) then + _G["GuildFrameGuildStatusButton"..i.."Online"]:SetText(GUILD_ONLINE_LABEL); + else + _G["GuildFrameGuildStatusButton"..i.."Online"]:SetText(status); + end + + if ( classFileName ) then + classTextColor = RAID_CLASS_COLORS[classFileName]; + else + classTextColor = NORMAL_FONT_COLOR; + end + _G["GuildFrameGuildStatusButton"..i.."Name"]:SetTextColor(NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b); + _G["GuildFrameGuildStatusButton"..i.."Rank"]:SetTextColor(1.0, 1.0, 1.0); + _G["GuildFrameGuildStatusButton"..i.."Note"]:SetTextColor(1.0, 1.0, 1.0); + _G["GuildFrameGuildStatusButton"..i.."Online"]:SetTextColor(classTextColor.r, classTextColor.g, classTextColor.b); + else + _G["GuildFrameGuildStatusButton"..i.."Online"]:SetText(GuildFrame_GetLastOnline(guildIndex)); + _G["GuildFrameGuildStatusButton"..i.."Name"]:SetTextColor(0.5, 0.5, 0.5); + _G["GuildFrameGuildStatusButton"..i.."Rank"]:SetTextColor(0.5, 0.5, 0.5); + _G["GuildFrameGuildStatusButton"..i.."Note"]:SetTextColor(0.5, 0.5, 0.5); + _G["GuildFrameGuildStatusButton"..i.."Online"]:SetTextColor(0.5, 0.5, 0.5); + end + + -- If need scrollbar resize columns + if ( showScrollBar ) then + _G["GuildFrameGuildStatusButton"..i.."Note"]:SetWidth(70); + else + _G["GuildFrameGuildStatusButton"..i.."Note"]:SetWidth(85); + end + + -- Highlight the correct who + if ( GetGuildRosterSelection() == guildIndex ) then + button:LockHighlight(); + else + button:UnlockHighlight(); + end + + if ( guildIndex > numGuildMembers ) then + button:Hide(); + else + button:Show(); + end + end + + GuildFrameGuildListToggleButton:SetText(GUILD_STATUS); + -- If need scrollbar resize columns + if ( showScrollBar ) then + WhoFrameColumn_SetWidth(GuildFrameGuildStatusColumnHeader3, 75); + GuildFrameGuildListToggleButton:SetPoint("LEFT", "GuildFrame", "LEFT", 284, -67); + else + WhoFrameColumn_SetWidth(GuildFrameGuildStatusColumnHeader3, 90); + GuildFrameGuildListToggleButton:SetPoint("LEFT", "GuildFrame", "LEFT", 307, -67); + end + + -- ScrollFrame update + FauxScrollFrame_Update(GuildListScrollFrame, numGuildMembers, GUILDMEMBERS_TO_DISPLAY, FRIENDS_FRAME_GUILD_HEIGHT ); + + GuildPlayerStatusFrame:Hide(); + GuildStatusFrame:Show(); + end +end + +function WhoFrameColumn_SetWidth(frame, width) + frame:SetWidth(width); + _G[frame:GetName().."Middle"]:SetWidth(width - 9); +end + +function WhoFrameDropDown_Initialize() + local info = UIDropDownMenu_CreateInfo(); + for i=1, getn(WHOFRAME_DROPDOWN_LIST), 1 do + info.text = WHOFRAME_DROPDOWN_LIST[i].name; + info.func = WhoFrameDropDownButton_OnClick; + info.checked = nil; + UIDropDownMenu_AddButton(info); + end +end + +function WhoFrameDropDown_OnLoad(self) + UIDropDownMenu_Initialize(self, WhoFrameDropDown_Initialize); + UIDropDownMenu_SetWidth(self, 80); + UIDropDownMenu_SetButtonWidth(self, 24); + UIDropDownMenu_JustifyText(WhoFrameDropDown, "LEFT") +end + +function WhoFrameDropDownButton_OnClick(self) + UIDropDownMenu_SetSelectedID(WhoFrameDropDown, self:GetID()); + WhoList_Update(); +end + +function FriendsFrame_OnEvent(self, event, ...) + if ( event == "FRIENDLIST_SHOW" ) then + FriendsList_Update(); + FriendsFrame_Update(); + elseif ( event == "FRIENDLIST_UPDATE" or event == "PARTY_MEMBERS_CHANGED" ) then + FriendsList_Update(); + elseif ( event == "BN_FRIEND_LIST_SIZE_CHANGED" or event == "BN_FRIEND_INFO_CHANGED" ) then + BNetBroadcasts, numOnlineBroadcasts, numOfflineBroadcasts = BNGetCustomMessageTable(BNetBroadcasts); + if(not BNetBroadcasts) then + BNetBroadcasts = { }; + end + FriendsList_Update(); + elseif ( event == "BN_CUSTOM_MESSAGE_CHANGED" ) then + local arg1 = ...; + if ( arg1 ) then --There is no presenceID given if this is ourself. + BNetBroadcasts, numOnlineBroadcasts, numOfflineBroadcasts = BNGetCustomMessageTable(BNetBroadcasts); + if(not BNetBroadcasts) then + BNetBroadcasts = { }; + end + FriendsList_Update(); + else + FriendsFrameBroadcastInput_UpdateDisplay(); + end + elseif ( event == "BN_CUSTOM_MESSAGE_LOADED" ) then + FriendsFrameBroadcastInput_UpdateDisplay(); + elseif ( event == "BN_FRIEND_INVITE_ADDED" ) then + local arg1 = ...; + if ( arg1 ) then + PendingInvitesNew[arg1] = true; + PendingList_Update(true); + end + elseif ( event == "BN_FRIEND_INVITE_LIST_INITIALIZED" ) then + PendingInvitesNew["all"] = true; + PendingList_Update(); + elseif ( event == "BN_FRIEND_INVITE_REMOVED" ) then + PendingList_Update(); + elseif ( event == "IGNORELIST_UPDATE" or event == "MUTELIST_UPDATE" or event == "BN_BLOCK_LIST_UPDATED" ) then + IgnoreList_Update(); + elseif ( event == "WHO_LIST_UPDATE" ) then + WhoList_Update(); + FriendsFrame_Update(); + elseif ( event == "GUILD_ROSTER_UPDATE" ) then + GuildInfoFrame.cachedText = nil; + if ( GuildFrame:IsShown() ) then + local arg1 = ...; + if ( arg1 ) then + GuildRoster(); + end + GuildStatus_Update(); + FriendsFrame_Update(); + GuildControlPopupFrame_Initialize(); + end + elseif ( event == "PLAYER_GUILD_UPDATE" ) then + if ( FriendsFrame:IsVisible() ) then + InGuildCheck(); + end + if ( not IsInGuild() ) then + GuildControlPopupFrame.initialized = false; + end + elseif ( event == "GUILD_MOTD") then + CURRENT_GUILD_MOTD = ...; + GuildFrameNotesText:SetText(CURRENT_GUILD_MOTD); + elseif ( event == "VOICE_CHAT_ENABLED_UPDATE" ) then + VoiceChat_Toggle(); + elseif ( event == "PLAYER_FLAGS_CHANGED" ) then + SynchronizeBNetStatus(); + FriendsFrameStatusDropDown_Update(); + elseif ( event == "PLAYER_ENTERING_WORLD" or event == "BN_CONNECTED" or event == "BN_DISCONNECTED" or event == "BN_SELF_ONLINE" ) then + FriendsFrame_CheckBattlenetStatus(); + end +end + +function FriendsFrameFriendButton_OnClick(self, button) + if ( button == "LeftButton" ) then + PlaySound("igMainMenuOptionCheckBoxOn"); + FriendsFrame_SelectFriend(self.buttonType, self.id); + FriendsList_Update(); + elseif ( button == "RightButton" ) then + PlaySound("igMainMenuOptionCheckBoxOn"); + if ( self.buttonType == FRIENDS_BUTTON_TYPE_BNET ) then + -- bnet friend + local presenceID, givenName, surname, toonName, toonID, client, isOnline = BNGetFriendInfo(self.id); + FriendsFrame_ShowBNDropdown(format(BATTLENET_NAME_FORMAT, givenName, surname), isOnline, nil, nil, nil, 1, presenceID); + else + -- wow friend + local name, level, class, area, connected = GetFriendInfo(self.id); + FriendsFrame_ShowDropdown(name, connected, nil, nil, nil, 1); + end + end +end + +function FriendsFrame_SelectFriend(friendType, id) + if ( friendType == FRIENDS_BUTTON_TYPE_WOW ) then + SetSelectedFriend(id); + elseif ( friendType == FRIENDS_BUTTON_TYPE_BNET ) then + BNSetSelectedFriend(id); + end + FriendsFrame.selectedFriendType = friendType; +end + +function FriendsFrame_SelectSquelched(ignoreType, index) + if ( ignoreType == SQUELCH_TYPE_IGNORE ) then + SetSelectedIgnore(index); + elseif ( ignoreType == SQUELCH_TYPE_BLOCK_INVITE ) then + BNSetSelectedBlock(index); + elseif ( ignoreType == SQUELCH_TYPE_BLOCK_TOON ) then + BNSetSelectedToonBlock(index); + elseif ( ignoreType == SQUELCH_TYPE_MUTE ) then + SetSelectedMute(index); + end + FriendsFrame.selectedSquelchType = ignoreType; +end + +function FriendsFrameAddFriendButton_OnClick(self) + if ( UnitIsPlayer("target") and UnitCanCooperate("player", "target") and not GetFriendInfo(UnitName("target")) ) then + local name, server = UnitName("target"); + if ( server and (not UnitIsSameServer("player", "target")) ) then + name = name.."-"..server; + end + AddFriend(name); + PlaySound("UChatScrollButton"); + else + if ( BNFeaturesEnabled() ) then + AddFriendEntryFrame_Collapse(true); + AddFriendFrame.editFocus = AddFriendNameEditBox; + StaticPopupSpecial_Show(AddFriendFrame); + if ( GetCVarBool("addFriendInfoShown") ) then + AddFriendFrame_ShowEntry(); + else + AddFriendFrame_ShowInfo(); + end + else + StaticPopup_Show("ADD_FRIEND"); + end + end +end + +function FriendsFrameSendMessageButton_OnClick(self) + local name; + if ( FriendsFrame.selectedFriendType == FRIENDS_BUTTON_TYPE_WOW ) then + name = GetFriendInfo(FriendsFrame.selectedFriend); + elseif ( FriendsFrame.selectedFriendType == FRIENDS_BUTTON_TYPE_BNET ) then + local presenceID, givenName, surname = BNGetFriendInfo(FriendsFrame.selectedFriend); + name = string.format(BATTLENET_NAME_FORMAT, givenName, surname); + end + if ( name ) then + PlaySound("igMainMenuOptionCheckBoxOn"); + ChatFrame_SendTell(name); + end +end + +function FriendsFrameMuteButton_OnClick(self) + SetSelectedMute(self:GetID()); + MutedList_Update(); +end + +function FriendsFrameUnsquelchButton_OnClick(self) + local selectedSquelchType = FriendsFrame.selectedSquelchType; + if ( selectedSquelchType == SQUELCH_TYPE_IGNORE ) then + local name = GetIgnoreName(GetSelectedIgnore()); + DelIgnore(name); + elseif ( selectedSquelchType == SQUELCH_TYPE_BLOCK_INVITE ) then + local blockID = BNGetBlockedInfo(BNGetSelectedBlock()); + BNSetBlocked(blockID, false); + elseif ( selectedSquelchType == SQUELCH_TYPE_BLOCK_TOON ) then + local blockID = BNGetBlockedToonInfo(BNGetSelectedToonBlock()); + BNSetToonBlocked(blockID, false); + elseif ( selectedSquelchType == SQUELCH_TYPE_MUTE ) then + local name = GetMuteName(GetSelectedMute()); + DelMute(name); + end + PlaySound("igMainMenuOptionCheckBoxOn"); +end + +function FriendsFrameWhoButton_OnClick(self, button) + if ( button == "LeftButton" ) then + WhoFrame.selectedWho = _G["WhoFrameButton"..self:GetID()].whoIndex; + WhoFrame.selectedName = _G["WhoFrameButton"..self:GetID().."Name"]:GetText(); + WhoList_Update(); + else + local name = _G["WhoFrameButton"..self:GetID().."Name"]:GetText(); + FriendsFrame_ShowDropdown(name, 1); + end +end + +function FriendsFrameGuildStatusButton_OnClick(self, button) + if ( button == "LeftButton" ) then + GuildFrame.previousSelectedGuildMember = GuildFrame.selectedGuildMember; + GuildFrame.selectedGuildMember = self.guildIndex; + GuildFrame.selectedName = _G[self:GetName().."Name"]:GetText(); + SetGuildRosterSelection(GuildFrame.selectedGuildMember); + -- Toggle guild details frame + if ( GuildMemberDetailFrame:IsShown() and (GuildFrame.previousSelectedGuildMember and (GuildFrame.previousSelectedGuildMember == GuildFrame.selectedGuildMember)) ) then + GuildMemberDetailFrame:Hide(); + GuildFrame.selectedGuildMember = 0; + SetGuildRosterSelection(0); + else + GuildFramePopup_Show(GuildMemberDetailFrame); + end + GuildStatus_Update(); + else + local guildIndex = self.guildIndex; + local name, rank, rankIndex, level, class, zone, note, officernote, online = GetGuildRosterInfo(guildIndex); + FriendsFrame_ShowDropdown(name, online); + end +end + +function FriendsFrame_UnIgnore(button, name) + DelIgnore(name); +end + +function FriendsFrame_UnMute(button, name) + DelMute(name); +end + +function FriendsFrame_UnBlock(button, blockID) + BNSetBlocked(blockID, false); +end + +function FriendsFrame_RemoveFriend() + if ( FriendsFrame.selectedFriend ) then + RemoveFriend(FriendsFrame.selectedFriend); + PlaySound("UChatScrollButton"); + end +end + +function FriendsFrame_SendMessage() + local name = GetFriendInfo(FriendsFrame.selectedFriend); + ChatFrame_SendTell(name); + PlaySound("UChatScrollButton"); +end + +function FriendsFrame_GroupInvite() + local name = GetFriendInfo(FriendsFrame.selectedFriend); + InviteUnit(name); + PlaySound("UChatScrollButton"); +end + +function ToggleFriendsFrame(tab) + if ( not tab ) then + if ( FriendsFrame:IsShown() ) then + HideUIPanel(FriendsFrame); + else + ShowUIPanel(FriendsFrame); + end + else + -- If not in a guild don't do anything when they try to toggle the guild tab + if ( tab == 3 and not IsInGuild() ) then + return; + end + if ( tab == PanelTemplates_GetSelectedTab(FriendsFrame) and FriendsFrame:IsShown() ) then + HideUIPanel(FriendsFrame); + return; + end + PanelTemplates_SetTab(FriendsFrame, tab); + if ( FriendsFrame:IsShown() ) then + FriendsFrame_OnShow(); + else + ShowUIPanel(FriendsFrame); + end + end +end + +function WhoFrameEditBox_OnEnterPressed(self) + SendWho(self:GetText()); + self:ClearFocus(); +end + +function ToggleFriendsPanel() + local friendsTabShown = + FriendsFrame:IsShown() and + PanelTemplates_GetSelectedTab(FriendsFrame) == 1 and + FriendsTabHeader.selectedTab == 1; + + if ( friendsTabShown ) then + HideUIPanel(FriendsFrame); + else + PanelTemplates_SetTab(FriendsFrame, 1); + PanelTemplates_SetTab(FriendsTabHeader, 1); + ShowUIPanel(FriendsFrame); + end +end + +function ShowWhoPanel() + PanelTemplates_SetTab(FriendsFrame, 2); + if ( FriendsFrame:IsShown() ) then + FriendsFrame_OnShow(); + else + ShowUIPanel(FriendsFrame); + end +end + +function ToggleIgnorePanel() + local ignoreTabShown = + FriendsFrame:IsShown() and + PanelTemplates_GetSelectedTab(FriendsFrame) == 1 and + FriendsTabHeader.selectedTab == 2; + + if ( ignoreTabShown ) then + HideUIPanel(FriendsFrame); + else + PanelTemplates_SetTab(FriendsFrame, 1); + PanelTemplates_SetTab(FriendsTabHeader, 2); + FriendsFrame_Update(); + ShowUIPanel(FriendsFrame); + end +end + +function WhoFrame_GetDefaultWhoCommand() + local level = UnitLevel("player"); + local minLevel = level-3; + if ( minLevel <= 0 ) then + minLevel = 1; + end + local command = WHO_TAG_ZONE.."\""..GetRealZoneText().."\" "..minLevel.."-"..(level+3); + return command; +end + +function GuildControlPopupFrame_OnLoad() + local buttonText; + for i=1, 17 do + buttonText = _G["GuildControlPopupFrameCheckbox"..i.."Text"]; + if ( buttonText ) then + buttonText:SetText(_G["GUILDCONTROL_OPTION"..i]); + end + end + GuildControlTabPermissionsViewTabText:SetText(GUILDCONTROL_VIEW_TAB); + GuildControlTabPermissionsDepositItemsText:SetText(GUILDCONTROL_DEPOSIT_ITEMS); + GuildControlTabPermissionsUpdateTextText:SetText(GUILDCONTROL_UPDATE_TEXT); + ClearPendingGuildBankPermissions(); +end + +--Need to call this function on an event since the guildroster is not available during OnLoad() +function GuildControlPopupFrame_Initialize() + if ( GuildControlPopupFrame.initialized ) then + return; + end + UIDropDownMenu_Initialize(GuildControlPopupFrameDropDown, GuildControlPopupFrameDropDown_Initialize); + GuildControlSetRank(1); + UIDropDownMenu_SetSelectedID(GuildControlPopupFrameDropDown, 1); + UIDropDownMenu_SetText(GuildControlPopupFrameDropDown, GuildControlGetRankName(1)); + -- Select tab 1 + GuildBankTabPermissionsTab_OnClick(1); + + GuildControlPopupFrame:SetScript("OnEvent", GuildControlPopupFrame_OnEvent); + GuildControlPopupFrame.initialized = 1; + GuildControlPopupFrame.rank = GuildControlGetRankName(1); +end + +function GuildControlPopupFrame_OnShow() + FriendsFrame:SetAttribute("UIPanelLayout-defined", nil); + FriendsFrame.guildControlShow = 1; + GuildControlPopupAcceptButton:Disable(); + -- Update popup + GuildControlPopupframe_Update(); + + UIPanelWindows["FriendsFrame"].width = FriendsFrame:GetWidth() + GuildControlPopupFrame:GetWidth(); + UpdateUIPanelPositions(FriendsFrame); + --GuildControlPopupFrame:RegisterEvent("GUILD_ROSTER_UPDATE"); --It was decided that having a risk of conflict when two people are editing the guild permissions at once is better than resetting whenever someone joins the guild or changes ranks. +end + +function GuildControlPopupFrame_OnEvent (self, event, ...) + if ( not IsGuildLeader(UnitName("player")) ) then + GuildControlPopupFrame:Hide(); + return; + end + + local rank + for i = 1, GuildControlGetNumRanks() do + rank = GuildControlGetRankName(i); + if ( GuildControlPopupFrame.rank and rank == GuildControlPopupFrame.rank ) then + UIDropDownMenu_SetSelectedID(GuildControlPopupFrameDropDown, i); + UIDropDownMenu_SetText(GuildControlPopupFrameDropDown, rank); + end + end + + GuildControlPopupframe_Update() +end + +function GuildControlPopupFrame_OnHide() + FriendsFrame:SetAttribute("UIPanelLayout-defined", nil); + FriendsFrame.guildControlShow = 0; + + UIPanelWindows["FriendsFrame"].width = FriendsFrame:GetWidth(); + UpdateUIPanelPositions(); + + GuildControlPopupFrame.goldChanged = nil; + GuildControlPopupFrame:UnregisterEvent("GUILD_ROSTER_UPDATE"); +end + +function GuildControlPopupframe_Update(loadPendingTabPermissions, skipCheckboxUpdate) + -- Skip non-tab specific updates to fix Bug ID: 110210 + if ( not skipCheckboxUpdate ) then + -- Update permission flags + GuildControlCheckboxUpdate(GuildControlGetRankFlags()); + end + + local rankID = UIDropDownMenu_GetSelectedID(GuildControlPopupFrameDropDown); + GuildControlPopupFrameEditBox:SetText(GuildControlGetRankName(rankID)); + if ( GuildControlPopupFrame.previousSelectedRank and GuildControlPopupFrame.previousSelectedRank ~= rankID ) then + ClearPendingGuildBankPermissions(); + end + GuildControlPopupFrame.previousSelectedRank = rankID; + + --If rank to modify is guild master then gray everything out + if ( IsGuildLeader() and rankID == 1 ) then + GuildBankTabLabel:SetVertexColor(GRAY_FONT_COLOR.r, GRAY_FONT_COLOR.g, GRAY_FONT_COLOR.b); + GuildControlTabPermissionsDepositItems:SetChecked(1); + GuildControlTabPermissionsViewTab:SetChecked(1); + GuildControlTabPermissionsUpdateText:SetChecked(1); + BlizzardOptionsPanel_CheckButton_Disable(GuildControlTabPermissionsDepositItems); + BlizzardOptionsPanel_CheckButton_Disable(GuildControlTabPermissionsViewTab); + BlizzardOptionsPanel_CheckButton_Disable(GuildControlTabPermissionsUpdateText); + GuildControlTabPermissionsWithdrawItemsText:SetVertexColor(GRAY_FONT_COLOR.r, GRAY_FONT_COLOR.g, GRAY_FONT_COLOR.b); + GuildControlWithdrawItemsEditBox:SetNumeric(nil); + GuildControlWithdrawItemsEditBox:SetTextColor(GRAY_FONT_COLOR.r, GRAY_FONT_COLOR.g, GRAY_FONT_COLOR.b); + GuildControlWithdrawItemsEditBox:SetText(UNLIMITED); + GuildControlWithdrawItemsEditBox:ClearFocus(); + GuildControlWithdrawItemsEditBoxMask:Show(); + GuildControlWithdrawGoldText:SetVertexColor(GRAY_FONT_COLOR.r, GRAY_FONT_COLOR.g, GRAY_FONT_COLOR.b); + GuildControlWithdrawGoldAmountText:SetVertexColor(GRAY_FONT_COLOR.r, GRAY_FONT_COLOR.g, GRAY_FONT_COLOR.b); + GuildControlWithdrawGoldEditBox:SetNumeric(nil); + GuildControlWithdrawGoldEditBox:SetMaxLetters(0); + GuildControlWithdrawGoldEditBox:SetTextColor(GRAY_FONT_COLOR.r, GRAY_FONT_COLOR.g, GRAY_FONT_COLOR.b); + GuildControlWithdrawGoldEditBox:SetText(UNLIMITED); + GuildControlWithdrawGoldEditBox:ClearFocus(); + GuildControlWithdrawGoldEditBoxMask:Show(); + BlizzardOptionsPanel_CheckButton_Disable(GuildControlPopupFrameCheckbox15); + BlizzardOptionsPanel_CheckButton_Disable(GuildControlPopupFrameCheckbox16); + else + if ( GetNumGuildBankTabs() == 0 ) then + -- No tabs, no permissions! Disable the tab related doohickies + GuildBankTabLabel:SetVertexColor(GRAY_FONT_COLOR.r, GRAY_FONT_COLOR.g, GRAY_FONT_COLOR.b); + BlizzardOptionsPanel_CheckButton_Disable(GuildControlTabPermissionsViewTab); + BlizzardOptionsPanel_CheckButton_Disable(GuildControlTabPermissionsDepositItems); + BlizzardOptionsPanel_CheckButton_Disable(GuildControlTabPermissionsUpdateText); + GuildControlTabPermissionsWithdrawItemsText:SetVertexColor(GRAY_FONT_COLOR.r, GRAY_FONT_COLOR.g, GRAY_FONT_COLOR.b); + GuildControlWithdrawItemsEditBox:SetText(UNLIMITED); + GuildControlWithdrawItemsEditBox:ClearFocus(); + GuildControlWithdrawItemsEditBoxMask:Show(); + else + GuildBankTabLabel:SetVertexColor(NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b); + BlizzardOptionsPanel_CheckButton_Enable(GuildControlTabPermissionsViewTab); + GuildControlTabPermissionsWithdrawItemsText:SetVertexColor(NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b); + GuildControlWithdrawItemsEditBox:SetNumeric(1); + GuildControlWithdrawItemsEditBox:SetTextColor(HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b); + GuildControlWithdrawItemsEditBoxMask:Hide(); + end + + GuildControlWithdrawGoldText:SetVertexColor(NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b); + GuildControlWithdrawGoldAmountText:SetVertexColor(NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b); + GuildControlWithdrawGoldEditBox:SetNumeric(1); + GuildControlWithdrawGoldEditBox:SetMaxLetters(MAX_GOLD_WITHDRAW_DIGITS); + GuildControlWithdrawGoldEditBox:SetTextColor(HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b); + GuildControlWithdrawGoldEditBoxMask:Hide(); + BlizzardOptionsPanel_CheckButton_Enable(GuildControlPopupFrameCheckbox15); + BlizzardOptionsPanel_CheckButton_Enable(GuildControlPopupFrameCheckbox16); + + -- Update tab specific info + local viewTab, canDeposit, canUpdateText, numWithdrawals = GetGuildBankTabPermissions(GuildControlPopupFrameTabPermissions.selectedTab); + if ( rankID == 1 ) then + --If is guildmaster then force checkboxes to be selected + viewTab = 1; + canDeposit = 1; + canUpdateText = 1; + elseif ( loadPendingTabPermissions ) then + local permissions = PENDING_GUILDBANK_PERMISSIONS[GuildControlPopupFrameTabPermissions.selectedTab]; + local value; + value = permissions[GuildControlTabPermissionsViewTab:GetID()]; + if ( value ) then + viewTab = value; + end + value = permissions[GuildControlTabPermissionsDepositItems:GetID()]; + if ( value ) then + canDeposit = value; + end + value = permissions[GuildControlTabPermissionsUpdateText:GetID()]; + if ( value ) then + canUpdateText = value; + end + value = permissions["withdraw"]; + if ( value ) then + numWithdrawals = value; + end + end + GuildControlTabPermissionsViewTab:SetChecked(viewTab); + GuildControlTabPermissionsDepositItems:SetChecked(canDeposit); + GuildControlTabPermissionsUpdateText:SetChecked(canUpdateText); + GuildControlWithdrawItemsEditBox:SetText(numWithdrawals); + local goldWithdrawLimit = GetGuildBankWithdrawLimit(); + -- Only write to the editbox if the value hasn't been changed by the player + if ( not GuildControlPopupFrame.goldChanged ) then + if ( goldWithdrawLimit >= 0 ) then + GuildControlWithdrawGoldEditBox:SetText(goldWithdrawLimit); + else + -- This is for the guild leader who defaults to -1 + GuildControlWithdrawGoldEditBox:SetText(MAX_GOLD_WITHDRAW); + end + end + GuildControlPopup_UpdateDepositCheckBox(); + end + + --Only show available tabs + local tab; + local numTabs = GetNumGuildBankTabs(); + local name, permissionsTabBackground, permissionsText; + for i=1, MAX_GUILDBANK_TABS do + name = GetGuildBankTabInfo(i); + tab = _G["GuildBankTabPermissionsTab"..i]; + + if ( i <= numTabs ) then + tab:Show(); + tab.tooltip = name; + permissionsTabBackground = _G["GuildBankTabPermissionsTab"..i.."Background"]; + permissionsText = _G["GuildBankTabPermissionsTab"..i.."Text"]; + if ( GuildControlPopupFrameTabPermissions.selectedTab == i ) then + tab:LockHighlight(); + permissionsTabBackground:SetTexCoord(0, 1.0, 0, 1.0); + permissionsTabBackground:SetHeight(32); + permissionsText:SetPoint("CENTER", permissionsTabBackground, "CENTER", 0, -3); + else + tab:UnlockHighlight(); + permissionsTabBackground:SetTexCoord(0, 1.0, 0, 0.875); + permissionsTabBackground:SetHeight(28); + permissionsText:SetPoint("CENTER", permissionsTabBackground, "CENTER", 0, -5); + end + if ( IsGuildLeader() and rankID == 1 ) then + tab:Disable(); + else + tab:Enable(); + end + else + tab:Hide(); + end + end +end + +function WithdrawGoldEditBox_Update() + if ( not GuildControlPopupFrameCheckbox15:GetChecked() and not GuildControlPopupFrameCheckbox16:GetChecked() ) then + GuildControlWithdrawGoldAmountText:SetVertexColor(GRAY_FONT_COLOR.r, GRAY_FONT_COLOR.g, GRAY_FONT_COLOR.b); + GuildControlWithdrawGoldEditBox:SetTextColor(GRAY_FONT_COLOR.r, GRAY_FONT_COLOR.g, GRAY_FONT_COLOR.b); + GuildControlWithdrawGoldEditBox:ClearFocus(); + GuildControlWithdrawGoldEditBoxMask:Show(); + else + GuildControlWithdrawGoldAmountText:SetVertexColor(NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b); + GuildControlWithdrawGoldEditBox:SetTextColor(HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b); + GuildControlWithdrawGoldEditBoxMask:Hide(); + end +end + +function GuildControlPopupAcceptButton_OnClick() + local amount = GuildControlWithdrawGoldEditBox:GetText(); + if(amount and amount ~= "" and amount ~= UNLIMITED and tonumber(amount) and tonumber(amount) > 0) then + SetGuildBankWithdrawLimit(amount); + else + SetGuildBankWithdrawLimit(0); + end + SavePendingGuildBankTabPermissions() + GuildControlSaveRank(GuildControlPopupFrameEditBox:GetText()); + GuildStatus_Update(); + GuildControlPopupAcceptButton:Disable(); + UIDropDownMenu_SetText(GuildControlPopupFrameDropDown, GuildControlPopupFrameEditBox:GetText()); + GuildControlPopupFrame:Hide(); + ClearPendingGuildBankPermissions(); +end + +function GuildControlPopupFrameDropDown_OnLoad(self) + UIDropDownMenu_SetWidth(self, 160); + UIDropDownMenu_SetButtonWidth(self, 54); + UIDropDownMenu_JustifyText(GuildControlPopupFrameDropDown, "LEFT"); +end + +function GuildControlPopupFrameDropDown_Initialize() + local info = UIDropDownMenu_CreateInfo(); + for i=1, GuildControlGetNumRanks() do + info.text = GuildControlGetRankName(i); + info.func = GuildControlPopupFrameDropDownButton_OnClick; + info.checked = nil; + UIDropDownMenu_AddButton(info); + end +end + +function GuildControlPopupFrameDropDownButton_OnClick(self) + local rank = self:GetID(); + UIDropDownMenu_SetSelectedID(GuildControlPopupFrameDropDown, rank); + GuildControlSetRank(rank); + GuildControlPopupFrame.rank = GuildControlGetRankName(rank); + GuildControlPopupFrame.goldChanged = nil; + GuildControlPopupframe_Update(); + GuildControlPopupFrameAddRankButton_OnUpdate(GuildControlPopupFrameAddRankButton); + GuildControlPopupFrameRemoveRankButton_OnUpdate(GuildControlPopupFrameRemoveRankButton); + GuildControlPopupAcceptButton:Disable(); +end + +function GuildControlCheckboxUpdate(...) + local checkbox; + for i=1, select("#", ...), 1 do + checkbox = _G["GuildControlPopupFrameCheckbox"..i] + if ( checkbox ) then + checkbox:SetChecked(select(i, ...)); + else + --We need to skip checkbox 14 since it's a deprecated flag + --message("GuildControlPopupFrameCheckbox"..i.." does not exist!"); + end + end +end + +function GuildControlPopupFrameAddRankButton_OnUpdate(self) + if ( GuildControlGetNumRanks() >= 10 ) then + self:Disable(); + else + self:Enable(); + end +end + +function GuildControlPopupFrameRemoveRankButton_OnClick() + GuildControlDelRank(GuildControlGetRankName(UIDropDownMenu_GetSelectedID(GuildControlPopupFrameDropDown))); + GuildControlPopupFrame.rank = GuildControlGetRankName(1); + GuildControlSetRank(1); + GuildStatus_Update(); + UIDropDownMenu_SetSelectedID(GuildControlPopupFrameDropDown, 1); + GuildControlPopupFrameEditBox:SetText(GuildControlGetRankName(1)); + GuildControlCheckboxUpdate(GuildControlGetRankFlags()); + CloseDropDownMenus(); + -- Set this to call guildroster in the next frame + --GuildRoster(); + --GuildControlPopupFrame.update = 1; +end + +function GuildControlPopupFrameRemoveRankButton_OnUpdate(self) + local numRanks = GuildControlGetNumRanks() + if ( (UIDropDownMenu_GetSelectedID(GuildControlPopupFrameDropDown) == numRanks) and (numRanks > 5) ) then + self:Show(); + if ( FriendsFrame.playersInBotRank > 0 ) then + self:Disable(); + else + self:Enable(); + end + else + self:Hide(); + end +end + +function GuildControlPopup_UpdateDepositCheckBox() + if(GuildControlTabPermissionsViewTab:GetChecked()) then + BlizzardOptionsPanel_CheckButton_Enable(GuildControlTabPermissionsDepositItems); + BlizzardOptionsPanel_CheckButton_Enable(GuildControlTabPermissionsUpdateText); + else + BlizzardOptionsPanel_CheckButton_Disable(GuildControlTabPermissionsDepositItems); + BlizzardOptionsPanel_CheckButton_Disable(GuildControlTabPermissionsUpdateText); + end +end + +function InGuildCheck() + if ( not IsInGuild() ) then + PanelTemplates_DisableTab( FriendsFrame, 3 ); + if ( FriendsFrame.selectedTab == 3 ) then + FriendsFrame.selectedTab = 1; + FriendsFrame_Update(); + end + else + PanelTemplates_EnableTab( FriendsFrame, 3 ); + FriendsFrame_Update(); + end +end + +function GuildFrameGuildListToggleButton_OnClick() + if ( FriendsFrame.playerStatusFrame ) then + FriendsFrame.playerStatusFrame = nil; + else + FriendsFrame.playerStatusFrame = 1; + end + GuildStatus_Update(); +end + +function GuildFrameControlButton_OnUpdate() + if ( FriendsFrame.guildControlShow == 1 ) then + GuildFrameControlButton:LockHighlight(); + else + GuildFrameControlButton:UnlockHighlight(); + end + -- Janky way to make sure a change made to the guildroster will reflect in the guildroster call + if ( GuildControlPopupFrame.update == 1 ) then + GuildControlPopupFrame.update = 2; + elseif ( GuildControlPopupFrame.update == 2 ) then + GuildRoster(); + GuildControlPopupFrame.update = nil; + end +end + +function GuildFrame_GetLastOnline(guildIndex) + return RecentTimeDate( GetGuildRosterLastOnline(guildIndex) ); +end + +function FriendsFrame_GetLastOnline(lastOnline) + local year, month, day, hour, minute; + local timeDifference = time() - lastOnline; + local ONE_MINUTE = 60; + local ONE_HOUR = 60 * ONE_MINUTE; + local ONE_DAY = 24 * ONE_HOUR; + local ONE_MONTH = 30 * ONE_DAY; + local ONE_YEAR = 12 * ONE_MONTH; + -- local ONE_MILLENIUM = 1000 * ONE_YEAR; for the future + + if ( timeDifference < ONE_MINUTE ) then + return LASTONLINE_SECS; + elseif ( timeDifference >= ONE_MINUTE and timeDifference < ONE_HOUR ) then + return format(LASTONLINE_MINUTES, floor(timeDifference / ONE_MINUTE)); + elseif ( timeDifference >= ONE_HOUR and timeDifference < ONE_DAY ) then + return format(LASTONLINE_HOURS, floor(timeDifference / ONE_HOUR)); + elseif ( timeDifference >= ONE_DAY and timeDifference < ONE_MONTH ) then + return format(LASTONLINE_DAYS, floor(timeDifference / ONE_DAY)); + elseif ( timeDifference >= ONE_MONTH and timeDifference < ONE_YEAR ) then + return format(LASTONLINE_MONTHS, floor(timeDifference / ONE_MONTH)); + else + return format(LASTONLINE_YEARS, floor(timeDifference / ONE_YEAR)); + end +end + +function ToggleGuildInfoFrame() + if ( GuildInfoFrame:IsShown() ) then + GuildInfoFrame:Hide(); + else + GuildFramePopup_Show(GuildInfoFrame); + end +end + +function GuildBankTabPermissionsTab_OnClick(tab) + GuildControlPopupFrameTabPermissions.selectedTab = tab; + GuildControlPopupframe_Update(true, true); +end + +-- Functions to allow canceling +function ClearPendingGuildBankPermissions() + for i=1, MAX_GUILDBANK_TABS do + PENDING_GUILDBANK_PERMISSIONS[i] = {}; + end +end + +function SetPendingGuildBankTabPermissions(tab, id, checked) + if ( not checked ) then + checked = 0; + end + PENDING_GUILDBANK_PERMISSIONS[tab][id] = checked; +end + +function SetPendingGuildBankTabWithdraw(tab, amount) + PENDING_GUILDBANK_PERMISSIONS[tab]["withdraw"] = amount; +end + +function SavePendingGuildBankTabPermissions() + for index, value in pairs(PENDING_GUILDBANK_PERMISSIONS) do + for i=1, 3 do + if ( value[i] ) then + SetGuildBankTabPermissions(index, i, value[i]); + end + end + if ( value["withdraw"] ) then + SetGuildBankTabWithdraw(index, value["withdraw"]); + end + end +end + +-- Guild event log functions +function ToggleGuildEventLog() + if ( GuildEventLogFrame:IsShown() ) then + GuildEventLogFrame:Hide(); + else + GuildFramePopup_Show(GuildEventLogFrame); +-- QueryGuildEventLog(); + end +end + +function GuildEventLog_Update() + local numEvents = GetNumGuildEvents(); + local type, player1, player2, rank, year, month, day, hour; + local msg; + local buffer = ""; + local max = GuildEventMessage:GetFieldSize() + local length = 0; + for i=numEvents, 1, -1 do + type, player1, player2, rank, year, month, day, hour = GetGuildEventInfo(i); + if ( not player1 ) then + player1 = UNKNOWN; + end + if ( not player2 ) then + player2 = UNKNOWN; + end + if ( type == "invite" ) then + msg = format(GUILDEVENT_TYPE_INVITE, player1, player2); + elseif ( type == "join" ) then + msg = format(GUILDEVENT_TYPE_JOIN, player1); + elseif ( type == "promote" ) then + msg = format(GUILDEVENT_TYPE_PROMOTE, player1, player2, rank); + elseif ( type == "demote" ) then + msg = format(GUILDEVENT_TYPE_DEMOTE, player1, player2, rank); + elseif ( type == "remove" ) then + msg = format(GUILDEVENT_TYPE_REMOVE, player1, player2); + elseif ( type == "quit" ) then + msg = format(GUILDEVENT_TYPE_QUIT, player1); + end + if ( msg ) then + msg = msg.."|cff009999 "..format(GUILD_BANK_LOG_TIME, RecentTimeDate(year, month, day, hour)).."|r|n"; + length = length + msg:len(); + if(length>max) then + i=0 + else + buffer = buffer..msg + end + end + end + GuildEventMessage:SetText(buffer); +end + +GUILDFRAME_POPUPS = { + "GuildEventLogFrame", + "GuildInfoFrame", + "GuildMemberDetailFrame", + "GuildControlPopupFrame", +}; + +function GuildFramePopup_Show(frame) + local name = frame:GetName(); + for index, value in ipairs(GUILDFRAME_POPUPS) do + if ( name ~= value ) then + _G[value]:Hide(); + end + end + frame:Show(); +end + +function GuildFramePopup_HideAll() + for index, value in ipairs(GUILDFRAME_POPUPS) do + _G[value]:Hide(); + end +end + +-- Battle.net stuff starts here + +function FriendsFrame_CheckBattlenetStatus() + if ( BNFeaturesEnabled() ) then + if ( BNConnected() ) then + BNetBroadcasts, numOnlineBroadcasts, numOfflineBroadcasts = BNGetCustomMessageTable(BNetBroadcasts); + if(not BNetBroadcasts) then + BNetBroadcasts = { }; + end + playerRealmName = GetRealmName(); + playerFactionGroup = UnitFactionGroup("player"); + FriendsFrameBattlenetStatus:Hide(); + FriendsFrameStatusDropDown:Show(); + FriendsFrameBroadcastInput:Show(); + FriendsFrameBroadcastInput_UpdateDisplay(); + else + numOnlineBroadcasts = 0; + numOfflineBroadcasts = 0; + FriendsFrameBattlenetStatus:Show(); + FriendsFrameStatusDropDown:Hide(); + FriendsFrameBroadcastInput:Hide(); + FriendsFrameOfflineHeader:Hide(); + end + if ( FriendsFrame:IsShown() ) then + IgnoreList_Update(); + PendingList_Update(); + end + -- has its own check if it is being shown, after it updates the count on the FriendsMicroButton + FriendsList_Update(); + end +end + +function FriendsFrame_GetTopButton(offset) + local heightLeft = offset; + local priorHeight = 0; + local buttonHeight; + local numBNetTotal, numBNetOnline = BNGetNumFriends(); + local numBNetOffline = numBNetTotal - numBNetOnline; + local numWoWTotal, numWoWOnline = GetNumFriends(); + local numWoWOffline = numWoWTotal - numWoWOnline; + local buttonIndex = 0; + + -- online + if ( numBNetOnline + numWoWOnline > 0 ) then + local totalBNOnlineHeight = numBNetOnline * FRIENDS_BUTTON_NORMAL_HEIGHT + numOnlineBroadcasts * (FRIENDS_BUTTON_LARGE_HEIGHT - FRIENDS_BUTTON_NORMAL_HEIGHT); + if ( heightLeft < totalBNOnlineHeight ) then + for i = 1, numBNetOnline do + if ( BNetBroadcasts[i] ) then + buttonHeight = FRIENDS_BUTTON_LARGE_HEIGHT; + else + buttonHeight = FRIENDS_BUTTON_NORMAL_HEIGHT; + end + if ( (heightLeft - buttonHeight) < 1 ) then + return i + buttonIndex, offset - heightLeft, totalScrollHeight; + else + heightLeft = heightLeft - buttonHeight; + end + end + end + heightLeft = heightLeft - totalBNOnlineHeight; + buttonIndex = buttonIndex + numBNetOnline; + if ( heightLeft < numWoWOnline * FRIENDS_BUTTON_NORMAL_HEIGHT ) then + local index = math.floor(heightLeft / FRIENDS_BUTTON_NORMAL_HEIGHT) + 1; + return buttonIndex + index, offset - heightLeft + (index - 1) * FRIENDS_BUTTON_NORMAL_HEIGHT, totalScrollHeight; + end + heightLeft = heightLeft - numWoWOnline * FRIENDS_BUTTON_NORMAL_HEIGHT; + buttonIndex = buttonIndex + numWoWOnline; + end + -- offline + if ( numBNetOffline + numWoWOffline > 0 ) then + -- check header first + if ( numBNetOnline + numWoWOnline > 0 ) then + buttonIndex = buttonIndex + 1; + if ( heightLeft < FRIENDS_BUTTON_HEADER_HEIGHT ) then + return buttonIndex, offset - heightLeft, totalScrollHeight; + else + heightLeft = heightLeft - FRIENDS_BUTTON_HEADER_HEIGHT; + end + end + local totalBNOfflineHeight = numBNetOffline * FRIENDS_BUTTON_NORMAL_HEIGHT + numOfflineBroadcasts * (FRIENDS_BUTTON_LARGE_HEIGHT - FRIENDS_BUTTON_NORMAL_HEIGHT); + if ( heightLeft < totalBNOfflineHeight ) then + for i = 1, numBNetOffline do + if ( BNetBroadcasts[numBNetOnline + i] ) then + buttonHeight = FRIENDS_BUTTON_LARGE_HEIGHT; + else + buttonHeight = FRIENDS_BUTTON_NORMAL_HEIGHT; + end + if ( (heightLeft - buttonHeight) < 1 ) then + return i + buttonIndex, offset - heightLeft, totalScrollHeight; + else + heightLeft = heightLeft - buttonHeight; + end + end + end + heightLeft = heightLeft - totalBNOfflineHeight; + buttonIndex = buttonIndex + numBNetOffline; + if ( heightLeft < numWoWOffline * FRIENDS_BUTTON_NORMAL_HEIGHT ) then + local index = math.floor(heightLeft / FRIENDS_BUTTON_NORMAL_HEIGHT) + 1; + return buttonIndex + index, offset - heightLeft + (index - 1) * FRIENDS_BUTTON_NORMAL_HEIGHT, totalScrollHeight; + end + end +end + +function FriendsFrame_SetButton(button, index, firstButton) + local height; + local nameText, nameColor, infoText, broadcastText; + + if ( firstButton ) then + FriendsFrameOfflineHeader:Hide(); + DynamicScrollFrame_UnlockAllHighlights(FriendsFrameFriendsScrollFrame); + end + button.buttonType = FriendButtons[index].buttonType; + button.id = FriendButtons[index].id; + if ( FriendButtons[index].buttonType == FRIENDS_BUTTON_TYPE_WOW ) then + local name, level, class, area, connected, status, note = GetFriendInfo(FriendButtons[index].id); + if ( connected ) then + button.background:SetTexture(FRIENDS_WOW_BACKGROUND_COLOR.r, FRIENDS_WOW_BACKGROUND_COLOR.g, FRIENDS_WOW_BACKGROUND_COLOR.b, FRIENDS_WOW_BACKGROUND_COLOR.a); + if ( status == "" ) then + button.status:SetTexture(FRIENDS_TEXTURE_ONLINE); + elseif ( status == CHAT_FLAG_AFK ) then + button.status:SetTexture(FRIENDS_TEXTURE_AFK); + elseif ( status == CHAT_FLAG_DND ) then + button.status:SetTexture(FRIENDS_TEXTURE_DND); + end + nameText = name..", "..format(FRIENDS_LEVEL_TEMPLATE, level, class); + nameColor = FRIENDS_WOW_NAME_COLOR; + else + button.background:SetTexture(FRIENDS_OFFLINE_BACKGROUND_COLOR.r, FRIENDS_OFFLINE_BACKGROUND_COLOR.g, FRIENDS_OFFLINE_BACKGROUND_COLOR.b, FRIENDS_OFFLINE_BACKGROUND_COLOR.a); + button.status:SetTexture(FRIENDS_TEXTURE_OFFLINE); + nameText = name; + nameColor = FRIENDS_GRAY_COLOR; + end + infoText = area; + button.gameIcon:Hide(); + FriendsFrame_SummonButton_Update(button.summonButton); + elseif ( FriendButtons[index].buttonType == FRIENDS_BUTTON_TYPE_BNET ) then + local presenceID, givenName, surname, toonName, toonID, client, isOnline, lastOnline, isAFK, isDND, messageText, noteText = BNGetFriendInfo(FriendButtons[index].id); + broadcastText = messageText; + if ( isOnline ) then + local _, _, _, _, _, _, _, _, zoneName, _, gameText = BNGetToonInfo(toonID); + button.background:SetTexture(FRIENDS_BNET_BACKGROUND_COLOR.r, FRIENDS_BNET_BACKGROUND_COLOR.g, FRIENDS_BNET_BACKGROUND_COLOR.b, FRIENDS_BNET_BACKGROUND_COLOR.a); + if ( isAFK ) then + button.status:SetTexture(FRIENDS_TEXTURE_AFK); + elseif ( isDND ) then + button.status:SetTexture(FRIENDS_TEXTURE_DND); + else + button.status:SetTexture(FRIENDS_TEXTURE_ONLINE); + end + if ( client == BNET_CLIENT_WOW ) then + if ( not zoneName or zoneName == "" ) then + infoText = UNKNOWN; + else + infoText = zoneName; + end + button.gameIcon:SetTexture("Interface\\FriendsFrame\\Battlenet-WoWicon"); + elseif ( client == BNET_CLIENT_SC2 ) then + button.gameIcon:SetTexture("Interface\\FriendsFrame\\Battlenet-Sc2icon"); + infoText = gameText; + end + nameColor = FRIENDS_BNET_NAME_COLOR; + button.gameIcon:Show(); + else + button.background:SetTexture(FRIENDS_OFFLINE_BACKGROUND_COLOR.r, FRIENDS_OFFLINE_BACKGROUND_COLOR.g, FRIENDS_OFFLINE_BACKGROUND_COLOR.b, FRIENDS_OFFLINE_BACKGROUND_COLOR.a); + button.status:SetTexture(FRIENDS_TEXTURE_OFFLINE); + nameColor = FRIENDS_GRAY_COLOR; + button.gameIcon:Hide(); + if ( lastOnline == 0 ) then + infoText = FRIENDS_LIST_OFFLINE; + else + infoText = string.format(BNET_LAST_ONLINE_TIME, FriendsFrame_GetLastOnline(lastOnline)); + end + end + if ( givenName and surname ) then + if ( toonName ) then + if ( client == BNET_CLIENT_WOW and CanCooperateWithToon(toonID) ) then + nameText = string.format(BATTLENET_NAME_FORMAT, givenName, surname).." "..FRIENDS_WOW_NAME_COLOR_CODE.."("..toonName..")"; + else + if ( ENABLE_COLORBLIND_MODE == "1" ) then + toonName = toonName..CANNOT_COOPERATE_LABEL; + end + nameText = string.format(BATTLENET_NAME_FORMAT, givenName, surname).." "..FRIENDS_OTHER_NAME_COLOR_CODE.."("..toonName..")"; + end + else + nameText = string.format(BATTLENET_NAME_FORMAT, givenName, surname); + end + else + nameText = UNKNOWN; + end + FriendsFrame_SummonButton_Update(button.summonButton); + else -- header + button:Hide(); + FriendsFrameOfflineHeader:Show(); + FriendsFrameOfflineHeader:SetAllPoints(button); + return FRIENDS_BUTTON_HEADER_HEIGHT; + end + + if ( FriendsFrame.selectedFriendType == FriendButtons[index].buttonType and FriendsFrame.selectedFriend == FriendButtons[index].id ) then + button:LockHighlight(); + end + + button.name:SetText(nameText); + button.name:SetTextColor(nameColor.r, nameColor.g, nameColor.b); + button.info:SetText(infoText); + -- don't display a broadcast if the BNetBroadcasts data is out of sync + if ( broadcastText and broadcastText ~= "" and BNetBroadcasts[FriendButtons[index].id] ) then + height = FRIENDS_BUTTON_LARGE_HEIGHT; + button.broadcastMessage:SetText(broadcastText); + button.broadcastMessage:Show(); + button.broadcastIcon:Show(); + else + height = FRIENDS_BUTTON_NORMAL_HEIGHT; + button.broadcastMessage:Hide(); + button.broadcastIcon:Hide(); + end + -- update the tooltip if hovering over a button + if ( FriendsTooltip.button == button ) then + FriendsFrameTooltip_Show(button); + end + button:Show(); + return height; +end + +function FriendsFrameStatusDropDown_OnLoad(self) + UIDropDownMenu_Initialize(self, FriendsFrameStatusDropDown_Initialize); + UIDropDownMenu_SetWidth(FriendsFrameStatusDropDown, 28); + FriendsFrameStatusDropDownText:Hide(); + FriendsFrameStatusDropDownButton:SetScript("OnEnter", FriendsFrameStatusDropDown_ShowTooltip); + FriendsFrameStatusDropDownButton:SetScript("OnLeave", function() GameTooltip:Hide(); end); +end + +function FriendsFrameStatusDropDown_ShowTooltip() + local statusText; + local status = FriendsFrameStatusDropDown.status; + if ( status == 2 ) then + statusText = FRIENDS_LIST_AWAY; + elseif ( status == 3 ) then + statusText = FRIENDS_LIST_BUSY; + else + statusText = FRIENDS_LIST_AVAILABLE; + end + GameTooltip:SetOwner(FriendsFrameStatusDropDown, "ANCHOR_RIGHT", -18, 0); + GameTooltip:SetText(format(FRIENDS_LIST_STATUS_TOOLTIP, statusText)); + GameTooltip:Show(); +end + +function FriendsFrameStatusDropDown_OnShow(self) + UIDropDownMenu_Initialize(self, FriendsFrameStatusDropDown_Initialize); + FriendsFrameStatusDropDown_Update(self); +end + +function FriendsFrameStatusDropDown_Initialize() + local info = UIDropDownMenu_CreateInfo(); + local optionText = "\124T%s.tga:16:16:0:0\124t %s"; + info.padding = 8; + info.checked = nil; + info.notCheckable = 1; + info.func = FriendsFrame_SetOnlineStatus; + + info.text = string.format(optionText, FRIENDS_TEXTURE_ONLINE, FRIENDS_LIST_AVAILABLE); + UIDropDownMenu_AddButton(info); + + info.text = string.format(optionText, FRIENDS_TEXTURE_AFK, FRIENDS_LIST_AWAY); + UIDropDownMenu_AddButton(info); + + info.text = string.format(optionText, FRIENDS_TEXTURE_DND, FRIENDS_LIST_BUSY); + UIDropDownMenu_AddButton(info); +end + +function FriendsFrameStatusDropDown_Update(self) + local status; + self = self or FriendsFrameStatusDropDown; + if ( UnitIsAFK("player") ) then + FriendsFrameStatusDropDownStatus:SetTexture(FRIENDS_TEXTURE_AFK); + status = 2; + elseif ( UnitIsDND("player") ) then + FriendsFrameStatusDropDownStatus:SetTexture(FRIENDS_TEXTURE_DND); + status = 3; + else + FriendsFrameStatusDropDownStatus:SetTexture(FRIENDS_TEXTURE_ONLINE); + status = 1; + end + FriendsFrameStatusDropDown.status = status; +end + +function FriendsFrame_SetOnlineStatus(button, status) + status = status or button:GetID(); + if ( status == FriendsFrameStatusDropDown.status ) then + return; + end + if ( status == 1 ) then + if ( UnitIsAFK("player") ) then + SendChatMessage("", "AFK"); + elseif ( UnitIsDND("player") ) then + SendChatMessage("", "DND"); + end + elseif ( status == 2 ) then + SendChatMessage("", "AFK"); + else + SendChatMessage("", "DND"); + end +end + +function FriendsFrameBroadcastInput_OnEnterPressed(self) + local broadcastText = self:GetText() + BNSetCustomMessage(broadcastText); + FriendsFrameBroadcastInput_UpdateDisplay(self, broadcastText); +end + +function FriendsFrameBroadcastInput_OnEscapePressed(self) + FriendsFrameBroadcastInput_UpdateDisplay(self); +end + +function FriendsFrameBroadcastInput_OnClearPressed(self) + BNSetCustomMessage(""); + FriendsFrameBroadcastInput_UpdateDisplay(nil, ""); +end + +function FriendsFrameBroadcastInput_UpdateDisplay(self, broadcastText) + local _; + self = self or FriendsFrameBroadcastInput; + if ( not broadcastText ) then + _, _, broadcastText = BNGetInfo(); + broadcastText = broadcastText or ""; + end + self:ClearFocus(); + self:SetText(broadcastText); + if ( broadcastText ~= "" ) then + self.icon:SetAlpha(1); + self:SetCursorPosition(0); + self.clear:Show(); + self:SetTextInsets(0, 18, 0, 0); + else + self.icon:SetAlpha(0.35); + self.clear:Hide(); + self:SetTextInsets(0, 10, 0, 0); + end +end + +function FriendsFrameTooltip_Show(self) + if ( self.buttonType == FRIENDS_BUTTON_TYPE_HEADER ) then + return; + end + local anchor, text; + local FRIENDS_TOOLTIP_WOW_INFO_TEMPLATE = NORMAL_FONT_COLOR_CODE..FRIENDS_LIST_ZONE.."|r%1$s|n"..NORMAL_FONT_COLOR_CODE..FRIENDS_LIST_REALM.."|r%2$s"; + local numToons = 0; + local tooltip = FriendsTooltip; + tooltip.height = 0; + tooltip.maxWidth = 0; + + if ( self.buttonType == FRIENDS_BUTTON_TYPE_BNET ) then + local nameText; + local presenceID, givenName, surname, toonName, toonID, client, isOnline, lastOnline, isAFK, isDND, broadcastText, noteText, isFriend, broadcastTime = BNGetFriendInfo(self.id); + -- account name + if ( givenName and surname ) then + nameText = format(BATTLENET_NAME_FORMAT, givenName, surname); + else + nameText = UNKNOWN; + end + anchor = FriendsFrameTooltip_SetLine(FriendsTooltipHeader, nil, nameText); + -- toon 1 + if ( toonID ) then + local hasFocus, toonName, client, realmName, faction, race, class, guild, zoneName, level, gameText = BNGetToonInfo(toonID); + level = level or ""; + race = race or ""; + class = class or ""; + if ( client == BNET_CLIENT_WOW ) then + if ( CanCooperateWithToon(toonID) ) then + text = string.format(FRIENDS_TOOLTIP_WOW_TOON_TEMPLATE, toonName, level, race, class); + else + text = string.format(FRIENDS_TOOLTIP_WOW_TOON_TEMPLATE, toonName..CANNOT_COOPERATE_LABEL, level, race, class); + end + FriendsFrameTooltip_SetLine(FriendsTooltipToon1Name, nil, text); + anchor = FriendsFrameTooltip_SetLine(FriendsTooltipToon1Info, nil, string.format(FRIENDS_TOOLTIP_WOW_INFO_TEMPLATE, zoneName, realmName), -4); + elseif ( client == BNET_CLIENT_SC2 ) then + FriendsFrameTooltip_SetLine(FriendsTooltipToon1Name, nil, toonName); + anchor = FriendsFrameTooltip_SetLine(FriendsTooltipToon1Info, nil, gameText, -4); + end + else + FriendsTooltipToon1Info:Hide(); + FriendsTooltipToon1Name:Hide(); + end + -- note + if ( noteText and noteText ~= "" ) then + FriendsTooltipNoteIcon:Show(); + anchor = FriendsFrameTooltip_SetLine(FriendsTooltipNoteText, anchor, noteText, -8); + else + FriendsTooltipNoteIcon:Hide(); + FriendsTooltipNoteText:Hide(); + end + -- broadcast + if ( broadcastText and broadcastText ~= "" ) then + FriendsTooltipBroadcastIcon:Show(); + broadcastText = broadcastText.."|n"..FRIENDS_BROADCAST_TIME_COLOR_CODE..string.format(BNET_BROADCAST_SENT_TIME, FriendsFrame_GetLastOnline(broadcastTime)); + anchor = FriendsFrameTooltip_SetLine(FriendsTooltipBroadcastText, anchor, broadcastText, -8); + else + FriendsTooltipBroadcastIcon:Hide(); + FriendsTooltipBroadcastText:Hide(); + end + if ( isOnline ) then + FriendsTooltipHeader:SetTextColor(FRIENDS_BNET_NAME_COLOR.r, FRIENDS_BNET_NAME_COLOR.g, FRIENDS_BNET_NAME_COLOR.b); + FriendsTooltipLastOnline:Hide(); + numToons = BNGetNumFriendToons(self.id); + else + FriendsTooltipHeader:SetTextColor(FRIENDS_GRAY_COLOR.r, FRIENDS_GRAY_COLOR.g, FRIENDS_GRAY_COLOR.b); + if ( lastOnline == 0 ) then + text = FRIENDS_LIST_OFFLINE; + else + text = string.format(BNET_LAST_ONLINE_TIME, FriendsFrame_GetLastOnline(lastOnline)); + end + anchor = FriendsFrameTooltip_SetLine(FriendsTooltipLastOnline, anchor, text, -4); + end + elseif ( self.buttonType == FRIENDS_BUTTON_TYPE_WOW ) then + local name, level, class, area, connected, status, noteText = GetFriendInfo(self.id); + anchor = FriendsFrameTooltip_SetLine(FriendsTooltipHeader, nil, name); + if ( connected ) then + FriendsTooltipHeader:SetTextColor(FRIENDS_WOW_NAME_COLOR.r, FRIENDS_WOW_NAME_COLOR.g, FRIENDS_WOW_NAME_COLOR.b); + FriendsFrameTooltip_SetLine(FriendsTooltipToon1Name, nil, string.format(FRIENDS_LEVEL_TEMPLATE, level, class)); + anchor = FriendsFrameTooltip_SetLine(FriendsTooltipToon1Info, nil, area); + else + FriendsTooltipHeader:SetTextColor(FRIENDS_GRAY_COLOR.r, FRIENDS_GRAY_COLOR.g, FRIENDS_GRAY_COLOR.b); + FriendsTooltipToon1Name:Hide(); + FriendsTooltipToon1Info:Hide(); + end + if ( noteText ) then + FriendsTooltipNoteIcon:Show(); + anchor = FriendsFrameTooltip_SetLine(FriendsTooltipNoteText, anchor, noteText, -8); + else + FriendsTooltipNoteIcon:Hide(); + FriendsTooltipNoteText:Hide(); + end + FriendsTooltipBroadcastIcon:Hide(); + FriendsTooltipBroadcastText:Hide(); + FriendsTooltipLastOnline:Hide(); + end + + -- other toons + local toonIndex = 1; + local toonNameString; + local toonInfoString; + if ( numToons > 1 ) then + FriendsFrameTooltip_SetLine(FriendsTooltipOtherToons, anchor, nil, -8); + for i = 1, numToons do + local hasFocus, toonName, client, realmName, faction, race, class, guild, zoneName, level, gameText = BNGetFriendToonInfo(self.id, i); + -- the focused toon is already at the top of the tooltip + if ( not hasFocus ) then + toonIndex = toonIndex + 1; + if ( toonIndex > FRIENDS_TOOLTIP_MAX_TOONS ) then + break; + end + toonNameString = _G["FriendsTooltipToon"..toonIndex.."Name"]; + toonInfoString = _G["FriendsTooltipToon"..toonIndex.."Info"]; + if ( client == BNET_CLIENT_WOW ) then + if ( realmName == playerRealmName and PLAYER_FACTION_GROUP[faction] == playerFactionGroup ) then + text = string.format(FRIENDS_TOOLTIP_WOW_TOON_TEMPLATE, toonName, level, race, class); + else + text = string.format(FRIENDS_TOOLTIP_WOW_TOON_TEMPLATE, toonName..CANNOT_COOPERATE_LABEL, level, race, class); + end + gameText = zoneName; + elseif ( client == BNET_CLIENT_SC2 ) then + text = toonName; + end + FriendsFrameTooltip_SetLine(toonNameString, nil, text); + FriendsFrameTooltip_SetLine(toonInfoString, nil, gameText); + end + end + else + FriendsTooltipOtherToons:Hide(); + end + for i = toonIndex + 1, FRIENDS_TOOLTIP_MAX_TOONS do + toonNameString = _G["FriendsTooltipToon"..i.."Name"]; + toonInfoString = _G["FriendsTooltipToon"..i.."Info"]; + toonNameString:Hide(); + toonInfoString:Hide(); + end + if ( numToons > FRIENDS_TOOLTIP_MAX_TOONS ) then + FriendsFrameTooltip_SetLine(FriendsTooltipToonMany, nil, string.format(FRIENDS_TOOLTIP_TOO_MANY_CHARACTERS, numToons - FRIENDS_TOOLTIP_MAX_TOONS), 0); + else + FriendsTooltipToonMany:Hide(); + end + + tooltip.button = self; + tooltip:SetPoint("TOPLEFT", self, "TOPRIGHT", 36, 0); + tooltip:SetHeight(tooltip.height + FRIENDS_TOOLTIP_MARGIN_WIDTH); + tooltip:SetWidth(min(FRIENDS_TOOLTIP_MAX_WIDTH, tooltip.maxWidth + FRIENDS_TOOLTIP_MARGIN_WIDTH)); + tooltip:Show(); +end + +function FriendsFrameTooltip_SetLine(line, anchor, text, yOffset) + local tooltip = FriendsTooltip; + local top = 0; + local left = FRIENDS_TOOLTIP_MAX_WIDTH - FRIENDS_TOOLTIP_MARGIN_WIDTH - line:GetWidth(); + + if ( text ) then + line:SetText(text); + end + if ( anchor ) then + top = yOffset or 0; + line:SetPoint("TOP", anchor, "BOTTOM", 0, top); + else + local point, _, _, _, y = line:GetPoint(1); + if ( point == "TOP" or point == "TOPLEFT" ) then + top = y; + end + end + line:Show(); + tooltip.height = tooltip.height + line:GetHeight() - top; + tooltip.maxWidth = max(tooltip.maxWidth, line:GetStringWidth() + left); + return line; +end + +function AddFriendFrame_OnShow() + local factionGroup = UnitFactionGroup("player"); + if ( factionGroup ) then + local textureFile = "Interface\\FriendsFrame\\PlusManz-"..factionGroup; + AddFriendInfoFrameFactionIcon:SetTexture(textureFile); + AddFriendInfoFrameFactionIcon:Show(); + AddFriendEntryFrameRightIcon:SetTexture(textureFile); + AddFriendEntryFrameRightIcon:Show(); + end +end + +function AddFriendFrame_ShowInfo() + AddFriendFrame:SetWidth(AddFriendInfoFrame:GetWidth()); + AddFriendFrame:SetHeight(AddFriendInfoFrame:GetHeight()); + AddFriendInfoFrame:Show(); + AddFriendEntryFrame:Hide(); + PlaySound("igMainMenuOpen"); +end + +function AddFriendFrame_ShowEntry() + AddFriendFrame:SetWidth(AddFriendEntryFrame:GetWidth()); + AddFriendFrame:SetHeight(AddFriendEntryFrame:GetHeight()); + AddFriendInfoFrame:Hide(); + AddFriendEntryFrame:Show(); + if ( BNFeaturesEnabledAndConnected() ) then + AddFriendFrame.BNconnected = true; + AddFriendEntryFrameLeftTitle:SetAlpha(1); + AddFriendEntryFrameLeftDescription:SetText(BATTLENET_FRIEND_LABEL); + AddFriendEntryFrameLeftDescription:SetTextColor(1, 1, 1); + AddFriendEntryFrameLeftIcon:SetVertexColor(1, 1, 1); + AddFriendEntryFrameLeftFriend:SetVertexColor(1, 1, 1); + else + AddFriendFrame.BNconnected = nil; + AddFriendEntryFrameLeftTitle:SetAlpha(0.35); + AddFriendEntryFrameLeftDescription:SetText(BATTLENET_UNAVAILABLE); + AddFriendEntryFrameLeftDescription:SetTextColor(1, 0, 0); + AddFriendEntryFrameLeftIcon:SetVertexColor(.4, .4, .4); + AddFriendEntryFrameLeftFriend:SetVertexColor(.4, .4, .4); + end + if ( AddFriendFrame.editFocus ) then + AddFriendFrame.editFocus:SetFocus(); + end + PlaySound("igMainMenuOpen"); +end + +function AddFriendNameEditBox_OnTextChanged(self, userInput) + if ( not AutoCompleteEditBox_OnTextChanged(self, userInput) ) then + local text = self:GetText(); + if ( text ~= "" ) then + AddFriendNameEditBoxFill:Hide(); + if ( AddFriendFrame.BNconnected ) then + if ( string.find(text, "@") ) then + AddFriendEntryFrame_Expand(); + else + AddFriendEntryFrame_Collapse(); + end + end + else + AddFriendEntryFrame_Collapse(); + AddFriendNameEditBoxFill:Show(); + end + end +end + +function AddFriendEntryFrame_Expand() + AddFriendEntryFrame:SetHeight(296); + AddFriendFrame:SetHeight(296); + AddFriendNoteFrame:Show(); + AddFriendEntryFrameAcceptButton:SetText(SEND_REQUEST); + AddFriendEntryFrameRightTitle:SetAlpha(0.35); + AddFriendEntryFrameRightDescription:SetAlpha(0.35); + AddFriendEntryFrameRightIcon:SetVertexColor(.4, .4, .4); + AddFriendEntryFrameRightFriend:SetVertexColor(.4, .4, .4); + AddFriendEntryFrameLeftIcon:SetAlpha(1); + AddFriendEntryFrameOrLabel:SetVertexColor(.3, .3, .3); +end + +function AddFriendEntryFrame_Collapse(clearText) + AddFriendEntryFrame:SetHeight(218); + AddFriendFrame:SetHeight(218); + AddFriendNoteFrame:Hide(); + AddFriendEntryFrameAcceptButton:SetText(ADD_FRIEND); + AddFriendEntryFrameRightTitle:SetAlpha(1); + AddFriendEntryFrameRightDescription:SetAlpha(1); + AddFriendEntryFrameRightIcon:SetVertexColor(1, 1, 1); + AddFriendEntryFrameRightFriend:SetVertexColor(1, 1, 1); + AddFriendEntryFrameLeftIcon:SetAlpha(0.5); + if ( AddFriendFrame.BNconnected ) then + AddFriendEntryFrameOrLabel:SetVertexColor(1, 1, 1); + else + AddFriendEntryFrameOrLabel:SetVertexColor(0.3, 0.3, 0.3); + end + if ( clearText ) then + AddFriendNameEditBox:SetText(""); + AddFriendNoteEditBox:SetText(""); + end +end + +function AddFriendFrame_Accept() + local name = AddFriendNameEditBox:GetText(); + if ( AddFriendFrame.BNconnected and string.find(name, "@") ) then + BNSendFriendInvite(name, AddFriendNoteEditBox:GetText()); + else + AddFriend(name); + end + StaticPopupSpecial_Hide(AddFriendFrame); +end + +function FriendsFriendsFrameDropDown_Initialize() + local info = UIDropDownMenu_CreateInfo(); + local value = FriendsFriendsFrame.view; + + info.value = FRIENDS_FRIENDS_ALL; + info.text = FRIENDS_FRIENDS_CHOICE_EVERYONE; + info.func = FriendsFriendsFrameDropDown_OnClick; + info.arg1 = FRIENDS_FRIENDS_ALL; + if ( value == info.value ) then + info.checked = 1; + UIDropDownMenu_SetText(FriendsFriendsFrameDropDown, info.text); + else + info.checked = nil; + end + UIDropDownMenu_AddButton(info); + + info.value = FRIENDS_FRIENDS_POTENTIAL; + info.text = FRIENDS_FRIENDS_CHOICE_POTENTIAL; + info.func = FriendsFriendsFrameDropDown_OnClick; + info.arg1 = FRIENDS_FRIENDS_POTENTIAL; + if ( value == info.value ) then + info.checked = 1; + UIDropDownMenu_SetText(FriendsFriendsFrameDropDown, info.text); + else + info.checked = nil; + end + UIDropDownMenu_AddButton(info); + + info.value = FRIENDS_FRIENDS_MUTUAL; + info.text = FRIENDS_FRIENDS_CHOICE_MUTUAL; + info.func = FriendsFriendsFrameDropDown_OnClick; + info.arg1 = FRIENDS_FRIENDS_MUTUAL; + if ( value == info.value ) then + info.checked = 1; + UIDropDownMenu_SetText(FriendsFriendsFrameDropDown, info.text); + else + info.checked = nil; + end + UIDropDownMenu_AddButton(info); +end + +function FriendsFriendsFrameDropDown_OnClick(self, value) + FriendsFriendsFrame.view = value; + UIDropDownMenu_SetSelectedValue(FriendsFriendsFrameDropDown, value); + FriendsFriendsScrollFrameScrollBar:SetValue(0); + FriendsFriendsList_Update(); +end + +function FriendsFriendsList_Update() + if ( FriendsFriendsWaitFrame:IsShown() ) then + return; + end + + local friendsButton, friendsIndex; + local showMutual, showPotential; + local view = FriendsFriendsFrame.view; + local selection = FriendsFriendsFrame.selection; + local requested = FriendsFriendsFrame.requested; + local presenceID = FriendsFriendsFrame.presenceID; + local numFriendsFriends = 0; + local numMutual, numPotential = BNGetNumFOF(presenceID); + local offset = FauxScrollFrame_GetOffset(FriendsFriendsScrollFrame); + local haveSelection; + if ( view == FRIENDS_FRIENDS_POTENTIAL or view == FRIENDS_FRIENDS_ALL ) then + showPotential = true; + numFriendsFriends = numFriendsFriends + numPotential; + end + if ( view == FRIENDS_FRIENDS_MUTUAL or view == FRIENDS_FRIENDS_ALL ) then + showMutual = true; + numFriendsFriends = numFriendsFriends + numMutual; + end + for i = 1, FRIENDS_FRIENDS_TO_DISPLAY, 1 do + friendsIndex = i + offset; + friendsButton = _G["FriendsFriendsButton"..i]; + if ( friendsIndex > numFriendsFriends ) then + friendsButton:Hide(); + else + local friendID, givenName, surname, isMutual = BNGetFOFInfo(presenceID, showMutual, showPotential, friendsIndex); + local name = string.format(BATTLENET_NAME_FORMAT, givenName, surname); + if ( isMutual ) then + friendsButton:Disable(); + if ( view ~= FRIENDS_FRIENDS_MUTUAL ) then + friendsButton.name:SetText(name.." "..HIGHLIGHT_FONT_COLOR_CODE..FRIENDS_FRIENDS_MUTUAL_TEXT); + else + friendsButton.name:SetText(name); + end + friendsButton.name:SetTextColor(GRAY_FONT_COLOR .r, GRAY_FONT_COLOR .g, GRAY_FONT_COLOR .b); + elseif ( requested[friendID] ) then + friendsButton.name:SetText(name.." "..HIGHLIGHT_FONT_COLOR_CODE..FRIENDS_FRIENDS_REQUESTED_TEXT); + friendsButton:Disable(); + friendsButton.name:SetTextColor(GRAY_FONT_COLOR .r, GRAY_FONT_COLOR .g, GRAY_FONT_COLOR .b); + else + friendsButton.name:SetText(name); + friendsButton:Enable(); + friendsButton.name:SetTextColor(NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b); + if ( selection == friendID ) then + haveSelection = true; + friendsButton:LockHighlight(); + else + friendsButton:UnlockHighlight(); + end + end + friendsButton.friendID = friendID; + friendsButton:Show(); + end + end + if ( haveSelection ) then + FriendsFriendsSendRequestButton:Enable(); + else + FriendsFriendsSendRequestButton:Disable(); + end + FauxScrollFrame_Update(FriendsFriendsScrollFrame, numFriendsFriends, FRIENDS_FRIENDS_TO_DISPLAY, FRIENDS_FRAME_FRIENDS_FRIENDS_HEIGHT); +end + +function FriendsFriendsButton_OnClick(self) + PlaySound("igMainMenuOptionCheckBoxOn"); + FriendsFriendsFrame.selection = self.friendID; + FriendsFriendsList_Update(); +end + +function FriendsFrameIgnoreButton_OnClick(self) + FriendsFrame_SelectSquelched(self.type, self.index); + IgnoreList_Update(); +end + +function FriendsFriendsFrame_SendRequest() + PlaySound("igCharacterInfoTab"); + FriendsFriendsFrame.requested[FriendsFriendsFrame.selection] = true; + BNSendFriendInviteByID(FriendsFriendsFrame.selection, FriendsFriendsNoteEditBox:GetText()); + FriendsFriendsFrame_Reset(); + FriendsFriendsList_Update(); +end + +function FriendsFriendsFrame_Close() + StaticPopupSpecial_Hide(FriendsFriendsFrame); +end + +function FriendsFriendsFrame_OnEvent(self, event) + if ( event == "BN_REQUEST_FOF_SUCCEEDED" ) then + if ( self:IsShown() ) then + FriendsFriendsFrame.view = FRIENDS_FRIENDS_ALL; + UIDropDownMenu_EnableDropDown(FriendsFriendsFrameDropDown); + UIDropDownMenu_Initialize(FriendsFriendsFrameDropDown, FriendsFriendsFrameDropDown_Initialize); + UIDropDownMenu_SetSelectedValue(FriendsFriendsFrameDropDown, FRIENDS_FRIENDS_ALL); + local waitFrame = FriendsFriendsWaitFrame; + -- need to stop the flashing because it's flashing with showWhenDone set to true + if ( UIFrameIsFlashing(waitFrame) ) then + UIFrameFlashStop(waitFrame); + end + waitFrame:Hide(); + FriendsFriendsList_Update(); + end + elseif ( event == "BN_REQUEST_FOF_FAILED" ) then + -- FIX ME - need an error here + elseif ( event == "BN_DISCONNECTED" ) then + FriendsFriendsFrame_Close(); + end +end + +function FriendsFriendsFrame_Reset() + FriendsFriendsSendRequestButton:Disable(); + FriendsFriendsNoteEditBox:SetText(""); + FriendsFriendsNoteEditBox:ClearFocus(); + FriendsFriendsFrame.selection = nil; +end + +function FriendsFriendsFrame_Show(presenceID) + local presenceID, givenName, surname = BNGetFriendInfoByID(presenceID); + FriendsFriendsFrameTitle:SetFormattedText(FRIENDS_FRIENDS_HEADER, FRIENDS_BNET_NAME_COLOR_CODE..string.format(BATTLENET_NAME_FORMAT, givenName, surname)); + FriendsFriendsFrame.presenceID = presenceID; + UIDropDownMenu_DisableDropDown(FriendsFriendsFrameDropDown); + FriendsFriendsFrame_Reset(); + FriendsFriendsWaitFrame:Show(); + for i = 1, FRIENDS_FRIENDS_TO_DISPLAY, 1 do + _G["FriendsFriendsButton"..i]:Hide(); + end + FauxScrollFrame_Update(FriendsFriendsScrollFrame, 0, FRIENDS_FRIENDS_TO_DISPLAY, FRIENDS_FRAME_FRIENDS_FRIENDS_HEIGHT); + StaticPopupSpecial_Show(FriendsFriendsFrame); + BNRequestFOFInfo(presenceID); +end + +function CanCooperateWithToon(toonID) + local hasFocus, toonName, client, realmName, faction = BNGetToonInfo(toonID); + if ( realmName == playerRealmName and PLAYER_FACTION_GROUP[faction] == playerFactionGroup ) then + return true; + else + return false; + end +end \ No newline at end of file diff --git a/reference/FrameXML/FriendsFrame.xml b/reference/FrameXML/FriendsFrame.xml new file mode 100644 index 0000000..1b566b9 --- /dev/null +++ b/reference/FrameXML/FriendsFrame.xml @@ -0,0 +1,5954 @@ + + + diff --git a/reference/FrameXML/LocalizationPost.lua b/reference/FrameXML/LocalizationPost.lua new file mode 100644 index 0000000..5625162 --- /dev/null +++ b/reference/FrameXML/LocalizationPost.lua @@ -0,0 +1,6 @@ + + + +function LocalizePost() + -- Put all locale specific string adjustments here +end diff --git a/reference/FrameXML/LocalizationPost.xml b/reference/FrameXML/LocalizationPost.xml new file mode 100644 index 0000000..a8dea10 --- /dev/null +++ b/reference/FrameXML/LocalizationPost.xml @@ -0,0 +1,8 @@ + + + \ No newline at end of file diff --git a/reference/FrameXML/LootFrame.lua b/reference/FrameXML/LootFrame.lua new file mode 100644 index 0000000..28fe1b4 --- /dev/null +++ b/reference/FrameXML/LootFrame.lua @@ -0,0 +1,412 @@ +LOOTFRAME_NUMBUTTONS = 4; +NUM_GROUP_LOOT_FRAMES = 4; +MASTER_LOOT_THREHOLD = 4; + +function LootFrame_OnLoad(self) + self:RegisterEvent("LOOT_OPENED"); + self:RegisterEvent("LOOT_SLOT_CLEARED"); + self:RegisterEvent("LOOT_SLOT_CHANGED"); + self:RegisterEvent("LOOT_CLOSED"); + self:RegisterEvent("OPEN_MASTER_LOOT_LIST"); + self:RegisterEvent("UPDATE_MASTER_LOOT_LIST"); +end + +function LootFrame_OnEvent(self, event, ...) + if ( event == "LOOT_OPENED" ) then + local autoLoot = ...; + + self.page = 1; + LootFrame_Show(self); + if ( not self:IsShown()) then + CloseLoot(autoLoot == 0); -- The parameter tells code that we were unable to open the UI + end + elseif ( event == "LOOT_SLOT_CLEARED" ) then + local arg1 = ...; + + if ( not self:IsShown() ) then + return; + end + + local numLootToShow = LOOTFRAME_NUMBUTTONS; + if ( self.numLootItems > LOOTFRAME_NUMBUTTONS ) then + numLootToShow = numLootToShow - 1; + end + local slot = arg1 - ((self.page - 1) * numLootToShow); + if ( (slot > 0) and (slot < (numLootToShow + 1)) ) then + local button = _G["LootButton"..slot]; + if ( button ) then + button:Hide(); + end + end + -- try to move second page of loot items to the first page + local button; + local allButtonsHidden = 1; + + for index = 1, LOOTFRAME_NUMBUTTONS do + button = _G["LootButton"..index]; + if ( button:IsShown() ) then + allButtonsHidden = nil; + end + end + if ( allButtonsHidden and LootFrameDownButton:IsShown() ) then + LootFrame_PageDown(); + end + return; + elseif ( event == "LOOT_SLOT_CHANGED" ) then + local arg1 = ...; + + if ( not self:IsShown() ) then + return; + end + + local numLootToShow = LOOTFRAME_NUMBUTTONS; + if ( self.numLootItems > LOOTFRAME_NUMBUTTONS ) then + numLootToShow = numLootToShow - 1; + end + local slot = arg1 - ((self.page - 1) * numLootToShow); + if ( (slot > 0) and (slot < (numLootToShow + 1)) ) then + local button = _G["LootButton"..slot]; + if ( button ) then + LootFrame_UpdateButton(slot); + end + end + elseif ( event == "LOOT_CLOSED" ) then + StaticPopup_Hide("LOOT_BIND"); + HideUIPanel(self); + return; + elseif ( event == "OPEN_MASTER_LOOT_LIST" ) then + ToggleDropDownMenu(1, nil, GroupLootDropDown, LootFrame.selectedLootButton, 0, 0); + return; + elseif ( event == "UPDATE_MASTER_LOOT_LIST" ) then + UIDropDownMenu_Refresh(GroupLootDropDown); + end +end + +function LootFrame_UpdateButton(index) + local numLootItems = LootFrame.numLootItems; + --Logic to determine how many items to show per page + local numLootToShow = LOOTFRAME_NUMBUTTONS; + if ( numLootItems > LOOTFRAME_NUMBUTTONS ) then + numLootToShow = numLootToShow - 1; + end + + local button = _G["LootButton"..index]; + local slot = (numLootToShow * (LootFrame.page - 1)) + index; + if ( slot <= numLootItems ) then + if ( (LootSlotIsItem(slot) or LootSlotIsCoin(slot)) and index <= numLootToShow ) then + local texture, item, quantity, quality, locked = GetLootSlotInfo(slot); + local color = ITEM_QUALITY_COLORS[quality]; + _G["LootButton"..index.."IconTexture"]:SetTexture(texture); + local text = _G["LootButton"..index.."Text"]; + text:SetText(item); + if( locked ) then + SetItemButtonNameFrameVertexColor(button, 1.0, 0, 0); + SetItemButtonTextureVertexColor(button, 0.9, 0, 0); + SetItemButtonNormalTextureVertexColor(button, 0.9, 0, 0); + else + SetItemButtonNameFrameVertexColor(button, 0.5, 0.5, 0.5); + SetItemButtonTextureVertexColor(button, 1.0, 1.0, 1.0); + SetItemButtonNormalTextureVertexColor(button, 1.0, 1.0, 1.0); + end + text:SetVertexColor(color.r, color.g, color.b); + local countString = _G["LootButton"..index.."Count"]; + if ( quantity > 1 ) then + countString:SetText(quantity); + countString:Show(); + else + countString:Hide(); + end + button.slot = slot; + button.quality = quality; + button:Show(); + else + button:Hide(); + end + else + button:Hide(); + end +end + +function LootFrame_Update() + for index = 1, LOOTFRAME_NUMBUTTONS do + LootFrame_UpdateButton(index); + end + if ( LootFrame.page == 1 ) then + LootFrameUpButton:Hide(); + LootFramePrev:Hide(); + else + LootFrameUpButton:Show(); + LootFramePrev:Show(); + end + local numItemsPerPage = LOOTFRAME_NUMBUTTONS; + if ( LootFrame.numLootItems > LOOTFRAME_NUMBUTTONS ) then + numItemsPerPage = numItemsPerPage - 1; + end + if ( LootFrame.page == ceil(LootFrame.numLootItems / numItemsPerPage) or LootFrame.numLootItems == 0 ) then + LootFrameDownButton:Hide(); + LootFrameNext:Hide(); + else + LootFrameDownButton:Show(); + LootFrameNext:Show(); + end +end + +function LootFrame_PageDown() + LootFrame.page = LootFrame.page + 1; + LootFrame_Update(); +end + +function LootFrame_PageUp() + LootFrame.page = LootFrame.page - 1; + LootFrame_Update(); +end + +function LootFrame_Show(self) + ShowUIPanel(self); + self.numLootItems = GetNumLootItems(); + + if ( GetCVar("lootUnderMouse") == "1" ) then + -- position loot window under mouse cursor + local x, y = GetCursorPosition(); + x = x / self:GetEffectiveScale(); + y = y / self:GetEffectiveScale(); + + local posX = x - 175; + local posY = y + 25; + + if (self.numLootItems > 0) then + posX = x - 40; + posY = y + 55; + posY = posY + 40; + end + + if( posY < 350 ) then + posY = 350; + end + + self:ClearAllPoints(); + self:SetPoint("TOPLEFT", nil, "BOTTOMLEFT", posX, posY); + self:GetCenter(); + self:Raise(); + end + + LootFrame_Update(); + LootFramePortraitOverlay:SetTexture("Interface\\TargetingFrame\\TargetDead"); +end + +function LootFrame_OnShow(self) + if( self.numLootItems == 0 ) then + PlaySound("LOOTWINDOWOPENEMPTY"); + elseif( IsFishingLoot() ) then + PlaySound("FISHING REEL IN"); + LootFramePortraitOverlay:SetTexture("Interface\\LootFrame\\FishingLoot-Icon"); + end +end + +function LootFrame_OnHide() + CloseLoot(); + -- Close any loot distribution confirmation windows + StaticPopup_Hide("CONFIRM_LOOT_DISTRIBUTION"); +end + +function LootButton_OnClick(self, button) + -- Close any loot distribution confirmation windows + StaticPopup_Hide("CONFIRM_LOOT_DISTRIBUTION"); + + LootFrame.selectedLootButton = self:GetName(); + LootFrame.selectedSlot = self.slot; + LootFrame.selectedQuality = self.quality; + LootFrame.selectedItemName = _G[self:GetName().."Text"]:GetText(); + + LootSlot(self.slot); +end + +function LootItem_OnEnter(self) + local slot = ((LOOTFRAME_NUMBUTTONS - 1) * (LootFrame.page - 1)) + self:GetID(); + if ( LootSlotIsItem(slot) ) then + GameTooltip:SetOwner(self, "ANCHOR_RIGHT"); + GameTooltip:SetLootItem(slot); + CursorUpdate(self); + end +end + +function GroupLootDropDown_OnLoad(self) + UIDropDownMenu_Initialize(self, GroupLootDropDown_Initialize, "MENU"); +end + +function GroupLootDropDown_Initialize() + local candidate; + local info = UIDropDownMenu_CreateInfo(); + + if ( UIDROPDOWNMENU_MENU_LEVEL == 2 ) then + local lastIndex = UIDROPDOWNMENU_MENU_VALUE + 5 - 1; + for i=UIDROPDOWNMENU_MENU_VALUE, lastIndex do + candidate = GetMasterLootCandidate(i); + if ( candidate ) then + -- Add candidate button + info.text = candidate; + info.fontObject = GameFontNormalLeft; + info.value = i; + info.notCheckable = 1; + info.func = GroupLootDropDown_GiveLoot; + UIDropDownMenu_AddButton(info,UIDROPDOWNMENU_MENU_LEVEL); + end + end + return; + end + + if ( GetNumRaidMembers() > 0 ) then + -- In a raid + info.isTitle = 1; + info.text = GIVE_LOOT; + info.fontObject = GameFontNormalLeft; + info.notCheckable = 1; + UIDropDownMenu_AddButton(info); + + for i=1, 40, 5 do + for j=i, i+4 do + candidate = GetMasterLootCandidate(j); + if ( candidate ) then + -- Add raid group + info.isTitle = nil; + info.text = GROUP.." "..ceil(i/5); + info.fontObject = GameFontNormalLeft; + info.hasArrow = 1; + info.notCheckable = 1; + info.value = j; + info.func = nil; + UIDropDownMenu_AddButton(info); + break; + end + end + end + else + -- In a party + for i=1, MAX_PARTY_MEMBERS+1, 1 do + candidate = GetMasterLootCandidate(i); + if ( candidate ) then + -- Add candidate button + info.text = candidate; + info.fontObject = GameFontNormalLeft; + info.value = i; + info.notCheckable = 1; + info.value = i; + info.func = GroupLootDropDown_GiveLoot; + UIDropDownMenu_AddButton(info); + end + end + end +end + +function GroupLootDropDown_GiveLoot(self) + if ( LootFrame.selectedQuality >= MASTER_LOOT_THREHOLD ) then + local dialog = StaticPopup_Show("CONFIRM_LOOT_DISTRIBUTION", ITEM_QUALITY_COLORS[LootFrame.selectedQuality].hex..LootFrame.selectedItemName..FONT_COLOR_CODE_CLOSE, self:GetText()); + if ( dialog ) then + dialog.data = self.value; + end + else + GiveMasterLoot(LootFrame.selectedSlot, self.value); + end + CloseDropDownMenus(); +end + +function GroupLootFrame_OpenNewFrame(id, rollTime) + local frame; + for i=1, NUM_GROUP_LOOT_FRAMES do + frame = _G["GroupLootFrame"..i]; + if ( not frame:IsShown() ) then + frame.rollID = id; + frame.rollTime = rollTime; + _G["GroupLootFrame"..i.."Timer"]:SetMinMaxValues(0, rollTime); + frame:Show(); + return; + end + end +end + +function GroupLootFrame_EnableLootButton(button) + button:Enable(); + button:SetAlpha(1.0); + SetDesaturation(button:GetNormalTexture(), false); +end + +function GroupLootFrame_DisableLootButton(button) + button:Disable(); + button:SetAlpha(0.35); + SetDesaturation(button:GetNormalTexture(), true); +end + +function GroupLootFrame_OnShow(self) + AlertFrame_FixAnchors(); + local texture, name, count, quality, bindOnPickUp, canNeed, canGreed, canDisenchant, reasonNeed, reasonGreed, reasonDisenchant, deSkillRequired = GetLootRollItemInfo(self.rollID); + if (name == nil) then + self:Hide(); + return; + end + if ( bindOnPickUp ) then + self:SetBackdrop({bgFile = "Interface\\DialogFrame\\UI-DialogBox-Gold-Background", edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Gold-Border", tile = true, tileSize = 32, edgeSize = 32, insets = { left = 11, right = 12, top = 12, bottom = 11 } } ); + _G[self:GetName().."Corner"]:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Gold-Corner"); + _G[self:GetName().."Decoration"]:Show(); + else + self:SetBackdrop({bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background", edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border", tile = true, tileSize = 32, edgeSize = 32, insets = { left = 11, right = 12, top = 12, bottom = 11 } } ); + _G[self:GetName().."Corner"]:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Corner"); + _G[self:GetName().."Decoration"]:Hide(); + end + + local id = self:GetID(); + _G["GroupLootFrame"..id.."IconFrameIcon"]:SetTexture(texture); + _G["GroupLootFrame"..id.."Name"]:SetText(name); + local color = ITEM_QUALITY_COLORS[quality]; + _G["GroupLootFrame"..id.."Name"]:SetVertexColor(color.r, color.g, color.b); + if ( count > 1 ) then + _G["GroupLootFrame"..id.."IconFrameCount"]:SetText(count); + _G["GroupLootFrame"..id.."IconFrameCount"]:Show(); + else + _G["GroupLootFrame"..id.."IconFrameCount"]:Hide(); + end + + if ( canNeed ) then + GroupLootFrame_EnableLootButton(self.needButton); + self.needButton.reason = nil; + else + GroupLootFrame_DisableLootButton(self.needButton); + self.needButton.reason = _G["LOOT_ROLL_INELIGIBLE_REASON"..reasonNeed]; + end + if ( canGreed) then + GroupLootFrame_EnableLootButton(self.greedButton); + self.greedButton.reason = nil; + else + GroupLootFrame_DisableLootButton(self.greedButton); + self.greedButton.reason = _G["LOOT_ROLL_INELIGIBLE_REASON"..reasonGreed]; + end + if ( canDisenchant) then + GroupLootFrame_EnableLootButton(self.disenchantButton); + self.disenchantButton.reason = nil; + else + GroupLootFrame_DisableLootButton(self.disenchantButton); + self.disenchantButton.reason = format(_G["LOOT_ROLL_INELIGIBLE_REASON"..reasonDisenchant], deSkillRequired); + end +end + +function GroupLootFrame_OnHide (self) + AlertFrame_FixAnchors(); +end + +function GroupLootFrame_OnEvent(self, event, ...) + if ( event == "CANCEL_LOOT_ROLL" ) then + local arg1 = ...; + if ( arg1 == self.rollID ) then + self:Hide(); + StaticPopup_Hide("CONFIRM_LOOT_ROLL", self.rollID); + end + end +end + +function GroupLootFrame_OnUpdate(self, elapsed) + local left = GetLootRollTimeLeft(self:GetParent().rollID); + local min, max = self:GetMinMaxValues(); + if ( (left < min) or (left > max) ) then + left = min; + end + self:SetValue(left); +end diff --git a/reference/FrameXML/LootFrame.xml b/reference/FrameXML/LootFrame.xml new file mode 100644 index 0000000..c611603 --- /dev/null +++ b/reference/FrameXML/LootFrame.xml @@ -0,0 +1,553 @@ + +