Mercurial > wow > buffalo2
diff ObjectiveTracker/ObjectiveTracker.lua @ 28:c33c17dd97e7
file renames
author | Nenue |
---|---|
date | Wed, 13 Apr 2016 20:19:37 -0400 |
parents | |
children | adcd7c328d07 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ObjectiveTracker/ObjectiveTracker.lua Wed Apr 13 20:19:37 2016 -0400 @@ -0,0 +1,507 @@ +--- ${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 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 +--[[ + 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 + +T.strings = {} +T.strings.CLICK_TO_ACCCEPT = 'Click to Accept' +T.strings.CLICK_TO_COMPLETE = 'Click to complete' +T.colors ={ + enable = true, + default = { + titlebg = {'HORIZONTAL', 1, 0, .7, .25, 1, 0, .7, .125}, + textbg = {'HORIZONTAL', 0, 0, 0, 0.4, 0, 0, 0, 0 }, + selectionbg = {'HORIZONTAL', 1, 1, 1, 0, 1, 1, 1, 0.225}, + }, + daily = { + titlebg = {'HORIZONTAL', 0, .7, 1, .25, 0, 1, .7, .125}, + textbg = {'HORIZONTAL', 0, .7, 1, .1, 0, 1, .7, .075 }, + }, + weekly = { + titlebg = {'HORIZONTAL', 0, .35, .7, .25, 0, .35, .7, .125}, + textbg = {'HORIZONTAL', 0, .35, .7, .1, 0, .35, .7, .075 }, + }, + account = { + titlebg = {'HORIZONTAL', .1, .1, .1, .25, .1, .1, .1, .125}, + textbg = {'HORIZONTAL', .1, .1, .1, 0.4, .1, .1, .1, .085 }, + }, + -- alliance + faction_1 = { + titlebg = {'HORIZONTAL', .2, .4, 1, 0.4, .2, .4, 1, .085 }, + textbg = {'HORIZONTAL', .2, .4, 1, 0.4, .2, .4, 1, .085 }, + }, + -- horde + faction_2 = { + titlebg = {'HORIZONTAL', .6, 0, 0.4, 0.4, .6, 0, 0.4, .085 }, + textbg = {'HORIZONTAL', .6, 0, 0.4, 0.4, .6, 0, 0.4, .085 }, + } +} + +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, + TitleSpacing = 3, +} + + + +--- 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 + + 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 +} + +T.AutoQuest = { + name = "AutoQuest", + displayName = "Notice", + updateReasonModule = OBJECTIVE_TRACKER_UPDATE_MODULE_QUEST, + updateReasonEvents = OBJECTIVE_TRACKER_UPDATE_QUEST + OBJECTIVE_TRACKER_UPDATE_QUEST_ADDED, +} +T.Quest = { + name = "Quest", + displayName = "Quests", + updateReasonModule = OBJECTIVE_TRACKER_UPDATE_MODULE_QUEST, + updateReasonEvents = OBJECTIVE_TRACKER_UPDATE_QUEST + OBJECTIVE_TRACKER_UPDATE_QUEST_ADDED, + itemButtons = {}, + freeButtons = {}, +} +T.Cheevs = { + name = "Cheevs", + displayName = "Achievements", + updateReasonModule = OBJECTIVE_TRACKER_UPDATE_MODULE_ACHIEVEMENT, + updateReasonEvents = OBJECTIVE_TRACKER_UPDATE_ACHIEVEMENT + + OBJECTIVE_TRACKER_UPDATE_ACHIEVEMENT_ADDED, +} +T.Bonus = { + name = "Bonus", + displayName = "Bonus Objectives", + updateReasonModule = OBJECTIVE_TRACKER_UPDATE_MODULE_BONUS_OBJECTIVE, + updateReasonEvents = OBJECTIVE_TRACKER_UPDATE_QUEST + OBJECTIVE_TRACKER_UPDATE_TASK_ADDED +} + +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 +} + +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) + handler.frame = frame + 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') + + T.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 ~= 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 +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(); + 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 + +--- 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 + +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 +T.animateReasons = 0 +T.SetAnimate = function(reason) + print('comparing', T.animateReasons, reason) + if animate then + if band(T.animateReasons, reason) == 0 then + T.animateReasons = T.animateReasons + reason + end + else + if band(T.animateReasons, reason) > 0 then + T.animateReasons = T.animateReasons - reason + end + end +end + +local Play = function(file) if Devian and Devian.InWorkspace() then PlaySoundFile(file) end end + +function T: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 + T: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 + T:Update(reason, arg1, arg2, arg3) + else + print('no reason value returned') + Play([[Interface\Addons\SharedMedia_MyMedia\sound\Quack.ogg]]) + end + +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 blizzFunc, veneerFunc in pairs(BlizzHooks) do + if T[veneerFunc] then + hooksecurefunc(blizzFunc, T[veneerFunc]) + else + hooksecurefunc(blizzFunc, function(...) + print('|cFFFF0088securehook('..tostring(blizzFunc)..')|r args:', ...) + tinsert(VeneerData.CallLog, {blizzFunc, ...}) + end) + end + end + end + + T.Conf.TasksLog = T.Conf.TasksLog or {} + + ObjectiveTrackerFrame:UnregisterAllEvents() + ObjectiveTrackerFrame: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) + if not B.Conf.VeneerObjectiveWrapper.enabled then + return + end + + 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 + + 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:GetName(), to, x,y) + + T:Update() + + -- run once to prime the data structure + T.UpdateActionButtons() +end + +function T:OnDisable() + self:UnregisterAllEvents() + Scroller:Hide() +end +