Mercurial > wow > buffalo2
view ObjectiveTracker/ObjectiveTracker.lua @ 44:756e8aeb040b
- Default.lua
- simplified the response to SuperTrackedQuestID changes
- tag icons work again
author | Nenue |
---|---|
date | Mon, 25 Apr 2016 19:37:13 -0400 |
parents | 03ed70f846de |
children | dd1ae565f559 |
line wrap: on
line source
--- ${PACKAGE_NAME} -- @file-author@ -- @project-revision@ @project-hash@ -- @file-revision@ @file-hash@ -- Created: 3/26/2016 1:51 AM local B, _G = select(2,...).frame, _G local pairs, setmetatable, type, tostring, band, format = _G.pairs, _G.setmetatable, _G.type, _G.tostring, bit.band, string.format local ipairs, tinsert, hooksecurefunc = _G.ipairs, _G.tinsert, _G.hooksecurefunc local PlaySoundFile, IsQuestTask, SortQuestWatches, GetCurrentMapAreaID, GetZoneText, GetMinimapZoneText = PlaySoundFile, IsQuestTask, SortQuestWatches, GetCurrentMapAreaID, GetZoneText, GetMinimapZoneText local QuestPOIUpdateIcons, GetCVar, IsPlayerInMicroDungeon, WorldMapFrame, GetCVarBool, SetMapToCurrentZone = QuestPOIUpdateIcons, GetCVar, IsPlayerInMicroDungeon, WorldMapFrame, GetCVarBool, SetMapToCurrentZone local AddAutoQuestPopUp = AddAutoQuestPopUp local T = B:RegisterModule("ObjectiveTracker", _G.VeneerObjectiveWrapper, 'BuffFrame') local print = B.print('Objectives') local ObjectiveTrackerFrame, VeneerObjectiveScroll, CreateFrame = _G.ObjectiveTrackerFrame, _G.VeneerObjectiveScroll, _G.CreateFrame local Wrapper = _G.VeneerObjectiveWrapper local Scroller = VeneerObjectiveWrapper.scrollArea local Scroll = _G.VeneerObjectiveScroll local unitLevel = UnitLevel('player') --- Performance values --- Done once per ui load local BlizzHooks = { 'AcceptQuest', 'AddQuestWatch', 'RemoveQuestWatch', 'AbandonQuest', 'AcknowledgeAutoAcceptQuest', 'AddAutoQuestPopUp', 'RemoveAutoQuestPopUp', 'AddTrackedAchievement', 'RemoveTrackedAchievement', 'SetSuperTrackedQuestID', 'SelectQuestLogEntry', } local enabledOnly = { ['AddQuestWatch'] = true, } --- These are the bitfields used by Blizzard_ObjectiveTracker to determine which segments get parsed. --- They are replicated here so that plugins can make use of any securehook args involving this info. local OBJECTIVE_TRACKER_UPDATE_MODULE_QUEST = OBJECTIVE_TRACKER_UPDATE_MODULE_QUEST -- 0x0100 local OBJECTIVE_TRACKER_UPDATE_MODULE_AUTO_QUEST_POPUP = OBJECTIVE_TRACKER_UPDATE_MODULE_AUTO_QUEST_POPUP -- 0x0200 local OBJECTIVE_TRACKER_UPDATE_MODULE_BONUS_OBJECTIVE = OBJECTIVE_TRACKER_UPDATE_MODULE_BONUS_OBJECTIVE -- 0x0400 local OBJECTIVE_TRACKER_UPDATE_MODULE_SCENARIO = OBJECTIVE_TRACKER_UPDATE_MODULE_SCENARIO -- 0x0800 local OBJECTIVE_TRACKER_UPDATE_MODULE_ACHIEVEMENT = OBJECTIVE_TRACKER_UPDATE_MODULE_ACHIEVEMENT -- 0x1000 local OBJECTIVE_TRACKER_UPDATE_STATIC = OBJECTIVE_TRACKER_UPDATE_STATIC -- 0x0000 local OBJECTIVE_TRACKER_UPDATE_ALL = OBJECTIVE_TRACKER_UPDATE_ALL -- 0xFFFF local OBJECTIVE_TRACKER_UPDATE_ID = OBJECTIVE_TRACKER_UPDATE_ID -- 0 local OBJECTIVE_TRACKER_UPDATE_QUEST = OBJECTIVE_TRACKER_UPDATE_QUEST -- 0x0001 local OBJECTIVE_TRACKER_UPDATE_QUEST_ADDED = OBJECTIVE_TRACKER_UPDATE_QUEST_ADDED -- 0x0002 local OBJECTIVE_TRACKER_UPDATE_TASK_ADDED = OBJECTIVE_TRACKER_UPDATE_TASK_ADDED -- 0x0004 local OBJECTIVE_TRACKER_UPDATE_SCENARIO = OBJECTIVE_TRACKER_UPDATE_SCENARIO -- 0x0008 local OBJECTIVE_TRACKER_UPDATE_SCENARIO_NEW_STAGE = OBJECTIVE_TRACKER_UPDATE_SCENARIO_NEW_STAGE -- 0x0010 local OBJECTIVE_TRACKER_UPDATE_ACHIEVEMENT = OBJECTIVE_TRACKER_UPDATE_ACHIEVEMENT -- 0x0020 local OBJECTIVE_TRACKER_UPDATE_ACHIEVEMENT_ADDED = OBJECTIVE_TRACKER_UPDATE_ACHIEVEMENT_ADDED -- 0x0040 local OBJECTIVE_TRACKER_UPDATE_SCENARIO_BONUS_DELAYED = OBJECTIVE_TRACKER_UPDATE_SCENARIO_BONUS_DELAYED -- 0x0080 local OBJECTIVE_TRACKER_UPDATE_REASON = OBJECTIVE_TRACKER_UPDATE_ALL -- default --- Used to determine which trackers are listening for money events T.strings = {} T.strings.CLICK_TO_ACCCEPT = 'Click to Accept' T.strings.CLICK_TO_COMPLETE = 'Click to complete' T.colors ={ enable = true, } T.watchMoneyReasons = 0 --- Baseline defaults table; values defined in the files that they pertain to T.defaults = {} --- Tracker display order T.orderedNames = {'Bonus', 'AutoQuest', 'Quest', 'Cheevs'} --- ipairs() argument tables T.orderedHandlers = setmetatable({}, {__mode = "k"}) T.orderedTrackers = setmetatable({}, {__mode = "k"}) T.indexedTrackers = setmetatable({}, {__mode = "k"}) --- pairs() argument tables T.namedTrackers = setmetatable({}, {__mode = "k"}) local WRAPPER_ANCHOR_POINT = 'TOPRIGHT' local WRAPPER_OFFSET_X = 0 local WRAPPER_OFFSET_Y = -200 local WRAPPER_MAX_HEIGHT = 670 local WRAPPER_WIDTH = 280 local WRAPPER_HEADER_HEIGHT = 24 T.defaults.Wrapper = { AnchorPoint = WRAPPER_ANCHOR_POINT, OffsetX = WRAPPER_OFFSET_X, OffsetY = WRAPPER_OFFSET_Y, Height = WRAPPER_MAX_HEIGHT, Width = WRAPPER_WIDTH, HeaderHeight = WRAPPER_HEADER_HEIGHT, TextSpacing = 3, TextIndent = 4, TitleSpacing = 3, TitleIndent = 4, } --- Tracker module definitions begin here; innards dealing with data retreival and output are defined further in T.DefaultHandler = { previousHeight = 0, name = "temp", displayName = "temp", updateReasonModule = 0xFF00, updateReasonEvent = 0x00FF, numWatched = 0, --- number of entries being handled numBlocks = 0, --- number of blocks created actualBlocks = 0, --- number of blocks in use Info = {}, --- stored watch list information, keyed by whatever unique ID is involved for that tracker Watched = {}, --- stores whether the given unique ID is tracked freeBlocks = {}, --- blocks hidden due to list shrinkage usedBlocks = {}, --- block in use BlockInfo = {}, --- by block creation offset, used by framescript WatchList = {}, --- ordered manifest of watched items --- Indexes InfoBlock = {}, --- by unique ID LogBlock = {}, --- by API log offset, used by GetBlock if possible WatchBlock = {}, --- block by internal offset, used in GetBlock scope WatchInfo = {}, --- info by internal offset, used in Update scope } T.AutoQuest = { name = "AutoQuest", displayName = "Notice", updateReasonModule = OBJECTIVE_TRACKER_UPDATE_MODULE_QUEST, updateReasonEvents = OBJECTIVE_TRACKER_UPDATE_QUEST + OBJECTIVE_TRACKER_UPDATE_QUEST_ADDED, internalColor = '00FFFF', LogInfo = {}, QuestBlock = {}, } T.Quest = { name = "Quest", displayName = "Quests", updateReasonModule = OBJECTIVE_TRACKER_UPDATE_MODULE_QUEST, updateReasonEvents = OBJECTIVE_TRACKER_UPDATE_QUEST + OBJECTIVE_TRACKER_UPDATE_QUEST_ADDED, internalColor = '0088FF', itemButtons = {}, freeButtons = {}, LogInfo = {}, QuestBlock = {}, } T.Cheevs = { name = "Cheevs", displayName = "Achievements", schema = 'achievement', updateReasonModule = OBJECTIVE_TRACKER_UPDATE_MODULE_ACHIEVEMENT, updateReasonEvents = OBJECTIVE_TRACKER_UPDATE_ACHIEVEMENT + OBJECTIVE_TRACKER_UPDATE_ACHIEVEMENT_ADDED, internalColor = '00FF88', } T.Bonus = { name = "Bonus", displayName = "Bonus Objectives", updateReasonModule = OBJECTIVE_TRACKER_UPDATE_MODULE_BONUS_OBJECTIVE, updateReasonEvents = OBJECTIVE_TRACKER_UPDATE_QUEST + OBJECTIVE_TRACKER_UPDATE_TASK_ADDED, internalColor = '00FF00', QuestBlock = {}, } T.Scenario = { name = 'Scenario', displayName = 'Scenario Objectives', updateReasonModule = OBJECTIVE_TRACKER_UPDATE_MODULE_SCENARIO, updateReasonEvents = OBJECTIVE_TRACKER_UPDATE_SCENARIO_NEW_STAGE + OBJECTIVE_TRACKER_UPDATE_SCENARIO_BONUS_DELAYED, internalColor = '88FF00', } local lastLabel local Tracker_debug = function(handler, channel) local func = B.print(channel) local color = handler.internalColor return function(label, ...) if lastLabel == label then label = label:gsub('%a', ' ').. ' ' else lastLabel = label label = '|cFF'..color..label..':|r' end func(label, ...) end end local Tracker_string = function (self) return self.name end local Tracker_call = function (self, reason) self:Update(reason) end local Handler_Initialize = function (self, name, index) local c = T.Conf.Wrapper print('Initializing |cFF00FFFF'..name..'|r module...') local handler = setmetatable(T[name] or {}, { __tostring = Tracker_string, __call = Tracker_call }) if type(T.orderedHandlers[index]) == 'table' then return T.orderedHandlers[index] end print('|cFFFFFF00Acquiring locals') local preset = {} for k, _ in pairs(handler) do preset[k] = true end print('|cFFFF8800Inheriting') for k, v in pairs(self) do if not handler[k] then if type(v) == 'table' then -- assume all tables to be local data; don't inherit or ref handler[k] = {} else handler[k] = self[k] end print('copying', k) end end print('|cFFFF4400'..tostring(name)..'|r:') for k, v in pairs(handler) do print(format("%32s %8s %s", (preset[k] and '|cFFFFFFFF' or '|cFFFFFF00') .. k .. '|r', type(v), tostring(v))) end T[name] = handler local trackerName = 'Veneer'..name..'Tracker' local handler = T[name] local frame = CreateFrame('Frame', trackerName, _G.VeneerObjectiveScroll, 'VeneerTrackerTemplate') frame.title:SetText(handler.displayName) frame:SetWidth(c.Width) frame.previousOffset = 0 handler.frame = frame handler.numBlocks = 0 handler.actualBlocks = 0 handler.trackerName = trackerName handler.lines = {} T.orderedTrackers[index] = frame T.namedTrackers[name] = frame T.indexedTrackers[handler] = frame print('|cFFFF0088' .. trackerName .. '|r created for |cFF00FFFF' .. handler.displayName .. '|r module') handler.print = Tracker_debug(handler, 'Tracker') handler.lprint = Tracker_debug(handler, 'Line') handler.bprint = Tracker_debug(handler, 'Block') T.orderedHandlers[index] = handler return true end local Event = {} Event.QUEST_LOG_UPDATE = function() return OBJECTIVE_TRACKER_UPDATE_QUEST end local GetNumQuestWatches, AddQuestWatch, SetSuperTrackedQuestID = GetNumQuestWatches, AddQuestWatch, SetSuperTrackedQuestID Event.QUEST_ACCEPTED = function(questLogIndex, questID, added) if ( IsQuestTask(questID) ) then return OBJECTIVE_TRACKER_UPDATE_QUEST_ADDED + OBJECTIVE_TRACKER_UPDATE_TASK_ADDED, questID, added else return OBJECTIVE_TRACKER_UPDATE_QUEST_ADDED, questID, added end AddQuestWatch(questID) end Event.QUEST_WATCH_LIST_CHANGED = function(questID, added) if ( added == true ) then if ( not IsQuestTask(questID) ) then return OBJECTIVE_TRACKER_UPDATE_QUEST_ADDED, questID, added end elseif questID then return OBJECTIVE_TRACKER_UPDATE_QUEST_ADDED, questID, added else return OBJECTIVE_TRACKER_UPDATE_MODULE_QUEST end end Event.QUEST_POI_UPDATE = function() QuestPOIUpdateIcons(); if ( GetCVar("trackQuestSorting") == "proximity" ) then SortQuestWatches(); end return OBJECTIVE_TRACKER_UPDATE_ALL end Event.SUPER_TRACKED_QUEST_CHANGED = function(questID) --return OBJECTIVE_TRACKER_UPDATE_QUEST, questID end Event.ZONE_CHANGED = function() local inMicroDungeon = IsPlayerInMicroDungeon(); if ( inMicroDungeon ~= T.inMicroDungeon ) then if ( not WorldMapFrame:IsShown() and GetCVarBool("questPOI") ) then SetMapToCurrentZone(); -- update the zone to get the right POI numbers for the tracker end --SortQuestWatches(); T.inMicroDungeon = inMicroDungeon; end return OBJECTIVE_TRACKER_UPDATE_MODULE_BONUS_OBJECTIVE + OBJECTIVE_TRACKER_UPDATE_MODULE_SCENARIO end Event.QUEST_AUTOCOMPLETE = function(questId) AddAutoQuestPopUp(questId, "COMPLETE"); return OBJECTIVE_TRACKER_UPDATE_MODULE_QUEST + OBJECTIVE_TRACKER_UPDATE_MODULE_AUTO_QUEST_POPUP end Event.SCENARIO_CRITERIA_UPDATE = function() return OBJECTIVE_TRACKER_UPDATE_SCENARIO end Event.SCENARIO_UPDATE = function(newStage) if ( newStage ) then return OBJECTIVE_TRACKER_UPDATE_SCENARIO_NEW_STAGE else return OBJECTIVE_TRACKER_UPDATE_SCENARIO end end Event.TRACKED_ACHIEVEMENT_UPDATE = function() return OBJECTIVE_TRACKER_UPDATE_ACHIEVEMENT end Event.TRACKED_ACHIEVEMENT_LIST_CHANGED = function(achievementID, added) return OBJECTIVE_TRACKER_UPDATE_ACHIEVEMENT_ADDED, achievementID, added end Event.ZONE_CHANGED_NEW_AREA = function () if ( not WorldMapFrame:IsShown() and GetCVarBool("questPOI") ) then SetMapToCurrentZone(); -- update the zone to get the right POI numbers for the tracker end SortQuestWatches(); T.currentZoneArea = GetCurrentMapAreaID() print('Updating zone ID to', T.currentZoneArea, '=', GetZoneText(), GetMinimapZoneText()) return OBJECTIVE_TRACKER_UPDATE_TASK_ADDED end Event.PLAYER_MONEY = function() if T.watchMoneyReasons > 0 then return T.watchMoneyReasons end end Event.CRITERIA_COMPLETE = function() return OBJECTIVE_TRACKER_UPDATE_MODULE_BONUS_OBJECTIVE end Event.QUEST_TURN_IN = function(questID, xp, money) if ( IsQuestTask(questID) ) then T.Bonus:OnTurnIn(questID, xp, money) print('updating bonus modules (code', OBJECTIVE_TRACKER_UPDATE_MODULE_BONUS_OBJECTIVE, ',', questID, xp, money) return OBJECTIVE_TRACKER_UPDATE_MODULE_BONUS_OBJECTIVE, questID, xp, money else return OBJECTIVE_TRACKER_UPDATE_MODULE_QUEST, questID, xp, money end end T.Event = Event local VeneerData T.SetWatchMoney = function(watchMoney, reason) if watchMoney then if band(T.watchMoneyReasons, reason) == 0 then T.watchMoneyReasons = T.watchMoneyReasons + reason; end else if band(T.watchMoneyReasons, reason) > 0 then T.watchMoneyReasons = T.watchMoneyReasons - reason; end end end local iprint = B.print('Info') T.SetRewards = function(t, questID) local previousSelection = GetQuestLogSelection() SelectQuestLogEntry(GetQuestLogIndexByID(questID)) local numQuestChoices = GetNumQuestLogChoices(); local skillName, skillIcon, skillPoints = GetQuestLogRewardSkillPoints(); local xp = GetQuestLogRewardXP(); local playerTitle = GetQuestLogRewardTitle(); ProcessQuestLogRewardFactions(); local rewards = {} local texture, name, isTradeskillSpell, isSpellLearned, hideSpellLearnText, isBoostSpell, garrFollowerID = GetQuestLogRewardSpell(questID) if name then tinsert(rewards,{ type = 'spell', name = name, texture = texture, }) end if previousSelection then SelectQuestLogEntry(previousSelection) end t.numCurrencies = GetNumQuestLogRewardCurrencies(questID) for i = 1, t.numCurrencies do local name, texture, count = GetQuestLogRewardCurrencyInfo(i, questID) tinsert(rewards,{ type = 'currency', index = i, name = name, texture = texture, count = count }); end -- items t.numItems = GetNumQuestLogRewards(questID) for i = 1, t.numItems do local name, texture, count, quality, isUsable = GetQuestLogRewardInfo(i, questID) tinsert(rewards, { type = 'item', index = i , name = name, texture = texture, count = count, quality = quality, isUsable = isUsable }); end -- money local money = GetQuestLogRewardMoney(questID) if ( money > 0 ) then tinsert(rewards, { type = 'money', name = GetMoneyString(money), texture = "Interface\\Icons\\inv_misc_coin_01", count = 0, }); end if #rewards >= 1 then t.rewardInfo = rewards end end local Play = function(file) if Devian and Devian.InWorkspace() then PlaySoundFile(file) end end local tprint = B.print('Tracker') T.OnHookedFunc = function(name, ...) print('|cFFFF8800securehook:|r', name, '|cFF00FFFFargs:|r', ...) local updateReason, arg1, arg2, arg3 = T[name](...) if updateReason then print('|cFF00FFFFupdate reason:|r', updateReason, arg1, arg2, arg3) T:Update(updateReason, arg1, arg2, arg3) end end function T:OnEvent (event, ...) local isHandled local reason, arg1, arg2, arg3 if Event[event] then if type(Event[event]) == 'function' then Play([[Interface\Addons\SharedMedia_MyMedia\sound\Info.ogg]]) reason, arg1, arg2, arg3 = Event[event](...) else Play([[Interface\Addons\SharedMedia_MyMedia\sound\Heart.ogg]]) reason = Event[event] end else print('no event handler set for', event) Play([[Interface\Addons\SharedMedia_MyMedia\sound\IM.ogg]]) end if reason then tprint('OnEvent(|cFF00FF00'.. event ..'|r):', ...) T:Update(reason, arg1, arg2, arg3) else print('OnEvent(|cFFFF4400'.. event ..'|r):', ...) print('no detected reason') --Play([[Interface\Addons\SharedMedia_MyMedia\sound\Quack.ogg]]) end local args = (reason or '0') if arg1 then args = args .. ', ' .. tostring(arg1) end if arg2 then args = args .. ', ' .. tostring(arg2) end if arg3 then args = args .. ', ' .. tostring(arg3) end tprint('OnEvent(|cFF00FF00'.. event ..'|r):', ..., '|cFFFFFF00=> Update (|r', args,'|cFFFFFF00)|r') end function T:OnInitialize() local c = T.Conf.Wrapper VeneerData = _G.VeneerData VeneerData.CallLog = VeneerData.CallLog or {} if not T.isHooked then T.isHooked = true for _, func in ipairs(BlizzHooks) do if T[func] then hooksecurefunc(func, function(...) return T.OnHookedFunc(func, ...) end) else hooksecurefunc(func, function(...) print('|cFFFF0088securehook('..tostring(func)..')|r args:', ...) tinsert(VeneerData.CallLog, {func, ...}) end) end end end ObjectiveTrackerFrame:UnregisterAllEvents() ObjectiveTrackerFrame:Hide() _G.MinimapCluster:Hide() for id, name in ipairs(T.orderedNames) do if not T.orderedHandlers[id] then Handler_Initialize(T.DefaultHandler, name, id) end end self:SetSize(c.Width, 40) T.InitializeWidgets() end --- Done any time the the minimize button is toggled up function T:OnEnable() print(B.Conf.VeneerObjectiveWrapper.enabled) for event, action in pairs(Event) do print('|cFFFF0088listen to', event, 'for action|r', tostring(action)) Wrapper:RegisterEvent(event) end local c = T.Conf.Wrapper Wrapper.previousHeight = 0 Scroller:SetScrollChild(Scroll) Scroller:SetWidth(c.Width) Scroll:SetWidth(c.Width) Scroll:ClearAllPoints() Scroll:SetPoint('TOP', Scroller, 'TOP') self:SetScript('OnEvent', T.OnEvent) Scroller:Show() local from, target, to, x, y = Wrapper:GetPoint(1) print(from, target, to, x,y) T.UpdateSchema('tracker', 'default') -- run once to prime the data structure T.UpdateActionButtons() end function T:OnDisable() self:UnregisterAllEvents() Scroller:Hide() end