Nenue@0: --- ${PACKAGE_NAME} Nenue@0: -- @file-author@ Nenue@0: -- @project-revision@ @project-hash@ Nenue@0: -- @file-revision@ @file-hash@ Nenue@0: -- Created: 3/29/2016 7:07 PM Nenue@0: local B = select(2,...).frame Nenue@0: local mod = B:RegisterModule("ObjectiveTracker", _G.VeneerObjectiveWrapper, 'BuffFrame') Nenue@0: local print = B.print('Objectives') Nenue@0: local Tracker, AutoQuest, Quest, Cheevs = mod.Tracker, mod.AutoQuest, mod.Quest, mod.Cheevs Nenue@6: local itemButtonSize, itemButtonSpacing = 36, 1 Nenue@7: local tremove, tremovebyval = table.remove, table.removebyval Nenue@0: Nenue@0: -------------------------------------------------------------------- Nenue@3: --- Tracker-specific widgets and their handlers Nenue@0: -------------------------------------------------------------------- Nenue@0: Nenue@0: Tracker.Select = function(self) end Nenue@0: Tracker.Open = function(self) end Nenue@0: Tracker.Remove = function(self) end Nenue@0: Tracker.Report = function(self) Nenue@0: print('Stats:', self.numWatched,'items tracked,', self.numBlocks,'blocks assigned.') Nenue@0: end Nenue@0: Nenue@0: Tracker.OnMouseUp = function(self, button) Nenue@9: if button == 'LeftButton' then Nenue@9: if IsModifiedClick("CHATLINK") and ChatEdit_GetActiveWindow() then Nenue@7: self:Link() Nenue@9: elseif IsModifiedClick("QUESTWATCHTOGGLE") then Nenue@1: self:Remove() Nenue@7: else Nenue@7: self:Select() Nenue@1: end Nenue@0: elseif button == 'RightButton' then Nenue@0: self:Open() Nenue@0: end Nenue@1: self.initialButton = nil Nenue@7: self.modChatLink = nil Nenue@7: self.modQuestWatch = nil Nenue@8: print('|cFFFF8800'..tostring(self:GetName())..':MouseUp()|r') Nenue@0: end Nenue@0: Nenue@0: Tracker.OnMouseDown = function(self, button) Nenue@7: self:SetStyle('Active') Nenue@8: print(IsModifiedClick("CHATLINK"), IsModifiedClick("QUESTWATCHTOGGLE")) Nenue@0: print(self.info.title) Nenue@0: end Nenue@0: Nenue@0: ----------------------------- Nenue@0: --- AUTO_QUEST Nenue@0: AutoQuest.name = "Remote Quests" Nenue@0: AutoQuest.GetNumWatched = GetNumAutoQuestPopUps Nenue@0: Nenue@0: ----------------------------- Nenue@0: --- QUEST Nenue@0: Quest.name = "Quests" Nenue@0: Quest.Select = function(self) Nenue@0: SetSuperTrackedQuestID(self.info.questID) Nenue@7: mod.UpdateWrapper() Nenue@7: end Nenue@7: Quest.Link = function(self) Nenue@7: local questLink = GetQuestLink(block.questLogIndex); Nenue@7: if ( questLink ) then Nenue@7: ChatEdit_InsertLink(questLink); Nenue@7: end Nenue@0: end Nenue@0: Quest.Open = function(self) Nenue@1: QuestMapFrame_OpenToQuestDetails(self.info.questID) Nenue@1: end Nenue@1: Nenue@1: Quest.Remove = function(self) Nenue@5: print('removing', self.info.questLogIndex, 'from watcher') Nenue@5: RemoveQuestWatch(self.info.questLogIndex) Nenue@0: end Nenue@0: Nenue@0: Nenue@0: ----------------------------- Nenue@0: --- CHEEVS Nenue@0: Cheevs.Select = function(self) Nenue@0: end Nenue@8: Cheevs.Remove = function(self) Nenue@8: RemoveTrackedAchievement(self.info.cheevID) Nenue@8: end Nenue@9: Cheevs.OnMouseUp = function(self, button) Nenue@9: Tracker.OnMouseUp(self, button) Nenue@8: self:SetStyle('CheevNormal') Nenue@8: end Nenue@7: Cheevs.Link = function(self) Nenue@8: local achievementLink = GetAchievementLink(self.info.cheevID); Nenue@8: if ( achievementLink ) then Nenue@8: ChatEdit_InsertLink(achievementLink); Nenue@8: end Nenue@7: end Nenue@0: Nenue@0: Cheevs.Open = function(self) Nenue@3: if ( not AchievementFrame ) then Nenue@3: AchievementFrame_LoadUI(); Nenue@3: end Nenue@3: if ( not AchievementFrame:IsShown() ) then Nenue@3: AchievementFrame_ToggleAchievementFrame(); Nenue@3: end Nenue@3: AchievementFrame_SelectAchievement(self.info.cheevID); Nenue@0: end Nenue@0: Nenue@1: ---------------------------------------------------------------------------------------- Nenue@1: --- frame template and scripts lifted from "QuestKing 2" by Barjack Nenue@1: --- url: http://mods.curse.com/addons/wow/questking Nenue@1: ---------------------------------------------------------------------------------------- Nenue@1: local usedButtons = mod.Quest.itemButtons Nenue@1: local freeButtons = mod.Quest.freeButtons Nenue@1: mod.SetItemButton = function(block, info) Nenue@1: local itemInfo = info.specialItem Nenue@1: if not itemInfo then Nenue@1: return Nenue@1: end Nenue@1: --- .specialItem :: {link = link, charges = charges, icon = icon, start = start, duration = duration, enable = enable} Nenue@1: Nenue@1: Nenue@1: local itemButton Nenue@1: if not info.itemButton then Nenue@1: if #freeButtons >= 1 then Nenue@2: print(' |cFF00FFFFfound a free button') Nenue@1: itemButton = freeButtons[#freeButtons] Nenue@1: freeButtons[#freeButtons] = nil Nenue@2: if itemButton.block then Nenue@2: itemButton.block.itemButton = nil Nenue@2: itemButton.block = nil Nenue@2: end Nenue@1: else Nenue@1: local buttonIndex = mod.Quest.numButtons + #freeButtons + 1 Nenue@1: itemButton = CreateFrame('Button', 'VeneerQuestItemButton' .. buttonIndex, UIParent, 'VeneerItemButtonTemplate') Nenue@1: itemButton.buttonIndex = buttonIndex Nenue@6: itemButton:SetSize(itemButtonSize, itemButtonSize) Nenue@6: itemButton:GetNormalTexture():SetSize(itemButtonSize * (5/3), itemButtonSize * (5/3)) Nenue@5: print(' |cFFFF4400starting new button', itemButton:GetName()) Nenue@1: end Nenue@1: mod.Quest.numButtons = mod.Quest.numButtons + 1 Nenue@1: else Nenue@1: itemButton = info.itemButton Nenue@5: print(' |cFF00FF00found assigned button', itemButton:GetName()) Nenue@2: Nenue@1: end Nenue@1: -- set values Nenue@2: Nenue@5: info.itemButton = itemButton Nenue@5: usedButtons[info.questID] = itemButton Nenue@5: print(' |cFF8800FFassigning|r', itemButton:GetName(), 'to quest|cFF00FF00', info.questID, '|rat|cFFFFFF00', block:GetName(),'|r') Nenue@2: Nenue@5: for k,v in pairs(usedButtons) do Nenue@5: print('|cFFFF44DD'..k..'|r', v:GetName()) Nenue@5: end Nenue@1: Nenue@1: itemButton:SetAttribute("type", "item") Nenue@1: itemButton:SetAttribute("item", itemInfo.link) Nenue@1: Nenue@2: itemButton.questID = info.questID Nenue@1: itemButton.questLogIndex = info.questLogIndex Nenue@1: itemButton.charges = itemInfo.charges Nenue@1: itemButton.rangeTimer = -1 Nenue@1: itemButton.block = block Nenue@1: Nenue@1: SetItemButtonTexture(itemButton, itemInfo.icon) Nenue@1: SetItemButtonCount(itemButton, itemInfo.charges) Nenue@1: Veneer_QuestObjectiveItem_UpdateCooldown(itemButton); Nenue@1: Nenue@1: return itemButton Nenue@1: end Nenue@1: --- Clear an itemButton from the given block Nenue@2: mod.FreeItemButtons = function(block) Nenue@2: Nenue@2: if block.itemButton then Nenue@2: local itemButton = block.itemButton Nenue@5: if itemButton.questID ~= block.info.questID then Nenue@5: block.itemButton = nil Nenue@5: itemButton.block = mod.Quest.InfoBlock[itemButton.questID] Nenue@5: else Nenue@5: itemButton.block = nil Nenue@5: itemButton:Hide() Nenue@2: Nenue@5: usedButtons[itemButton.questID] = nil Nenue@5: freeButtons[#freeButtons + 1] = itemButton Nenue@5: mod.Quest.numButtons = mod.Quest.numButtons - 1 Nenue@5: print('|cFFFF0088released', itemButton:GetName(),'and', block:GetName()) Nenue@5: end Nenue@1: end Nenue@1: end Nenue@1: Nenue@1: function Veneer_QuestObjectiveItem_OnUpdate (self, elapsed) Nenue@1: -- Handle range indicator Nenue@1: local rangeTimer = self.rangeTimer Nenue@1: if (rangeTimer) then Nenue@1: rangeTimer = rangeTimer - elapsed Nenue@1: if (rangeTimer <= 0) then Nenue@1: local link, item, charges, showItemWhenComplete = GetQuestLogSpecialItemInfo(self.questLogIndex) Nenue@1: if ((not charges) or (charges ~= self.charges)) then Nenue@2: mod.UpdateWrapper() Nenue@1: return Nenue@1: end Nenue@1: Nenue@1: local count = self.HotKey Nenue@1: local valid = IsQuestLogSpecialItemInRange(self.questLogIndex) Nenue@1: if (valid == 0) then Nenue@1: count:Show() Nenue@1: count:SetVertexColor(1.0, 0.1, 0.1) Nenue@1: elseif (valid == 1) then Nenue@1: count:Show() Nenue@1: count:SetVertexColor(0.6, 0.6, 0.6) Nenue@1: else Nenue@1: count:Hide() Nenue@1: end Nenue@1: rangeTimer = TOOLTIP_UPDATE_TIME Nenue@1: end Nenue@1: Nenue@1: self.rangeTimer = rangeTimer Nenue@1: end Nenue@1: end Nenue@1: Nenue@1: function Veneer_QuestObjectiveItem_UpdateCooldown (itemButton) Nenue@1: local start, duration, enable = GetQuestLogSpecialItemCooldown(itemButton.questLogIndex) Nenue@1: if (start) then Nenue@1: CooldownFrame_SetTimer(itemButton.Cooldown, start, duration, enable) Nenue@1: if (duration > 0 and enable == 0) then Nenue@1: SetItemButtonTextureVertexColor(itemButton, 0.4, 0.4, 0.4) Nenue@1: else Nenue@1: SetItemButtonTextureVertexColor(itemButton, 1, 1, 1) Nenue@1: end Nenue@1: end Nenue@3: end Nenue@3: Nenue@3: ----------------------------------------- Nenue@7: -- Criteria frames Nenue@7: Nenue@7: --[[ Nenue@7: text = description, Nenue@7: type = type, Nenue@7: finished = completed, Nenue@7: quantity = quantity, Nenue@7: requiredQuantity = requiredQuantity, Nenue@7: characterName = characterName, Nenue@7: flags = flags, Nenue@7: assetID = assetID, Nenue@7: quantityString = quantityString, Nenue@7: criteriaID = criteriaID, Nenue@7: ]] Nenue@7: local newWidgetID = 0 Nenue@7: mod.WidgetRegistry = {} Nenue@7: local wr = mod.WidgetRegistry Nenue@7: Nenue@7: --- Get a usable widget for the given achievement criteria set. Nenue@7: -- Returns a frame object with dimensioning parameters needed to size the receiving tracker block Nenue@7: mod.SetWidget = function(obj, info) Nenue@8: local print = B.print('ObjectiveWidgets') Nenue@7: local widgetType = obj.type Nenue@7: local widget Nenue@8: if wr[widgetType] and wr[widgetType].used[obj.criteriaID] then Nenue@8: widget = wr[widgetType].used[obj.criteriaID] Nenue@8: print('|cFF00FF00Updating ('..obj.criteriaID..')', widget) Nenue@8: elseif not wr[widgetType] or #wr[widgetType].free == 0 then Nenue@8: widget = CreateFrame('Frame', 'VeneerObjective' .. widgetType .. (wr[widgetType] and (wr[widgetType].lastn+1) or (1)), VeneerObjectiveScroll, 'VeneerObjectiveCriteria' .. widgetType) Nenue@7: Nenue@8: print('|cFFFF0088Creating `'..widget:GetName()..'` id', wr[widgetType].lastn) Nenue@8: else Nenue@8: widget = tremove(wr[widgetType].free) Nenue@8: print('|cFFFFFF00Acquiring released widget', widget:GetName()) Nenue@7: end Nenue@7: Nenue@8: wr[widgetType].used[obj.criteriaID] = widget Nenue@7: widget.info = obj Nenue@7: widget.parentInfo = info Nenue@7: mod.InitializeWidget(widget) Nenue@7: return widget Nenue@3: end Nenue@3: Nenue@8: --- WidgetTemplate 'OnLoad' Nenue@7: mod.RegisterWidget = function(frame) Nenue@8: local print = B.print('ObjectiveWidgets') Nenue@7: local widgetType = frame.widgetType Nenue@7: if not wr[frame.widgetType] then Nenue@7: print('|cFFFF4400[[WidgetTemplate]]|r', widgetType) Nenue@8: wr[widgetType] = { lastn = 1, free = {}, used = {}, usedIndex = {}, freeIndex = {} } Nenue@8: else Nenue@8: print('|cFF0088FF+ [[WidgetTemplate]]r', widgetType, wr[widgetType].lastn) Nenue@8: wr[widgetType].lastn = wr[widgetType].lastn + 1 Nenue@3: end Nenue@7: end Nenue@8: Nenue@8: --- WidgetTemplate 'OnShow' Nenue@7: mod.InitializeWidget = setmetatable({}, { Nenue@7: __call = function(t, frame) Nenue@7: -- todo: config pull Nenue@7: local maxWidth = 250 Nenue@3: Nenue@7: frame:SetWidth(maxWidth) Nenue@7: mod.UpdateWidget[frame.widgetType](frame) Nenue@7: frame:SetScript('OnEvent', mod.UpdateWidget[frame.widgetType]) Nenue@7: if frame.info.isCurrency then Nenue@7: frame:RegisterEvent('CHAT_MSG_CURRENCY') Nenue@7: frame:RegisterEvent('CURRENCY_LIST_UPDATE') Nenue@7: end Nenue@7: frame:RegisterEvent('TRACKED_ACHIEVEMENT_UPDATE') Nenue@7: frame:RegisterEvent('TRACKED_ACHIEVEMENT_LIST_CHANGED') Nenue@7: frame:RegisterEvent('CRITERIA_UPDATE') Nenue@7: frame:RegisterEvent('CRITERIA_COMPLETE') Nenue@7: frame:RegisterEvent('CRITERIA_EARNED') Nenue@7: Nenue@7: return t[frame.widgetType](frame) Nenue@7: end, Nenue@7: }) Nenue@8: Nenue@8: --- WidgetTemplate 'OnEvent' Nenue@7: mod.UpdateWidget = setmetatable({}, { Nenue@7: __call = function(t, frame) Nenue@7: if not frame.widgetType then Nenue@7: error('Invalid widget template, needs .widgetType') Nenue@7: return Nenue@7: end Nenue@7: Nenue@7: return t[frame.widgetType](frame) Nenue@7: end Nenue@7: }) Nenue@7: Nenue@8: --- WidgetTemplate 'OnHide' Nenue@7: mod.ReleaseWidget = function(frame) Nenue@8: local print = B.print('ObjectiveWidgets') Nenue@7: local reg = wr[frame.widgetType] Nenue@8: if reg and reg.used[frame.info.criteriaID] then Nenue@8: reg.used[frame.info.criteriaID] = nil Nenue@8: frame.info = nil Nenue@8: frame.parentInfo = nil Nenue@7: frame:UnregisterAllEvents() Nenue@7: tinsert(reg.free, frame) Nenue@8: print('|cFFBBBBBBreleased from service', frame:GetName()) Nenue@8: end Nenue@8: end Nenue@8: Nenue@8: --- RemoveTrackedAchievement post-hook Nenue@8: mod.CleanWidgets = function() Nenue@8: local print = B.print('ObjectiveWidgets') Nenue@8: local tracked = {GetTrackedAchievements() } Nenue@8: for type, reg in pairs(mod.WidgetRegistry) do Nenue@8: print('collecting', type) Nenue@8: for criteriaID, frame in pairs(reg.used) do Nenue@8: local id = frame.info.cheevID Nenue@8: Nenue@8: if id and not tContains(tracked, id) then Nenue@8: Nenue@8: print(' untracked achievement', id, 'associated with', criteriaID, frame:GetName()) Nenue@8: frame:Hide() Nenue@8: end Nenue@8: end Nenue@3: end Nenue@3: end Nenue@7: Nenue@7: mod.WidgetParams = { Nenue@7: ['ProgressBar'] = { Nenue@7: height = 20, Nenue@7: caption = {}, Nenue@7: quantityString = {SetFontObject = _G.VeneerFontNormal} Nenue@7: } Nenue@7: } Nenue@7: Nenue@7: mod.InitializeWidget.ProgressBar = function(self) Nenue@8: local print = B.print('ObjectiveWidgets') Nenue@7: local params = mod.WidgetParams[self.widgetType] Nenue@7: self.height = params.height Nenue@7: self:SetHeight(20) Nenue@7: self.bg:SetHeight(20) Nenue@9: self.fg:ClearAllPoints() Nenue@9: self.fg:SetPoint('BOTTOMLEFT', self, 'BOTTOMLEFT', 2, 2) Nenue@8: self.fg:SetHeight(16) Nenue@7: self.quantityString:SetFontObject(params.quantityString.SetFontObject) Nenue@7: self.quantityString:SetText(self.info.quantityString) Nenue@3: end Nenue@7: Nenue@7: mod.UpdateWidget.ProgressBar = function (self) Nenue@8: local print = B.print('ObjectiveWidgets') Nenue@7: local quantity, requiredQuantity = self.info.quantity, self.info.requiredQuantity Nenue@8: Nenue@7: if self.info.finished then Nenue@9: self.fg:SetWidth(self.bg:GetWidth() - 4) Nenue@7: elseif quantity == 0 then Nenue@7: self.fg:Hide() Nenue@7: else Nenue@7: self.fg:Show() Nenue@9: self.fg:SetWidth((self.bg:GetWidth()-4) * (quantity / requiredQuantity)) Nenue@7: end Nenue@8: end