Mercurial > wow > buffalo2
view ObjectiveFrame.lua @ 16:880828018bf4
ObjectiveEvents
- trim down the number of events that fire full updates
- begin the general outline for determining which trackers need to refresh
- handlers for accepting and completing auto-popup quests
ObjectiveFrame
- correct variables for money reward calculation
- make sure everythign is scaling to the font strings and that the font strings aren't being pinned by SetSize
ObjectiveInfo
- implementation of autoquest popups
- discern between internal and client bonus objective indexes
- acquire the correct data set from bonus objective query
ObjectiveStyle
- look for a style table under the previously interpreted set before deferring standard options
- horizontal/vertical options in gradient
- remove height-fixing for font strings
author | Nenue |
---|---|
date | Tue, 05 Apr 2016 00:39:12 -0400 |
parents | f660f1c1e0aa |
children | d1812fb10ae6 |
line wrap: on
line source
--- ${PACKAGE_NAME} -- @file-author@ -- @project-revision@ @project-hash@ -- @file-revision@ @file-hash@ -- Created: 3/30/2016 12:49 AM local B = select(2,...).frame local mod = B:RegisterModule("ObjectiveTracker", _G.VeneerObjectiveWrapper, 'BuffFrame') local ipairs, max, min, unpack, floor, pairs, tostring, type, band = ipairs, max, min, unpack, floor, pairs, tostring, type, bit.band local IsResting, UnitXP, UnitXPMax, GetXPExhaustion = IsResting, UnitXP, UnitXPMax, GetXPExhaustion local UnitLevel, IsQuestWatched, UIParent = UnitLevel, IsQuestWatched, UIParent local Quest, Bonus, Cheevs = mod.Quest, mod.Bonus, mod.Cheevs local CreateFrame = CreateFrame local print = B.print('Objectives') local unitLevel = 1 -------------------------------------------------------------------- --- Global frame layout -------------------------------------------------------------------- --- Upvalues local Wrapper = VeneerObjectiveWrapper local Scroller = Wrapper.scrollArea local Scroll = VeneerObjectiveScroll local orderedHandlers = mod.orderedHandlers local orderedNames = mod.orderedNames --- Temp values set during updates local wrapperWidth, wrapperHeight local scrollWidth, scrollHeight local previousBlock local currentBlock --- todo: source these from config local itemButtonSize, itemButtonSpacing = 36, 1 local titleFont, textFont = [[Interface\Addons\SharedMedia_MyMedia\font\ArchivoNarrow-Bold.ttf]], [[Interface\Addons\SharedMedia_MyMedia\font\ArchivoNarrow-Regular.ttf]] local titleSize, textSize = 15, 15 local titleOutline, textOutline = "OUTLINE", "OUTLINE" local titleSpacing, textSpacing = 4, 3 local textIndent = 5 local wrapperMaxWidth, wrapperMaxHeight = 270, 490 -- these are the hard bounds, actual *Height variables are changed local wrapperHeadFont, wrapperHeadSize, wrapperHeadOutline = [[Interface\Addons\SharedMedia_MyMedia\font\ArchivoNarrow-Bold.ttf]], 16, 'NONE' local headerFont, headerSize, headerHeight = [[Interface\Addons\SharedMedia_MyMedia\font\ArchivoNarrow-Bold.ttf]], 18, 24 local headerOutline, headerColor, headerSpacing = 'OUTLINE', {1,1,1,1}, 2 local wrapperPosition = {'RIGHT', UIParent, 'RIGHT', -84, 0} mod.InitializeWrapper = function() mod.SetBlockStyle(Scroller, 'Scroller', 'Normal') mod.SetBlockStyle(Scroller, 'Scroll', 'Normal') mod.SetBlockStyle(Wrapper, 'Wrapper', 'Normal') for i, name in ipairs(orderedNames) do if not mod.orderedHandlers[i] then if mod.Tracker(name, i) then local handler = mod[name] local tracker = CreateFrame('Frame', 'Veneer'..name..'Tracker', Scroll, 'VeneerTrackerTemplate') tracker.title:SetText(handler.displayName) mod.SetBlockStyle(tracker, 'Tracker', 'Normal') handler.Tracker = tracker mod.orderedTrackers[i] = tracker mod.namedTrackers[name] = tracker mod.indexedTrackers[handler] = tracker print('created new tracker frames for new handler') end end end Scroller:SetScrollChild(Scroll) mod.InitializeWrapperWidgets() if B.Conf.ObjectiveTrackerMinimized then Scroller_OnShow(Scroller) end mod.UpdateWrapperStyle() end mod.InitializeXPTracker = function() local XPBar = Wrapper.XPBar if UnitLevel('player') == 100 then XPBar:Hide() return end --- xp bar XPBar:SetWidth(mod.Conf.Wrapper.WrapperWidth - Wrapper.CloseButton:GetWidth()) XPBar.statusbg:SetAllPoints(XPBar) XPBar:RegisterEvent('DISABLE_XP_GAIN') XPBar:RegisterEvent('ENABLE_XP_GAIN') XPBar:SetScript('OnEvent', mod.UpdateXP) if not IsXPUserDisabled() then mod.EnableXP(XPBar) else mod.DisableXP(XPBar) end mod.UpdateXP(XPBar) end mod.EnableXP = function(self) self:RegisterEvent('PLAYER_XP_UPDATE') self:RegisterEvent('PLAYER_LEVEL_UP') self:RegisterEvent('PLAYER_UPDATE_RESTING') self.statusbg:SetTexture(0,0,0,.25) self:Show() end mod.DisableXP = function(self) self:UnregisterEvent('PLAYER_XP_UPDATE') self:UnregisterEvent('PLAYER_LEVEL_UP') self:UnregisterEvent('PLAYER_UPDATE_RESTING') self.statusbg:SetTexture(0.5,0.5,0.5,0.5) self:Hide() end mod.UpdateXP = function(self, event) if event == 'DISABLE_XP_GAIN' then mod.DisableXP(self) elseif event == 'ENABLE_XP_GAIN' then mod.EnableXP(self) end if not IsXPUserDisabled() then local xp = UnitXP('player') local xpmax = UnitXPMax('player') local rest = GetXPExhaustion() self.foreground:SetWidth((xp/xpmax) * self:GetWidth()) if rest then self.rested:ClearAllPoints() if xp == 0 then self.rested:SetPoint('TOPLEFT', self, 'TOPLEFT', 0, 0) else self.rested:SetPoint('TOPLEFT', self.fg, 'TOPRIGHT', 0, 0) end if (xp + rest) > xpmax then self.rested:SetPoint('BOTTOMRIGHT', self, 'BOTTOMRIGHT', 0, 0) else self.rested:SetWidth((rest/xpmax) * self:GetWidth()) end self.rested:SetPoint('BOTTOM', self, 'BOTTOM') self.rested:Show() else self.rested:Hide() end if IsResting() then self.statusbg:SetTexture(.2,.8,.2,.5) else self.statusbg:SetTexture(0,0,0,.25) end self.xpText:SetText(xp .. '/'.. xpmax .. (rest and (' ('..tostring(rest)..')') or '')) end end mod.UpdateTracker = function(handler) local tracker = handler.Tracker print('|cFFFF4400'..tracker:GetName().. '|r:Update()') local blockIndex = 0 local trackerHeight = headerHeight previousBlock = tracker.title local numWatched = handler.GetNumWatched() local numBlocks = handler.numBlocks local actualBlocks = 0 for watchIndex = 1, 25 do blockIndex = blockIndex + 1 if watchIndex <= numWatched then local info = handler:GetInfo(watchIndex) if info then local currentBlock = mod.UpdateTrackerBlock(handler, blockIndex, info) previousBlock = currentBlock print(' |cFFFFFF00'..watchIndex..'|r', '|cFF00FF00'..currentBlock:GetName()..'|r', currentBlock.height) trackerHeight = trackerHeight + currentBlock.height numBlocks = max(numBlocks, watchIndex) actualBlocks = actualBlocks + 1 else print(' |cFFFF0000Failed to draw info for index #'..watchIndex) end elseif watchIndex <= numBlocks then local used = handler.usedBlocks local free = handler.freeBlocks print('clean up dead quest block') if used[blockIndex] then used[blockIndex]:Hide() used[blockIndex]:ClearAllPoints() free[#free+1]= used[blockIndex] used[blockIndex] = nil end else print(' |cFFFF9900END|r @', blockIndex) break -- done with quest stuff end end handler.numWatched = numWatched handler.numBlocks = numBlocks handler.actualBlocks = actualBlocks handler:Report() if numBlocks >= 1 then previousBlock = nil tracker.height = trackerHeight else tracker.height = 0 end return tracker.numWatched, tracker.numAll end --- Updates the selected block frame to display the given info batch -- If `previousBlock` is set, it will attempt to anchor to that -- @param blockNum the ordered block to be updated, not a watchIndex value -- @param info the reference returned by the GetXInfo functions -- REMEMBER: t.info and questData[questID] are the same table mod.UpdateTrackerBlock = function (handler, blockIndex, info) local print = B.print('BlockParse') print(' Read list item |cFF00FFFF'..blockIndex..'|r') if not blockIndex or not info then return end local tracker = handler.Tracker local t = handler:GetBlock(blockIndex) t.handler = handler t.info = info t.mainStyle = 'Normal' t.subStyle = nil info.blockIndex = blockIndex if info.questID then handler.QuestBlock[info.questID] = t end if info.questLogIndex then handler.LogBlock[info.questLogIndex] = t end if info.watchIndex then handler.WatchBlock[info.watchIndex] = t end handler.BlockInfo[blockIndex] = info t.attachmentHeight = 0 --if info.isComplete then --t.status:Show() --t.status:SetText(info.completionText) --end if info.numObjectives >= 1 then t.attachmentHeight = 0 t.status:Show() print(' lines to build:', info.numObjectives) local text = '' mod.UpdateObjectives(t, info, text) elseif info.description then t.status:SetText(info.description) else t.status:SetText(nil) end t.title:SetText(info.title) print(' ', t.status:CanWordWrap(), t.status:GetStringHeight()) if info.specialItem and not info.itemButton then print(' - |cFF00FFFFgenerating item button for info set') info.itemButton = mod.SetItemButton(t, info) else --info.itemButton = nil end handler.SetBlockTags(t, info) if previousBlock then t:SetPoint('TOPLEFT', previousBlock, 'BOTTOMLEFT', 0, 0) t:SetPoint('RIGHT', tracker,'RIGHT', 0, 0) print(' anchor to|cFF0088FF', previousBlock:GetName()) end --- metrics are calculated in SetStyle t:SetStyle('TrackerBlock', handler.name, t.mainStyle, t.subStyle) t:Show() print(' |cFF00FFFF)|r -> ', t, t:GetHeight()) if info.rewardInfo then print('has immediate reward') if info.rewardInfo[1].type == 'currency' or info.rewardInfo[1].type == 'item' then t.icon:Show() t.iconLabel:SetText(info.rewardInfo[1].count) t.icon:SetSize(t.height, t.height) t.icon:SetTexture(info.rewardInfo[1].texture) end else t.icon:Hide() end if Devian and Devian.InWorkspace() then t.debugText:Show() t.debugText:SetText(tostring(blockIndex) .. '\n' .. tostring(info.itemButton and info.itemButton:GetName()) .. "\n" .. (tostring(t.mainStyle) .. '/' .. tostring(t.subStyle))) end return t end mod.UpdateObjectives = function(block, info, text) local print = B.print('BlockLine') print(' |cFF00FF00objective updates for', block:GetName()) local attachmentHeight = block.attachmentHeight if info.description then print(' -- has description text:', select('#', info.description), info.description) text = info.description end local completionScore, completionMax = 0, 0 for i, line in ipairs(info.objectives) do print(' |cFF88FF00objective', i) block.handler.ParseObjective(line, info) if line.title then info.title = line.title line.title = nil end if line.widget then if attachmentHeight == 0 then attachmentHeight = block.status.spacing end line.widget:Show() line.widget:SetParent(block) line.widget:SetPoint('TOPLEFT', block.status, 'BOTTOMLEFT', 0, -attachmentHeight ) print(' has a widget, height is', line.widget.height) attachmentHeight = attachmentHeight + line.widget.height completionScore = completionScore + line.progress completionMax = completionMax + 2 end if line.displayText then print(' has text') text = text .. ((text == '') and "" or "\n") .. '|cFF'..line.displayColor.. line.displayText .. '|r' end end block.completionScore = completionScore / completionMax block.attachmentHeight = attachmentHeight block.status:SetText(text) block.status:SetWordWrap(true) end --- Objective parsers -- defines the following variables -- * height - height of whatever display widget is involved in conveying the task -- * lines - number of non-wrapped text lines to account for line space; may be discarded depending on things -- * money - boolean that determines listening for money events or not -- * progress - number ranging 0 to 2 indicating none/partial/full completion respectively mod.Tracker.ParseObjective = function(line, info) if line.finished then line.progress = 2 elseif line.quantity > 0 then line.progress = 1 else line.progress = 0 end end Bonus.ParseObjective = function(line, info) local print = B.print('BonusLine') line.displayColor = 'FFFFFF' if line.text and not info.title then line.title = line.text else line.displayText = line.text end line.progress = 0 print(' ', line.index,'|cFFFF0088-|r', line.objectiveType, line.text) if line.objectiveType == 'progressbar' then line.widgetType = 'ProgressBar' print(' |cFFFF44DDpercent='..tostring(GetQuestProgressBarPercent(info.questID))) line.value = GetQuestProgressBarPercent(info.questID) or 0 line.maxValue = 100 if line.value >= line.maxValue then line.progress = 1 elseif line.value > 0 then line.progress = 2 end line.format = PERCENTAGE_STRING line.widget = mod.SetWidget(line, info, 'ProgressBar', info.questID..'-'..line.index) print(' ** text:', line.text, 'value:', line.value, 'max:', line.maxValue) else line.widget = nil end end Cheevs.ParseObjective = function(line, info) local print = B.print('CheevsLine') line.progress = 0 if line.flags then if band(line.flags, 0x00000001) > 0 then line.format = "%d/%d" line.widget = mod.SetWidget(line, info, 'ProgressBar', line.criteriaID) elseif band(line.flags, 0x00000002) then line.widget = nil else line.widget = nil line.displayColor = 'FFFFFF' line.displayText = line.text end end print('line.type =', line.type) print(' ** qtyStr:', line.quantityString, 'qty:', line.quantity, 'assetID:', line.assetID) end Quest.ParseObjective = function(line) local print = B.print('QuestLine') print(' |cFFFF0088', line.type) local color = '00FFFF' line.progress = 0 if line.finished then line.progress = 2 color = 'FFFFFF' elseif line.type == 'monster' then color = 'FFFF00' elseif line.type == 'item' then color = '44DDFF' elseif line.type == 'object' then color = 'FF44DD' end line.displayColor = color line.displayText = line.text end mod.Quest.numButtons = 0 local usedButtons = mod.Quest.itemButtons local freeButtons = mod.Quest.freeButtons mod.UpdateWrapper = function(reason) print('|cFF00FFFFUpdateWrapper:|r', reason) unitLevel = UnitLevel('player') wrapperWidth = mod.Conf.Wrapper.WrapperWidth scrollWidth = mod.Conf.Wrapper.WrapperWidth local wrapperBlocks = 0 -- Update scroll child vertical size scrollHeight = 0 for i, handler in ipairs(orderedHandlers) do mod.UpdateTracker(handler) local tracker = handler.Tracker if handler.actualBlocks >= 1 then tracker:SetParent(Scroll) tracker:SetPoint('TOPLEFT', Scroll, 'TOPLEFT', 0, - scrollHeight) tracker:SetSize(wrapperWidth, tracker.height) print('|cFF00FFFF'..tracker:GetName()..'|r h:|cFF00FF00', tracker.height, '|r y:|cFF00FF00', -scrollHeight) scrollHeight = scrollHeight + tracker.height tracker:Show() else tracker:Hide() end wrapperBlocks = wrapperBlocks + handler.actualBlocks end print('final scrollHeight:', scrollHeight) -- Update frame dimensions if scrollHeight > wrapperMaxHeight then print(' is larger than', wrapperMaxHeight) wrapperHeight = wrapperMaxHeight else wrapperHeight = scrollHeight B.Conf.ObjectiveScroll = 0 end scrollWidth = floor(scrollWidth+.5) scrollHeight = floor(scrollHeight+.5) wrapperWidth = floor(wrapperWidth+.5) wrapperHeight = floor(wrapperHeight+.5) headerHeight = floor(headerHeight+.5) if wrapperBlocks >= 1 then for i, region in ipairs(Wrapper.headerComplex) do region:Show() end else for i, region in ipairs(Wrapper.headerComplex) do region:Hide() end return end --[[wrapperHeight = scrollHeight print('|cFFFFFF00params:|r scroller:', scrollWidth .. ',' .. scrollHeight, 'scroll:', scrollWidth .. ',' .. scrollHeight, 'wrapper:', wrapperWidth .. ',' .. wrapperHeight, 'header:', headerHeight)]] --Scroller:SetSize(wrapperWidth, wrapperHeight) Scroller:SetPoint('TOPLEFT', Wrapper, 'TOPLEFT', 0, 0) Scroller:SetPoint('BOTTOMRIGHT', Wrapper, 'BOTTOMRIGHT') Scroll:SetSize(scrollWidth, scrollHeight) Scroll:SetPoint('TOPLEFT', Scroller, 'TOPLEFT', 0, B.Conf.ObjectiveScroll or 0) Scroll:SetPoint('RIGHT', Scroller, 'RIGHT') --Scroller:UpdateScrollChildRect() Wrapper:SetSize(wrapperWidth, wrapperHeight) --[[ update action buttons print('|cFF00FF00'..Scroll:GetName()..'|r:', Scroll:GetWidth(), Scroll:GetHeight(), '|cFF00FF00'..Scroller:GetName()..'|r:', Scroller:GetWidth(), Scroller:GetHeight(), '|cFF00FF00'..Wrapper:GetName()..'|r:', Wrapper:GetWidth(), Wrapper:GetHeight(), '|cFF0088FFvScrollRange|r:', floor(Scroller:GetVerticalScrollRange()+.5) ) mod.UpdateActionButtons() --]] end --- Queue any active item buttons for update for that frame mod.UpdateActionButtons = function(updateReason) Scroller.snap_upper = 0 Scroller.snap_lower = 0 local print = B.print('ItemButton') if updateReason then print = B.print('IB_'..updateReason) end local previousItem for questID, itemButton in pairs(usedButtons) do local info= mod.Quest.Info[questID] print('|cFF00FFFF'.. questID .. '|r', itemButton:GetName()) local block = mod.Quest.QuestBlock[questID] if block then -- Dispatch the probe if IsQuestWatched(info.questLogIndex) then itemButton.previousItem = previousItem print(' |cFFFFFF00probing', block:GetName()) block:SetScript('OnUpdate', function() if block:GetBottom() and not InCombatLockdown() then print(' '..block:GetName()..' |cFF00FF00probe hit!') mod.UpdateBlockAction(block, itemButton, itemButton.previousItem) -- needs to be previousItem from this scope block:SetScript('OnUpdate', nil) end end) previousItem = itemButton else print('hidden block or unwatched quest') itemButton.previousItem = nil itemButton:Hide() end elseif itemButton:IsVisible() then print(' |cFFFF0088hiding unwatched quest button', itemButton:GetName()) itemButton.previousItem = nil itemButton:Hide() else print(' |cFFBBBBBBignoring hidden log quest button', itemButton:GetName()) end end end mod.UpdateBlockAction = function (block, itemButton) print('**|cFF0088FF'..itemButton:GetName(), '|r:Update()') if itemButton.questID ~= block.info.questID then print('** |cFFFF0088mismatched block assignment', itemButton.questID,'<~>', block.info.questID) -- something happened between this and last frame, go back and set new probes return mod.UpdateActionButtons() end local previousItem = itemButton.previousItem local upper_bound = Scroller:GetTop() + Scroller.snap_upper local lower_bound = Scroller:GetBottom() + Scroller.snap_lower + itemButtonSize local point, anchor, relative if block:GetBottom() < lower_bound then print('** ',block:GetName() ,'|cFFFFFF00bottom =', floor(block:GetBottom()+.5), 'threschold =', floor(lower_bound+.5)) if previousItem then print('adjusting', previousItem:GetName()) previousItem:ClearAllPoints() previousItem:SetPoint('BOTTOM', itemButton, 'TOP', 0, itemButtonSpacing) end itemButton:ClearAllPoints() itemButton.x = Wrapper:GetLeft() -4 itemButton.y = Wrapper:GetBottom() point, anchor, relative = 'BOTTOMRIGHT', UIParent, 'BOTTOMLEFT' Scroller.snap_lower = Scroller.snap_lower + itemButtonSize + itemButtonSpacing elseif block:GetTop() > upper_bound then print('** ',block:GetName() ,'|cFFFFFF00top =', floor(block:GetTop()+.5), 'threschold =', floor(upper_bound+.5)) itemButton:ClearAllPoints() if previousItem then print('latch onto another piece') point, anchor, relative ='TOP', previousItem, 'BOTTOM' itemButton.x = 0 itemButton.y = -itemButtonSpacing else print('latch at corner', Scroller:GetLeft() -itemButtonSpacing, Scroller:GetTop()) point, anchor, relative = 'TOPRIGHT', UIParent, 'BOTTOMLEFT' itemButton.x = Scroller:GetLeft() -4 itemButton.y = Scroller:GetTop() end itemButton:Show() Scroller.snap_upper = Scroller.snap_upper - (itemButtonSize + itemButtonSpacing) else print('** ',block:GetName() ,'|cFF00FF00span =', floor(block:GetBottom()+.5), floor(block:GetTop()+.5), 'threschold =', floor(lower_bound+.5)) itemButton:ClearAllPoints() itemButton.x = block:GetLeft() - itemButtonSpacing itemButton.y = block:GetTop() point, anchor, relative = 'TOPRIGHT', UIParent, 'BOTTOMLEFT' end itemButton:SetPoint(point, anchor, relative, itemButton.x, itemButton.y) itemButton:Show() end mod.UpdateItemButtonCooldown = function(button) end