Mercurial > wow > worldplan
view WorldPlan.lua @ 43:77c2ffb5c7f5 v1.0-rc11
- Removed possible refresh loop occurring in non-BrokenIsle zones
author | Nenue |
---|---|
date | Sun, 25 Dec 2016 15:47:17 -0500 |
parents | 79e5e96e5f18 |
children | db570c6a0ffb |
line wrap: on
line source
-- WorldPlan.lua -- Created: 8/16/2016 8:19 AM -- %file-revision% local addonFileName, db = ... local print = DEVIAN_WORKSPACE and function(...) _G.print('WP', ...) end or function() end local WP_VERSION = "1.0" local tinsert, pairs, floor = tinsert, pairs, floor local tremove, ipairs, wipe, unpack = tremove, ipairs, wipe, unpack local select, type, tostring, tonumber = select, type, tostring, tonumber local ITEM_QUALITY_COLORS = ITEM_QUALITY_COLORS local BROKEN_ISLES_ID = 1007 local GetCurrentMapAreaID = GetCurrentMapAreaID local GetTime, IsLoggedIn = GetTime, IsLoggedIn -- Define tables here so the pointers match up WorldPlanCore = { defaults = {}, modules = {}, TaskQueue = {}, } WorldPlanQuestsMixin = { UsedPositions = {}, } WorldPlanPOIMixin = {} WorldPlanSummaryMixin = {} db.filtersDirty = true db.questsDirty = true db.OrderedModules = {} db.LoadedModules = {} db.UsedFilters = {} db.QuestsByZone = {} db.QuestsByID = {} db.TasksByID = {} db.FreePins = {} db.UsedPins = {} db.ReportChunks = {} -- default color templates db.DefaultType = { a = 1, r = 1, g = 1, b = 1, x = 0, y = 0, desaturated = true, pinMask = "Interface\\Minimap\\UI-Minimap-Background", rewardMask = "Interface\\Minimap\\UI-Minimap-Background", texture = "Interface\\BUTTONS\\YELLOWORANGE64", continent = { iconWidth = 14, borderWidth = 2, highlightWidth = 1, TagSize = 8, maxAlertLevel = 0, showNumber = true, numberFontObject = 'WorldPlanFont' }, zone = { iconWidth = 22, borderWidth = 3, highlightWidth = 2, TagSize = 12, maxAlertLevel = 3, showNumber = true, numberFontObject = 'WorldPlanNumberFontThin' }, minimized = { r = 0, g = 0, b = 0, a = 0.1, iconWidth = 8, borderWidth = 2, alpha = 0.5, highlightWidth = 0, maxAlertLevel = 0, NoIcon = true, TagSize = 8, TimeleftStage = 1, showNumber = false, alpha = 0.1, } } db.DefaultConfig = { ShowAllProfessionQuests = false, DisplayContinentSummary = true, DisplayContinentPins = true, NotifyWhenNewQuests = true, EnablePins = true, FadeWhileGrouped = false, FlightMapAlphaLimits = {1, 1, 1}, FlightMapScalingLimits = {1, 3, 1.5}, } -- tracking menu toggler local DropDown_OnClick = function(self) local key = self.value if key then if WorldPlanData[key] then WorldPlanData[key] = nil else WorldPlanData[key] = true end end _G.WorldPlan:Refresh() end function db.print(...) for i = 1, select('#', ...) do tinsert(db.ReportChunks, tostring(select(i, ...))) end end function WorldPlanCore:print(...) db.print(...) end function WorldPlanCore:AddHandler (frame) if not db.LoadedModules[frame] then print('|cFFFFFF00'..self:GetName()..':AddHandler()', frame:GetName(), self.initialized) db.LoadedModules[frame] = true tinsert(db.OrderedModules, frame) if frame.defaults then db.DefaultConfig[frame:GetName()] = frame.defaults end frame.GetTypeInfo = function(frame, typeID) return self:GetTypeInfo(frame, typeID) end frame.owningFrame = self else print('|cFFFF4400'..self:GetName()..':AddHandler()', frame:GetName()) end end function WorldPlanCore:OnLoad () self.Types = setmetatable({}, { __newindex = function(t, k, v) if type(v) == 'table' then print('adding owner', k) v = setmetatable(v, { __newindex = function(t2,k2,v2) if type(v2) == 'table' then --print('adding type', k2) v2 = setmetatable(v2, {__index = function(t3,k3) --print('##deferring to default key', k3) return db.DefaultType[k3] end}) end rawset(t2,k2,v2) end}) end rawset(t,k,v) end }) self.Types[self] = {} for index, color in pairs(ITEM_QUALITY_COLORS) do self:AddTypeInfo(self, index, { r = color.r, g = color.g, b = color.b, hex = color.hex, }) end db.print('v'..WP_VERSION) self:RegisterEvent("QUESTLINE_UPDATE") self:RegisterEvent("QUEST_LOG_UPDATE") self:RegisterEvent("WORLD_MAP_UPDATE") self:RegisterEvent("SPELLS_CHANGED") self:RegisterEvent('PLAYER_ENTERING_WORLD') self:RegisterEvent("WORLD_QUEST_COMPLETED_BY_SPELL") self:RegisterEvent("SUPER_TRACKED_QUEST_CHANGED") self:RegisterEvent("SKILL_LINES_CHANGED") self:RegisterEvent("ARTIFACT_XP_UPDATE") self:RegisterEvent("ADDON_LOADED") self:RegisterEvent("PLAYER_LOGIN") --self:SetParent(WorldMapFrame) end function WorldPlanCore:OnShow() --print(self:GetName()..':OnShow()') --hooksecurefunc(self, 'SetScript', function(...) self:print('|cFFFFFF00'..self:GetName()..':SetScript()|r', ...) end) end local BROKEN_ISLE_MAPS = { [1007] = true, -- Broken Isle [1014] = true, -- Dalaran [1021] = true, -- Broken Shoree [1024] = true, -- Highmountain [1015] = true, -- Azsuna [1017] = true, -- Azsuna [1018] = true, -- Val'Sharah [1033] = true, -- Suramar [1077] = true, -- Dreamgrove [1096] = true, -- Eye of Azshara [1080] = true, -- Thunder Totem [1072] = true, -- True Shot Lodge, } function WorldPlanCore:SetCurrentMap() local mapAreaID = GetCurrentMapAreaID() local isBrokenIsle = BROKEN_ISLE_MAPS[mapAreaID] db.currentMapID = mapAreaID db.isContinentMap = (mapAreaID == BROKEN_ISLES_ID) db.useContinentType = (WorldMapDetailFrame:GetScale() < 1) for _, module in ipairs(db.OrderedModules) do if module.OnMapInfo then print(' |cFF00FFFF'..module:GetName() .. ':OnMapInfo()|r') module:OnMapInfo(isBrokenIsle, mapAreaID) end end end function WorldPlanCore:OnEvent (event, ...) print('|cFF00FF88'..self:GetName().. ':OnEvent()|r', event, GetTime(), 'init:', self.initialized) if event == 'ADDON_LOADED' then if IsLoggedIn() and not self.initialized then self:Setup() end else if (event == 'WORLD_MAP_UPDATE') or (event == 'PLAYER_ENTERING_WORLD') or (event == 'PLAYER_LOGIN') then print('|cFFFF4400currentMapID =', db.currentMapID, ...) self:SetCurrentMap() end end end function WorldPlanCore:OnNext(func) tinsert(self.TaskQueue, func) --self:print('|cFF00FF00adding scheduled task #', #self.TaskQueue) end function WorldPlanCore:OnUpdate() if #self.TaskQueue >= 1 then local func = tremove(self.TaskQueue, 1) --self:print('|cFF00FF00running scheduled task #', #self.TaskQueue) func() end if self.isStale then -- these need to happen in load order for i, module in ipairs(db.OrderedModules) do if module:IsVisible() and module.isStale then print('|cFF00FF00internal '..module:GetName()..':Refresh()|r') module:Refresh() end end self.isStale = nil end if #db.ReportChunks >= 1 then DEFAULT_CHAT_FRAME:AddMessage("|cFF0088FF"..addonFileName.."|r: " .. table.concat(db.ReportChunks, ', ')) wipe(db.ReportChunks) end end function WorldPlanCore:Setup () print('|cFFFFFF00'..self:GetName()..':Setup()|r') if not WorldPlanData then WorldPlanData = {key = 0} end WorldPlanData.key = (WorldPlanData.key or 0) + 1 db.Config = WorldPlanData for k,v in pairs(db.DefaultConfig) do --[===[@non-debug@ if not db.Config[k] then db.Config[k] = v end --@end-non-debug@]===] --@debug@ db.Config[k] = v --@end-debug@ end db.currentMapID = GetCurrentMapAreaID() for i, module in ipairs(db.OrderedModules) do db.Config[module:GetName()] = db.Config[module:GetName()] or {} if module.Setup then module:Setup() end if not module.RegisterEvent then module.RegisterEvent = self.RegisterEvent end end self.initialized = true hooksecurefunc("UIDropDownMenu_Initialize", self.OnDropDownInitialize) hooksecurefunc("WorldMapTrackingOptionsDropDown_OnClick", function(button) print("|cFF0088FFWorldMapTrackingOptionsDropDown_OnClick|r") local value = button.value if (value == "worldQuestFilterOrderResources" or value == "worldQuestFilterArtifactPower" or value == "worldQuestFilterProfessionMaterials" or value == "worldQuestFilterGold" or value == "worldQuestFilterEquipment") then self:Refresh(true) end end) hooksecurefunc("WorldMapFrame_Update", function() print('|cFFFF4400WorldMapFrame_Update|r') for _,module in ipairs(db.OrderedModules) do if module.OnWorldMapFrameUpdate then print(' |cFFFF4400'..module:GetName()..'|r') module:OnWorldMapFrameUpdate() end end end) SLASH_WORLDPLAN1 = "/worldplan" SLASH_WORLDPLAN2 = "/wp" SlashCmdList.WORLDPLAN = function(args) local arg1, arg2, extraArgs = args:match("(%S+)%s*(%S*)%s*(.*)") if arg1 == 'wq' then if arg2 and WorldPlanQuests[arg2] then self:print('WorldPlanQuests:'..arg2..'()') WorldPlanQuests[arg2](WorldPlanQuests) elseif arg2 == 'flightscale' and extraArgs then local val1, val2, val3 = extraArgs:match("(%S+)%s*(%S*)%s*(%S*)") if tonumber(val1) and tonumber(val2) and tonumber(val3) then db.Config.FlightMapScalingLimits = {tonumber(val1), tonumber(val2), tonumber(val3)} self:print('FlightMapFrame scaling limits updated:', unpack(db.Config.FlightMapScalingLimits)) else self:print('FlightMapFrame scaling limits:', unpack(db.Config.FlightMapScalingLimits)) end elseif arg2 == 'flightalpha' and extraArgs then local val1, val2, val3 = extraArgs:match("(%S+)%s*(%S*)%s*(%S*)") if tonumber(val1) and tonumber(val2) and tonumber(val3) then db.Config.FlightMapAlphaLimits = {tonumber(val1), tonumber(val2), tonumber(val3)} self:print('FlightMapFrame alpha limits updated:', unpack(db.Config.FlightMapAlphaLimits)) else self:print('FlightMapFrame alpha limits:', unpack(db.Config.FlightMapAlphaLimits)) end else self:print('WorldPlanQuests:Refresh(true)') WorldPlanQuests:Refresh(true) end elseif arg1 == 'filter' then if arg2 and WorldPlanSummary[arg2] then self:print('WorldPlanSummary:'..arg2..'()') WorldPlanSummary[arg2](WorldPlanSummary) else self:print('WorldPlanSummary:Refresh(true)') WorldPlanSummary:Refresh(true) end else self:print('Refreshing data.') self:Refresh(true) end end end -- registers a template table function WorldPlanCore:AddTypeInfo(owner, id, info) self.Types[owner] = self.Types[owner] or {} self.Types[owner][id] = info print('Type('..owner:GetName()..')('..id..') = '.. tostring(info)) end -- recall a template table, with situational details filled in function WorldPlanCore:GetTypeInfo(owner, typeID) local info, extraInfo if not owner then --print('## deferring to default type list') else --print('## pulling for', owner:GetName(), 'id =', typeID) end owner = owner or self if (not typeID) or (not self.Types[owner][typeID]) then --print('## sending list default') info = db.DefaultType else --print('## sent list definition', typeID) info = self.Types[owner][typeID] end local subType = 'continent' if ( FlightMapFrame and FlightMapFrame:IsVisible() and FlightMapFrame:IsZoomedIn() ) or ( not db.isContinentMap ) or ( db.useContinentType == false ) then subType = 'zone' end return info, info[subType] or db.DefaultType[subType] end do local timeStates = { {maxSeconds = 60, r=1, g=0.25, b =0, format = function (minutes) return '|cFFFF4400'.. minutes .. 'm' end, }, {maxSeconds = 240, r=1, g=.5, b=0, format = function(minutes) return '|cFFFF4400'.. floor(minutes/60) .. 'h' end, }, {maxSeconds = 1440, r=1, g=1, b=0, format = function(minutes) return '|cFFFFFF00'.. floor(minutes/60) .. 'h' end, }, {maxSeconds = 10081, r=0, g=1, b=0, }, -- 7 days + 1 minute } -- Generates a timeleft string function WorldPlanCore:GetTimeInfo(timeLeft, limit) for index = 1, limit do local state = timeStates[index] if timeLeft <= state.maxSeconds then local text if state.format then text = state.format(timeLeft) end return text, index end end return nil, nil end end function WorldPlanCore:Refresh (forced) print('|cFFFFFF00'..self:GetName()..':Refresh()|r forced:', forced, 'init:', self.initialized) if not self.initialized then return end for i, module in ipairs(db.OrderedModules) do if module.Refresh then print('|cFF00FF00external '..module:GetName()..':Refresh()|r') module:Refresh(forced) end end self.isStale = nil end -- insert visual options into the tracking button menu WorldPlanCore.OnDropDownInitialize = function (self, callback, dropType) if self ~= WorldMapFrameDropDown then return end local config = WorldPlanData local info = UIDropDownMenu_CreateInfo() info.text = "" info.isTitle = true UIDropDownMenu_AddButton(info) info.text = "|cFF00AAFFWorldPlan|r" info.isTitle = true UIDropDownMenu_AddButton(info) info.isTitle = nil info.disabled = nil info.keepShownOnClick = true info.tooltipOnButton = 1 info.text = "Enable" info.isNotRadio = true info.value = "EnablePins" info.checked = config.EnablePins info.tooltipTitle = "Enable World Quest Overlays" info.tooltipText = "Toggle the detail layers here." info.func = DropDown_OnClick UIDropDownMenu_AddButton(info) info.text = "Display All Profession Quests" info.isNotRadio = true info.value = "ShowAllProfessionQuests" info.checked = config.ShowAllProfessionQuests info.tooltipTitle = "Hidden Quests" info.tooltipText = "Display work order and profession-related quests that are skipped by the default UI." info.func = DropDown_OnClick UIDropDownMenu_AddButton(info) info.text = "Show Continent Pins" info.isNotRadio = true info.value = "DisplayContinentPins" info.checked = config.DisplayContinentPins info.tooltipTitle = "Continent Pins" info.tooltipText = "Display quest pins on the continent map (may get cramped)." info.func = DropDown_OnClick UIDropDownMenu_AddButton(info) info.text = "Show Summary" info.isNotRadio = true info.value = "DisplayContinentSummary" info.tooltipTitle = "Summary Bar" info.tooltipText = "Display a summary of active world quests. Note: requires directly viewing Broken Isle and Dalaran maps to gain complete info." info.checked = config.DisplayContinentSummary info.func = DropDown_OnClick UIDropDownMenu_AddButton(info) info.text = "Nudge Pins" info.isNotRadio = true info.value = "NudgePins" info.tooltipTitle = "Pin Nudging" info.tooltipText = "Adjust the position of quest pins that overlap." info.checked = config.NudgePins info.func = DropDown_OnClick UIDropDownMenu_AddButton(info) info.text = "Fade Whiled Grouped" info.isNotRadio = true info.value = "FadeWhileGrouped" info.tooltipTitle = "Group Fade" info.tooltipText = "Reduce pin alpha when grouped, so player dots are easier to see." info.checked = config.FadeWhileGrouped info.func = DropDown_OnClick UIDropDownMenu_AddButton(info) end -------------------------------------------------------------------------------------------------------------------- ------------------- --%end-debug%