Mercurial > wow > buffalo2
diff ObjectiveTracker/QuestData.lua @ 43:9480bd904f4c
- file name organizing
author | Nenue |
---|---|
date | Mon, 25 Apr 2016 13:51:58 -0400 |
parents | ObjectiveTracker/Quests.lua@03ed70f846de |
children | 756e8aeb040b |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ObjectiveTracker/QuestData.lua Mon Apr 25 13:51:58 2016 -0400 @@ -0,0 +1,577 @@ +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, wipe, select = format, table.wipe, select +local wipeall = B.wipeall +local lprint, iprint, tprint = B.print('Line'), B.print('Info'), B.print('Tracker') +local print = tprint +local fprint = B.print('Frame') + + +local superTrackQuestID, playerMoney, inScenario, showPOIs +Quest.Update = function(self, reason, ...) + local print = self.print + 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(self, block) + local print = lprint + print('|cFF'..self.internalColor..'UpdateObjectives()') + 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 displayObjectives = true + 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') + self:AddLine(block, T.strings.CLICK_TO_COMPLETE, nil, 'complete') + end + else + if not completionText or info.completionText then + info.completionText = GetQuestLogCompletionText(info.logIndex) + end + end + self:AddLine(block, info.completionText, nil, 'complete') + displayObjectives = false + print('|cFF'..self.internalColor..' :: complete quest :: show instruction: "'.. tostring(info.completionText) .. '"') + end + + Default.UpdateObjectives(self, block, block_schema, displayObjectives) + return 0, block_schema +end + +Quest.UpdateLine = function(handler, block, data) + local objectiveType = data.type + return data.text, nil, objectiveType +end + +----------------------------- +--- QUEST +local tremove, tinsert = tremove, tinsert +local GetQuestLogIndexByID, IsQuestWatched = GetQuestLogIndexByID, IsQuestWatched +Quest.QuestBlock = {} +Quest.LogBlock = {} +Quest.LogInfo = {} + +Quest.OnRemoved = function(block) + +end + +Quest.GetBlock = function(self, index) + local block = Default.GetBlock(self, index) + block:SetScript('OnEvent', Quest.OnRemoved) + block:RegisterEvent('QUEST_REMOVED') + return block +end + +local GetQuestWatchIndex = GetQuestWatchIndex +local numAnimating = 0 +local blocksChecked = {} + +--- Get a total of things to show, and straighten out the index while we're at it +--- Return the number shown, total in log, and the info table to parse +Quest.GetNumWatched = function (self, id, added) + local print = self.print + B.print('Block')('########') + B.print('Block')('########') + superTrackQuestID = GetSuperTrackedQuestID() + playerMoney = GetMoney(); + inScenario = C_Scenario.IsInScenario(); + showPOIs = GetCVarBool("questPOI"); + local numAll = GetNumQuestLogEntries() + local numWatched = GetNumQuestWatches() + local bottomIndex = 1 + print('GetNumWatched', self.name, numWatched, 'of', numAll) + local start, limit = 1, numAll + + if id and not added then + -- if a particular id is supplied, add to checklist + if self.InfoBlock[id] then + blocksChecked[self.InfoBlock[id]] = self.InfoBlock[id] + end + end + + numAnimating = 0 + for logIndex = start, limit do + local reason1, reason2 = '', '' + local title, level, suggestedGroup, isHeader, isCollapsed, isComplete, frequency, questID, startEvent, displayQuestID, isOnMap, hasLocalPOI, isTask, isStory = GetQuestLogTitle(logIndex) + local watchIndex = GetQuestWatchIndex(logIndex) + + --- Start of crazy audit flagging + if watchIndex and watchIndex >= bottomIndex then + -- do watch data pointers match? + local watchInfo = self.WatchInfo[watchIndex] + local watchBlock = self.WatchBlock[watchIndex] + if watchInfo and watchInfo.questID ~= questID then + print('GetNumWatched', 'trimming WatchInfo ['..watchIndex..'] =/=', questID) + self.WatchInfo[watchIndex] = nil + end + if watchBlock and watchBlock.info.questID ~= questID then + print('GetNumWatched', 'trimming WatchBlock ['..watchIndex..'] =/=', watchBlock:GetName()) + self.WatchBlock[watchIndex] = nil + blocksChecked[watchBlock] = watchBlock + end + end + + -- check log-block pointer + local logBlock = self.LogBlock[logIndex] + if logBlock then + -- check later that the block isn't for a dropped quest + if logBlock.info.questID ~= questID then + print('GetQuests', 'replace info', logBlock.info.questID, '->', questID) + self.LogBlock[logIndex] = nil + blocksChecked[logBlock] = logBlock + end + end + --- end of crazy audit flagging + + -- add to watch index if: the questID is non-zero + if questID ~= 0 then + self.Info[questID] = self:GetInfo(logIndex, watchIndex) + print('GetQuests', format('request info |cFF00FF00%2d|r |cFFFFFF00%6d|r |cFFFF4400%3s|r', logIndex, questID, tostring(watchIndex or ''))) + end + end + + --- After GetInfo pass, look for any non-conformant blocks and deal with them + for _, block in pairs(blocksChecked) do + local logIndex = GetQuestLogIndexByID(block.info.questID, 'player') + -- animating blocks have been evaluated + if not block.isAnimating then + if not logIndex then + self:ClearBlock(block) + elseif not IsQuestWatched(block.info.logIndex) then + self:ClearBlock(block) + end + end + blocksChecked[block] = nil + end + + self.numWatched = numWatched + self.numAll = numAll + + return numWatched, numAll, self.WatchList +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, logIndex, watchIndex) + local print = iprint + local title, level, suggestedGroup, isHeader, isCollapsed, isComplete, frequency, questID, startEvent, displayQuestID, isOnMap, hasLocalPOI, isTask, isStory = GetQuestLogTitle(logIndex) + if ( not questID ) then + tprint('GetNumWatched', logIndex, watchIndex, '|cFFFF2299no data|r') + return + end + + Quest.Info[questID] = Quest.Info[questID] or {} + local q = Quest.Info[questID] + q.questID = questID + q.id = questID + q.logIndex = logIndex + q.watchIndex = watchIndex + + local numObjectives, requiredMoney, isAutoComplete, failureTime, timeElapsed, questType + = 0, 0, nil, false, false, 0 + if watchIndex then + local _ + _,_,_, numObjectives, requiredMoney, _, _, isAutoComplete, + failureTime, timeElapsed, questType = GetQuestWatchInfo(watchIndex) + + -- ensure that the entry being populated isn't animating + if self.WatchBlock[watchIndex] then + local checkIndex = watchIndex + while self.WatchBlock[checkIndex + numAnimating] and self.WatchBlock[checkIndex + numAnimating].isAnimating do + print(self.WatchBlock[checkIndex + numAnimating]:GetName(), 'is in an animation sequence') + numAnimating = numAnimating + 1 + end + end + + self.WatchList[watchIndex + numAnimating] = q + --tprint(' |cFF88FF00GetInfo:|r set watch entry', watchIndex) + print('GetInfo:', logIndex, watchIndex, '|cFFFF2299'..title..'|r') + end + self.LogInfo[logIndex] = q + + q.numObjectives = numObjectives + q.requiredMoney = requiredMoney + q.failureTime = failureTime + q.timeElapsed = timeElapsed + + + + 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('QuestFlags', (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 + self.print(' QuestInfo', title, questType, isAutoComplete) + objectives = Quest.GetObjectives(logIndex, 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.objectives = objectives + q.moneyInfo = moneyInfo + q.timerInfo = timerInfo + q.completionText = completionText + + -- POI data + local POI = false + if ( showPOIs ) then + POI = { + questID = questID, + logIndex = logIndex, + watchIndex = watchIndex + } + 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(logIndex) + 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 schema = 'default' + 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" + schema = 'alliance' + if ( factionGroup == LE_QUEST_FACTION_HORDE ) then + tagID = "HORDE" + schema = '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 + schema = 'daily' + 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 + schema = 'weekly' + 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(logIndex) + local start, duration, enable = GetQuestLogSpecialItemCooldown(logIndex) + if link or icon or charges then + q.specialItem = { + questID = questID, + logIndex = 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 = logIndex + q.watchIndex = watchIndex + q.id = questID + q.schema = schema + + if Devian and Devian.InWorkspace() then + print('QuestStatus', temp_status, '|cFF00FF00questLogIndex|r:', logIndex, title) + local temp ={} + local data_txt = '|cFF'..self.internalColor..'values:|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('DataStatus',data_txt) + sort(temp, function(a,b) return a < b end) + for i, k in ipairs(temp) do + iprint('GetInfo', questID, ''..k..'|r') + for kk,v in pairs(q[k]) do + iprint('GetInfo', questID, kk, '=', v) + end + end + end + + return q +end + +Quest.GetObjectives = function(logIndex, numObjectives, isComplete, isSequenced, isStory) + local print = Quest.print + local objectives = {} + if not logIndex then + return + end + + for i = 1, numObjectives do + local text, type, finished = GetQuestLogLeaderBoard(i, logIndex) + + local progress = 0 + if finished then + progress = 1 + elseif text then + local quantity, maxQuantity = text:match('^(%d+)/(%d+)') + if quantity and maxQuantity then + progress = quantity / maxQuantity + --print('GetObjectives', 'calculated objective progress:', quantity, '/', maxQuantity, '=', progress) + end + end + + print('GetObjectives', format('|cFF88FF88#%d %s %s %s', i, tostring(type), tostring(text), tostring(finished)), '('.. tostring(progress)..')') + + + objectives[i] = { + index = i, + type = type, + text = text, + finished = finished, + progress = progress + } + 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