Mercurial > wow > buffalo2
view ObjectiveTracker/Quests.lua @ 34:9856ebc63fa4
- half solution to Update being fired multiple times during load
- change securefunc handlers to dispense a reason code; catch that reason code in the enclosure passed to hooksecurefunc, and decide whether to update or not from there.
author | Nenue |
---|---|
date | Sun, 17 Apr 2016 00:21:45 -0400 |
parents | a3afe6c3771e |
children | 69d03f8e293e |
line wrap: on
line source
local B = select(2,...).frame local T = B:RegisterModule("ObjectiveTracker", _G.VeneerObjectiveWrapper, 'BuffFrame') local _G, ipairs, max, min, unpack, floor, pairs, tostring, type, band = _G, ipairs, max, min, unpack, floor, pairs, tostring, type, bit.band local GetQuestWatchInfo, GetQuestLogCompletionText = GetQuestWatchInfo, GetQuestLogCompletionText local GetQuestLogLeaderBoard, GetNumQuestLogEntries, GetQuestLogTitle = GetQuestLogLeaderBoard, GetNumQuestLogEntries, GetQuestLogTitle local GetQuestLogSpecialItemInfo, GetQuestLogSpecialItemCooldown = GetQuestLogSpecialItemInfo, GetQuestLogSpecialItemCooldown local GetSuperTrackedQuestID, GetMoney, C_Scenario, GetCVarBool, GetNumQuestWatches = GetSuperTrackedQuestID, GetMoney, C_Scenario, GetCVarBool, GetNumQuestWatches local GetQuestTagInfo, GetMoneyString, GetDistanceSqToQuest, GetQuestFactionGroup = GetQuestTagInfo, GetMoneyString, GetDistanceSqToQuest, GetQuestFactionGroup 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 local QUEST_TAG_TCOORDS, IsQuestSequenced = QUEST_TAG_TCOORDS, IsQuestSequenced local Default, Quest = T.DefaultHandler, T.Quest local format = format local print = B.print('Tracker') local lprint = B.print('Line') local iprint = B.print('Info') local colors = T.colors local tprint = B.print('Tracker') local superTrackQuestID, playerMoney, inScenario, showPOIs Quest.Update = function(self, reason, ...) local print = tprint print('QuestTracker:Update() received') T.UpdateActionButtons() Default.Update(self, reason, ...) end T.Quest.numButtons = 0 local usedButtons = T.Quest.itemButtons local freeButtons = T.Quest.freeButtons Quest.UpdateObjectives = function(handler, block) local print = lprint print('|cFF00FFFFUpdateObjectives()') local info = block.info 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) local block_schema = 'default' if info.isAccount then if info.isFaction then print(' faction', info.tagID) block_schema = 'faction_'..info.tagID else print(' account', info.isAccount, info.isFaction) block_schema = 'account' end elseif info.isDaily then print(' daily', info.frequency) block_schema = 'daily' elseif info.isWeekly then print(' weekly', info.frequency) block_schema = 'weekly' end local completionText if info.isComplete then if info.isAutoComplete then local questID, popupType = GetAutoQuestPopUp(info.logIndex) if popupType == 'COMPLETE' then print(' :: auto-complete quest :: set the message') info.completionText = T.strings.CLICK_TO_COMPLETE end else if not completionText or info.completionText then info.completionText = GetQuestLogCompletionText(info.logIndex) end end print(' :: complete quest :: show instruction: "'.. tostring(info.completionText) .. '"') end Default.UpdateObjectives(handler, block, block_schema) return block_schema end Quest.UpdateLine = function(handler, block, line, data) local print = lprint local objectiveType = data.type return data.text, nil, objectiveType end ----------------------------- --- QUEST Quest.QuestBlock = {} Quest.LogBlock = {} Quest.LogInfo = {} function Quest:GetNumWatched () superTrackQuestID = GetSuperTrackedQuestID() playerMoney = GetMoney(); inScenario = C_Scenario.IsInScenario(); showPOIs = GetCVarBool("questPOI"); self.numAll = GetNumQuestLogEntries() self.numWatched = GetNumQuestWatches() return self.numWatched, self.numAll end --- Returns an iterable table from which tracker blocks can be filled out. Data includes: -- All entry-layer GetXInfo return values -- Manifest of line data to be displayed in relation to the tracked object Quest.GetInfo = function (self, watchIndex) local print = iprint local questID, title, questLogIndex, numObjectives, requiredMoney, isComplete, startEvent, isAutoComplete, failureTime, timeElapsed, questType, isTask, isStory, isOnMap, hasLocalPOI = GetQuestWatchInfo(watchIndex) if ( not questID ) then return end tprint(' |cFFFFBB00GetInfo:|r', watchIndex, '|cFFFF2299'..title..'|r') local _, level, suggestedGroup, isHeader, isCollapsed, isComplete, frequency, _, startEvent, displayQuestID, isOnMap, hasLocalPOI, isTask, isStory = GetQuestLogTitle(questLogIndex) Quest.Info[questID] = Quest.Info[questID] or {} local q = Quest.Info[questID] q.type = 'Quest' q.title = title q.level = level q.displayQuestID = displayQuestID q.suggestedGroup = suggestedGroup -- re-use Blizzard logic for consistency local showQuest = true if isTask then showQuest = false end local watchMoney = false; local tagID, typeTag, frequencyTag, completionTag, completionText local isAccount, isFaction, isWeekly, isDaily = false, false, false, false local isBreadcrumb = false local questFailed = false local watchMoney = false local timerInfo, moneyInfo = false, false local objectives = q.objectives or {} -- Case 1: completed quest or "go to thing" breadcrumb -- * 1 line containing the completion text if ( isComplete and isComplete < 0 ) then isComplete = false questFailed = true elseif ( numObjectives == 0 and playerMoney >= requiredMoney and not startEvent ) then isComplete = true; questFailed = false if ( requiredMoney == 0 ) then isBreadcrumb = true; end end print('|cFF0088FFflags:|r', (isComplete and 'isComplete' or ''), (questFailed and 'questFailed' or ''), (isBreadcrumb and 'isBreadcrumb' or '')) -- completion message? local isSequenced = IsQuestSequenced(questID) local temp_status = '' if ( isComplete ) then temp_status = 'COMPLETED_OBJECTIVES' objectives = Quest.GetObjectives(questLogIndex, numObjectives, true, isSequenced, isStory) if ( isAutoComplete ) then temp_status = 'AUTOCOMPLETE_OBJECTIVES' completionText = _G.QUEST_WATCH_CLICK_TO_COMPLETE else if ( isBreadcrumb ) then temp_status = 'COMPLETE_BREADCRUMB' completionText = GetQuestLogCompletionText(questLogIndex) else temp_status = 'COMPLETE_READY_FOR_TURN_IN' completionText = _G.QUEST_WATCH_QUEST_READY end end elseif ( questFailed ) then temp_status = 'FAILED' -- Case 2: failed quest -- * 1 status line; hide other info completionText = _G.FAILED else temp_status = 'PROGRESS_OBJECTIVES' -- Case 3: quest in progress -- * Multiple objective lines -- * Possible extra lines for money and timer data respectively objectives = Quest.GetObjectives(questLogIndex, numObjectives, false, isSequenced, isStory) q.objectives = objectives --- anything past here gets appended to existing objectives -- money if ( requiredMoney > playerMoney ) then temp_status = temp_status .. '_MONEY' local text = GetMoneyString(playerMoney).." / "..GetMoneyString(requiredMoney); moneyInfo = { type = 'money', text = text, finished = false, requiredMoney = requiredMoney, playerMoney = playerMoney, } tinsert(objectives, moneyInfo) end -- time limit if ( failureTime ) then temp_status = temp_status .. '_TIMED' if ( timeElapsed and timeElapsed <= failureTime ) then timerInfo = { type = 'timer', finished = false, timeElapsed = timeElapsed, failureTime = failureTime, } tinsert(objectives, timerInfo) end end end q.numObjectives = numObjectives q.objectives = objectives q.requiredMoney = requiredMoney q.moneyInfo = moneyInfo q.timerInfo = timerInfo q.failureTime = failureTime q.timeElapsed = timeElapsed q.completionText = completionText -- POI data local POI = false if ( showPOIs ) then POI = { questID = questID, questLogIndex = questLogIndex, } local poiButton; if ( hasLocalPOI ) then if ( isComplete ) then POI.type = 'normal' else POI.type = 'numeric' end elseif ( isComplete ) then POI.type = 'remote' end local distance, onContinent = GetDistanceSqToQuest(questLogIndex) if distance ~= nil and distance > 0 then POI.distance = distance POI.onContinent = onContinent end end q.POI = POI --- Block Tags -- completionTag - in progres, complete, failed, autocomplete -- typeTag - account, faction, pvp, dungeon, group -- frequencyTag - daily/weekly local questTagID, tagName = GetQuestTagInfo(questID) local tagInfo = {} local tagCoords = {} local factionGroup = GetQuestFactionGroup(questID); if( questTagID and questTagID == QUEST_TAG_ACCOUNT ) then if( factionGroup ) then tagID = "ALLIANCE" if ( factionGroup == LE_QUEST_FACTION_HORDE ) then tagID = "HORDE" end isFaction = true else tagID = QUEST_TAG_ACCOUNT isAccount = true end tagInfo['typeTag'] = tagID tagCoords['typeTag'] = QUEST_TAG_TCOORDS[tagID] elseif ( factionGroup) then tagID = "ALLIANCE" if ( factionGroup == LE_QUEST_FACTION_HORDE ) then tagID = "HORDE" end isFaction = true tagInfo['typeTag'] = tagID tagCoords['typeTag'] = QUEST_TAG_TCOORDS[tagID] end if( frequency == LE_QUEST_FREQUENCY_DAILY and (not isComplete or isComplete == 0) ) then tagID = 'DAILY' tagInfo['frequencyTag'] = tagID tagCoords['frequencyTag'] = QUEST_TAG_TCOORDS[tagID] isDaily = true elseif( frequency == LE_QUEST_FREQUENCY_WEEKLY and (not isComplete or isComplete == 0) )then tagID = 'WEEKLY' tagInfo['frequencyTag'] = tagID tagCoords['frequencyTag'] = QUEST_TAG_TCOORDS[tagID] isWeekly = true elseif( questTagID ) then tagID = questTagID end if( isComplete ) then tagInfo['completionTag'] = 'COMPLETED' elseif ( questFailed ) then tagInfo['completionTag'] = 'FAILED' end tagCoords['completionTag'] = QUEST_TAG_TCOORDS[tagInfo['completionTag']] q.tagInfo = tagInfo q.tagCoords = tagCoords -- establishes the primary block tag for view compacting q.tagID = tagID q.tagName = tagName -- action button information local link, icon, charges = GetQuestLogSpecialItemInfo(questLogIndex) local start, duration, enable = GetQuestLogSpecialItemCooldown(questLogIndex) if link or icon or charges then q.specialItem = { questID = questID, questLogIndex = questLogIndex, link = link, charges = charges, icon = icon, start = start, duration = duration, enable = enable, } end if moneyInfo or timerInfo then numObjectives = #objectives end -- raw data q.isComplete = isComplete q.startEvent = startEvent q.isAutoComplete = isAutoComplete q.questType = questType q.isTask = isTask q.isStory = isStory q.isOnMap = isOnMap q.hasLocalPOI = hasLocalPOI q.frequency = frequency q.isComplete = isComplete q.isStory = isStory q.isTask = isTask q.statusKey = temp_status q.selected = (questID == superTrackQuestID) T.SetRewards(q, questID) q.questID = questID q.logIndex = questLogIndex q.watchIndex = watchIndex q.id = questID self.WatchInfo[watchIndex] = q self.LogInfo[questLogIndex] = q if Devian and Devian.InWorkspace() then print('|cFF00DDFFstatus:|r', temp_status, '|cFF00FF00questLogIndex|r:', questLogIndex, title) local temp ={} local data_txt = '|cFFFF4400values:|r' for k,v in pairs(q) do if type(v) =='number' then data_txt = data_txt .. ' |cFFFFFF00'..k..'|r: ' .. tostring(v) elseif type(v) == 'table' then tinsert(temp, k) end end print(data_txt) sort(temp, function(a,b) return a < b end) for i, k in ipairs(temp) do print('|cFF00FF00'..k..'|r') for kk,v in pairs(q[k]) do print(' ', kk, '=', v) end end end return q end Quest.GetObjectives = function(questLogIndex, numObjectives, isComplete, isSequenced, isStory) local objectives = {} for i = 1, numObjectives do local text, type, finished = GetQuestLogLeaderBoard(i, questLogIndex) print(format(' |cFFFF4400GetObjectives:|r #%d %s %s %s', i, tostring(type), tostring(text), tostring(finished))) objectives[i] = { index = i, type = type, text = text, finished = finished } end return objectives end local huge, sqrt = math.huge, math.sqrt Quest.GetClosest = function() local minID, minTitle local minDist = huge local numQuests = GetNumQuestLogEntries() for questIndex = 1, numQuests do local distance, onContinent = GetDistanceSqToQuest(questIndex) local title, level, _, _, _, _, _, _, questID = GetQuestLogTitle(questIndex) if onContinent and distance < minDist then minDist = distance minTitle = title minID = questID end end print('nearest quest is', minTitle, 'by', sqrt(minDist)) return minID, minTitle, minDist end Quest.OnTurnIn = function(self, questID, xp, money) end Quest.Select = function (handler, block) if block.info.isAutoComplete and block.info.isComplete then ShowQuestComplete(block.info.logIndex) else SetSuperTrackedQuestID(block.info.questID) end end Quest.Link = function(handler, block) local questLink = GetQuestLink(block.info.logIndex); if ( questLink ) then ChatEdit_InsertLink(questLink); end end Quest.Open = function(handler, block) QuestMapFrame_OpenToQuestDetails(block.info.questID) end Quest.Remove = function(handler, block) print('removing', block.info.logIndex, 'from watcher') RemoveQuestWatch(block.info.logIndex) end