Nenue@28: local B = select(2,...).frame Nenue@28: local T = B:RegisterModule("ObjectiveTracker", _G.VeneerObjectiveWrapper, 'BuffFrame') Nenue@28: local _G, ipairs, max, min, unpack, floor, pairs, tostring, type, band = _G, ipairs, max, min, unpack, floor, pairs, tostring, type, bit.band Nenue@30: local GetQuestWatchInfo, GetQuestLogCompletionText = GetQuestWatchInfo, GetQuestLogCompletionText Nenue@30: local GetQuestLogLeaderBoard, GetNumQuestLogEntries, GetQuestLogTitle = GetQuestLogLeaderBoard, GetNumQuestLogEntries, GetQuestLogTitle Nenue@30: local GetQuestLogSpecialItemInfo, GetQuestLogSpecialItemCooldown = GetQuestLogSpecialItemInfo, GetQuestLogSpecialItemCooldown Nenue@30: local GetSuperTrackedQuestID, GetMoney, C_Scenario, GetCVarBool, GetNumQuestWatches = GetSuperTrackedQuestID, GetMoney, C_Scenario, GetCVarBool, GetNumQuestWatches Nenue@30: local GetQuestTagInfo, GetMoneyString, GetDistanceSqToQuest, GetQuestFactionGroup = GetQuestTagInfo, GetMoneyString, GetDistanceSqToQuest, GetQuestFactionGroup Nenue@30: local QUEST_TAG_ACCOUNT, LE_QUEST_FACTION_HORDE, LE_QUEST_FREQUENCY_DAILY, LE_QUEST_FREQUENCY_WEEKLY = QUEST_TAG_ACCOUNT, LE_QUEST_FACTION_HORDE, LE_QUEST_FREQUENCY_DAILY, LE_QUEST_FREQUENCY_WEEKLY Nenue@30: local QUEST_TAG_TCOORDS, IsQuestSequenced = QUEST_TAG_TCOORDS, IsQuestSequenced Nenue@28: local Default, Quest = T.DefaultHandler, T.Quest Nenue@37: local format, wipe, select = format, table.wipe, select Nenue@37: local wipeall = B.wipeall Nenue@37: local lprint, iprint, tprint = B.print('Line'), B.print('Info'), B.print('Tracker') Nenue@37: local print = tprint Nenue@28: Nenue@30: local superTrackQuestID, playerMoney, inScenario, showPOIs Nenue@28: Quest.Update = function(self, reason, ...) Nenue@28: local print = tprint Nenue@28: print('QuestTracker:Update() received') Nenue@28: T.UpdateActionButtons() Nenue@28: Default.Update(self, reason, ...) Nenue@28: end Nenue@28: Nenue@28: T.Quest.numButtons = 0 Nenue@28: local usedButtons = T.Quest.itemButtons Nenue@28: local freeButtons = T.Quest.freeButtons Nenue@28: Nenue@28: Quest.UpdateObjectives = function(handler, block) Nenue@28: local print = lprint Nenue@28: print('|cFF00FFFFUpdateObjectives()') Nenue@28: local info = block.info Nenue@28: Nenue@28: print((info.isAccount and 'isAccount' or ''), (info.isFaction and 'isFaction' or ''), (info.isDaily and 'isDaily' or ''), (info.isWeekly and 'isWeekly' or ''), info.tagID, info.tagName) Nenue@28: Nenue@34: local block_schema = 'default' Nenue@28: if info.isAccount then Nenue@28: if info.isFaction then Nenue@28: print(' faction', info.tagID) Nenue@34: block_schema = 'faction_'..info.tagID Nenue@28: else Nenue@28: print(' account', info.isAccount, info.isFaction) Nenue@34: block_schema = 'account' Nenue@28: end Nenue@28: elseif info.isDaily then Nenue@28: print(' daily', info.frequency) Nenue@34: block_schema = 'daily' Nenue@28: elseif info.isWeekly then Nenue@28: print(' weekly', info.frequency) Nenue@34: block_schema = 'weekly' Nenue@28: end Nenue@28: local completionText Nenue@28: if info.isComplete then Nenue@28: if info.isAutoComplete then Nenue@34: local questID, popupType = GetAutoQuestPopUp(info.logIndex) Nenue@28: if popupType == 'COMPLETE' then Nenue@28: print(' :: auto-complete quest :: set the message') Nenue@28: info.completionText = T.strings.CLICK_TO_COMPLETE Nenue@28: end Nenue@28: else Nenue@28: if not completionText or info.completionText then Nenue@34: info.completionText = GetQuestLogCompletionText(info.logIndex) Nenue@28: end Nenue@28: end Nenue@28: print(' :: complete quest :: show instruction: "'.. tostring(info.completionText) .. '"') Nenue@28: end Nenue@28: Nenue@34: Default.UpdateObjectives(handler, block, block_schema) Nenue@34: return block_schema Nenue@28: end Nenue@28: Nenue@28: Quest.UpdateLine = function(handler, block, line, data) Nenue@28: local print = lprint Nenue@28: local objectiveType = data.type Nenue@31: return data.text, nil, objectiveType Nenue@28: end Nenue@28: Nenue@28: ----------------------------- Nenue@28: --- QUEST Nenue@37: local tremove, tinsert = tremove, tinsert Nenue@37: local GetQuestLogIndexByID, IsQuestWatched = GetQuestLogIndexByID, IsQuestWatched Nenue@28: Quest.QuestBlock = {} Nenue@28: Quest.LogBlock = {} Nenue@28: Quest.LogInfo = {} Nenue@37: function Quest:FreeBlock (block) Nenue@37: local used = Quest.usedBlocks Nenue@37: local free = Quest.freeBlocks Nenue@37: local reason = '' Nenue@37: local doRelease = false Nenue@37: local info = block.info Nenue@37: local questID = info.questID Nenue@37: local logIndex = info.logIndex Nenue@28: Nenue@37: if info.posIndex then Nenue@37: if used[info.posIndex] == block then Nenue@37: doRelease = true Nenue@37: reason = 'posIndex mismatch' Nenue@37: end Nenue@37: elseif logIndex then Nenue@37: if not IsQuestWatched(logIndex) then Nenue@37: reason = 'not being watched' Nenue@37: elseif not self.LogBlock[logIndex] then Nenue@37: doRelease = true Nenue@37: reason = 'missing logBlock entry' Nenue@37: elseif (self.LogBlock[logIndex] ~= block) then Nenue@37: doRelease = true Nenue@37: reason = 'different block using index' Nenue@37: end Nenue@37: elseif info.questID then Nenue@37: if not GetQuestLogIndexByID(info.questID) then Nenue@37: doRelease = true Nenue@37: reason = 'no identifiable quest log entry' Nenue@37: end Nenue@37: end Nenue@37: Nenue@37: Nenue@37: if doRelease then Nenue@37: print(' |cFF00FF00FreeBlock (' .. block:GetName() .. '):', reason) Nenue@37: block:Hide() Nenue@37: tremove(used, info.posIndex) Nenue@37: tinsert(free, block) Nenue@37: end Nenue@37: Nenue@37: Nenue@37: end Nenue@37: local watchesChecked = {} Nenue@37: local infosChecked = {} Nenue@37: local blocksChecked = {} Nenue@37: local GetQuestWatchIndex = GetQuestWatchIndex Nenue@37: --- Get a total of things to show, and straighten out the index while we're at it Nenue@37: --- Return the number shown, total in log, and the info table to parse Nenue@37: Quest.GetNumWatched = function (self, id, added) Nenue@30: superTrackQuestID = GetSuperTrackedQuestID() Nenue@30: playerMoney = GetMoney(); Nenue@30: inScenario = C_Scenario.IsInScenario(); Nenue@30: showPOIs = GetCVarBool("questPOI"); Nenue@37: local numAll = GetNumQuestLogEntries() Nenue@37: local numWatched = GetNumQuestWatches() Nenue@37: local bottomIndex = 1 Nenue@37: print(' |cFF00FF88GetNumWatched:|r',self.name, numWatched, 'of', numAll) Nenue@37: local start, limit = 1, numAll Nenue@37: Nenue@37: --- start a list of blocks affected by this function Nenue@37: wipe(blocksChecked) Nenue@37: if id and not added then Nenue@37: if self.InfoBlock[id] then Nenue@37: tinsert(blocksChecked, self.InfoBlock[id]) Nenue@37: end Nenue@37: end Nenue@37: Nenue@37: for logIndex = start, limit do Nenue@37: local reason1, reason2 = '', '' Nenue@37: local title, level, suggestedGroup, isHeader, isCollapsed, isComplete, frequency, questID, startEvent, displayQuestID, isOnMap, hasLocalPOI, isTask, isStory = GetQuestLogTitle(logIndex) Nenue@37: local watchIndex = GetQuestWatchIndex(logIndex) Nenue@37: Nenue@37: if watchIndex and watchIndex >= bottomIndex then Nenue@37: local watchInfo = self.WatchInfo[watchIndex] Nenue@37: local watchBlock = self.WatchBlock[watchIndex] Nenue@37: if watchInfo and watchInfo.questID ~= questID then Nenue@37: print(' |cFFBBFF00GetNumWatched: trimming WatchInfo ['..watchIndex..'] =/=', questID) Nenue@37: self.WatchInfo[watchIndex] = nil Nenue@37: end Nenue@37: if watchBlock and watchBlock.info.questID ~= questID then Nenue@37: print(' |cFFBBFF00GetNumWatched: trimming WatchBlock ['..watchIndex..'] =/=', watchBlock:GetName()) Nenue@37: self.WatchBlock[watchIndex] = nil Nenue@37: tinsert(blocksChecked, watchBlock) Nenue@37: end Nenue@37: end Nenue@37: Nenue@37: local logBlock = self.LogBlock[logIndex] Nenue@37: if logBlock and logBlock.info.questID ~= questID then Nenue@37: --print(' |cFFBBFF00GetNumWatched: trimming LogBlock ['..logIndex..'] =/=', logBlock:GetName()) Nenue@37: self.LogBlock[logIndex] = nil Nenue@37: tinsert(blocksChecked, logBlock) Nenue@37: end Nenue@37: Nenue@37: if questID ~= 0 then Nenue@37: self.Info[questID] = self:GetInfo(logIndex, watchIndex) Nenue@37: --print(' |cFF44BBFFGetNumWatched:|r map', questID, 'to', logIndex, (watchIndex and ('('..watchIndex..')') or '')) Nenue@37: end Nenue@37: end Nenue@37: Nenue@37: --- remove any orphaned blocks from view and, if possible, free it for re-use Nenue@37: for i, block in ipairs(blocksChecked) do Nenue@37: if not GetQuestLogIndexByID(block.info.questID, 'player') then Nenue@37: print(' |cFFBBFF00GetNumWatched:|r literating a block without an index |cFFBBFF00'.. block:GetName()..'|r') Nenue@37: block:Hide() Nenue@37: self:FreeBlock(block) Nenue@37: end Nenue@37: if not IsQuestWatched(block.info.logIndex) then Nenue@37: print(' |cFFBBFF00GetNumWatched:|r hiding untracked quest |cFFBBFF00'.. block:GetName()..'|r') Nenue@37: block:Hide() Nenue@37: end Nenue@37: end Nenue@37: Nenue@37: self.numWatched = numWatched Nenue@37: self.numAll = numAll Nenue@37: Nenue@37: return numWatched, numAll, self.WatchList Nenue@28: end Nenue@30: Nenue@37: Nenue@30: --- Returns an iterable table from which tracker blocks can be filled out. Data includes: Nenue@30: -- All entry-layer GetXInfo return values Nenue@30: -- Manifest of line data to be displayed in relation to the tracked object Nenue@37: Quest.GetInfo = function (self, logIndex, watchIndex) Nenue@28: local print = iprint Nenue@37: local title, level, suggestedGroup, isHeader, isCollapsed, isComplete, frequency, questID, startEvent, displayQuestID, isOnMap, hasLocalPOI, isTask, isStory = GetQuestLogTitle(logIndex) Nenue@30: if ( not questID ) then Nenue@37: tprint(' |cFFFF0088GetInfo:|r', logIndex, watchIndex, '|cFFFF2299no data|r') Nenue@28: return Nenue@28: end Nenue@28: Nenue@37: Quest.Info[questID] = Quest.Info[questID] or {} Nenue@37: local q = Quest.Info[questID] Nenue@37: q.questID = questID Nenue@37: q.id = questID Nenue@37: q.logIndex = logIndex Nenue@37: q.watchIndex = watchIndex Nenue@28: Nenue@37: local numObjectives, requiredMoney, isAutoComplete, failureTime, timeElapsed, questType Nenue@37: = 0, 0, nil, false, false, 0 Nenue@37: if watchIndex then Nenue@37: local _ Nenue@37: _,_,_, numObjectives, requiredMoney, _, _, isAutoComplete, Nenue@37: failureTime, timeElapsed, questType = GetQuestWatchInfo(watchIndex) Nenue@37: self.WatchList[watchIndex] = q Nenue@37: --tprint(' |cFF88FF00GetInfo:|r set watch entry', watchIndex) Nenue@37: tprint(' |cFFFFBB00GetInfo:|r', logIndex, watchIndex, '|cFFFF2299'..title..'|r') Nenue@37: end Nenue@37: self.LogInfo[logIndex] = q Nenue@28: Nenue@37: q.numObjectives = numObjectives Nenue@37: q.requiredMoney = requiredMoney Nenue@37: q.failureTime = failureTime Nenue@37: q.timeElapsed = timeElapsed Nenue@30: Nenue@37: Nenue@37: Nenue@32: q.type = 'Quest' Nenue@32: q.title = title Nenue@32: q.level = level Nenue@32: q.displayQuestID = displayQuestID Nenue@32: q.suggestedGroup = suggestedGroup Nenue@32: Nenue@30: -- re-use Blizzard logic for consistency Nenue@32: local showQuest = true Nenue@32: if isTask then showQuest = false end Nenue@30: local watchMoney = false; Nenue@30: local tagID, typeTag, frequencyTag, completionTag, completionText Nenue@30: local isAccount, isFaction, isWeekly, isDaily = false, false, false, false Nenue@30: local isBreadcrumb = false Nenue@30: local questFailed = false Nenue@30: local watchMoney = false Nenue@30: local timerInfo, moneyInfo = false, false Nenue@30: local objectives = q.objectives or {} Nenue@30: Nenue@30: Nenue@30: -- Case 1: completed quest or "go to thing" breadcrumb Nenue@30: -- * 1 line containing the completion text Nenue@30: if ( isComplete and isComplete < 0 ) then Nenue@30: isComplete = false Nenue@30: questFailed = true Nenue@30: elseif ( numObjectives == 0 and playerMoney >= requiredMoney and not startEvent ) then Nenue@30: isComplete = true; Nenue@30: questFailed = false Nenue@30: if ( requiredMoney == 0 ) then Nenue@30: isBreadcrumb = true; Nenue@30: end Nenue@30: end Nenue@30: print('|cFF0088FFflags:|r', (isComplete and 'isComplete' or ''), (questFailed and 'questFailed' or ''), (isBreadcrumb and 'isBreadcrumb' or '')) Nenue@30: Nenue@30: -- completion message? Nenue@30: local isSequenced = IsQuestSequenced(questID) Nenue@30: local temp_status = '' Nenue@30: if ( isComplete ) then Nenue@30: temp_status = 'COMPLETED_OBJECTIVES' Nenue@30: objectives = Quest.GetObjectives(questLogIndex, numObjectives, true, isSequenced, isStory) Nenue@30: if ( isAutoComplete ) then Nenue@30: temp_status = 'AUTOCOMPLETE_OBJECTIVES' Nenue@30: completionText = _G.QUEST_WATCH_CLICK_TO_COMPLETE Nenue@30: else Nenue@30: if ( isBreadcrumb ) then Nenue@30: temp_status = 'COMPLETE_BREADCRUMB' Nenue@30: completionText = GetQuestLogCompletionText(questLogIndex) Nenue@30: else Nenue@30: temp_status = 'COMPLETE_READY_FOR_TURN_IN' Nenue@30: completionText = _G.QUEST_WATCH_QUEST_READY Nenue@30: end Nenue@30: end Nenue@30: elseif ( questFailed ) then Nenue@30: temp_status = 'FAILED' Nenue@30: -- Case 2: failed quest Nenue@30: -- * 1 status line; hide other info Nenue@30: completionText = _G.FAILED Nenue@30: else Nenue@30: Nenue@30: temp_status = 'PROGRESS_OBJECTIVES' Nenue@30: -- Case 3: quest in progress Nenue@30: -- * Multiple objective lines Nenue@30: -- * Possible extra lines for money and timer data respectively Nenue@37: objectives = Quest.GetObjectives(logIndex, numObjectives, false, isSequenced, isStory) Nenue@30: q.objectives = objectives Nenue@30: Nenue@30: --- anything past here gets appended to existing objectives Nenue@30: Nenue@30: -- money Nenue@30: if ( requiredMoney > playerMoney ) then Nenue@30: Nenue@30: temp_status = temp_status .. '_MONEY' Nenue@30: local text = GetMoneyString(playerMoney).." / "..GetMoneyString(requiredMoney); Nenue@30: moneyInfo = { Nenue@30: type = 'money', Nenue@30: text = text, Nenue@30: finished = false, Nenue@30: requiredMoney = requiredMoney, Nenue@30: playerMoney = playerMoney, Nenue@30: } Nenue@31: tinsert(objectives, moneyInfo) Nenue@30: end Nenue@30: Nenue@30: -- time limit Nenue@30: if ( failureTime ) then Nenue@30: temp_status = temp_status .. '_TIMED' Nenue@30: if ( timeElapsed and timeElapsed <= failureTime ) then Nenue@30: timerInfo = { Nenue@30: type = 'timer', Nenue@30: finished = false, Nenue@30: timeElapsed = timeElapsed, Nenue@30: failureTime = failureTime, Nenue@30: } Nenue@31: tinsert(objectives, timerInfo) Nenue@30: end Nenue@30: end Nenue@30: end Nenue@30: q.objectives = objectives Nenue@30: q.moneyInfo = moneyInfo Nenue@30: q.timerInfo = timerInfo Nenue@30: q.completionText = completionText Nenue@30: Nenue@30: -- POI data Nenue@30: local POI = false Nenue@30: if ( showPOIs ) then Nenue@30: POI = { Nenue@30: questID = questID, Nenue@37: logIndex = logIndex, Nenue@37: watchIndex = watchIndex Nenue@30: } Nenue@30: local poiButton; Nenue@30: if ( hasLocalPOI ) then Nenue@30: Nenue@30: if ( isComplete ) then Nenue@30: POI.type = 'normal' Nenue@30: else Nenue@30: POI.type = 'numeric' Nenue@30: end Nenue@30: elseif ( isComplete ) then Nenue@30: POI.type = 'remote' Nenue@30: end Nenue@30: Nenue@37: local distance, onContinent = GetDistanceSqToQuest(logIndex) Nenue@30: if distance ~= nil and distance > 0 then Nenue@30: POI.distance = distance Nenue@30: POI.onContinent = onContinent Nenue@30: end Nenue@30: end Nenue@30: q.POI = POI Nenue@30: Nenue@30: --- Block Tags Nenue@30: -- completionTag - in progres, complete, failed, autocomplete Nenue@30: -- typeTag - account, faction, pvp, dungeon, group Nenue@30: -- frequencyTag - daily/weekly Nenue@37: local schema = 'default' Nenue@30: local questTagID, tagName = GetQuestTagInfo(questID) Nenue@30: local tagInfo = {} Nenue@30: local tagCoords = {} Nenue@30: local factionGroup = GetQuestFactionGroup(questID); Nenue@30: if( questTagID and questTagID == QUEST_TAG_ACCOUNT ) then Nenue@30: if( factionGroup ) then Nenue@30: tagID = "ALLIANCE" Nenue@37: schema = 'alliance' Nenue@30: if ( factionGroup == LE_QUEST_FACTION_HORDE ) then Nenue@30: tagID = "HORDE" Nenue@37: schema = 'horde' Nenue@30: end Nenue@30: isFaction = true Nenue@30: else Nenue@30: tagID = QUEST_TAG_ACCOUNT Nenue@30: isAccount = true Nenue@30: end Nenue@30: tagInfo['typeTag'] = tagID Nenue@30: tagCoords['typeTag'] = QUEST_TAG_TCOORDS[tagID] Nenue@30: elseif ( factionGroup) then Nenue@30: tagID = "ALLIANCE" Nenue@30: if ( factionGroup == LE_QUEST_FACTION_HORDE ) then Nenue@30: tagID = "HORDE" Nenue@30: end Nenue@30: isFaction = true Nenue@30: tagInfo['typeTag'] = tagID Nenue@30: tagCoords['typeTag'] = QUEST_TAG_TCOORDS[tagID] Nenue@30: end Nenue@30: Nenue@30: if( frequency == LE_QUEST_FREQUENCY_DAILY and (not isComplete or isComplete == 0) ) then Nenue@30: tagID = 'DAILY' Nenue@30: tagInfo['frequencyTag'] = tagID Nenue@30: tagCoords['frequencyTag'] = QUEST_TAG_TCOORDS[tagID] Nenue@30: isDaily = true Nenue@37: schema = 'daily' Nenue@30: elseif( frequency == LE_QUEST_FREQUENCY_WEEKLY and (not isComplete or isComplete == 0) )then Nenue@30: tagID = 'WEEKLY' Nenue@30: tagInfo['frequencyTag'] = tagID Nenue@30: tagCoords['frequencyTag'] = QUEST_TAG_TCOORDS[tagID] Nenue@30: isWeekly = true Nenue@37: schema = 'weekly' Nenue@30: elseif( questTagID ) then Nenue@30: tagID = questTagID Nenue@30: end Nenue@30: Nenue@30: if( isComplete ) then Nenue@30: tagInfo['completionTag'] = 'COMPLETED' Nenue@30: elseif ( questFailed ) then Nenue@30: tagInfo['completionTag'] = 'FAILED' Nenue@30: end Nenue@30: tagCoords['completionTag'] = QUEST_TAG_TCOORDS[tagInfo['completionTag']] Nenue@30: Nenue@30: q.tagInfo = tagInfo Nenue@30: q.tagCoords = tagCoords Nenue@30: -- establishes the primary block tag for view compacting Nenue@30: q.tagID = tagID Nenue@30: q.tagName = tagName Nenue@30: Nenue@30: -- action button information Nenue@37: local link, icon, charges = GetQuestLogSpecialItemInfo(logIndex) Nenue@37: local start, duration, enable = GetQuestLogSpecialItemCooldown(logIndex) Nenue@30: if link or icon or charges then Nenue@30: q.specialItem = { Nenue@30: questID = questID, Nenue@37: logIndex = questLogIndex, Nenue@30: link = link, Nenue@30: charges = charges, Nenue@30: icon = icon, Nenue@30: start = start, Nenue@30: duration = duration, Nenue@30: enable = enable, Nenue@30: } Nenue@30: end Nenue@30: Nenue@32: if moneyInfo or timerInfo then Nenue@32: numObjectives = #objectives Nenue@32: end Nenue@30: Nenue@30: -- raw data Nenue@28: q.isComplete = isComplete Nenue@28: q.startEvent = startEvent Nenue@28: q.isAutoComplete = isAutoComplete Nenue@28: q.questType = questType Nenue@28: q.isTask = isTask Nenue@28: q.isStory = isStory Nenue@28: q.isOnMap = isOnMap Nenue@28: q.hasLocalPOI = hasLocalPOI Nenue@28: q.frequency = frequency Nenue@28: q.isComplete = isComplete Nenue@28: q.isStory = isStory Nenue@28: q.isTask = isTask Nenue@31: q.statusKey = temp_status Nenue@32: q.selected = (questID == superTrackQuestID) Nenue@28: Nenue@32: T.SetRewards(q, questID) Nenue@32: Nenue@34: q.questID = questID Nenue@37: q.logIndex = logIndex Nenue@34: q.watchIndex = watchIndex Nenue@34: q.id = questID Nenue@37: q.schema = schema Nenue@28: Nenue@30: if Devian and Devian.InWorkspace() then Nenue@37: print('|cFF00DDFFstatus:|r', temp_status, '|cFF00FF00questLogIndex|r:', logIndex, title) Nenue@30: local temp ={} Nenue@30: local data_txt = '|cFFFF4400values:|r' Nenue@30: for k,v in pairs(q) do Nenue@30: if type(v) =='number' then Nenue@30: data_txt = data_txt .. ' |cFFFFFF00'..k..'|r: ' .. tostring(v) Nenue@30: elseif type(v) == 'table' then Nenue@30: tinsert(temp, k) Nenue@28: end Nenue@28: end Nenue@30: print(data_txt) Nenue@30: sort(temp, function(a,b) return a < b end) Nenue@30: for i, k in ipairs(temp) do Nenue@30: print('|cFF00FF00'..k..'|r') Nenue@30: for kk,v in pairs(q[k]) do Nenue@30: print(' ', kk, '=', v) Nenue@30: end Nenue@28: end Nenue@28: end Nenue@28: Nenue@30: return q Nenue@30: end Nenue@28: Nenue@37: Quest.GetObjectives = function(logIndex, numObjectives, isComplete, isSequenced, isStory) Nenue@30: local objectives = {} Nenue@30: for i = 1, numObjectives do Nenue@37: local text, type, finished = GetQuestLogLeaderBoard(i, logIndex) Nenue@34: print(format(' |cFFFF4400GetObjectives:|r #%d %s %s %s', i, tostring(type), tostring(text), tostring(finished))) Nenue@30: objectives[i] = { Nenue@28: index = i, Nenue@28: type = type, Nenue@28: text = text, Nenue@28: finished = finished Nenue@28: } Nenue@28: end Nenue@30: return objectives Nenue@28: end Nenue@28: Nenue@30: local huge, sqrt = math.huge, math.sqrt Nenue@28: Quest.GetClosest = function() Nenue@28: local minID, minTitle Nenue@30: local minDist = huge Nenue@28: local numQuests = GetNumQuestLogEntries() Nenue@28: for questIndex = 1, numQuests do Nenue@28: local distance, onContinent = GetDistanceSqToQuest(questIndex) Nenue@28: local title, level, _, _, _, _, _, _, questID = GetQuestLogTitle(questIndex) Nenue@28: if onContinent and distance < minDist then Nenue@28: minDist = distance Nenue@28: minTitle = title Nenue@28: minID = questID Nenue@28: end Nenue@28: end Nenue@28: Nenue@30: print('nearest quest is', minTitle, 'by', sqrt(minDist)) Nenue@28: return minID, minTitle, minDist Nenue@28: end Nenue@28: Nenue@28: Quest.OnTurnIn = function(self, questID, xp, money) Nenue@28: end Nenue@28: Nenue@29: Quest.Select = function (handler, block) Nenue@29: if block.info.isAutoComplete and block.info.isComplete then Nenue@34: ShowQuestComplete(block.info.logIndex) Nenue@28: else Nenue@29: SetSuperTrackedQuestID(block.info.questID) Nenue@28: end Nenue@28: end Nenue@28: Nenue@29: Quest.Link = function(handler, block) Nenue@34: local questLink = GetQuestLink(block.info.logIndex); Nenue@28: if ( questLink ) then Nenue@28: ChatEdit_InsertLink(questLink); Nenue@28: end Nenue@28: end Nenue@28: Nenue@29: Quest.Open = function(handler, block) Nenue@29: QuestMapFrame_OpenToQuestDetails(block.info.questID) Nenue@28: end Nenue@28: Nenue@29: Quest.Remove = function(handler, block) Nenue@34: print('removing', block.info.logIndex, 'from watcher') Nenue@34: RemoveQuestWatch(block.info.logIndex) Nenue@29: end