-- global constants
MAX_QUESTS = 25;
MAX_OBJECTIVES = 10;
MAX_QUESTLOG_QUESTS = 25;
MAX_WATCHABLE_QUESTS = 25;
MAX_QUEST_WATCH_TIME = 300;
QuestDifficultyColors["impossible"].font = QuestDifficulty_Impossible;
QuestDifficultyColors["verydifficult"].font = QuestDifficulty_VeryDifficult;
QuestDifficultyColors["difficult"].font = QuestDifficulty_Difficult;
QuestDifficultyColors["standard"].font = QuestDifficulty_Standard;
QuestDifficultyColors["trivial"].font = QuestDifficulty_Trivial;
QuestDifficultyColors["header"].font = QuestDifficulty_Header;
-- local constants
local QUEST_TIMER_UPDATE_DELAY = 0.1;
local GROUP_UPDATE_INTERVAL_SEC = 3;
-- update optimizations
local max = max;
--
-- local helper functions
--
local function _QuestLog_HighlightQuest(questLogTitle)
local prevParent = QuestLogHighlightFrame:GetParent();
if ( prevParent and prevParent ~= questLogTitle ) then
-- set prev quest's colors back to normal
local prevName = prevParent:GetName();
prevParent:UnlockHighlight();
prevParent.tag:SetTextColor(prevParent.r, prevParent.g, prevParent.b);
prevParent.groupMates:SetTextColor(prevParent.r, prevParent.g, prevParent.b);
end
if ( questLogTitle ) then
local name = questLogTitle:GetName();
-- highlight the quest's colors
questLogTitle.tag:SetTextColor(HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b);
questLogTitle.groupMates:SetTextColor(HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b);
questLogTitle:LockHighlight();
-- reposition highlight frames
QuestLogHighlightFrame:SetParent(questLogTitle);
QuestLogHighlightFrame:SetPoint("TOPLEFT", questLogTitle, "TOPLEFT", 0, 0);
QuestLogHighlightFrame:SetPoint("BOTTOMRIGHT", questLogTitle, "BOTTOMRIGHT", 0, 0);
QuestLogSkillHighlight:SetVertexColor(questLogTitle.r, questLogTitle.g, questLogTitle.b);
QuestLogHighlightFrame:Show();
else
QuestLogHighlightFrame:Hide();
end
end
-- this function returns the amount needed to adjust the scroll bar in order to get the given quest index to appear in the
-- QuestLogScrollFrame's viewable area
local function _QuestLog_GetQuestScrollOffset(questIndex)
local scrollBarOffset = 0;
local buttons = QuestLogScrollFrame.buttons;
local testButton = buttons[1];
local testIndex = testButton:GetID();
local buttonHeight = testButton:GetHeight();
if ( questIndex <= testIndex ) then
if ( questIndex < testIndex ) then
-- selected quest comes before the first visible quest
-- instead of just offsetting by the delta of the indexes, we offset by 1 more to get the line BEFORE the selected
-- line to be at the top...if we don't do this, then the selected line would be at the top of the frame, which
-- isn't bad, but it feels better if we have the previous element at the top
scrollBarOffset = (testIndex - questIndex + 1) * buttonHeight;
end
-- make sure the visible area is aligned to the top of a button by adding the difference between the button's
-- top and the scroll area's top
scrollBarOffset = scrollBarOffset - (QuestLogScrollFrame:GetTop() - testButton:GetTop());
else
local numButtons = #buttons;
testButton = buttons[numButtons];
testIndex = max(testButton:GetID(), numButtons); --If the buttons aren't initalized, this will default to the last button. The index of the last button should never be greater than it's ID otherwise
if ( questIndex >= (testIndex - 1) ) then
if ( questIndex > testIndex ) then
-- selected quest comes after the last visible quest
-- instead of just offsetting by the delta of the indexes, we offset by 1 more to get the line AFTER the selected
-- line to be at the bottom...if we don't do this, then the selected line would be at the bottom of the frame, which
-- isn't bad, but it feels better if we have the next element at the bottom
scrollBarOffset = (testIndex - questIndex - 1) * buttonHeight;
end
-- make sure the visible area is aligned to the bottom of a button by adding the difference between the button's
-- bottom and the scroll area's bottom
if ( questIndex == (testIndex - 1) ) then
testButton = buttons[numButtons - 1];
end
local testBottom = testButton:GetBottom();
local scrollBottom = QuestLogScrollFrame:GetBottom();
if ( scrollBottom > testBottom ) then
-- don't add the offset unless the test button is actually lower than the scroll frame...it feels jumpy if you do
scrollBarOffset = scrollBarOffset + (testBottom - scrollBottom);
end
end
end
return scrollBarOffset;
end
local function _QuestLog_ToggleQuestWatch(questIndex)
if ( IsQuestWatched(questIndex) ) then
RemoveQuestWatch(questIndex);
WatchFrame_Update();
else
if ( GetNumQuestWatches() >= MAX_WATCHABLE_QUESTS ) then -- Check this first though it's less likely, otherwise they could make the frame bigger and be disappointed
UIErrorsFrame:AddMessage(format(QUEST_WATCH_TOO_MANY, MAX_WATCHABLE_QUESTS), 1.0, 0.1, 0.1, 1.0);
return;
end
AddQuestWatch(questIndex);
WatchFrame_Update();
end
end
--
-- QuestLogTitleButton
--
function QuestLogTitleButton_OnLoad(self)
self:RegisterForClicks("LeftButtonUp", "RightButtonUp");
self:RegisterEvent("UNIT_QUEST_LOG_CHANGED");
self:RegisterEvent("GROUP_ROSTER_UPDATE");
self:RegisterEvent("PARTY_MEMBER_ENABLE");
self:RegisterEvent("PARTY_MEMBER_DISABLE");
-- anchor the check to the normal text now since we can't do it with the way it's currently setup in XML
local name = self:GetName();
self.check:SetPoint("LEFT", name.."NormalText", "RIGHT", 2, 0);
end
function QuestLogTitleButton_OnEvent(self, event, ...)
if ( GameTooltip:IsOwned(self) ) then
GameTooltip:Hide();
QuestLog_UpdatePartyInfoTooltip(self);
end
end
function QuestLogTitleButton_OnClick(self, button)
local questName = self:GetText();
local questIndex = self:GetID();
if ( IsModifiedClick() ) then
-- If header then return
if ( self.isHeader ) then
return;
end
-- Otherwise try to track it or put it into chat
if ( IsModifiedClick("CHATLINK") and ChatEdit_GetActiveWindow() ) then
local questLink = GetQuestLink(questIndex);
if ( questLink ) then
ChatEdit_InsertLink(questLink);
end
QuestLog_SetSelection(questIndex);
elseif ( IsModifiedClick("QUESTWATCHTOGGLE") ) then
_QuestLog_ToggleQuestWatch(questIndex);
QuestLog_SetSelection(questIndex);
QuestLog_Update();
end
else
QuestLog_SetSelection(questIndex);
end
end
function QuestLogTitleButton_OnEnter(self)
-- Set highlight
local name = self:GetName();
self.tag:SetTextColor(HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b);
self.groupMates:SetTextColor(HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b);
-- Set group info tooltip
QuestLog_UpdatePartyInfoTooltip(self);
end
function QuestLogTitleButton_OnLeave(self)
if ( self:GetID() ~= QuestLogFrame.selectedIndex ) then
local name = self:GetName();
self.tag:SetTextColor(self.r, self.g, self.b);
self.groupMates:SetTextColor(self.r, self.g, self.b);
end
GameTooltip:Hide();
end
-- HACK ALERT --
-- QuestLogTitleButton_Resize contains a couple of big hacks to compensate for some weaknesses in the UI system
function QuestLogTitleButton_Resize(questLogTitle)
-- the purpose of this function is to resize the contents of the questLogTitle button to fit inside its width
-- first reset the width of the button's font string (called normal text)
local questNormalText = questLogTitle.normalText;
-- HACK: in order to reset the width of the font string to be exactly the width of the quest title text,
-- we have to explicitly set the font string's width to 0 and then call SetText on the button
questNormalText:SetWidth(0);
questLogTitle:SetText(questLogTitle:GetText());
local questTitleTag = questLogTitle.tag;
local questCheck = questLogTitle.check;
-- find the right edge of the text
-- HACK: Unfortunately we can't just call questTitleTag:GetLeft() or questLogTitle:GetRight() to find right edges.
-- The reason why is because SetWidth may be called on the questLogTitle button before we enter this function. The
-- results of a SetWidth are not calculated until the next update tick; so in order to get the most up-to-date
-- right edge, we call GetLeft() + GetWidth() instead of just GetRight()
local rightEdge = questLogTitle:GetLeft() + questLogTitle:GetWidth();
-- adjust the normal text to not overrun the button
if ( questCheck:IsShown() ) then
rightEdge = rightEdge - questCheck:GetWidth() - 2;
end
-- adjust the normal text to not overrun the title tag
if ( questTitleTag:IsShown() ) then
rightEdge = rightEdge - questTitleTag:GetWidth() - 4;
end
if (questLogTitle.QuestionMark:IsShown()) then
rightEdge = rightEdge - questLogTitle.QuestionMark:GetWidth();
end
-- subtract from the text width the number of pixels that overrun the right edge
local questNormalTextWidth = questNormalText:GetWidth() - max(questNormalText:GetRight() - rightEdge, 0);
questNormalText:SetWidth(questNormalTextWidth);
end
function QuestLogScrollFrame_OnLoad(self)
HybridScrollFrame_OnLoad(self);
self.update = QuestLog_Update;
HybridScrollFrame_CreateButtons(self, "QuestLogTitleButtonTemplate");
end
--
-- QuestLogFrame
--
function QuestLog_OnLoad(self)
self:RegisterEvent("QUEST_LOG_UPDATE");
self:RegisterEvent("QUEST_ACCEPTED");
self:RegisterEvent("QUEST_WATCH_UPDATE");
self:RegisterEvent("UPDATE_FACTION");
self:RegisterEvent("UNIT_QUEST_LOG_CHANGED");
self:RegisterEvent("GROUP_ROSTER_UPDATE");
self:RegisterEvent("PARTY_MEMBER_ENABLE");
self:RegisterEvent("PARTY_MEMBER_DISABLE");
self:RegisterEvent("DISPLAY_SIZE_CHANGED");
QuestLog_SetSelection(0);
end
function QuestLog_OnEvent(self, event, ...)
local arg1, arg2 = ...;
if ( event == "QUEST_LOG_UPDATE" or event == "UPDATE_FACTION" or (event == "UNIT_QUEST_LOG_CHANGED" and arg1 == "player") ) then
QuestLog_Update();
if ( QuestLogDetailScrollFrame:IsVisible() ) then
QuestLog_UpdateQuestDetails(false);
end
if (not IsTutorialFlagged(55) and TUTORIAL_QUEST_TO_WATCH) then
local isComplete = select(7, GetQuestLogTitle(GetQuestLogIndexByID(TUTORIAL_QUEST_TO_WATCH)));
if (isComplete) then
TriggerTutorial(55);
end
end
elseif ( event == "QUEST_ACCEPTED" ) then
TUTORIAL_QUEST_ACCEPTED = arg2;
QuestPOIUpdateIcons();
if ( AUTO_QUEST_WATCH == "1" and GetNumQuestWatches() < MAX_WATCHABLE_QUESTS ) then
AddQuestWatch(arg1);
QuestLog_Update();
end
elseif ( event == "QUEST_WATCH_UPDATE" ) then
if (not IsTutorialFlagged(11) and TUTORIAL_QUEST_TO_WATCH) then
local questID = select(9, GetQuestLogTitle(arg1));
if (questID == TUTORIAL_QUEST_TO_WATCH) then
TriggerTutorial(11);
end
end
if ( AUTO_QUEST_WATCH == "1" and
GetNumQuestLeaderBoards(arg1) > 0 and
GetNumQuestWatches() < MAX_WATCHABLE_QUESTS ) then
AddQuestWatch(arg1,MAX_QUEST_WATCH_TIME);
QuestLog_Update();
end
elseif ( event == "GROUP_ROSTER_UPDATE" or event == "PARTY_MEMBER_ENABLE" or event == "PARTY_MEMBER_DISABLE" ) then
QuestLog_Update();
if ( event == "GROUP_ROSTER_UPDATE" ) then
QuestLogControlPanel_UpdateState();
end
elseif ( event == "DISPLAY_SIZE_CHANGED" and self:IsShown() ) then
for _, questTitleButton in pairs(QuestLogScrollFrame.buttons) do
QuestLogTitleButton_Resize(questTitleButton);
end
end
end
function QuestLog_OnShow(self)
if ( QuestLogDetailFrame:IsShown() ) then
HideUIPanel(QuestLogDetailFrame);
end
UpdateMicroButtons();
PlaySound("igQuestLogOpen");
QuestLogControlPanel_UpdatePosition();
QuestLogShowMapPOI_UpdatePosition();
QuestLog_SetSelection(GetQuestLogSelection());
QuestLog_Update();
QuestLogDetailFrame_AttachToQuestLog();
if (TutorialFrame.id == 1 or TutorialFrame.id == 55 or TutorialFrame.id == 57) then
TutorialFrame_Hide();
end
end
function QuestLog_OnHide(self)
UpdateMicroButtons();
PlaySound("igQuestLogClose");
QuestLogShowMapPOI_UpdatePosition();
QuestLogControlPanel_UpdatePosition();
QuestLogDetailFrame_DetachFromQuestLog();
if (TUTORIAL_QUEST_ACCEPTED) then
if (not IsTutorialFlagged(2)) then
local _, raceName = UnitRace("player");
if ( strupper(raceName) ~= "PANDAREN" ) then
TriggerTutorial(2);
end
end
if (not IsTutorialFlagged(10) and (TUTORIAL_QUEST_ACCEPTED == TUTORIAL_QUEST_TO_WATCH)) then
TriggerTutorial(10);
end
TUTORIAL_QUEST_ACCEPTED = nil
end
end
function QuestLog_OnUpdate(self, elapsed)
if ( self.groupUpdateTimer ) then
-- this updates the quest log periodically so we can accurately update the number of group members sharing
-- quests with the player
self.groupUpdateTimer = self.groupUpdateTimer + elapsed;
if ( self.groupUpdateTimer > GROUP_UPDATE_INTERVAL_SEC ) then
QuestLog_Update();
self.groupUpdateTimer = 0;
end
end
end
function QuestLog_UpdateMapButton()
if ( WatchFrame.showObjectives and GetNumQuestLogEntries() ~= 0 ) then
QuestLogFrameShowMapButton:Show();
else
QuestLogFrameShowMapButton:Hide();
end
end
function QuestLog_Update()
if ( not QuestLogFrame:IsShown() ) then
return;
end
local numEntries, numQuests = GetNumQuestLogEntries();
if ( numEntries == 0 ) then
HideUIPanel(QuestLogDetailFrame);
QuestLogDetailFrame.timeLeft = nil;
EmptyQuestLogFrame:Show();
QuestLog_SetSelection(0);
else
EmptyQuestLogFrame:Hide();
end
QuestLog_UpdateMapButton();
-- Update Quest Count
QuestLog_UpdateQuestCount(numQuests);
-- If no selection then set it to the first available quest
local questLogSelection = GetQuestLogSelection();
local haveSelection = questLogSelection ~= 0;
if ( numQuests > 0 and not haveSelection ) then
if ( QuestLogFrame.selectedIndex ) then
QuestLog_SetNearestValidSelection();
else
QuestLog_SetFirstValidSelection();
end
questLogSelection = GetQuestLogSelection();
end
QuestLogFrame.selectedIndex = questLogSelection;
--The counts may have changed with SetNearestValidSelection expanding quest headers.
--Bug ID 170644
numEntries, numQuests = GetNumQuestLogEntries();
-- hide the details if we don't have a selected quest
if ( not haveSelection ) then
HideUIPanel(QuestLogDetailFrame);
end
-- update the group timer
local haveGroup = IsInGroup();
if ( haveGroup ) then
QuestLogFrame.groupUpdateTimer = 0;
else
QuestLogFrame.groupUpdateTimer = nil;
end
-- hide the highlight frame initially, it may be shown when we loop through the quest listing if a quest is selected
QuestLogHighlightFrame:Hide();
-- Update the quest listing
local buttons = QuestLogScrollFrame.buttons;
local numButtons = #buttons;
local scrollOffset = HybridScrollFrame_GetOffset(QuestLogScrollFrame);
local buttonHeight = buttons[1]:GetHeight();
local displayedHeight = 0;
local numPartyMembers = GetNumSubgroupMembers();
local questIndex, questLogTitle, questTitleTag, questNumGroupMates, questNormalText, questCheck;
local title, level, questTag, suggestedGroup, isHeader, isCollapsed, isComplete, isDaily, questID, startEvent, displayQuestID;
local color;
local partyMembersOnQuest, tempWidth, textWidth;
for i=1, numButtons do
questLogTitle = buttons[i];
questIndex = i + scrollOffset;
questLogTitle:SetID(questIndex);
questTitleTag = questLogTitle.tag;
questNumGroupMates = questLogTitle.groupMates;
questCheck = questLogTitle.check;
questNormalText = questLogTitle.normalText;
if ( questIndex <= numEntries ) then
title, level, questTag, suggestedGroup, isHeader, isCollapsed, isComplete, isDaily, questID, startEvent, displayQuestID = GetQuestLogTitle(questIndex);
if ( isHeader ) then
-- set the title
if ( title ) then
questLogTitle:SetText(title);
else
questLogTitle:SetText("");
end
-- set the normal texture based on the header's collapsed state
if ( isCollapsed ) then
questLogTitle:SetNormalTexture("Interface\\Buttons\\UI-PlusButton-Up");
else
questLogTitle:SetNormalTexture("Interface\\Buttons\\UI-MinusButton-Up");
end
questLogTitle:SetHighlightTexture("Interface\\Buttons\\UI-PlusButton-Hilight");
questNumGroupMates:Hide();
questTitleTag:Hide();
questCheck:Hide();
questLogTitle.QuestionMark:Hide();
else
-- set the title
if ( ENABLE_COLORBLIND_MODE == "1" ) then
title = "["..level.."] " .. title;
end
if (questID and displayQuestID) then
questLogTitle:SetText(" "..questID.." - "..title);
else
questLogTitle:SetText(" "..title);
end
-- this isn't a header, hide the header textures
questLogTitle:SetNormalTexture("");
questLogTitle:SetHighlightTexture("");
-- If not a header see if any nearby group mates are on this quest
partyMembersOnQuest = 0;
for j=1, numPartyMembers do
if ( IsUnitOnQuest(questIndex, "party"..j) ) then
partyMembersOnQuest = partyMembersOnQuest + 1;
end
end
if ( partyMembersOnQuest > 0 ) then
questNumGroupMates:SetText("["..partyMembersOnQuest.."]");
questNumGroupMates:Show();
else
questNumGroupMates:Hide();
end
-- figure out which tag to show, if any
if ( isComplete and isComplete < 0 ) then
questTag = FAILED;
elseif ( isComplete and isComplete > 0 ) then
questTag = COMPLETE;
elseif ( isDaily ) then
if ( questTag ) then
questTag = format(DAILY_QUEST_TAG_TEMPLATE, questTag);
else
questTag = DAILY;
end
end
if ( questTag ) then
questTitleTag:SetText("("..questTag..")");
questTitleTag:Show();
else
questTitleTag:Hide();
end
-- show the quest check if the quest is being watched
if ( IsQuestWatched(questIndex) ) then
questCheck:Show();
else
questCheck:Hide();
end
-- Show the question mark icon for auto-complete quests
if (isComplete and isComplete>0 and GetQuestLogIsAutoComplete(questIndex)) then
questLogTitle.QuestionMark:Show();
else
questLogTitle.QuestionMark:Hide();
end
end
-- Save if its a header or not
questLogTitle.isHeader = isHeader;
-- resize the title button so everything fits where it's supposed to
QuestLogTitleButton_Resize(questLogTitle);
-- Color the quest title and highlight according to the difficulty level
if ( isHeader ) then
color = QuestDifficultyColors["header"];
else
color = GetQuestDifficultyColor(level);
end
questTitleTag:SetTextColor(color.r, color.g, color.b);
questLogTitle:SetNormalFontObject(color.font);
questNumGroupMates:SetTextColor(color.r, color.g, color.b);
questLogTitle.r = color.r;
questLogTitle.g = color.g;
questLogTitle.b = color.b;
questLogTitle:Show();
-- Place the highlight and lock the highlight state
if ( questLogSelection == questIndex ) then
_QuestLog_HighlightQuest(questLogTitle);
else
questLogTitle:UnlockHighlight();
end
else
questLogTitle:Hide();
end
displayedHeight = displayedHeight + buttonHeight;
end
HybridScrollFrame_Update(QuestLogScrollFrame, numEntries * buttonHeight, displayedHeight);
local selectedIsComplete = select(7, GetQuestLogTitle(questLogSelection));
if (selectedIsComplete and GetQuestLogIsAutoComplete()) then
QuestLogFrameCompleteButton:Show();
else
QuestLogFrameCompleteButton:Hide();
end
-- update the control panel
QuestLogControlPanel_UpdateState();
end
function QuestLog_UpdateQuestCount(numQuests)
if (numQuests > MAX_QUESTLOG_QUESTS) then
QuestLogQuestCount:SetFormattedText(QUEST_LOG_COUNT_TEMPLATE, RED_FONT_COLOR_CODE, numQuests, MAX_QUESTLOG_QUESTS);
else
QuestLogQuestCount:SetFormattedText(QUEST_LOG_COUNT_TEMPLATE, "|cffffffff", numQuests, MAX_QUESTLOG_QUESTS);
end
end
function QuestLog_UpdateQuestDetails(resetScrollBar)
QuestInfo_Display(QUEST_TEMPLATE_LOG, QuestLogDetailScrollChildFrame)
if ( resetScrollBar ) then
QuestLogDetailScrollFrameScrollBar:SetValue(0);
end
QuestLogDetailScrollFrame:Show();
end
function QuestLog_UpdatePartyInfoTooltip(questLogTitle)
local numPartyMembers = GetNumSubgroupMembers();
if ( numPartyMembers == 0 or questLogTitle.isHeader ) then
return;
end
GameTooltip_SetDefaultAnchor(GameTooltip, questLogTitle);
local questIndex = questLogTitle:GetID();
local title = GetQuestLogTitle(questIndex);
GameTooltip:SetText(title);
local partyMemberOnQuest = false;
for i=1, numPartyMembers do
if ( IsUnitOnQuest(questIndex, "party"..i) ) then
if ( not partyMemberOnQuest ) then
GameTooltip:AddLine(HIGHLIGHT_FONT_COLOR_CODE..PARTY_QUEST_STATUS_ON..FONT_COLOR_CODE_CLOSE);
partyMemberOnQuest = true;
end
GameTooltip:AddLine(LIGHTYELLOW_FONT_COLOR_CODE..UnitName("party"..i)..FONT_COLOR_CODE_CLOSE);
end
end
if ( not partyMemberOnQuest ) then
--GameTooltip:AddLine(HIGHLIGHT_FONT_COLOR_CODE..PARTY_QUEST_STATUS_NONE..FONT_COLOR_CODE_CLOSE);
GameTooltip:Hide();
else
GameTooltip:Show();
end
end
function QuestLog_UpdatePortrait()
local questPortrait, questPortraitText, questPortraitName = GetQuestLogPortraitGiver();
if (questPortrait and questPortrait ~= 0 and QuestLogShouldShowPortrait()) then
if (QuestLogDetailFrame.attached) then
QuestFrame_ShowQuestPortrait(QuestLogFrame, questPortrait, questPortraitText, questPortraitName, -5, -42);
else
QuestFrame_ShowQuestPortrait(QuestLogDetailFrame, questPortrait, questPortraitText, questPortraitName, -3, -42);
end
else
QuestFrame_HideQuestPortrait();
end
end
function QuestLog_SetSelection(questIndex)
SelectQuestLogEntry(questIndex);
StaticPopup_Hide("ABANDON_QUEST");
StaticPopup_Hide("ABANDON_QUEST_WITH_ITEMS");
SetAbandonQuest();
QuestLogControlPanel_UpdateState();
if ( questIndex == 0 ) then
QuestLogFrame.selectedIndex = nil;
HideUIPanel(QuestLogDetailFrame);
QuestLogDetailScrollChildFrame:Hide();
QuestLogFrameCompleteButton:Hide();
QuestFrame_HideQuestPortrait();
return;
else
QuestLogDetailScrollChildFrame:Show();
end
local title, level, questTag, suggestedGroup, isHeader, isCollapsed, isComplete, isDaily, questID = GetQuestLogTitle(questIndex);
if ( isHeader ) then
if ( isCollapsed ) then
ExpandQuestHeader(questIndex);
else
CollapseQuestHeader(questIndex);
end
return;
end
if ( CanAbandonQuest(questID) ) then
QuestLogFrameAbandonButton:Enable();
else
QuestLogFrameAbandonButton:Disable();
end
if (isComplete and GetQuestLogIsAutoComplete(questIndex)) then
QuestLogFrameCompleteButton:Show();
else
QuestLogFrameCompleteButton:Hide();
end
QuestLog_UpdatePortrait();
QuestLogFrame.selectedIndex = questIndex;
local scrollBarOffset = _QuestLog_GetQuestScrollOffset(questIndex);
if ( scrollBarOffset ~= 0 ) then
-- adjust the scroll bar to show the quest, if necessary
-- NOTE: this must be done BEFORE you highlight the quest (otherwise, the button you need to highlight may not be visible)
QuestLogScrollFrameScrollBar:SetValue(QuestLogScrollFrameScrollBar:GetValue() - scrollBarOffset);
end
-- find and highlight the selected quest
local buttons = QuestLogScrollFrame.buttons;
local numButtons = #buttons;
local min = 1;
local max = #buttons;
local mid;
local titleButton, id;
while ( min <= max ) do
mid = bit.rshift(min + max, 1);
titleButton = buttons[mid];
id = titleButton:GetID();
if ( id == questIndex ) then
_QuestLog_HighlightQuest(titleButton);
break;
end
if ( id > questIndex ) then
max = mid - 1;
else
min = mid + 1;
end
end
-- update the quest
QuestLog_UpdateQuestDetails(true);
if ( not QuestLogFrame:IsShown() ) then
ShowUIPanel(QuestLogDetailFrame);
end
end
function QuestLog_UnsetSelection()
QuestLog_SetSelection(0);
QuestLog_Update();
end
function QuestLog_GetFirstSelectableQuest()
local numEntries = GetNumQuestLogEntries();
local title, level, questTag, suggestedGroup, isHeader, isCollapsed;
for i=1, numEntries do
title, level, questTag, suggestedGroup, isHeader, isCollapsed = GetQuestLogTitle(i);
if ( title and not isHeader ) then
return i;
end
end
return 0;
end
function QuestLog_SetFirstValidSelection()
local selectableQuest = QuestLog_GetFirstSelectableQuest();
QuestLog_SetSelection(selectableQuest);
QuestLogDetailScrollFrameScrollBar:SetValue(0);
end
-- this function assumes that QuestLogFrame.selectedIndex points to an invalid quest
-- the most likely cause of this case is that the selected quest was abandoned
function QuestLog_SetNearestValidSelection()
local numEntries = GetNumQuestLogEntries();
if ( numEntries == 0 ) then
QuestLog_SetSelection(0);
return;
end
local questIndex = QuestLogFrame.selectedIndex;
if ( questIndex > numEntries ) then
-- if the index is now past the end of the list, treat it as if it were at the end of the list
questIndex = numEntries;
end
local title, level, questTag, suggestedGroup, isHeader, isCollapsed;
-- 1. try to select the quest that is currently under the selected index
title, level, questTag, suggestedGroup, isHeader, isCollapsed = GetQuestLogTitle(questIndex);
if ( title and not isHeader ) then
QuestLog_SetSelection(questIndex);
QuestLogDetailScrollFrameScrollBar:SetValue(0);
return;
end
-- 2. try to select the previous quest
title, level, questTag, suggestedGroup, isHeader, isCollapsed = GetQuestLogTitle(questIndex - 1);
if ( title ) then
if ( not isHeader ) then
-- the previous quest is not a header, select it
QuestLog_SetSelection(questIndex - 1);
QuestLogDetailScrollFrameScrollBar:SetValue(0);
return;
else
-- the previous quest is a header
-- at this point, we will just expand the header if it is collapsed, then we will select the first quest under the header
if ( isCollapsed ) then
ExpandQuestHeader(questIndex - 1);
end
QuestLog_SetSelection(questIndex);
QuestLogDetailScrollFrameScrollBar:SetValue(0);
return;
end
end
-- 3, Found nothing, so deselect
QuestLog_SetSelection(0);
end
function QuestLog_OpenToQuest(questIndex, keepOpen)
local selectedIndex = GetQuestLogSelection();
--[[
if ( selectedIndex ~= 0 and questIndex == selectedIndex and QuestLogFrame:IsShown() and
_QuestLog_GetQuestScrollOffset(questIndex) == 0 ) then
-- if the current quest is selected and is visible, then treat this as a toggle
HideUIPanel(QuestLogFrame);
return;
end
local numEntries, numQuests = GetNumQuestLogEntries();
if ( questIndex < 1 or questIndex > numEntries ) then
return;
end
ExpandQuestHeader(0);
ShowUIPanel(QuestLogFrame);
QuestLog_SetSelection(questIndex);
--]]
if ( not keepOpen and selectedIndex ~= 0 and questIndex == selectedIndex and QuestLogDetailFrame:IsShown() ) then
-- if the current quest is selected and is visible, then treat this as a toggle
HideUIPanel(QuestLogDetailFrame);
return;
end
local numEntries, numQuests = GetNumQuestLogEntries();
if ( questIndex < 1 or questIndex > numEntries ) then
return;
end
HideUIPanel(QuestFrame);
QuestLog_SetSelection(questIndex);
end
--
-- QuestLogFrameTrackButton
--
function QuestLogFrameTrackButton_OnClick(self)
PlaySound("igMainMenuOptionCheckBoxOn");
_QuestLog_ToggleQuestWatch(GetQuestLogSelection());
QuestLog_Update();
end
--
-- QuestLogDetailFrame
--
function QuestLogDetailFrame_OnShow(self)
PlaySound("igQuestLogOpen");
QuestLogControlPanel_UpdatePosition();
QuestLogShowMapPOI_UpdatePosition();
QuestLog_UpdateQuestDetails();
end
function QuestLogDetailFrame_OnHide(self)
-- this function effectively deselects the selected quest
PlaySound("igQuestLogClose");
QuestLogControlPanel_UpdatePosition();
QuestLogShowMapPOI_UpdatePosition();
end
function QuestLogDetailFrame_AttachToQuestLog()
QuestLogDetailFrame.attached = true;
if (QuestNPCModel:GetParent() == QuestLogDetailFrame) then
QuestNPCModel:SetParent(QuestLogFrame);
QuestNPCModel:ClearAllPoints();
QuestNPCModel:SetPoint("TOPLEFT", QuestLogFrame, "TOPRIGHT", -3, -34);
end
QuestLogDetailScrollFrame:SetParent(QuestLogFrame);
QuestLogDetailScrollFrame:ClearAllPoints();
QuestLogDetailScrollFrame:SetPoint("TOPRIGHT", QuestLogFrame, "TOPRIGHT", -33, -65);
QuestLogDetailScrollFrameScrollBar:SetPoint("TOPLEFT", QuestLogDetailScrollFrame, "TOPRIGHT", 6, -13);
QuestLog_UpdatePortrait();
end
function QuestLogDetailFrame_DetachFromQuestLog()
QuestLogDetailFrame.attached = false;
if (QuestNPCModel:GetParent() == QuestLogFrame) then
QuestNPCModel:SetParent(QuestLogDetailFrame);
QuestNPCModel:ClearAllPoints();
QuestNPCModel:SetPoint("TOPLEFT", QuestLogDetailFrame, "TOPRIGHT", -1, -34);
end
QuestLogDetailScrollFrame:SetParent(QuestLogDetailFrame);
QuestLogDetailScrollFrame:ClearAllPoints();
QuestLogDetailScrollFrame:SetPoint("TOPLEFT", QuestLogDetailFrame, "TOPLEFT", 8, -65);
QuestLogDetailScrollFrameScrollBar:SetPoint("TOPLEFT", QuestLogDetailScrollFrame, "TOPRIGHT", 6, -14);
QuestLog_UpdatePortrait();
end
function QuestLogDetailFrame_OnLoad(self)
QuestLogDetailFrame_DetachFromQuestLog();
end
--
-- QuestLogControlPanel
--
function QuestLogControlPanel_UpdatePosition()
local parent;
if ( QuestLogFrame:IsShown() ) then
parent = QuestLogFrame;
QuestLogControlPanel:SetPoint("BOTTOMLEFT", parent, "BOTTOMLEFT", 4, 1);
QuestLogControlPanel:SetWidth(307);
elseif ( QuestLogDetailFrame:IsShown() ) then
parent = QuestLogDetailFrame;
QuestLogControlPanel:SetPoint("BOTTOMLEFT", parent, "BOTTOMLEFT", 4, 1);
QuestLogControlPanel:SetWidth(327);
end
if ( parent ) then
QuestLogControlPanel:SetParent(parent);
QuestLogControlPanel:Show();
else
QuestLogControlPanel:Hide();
end
end
function QuestLogControlPanel_UpdateState()
local questLogSelection = GetQuestLogSelection();
if ( questLogSelection == 0 ) then
QuestLogFrameAbandonButton:Disable();
QuestLogFrameTrackButton:Disable();
QuestLogFramePushQuestButton:Disable();
else
local _, _, _, _, _, _, _, _, questID = GetQuestLogTitle(questLogSelection);
if ( GetAbandonQuestName() and CanAbandonQuest(questID)) then
QuestLogFrameAbandonButton:Enable();
else
QuestLogFrameAbandonButton:Disable();
end
QuestLogFrameTrackButton:Enable();
if ( GetQuestLogPushable() and IsInGroup() ) then
QuestLogFramePushQuestButton:Enable();
else
QuestLogFramePushQuestButton:Disable();
end
end
end
function QuestLogShowMapPOI_UpdatePosition()
local parent;
if ( QuestLogFrame:IsShown() ) then
parent = QuestLogFrame;
elseif ( QuestLogDetailFrame:IsShown() ) then
parent = QuestLogDetailFrame;
end
if ( parent ) then
QuestLogFrameShowMapButton:SetParent(parent);
QuestLogFrameShowMapButton:SetPoint("TOPRIGHT", -24, -25);
end
end