Files
moonwell-client/reference/FrameXML/WatchFrame.lua
T

1471 lines
49 KiB
Lua

-- Who watches the WatchFrame...?
WATCHFRAME_COLLAPSEDWIDTH = 0; -- set in WatchFrame_OnLoad
WATCHFRAME_EXPANDEDWIDTH = 204;
WATCHFRAME_LINEHEIGHT = 16;
WATCHFRAME_MAXLINEWIDTH = 0; -- set in WatchFrame_SetWidth
WATCHFRAME_MULTIPLE_LINEHEIGHT = 29;
WATCHFRAME_ITEM_WIDTH = 33;
local DASH_NONE = 0;
local DASH_SHOW = 1;
local DASH_HIDE = 2;
local DASH_WIDTH;
local IS_HEADER = true;
WATCHFRAME_INITIAL_OFFSET = 0;
WATCHFRAME_TYPE_OFFSET = 10;
WATCHFRAME_QUEST_OFFSET = 10;
WATCHFRAMELINES_FONTSPACING = 0;
WATCHFRAMELINES_FONTHEIGHT = 0;
WATCHFRAME_MAXQUESTS = 10;
WATCHFRAME_MAXACHIEVEMENTS = 10;
WATCHFRAME_CRITERIA_PER_ACHIEVEMENT = 5;
WATCHFRAME_NUM_TIMERS = 0;
WATCHFRAME_NUM_ITEMS = 0;
WATCHFRAME_OBJECTIVEHANDLERS = {};
WATCHFRAME_TIMEDCRITERIA = {};
WATCHFRAME_TIMERLINES = {};
WATCHFRAME_ACHIEVEMENTLINES = {};
WATCHFRAME_QUESTLINES = {};
WATCHFRAME_LINKBUTTONS = {};
local WATCHFRAME_SETLINES = { }; -- buffer to hold lines for a quest/achievement that will be displayed only if there is room
local WATCHFRAME_SETLINES_NUMLINES; -- the number of visual lines to be rendered for the buffered data - used just for item wrapping right now
CURRENT_MAP_QUESTS = { };
LOCAL_MAP_QUESTS = { };
VISIBLE_WATCHES = { };
WATCHFRAME_FLAGS = { ["locked"] = 0x01, ["collapsed"] = 0x02 }
WATCHFRAME_ACHIEVEMENT_ARENA_CATEGORY = 165;
local watchFrameTestLine;
WATCHFRAME_SORT_PROXIMITY = 1;
WATCHFRAME_SORT_DIFFICULTY_HIGH = 2;
WATCHFRAME_SORT_DIFFICULTY_LOW = 3;
WATCHFRAME_SORT_MANUAL = 0;
WATCHFRAME_FILTER_ACHIEVEMENTS = 1;
WATCHFRAME_FILTER_COMPLETED_QUESTS = 2;
WATCHFRAME_FILTER_REMOTE_ZONES = 4;
WATCHFRAME_FILTER_NONE = 0;
WATCHFRAME_SORT_TYPE = 0;
WATCHFRAME_FILTER_TYPE = 0;
WATCHFRAME_UPDATE_RATE = 1;
local watchButtonIndex = 1;
local function WatchFrame_GetLinkButton ()
local button = WATCHFRAME_LINKBUTTONS[watchButtonIndex]
if ( not button ) then
WATCHFRAME_LINKBUTTONS[watchButtonIndex] = WatchFrame.buttonCache:GetFrame();
button = WATCHFRAME_LINKBUTTONS[watchButtonIndex];
end
watchButtonIndex = watchButtonIndex + 1;
return button;
end
local function WatchFrame_ResetLinkButtons ()
watchButtonIndex = 1;
end
local function WatchFrame_ReleaseUnusedLinkButtons ()
local watchButton
for i = watchButtonIndex, #WATCHFRAME_LINKBUTTONS do
watchButton = WATCHFRAME_LINKBUTTONS[i];
watchButton.type = nil
watchButton.index = nil;
watchButton:Hide();
watchButton.frameCache:ReleaseFrame(watchButton);
WATCHFRAME_LINKBUTTONS[i] = nil;
end
end
function WatchFrameLinkButtonTemplate_OnClick (self, button, pushed)
if ( IsModifiedClick("CHATLINK") and ChatEdit_GetActiveWindow() ) then
if ( self.type == "QUEST" ) then
local questLink = GetQuestLink(GetQuestIndexForWatch(self.index));
if ( questLink ) then
ChatEdit_InsertLink(questLink);
end
elseif ( self.type == "ACHIEVEMENT" ) then
local achievementLink = GetAchievementLink(self.index);
if ( achievementLink ) then
ChatEdit_InsertLink(achievementLink);
end
end
elseif ( button ~= "RightButton" ) then
WatchFrameLinkButtonTemplate_OnLeftClick(self, button);
else
local dropDown = WatchFrameDropDown;
if ( WatchFrame.lastLinkButton ~= self ) then
CloseDropDownMenus();
end
dropDown.type = self.type;
dropDown.index = self.index;
WatchFrame.dropDownOpen = true;
WatchFrame.lastLinkButton = self;
ToggleDropDownMenu(1, nil, dropDown, "cursor", 3, -3)
end
end
function WatchFrameLinkButtonTemplate_OnLeftClick (self, button)
CloseDropDownMenus();
if ( self.type == "QUEST" ) then
if ( IsModifiedClick("QUESTWATCHTOGGLE") ) then
WatchFrame_StopTrackingQuest( button, self.index);
else
ExpandQuestHeader( GetQuestSortIndex( GetQuestIndexForWatch(self.index) ) );
-- you have to call GetQuestIndexForWatch again because ExpandQuestHeader will sort the indices
QuestLog_OpenToQuest( GetQuestIndexForWatch(self.index) );
end
return;
elseif ( self.type == "ACHIEVEMENT" ) then
if ( not AchievementFrame ) then
AchievementFrame_LoadUI();
end
if ( IsModifiedClick("QUESTWATCHTOGGLE") ) then
WatchFrame_StopTrackingAchievement(button, self.index);
elseif ( not AchievementFrame:IsShown() ) then
AchievementFrame_ToggleAchievementFrame();
AchievementFrame_SelectAchievement(self.index);
else
if ( AchievementFrameAchievements.selection ~= self.index ) then
AchievementFrame_SelectAchievement(self.index);
else
AchievementFrame_ToggleAchievementFrame();
end
end
return;
end
end
local achievementLineIndex = 1;
local function WatchFrame_GetAchievementLine ()
local line = WATCHFRAME_ACHIEVEMENTLINES[achievementLineIndex];
if ( not line ) then
WATCHFRAME_ACHIEVEMENTLINES[achievementLineIndex] = WatchFrame.lineCache:GetFrame();
line = WATCHFRAME_ACHIEVEMENTLINES[achievementLineIndex];
end
line:Reset();
achievementLineIndex = achievementLineIndex + 1;
return line;
end
local function WatchFrame_ResetAchievementLines ()
achievementLineIndex = 1;
end
local function WatchFrame_ReleaseUnusedAchievementLines ()
local line
for i = achievementLineIndex, #WATCHFRAME_ACHIEVEMENTLINES do
line = WATCHFRAME_ACHIEVEMENTLINES[i];
line:Hide();
line.frameCache:ReleaseFrame(line);
WATCHFRAME_ACHIEVEMENTLINES[i] = nil;
end
end
local questLineIndex = 1;
local function WatchFrame_GetQuestLine ()
local line = WATCHFRAME_QUESTLINES[questLineIndex];
if ( not line ) then
WATCHFRAME_QUESTLINES[questLineIndex] = WatchFrame.lineCache:GetFrame();
line = WATCHFRAME_QUESTLINES[questLineIndex];
end
line:Reset();
questLineIndex = questLineIndex + 1;
return line;
end
local function WatchFrame_ResetQuestLines ()
questLineIndex = 1;
end
local function WatchFrame_ReleaseUnusedQuestLines ()
local line
for i = questLineIndex, #WATCHFRAME_QUESTLINES do
line = WATCHFRAME_QUESTLINES[i];
line:Hide();
line.frameCache:ReleaseFrame(line);
WATCHFRAME_QUESTLINES[i] = nil;
end
end
function WatchFrame_OnLoad (self)
self:RegisterEvent("PLAYER_ENTERING_WORLD");
self:RegisterEvent("QUEST_LOG_UPDATE");
self:RegisterEvent("TRACKED_ACHIEVEMENT_UPDATE");
self:RegisterEvent("ITEM_PUSH");
self:RegisterEvent("DISPLAY_SIZE_CHANGED");
self:RegisterEvent("ZONE_CHANGED_NEW_AREA");
self:RegisterEvent("WORLD_MAP_UPDATE");
self:RegisterEvent("QUEST_POI_UPDATE");
self:RegisterEvent("PLAYER_MONEY");
self:RegisterEvent("VARIABLES_LOADED");
self:SetScript("OnSizeChanged", WatchFrame_OnSizeChanged); -- Has to be set here instead of in XML for now due to OnSizeChanged scripts getting run before OnLoad scripts.
self.lineCache = UIFrameCache:New("FRAME", "WatchFrameLine", WatchFrameLines, "WatchFrameLineTemplate");
self.buttonCache = UIFrameCache:New("BUTTON", "WatchFrameLinkButton", WatchFrameLines, "WatchFrameLinkButtonTemplate")
watchFrameTestLine = self.lineCache:GetFrame();
local titleWidth = WatchFrameTitle:GetWidth();
WATCHFRAME_COLLAPSEDWIDTH = WatchFrameTitle:GetWidth() + 70;
local _, fontHeight = watchFrameTestLine.text:GetFont();
watchFrameTestLine.dash:SetText(QUEST_DASH);
DASH_WIDTH = watchFrameTestLine.dash:GetWidth();
WATCHFRAMELINES_FONTHEIGHT = fontHeight;
WATCHFRAMELINES_FONTSPACING = (WATCHFRAME_LINEHEIGHT - WATCHFRAMELINES_FONTHEIGHT) / 2
WatchFrame_AddObjectiveHandler(WatchFrame_HandleDisplayQuestTimers);
WatchFrame_AddObjectiveHandler(WatchFrame_HandleDisplayTrackedAchievements);
WatchFrame_AddObjectiveHandler(WatchFrame_DisplayTrackedQuests);
WatchFrame.updateTimer = WATCHFRAME_UPDATE_RATE;
end
function WatchFrame_OnEvent (self, event, ...)
if ( event == "PLAYER_MONEY" and self.watchMoney ) then
WatchFrame_Update(self);
if ( self.collapsed ) then
UIFrameFlash(WatchFrameTitleButtonHighlight, .5, .5, 5, false);
end
elseif ( event == "PLAYER_ENTERING_WORLD" ) then
SetMapToCurrentZone(); -- forces WatchFrame event via the WORLD_MAP_UPDATE event
elseif ( event == "QUEST_LOG_UPDATE" and not self.updating ) then -- May as well check here too and save some time
if ( WatchFrame.showObjectives ) then
WatchFrame_GetCurrentMapQuests();
end
WatchFrame_Update(self);
if ( self.collapsed ) then
UIFrameFlash(WatchFrameTitleButtonHighlight, .5, .5, 5, false);
end
elseif ( event == "TRACKED_ACHIEVEMENT_UPDATE" ) then
local achievementID, criteriaID, elapsed, duration = ...;
if ( not elapsed or not duration ) then
-- Don't do anything
elseif ( elapsed >= duration ) then
WATCHFRAME_TIMEDCRITERIA[criteriaID] = nil;
else
local timedCriteria = WATCHFRAME_TIMEDCRITERIA[criteriaID] or {};
timedCriteria.achievementID = achievementID;
timedCriteria.startTime = GetTime() - elapsed;
timedCriteria.duration = duration;
WATCHFRAME_TIMEDCRITERIA[criteriaID] = timedCriteria;
end
if ( self.collapsed ) then
UIFrameFlash(WatchFrameTitleButtonHighlight, .5, .5, 5, false);
end
WatchFrame_Update();
elseif ( event == "ITEM_PUSH" ) then
WatchFrame_Update();
elseif ( event == "ZONE_CHANGED_NEW_AREA" ) then
if ( not WorldMapFrame:IsShown() and WatchFrame.showObjectives ) then
SetMapToCurrentZone(); -- update the zone to get the right POI numbers for the tracker
end
elseif ( event == "WORLD_MAP_UPDATE" or event == "QUEST_POI_UPDATE" and WatchFrame.showObjectives ) then
WatchFrame_GetCurrentMapQuests();
WatchFrame_Update();
elseif ( event == "DISPLAY_SIZE_CHANGED" ) then
WatchFrame_OnSizeChanged(self);
elseif ( event == "VARIABLES_LOADED" ) then
WatchFrame_SetWidth(GetCVar("watchFrameWidth"));
WATCHFRAME_SORT_TYPE = tonumber(GetCVar("trackerSorting"));
WATCHFRAME_FILTER_TYPE = tonumber(GetCVar("trackerFilter"));
end
end
function WatchFrame_OnUpdate(self, elapsed)
if ( WATCHFRAME_SORT_TYPE == WATCHFRAME_SORT_PROXIMITY ) then
self.updateTimer = self.updateTimer - elapsed;
if ( self.updateTimer < 0 ) then
if ( SortQuestWatches() ) then
WatchFrame_Update();
end
self.updateTimer = WATCHFRAME_UPDATE_RATE;
end
end
end
function WatchFrame_OnSizeChanged(self)
WatchFrame_ClearDisplay();
WatchFrame_Update(self)
end
function WatchFrame_Collapse (self)
self.collapsed = true;
self:SetWidth(WATCHFRAME_COLLAPSEDWIDTH);
WatchFrameLines:Hide();
local button = WatchFrameCollapseExpandButton;
local texture = button:GetNormalTexture();
texture:SetTexCoord(0, 0.5, 0, 0.5);
texture = button:GetPushedTexture();
texture:SetTexCoord(0.5, 1, 0, 0.5);
end
function WatchFrame_Expand (self)
self.collapsed = nil;
self:SetWidth(WATCHFRAME_EXPANDEDWIDTH);
WatchFrameLines:Show();
local button = WatchFrameCollapseExpandButton;
local texture = button:GetNormalTexture();
texture:SetTexCoord(0, 0.5, 0.5, 1);
texture = button:GetPushedTexture();
texture:SetTexCoord(0.5, 1, 0.5, 1);
WatchFrame_Update(self);
end
function GetTimerTextColor (duration, elapsed)
local START_PERCENTAGE_YELLOW = .66
local START_PERCENTAGE_RED = .33
local percentageLeft = 1 - ( elapsed / duration )
if ( percentageLeft > START_PERCENTAGE_YELLOW ) then
return 1, 1, 1
elseif ( percentageLeft > START_PERCENTAGE_RED ) then -- Start fading to yellow by eliminating blue
local blueOffset = (percentageLeft - START_PERCENTAGE_RED) / (START_PERCENTAGE_YELLOW - START_PERCENTAGE_RED);
return 1, 1, blueOffset;
else
local greenOffset = percentageLeft / START_PERCENTAGE_RED; -- Fade to red by eliminating green
return 1, greenOffset, 0;
end
end
function WatchFrame_ClearDisplay ()
for _, timerLine in pairs(WATCHFRAME_TIMERLINES) do
timerLine:Reset();
end
for _, achievementLine in pairs(WATCHFRAME_ACHIEVEMENTLINES) do
achievementLine:Reset();
end
for _, questLine in pairs(WATCHFRAME_QUESTLINES) do
questLine:Reset();
end
end
function WatchFrame_Update (self)
self = self or WatchFrame; -- Speeds things up if we pass in this reference when we can conveniently.
-- Display things in this order: quest timers, achievements, quests, addon subscriptions.
if ( self.updating ) then
return;
end
self.updating = true;
self.watchMoney = false;
local pixelsUsed = 0;
local totalOffset = WATCHFRAME_INITIAL_OFFSET;
local lineFrame = WatchFrameLines;
local maxHeight = (WatchFrame:GetTop() - WatchFrame:GetBottom()); -- Can't use lineFrame:GetHeight() because it could be an invalid rectangle (width of 0)
local maxFrameWidth = WATCHFRAME_MAXLINEWIDTH;
local maxWidth = 0;
local maxLineWidth;
local numObjectives;
local totalObjectives = 0;
WatchFrame_ResetLinkButtons();
for i = 1, #WATCHFRAME_OBJECTIVEHANDLERS do
pixelsUsed, maxLineWidth, numObjectives = WATCHFRAME_OBJECTIVEHANDLERS[i](lineFrame, totalOffset, maxHeight, maxFrameWidth);
maxWidth = max(maxLineWidth, maxWidth);
totalObjectives = totalObjectives + numObjectives
if ( pixelsUsed > 0 ) then
totalOffset = totalOffset - WATCHFRAME_TYPE_OFFSET - pixelsUsed;
end
end
--disabled for now, might make it an option
--lineFrame:SetWidth(min(maxWidth, maxFrameWidth));
if ( totalObjectives > 0 ) then
WatchFrameHeader:Show();
WatchFrameCollapseExpandButton:Show();
WatchFrameTitle:SetText(OBJECTIVES_TRACKER_LABEL.." ("..totalObjectives..")");
WatchFrameHeader:SetWidth(WatchFrameTitle:GetWidth() + 4);
-- visible objectives?
if ( totalOffset < WATCHFRAME_INITIAL_OFFSET ) then
if ( self.collapsed and not self.userCollapsed ) then
WatchFrame_Expand(self);
end
WatchFrameCollapseExpandButton:Enable();
else
if ( not self.collapsed ) then
WatchFrame_Collapse(self);
end
WatchFrameCollapseExpandButton:Disable();
end
else
WatchFrameHeader:Hide();
WatchFrameCollapseExpandButton:Hide();
end
WatchFrame_ReleaseUnusedLinkButtons();
self.updating = nil;
self.nextOffset = totalOffset;
end
function WatchFrame_AddObjectiveHandler (func)
local numFunctions = #WATCHFRAME_OBJECTIVEHANDLERS
for i = 1, numFunctions do
if ( WATCHFRAME_OBJECTIVEHANDLERS[i] == func ) then
return;
end
end
tinsert(WATCHFRAME_OBJECTIVEHANDLERS, func);
return true;
end
function WatchFrame_RemoveObjectiveHandler (func)
local numFunctions = #WATCHFRAME_OBJECTIVEHANDLERS
for i = 1, numFunctions do
if ( WATCHFRAME_OBJECTIVEHANDLERS[i] == func ) then
tremove(WATCHFRAME_OBJECTIVEHANDLERS, i);
return true;
end
end
end
function WatchFrame_HandleDisplayQuestTimers (lineFrame, initialOffset, maxHeight, frameWidth)
return WatchFrame_DisplayQuestTimers(lineFrame, initialOffset, maxHeight, frameWidth, GetQuestTimers());
end
local timerLineIndex = 1;
local function WatchFrame_GetTimerLine ()
local line = WATCHFRAME_TIMERLINES[timerLineIndex];
if ( not line ) then
WATCHFRAME_TIMERLINES[timerLineIndex] = WatchFrame.lineCache:GetFrame();
line = WATCHFRAME_TIMERLINES[timerLineIndex];
end
line:Reset();
timerLineIndex = timerLineIndex + 1;
return line;
end
local function WatchFrame_ResetTimerLines ()
timerLineIndex = 1;
end
local function WatchFrame_ReleaseUnusedTimerLines ()
local line
for i = timerLineIndex, #WATCHFRAME_TIMERLINES do
line = WATCHFRAME_TIMERLINES[i];
line:Hide();
line:SetScript("OnEnter", nil);
line:SetScript("OnLeave", nil);
line:EnableMouse(false);
line.frameCache:ReleaseFrame(line);
WATCHFRAME_TIMERLINES[i] = nil;
end
end
function WatchFrame_DisplayQuestTimers (lineFrame, initialOffset, maxHeight, frameWidth, ...)
local numTimers = select("#", ...);
if ( numTimers == 0 ) then
WatchFrame_ResetTimerLines();
WatchFrame_ReleaseUnusedTimerLines();
-- Nothing to see here, move along.
if ( WATCHFRAME_NUM_TIMERS ~= 0 ) then
WatchFrameLines_RemoveUpdateFunction(WatchFrame_HandleQuestTimerUpdate);
WATCHFRAME_NUM_TIMERS = 0;
end
return 0, 0, 0;
end
WatchFrame_ResetTimerLines();
local lineCache = WatchFrame.lineCache;
local maxWidth = 0;
local heightUsed = 0;
local watchFrame = WatchFrame;
local line = WatchFrame_GetTimerLine();
line.text:SetText(NORMAL_FONT_COLOR_CODE .. QUEST_TIMERS);
line:Show();
line:SetPoint("TOPRIGHT", lineFrame, "TOPRIGHT", 0, initialOffset);
line:SetPoint("TOPLEFT", lineFrame, "TOPLEFT", 0, initialOffset);
heightUsed = heightUsed + line:GetHeight();
maxWidth = line.text:GetStringWidth();
local lastLine = line;
for i = 1, numTimers do
line = WatchFrame_GetTimerLine();
line.text:SetText(" - " .. SecondsToTime(select(i, ...)));
line:Show();
line:SetPoint("TOPRIGHT", lastLine, "BOTTOMRIGHT");
line:SetPoint("TOPLEFT", lastLine, "BOTTOMLEFT");
maxWidth = max(maxWidth, line.text:GetStringWidth());
line:SetWidth(maxWidth) -- FIXME
heightUsed = heightUsed + line:GetHeight();
line:SetScript("OnEnter", function (self) GameTooltip:SetOwner(self); GameTooltip:SetHyperlink(GetQuestLink(GetQuestIndexForTimer(i))); GameTooltip:Show(); end);
line:SetScript("OnLeave", GameTooltip_Hide);
line:EnableMouse(true);
end
if ( WATCHFRAME_NUM_TIMERS ~= numTimers ) then
WATCHFRAME_NUM_TIMERS = numTimers;
WatchFrameLines_AddUpdateFunction(WatchFrame_HandleQuestTimerUpdate);
end
WatchFrame_ReleaseUnusedTimerLines();
return heightUsed, maxWidth, 0;
end
function WatchFrame_HandleQuestTimerUpdate ()
return WatchFrame_QuestTimerUpdateFunction(GetQuestTimers());
end
function WatchFrame_QuestTimerUpdateFunction (...)
local numTimers = select("#", ...);
if ( numTimers ~= WATCHFRAME_NUM_TIMERS ) then
-- We need to update the entire watch frame, the number of displayed timers has changed.
return true;
end
for i = 1, numTimers do
local line = WATCHFRAME_TIMERLINES[i+1]; -- The first timer line is always the "Quest Timers" line, so skip it.
local seconds = select(i, ...);
line.text:SetText(" - " .. SecondsToTime(seconds));
end
end
function WatchFrame_HandleDisplayTrackedAchievements (lineFrame, initialOffset, maxHeight, frameWidth)
return WatchFrame_DisplayTrackedAchievements(lineFrame, initialOffset, maxHeight, frameWidth, GetTrackedAchievements());
end
function WatchFrame_UpdateTimedAchievements (elapsed)
local numAchievementLines = #WATCHFRAME_ACHIEVEMENTLINES
local timeNow, timeLeft;
local needsUpdate = false;
for i = 1, numAchievementLines do
local line = WATCHFRAME_ACHIEVEMENTLINES[i];
if ( line and line.criteriaID and WATCHFRAME_TIMEDCRITERIA[line.criteriaID] ) then
timeNow = timeNow or GetTime();
timeLeft = math.floor(line.startTime + line.duration - timeNow);
if ( timeLeft <= 0 ) then
line.text:SetText(string.format(" - " .. SECONDS_ABBR, 0));
line.text:SetTextColor(1, 0, 0, 1);
else
line.text:SetText(" - " .. SecondsToTime(timeLeft));
line.text:SetTextColor(GetTimerTextColor(line.duration, line.duration - timeLeft));
needsUpdate = true;
end
end
end
if ( not needsUpdate ) then
WatchFrameLines_RemoveUpdateFunction(WatchFrame_UpdateTimedAchievements);
end
end
function WatchFrame_SetLine(line, anchor, verticalOffset, isHeader, text, dash, hasItem, isComplete)
-- anchor
if ( anchor ) then
line:SetPoint("TOPRIGHT", anchor, "BOTTOMRIGHT", 0, verticalOffset);
line:SetPoint("TOPLEFT", anchor, "BOTTOMLEFT", 0, verticalOffset);
end
-- text
line.text:SetText(text);
if ( isHeader ) then
WATCHFRAME_SETLINES_NUMLINES = 0;
line.text:SetTextColor(0.75, 0.61, 0);
else
--this should be the default, set in WatchFrameLineTemplate_Reset
end
-- dash
local usedWidth = 0;
if ( dash == DASH_SHOW ) then
line.dash:SetText(QUEST_DASH);
usedWidth = DASH_WIDTH;
elseif ( dash == DASH_HIDE ) then
line.dash:SetText(QUEST_DASH);
line.dash:Hide();
usedWidth = DASH_WIDTH;
end
-- multiple lines
if ( hasItem and WATCHFRAME_SETLINES_NUMLINES < 2 ) then
usedWidth = usedWidth + WATCHFRAME_ITEM_WIDTH;
end
line.text:SetWidth(WATCHFRAME_MAXLINEWIDTH - usedWidth);
if ( line.text:GetHeight() > WATCHFRAME_LINEHEIGHT ) then
if ( isComplete ) then
line:SetHeight(line.text:GetHeight() + 4);
else
line:SetHeight(WATCHFRAME_MULTIPLE_LINEHEIGHT);
line.text:SetHeight(WATCHFRAME_MULTIPLE_LINEHEIGHT);
end
WATCHFRAME_SETLINES_NUMLINES = WATCHFRAME_SETLINES_NUMLINES + 2;
else
WATCHFRAME_SETLINES_NUMLINES = WATCHFRAME_SETLINES_NUMLINES + 1;
end
tinsert(WATCHFRAME_SETLINES, line);
end
function WatchFrame_DisplayTrackedAchievements (lineFrame, initialOffset, maxHeight, frameWidth, ...)
local _; -- Doing this here thanks to IBLJerry!
local numTrackedAchievements = select("#", ...);
local line;
local achievementTitle;
local previousLine;
local linkButton;
local numCriteria, criteriaDisplayed;
local achievementID, achievementName, completed, description, icon;
local criteriaString, criteriaType, criteriaCompleted, quantity, totalQuantity, name, flags, assetID, quantityString, criteriaID, achievementCategory;
local displayOnlyArena = ArenaEnemyFrames and ArenaEnemyFrames:IsShown();
local lineWidth = 0;
local maxWidth = 0;
local heightUsed = 0;
local topEdge = 0;
WatchFrame_ResetAchievementLines();
if ( bit.band(WATCHFRAME_FILTER_TYPE, WATCHFRAME_FILTER_ACHIEVEMENTS) == WATCHFRAME_FILTER_ACHIEVEMENTS ) then
for i = 1, numTrackedAchievements do
WATCHFRAME_SETLINES = table.wipe(WATCHFRAME_SETLINES or { });
achievementID = select(i, ...);
achievementCategory = GetAchievementCategory(achievementID);
_, achievementName, _, completed, _, _, _, description, _, icon = GetAchievementInfo(achievementID);
if ( not completed and (not displayOnlyArena) or achievementCategory == WATCHFRAME_ACHIEVEMENT_ARENA_CATEGORY ) then
-- achievement name
line = WatchFrame_GetAchievementLine();
achievementTitle = line;
WatchFrame_SetLine(line, previousLine, -WATCHFRAME_QUEST_OFFSET, IS_HEADER, achievementName, DASH_NONE);
if ( not previousLine ) then
line:SetPoint("TOPRIGHT", lineFrame, "TOPRIGHT", 0, initialOffset);
line:SetPoint("TOPLEFT", lineFrame, "TOPLEFT", 0, initialOffset);
topEdge = line:GetTop();
end
previousLine = line;
-- criteria
numCriteria = GetAchievementNumCriteria(achievementID);
if ( numCriteria > 0 ) then
criteriaDisplayed = 0;
for j = 1, numCriteria do
local dash = DASH_SHOW; -- default since most will have this
criteriaString, criteriaType, criteriaCompleted, quantity, totalQuantity, name, flags, assetID, quantityString, criteriaID = GetAchievementCriteriaInfo(achievementID, j);
if ( criteriaCompleted or ( criteriaDisplayed > WATCHFRAME_CRITERIA_PER_ACHIEVEMENT and not criteriaCompleted ) ) then
-- Do not display this one
criteriaString = nil;
dash = DASH_NONE;
elseif ( criteriaDisplayed == WATCHFRAME_CRITERIA_PER_ACHIEVEMENT ) then
-- We ran out of space to display incomplete criteria >_<
criteriaString = "...";
dash = DASH_HIDE;
else
if ( WATCHFRAME_TIMEDCRITERIA[criteriaID] ) then
-- not sure what this is for
local timedCriteria = WATCHFRAME_TIMEDCRITERIA[criteriaID]
line = WatchFrame_GetAchievementLine();
line.criteriaID = criteriaID;
line.duration = timedCriteria.duration;
line.startTime = timedCriteria.startTime;
WatchFrame_SetLine(line, previousLine, WATCHFRAMELINES_FONTSPACING, not IS_HEADER, "<???>", DASH_NONE);
previousLine = line;
criteriaDisplayed = criteriaDisplayed + 1;
WatchFrameLines_AddUpdateFunction(WatchFrame_UpdateTimedAchievements);
end
if ( bit.band(flags, ACHIEVEMENT_CRITERIA_PROGRESS_BAR) == ACHIEVEMENT_CRITERIA_PROGRESS_BAR ) then
-- progress bar
criteriaString = quantityString;
else
-- regular criteria
-- no need to do anything, criteriaString and dash are already set
end
end
-- set up the line
if ( criteriaString ) then
line = WatchFrame_GetAchievementLine();
WatchFrame_SetLine(line, previousLine, WATCHFRAMELINES_FONTSPACING, not IS_HEADER, criteriaString, dash);
previousLine = line;
criteriaDisplayed = criteriaDisplayed + 1;
end
end
else
-- single criteria type of achievement
line = WatchFrame_GetAchievementLine();
WatchFrame_SetLine(line, previousLine, WATCHFRAMELINES_FONTSPACING, not IS_HEADER, description, DASH_SHOW);
previousLine = line;
for criteriaID, timedCriteria in next, WATCHFRAME_TIMEDCRITERIA do
if ( timedCriteria.achievementID == achievementID ) then
-- not sure what this is for
line = WatchFrame_GetAchievementLine();
line.criteriaID = criteriaID;
line.duration = timedCriteria.duration;
line.startTime = timedCriteria.startTime;
WatchFrame_SetLine(line, previousLine, WATCHFRAMELINES_FONTSPACING, not IS_HEADER, "<???>", DASH_NONE)
previousLine = line;
WatchFrameLines_AddUpdateFunction(WatchFrame_UpdateTimedAchievements);
end
end
end
-- stop processing if there's no room to fit the achievement
local numLines = #WATCHFRAME_SETLINES;
local previousBottom = previousLine:GetBottom();
if ( previousBottom and previousBottom < WatchFrame:GetBottom() ) then
achievementLineIndex = achievementLineIndex - numLines;
table.wipe(WATCHFRAME_SETLINES);
break;
else
-- turn on all lines
for _, line in pairs(WATCHFRAME_SETLINES) do
line:Show();
lineWidth = line.text:GetWidth() + line.dash:GetWidth();
maxWidth = max(maxWidth, lineWidth);
end
-- turn on link button
linkButton = WatchFrame_GetLinkButton();
linkButton:SetPoint("TOPLEFT", achievementTitle.text);
linkButton:SetPoint("BOTTOMLEFT", achievementTitle.text);
linkButton:SetWidth(achievementTitle.text:GetStringWidth());
linkButton.type = "ACHIEVEMENT";
linkButton.index = achievementID;
linkButton.lines = WATCHFRAME_ACHIEVEMENTLINES;
linkButton.startLine = achievementLineIndex - numLines;
linkButton.lastLine = achievementLineIndex - 1;
linkButton:Show();
if ( previousBottom ) then
heightUsed = topEdge - previousBottom;
else
heightUsed = 1;
end
end
end
end
end
WatchFrame_ReleaseUnusedAchievementLines();
return heightUsed, maxWidth, numTrackedAchievements;
end
function WatchFrame_DisplayTrackedQuests (lineFrame, initialOffset, maxHeight, frameWidth)
local _;
local questTitle;
local questIndex;
local line;
local lastLine;
local linkButton;
local watchItemIndex = 0;
local numVisible = 0;
local numPOINumeric = 0;
local numPOICompleteIn = 0;
local numPOICompleteOut = 0;
local text, finished;
local numQuestWatches = GetNumQuestWatches();
local numObjectives;
local title, level, questTag, suggestedGroup, isHeader, isCollapsed, isComplete, isDaily, questID;
local maxWidth = 0;
local lineWidth = 0;
local heightUsed = 0;
local topEdge = 0;
local playerMoney = GetMoney();
local selectedQuestId;
if ( WorldMapFrame and WorldMapFrame:IsShown() ) then
selectedQuestId = WORLDMAP_SETTINGS.selectedQuestId;
else
-- For the filter REMOTE ZONES: when it's unchecked we need to display local POIs only. Unfortunately all the POI
-- code uses the current map so the tracker would not display the right quests if the world map was windowed and
-- open to a different zone.
table.wipe(LOCAL_MAP_QUESTS);
LOCAL_MAP_QUESTS["zone"] = GetCurrentMapZone();
for id in pairs(CURRENT_MAP_QUESTS) do
LOCAL_MAP_QUESTS[id] = true;
end
end
table.wipe(VISIBLE_WATCHES);
WatchFrame_ResetQuestLines();
for i = 1, numQuestWatches do
WATCHFRAME_SETLINES = table.wipe(WATCHFRAME_SETLINES or { });
questIndex = GetQuestIndexForWatch(i);
if ( questIndex ) then
title, level, questTag, suggestedGroup, isHeader, isCollapsed, isComplete, isDaily, questID = GetQuestLogTitle(questIndex);
local requiredMoney = GetQuestLogRequiredMoney(questIndex);
numObjectives = GetNumQuestLeaderBoards(questIndex);
if ( isComplete and isComplete < 0 ) then
isComplete = false;
elseif ( numObjectives == 0 and playerMoney >= requiredMoney ) then
isComplete = true;
end
-- check filters
local filterOK = true;
if ( isComplete and bit.band(WATCHFRAME_FILTER_TYPE, WATCHFRAME_FILTER_COMPLETED_QUESTS) ~= WATCHFRAME_FILTER_COMPLETED_QUESTS ) then
filterOK = false;
elseif ( bit.band(WATCHFRAME_FILTER_TYPE, WATCHFRAME_FILTER_REMOTE_ZONES) ~= WATCHFRAME_FILTER_REMOTE_ZONES and not LOCAL_MAP_QUESTS[questID] ) then
filterOK = false;
end
if ( filterOK ) then
local link, item, charges = GetQuestLogSpecialItemInfo(questIndex);
if ( requiredMoney > 0 ) then
WatchFrame.watchMoney = true; -- for update event
end
questTitle = WatchFrame_GetQuestLine();
WatchFrame_SetLine(questTitle, lastLine, -WATCHFRAME_QUEST_OFFSET, IS_HEADER, title, DASH_NONE, item);
if ( not lastLine ) then -- First line
questTitle:SetPoint("TOPRIGHT", lineFrame, "TOPRIGHT", 0, initialOffset);
questTitle:SetPoint("TOPLEFT", lineFrame, "TOPLEFT", 0, initialOffset);
topEdge = questTitle:GetTop();
end
lastLine = questTitle;
if ( isComplete ) then
line = WatchFrame_GetQuestLine();
WatchFrame_SetLine(line, lastLine, WATCHFRAMELINES_FONTSPACING, not IS_HEADER, GetQuestLogCompletionText(questIndex), DASH_SHOW, nil, true);
lastLine = line;
else
for j = 1, numObjectives do
text, _, finished = GetQuestLogLeaderBoard(j, questIndex);
if ( not finished ) then
text = WatchFrame_ReverseQuestObjective(text);
line = WatchFrame_GetQuestLine();
WatchFrame_SetLine(line, lastLine, WATCHFRAMELINES_FONTSPACING, not IS_HEADER, text, DASH_SHOW, item);
lastLine = line;
end
end
if ( requiredMoney > playerMoney ) then
text = GetMoneyString(playerMoney).." / "..GetMoneyString(requiredMoney);
line = WatchFrame_GetQuestLine();
WatchFrame_SetLine(line, lastLine, WATCHFRAMELINES_FONTSPACING, not IS_HEADER, text, DASH_SHOW, item);
lastLine = line;
end
end
-- stop processing if there's no room to fit the quest
local numLines = #WATCHFRAME_SETLINES;
local lastBottom = lastLine:GetBottom();
if ( lastBottom and lastBottom < WatchFrame:GetBottom() ) then
questLineIndex = questLineIndex - numLines;
table.wipe(WATCHFRAME_SETLINES);
break;
end
numVisible = numVisible + 1;
table.insert(VISIBLE_WATCHES, numVisible, questIndex); -- save the quest log index because watch order can change after dropdown is opened
-- turn on quest item
local itemButton;
if ( item and not isComplete ) then
watchItemIndex = watchItemIndex + 1;
itemButton = _G["WatchFrameItem"..watchItemIndex];
if ( not itemButton ) then
WATCHFRAME_NUM_ITEMS = watchItemIndex;
itemButton = CreateFrame("BUTTON", "WatchFrameItem" .. watchItemIndex, lineFrame, "WatchFrameItemButtonTemplate");
end
itemButton:Show();
itemButton:ClearAllPoints();
itemButton:SetID(questIndex);
SetItemButtonTexture(itemButton, item);
SetItemButtonCount(itemButton, charges);
itemButton.charges = charges;
WatchFrameItem_UpdateCooldown(itemButton);
itemButton.rangeTimer = -1;
itemButton:SetPoint("TOPRIGHT", questTitle, "TOPRIGHT", 10, -2);
end
-- turn on all lines
for _, line in pairs(WATCHFRAME_SETLINES) do
line:Show();
lineWidth = line.text:GetWidth() + line.dash:GetWidth();
maxWidth = max(maxWidth, lineWidth);
end
-- turn on link button
linkButton = WatchFrame_GetLinkButton();
linkButton:SetPoint("TOPLEFT", questTitle);
linkButton:SetPoint("BOTTOMLEFT", questTitle);
linkButton:SetPoint("RIGHT", questTitle.text);
linkButton.type = "QUEST"
linkButton.index = i; -- We want the Watch index, we'll get the quest index later with GetQuestIndexForWatch(i);
linkButton.lines = WATCHFRAME_QUESTLINES;
linkButton.startLine = questLineIndex - numLines;
linkButton.lastLine = questLineIndex - 1;
linkButton:Show();
-- quest POI icon
if ( WatchFrame.showObjectives ) then
local poiButton;
if ( CURRENT_MAP_QUESTS[questID] ) then
if ( isComplete ) then
numPOICompleteIn = numPOICompleteIn + 1;
poiButton = QuestPOI_DisplayButton("WatchFrameLines", QUEST_POI_COMPLETE_IN, numPOICompleteIn, questID);
else
numPOINumeric = numPOINumeric + 1;
poiButton = QuestPOI_DisplayButton("WatchFrameLines", QUEST_POI_NUMERIC, numPOINumeric, questID);
end
elseif ( isComplete ) then
numPOICompleteOut = numPOICompleteOut + 1;
poiButton = QuestPOI_DisplayButton("WatchFrameLines", QUEST_POI_COMPLETE_OUT, numPOICompleteOut, questID);
end
if ( poiButton ) then
poiButton:SetPoint("TOPRIGHT", questTitle, "TOPLEFT", 0, 5);
end
end
if ( lastBottom ) then
heightUsed = topEdge - lastLine:GetBottom();
else
heightUsed = 1;
end
end
end
end
for i = watchItemIndex + 1, WATCHFRAME_NUM_ITEMS do
_G["WatchFrameItem" .. i]:Hide();
end
QuestPOI_HideButtons("WatchFrameLines", QUEST_POI_NUMERIC, numPOINumeric + 1);
QuestPOI_HideButtons("WatchFrameLines", QUEST_POI_COMPLETE_IN, numPOICompleteIn + 1);
QuestPOI_HideButtons("WatchFrameLines", QUEST_POI_COMPLETE_OUT, numPOICompleteOut + 1);
WatchFrame_ReleaseUnusedQuestLines();
if ( selectedQuestId ) then
QuestPOI_SelectButtonByQuestId("WatchFrameLines", selectedQuestId, true);
end
return heightUsed, maxWidth, numQuestWatches;
end
function WatchFrameLines_OnUpdate (self, elapsed)
for i = 1, self.numFunctions do
if ( self.updateFunctions[i](elapsed) ) then -- If a function returns true, update the entire watch frame (the number of lines changed).
WatchFrame_Update(WatchFrame);
return;
end
end
end
function WatchFrameLines_AddUpdateFunction (func)
local self = WatchFrameLines;
local numFunctions = self.numFunctions
for i = 1, numFunctions do
if ( self.updateFunctions[i] == func ) then
return;
end
end
tinsert(self.updateFunctions, func);
self.numFunctions = self.numFunctions + 1;
self:SetScript("OnUpdate", WatchFrameLines_OnUpdate);
end
function WatchFrameLines_RemoveUpdateFunction (func)
local self = WatchFrameLines;
local numFunctions = WatchFrameLines.numFunctions
for i = 1, numFunctions do
if ( self.updateFunctions[i] == func ) then
tremove(self.updateFunctions, i);
self.numFunctions = self.numFunctions - 1;
break;
end
end
if ( self.numFunctions == 0 ) then
self:SetScript("OnUpdate", nil);
end
end
function WatchFrame_OpenQuestLog (button, arg1, arg2, checked)
ExpandQuestHeader(GetQuestIndexForWatch(arg1));
-- you have to call GetQuestIndexForWatch again because ExpandQuestHeader will sort the indices
QuestLog_OpenToQuest(GetQuestIndexForWatch(arg1), arg2);
end
function WatchFrame_AbandonQuest (button, arg1, arg2, checked)
local lastQuest = GetQuestLogSelection();
local lastNumQuests = GetNumQuestLogEntries();
SelectQuestLogEntry(GetQuestIndexForWatch(arg1)); -- More or less QuestLogFrameAbandonButton_OnClick, may want to consolidate
SetAbandonQuest();
local items = GetAbandonQuestItems();
if ( items ) then
StaticPopup_Hide("ABANDON_QUEST");
StaticPopup_Show("ABANDON_QUEST_WITH_ITEMS", GetAbandonQuestName(), items);
else
StaticPopup_Hide("ABANDON_QUEST_WITH_ITEMS");
StaticPopup_Show("ABANDON_QUEST", GetAbandonQuestName());
end
SelectQuestLogEntry(lastQuest);
end
function WatchFrame_ShareQuest (button, arg1, arg2, checked)
QuestLogPushQuest(GetQuestIndexForWatch(arg1));
end
function WatchFrame_StopTrackingQuest (button, arg1, arg2, checked)
RemoveQuestWatch(GetQuestIndexForWatch(arg1));
WatchFrame_Update();
QuestLog_Update();
end
function WatchFrame_OpenMapToQuest (button, arg1)
local index = GetQuestIndexForWatch(arg1);
local questID = select(9, GetQuestLogTitle(index));
WorldMap_OpenToQuest(questID);
end
function WatchFrame_OpenAchievementFrame (button, arg1, arg2, checked)
if ( not AchievementFrame ) then
AchievementFrame_LoadUI();
end
if ( not AchievementFrame:IsShown() ) then
AchievementFrame_ToggleAchievementFrame();
AchievementFrame_SelectAchievement(arg1);
else
if ( AchievementFrameAchievements.selection ~= arg1 ) then
AchievementFrame_SelectAchievement(arg1);
else
AchievementFrame_ToggleAchievementFrame();
end
end
end
function WatchFrame_StopTrackingAchievement (button, arg1, arg2, checked)
RemoveTrackedAchievement(arg1);
WatchFrame_Update();
if ( AchievementFrame ) then
AchievementFrameAchievements_ForceUpdate(); -- Quests handle this automatically because they have spiffy events.
end
end
function WatchFrameDropDown_OnHide ()
WatchFrame.dropDownOpen = nil;
if ( WatchFrame.lastLinkButton ) then
WatchFrame.lastLinkButton = nil;
end
end
function WatchFrameDropDown_OnLoad (self)
UIDropDownMenu_Initialize(self, WatchFrameDropDown_Initialize, "MENU");
self.onHide = WatchFrameDropDown_OnHide;
end
function WatchFrameDropDown_Initialize (self)
if ( self.type == "QUEST" ) then
local info = UIDropDownMenu_CreateInfo();
local questLogIndex = GetQuestIndexForWatch(self.index);
info.text = GetQuestLogTitle(questLogIndex);
info.isTitle = 1;
info.notCheckable = 1;
UIDropDownMenu_AddButton(info, UIDROPDOWN_MENU_LEVEL);
info = UIDropDownMenu_CreateInfo();
info.notCheckable = 1;
info.text = OBJECTIVES_VIEW_IN_QUESTLOG;
info.func = WatchFrame_OpenQuestLog;
info.arg1 = self.index;
info.arg2 = true;
info.noClickSound = 1;
info.checked = false;
UIDropDownMenu_AddButton(info, UIDROPDOWN_MENU_LEVEL);
info.text = OBJECTIVES_STOP_TRACKING;
info.func = WatchFrame_StopTrackingQuest;
info.arg1 = self.index;
info.checked = false;
UIDropDownMenu_AddButton(info, UIDROPDOWN_MENU_LEVEL);
if ( GetQuestLogPushable(GetQuestIndexForWatch(self.index)) and ( GetNumPartyMembers() > 0 or GetNumRaidMembers() > 1 ) ) then
info.text = SHARE_QUEST;
info.func = WatchFrame_ShareQuest;
info.arg1 = self.index;
info.checked = false;
UIDropDownMenu_AddButton(info, UIDROPDOWN_MENU_LEVEL);
end
if ( WatchFrame.showObjectives ) then
info.text = OBJECTIVES_SHOW_QUEST_MAP;
info.func = WatchFrame_OpenMapToQuest;
info.arg1 = self.index;
info.checked = false;
info.noClickSound = 1;
UIDropDownMenu_AddButton(info, UIDROPDOWN_MENU_LEVEL);
end
local numVisibleWatches = #VISIBLE_WATCHES;
if ( numVisibleWatches > 1 ) then
local visibleIndex = WatchFrame_GetVisibleIndex(questLogIndex);
if ( visibleIndex > 1 ) then
info.text = TRACKER_SORT_MANUAL_UP;
info.func = WatchFrame_MoveQuest;
info.arg1 = questLogIndex;
info.arg2 = -1;
info.checked = false;
UIDropDownMenu_AddButton(info, UIDROPDOWN_MENU_LEVEL);
info.text = TRACKER_SORT_MANUAL_TOP;
info.func = WatchFrame_MoveQuest;
info.arg1 = questLogIndex;
info.arg2 = -100; -- ensure move up to top regardless of reordering after dropdown has been opened
info.checked = false;
UIDropDownMenu_AddButton(info, UIDROPDOWN_MENU_LEVEL);
end
if ( visibleIndex < numVisibleWatches ) then
info.text = TRACKER_SORT_MANUAL_DOWN;
info.func = WatchFrame_MoveQuest;
info.arg1 = questLogIndex;
info.arg2 = 1;
info.checked = false;
UIDropDownMenu_AddButton(info, UIDROPDOWN_MENU_LEVEL);
info.text = TRACKER_SORT_MANUAL_BOTTOM;
info.func = WatchFrame_MoveQuest;
info.arg1 = questLogIndex;
info.arg2 = 100; -- ensure move down to bottom regardless of reordering after dropdown has been opened
info.checked = false;
UIDropDownMenu_AddButton(info, UIDROPDOWN_MENU_LEVEL);
end
end
elseif ( self.type == "ACHIEVEMENT" ) then
local _, achievementName, _, completed, _, _, _, _, _, icon = GetAchievementInfo(self.index);
local info = UIDropDownMenu_CreateInfo();
info.text = achievementName;
info.isTitle = 1;
info.notCheckable = 1;
UIDropDownMenu_AddButton(info, UIDROPDOWN_MENU_LEVEL);
info = UIDropDownMenu_CreateInfo();
info.notCheckable = 1;
info.text = OBJECTIVES_VIEW_ACHIEVEMENT;
info.func = WatchFrame_OpenAchievementFrame;
info.arg1 = self.index;
info.checked = false;
UIDropDownMenu_AddButton(info, UIDROPDOWN_MENU_LEVEL);
info.text = OBJECTIVES_STOP_TRACKING;
info.func = WatchFrame_StopTrackingAchievement;
info.arg1 = self.index;
info.checked = false;
UIDropDownMenu_AddButton(info, UIDROPDOWN_MENU_LEVEL);
end
end
function WatchFrame_CollapseExpandButton_OnClick (self)
local WatchFrame = WatchFrame;
if ( WatchFrame.collapsed ) then
WatchFrame.userCollapsed = nil;
WatchFrame_Expand(WatchFrame);
PlaySound("igMiniMapOpen");
else
WatchFrame.userCollapsed = true;
WatchFrame_Collapse(WatchFrame);
PlaySound("igMiniMapClose");
end
end
local function WatchFrameLineTemplate_Reset (self)
self:ClearAllPoints();
self.text:SetText("");
self.text:SetTextColor(0.8, 0.8, 0.8);
self.text:Show();
self.dash:SetText(nil);
self.dash:Show();
self:SetHeight(WATCHFRAME_LINEHEIGHT);
self.text:SetHeight(0);
self.criteriaID = nil;
end
function WatchFrameLineTemplate_OnLoad (self)
local name = self:GetName();
self.Reset = WatchFrameLineTemplate_Reset;
end
function WatchFrameItem_UpdateCooldown (self)
local itemCooldown = _G[self:GetName().."Cooldown"];
local start, duration, enable = GetQuestLogSpecialItemCooldown(self:GetID());
CooldownFrame_SetTimer(itemCooldown, start, duration, enable);
if ( duration > 0 and enable == 0 ) then
SetItemButtonTextureVertexColor(self, 0.4, 0.4, 0.4);
else
SetItemButtonTextureVertexColor(self, 1, 1, 1);
end
end
function WatchFrameItem_OnLoad (self)
self:RegisterForClicks("AnyUp");
end
function WatchFrameItem_OnEvent (self, event, ...)
if ( event == "PLAYER_TARGET_CHANGED" ) then
self.rangeTimer = -1;
elseif ( event == "BAG_UPDATE_COOLDOWN" ) then
WatchFrameItem_UpdateCooldown(self);
end
end
function WatchFrameItem_OnUpdate (self, elapsed)
-- Handle range indicator
local rangeTimer = self.rangeTimer;
if ( rangeTimer ) then
rangeTimer = rangeTimer - elapsed;
if ( rangeTimer <= 0 ) then
local link, item, charges = GetQuestLogSpecialItemInfo(self:GetID());
if ( not charges or charges ~= self.charges ) then
WatchFrame_Update();
return;
end
local count = _G[self:GetName().."HotKey"];
local valid = IsQuestLogSpecialItemInRange(self:GetID());
if ( valid == 0 ) then
count:Show();
count:SetVertexColor(1.0, 0.1, 0.1);
elseif ( valid == 1 ) then
count:Show();
count:SetVertexColor(0.6, 0.6, 0.6);
else
count:Hide();
end
rangeTimer = TOOLTIP_UPDATE_TIME;
end
self.rangeTimer = rangeTimer;
end
end
function WatchFrameItem_OnShow (self)
self:RegisterEvent("PLAYER_TARGET_CHANGED");
self:RegisterEvent("BAG_UPDATE_COOLDOWN");
end
function WatchFrameItem_OnHide (self)
self:UnregisterEvent("PLAYER_TARGET_CHANGED");
self:UnregisterEvent("BAG_UPDATE_COOLDOWN");
end
function WatchFrameItem_OnEnter (self)
GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
GameTooltip:SetQuestLogSpecialItem(self:GetID());
end
function WatchFrameItem_OnClick (self, button, down)
local questIndex = self:GetID();
if ( IsModifiedClick("CHATLINK") and ChatEdit_GetActiveWindow() ) then
local link, item, charges = GetQuestLogSpecialItemInfo(questIndex);
if ( link ) then
ChatEdit_InsertLink(link);
end
else
UseQuestLogSpecialItem(questIndex);
end
end
function WatchFrame_ReverseQuestObjective(text)
local _, _, arg1, arg2 = string.find(text, "(.*):%s(.*)");
if ( arg1 and arg2 ) then
return arg2.." "..arg1;
else
return text;
end
end
function WatchFrameLinkButtonTemplate_Highlight(self, onEnter)
local line;
for index = self.startLine, self.lastLine do
line = self.lines[index];
if ( line ) then
if ( index == self.startLine ) then
-- header
if ( onEnter ) then
line.text:SetTextColor(NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b);
else
line.text:SetTextColor(0.75, 0.61, 0);
end
else
if ( onEnter ) then
line.text:SetTextColor(HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b);
line.dash:SetTextColor(HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b);
else
line.text:SetTextColor(0.8, 0.8, 0.8);
line.dash:SetTextColor(0.8, 0.8, 0.8);
end
end
end
end
end
function WatchFrame_GetCurrentMapQuests()
local numQuests = QuestMapUpdateAllQuests();
table.wipe(CURRENT_MAP_QUESTS);
for i = 1, numQuests do
local questId = QuestPOIGetQuestIDByVisibleIndex(i);
CURRENT_MAP_QUESTS[questId] = i;
end
end
function WatchFrameQuestPOI_OnClick(self)
if ( WorldMapFrame:IsShown() ) then
if ( WORLDMAP_SETTINGS.selectedQuestId == self.questId ) then
HideUIPanel(WorldMapFrame);
return;
end
PlaySound("igMainMenuOptionCheckBoxOn");
end
WorldMap_OpenToQuest(self.questId);
end
function WatchFrame_SetWidth(width)
if ( width == "0" ) then
WATCHFRAME_EXPANDEDWIDTH = 204;
WATCHFRAME_MAXLINEWIDTH = 192;
else
WATCHFRAME_EXPANDEDWIDTH = 306;
WATCHFRAME_MAXLINEWIDTH = 294;
end
if ( WatchFrame:IsShown() and not WatchFrame.collapsed ) then
WatchFrame:SetWidth(WATCHFRAME_EXPANDEDWIDTH);
WatchFrame_Update();
end
end
-- header dropdown
function WatchFrameHeader_OnClick(self, button)
if ( button == "RightButton" ) then
ToggleDropDownMenu(1, nil, WatchFrameHeaderDropDown, "cursor", 3, -3)
end
end
function WatchFrameHeaderDropDown_OnLoad (self)
UIDropDownMenu_Initialize(self, WatchFrameHeaderDropDown_Initialize, "MENU");
end
function WatchFrameHeaderDropDown_Initialize (self)
local info = UIDropDownMenu_CreateInfo();
-- sort label
info.text = TRACKER_SORT_LABEL;
info.isTitle = 1;
info.notCheckable = 1;
UIDropDownMenu_AddButton(info, UIDROPDOWN_MENU_LEVEL);
-- sort: proximity
info = UIDropDownMenu_CreateInfo();
info.checked = (WATCHFRAME_SORT_TYPE == WATCHFRAME_SORT_PROXIMITY);
info.text = TRACKER_SORT_PROXIMITY;
info.tooltipTitle = TRACKER_SORT_PROXIMITY;
info.tooltipText = TOOLTIP_TRACKER_SORT_PROXIMITY;
info.arg1 = WATCHFRAME_SORT_PROXIMITY;
info.func = WatchFrame_SetSorting;
UIDropDownMenu_AddButton(info, UIDROPDOWN_MENU_LEVEL);
-- sort: difficulty high
info = UIDropDownMenu_CreateInfo();
info.checked = (WATCHFRAME_SORT_TYPE == WATCHFRAME_SORT_DIFFICULTY_HIGH);
info.text = TRACKER_SORT_DIFFICULTY_HIGH;
info.tooltipTitle = TRACKER_SORT_DIFFICULTY_HIGH;
info.tooltipText = TOOLTIP_TRACKER_SORT_DIFFICULTY_HIGH;
info.arg1 = WATCHFRAME_SORT_DIFFICULTY_HIGH;
info.func = WatchFrame_SetSorting;
UIDropDownMenu_AddButton(info, UIDROPDOWN_MENU_LEVEL);
-- sort: difficulty low
info = UIDropDownMenu_CreateInfo();
info.checked = (WATCHFRAME_SORT_TYPE == WATCHFRAME_SORT_DIFFICULTY_LOW);
info.text = TRACKER_SORT_DIFFICULTY_LOW;
info.tooltipTitle = TRACKER_SORT_DIFFICULTY_LOW;
info.tooltipText = TOOLTIP_TRACKER_SORT_DIFFICULTY_LOW;
info.arg1 = WATCHFRAME_SORT_DIFFICULTY_LOW;
info.func = WatchFrame_SetSorting;
UIDropDownMenu_AddButton(info, UIDROPDOWN_MENU_LEVEL);
-- sort: manual
info = UIDropDownMenu_CreateInfo();
info.checked = (WATCHFRAME_SORT_TYPE == WATCHFRAME_SORT_MANUAL);
info.text = TRACKER_SORT_MANUAL;
info.tooltipTitle = TRACKER_SORT_MANUAL;
info.tooltipText = TOOLTIP_TRACKER_SORT_MANUAL;
info.arg1 = WATCHFRAME_SORT_MANUAL;
info.func = WatchFrame_SetSorting;
UIDropDownMenu_AddButton(info, UIDROPDOWN_MENU_LEVEL);
-- filter label
info.text = TRACKER_FILTER_LABEL;
info.checked = false;
info.isTitle = 1;
info.notCheckable = 1;
UIDropDownMenu_AddButton(info, UIDROPDOWN_MENU_LEVEL);
-- filter: achievements
info = UIDropDownMenu_CreateInfo();
info.checked = (bit.band(WATCHFRAME_FILTER_TYPE, WATCHFRAME_FILTER_ACHIEVEMENTS) == WATCHFRAME_FILTER_ACHIEVEMENTS);
info.text = TRACKER_FILTER_ACHIEVEMENTS;
info.tooltipTitle = TRACKER_FILTER_ACHIEVEMENTS;
info.tooltipText = TOOLTIP_TRACKER_FILTER_ACHIEVEMENTS;
info.arg1 = WATCHFRAME_FILTER_ACHIEVEMENTS;
info.func = WatchFrame_SetFilter;
UIDropDownMenu_AddButton(info, UIDROPDOWN_MENU_LEVEL);
-- filter: completed quests
info = UIDropDownMenu_CreateInfo();
info.checked = (bit.band(WATCHFRAME_FILTER_TYPE, WATCHFRAME_FILTER_COMPLETED_QUESTS) == WATCHFRAME_FILTER_COMPLETED_QUESTS);
info.text = TRACKER_FILTER_COMPLETED_QUESTS;
info.tooltipTitle = TRACKER_FILTER_COMPLETED_QUESTS;
info.tooltipText = TOOLTIP_TRACKER_FILTER_COMPLETED_QUESTS;
info.arg1 = WATCHFRAME_FILTER_COMPLETED_QUESTS;
info.func = WatchFrame_SetFilter;
UIDropDownMenu_AddButton(info, UIDROPDOWN_MENU_LEVEL);
-- filter: current zone
info = UIDropDownMenu_CreateInfo();
info.checked = (bit.band(WATCHFRAME_FILTER_TYPE, WATCHFRAME_FILTER_REMOTE_ZONES) == WATCHFRAME_FILTER_REMOTE_ZONES);
info.text = TRACKER_FILTER_REMOTE_ZONES;
info.tooltipTitle = TRACKER_FILTER_REMOTE_ZONES;
info.tooltipText = TOOLTIP_TRACKER_FILTER_REMOTE_ZONES;
info.arg1 = WATCHFRAME_FILTER_REMOTE_ZONES;
info.func = WatchFrame_SetFilter;
UIDropDownMenu_AddButton(info, UIDROPDOWN_MENU_LEVEL);
end
function WatchFrame_SetSorting(button, arg1)
WATCHFRAME_SORT_TYPE = arg1;
SetCVar("trackerSorting", WATCHFRAME_SORT_TYPE);
if ( WATCHFRAME_SORT_TYPE ~= WATCHFRAME_SORT_MANUAL ) then
SortQuestWatches();
WatchFrame_Update();
WatchFrame.updateTimer = WATCHFRAME_UPDATE_RATE;
end
end
function WatchFrame_SetFilter(button, arg1)
if ( bit.band(WATCHFRAME_FILTER_TYPE, arg1) == arg1 ) then
WATCHFRAME_FILTER_TYPE = WATCHFRAME_FILTER_TYPE - arg1;
else
WATCHFRAME_FILTER_TYPE = WATCHFRAME_FILTER_TYPE + arg1;
end
SetCVar("trackerFilter", WATCHFRAME_FILTER_TYPE);
WatchFrame_Update();
end
function WatchFrame_GetVisibleIndex(questLogIndex)
for i = 1, #VISIBLE_WATCHES do
if ( VISIBLE_WATCHES[i] == questLogIndex ) then
return i;
end
end
end
function WatchFrame_MoveQuest(button, questLogIndex, numMoves)
if ( WATCHFRAME_SORT_TYPE ~= WATCHFRAME_SORT_MANUAL ) then
WatchFrame_SetSorting(nil, WATCHFRAME_SORT_MANUAL);
UIErrorsFrame:AddMessage(TRACKER_SORT_MANUAL_WARNING, 1.0, 1.0, 0.0, 1.0);
end
local numVisibleWatches = #VISIBLE_WATCHES;
local indexStart = WatchFrame_GetVisibleIndex(questLogIndex);
local indexEnd = indexStart + numMoves;
if ( indexEnd < 1 ) then
indexEnd = 1;
elseif ( indexEnd > numVisibleWatches ) then
indexEnd = numVisibleWatches;
end
ShiftQuestWatches(GetQuestWatchIndex(questLogIndex), GetQuestWatchIndex(VISIBLE_WATCHES[indexEnd]));
WatchFrame_Update();
end