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@93: local HaveQuestRewardData = HaveQuestRewardData Nenue@93: local TQ_GetQuestLocation = C_TaskQuest.GetQuestLocation Nenue@96: local InCombatLockdown, hooksecurefunc = InCombatLockdown, hooksecurefunc Nenue@33: Nenue@69: local ToggleButton = {} 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@93: local defaults = {} Nenue@72: Nenue@93: local continentScanned Nenue@93: local layoutDirty = true Nenue@93: local bountiesDirty = true Nenue@93: local artifactPowerDirty = true Nenue@96: local hooksDirty = true Nenue@93: local currentScale = WorldMapDetailFrame:GetScale() Nenue@93: local canTargetQuests Nenue@93: local isDataLoaded = true Nenue@93: local artifactKnowledgeLevel Nenue@93: local superTrackedQuestID Nenue@93: local lastRefresh Nenue@93: local refreshReason Nenue@93: Nenue@93: local bountyQuests = {} Nenue@93: local bountyInfo = {} Nenue@93: local bountyDisplayLocation, bountyLockedQuestID, selectedBountyIndex, selectedBountyQuestID Nenue@93: Nenue@93: local totalPins = 0 Nenue@93: local numShown = 0 Nenue@93: local numLoaded = 0 Nenue@93: local numOverlays = 1 Nenue@93: local scaleConstant = 1 Nenue@75: local pinBaseIndex = 1500 Nenue@75: local overlayBaseIndex = 1580 Nenue@93: Nenue@93: local artifactKnowldegeSpells = { Nenue@93: [207856] = true, Nenue@93: [209203] = true, Nenue@93: [209204] = true, Nenue@93: [209205] = true, Nenue@93: [209206] = true, Nenue@93: [209207] = true, Nenue@93: [209208] = true, Nenue@93: [209209] = true, Nenue@93: [209210] = true, Nenue@93: [209211] = true, Nenue@93: [209212] = true, Nenue@93: [219978] = true, Nenue@93: [227852] = true, Nenue@93: [236477] = true, Nenue@93: [236489] = true, Nenue@93: [236302] = true, Nenue@93: [236488] = true, Nenue@93: [236490] = true, Nenue@93: [240475] = true, Nenue@93: [243176] = true, Nenue@93: [243177] = true, Nenue@93: [243178] = true, Nenue@93: [243182] = true, Nenue@93: [243183] = true, Nenue@93: [243187] = true, Nenue@93: [245133] = true, Nenue@93: } 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@93: function Module:OnLoad() Nenue@93: --print('|cFFFF4400'..self:GetName()..':OnLoad()') Nenue@52: Nenue@93: self:SetParent(WorldMapFrame.UIElementsFrame) Nenue@93: WorldPlan:AddHandler(self, defaults) Nenue@93: Nenue@93: for areaID, fileName in pairs(WORLD_QUEST_MAPS) do Nenue@93: db.QuestsByZone[areaID] = {} Nenue@33: end Nenue@93: Nenue@93: -- WORLD_MAP_UPDATE and PLAYER_ENTERING_WORLD are passed down from a higher level Nenue@93: self:RegisterEvent('WORLD_QUEST_COMPLETED_BY_SPELL') Nenue@93: self:RegisterEvent('SUPER_TRACKED_QUEST_CHANGED') Nenue@93: self:RegisterEvent('SKILL_LINES_CHANGED') Nenue@93: self:RegisterEvent('ARTIFACT_UPDATE') Nenue@93: self:RegisterEvent('QUEST_LOG_UPDATE') Nenue@93: self:RegisterEvent('UNIT_SPELLCAST_STOP') Nenue@93: end Nenue@93: Nenue@93: function Module:OnEvent (event, ...) Nenue@93: print('|cFFFFFF00OnEvent() '..event..'|r', GetTime(), ...) Nenue@93: if (event == 'QUEST_LOG_UPDATE') then Nenue@93: self:UpdateBounties(event) Nenue@93: elseif event == 'WORLD_QUEST_COMPLETED_BY_SPELL' then Nenue@93: local questID = ... Nenue@93: if questID and db.QuestsByID[questID] then Nenue@93: db.QuestsByID[questID]:Release() Nenue@93: end Nenue@93: self:Refresh(event) Nenue@93: elseif event == 'SKILL_LINES_CHANGED' or event == 'CURRENT_SPELL_CAST_CHANGED' then Nenue@93: self:Refresh(event) Nenue@93: elseif event == 'ARTIFACT_UPDATE' then Nenue@93: self:UpdateArtifactPower() Nenue@93: elseif event == 'MODIFIER_STATE_CHANGED' then Nenue@93: self:UpdateModifierState() Nenue@93: elseif event == 'SUPER_TRACKED_QUEST_CHANGED' then Nenue@93: if superTrackedQuestID and db.QuestsByID[superTrackedQuestID] then Nenue@93: db.QuestsByID[superTrackedQuestID].isStale = true Nenue@93: end Nenue@93: local newID = GetSuperTrackedQuestID() Nenue@93: if newID and db.QuestsByID[newID] then Nenue@93: db.QuestsByID[newID].isStale = true Nenue@93: end Nenue@93: elseif event == 'UNIT_SPELLCAST_STOP' then Nenue@93: local name, _, _, _, spellID = ... Nenue@93: if artifactKnowldegeSpells[spellID] then Nenue@93: db.log('AK spellcast ended ' .. tostring(name) .. ' ('.. tostring(spellID)..')') Nenue@93: self:UpdateArtifactPower() Nenue@93: end Nenue@93: end Nenue@93: end Nenue@93: Nenue@93: function Module:OnUpdate(sinceLast) Nenue@93: if WorldPlanData.DebugEnabled then Nenue@93: if self.refreshBenchMarkTicker then Nenue@93: --print(self.refreshBenchMarkTicker) Nenue@93: self.refreshBenchMarkTicker = self.refreshBenchMarkTicker - 1 Nenue@93: Nenue@93: if self.refreshBenchMarkTicker == 0 then Nenue@93: Nenue@93: self.refreshTime = floor((GetTime() - self.refreshBenchMark) * 1000) Nenue@93: self.debugMessage:SetText(self.refreshTime) Nenue@93: self.refreshBenchMarkTicker = nil Nenue@69: end Nenue@69: else Nenue@93: self.refreshBenchMark = GetTime() Nenue@69: end Nenue@69: end Nenue@65: Nenue@93: if self.filtersDirty or self.isStale then Nenue@93: self:Refresh() Nenue@67: end Nenue@72: Nenue@93: if #db.UpdatedPins >= 1 then Nenue@93: --print('|cFF00FF88pending update', #db.UpdatedPins) Nenue@93: self:UpdateNext() Nenue@93: end Nenue@93: end Nenue@72: Nenue@93: local callbacks = {} 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@96: callbacks.UseWorldMapActionButtonSpellOnQuest = function(questID) Nenue@96: if db.QuestsByID[questID] then Nenue@96: db.QuestsByID[questID].isStale = true Nenue@93: end Nenue@96: end Nenue@96: Nenue@96: function Module:SetupCallbacks() Nenue@96: if InCombatLockdown() then Nenue@96: return nil Nenue@96: end Nenue@96: print('SetupCallbacks()') Nenue@93: for target, arg in pairs(callbacks) do Nenue@93: --print(type(target)) Nenue@93: if type(target) == 'table' then Nenue@93: local callerName = target:GetName() or tostring(target) Nenue@93: for name, method in pairs(arg) do Nenue@93: --print(callerName, arg) Nenue@93: hooksecurefunc(target, name, function(...) Nenue@93: self:OnSecureHook(callerName .. '.' .. name, method, ...) Nenue@93: end) Nenue@93: end Nenue@93: else Nenue@93: hooksecurefunc(target, function(...) Nenue@93: self:OnSecureHook(target, arg, ...) Nenue@93: end) Nenue@93: end Nenue@93: end Nenue@93: Nenue@93: Nenue@96: end Nenue@96: Nenue@96: function Module:Setup() Nenue@96: --print('|cFFFF4400'..self:GetName()..':Setup()') Nenue@96: for mapID, mapName in pairs(WORLD_QUEST_MAPS) do Nenue@96: db.QuestsByZone[mapID] = {} Nenue@96: end Nenue@96: Nenue@96: hooksDirty = self:SetupCallbacks() Nenue@96: Nenue@93: self:SetAllPoints(WorldMapFrame.UIElementsFrame) Nenue@93: self:UpdateArtifactPower() Nenue@93: self:UpdateBounties('SETUP') Nenue@93: self:Show() Nenue@93: end Nenue@93: Nenue@93: function Module:OnMapInfo(isBrokenIsle, isZoomedOut, mapAreaID, isNewMap, isMapOpen) Nenue@93: if isNewMap or self.isStale then Nenue@93: print('|cFF0088FFOnMapInfo()|r, mapAreaID =', mapAreaID,'visible =', isMapOpen, 'changed =', isNewMap) Nenue@93: layoutDirty = true Nenue@93: self:Refresh('WORLD_MAP_CHANGED') Nenue@93: end Nenue@93: end Nenue@93: 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@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@93: function Module:UpdateModifierState() Nenue@33: Nenue@33: end Nenue@33: Nenue@93: function Module:UpdateTaskPOIs() Nenue@93: canTargetQuests = SpellCanTargetQuest() Nenue@93: for i = 1, NUM_WORLDMAP_TASK_POIS do Nenue@93: local poiFrame = _G['WorldMapFrameTaskPOI'..i] Nenue@93: if poiFrame and poiFrame.worldQuest then Nenue@93: local pin = db.QuestsByID[poiFrame.questID] Nenue@93: if pin and pin.used and canTargetQuests and IsQuestIDValidSpellTarget(pin.questID) then Nenue@93: poiFrame:Show() Nenue@93: else Nenue@93: poiFrame:Hide() Nenue@93: end Nenue@93: end Nenue@93: end Nenue@93: end Nenue@93: -- re-anchors and scales pins that have had either of these changed due to data loading delays Nenue@93: function Module:UpdateNext() Nenue@93: --print('|cFF00FF88UpdateNext()') Nenue@93: local pin = tremove(db.UpdatedPins) Nenue@96: pin:CheckFilterRules() Nenue@40: Nenue@93: local scaleFactor = SCALE_FACTORS[(pin.dataLoaded and not pin.filtered) and scaleConstant or 1] Nenue@93: --print(pin.title, pin.dataLoaded and not pin.filtered, scaleFactor) Nenue@93: if pin.used then Nenue@96: pin:SetShown(true) Nenue@93: pin:SetAnchor(nil, pin.x, pin.y, self.hostWidth, self.hostHeight, scaleFactor) Nenue@96: pin:Refresh() Nenue@96: else Nenue@96: print('|cFFFF4400flagging queued pin that got hidden:', pin.title) Nenue@96: pin.isStale = true Nenue@33: end Nenue@33: end Nenue@33: 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@93: -- check current artifact knowledge and update pins accordingly Nenue@93: function Module:UpdateArtifactPower(overrideLevel) Nenue@93: if InCombatLockdown() then Nenue@93: artifactPowerDirty = true Nenue@93: return Nenue@40: end Nenue@40: Nenue@93: print('|cFF00FF88UpdateArtifactPower()|r') Nenue@93: local _, akLevel = GetCurrencyInfo(1171) Nenue@93: if overrideLevel then Nenue@93: akLevel = overrideLevel Nenue@40: end Nenue@40: Nenue@93: --db.print('current AK', akLevel) Nenue@93: if akLevel and (akLevel ~= artifactKnowledgeLevel) or (not artifactKnowledgeLevel) then Nenue@93: --print('new ak level', akLevel) Nenue@93: db.log('AK update ' .. tostring(artifactKnowledgeLevel) .. ' to '.. tostring(akLevel)) Nenue@93: for _, pin in pairs(db.QuestsByID) do Nenue@93: if (pin.rewardType == REWARD_ARTIFACT_POWER) then Nenue@93: print(pin.title, pin.itemNumber) Nenue@93: local newAP = pin:UpdateArtifactPower() Nenue@93: if newAP then Nenue@93: pin.itemNumber = newAP Nenue@93: print(newAP) Nenue@93: else Nenue@93: pin.dataLoaded = nil Nenue@93: end Nenue@93: pin.isStale = true Nenue@93: end Nenue@33: end Nenue@93: artifactKnowledgeLevel = akLevel Nenue@40: end Nenue@93: artifactPowerDirty = nil Nenue@75: end Nenue@40: Nenue@72: local msg = '|cFF00FF88WorldQuests:Refresh()|r|cFF00FFFF' Nenue@72: function Module:Refresh(...) Nenue@96: Nenue@96: if hooksDirty then Nenue@96: hooksDirty = self:SetupCallbacks() Nenue@96: end Nenue@96: Nenue@96: Nenue@34: if not self:IsVisible() then Nenue@75: print('|cFFFF4400Refresh()|r', ...) Nenue@75: return Nenue@73: else Nenue@75: if lastRefresh == GetTime() then Nenue@75: print('|cFFFF4400multiple refreshes tried') Nenue@75: end Nenue@75: lastRefresh = GetTime() Nenue@75: print(msg, lastRefresh, ...) Nenue@40: end Nenue@73: Nenue@67: if not db.Config.EnablePins then Nenue@69: numShown = 0 Nenue@76: self.refreshBenchMark = GetTime() Nenue@76: self.refreshBenchMarkTicker = 2 Nenue@76: print('starting bench', self.refreshBenchMark) Nenue@67: return Nenue@67: end 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@95: self:UpdateAnchors(...) Nenue@72: Nenue@93: if artifactPowerDirty and not InCombatLockdown() then Nenue@93: self:UpdateArtifactPower() Nenue@93: end 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 Nenue@96: print('show', pin.title) Nick@60: pin.throttle = 1 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@96: if pin:IsShown() then Nenue@96: print('|cFFFF4400need to remove', pin.title) Nenue@96: Nick@60: end Nenue@96: Nenue@69: pin.hideReason = "Not used in map area " .. (db.currentMapID) Nenue@75: pin:SetShown(false) Nick@60: end Nenue@93: Nick@60: end Nenue@93: Nenue@65: Nenue@75: -- Nenue@93: self.refreshBenchMark = GetTime() Nenue@93: self.refreshBenchMarkTicker = 2 Nenue@93: print('starting bench', self.refreshBenchMark) Nenue@76: 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@93: if WorldPlanSummary then Nenue@93: WorldPlanSummary.isStale = true Nenue@93: end Nenue@93: Nenue@40: end Nenue@40: 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: 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@93: -- Walks the current map tree and fires updates as needed Nenue@95: function Module:UpdateAnchors (event) Nenue@40: wipe(self.UsedPositions) 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@95: print('|cFF00FF00UpdateAnchors()', event) 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@82: Nenue@82: db.QuestsByZone[mapAreaID] = db.QuestsByZone[mapAreaID] or {} Nenue@82: 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@96: -- Attempt to display the pins for quests in taskInfo Nenue@93: function Module:UpdateQuestsForMap(taskInfo, mapID) Nenue@93: print('|cFF00FF00UpdateQuestsForMap()|r', GetMapNameByID(mapID), GetMapNameByID(db.currentMapID), layoutDirty) Nenue@93: if db.QuestsByZone[mapID] then Nenue@93: wipe(db.QuestsByZone[mapID]) Nenue@93: elseif db.isBrokenIsle then Nenue@93: continentScanned = true Nenue@93: end Nenue@96: print('layoutDirty =',layoutDirty) Nenue@93: Nenue@93: for index, info in pairs(taskInfo) do Nenue@93: local questID, x, y = info.questId, info.x, info.y Nenue@93: local pin = self:AcquirePin(info) Nenue@93: Nenue@96: if pin.canShow then Nenue@93: pin.used = true Nenue@96: print('using', pin.title, (pin.owningFrame ~= WorldMapFrame)) Nenue@96: if layoutDirty or (pin.owningFrame ~= WorldMapFrame) then Nenue@93: local scaleFactor = SCALE_FACTORS[(not pin.filtered and scaleConstant) or 1] Nenue@93: pin.owningFrame = WorldMapFrame Nenue@93: pin:SetAnchor(WorldMapPOIFrame, x, y, self.hostWidth, self.hostHeight, scaleFactor) Nenue@93: if pin.isStale then Nenue@93: pin:Refresh('WORLDMAP_REFRESH ' .. GetTime()) Nenue@93: end Nenue@93: end Nenue@96: if db.QuestsByZone[mapID] then Nenue@93: db.QuestsByZone[mapID][questID] = pin Nenue@93: end Nenue@96: else Nenue@96: print('|cFFFF4400not using|r', pin.title) Nenue@93: end Nenue@93: end Nenue@67: end Nenue@93: Nenue@93: -- locates or creates a corresponding pin frame for the provided TaskInfo data Nenue@93: function Module:AcquirePin (info) Nenue@93: local questID = info.questId Nenue@93: if not (questID and QuestUtils_IsQuestWorldQuest(questID)) then Nenue@93: return nil Nenue@93: end Nenue@93: Nenue@93: local pin = db.QuestsByID[questID] Nenue@93: if not pin then Nenue@93: local numFree = #db.FreePins Nenue@93: if numFree >= 1 then Nenue@93: pin = tremove(db.FreePins, numFree) Nenue@93: print('|cFF00FF00Re-using', pin:GetName()) Nenue@93: else Nenue@93: totalPins = totalPins + 1 Nenue@93: local name = 'WorldPlanQuestMarker' .. numOverlays Nenue@93: print('|cFF00FF00Creating', name) Nenue@93: pin = CreateFrame('Frame', name, WorldMapPOIFrame, 'WorldPlanQuestPin') Nenue@93: Nenue@93: pin:SetID(totalPins) Nenue@93: numOverlays = numOverlays + 1 Nenue@93: --pin.iconBorder:SetVertexColor(0,0,0,1) Nenue@93: end Nenue@93: pin.questID = questID Nenue@93: pin.worldQuest = true Nenue@93: pin.throttle = pin.updateRate Nenue@93: pin.isNew = true Nenue@93: pin.currentWidth = nil Nenue@93: db.QuestsByID[questID] = pin Nenue@93: tinsert(db.UsedPins, pin) Nenue@93: end Nenue@93: Nenue@93: if IsQuestComplete(questID) then Nenue@93: pin:Release() Nenue@93: return nil Nenue@93: elseif info then Nenue@93: pin.inProgress = info.inProgress Nenue@93: pin.floor = info.floor Nenue@93: pin.numObjectives = info.numObjectives or 0 Nenue@93: if info.x and info.y then Nenue@93: if (info.x ~= pin.x) or (info.y ~= pin.y) then Nenue@93: pin.isStale = true Nenue@93: --rprint('|cFFFF4400SetCoords|r', info.x, info.y) Nenue@93: end Nenue@93: end Nenue@93: end Nenue@93: Nenue@93: pin.x = info.x or pin.x Nenue@93: pin.y = info.y or pin.y Nenue@93: Nenue@93: if not HaveQuestRewardData(questID) then Nenue@93: TQ_RequestPreloadRewardData(questID); Nenue@93: end Nenue@93: Nenue@93: if (not pin.dataLoaded) then Nenue@93: local dataLoaded = pin:GetData() Nenue@93: if dataLoaded then Nenue@93: WorldPlan.dataFlush = true Nenue@93: else Nenue@93: isDataLoaded = false Nenue@93: end Nenue@93: end Nenue@93: Nenue@93: pin.isActive = TQ_IsActive(questID) Nenue@93: pin:GetCriteriaState() Nenue@93: pin:CheckFilterRules() Nenue@93: --rprint(pin:GetID(), pin.filtered, pin.used) Nenue@93: return pin Nenue@93: end Nenue@93: Nenue@93: function Module:Debug(...) Nenue@93: print(...) Nenue@67: end