Nenue@33: -- WorldPlan Nenue@33: -- WorldQuests.lua Nenue@33: -- Created: 11/2/2016 3:40 PM Nenue@33: -- %file-revision% Nenue@72: Nenue@75: local print = DEVIAN_WORKSPACE and function(...) _G.print('WorldQuests', ...) end or nop Nenue@75: local rprint = DEVIAN_WORKSPACE and function(...) _G.print('WQRefresh', ...) end or nop Nenue@75: local qprint = DEVIAN_WORKSPACE and function(...) _G.print('POI', ...) end or nop Nenue@75: local wprint = DEVIAN_WORKSPACE and function(...) _G.print('WP', ...) end or nop Nenue@75: local mprint = DEVIAN_WORKSPACE and function(...) _G.print('Canvas', ...) end or nop Nenue@40: local _, db = ... Nenue@45: local Module = WorldPlanQuestsMixin Nenue@33: Nick@64: local _G = _G Nenue@72: local type, tostring, tonumber, pairs, ipairs = type, tostring, tonumber, pairs, ipairs Nenue@33: local MC_GetNumZones, MC_GetZoneInfo = C_MapCanvas.GetNumZones, C_MapCanvas.GetZoneInfo Nenue@33: local TQ_GetQuestsForPlayerByMapID = C_TaskQuest.GetQuestsForPlayerByMapID -- This function is not yet documented Nenue@33: local TQ_GetQuestZoneID = C_TaskQuest.GetQuestZoneID Nick@64: local TQ_IsActive = C_TaskQuest.IsActive Nenue@75: local TQ_RequestPreloadRewardData = C_TaskQuest.RequestPreloadRewardData Nick@64: local pairs, ipairs, tinsert, tremove, wipe = pairs, ipairs, tinsert, tremove, table.wipe Nick@64: local GetTaskInfo, GetTasksTable, HaveQuestData = GetTaskInfo, GetTasksTable, HaveQuestData Nick@64: local GetTime = GetTime Nenue@69: local SpellCanTargetQuest, IsQuestIDValidSpellTarget = SpellCanTargetQuest, IsQuestIDValidSpellTarget Nick@64: local tonumber, abs = tonumber, math.abs Nick@64: local GetQuestLogRewardInfo = GetQuestLogRewardInfo Nick@64: local GetCurrentMapAreaID, GetMapInfo, GetMapNameByID = GetCurrentMapAreaID, GetMapInfo, GetMapNameByID Nenue@72: local GetQuestBountyInfoForMapID, GetQuestLogTitle, GetQuestLogIndexByID, IsQuestComplete = GetQuestBountyInfoForMapID, GetQuestLogTitle, GetQuestLogIndexByID, IsQuestComplete Nenue@72: local IsQuestCriteriaForBounty = IsQuestCriteriaForBounty Nenue@33: Nenue@69: local ToggleButton = {} Nenue@69: local callbacks = {} Nenue@40: local PinBaseIndex = 1200 Nenue@33: local BROKEN_ISLES_ID, DALARAN_ID, AZSUNA_ID, VALSHARAH_ID, HIGHMOUNTAIN_ID, STORMHEIM_ID, SURAMAR_ID, EOA_ID = 1007, 1014, 1015,1018, 1024, 1017, 1033, 1096 Nenue@33: local WORLD_QUEST_MAPS = { [DALARAN_ID] = 'Dalaran70', [AZSUNA_ID] = 'Azsuna', [VALSHARAH_ID] = "Val'sharah", Nenue@33: [HIGHMOUNTAIN_ID] = 'Highmountain', [STORMHEIM_ID] = 'Stormheim', [SURAMAR_ID] = 'Suramar', [EOA_ID] = 'EyeOfAszhara', } Nenue@33: Nenue@33: local REWARD_CASH = WORLD_QUEST_REWARD_TYPE_FLAG_GOLD Nenue@33: local REWARD_ARTIFACT_POWER = WORLD_QUEST_REWARD_TYPE_FLAG_ARTIFACT_POWER Nenue@33: local REWARD_GEAR = WORLD_QUEST_REWARD_TYPE_FLAG_EQUIPMENT Nenue@33: local REWARD_CURRENCY = WORLD_QUEST_REWARD_TYPE_FLAG_ORDER_RESOURCES Nenue@33: local REWARD_REAGENT = WORLD_QUEST_REWARD_TYPE_FLAG_MATERIALS Nenue@72: local SCALE_FACTORS = { 0.25, 0.7, 1 } Nenue@33: Nenue@72: local BountyBoard = WorldMapFrame.UIElementsFrame.BountyBoard Nenue@72: local ActionButton = WorldMapFrame.UIElementsFrame.ActionButton Nenue@72: Nenue@75: local pinBaseIndex = 1500 Nenue@75: local overlayBaseIndex = 1580 Nenue@72: local layoutDirty = true Nenue@72: local bountiesDirty = true Nenue@69: local currentScale = WorldMapDetailFrame:GetScale() Nenue@69: local canTargetQuests Nenue@65: local numShown = 0 Nenue@65: local numLoaded = 0 Nenue@69: local isDataLoaded = true Nenue@69: local numOverlays = 1 Nenue@66: local scaleConstant = 1 Nenue@45: Module.TasksByID = {} Nenue@33: Nenue@33: --%debug% Nenue@33: local SetTimedCallbackForAllPins = function(seconds, callback) Nenue@33: C_Timer.After(seconds, function() Nenue@33: for id, pin in pairs(WorldPlanQuests.QuestsByID) do Nenue@33: callback(pin) Nenue@33: end Nenue@33: end) Nenue@33: end Nenue@33: Nenue@52: Nenue@45: function Module:Setup() Nenue@75: --print('|cFFFF4400'..self:GetName()..':Setup()') Nenue@33: for mapID, mapName in pairs(WORLD_QUEST_MAPS) do Nenue@40: db.QuestsByZone[mapID] = {} Nenue@33: end Nenue@69: for target, arg in pairs(callbacks) do Nenue@75: --print(type(target)) Nenue@69: if type(target) == 'table' then Nenue@71: local callerName = target:GetName() or tostring(target) Nenue@69: for name, method in pairs(arg) do Nenue@75: --print(callerName, arg) Nenue@69: hooksecurefunc(target, name, function(...) Nenue@71: self:OnSecureHook(callerName .. '.' .. name, method, ...) Nenue@69: end) Nenue@69: end Nenue@69: else Nenue@69: hooksecurefunc(target, function(...) Nenue@69: self:OnSecureHook(target, arg, ...) Nenue@69: end) Nenue@69: end Nenue@69: end Nenue@65: Nenue@65: self.Status = CreateFrame('Frame', nil, self) Nenue@75: self.Status:SetPoint('TOPLEFT', WorldMapFrame.UIElementsFrame, 'TOPLEFT', 0, 0) Nenue@75: self.Status:SetPoint('BOTTOMRIGHT', WorldMapFrame.UIElementsFrame, 'TOPRIGHT', 0, -4) Nenue@65: self.Status.t = self.Status:CreateTexture(nil, 'OVERLAY') Nenue@65: self.Status.b = self.Status:CreateTexture(nil, 'BACKGROUND') Nenue@65: self.Status.b:SetColorTexture(0,0,0,.25) Nenue@65: self.Status.b:SetAllPoints(self.Status) Nenue@65: self.Status.t:SetColorTexture(1,1,1,.5) Nenue@65: self.Status.t:SetPoint('TOP') Nenue@65: self.Status.t:SetPoint('BOTTOM') Nenue@65: self.Status.t:SetPoint('LEFT') Nenue@65: local translationEnd, translationStart Nenue@65: self.Status:SetScript('OnUpdate', function(status) Nenue@65: local translateTo Nenue@65: if numLoaded < numShown then Nenue@75: translateTo = (numLoaded/numShown) * status:GetWidth() Nenue@65: status.t:SetWidth(translateTo) Nenue@65: else Nenue@75: translateTo = status:GetWidth() Nenue@65: status.t:SetWidth(translateTo) Nenue@65: end Nenue@65: end) Nenue@67: Nenue@75: self:SetAllPoints(WorldMapFrame.UIElementsFrame) Nenue@67: for k,v in pairs( ToggleButton) do Nenue@67: self.Toggle:SetScript(k,v) Nenue@67: end Nenue@72: Nenue@72: self:UpdateBounties('SETUP') Nenue@72: Nenue@67: self:Show() Nenue@67: end Nenue@69: callbacks.ClickWorldMapActionButton = function(WorldQuests) Nenue@73: WorldQuests:Refresh('CLICK_MAP_ACTION_BUTTON') Nenue@69: end Nenue@69: callbacks.WorldMap_UpdateQuestBonusObjectives = function(WorldQuests) Nenue@73: WorldQuests:UpdateTaskPOIs() Nenue@69: end Nenue@69: callbacks.WorldMapFrame_UpdateMap = function(WorldQuests) Nenue@75: WorldQuests:RefreshIfChanged('WMF_UPDATE') Nenue@69: end Nenue@69: callbacks.WorldMapScrollFrame_ReanchorQuestPOIs = function (WorldQuests) Nenue@75: WorldQuests:RefreshIfChanged('WMF_REANCHOR') Nenue@69: end Nenue@69: Nenue@72: callbacks[BountyBoard] = {} Nenue@72: callbacks[BountyBoard].SetSelectedBountyIndex = function(WorldQuests) Nenue@72: WorldQuests:UpdateBounties('BOUNTY_SELECTED') Nenue@73: WorldQuests:Refresh('BOUNTY_SELECTED') Nenue@72: end Nenue@67: Nenue@72: callbacks[ActionButton] = {} Nenue@72: callbacks[ActionButton].UpdateCastingState = function(WorldQuests) Nenue@73: WorldQuests:Refresh('CASTING_STATE_CHANGED') Nenue@67: end Nenue@67: Nenue@49: function Module:OnConfigUpdate() Nenue@75: --print('|cFFFFFF00OnConfigUpdate()|r') Nenue@49: if db.Config.FadeWhileGrouped then Nenue@49: db.PinAlpha = 0.15 Nenue@49: else Nenue@49: db.PinAlpha = 1 Nenue@49: end Nenue@67: Nenue@67: if not db.Config.EnablePins then Nenue@67: for _, pin in pairs(db.QuestsByID) do Nenue@67: pin:SetShown(false) Nenue@67: end Nenue@67: end Nenue@67: Nenue@67: ToggleButton.OnShow(self.Toggle) Nenue@49: end Nenue@49: Nenue@45: local InternalHideButton = function(button, index) Nenue@45: button:Hide() Nenue@45: end Nenue@45: local InternalShowButton = function(button, index) Nenue@45: button:Show() Nenue@45: end Nenue@33: Nenue@69: function Module:OnSecureHook(callbackName, func, ...) Nenue@75: --rprint('|cFFFF4400'..callbackName..'|r', ...) Nenue@69: func(self, ...) Nenue@45: end Nenue@40: Nenue@33: local defaults = {} Nenue@40: local REWARD_UNKNOWN = 768 Nenue@45: function Module:OnLoad() Nenue@75: --print('|cFFFF4400'..self:GetName()..':OnLoad()') Nenue@33: Nenue@75: self:SetParent(WorldMapFrame.UIElementsFrame) Nenue@33: WorldPlan:AddHandler(self, defaults) Nenue@33: Nenue@33: for areaID, fileName in pairs(WORLD_QUEST_MAPS) do Nenue@40: db.QuestsByZone[areaID] = {} Nenue@33: end Nenue@33: Nenue@41: -- WORLD_MAP_UPDATE and PLAYER_ENTERING_WORLD are passed down from a higher level Nenue@33: self:RegisterEvent('WORLD_QUEST_COMPLETED_BY_SPELL') Nenue@55: self:RegisterEvent('SUPER_TRACKED_QUEST_CHANGED') Nenue@33: self:RegisterEvent('SKILL_LINES_CHANGED') Nenue@75: --self:RegisterEvent('CURRENT_SPELL_CAST_CHANGED') Nenue@69: self:RegisterEvent('ARTIFACT_UPDATE') Nenue@73: self:RegisterEvent('QUEST_LOG_UPDATE') Nenue@33: end Nenue@33: Nenue@72: local artifactKnowledgeMultiplier Nenue@65: local superTrackedQuestID Nenue@45: function Module:OnEvent (event, ...) Nenue@40: Nenue@75: print('|cFFFFFF00OnEvent() '..event..'|r', GetTime(), ...) Nenue@69: if (event == 'QUEST_LOG_UPDATE') then Nenue@73: self:UpdateBounties(event) Nenue@33: elseif event == 'WORLD_QUEST_COMPLETED_BY_SPELL' then Nenue@33: local questID = ... Nenue@40: if questID and db.QuestsByID[questID] then Nenue@74: db.QuestsByID[questID].complete = true Nenue@75: self:ReleasePin(db.QuestsByID[questID]) Nenue@33: end Nenue@73: self:Refresh(event) Nenue@65: elseif event == 'SKILL_LINES_CHANGED' or event == 'CURRENT_SPELL_CAST_CHANGED' then Nenue@72: self:Refresh(event) Nenue@59: elseif event == 'ARTIFACT_UPDATE' then Nenue@72: local akCheck = C_ArtifactUI.GetArtifactKnowledgeMultiplier() Nenue@72: if akCheck and (akCheck ~= artifactKnowledgeMultiplier) then Nenue@72: if artifactKnowledgeMultiplier then Nenue@75: --print('push artifact knowledge update', artifactKnowledgeMultiplier, 'to', akCheck) Nenue@72: for index, pin in pairs( db.QuestsByID) do Nenue@72: if pin.rewardType == REWARD_ARTIFACT_POWER then Nenue@72: db.log(pin.questID .. ' ' .. tostring(pin.title) .. ' Flagged for artifact power.') Nenue@72: pin.itemNumber = 0 Nenue@72: pin.dataLoaded = nil Nenue@72: end Nenue@69: end Nenue@72: else Nenue@72: Nenue@72: print('artifact knowledge multiplier is known', akCheck) Nick@62: end Nenue@72: artifactKnowledgeMultiplier = akCheck Nenue@59: end Nenue@65: elseif event == 'SUPER_TRACKED_QUEST_CHANGED' then Nenue@65: if superTrackedQuestID and db.QuestsByID[superTrackedQuestID] then Nenue@65: db.QuestsByID[superTrackedQuestID].isStale = true Nenue@65: end Nenue@65: local newID = GetSuperTrackedQuestID() Nenue@65: if newID and db.QuestsByID[newID] then Nenue@65: db.QuestsByID[newID].isStale = true Nenue@65: end Nenue@33: end Nenue@33: end Nenue@33: Nenue@72: Nenue@75: function Module:OnUpdate(sinceLast) Nenue@75: Nenue@75: if self.refreshBenchMarkTicker then Nenue@75: --print(self.refreshBenchMarkTicker) Nenue@75: self.refreshBenchMarkTicker = self.refreshBenchMarkTicker - 1 Nenue@75: Nenue@75: if self.refreshBenchMarkTicker == 0 then Nenue@75: Nenue@75: self.refreshTime = floor((GetTime() - self.refreshBenchMark) * 1000)/1000 Nenue@75: self.debugMessage:SetText(self.refreshTime) Nenue@75: self.refreshBenchMarkTicker = nil Nenue@75: end Nenue@75: else Nenue@75: self.refreshBenchMark = GetTime() Nenue@75: end Nenue@75: Nenue@75: if self.filtersDirty or self.isStale then Nenue@75: self:Refresh() Nenue@75: end Nenue@75: if #db.UpdatedPins >= 1 then Nenue@75: --print('|cFF00FF88pending update', #db.UpdatedPins) Nenue@75: self:UpdateNext() Nenue@75: end Nenue@75: Nenue@75: end Nenue@75: Nenue@75: function Module:OnMapInfo(isBrokenIsle, isZoomedOut, mapAreaID, isNewMap, isMapOpen) Nenue@75: if isNewMap then Nenue@75: print('|cFF0088FFOnMapInfo()|r, mapAreaID =', mapAreaID,'visible =', isMapOpen, 'changed =', isNewMap) Nenue@75: layoutDirty = true Nenue@75: self:Refresh('WORLD_MAP_CHANGED') Nenue@75: else Nenue@75: Nenue@75: --print('|cFFFFFF00'..self:GetName()..':OnMapInfo()|r, mapAreaID =', mapAreaID,'visible =', isMapOpen, 'changed =', isNewMap) Nenue@75: end Nenue@75: end Nenue@75: Nenue@75: Nenue@75: function Module:UpdateTaskPOIs() Nenue@75: canTargetQuests = SpellCanTargetQuest() Nenue@75: local func = canTargetQuests and 'Show' or 'Hide' Nenue@75: for i = 1, NUM_WORLDMAP_TASK_POIS do Nenue@75: local button = _G['WorldMapFrameTaskPOI'..i] Nenue@75: if button and button.worldQuest then Nenue@75: button[func](button) Nenue@75: end Nenue@75: end Nenue@75: end Nenue@72: Nenue@73: local bountyQuests = {} Nenue@72: local bountyInfo = {} Nenue@75: Nenue@72: local bountyDisplayLocation, bountyLockedQuestID, selectedBountyIndex, selectedBountyQuestID Nenue@72: function Module:UpdateBounties(...) Nenue@75: print('|cFF00FF88BountyInfo()|r', ...) Nenue@72: wipe(db.BountiesByFactionID) Nenue@75: wipe(db.BountiesByQuestID) Nenue@72: Nenue@72: db.selectedBounty = nil Nenue@72: selectedBountyIndex = BountyBoard:GetSelectedBountyIndex() Nenue@75: db.Bounties, bountyDisplayLocation, bountyLockedQuestID = GetQuestBountyInfoForMapID(db.currentMapID, db.Bounties) Nenue@72: local numBounties = 0 Nenue@75: for index, info in ipairs(db.Bounties) do Nenue@72: numBounties = numBounties + 1 Nenue@73: info.index = index Nenue@73: info.complete = IsQuestComplete(info.questID) Nenue@73: if not info.complete then Nenue@73: db.BountiesByFactionID[info.factionID] = info Nenue@75: db.BountiesByQuestID[info.questID] = info Nenue@72: if index == selectedBountyIndex then Nenue@73: db.selectedBounty = info Nenue@73: selectedBountyQuestID = info.questID Nenue@72: end Nenue@73: print(' ', index, info.factionID, GetQuestLogTitle(GetQuestLogIndexByID(info.questID)), info.complete, (index == selectedBountyIndex) and 'SELECTED' or '') Nenue@72: end Nenue@72: end Nenue@73: bountiesDirty = nil Nenue@72: end Nenue@72: Nenue@72: Nenue@40: local totalPins = 0 Nenue@33: local TQ_GetQuestLocation = C_TaskQuest.GetQuestLocation Nenue@45: function Module:AcquirePin (info) Nenue@40: local questID = info.questId Nenue@40: if not questID then Nenue@40: return nil Nenue@40: end Nenue@40: Nenue@40: if not QuestUtils_IsQuestWorldQuest(questID) then Nenue@40: return nil Nenue@40: end Nenue@40: Nenue@49: -- if we're grabbing a pin, the filters need to be checked Nenue@40: local pin = db.QuestsByID[questID] Nenue@33: if not pin then Nenue@40: local numFree = #db.FreePins Nenue@33: if numFree >= 1 then Nenue@40: pin = tremove(db.FreePins, numFree) Nenue@33: --print('|cFF00FF00Re-using', pin:GetName()) Nenue@33: else Nenue@40: totalPins = totalPins + 1 Nenue@69: local name = 'WorldPlanQuestMarker' .. numOverlays Nenue@33: --print('|cFF00FF00Creating', name) Nenue@33: pin = CreateFrame('Frame', name, WorldMapPOIFrame, 'WorldPlanQuestPin') Nenue@33: Nenue@75: pin:SetID(totalPins) Nenue@33: pin:SetFrameStrata('HIGH') Nenue@69: numOverlays = numOverlays + 1 Nenue@33: --pin.iconBorder:SetVertexColor(0,0,0,1) Nenue@33: end Nenue@40: pin.questID = questID Nenue@40: pin.worldQuest = true Nenue@75: pin.throttle = pin.updateRate Nenue@33: pin.isNew = true Nenue@33: pin.currentWidth = nil Nenue@40: db.QuestsByID[questID] = pin Nenue@40: tinsert(db.UsedPins, pin) Nenue@75: Nenue@40: end Nenue@33: Nenue@40: if pin and info then Nenue@40: pin.inProgress = info.inProgress Nenue@40: pin.floor = info.floor Nenue@40: pin.numObjectives = info.numObjectives or 0 Nenue@40: if info.x and info.y then Nenue@75: if (info.x ~= pin.x) or (info.y ~= pin.y) then Nenue@75: pin.isStale = true Nenue@75: --rprint('|cFFFF4400SetCoords|r', info.x, info.y) Nenue@75: end Nenue@75: Nenue@40: end Nenue@40: end Nenue@33: Nenue@75: pin.x = info.x or pin.x Nenue@75: pin.y = info.y or pin.y Nenue@75: Nenue@75: if not HaveQuestData(questID) then Nenue@75: TQ_RequestPreloadRewardData(questID); Nenue@75: end Nenue@75: Nenue@75: Nick@62: if (not pin.dataLoaded) then Nenue@65: local dataLoaded = pin:GetData() Nenue@65: isDataLoaded = (isDataLoaded and dataLoaded) Nick@63: WorldPlan.dataFlush = true Nenue@49: end Nenue@49: Nenue@66: Nick@64: pin.isActive = TQ_IsActive(questID) Nenue@75: pin:GetCriteriaState() Nenue@57: pin:CheckFilterRules() Nenue@75: --rprint(pin:GetID(), pin.filtered, pin.used) Nenue@49: Nenue@40: return pin Nenue@33: end Nenue@33: Nenue@33: -- remove from index and add it to the recycling heap Nenue@45: function Module:ReleasePin (pin) Nenue@33: Nenue@40: local id = pin.questID Nenue@33: if id then Nenue@40: db.QuestsByID[id] = nil Nenue@40: Nenue@40: for i, zone in pairs(db.QuestsByZone) do Nenue@75: --print('-', i, zone[i]) Nenue@33: zone[id] = nil Nenue@33: end Nenue@40: db.TasksByID[id] = nil Nenue@33: end Nick@64: pin.isActive = nil Nick@64: pin.dataLoaded = nil Nick@62: pin:HideFrames() Nenue@40: tinsert(db.FreePins, pin) Nenue@40: Nick@63: WorldPlan.dataFlush = true Nenue@75: --print('|cFF00FF00-'.. (pin.mapID and GetMapNameByID(pin.mapID) or '???') ..'|r', id, pin.title) Nenue@33: end Nenue@33: Nenue@72: -- re-anchors and scales pins that have had either of these changed due to data loading delays Nenue@75: function Module:UpdateNext() Nenue@75: --print('|cFF00FF88UpdateNext()') Nenue@67: local pin = tremove(db.UpdatedPins) Nenue@67: pin:CheckFilterRules() Nenue@67: Nenue@75: local scaleFactor = SCALE_FACTORS[(pin.dataLoaded and not pin.filtered) and scaleConstant or 1] Nenue@75: --print(pin.title, pin.dataLoaded and not pin.filtered, scaleFactor) Nenue@75: if pin.used then Nenue@75: pin:SetAnchor(nil, pin.x, pin.y, self.hostWidth, self.hostHeight, scaleFactor) Nenue@75: pin:OnShow() Nenue@75: end Nenue@69: Nenue@69: Nenue@67: end Nenue@67: Nenue@75: function Module:Debug(...) Nenue@75: print(...) Nenue@75: end Nenue@40: Nenue@72: local msg = '|cFF00FF88WorldQuests:Refresh()|r|cFF00FFFF' Nenue@75: local lastRefresh Nenue@72: function Module:Refresh(...) Nenue@75: -- Nenue@33: Nenue@34: if not self:IsVisible() then Nenue@75: print('|cFFFF4400Refresh()|r', ...) Nenue@75: --layoutDirty = true Nenue@75: return Nenue@73: else Nenue@75: -- Nenue@75: if lastRefresh == GetTime() then Nenue@75: print('|cFFFF4400multiple refreshes tried') Nenue@75: end Nenue@75: lastRefresh = GetTime() Nenue@75: --rprint(msg, ...) Nenue@75: print(msg, lastRefresh, ...) Nenue@40: end Nenue@73: Nenue@67: if not db.Config.EnablePins then Nenue@69: numShown = 0 Nenue@67: return Nenue@67: end Nenue@75: --wprint(' '..msg) Nenue@67: Nenue@72: scaleConstant = db.isContinentMap and 2 or 3 Nenue@72: canTargetQuests = SpellCanTargetQuest() Nenue@67: Nenue@40: for index, pin in pairs(db.QuestsByID) do Nenue@40: pin.used = nil Nenue@40: end Nenue@40: Nenue@69: self:UpdateAnchors() Nenue@75: --[[ Nenue@72: if bountiesDirty then Nenue@75: --print(' bounties dirty, pushing that') Nenue@72: self:UpdateBounties() Nenue@72: end Nenue@75: --]] Nenue@72: Nick@60: Nenue@69: -- calculate quests shown Nenue@65: numShown = 0 Nenue@65: numLoaded = 0 Nick@60: for questID, pin in pairs(db.QuestsByID) do Nick@60: local oV = pin:IsShown() Nick@60: if pin.used then Nick@60: pin.throttle = 1 Nenue@75: --[[ Nick@60: if oV == false then Nenue@75: --rprint('|cFF00FF00cleanup +|r', questID, pin.title) Nick@60: end Nenue@75: --]] Nick@60: pin:SetShown(true) Nenue@65: numShown = numShown + 1 Nenue@65: if pin.dataLoaded then Nenue@65: numLoaded = numLoaded + 1 Nenue@65: end Nenue@65: Nick@60: else Nenue@75: --[[ Nick@60: if oV == true then Nenue@67: rprint('|cFFFF4400 -|r', questID, pin.title) Nick@60: end Nenue@75: --]] Nenue@69: pin.hideReason = "Not used in map area " .. (db.currentMapID) Nenue@75: pin:SetShown(false) Nick@60: end Nick@60: end Nick@60: Nenue@71: Nenue@75: --print('flags ', layoutDirty, self.isStale) Nenue@75: --print(' ', numShown, 'shown,', numLoaded, 'with data') Nenue@65: if numShown > numLoaded then Nenue@65: self.Status:Show() Nenue@65: end Nenue@65: Nenue@75: -- Nenue@75: if layoutDirty or self.isStale then Nenue@75: Nenue@75: self.refreshBenchMark = GetTime() Nenue@75: self.refreshBenchMarkTicker = 2 Nenue@75: print('starting bench', self.refreshBenchMark) Nenue@75: end Nenue@75: -- Nenue@65: Nenue@73: layoutDirty = nil Nenue@40: self.isStale = nil Nenue@54: self.sizesDirty = nil Nenue@66: self.isZoomDirty = nil Nenue@75: Nenue@40: end Nenue@40: Nenue@73: local refreshReason Nenue@75: function Module:RefreshIfChanged(event) Nenue@69: local scaleCheck = WorldMapDetailFrame:GetScale() Nenue@73: refreshReason = nil Nenue@69: if scaleCheck ~= currentScale then Nenue@73: refreshReason = 'map scale updated' Nenue@69: currentScale = scaleCheck Nenue@75: layoutDirty = true Nenue@72: elseif self.isStale or layoutDirty then Nenue@73: refreshReason = 'layout is marked dirty' Nenue@73: end Nenue@73: if not refreshReason then Nenue@73: return Nenue@73: end Nenue@73: Nenue@73: Nenue@73: if self:IsVisible() then Nenue@73: print('|cFF00FFFFRefreshIfChanged()|r', refreshReason) Nenue@75: self:Refresh(event) Nenue@73: else Nenue@75: print('|cFF00FFFFRefreshIfChanged()|r', refreshReason) Nenue@73: self.isStale = true Nenue@69: end Nenue@69: end Nenue@69: Nenue@40: -- update visibility states of all pins Nenue@57: function Module:MarkAllPins(pins) Nenue@75: --print(' |cFFFFFF00'..self:GetName()..':MarkAllPins()|r', pins) Nenue@40: pins = pins or db.QuestsByID Nenue@40: for questID, pin in pairs(pins) do Nenue@40: pin.isStale = true Nenue@75: --rprint('|cFF00FF00filter', pin.questID, pin.filtered, 'used:', pin.used) Nenue@33: end Nenue@33: end Nenue@33: Nenue@69: -- Updates quest markers in taskInfo while associating them with the given map Nenue@69: function Module:UpdateQuestsForMap(taskInfo, mapID) Nenue@75: if mapID then Nenue@75: db.QuestsByZone[mapID] = db.QuestsByZone[mapID] or {} Nenue@75: wipe(db.QuestsByZone[mapID]) Nenue@75: end Nenue@75: print('UpdateQuestsForMap()', GetMapNameByID(mapID), GetMapNameByID(db.currentMapID), layoutDirty) Nenue@40: for index, info in pairs(taskInfo) do Nenue@75: Nenue@75: local questID, x, y = info.questId, info.x, info.y Nenue@75: local pin = self:AcquirePin(info) Nenue@75: if pin then Nenue@75: print(pin.title, pin.isStale) Nenue@75: if pin:IsShown() and (layoutDirty or pin.isStale) then Nenue@75: local scaleFactor = SCALE_FACTORS[(pin.dataLoaded and not pin.filtered) and scaleConstant or 1] Nenue@75: pin.owningFrame = WorldMapFrame Nenue@75: pin:SetFrameLevel(PinBaseIndex+pin:GetID()) Nenue@75: pin.Overlay:SetFrameLevel(overlayBaseIndex+pin:GetID()) Nenue@75: pin:SetAnchor(WorldMapPOIFrame, x, y, self.hostWidth, self.hostHeight, scaleFactor) Nenue@75: if pin.isStale then Nenue@75: pin:Refresh('WORLDMAP_REFRESH ' .. GetTime()) Nenue@75: end Nenue@75: if mapID then Nenue@75: db.QuestsByZone[mapID][questID] = pin Nenue@75: end Nenue@75: else Nenue@75: if layoutDirty then Nenue@75: pin.isStale = true Nenue@75: end Nenue@75: end Nenue@75: Nenue@75: Nenue@75: end Nenue@40: end Nenue@40: end Nenue@33: Nenue@69: -- Used to refresh the visible quest markers Nick@60: function Module:UpdateAnchors () Nenue@40: wipe(self.UsedPositions) Nick@60: print(' |cFF00FF00'..self:GetName()..':UpdateAnchors()') Nenue@74: local hostWidth, hostHeight = WorldMapPOIFrame:GetSize() Nenue@74: Nenue@74: if (hostWidth ~= self.hostWidth) or (hostHeight ~= self.hostHeight) then Nenue@74: self.hostWidth, self.hostHeight = hostWidth, hostHeight Nenue@74: layoutDirty = true Nenue@74: end Nenue@74: Nenue@67: Nenue@75: --rprint('|cFF00FF00'..self:GetName()..':UpdateAnchors()') Nenue@33: local mapFileName, textureHeight, textureWidth, isMicroDungeon, microDungeonMapName = GetMapInfo() Nenue@33: if isMicroDungeon then Nenue@33: return Nenue@33: end Nenue@69: Nenue@65: isDataLoaded = true Nenue@67: local taskInfo = TQ_GetQuestsForPlayerByMapID(db.currentMapID) Nenue@40: if taskInfo then Nenue@69: self:UpdateQuestsForMap(taskInfo, db.currentMapID) Nenue@33: end Nenue@67: local numZones = MC_GetNumZones(db.currentMapID) Nenue@33: if numZones then Nenue@33: for i = 1, numZones do Nenue@67: local mapAreaID = MC_GetZoneInfo(db.currentMapID, i) Nenue@67: local taskInfo = TQ_GetQuestsForPlayerByMapID(mapAreaID, db.currentMapID) Nenue@40: if taskInfo then Nenue@69: self:UpdateQuestsForMap(taskInfo, mapAreaID) Nenue@40: end Nenue@33: end Nenue@33: end Nenue@33: end Nenue@33: Nenue@67: function ToggleButton:OnShow() Nenue@67: self:SetChecked(db.Config.EnablePins and true or false) Nenue@67: end Nenue@67: function ToggleButton:OnClick() Nenue@75: --print(self:GetChecked()) Nenue@67: db.Config.EnablePins = self:GetChecked() Nenue@67: _G.WorldPlan:OnConfigUpdate() Nenue@67: end