Mercurial > wow > buffalo2
diff ObjectiveTracker/ObjectiveCore.lua @ 23:e837384ac363
Separating objective tracker module
author | Nenue |
---|---|
date | Sun, 10 Apr 2016 04:35:32 -0400 |
parents | ObjectiveCore.lua@9b3fa734abff |
children | 66b927b46776 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ObjectiveTracker/ObjectiveCore.lua Sun Apr 10 04:35:32 2016 -0400 @@ -0,0 +1,451 @@ +--- ${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 AddQuestWatch, SetSuperTrackedQuestID, GetNumQuestWatches, AUTO_QUEST_WATCH, MAX_WATCHABLE_QUESTS = AddQuestWatch, SetSuperTrackedQuestID, GetNumQuestWatches, AUTO_QUEST_WATCH, MAX_WATCHABLE_QUESTS +local QuestPOIUpdateIcons, GetCVar, IsPlayerInMicroDungeon, WorldMapFrame, GetCVarBool, SetMapToCurrentZone = QuestPOIUpdateIcons, GetCVar, IsPlayerInMicroDungeon, WorldMapFrame, GetCVarBool, SetMapToCurrentZone +local AddAutoQuestPopUp = AddAutoQuestPopUp +local mod = 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 + +--- Performance values +--[[ + self:RegisterEvent("QUEST_LOG_UPDATE"); + self:RegisterEvent("TRACKED_ACHIEVEMENT_LIST_CHANGED"); + self:RegisterEvent("QUEST_WATCH_LIST_CHANGED"); + self:RegisterEvent("QUEST_AUTOCOMPLETE"); + self:RegisterEvent("QUEST_ACCEPTED"); + self:RegisterEvent("SUPER_TRACKED_QUEST_CHANGED"); + self:RegisterEvent("SCENARIO_UPDATE"); + self:RegisterEvent("SCENARIO_CRITERIA_UPDATE"); + self:RegisterEvent("TRACKED_ACHIEVEMENT_UPDATE"); + self:RegisterEvent("ZONE_CHANGED_NEW_AREA"); + self:RegisterEvent("ZONE_CHANGED"); + self:RegisterEvent("QUEST_POI_UPDATE"); + self:RegisterEvent("VARIABLES_LOADED"); + self:RegisterEvent("QUEST_TURNED_IN"); + self:RegisterEvent("PLAYER_MONEY"); + ]] + + +--- 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 +mod.watchMoneyReasons = 0 + +--- Baseline defaults table; values defined in the files that they pertain to +mod.defaults = {} + +--- Tracker display order +mod.orderedNames = {'Bonus', 'AutoQuest', 'Quest', 'Cheevs'} + +--- ipairs() argument tables +mod.orderedHandlers = setmetatable({}, {__mode = "k"}) +mod.orderedTrackers = setmetatable({}, {__mode = "k"}) +mod.indexedTrackers = setmetatable({}, {__mode = "k"}) + +--- pairs() argument tables +mod.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 + +mod.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, + TitleSpacing = 3, +} + + + +--- Tracker module definitions begin here; innards dealing with data retreival and output are defined further in +mod.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 + + freeBlocks = {}, --- block heap + usedBlocks = {}, + + Info = {}, -- find data by ID + BlockInfo = {}, -- find data by block ID + Watched = {}, -- find watchIndex by data ID + WatchInfo = {}, -- find data by watch index + WatchBlock = {}, -- find block by watch index +} + +mod.AutoQuest = { + name = "AutoQuest", + displayName = "Notice", + updateReasonModule = OBJECTIVE_TRACKER_UPDATE_MODULE_QUEST, + updateReasonEvents = OBJECTIVE_TRACKER_UPDATE_QUEST + + OBJECTIVE_TRACKER_UPDATE_QUEST_ADDED, +} +mod.Quest = { + name = "Quest", + displayName = "Quests", + updateReasonModule = OBJECTIVE_TRACKER_UPDATE_MODULE_QUEST, + updateReasonEvents = OBJECTIVE_TRACKER_UPDATE_QUEST + + OBJECTIVE_TRACKER_UPDATE_QUEST_ADDED, +} +mod.Cheevs = { + name = "Cheevs", + displayName = "Achievements", + updateReasonModule = OBJECTIVE_TRACKER_UPDATE_MODULE_ACHIEVEMENT, + updateReasonEvents = OBJECTIVE_TRACKER_UPDATE_ACHIEVEMENT + + OBJECTIVE_TRACKER_UPDATE_ACHIEVEMENT_ADDED, +} +mod.Bonus = { + name = "Bonus", + displayName = "Bonus Objectives", + updateReasonModule = OBJECTIVE_TRACKER_UPDATE_MODULE_BONUS_OBJECTIVE, + updateReasonEvents = OBJECTIVE_TRACKER_UPDATE_QUEST + OBJECTIVE_TRACKER_UPDATE_TASK_ADDED +} + +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) + print('Initializing |cFF00FFFF'..name..'|r module...') + + local handler = setmetatable(mod[name] or {}, { + __tostring = Tracker_string, + __call = Tracker_call + }) + if type(mod.orderedHandlers[index]) == 'table' then + return mod.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 + + mod[name] = handler + + local trackerName = 'Veneer'..name..'Tracker' + local handler = mod[name] + local frame = CreateFrame('Frame', trackerName, _G.VeneerObjectiveScroll, 'VeneerTrackerTemplate') + frame.title:SetText(handler.displayName) + mod.SetBlockStyle(frame, 'Tracker', 'Normal') + handler.frame = frame + handler.trackerName = trackerName + handler.lines = {} + mod.orderedTrackers[index] = frame + mod.namedTrackers[name] = frame + mod.indexedTrackers[handler] = frame + print('|cFFFF0088' .. trackerName .. '|r created for |cFF00FFFF' .. handler.displayName .. '|r module') + + mod.orderedHandlers[index] = handler + return true +end + +local Event = {} +Event.QUEST_LOG_UPDATE = function() + return OBJECTIVE_TRACKER_UPDATE_MODULE_QUEST + OBJECTIVE_TRACKER_UPDATE_MODULE_BONUS_OBJECTIVE +end +Event.QUEST_ACCEPTED = function(questLogIndex, questID) + if ( IsQuestTask(questID) ) then + return OBJECTIVE_TRACKER_UPDATE_TASK_ADDED, questID + else + if ( AUTO_QUEST_WATCH == "1" and GetNumQuestWatches() < MAX_WATCHABLE_QUESTS ) then + AddQuestWatch(questLogIndex); + SetSuperTrackedQuestID(questID); + end + return OBJECTIVE_TRACKER_UPDATE_MODULE_QUEST + end +end + +Event.QUEST_WATCH_LIST_CHANGED = function(questID, added) + if ( added ) then + if ( not IsQuestTask(questID) ) then + return OBJECTIVE_TRACKER_UPDATE_QUEST_ADDED, questID, added + end + else + return OBJECTIVE_TRACKER_UPDATE_QUEST, questID, added + 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() + return OBJECTIVE_TRACKER_UPDATE_QUEST +end +Event.ZONE_CHANGED = function() + + local inMicroDungeon = IsPlayerInMicroDungeon(); + if ( inMicroDungeon ~= mod.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(); + mod.inMicroDungeon = inMicroDungeon; + end +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) + if ( added ) then + return OBJECTIVE_TRACKER_UPDATE_ACHIEVEMENT_ADDED, achievementID + else + return OBJECTIVE_TRACKER_UPDATE_ACHIEVEMENT + end +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(); + mod.currentZoneArea = GetCurrentMapAreaID() + print('Updating zone ID to', mod.currentZoneArea, '=', GetZoneText(), GetMinimapZoneText()) + + + return OBJECTIVE_TRACKER_UPDATE_TASK_ADDED +end + + +Event.PLAYER_MONEY = function() + if mod.watchMoneyReasons > 0 then + return mod.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 + mod.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 +mod.Event = Event + +--- Done once per ui load +local BlizzHooks = { + ['AddQuestWatch'] = 'AddQuestWatch', + ['RemoveQuestWatch'] = 'RemoveQuestWatch', + ['AbandonQuest'] = 'AbandonQuest', + ['AcknowledgeAutoAcceptQuest'] = 'AcknowledgeAutoAcceptQuest', + ['AddAutoQuestPopUp'] = 'AddAutoQuestPopUp', + ['RemoveAutoQuestPopUp'] = 'RemoveAutoQuestPopUp', + ['AddTrackedAchievement'] = 'AddTrackedAchievement', + ['RemoveTrackedAchievement'] = 'RemoveTrackedAchievement', + ['SetSuperTrackedQuestID'] = 'SetSuperTrackedQuestID' +} +local VeneerData + +mod.SetWatchMoney = function(watchMoney, reason) + if watchMoney then + if band(mod.watchMoneyReasons, reason) == 0 then + mod.watchMoneyReasons = mod.watchMoneyReasons + reason; + end + else + if band(mod.watchMoneyReasons, reason) > 0 then + mod.watchMoneyReasons = mod.watchMoneyReasons - reason; + end + end +end +mod.animateReasons = 0 +mod.SetAnimate = function(animate, reason) + if animate then + if band(mod.animateReasons, reason) == 0 then + mod.animateReasons = mod.animateReasons + reason + end + else + if band(mod.animateReasons, reason) > 0 then + mod.animateReasons = mod.animateReasons - reason + end + end +end + + +function mod:OnInitialize() + local c = mod.Conf.Wrapper + VeneerData = _G.VeneerData + VeneerData.CallLog = VeneerData.CallLog or {} + if not mod.isHooked then + mod.isHooked = true + for blizzFunc, veneerFunc in pairs(BlizzHooks) do + if mod[veneerFunc] then + hooksecurefunc(blizzFunc, mod[veneerFunc]) + else + hooksecurefunc(blizzFunc, function(...) + print('|cFFFF0088securehook('..tostring(blizzFunc)..')|r args:', ...) + tinsert(VeneerData.CallLog, {blizzFunc, ...}) + end) + end + end + end + + mod.Conf.TasksLog = mod.Conf.TasksLog or {} + + Scroller:SetScrollChild(Scroll) + Scroller:SetWidth(c.Width) + Scroll:SetWidth(c.Width) + Scroll:ClearAllPoints() + Scroll:SetPoint('TOP', Scroller, 'TOP') + ObjectiveTrackerFrame:UnregisterAllEvents() + ObjectiveTrackerFrame:Hide() + + if B.Conf.FrameState[Wrapper:GetName()] == 0 then + Scroller:Hide() + end +end + +local Play = function(file) if Devian and Devian.InWorkspace() then PlaySoundFile(file) end end + +function mod:OnEvent (event, ...) + local isHandled + print('OnEvent(|cFF00FF00'.. event ..'|r):', ...) + 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](...) + elseif type(Event[event]) == 'table' then + Play([[Interface\Addons\SharedMedia_MyMedia\sound\Link.ogg]]) + for i, action in ipairs(Event[event]) do + if type(action) == 'function' then + reason, arg1, arg2, arg3 = action(event, ...) + else + reason = action + end + + if reason then + mod:Update(reason, arg1, arg2, arg3) + end + end + else + Play([[Interface\Addons\SharedMedia_MyMedia\sound\Heart.ogg]]) + reason = Event[event] + end + else + Play([[Interface\Addons\SharedMedia_MyMedia\sound\Quack.ogg]]) + end + if reason then + mod:Update(reason, arg1, arg2, arg3) + else + print('no reason value returned') + Play([[Interface\Addons\SharedMedia_MyMedia\sound\Quack.ogg]]) + end +end + +--- Done any time the the minimize button is toggled up +function mod:OnEnable() + for id, name in ipairs(mod.orderedNames) do + if not mod.orderedHandlers[id] then + Handler_Initialize(mod.DefaultHandler, name, id) + end + end + + for event, action in pairs(Event) do + print('|cFFFF0088listen to', event, 'for action|r', tostring(action)) + Wrapper:RegisterEvent(event) + end + + Wrapper:SetScript('OnEvent', mod.OnEvent) + local c = mod.Conf.Wrapper + Wrapper:SetWidth(c.Width) + + mod.InitializeWidgets() + mod:Update() + + +end + +function mod:OnDisable() + Wrapper:UnregisterAllEvents() +end + +