Nenue@0: --- ${PACKAGE_NAME} Nenue@0: -- @file-author@ Nenue@0: -- @project-revision@ @project-hash@ Nenue@0: -- @file-revision@ @file-hash@ Nenue@0: -- Created: 3/26/2016 1:51 AM Nenue@0: local B = select(2,...).frame Nenue@14: local pairs, setmetatable, type, tostring = pairs, setmetatable, type, tostring Nenue@14: local format = string.format Nenue@14: local M = B:RegisterModule("ObjectiveTracker", _G.VeneerObjectiveWrapper, 'BuffFrame') Nenue@0: local print = B.print('Objectives') Nenue@0: local ObjectiveTrackerFrame = ObjectiveTrackerFrame Nenue@0: Nenue@0: --[[ Nenue@0: Full quest info is available if: Nenue@0: - It's in the player quest log, or is available from the Gossip interface Nenue@0: - It's being shared from another player and is acceptible Nenue@0: - It's an auto-quest that is available in the current location Nenue@0: Partial quest info is availabe if: Nenue@0: - It's already completed (i.e. it appears in CompletedQuestInfo()). Nenue@0: - It's an scheduled interval quest (daily, weekly, etc.) Nenue@0: - It's contained in a quest link received from chat Nenue@0: Under any other circumstances, only minimal info can be pulled: Nenue@0: - Its availability to the player Nenue@0: - Its relation with the currently engaged NPC Nenue@0: - Its binary completion status Nenue@0: Nenue@0: ]] Nenue@0: --- Global Frames Nenue@0: local Wrapper = _G.VeneerObjectiveWrapper Nenue@0: local Scroller = Wrapper.scrollArea Nenue@0: local Scroll = _G.VeneerObjectiveScroll Nenue@0: Nenue@10: --- Baseline defaults Nenue@14: M.defaults = { Nenue@10: Nenue@10: } Nenue@10: Nenue@0: --- list used to make things happen Nenue@14: M.orderedNames = {'Bonus', 'AutoQuest', 'Quest', 'Cheevs'} Nenue@0: Nenue@0: --- ipairs() list of handlers for wrapper update Nenue@14: M.orderedHandlers = {} Nenue@14: M.orderedTrackers = {} Nenue@14: M.indexedTrackers = {} Nenue@0: --- pairs() list of handler frames for tracker updates Nenue@14: M.namedTrackers = {} Nenue@0: Nenue@0: --- Handler stubs Nenue@14: M.AutoQuest = { Nenue@14: name = "AutoQuest", Nenue@14: displayName = "Local Quests", Nenue@0: } Nenue@14: M.Quest = { Nenue@14: name = "Quest", Nenue@14: displayName = "Quests", Nenue@0: } Nenue@14: M.Cheevs = { Nenue@14: name = "Cheevs", Nenue@14: displayName = "Achievements", Nenue@14: } Nenue@14: M.Bonus = { Nenue@14: name = "Bonus", Nenue@14: displayName = "Bonus Objectives", Nenue@0: } Nenue@0: Nenue@0: Nenue@0: --- Temp values set during updates Nenue@0: local wrapperWidth, wrapperHeight Nenue@0: local scrollWidth, scrollHeight Nenue@0: local previousBlock Nenue@0: local currentBlock Nenue@0: Nenue@0: local frame_guide_init = function(self) Nenue@0: self.testU = self.testU or self:CreateTexture('TestU', 'OVERLAY', 'VnTestLine') Nenue@0: self.testB = self.testB or self:CreateTexture('TestB', 'OVERLAY', 'VnTestLine') Nenue@0: self.testL = self.testL or self:CreateTexture('TestL', 'OVERLAY', 'VnTestLine') Nenue@0: self.testR = self.testR or self:CreateTexture('TestR', 'OVERLAY', 'VnTestLine') Nenue@0: end Nenue@0: local frame_guide = function(self, target) Nenue@0: if not target then return end Nenue@0: if target:IsDragging() then return end Nenue@0: local thickness = 1 Nenue@0: local midX, midY = target:GetCenter() Nenue@0: local width, height = target:GetWidth() * 1.5, target:GetHeight() * 1.5 Nenue@0: --print('frame', target:GetLeft(), target:GetTop(), target:GetRight(), target:GetBottom()) Nenue@0: self.testB:ClearAllPoints() Nenue@0: self.testB:SetPoint('TOP', UIParent, 'BOTTOMLEFT', midX, target:GetBottom()) Nenue@0: self.testB:SetSize(width,thickness) Nenue@0: Nenue@0: self.testU:ClearAllPoints() Nenue@0: self.testU:SetPoint('BOTTOM', UIParent, 'BOTTOMLEFT', midX, target:GetTop()) Nenue@0: self.testU:SetSize(width,thickness) Nenue@0: Nenue@0: self.testL:ClearAllPoints() Nenue@0: self.testL:SetPoint('RIGHT', UIParent, 'BOTTOMLEFT', target:GetLeft(), midY) Nenue@0: self.testL:SetSize(thickness,height) Nenue@0: Nenue@0: self.testR:ClearAllPoints() Nenue@0: self.testR:SetPoint('LEFT', UIParent, 'BOTTOMLEFT', target:GetRight(), midY) Nenue@0: self.testR:SetSize(thickness,height) Nenue@0: end Nenue@0: Nenue@0: --- Handler template Nenue@0: local CreateHandler = function (self, name, index) Nenue@0: print(self, name) Nenue@0: local handler = setmetatable({}, { Nenue@0: __tostring = function() return name end, Nenue@14: __call = function (self) M.UpdateTracker(self) end Nenue@0: }) Nenue@14: if type(M.orderedHandlers[index]) == 'table' then Nenue@14: return M.orderedHandlers[index] Nenue@0: end Nenue@0: Nenue@0: print('take up locals first') Nenue@0: local preset = {} Nenue@14: for k,v in pairs(M[name]) do Nenue@0: preset[k] = true Nenue@0: if type(v) == 'table' then Nenue@0: handler[k] = {} Nenue@0: else Nenue@0: handler[k] = v Nenue@0: end Nenue@0: end Nenue@0: Nenue@0: print('resulting handler contents') Nenue@0: for k, v in pairs(self) do Nenue@0: if not handler[k] then Nenue@0: if type(v) == 'table' then Nenue@0: -- assume all tables to be local data; don't inherit or ref Nenue@0: handler[k] = {} Nenue@0: else Nenue@14: handler[k] = M.Tracker[k] Nenue@0: end Nenue@0: else Nenue@0: print(name, 'has its own', k) Nenue@0: end Nenue@0: end Nenue@0: print('|cFFFF4400'..tostring(name)..'|r:') Nenue@0: for k, v in pairs(handler) do Nenue@0: print(string.format("%24s %8s %s", (preset[k] and '|cFFFFFFFF' or '|cFFFFFF00') .. k .. '|r', type(v), tostring(v))) Nenue@0: end Nenue@14: M[name] = handler Nenue@14: M.orderedHandlers[index] = handler Nenue@0: return true Nenue@0: end Nenue@0: Nenue@14: M.Tracker = setmetatable({}, { Nenue@0: __call = CreateHandler, Nenue@0: __tostring = function() return 'DEFAULT_TRACKING_HANDLER' end Nenue@0: }) Nenue@14: local Tracker = M.Tracker Nenue@0: Tracker.numWatched = 0 --- number of entries being handled Nenue@0: Tracker.numBlocks = 0 --- number of blocks created Nenue@0: Tracker.actualBlocks = 0 --- number of blocks in use Nenue@0: Nenue@0: Tracker.freeBlocks = {} --- block heap Nenue@0: Tracker.usedBlocks = {} Nenue@0: Nenue@0: Tracker.Watched = {} -- find by watchIndex Nenue@0: Tracker.Info = {} -- find by data ID Nenue@0: Tracker.BlockInfo = {} -- find by block ID Nenue@0: Tracker.LogInfo = {} -- find by log ID (quest log mainly) Nenue@2: Tracker.WatchInfo = {} Nenue@0: Tracker.LogBlock = {} Nenue@8: Tracker.WatchBlock = {} Nenue@0: Nenue@0: Nenue@0: Nenue@0: Tracker.GetBlock = function(handler, blockIndex) Nenue@0: local block = handler.usedBlocks[blockIndex] Nenue@0: if not handler.usedBlocks[blockIndex] then Nenue@0: if #handler.freeBlocks >= 1 then Nenue@0: block = handler.freeBlocks[#handler.freeBlocks] Nenue@0: handler.freeBlocks[#handler.freeBlocks] = nil Nenue@0: else Nenue@0: block = CreateFrame('Frame', 'Veneer'..tostring(handler)..'Block'..blockIndex, Scroll, 'VeneerTrackerBlock') Nenue@14: block.SetStyle = M.SetBlockStyle Nenue@14: block.Select = handler.Select Nenue@14: block.Open = handler.Open Nenue@14: block.Remove = handler.Remove Nenue@14: block.Link = handler.Link Nenue@14: block:SetScript('OnMouseUp', handler.OnMouseUp) Nenue@14: block:SetScript('OnMouseDown', handler.OnMouseDown) Nenue@14: block:ClearAllPoints() Nenue@0: end Nenue@0: Nenue@0: handler.usedBlocks[blockIndex] = block Nenue@0: end Nenue@0: return handler.usedBlocks[blockIndex] Nenue@0: end Nenue@0: Nenue@14: function M:OnInitialize() Nenue@14: self.InitializeWrapper() Nenue@3: self.InitializeXPTracker() Nenue@14: M.SetEvents() Nenue@0: ObjectiveTrackerFrame:UnregisterAllEvents() Nenue@0: ObjectiveTrackerFrame:Hide() Nenue@13: Nenue@0: end Nenue@0: Nenue@0: --[[ Nenue@0: QUESTLINE_UPDATE This event is not yet documented Nenue@0: QUESTTASK_UPDATE This event is not yet documented Nenue@0: QUEST_ACCEPTED Fires when a new quest is added to the player's quest log (which is what happens after a player accepts a quest). Nenue@0: QUEST_ACCEPT_CONFIRM Fires when certain kinds of quests (e.g. NPC escort quests) are started by another member of the player's group Nenue@0: QUEST_AUTOCOMPLETE Fires when a quest is automatically completed (remote handin available) Nenue@0: QUEST_BOSS_EMOTE This event is not yet documented Nenue@0: QUEST_CHOICE_CLOSE This event is not yet documented Nenue@0: QUEST_CHOICE_UPDATE This event is not yet documented Nenue@0: QUEST_COMPLETE Fires when the player is looking at the "Complete" page for a quest, at a questgiver. Nenue@0: QUEST_DETAIL Fires when details of an available quest are presented by a questgiver Nenue@0: QUEST_FINISHED Fires when the player ends interaction with a questgiver or ends a stage of the questgiver dialog Nenue@0: QUEST_GREETING Fires when a questgiver presents a greeting along with a list of active or available quests Nenue@0: QUEST_ITEM_UPDATE Fires when information about items in a questgiver dialog is updated Nenue@0: QUEST_LOG_UPDATE Fires when the game client receives updates relating to the player's quest log (this event is not just related to the quests inside it) Nenue@0: QUEST_POI_UPDATE This event is not yet documented Nenue@0: QUEST_PROGRESS Fires when interacting with a questgiver about an active quest Nenue@0: QUEST_REMOVED This event is not yet documented Nenue@0: QUEST_TURNED_IN Fired when a quest is turned in Nenue@0: QUEST_WATCH_LIST_CHANGED This event is not yet documented Nenue@0: QUEST_WATCH_OBJECTIVES_CHANGED This event is not yet documented Nenue@0: QUEST_WATCH_UPDATE Fires when the player's status regarding a quest's objectives changes, for instance picking up a required object or killing a mob for that quest. All forms of (quest objective) progress changes will trigger this event.] Nenue@0: Nenue@0: TRACKED_ACHIEVEMENT_LIST_CHANGED This event is not yet documented Nenue@0: TRACKED_ACHIEVEMENT_UPDATE Fires when the player's progress changes on an achievement marked for watching in the objectives tracker Nenue@0: ]]