comparison WorldQuests.lua @ 93:98b5e08b75ed v1.4.9

- Fixed quest completion checking and handling - Changed animation method to hopefully stop weird flickering. - Pins are now visible before full reward data is loaded - Filter bar redesigned: - aligned horizontally along the top of the map display - filter buttons display a '+' when there are matches in both current and other zones, and '*' when there only matches in other zones - button tooltips separate local and global quests - button categories are highlighted and labeled when the cursor is over them - Fixed invalid POI targets appearing when the spell targeting cursor is active
author Nenue
date Sat, 15 Apr 2017 11:04:54 -0400
parents 77013bd72adb
children b29b35cb8539
comparison
equal deleted inserted replaced
92:df725cba1a6a 93:98b5e08b75ed
24 local SpellCanTargetQuest, IsQuestIDValidSpellTarget = SpellCanTargetQuest, IsQuestIDValidSpellTarget 24 local SpellCanTargetQuest, IsQuestIDValidSpellTarget = SpellCanTargetQuest, IsQuestIDValidSpellTarget
25 local tonumber, abs = tonumber, math.abs 25 local tonumber, abs = tonumber, math.abs
26 local GetQuestLogRewardInfo = GetQuestLogRewardInfo 26 local GetQuestLogRewardInfo = GetQuestLogRewardInfo
27 local GetCurrentMapAreaID, GetMapInfo, GetMapNameByID = GetCurrentMapAreaID, GetMapInfo, GetMapNameByID 27 local GetCurrentMapAreaID, GetMapInfo, GetMapNameByID = GetCurrentMapAreaID, GetMapInfo, GetMapNameByID
28 local GetQuestBountyInfoForMapID, GetQuestLogTitle, GetQuestLogIndexByID, IsQuestComplete = GetQuestBountyInfoForMapID, GetQuestLogTitle, GetQuestLogIndexByID, IsQuestComplete 28 local GetQuestBountyInfoForMapID, GetQuestLogTitle, GetQuestLogIndexByID, IsQuestComplete = GetQuestBountyInfoForMapID, GetQuestLogTitle, GetQuestLogIndexByID, IsQuestComplete
29 local IsQuestCriteriaForBounty = IsQuestCriteriaForBounty 29 local HaveQuestRewardData = HaveQuestRewardData
30 local TQ_GetQuestLocation = C_TaskQuest.GetQuestLocation
30 31
31 local ToggleButton = {} 32 local ToggleButton = {}
32 local callbacks = {}
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 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
34 local WORLD_QUEST_MAPS = { [DALARAN_ID] = 'Dalaran70', [AZSUNA_ID] = 'Azsuna', [VALSHARAH_ID] = "Val'sharah", 34 local WORLD_QUEST_MAPS = { [DALARAN_ID] = 'Dalaran70', [AZSUNA_ID] = 'Azsuna', [VALSHARAH_ID] = "Val'sharah",
35 [HIGHMOUNTAIN_ID] = 'Highmountain', [STORMHEIM_ID] = 'Stormheim', [SURAMAR_ID] = 'Suramar', [EOA_ID] = 'EyeOfAszhara', } 35 [HIGHMOUNTAIN_ID] = 'Highmountain', [STORMHEIM_ID] = 'Stormheim', [SURAMAR_ID] = 'Suramar', [EOA_ID] = 'EyeOfAszhara', }
36 36
37 local REWARD_CASH = WORLD_QUEST_REWARD_TYPE_FLAG_GOLD 37 local REWARD_CASH = WORLD_QUEST_REWARD_TYPE_FLAG_GOLD
41 local REWARD_REAGENT = WORLD_QUEST_REWARD_TYPE_FLAG_MATERIALS 41 local REWARD_REAGENT = WORLD_QUEST_REWARD_TYPE_FLAG_MATERIALS
42 local SCALE_FACTORS = { 0.25, 0.7, 1 } 42 local SCALE_FACTORS = { 0.25, 0.7, 1 }
43 43
44 local BountyBoard = WorldMapFrame.UIElementsFrame.BountyBoard 44 local BountyBoard = WorldMapFrame.UIElementsFrame.BountyBoard
45 local ActionButton = WorldMapFrame.UIElementsFrame.ActionButton 45 local ActionButton = WorldMapFrame.UIElementsFrame.ActionButton
46 46 local defaults = {}
47
48 local continentScanned
49 local layoutDirty = true
50 local bountiesDirty = true
51 local artifactPowerDirty = true
52 local currentScale = WorldMapDetailFrame:GetScale()
53 local canTargetQuests
54 local isDataLoaded = true
55 local artifactKnowledgeLevel
56 local superTrackedQuestID
57 local lastRefresh
58 local refreshReason
59
60 local bountyQuests = {}
61 local bountyInfo = {}
62 local bountyDisplayLocation, bountyLockedQuestID, selectedBountyIndex, selectedBountyQuestID
63
64 local totalPins = 0
65 local numShown = 0
66 local numLoaded = 0
67 local numOverlays = 1
68 local scaleConstant = 1
47 local pinBaseIndex = 1500 69 local pinBaseIndex = 1500
48 local overlayBaseIndex = 1580 70 local overlayBaseIndex = 1580
49 local layoutDirty = true 71
50 local bountiesDirty = true 72 local artifactKnowldegeSpells = {
51 local currentScale = WorldMapDetailFrame:GetScale() 73 [207856] = true,
52 local canTargetQuests 74 [209203] = true,
53 local numShown = 0 75 [209204] = true,
54 local numLoaded = 0 76 [209205] = true,
55 local isDataLoaded = true 77 [209206] = true,
56 local numOverlays = 1 78 [209207] = true,
57 local scaleConstant = 1 79 [209208] = true,
58 Module.TasksByID = {} 80 [209209] = true,
81 [209210] = true,
82 [209211] = true,
83 [209212] = true,
84 [219978] = true,
85 [227852] = true,
86 [236477] = true,
87 [236489] = true,
88 [236302] = true,
89 [236488] = true,
90 [236490] = true,
91 [240475] = true,
92 [243176] = true,
93 [243177] = true,
94 [243178] = true,
95 [243182] = true,
96 [243183] = true,
97 [243187] = true,
98 [245133] = true,
99 }
59 100
60 --%debug% 101 --%debug%
61 local SetTimedCallbackForAllPins = function(seconds, callback) 102 local SetTimedCallbackForAllPins = function(seconds, callback)
62 C_Timer.After(seconds, function() 103 C_Timer.After(seconds, function()
63 for id, pin in pairs(WorldPlanQuests.QuestsByID) do 104 for id, pin in pairs(WorldPlanQuests.QuestsByID) do
64 callback(pin) 105 callback(pin)
65 end 106 end
66 end) 107 end)
67 end 108 end
68 109
110 function Module:OnLoad()
111 --print('|cFFFF4400'..self:GetName()..':OnLoad()')
112
113 self:SetParent(WorldMapFrame.UIElementsFrame)
114 WorldPlan:AddHandler(self, defaults)
115
116 for areaID, fileName in pairs(WORLD_QUEST_MAPS) do
117 db.QuestsByZone[areaID] = {}
118 end
119
120 -- WORLD_MAP_UPDATE and PLAYER_ENTERING_WORLD are passed down from a higher level
121 self:RegisterEvent('WORLD_QUEST_COMPLETED_BY_SPELL')
122 self:RegisterEvent('SUPER_TRACKED_QUEST_CHANGED')
123 self:RegisterEvent('SKILL_LINES_CHANGED')
124 self:RegisterEvent('ARTIFACT_UPDATE')
125 self:RegisterEvent('QUEST_LOG_UPDATE')
126 self:RegisterEvent('UNIT_SPELLCAST_STOP')
127 end
128
129 function Module:OnEvent (event, ...)
130 print('|cFFFFFF00OnEvent() '..event..'|r', GetTime(), ...)
131 if (event == 'QUEST_LOG_UPDATE') then
132 self:UpdateBounties(event)
133 elseif event == 'WORLD_QUEST_COMPLETED_BY_SPELL' then
134 local questID = ...
135 if questID and db.QuestsByID[questID] then
136 db.QuestsByID[questID]:Release()
137 end
138 self:Refresh(event)
139 elseif event == 'SKILL_LINES_CHANGED' or event == 'CURRENT_SPELL_CAST_CHANGED' then
140 self:Refresh(event)
141 elseif event == 'ARTIFACT_UPDATE' then
142 self:UpdateArtifactPower()
143 elseif event == 'MODIFIER_STATE_CHANGED' then
144 self:UpdateModifierState()
145 elseif event == 'SUPER_TRACKED_QUEST_CHANGED' then
146 if superTrackedQuestID and db.QuestsByID[superTrackedQuestID] then
147 db.QuestsByID[superTrackedQuestID].isStale = true
148 end
149 local newID = GetSuperTrackedQuestID()
150 if newID and db.QuestsByID[newID] then
151 db.QuestsByID[newID].isStale = true
152 end
153 elseif event == 'UNIT_SPELLCAST_STOP' then
154 local name, _, _, _, spellID = ...
155 if artifactKnowldegeSpells[spellID] then
156 db.log('AK spellcast ended ' .. tostring(name) .. ' ('.. tostring(spellID)..')')
157 self:UpdateArtifactPower()
158 end
159 end
160 end
161
162 function Module:OnUpdate(sinceLast)
163 if WorldPlanData.DebugEnabled then
164 if self.refreshBenchMarkTicker then
165 --print(self.refreshBenchMarkTicker)
166 self.refreshBenchMarkTicker = self.refreshBenchMarkTicker - 1
167
168 if self.refreshBenchMarkTicker == 0 then
169
170 self.refreshTime = floor((GetTime() - self.refreshBenchMark) * 1000)
171 self.debugMessage:SetText(self.refreshTime)
172 self.refreshBenchMarkTicker = nil
173 end
174 else
175 self.refreshBenchMark = GetTime()
176 end
177 end
178
179 if self.filtersDirty or self.isStale then
180 self:Refresh()
181 end
182
183 if #db.UpdatedPins >= 1 then
184 --print('|cFF00FF88pending update', #db.UpdatedPins)
185 self:UpdateNext()
186 end
187 end
188
189 local callbacks = {}
190 callbacks.ClickWorldMapActionButton = function(WorldQuests)
191 WorldQuests:Refresh('CLICK_MAP_ACTION_BUTTON')
192 end
193 callbacks.WorldMap_UpdateQuestBonusObjectives = function(WorldQuests)
194 WorldQuests:UpdateTaskPOIs()
195 end
196 callbacks.WorldMapFrame_UpdateMap = function(WorldQuests)
197 WorldQuests:RefreshIfChanged('WMF_UPDATE')
198 end
199 callbacks.WorldMapScrollFrame_ReanchorQuestPOIs = function (WorldQuests)
200 WorldQuests:RefreshIfChanged('WMF_REANCHOR')
201 end
202
203 callbacks[BountyBoard] = {}
204 callbacks[BountyBoard].SetSelectedBountyIndex = function(WorldQuests)
205 WorldQuests:UpdateBounties('BOUNTY_SELECTED')
206 WorldQuests:Refresh('BOUNTY_SELECTED')
207 end
208
209 callbacks[ActionButton] = {}
210 callbacks[ActionButton].UpdateCastingState = function(WorldQuests)
211 WorldQuests:Refresh('CASTING_STATE_CHANGED')
212 end
69 213
70 function Module:Setup() 214 function Module:Setup()
71 --print('|cFFFF4400'..self:GetName()..':Setup()') 215 --print('|cFFFF4400'..self:GetName()..':Setup()')
72 for mapID, mapName in pairs(WORLD_QUEST_MAPS) do 216 for mapID, mapName in pairs(WORLD_QUEST_MAPS) do
73 db.QuestsByZone[mapID] = {} 217 db.QuestsByZone[mapID] = {}
87 self:OnSecureHook(target, arg, ...) 231 self:OnSecureHook(target, arg, ...)
88 end) 232 end)
89 end 233 end
90 end 234 end
91 235
92 self.Status = CreateFrame('Frame', nil, self)
93 self.Status:SetPoint('TOPLEFT', WorldMapFrame.UIElementsFrame, 'TOPLEFT', 0, 0)
94 self.Status:SetPoint('BOTTOMRIGHT', WorldMapFrame.UIElementsFrame, 'TOPRIGHT', 0, -4)
95 self.Status.t = self.Status:CreateTexture(nil, 'OVERLAY')
96 self.Status.b = self.Status:CreateTexture(nil, 'BACKGROUND')
97 self.Status.b:SetColorTexture(0,0,0,.25)
98 self.Status.b:SetAllPoints(self.Status)
99 self.Status.t:SetColorTexture(1,1,1,.5)
100 self.Status.t:SetPoint('TOP')
101 self.Status.t:SetPoint('BOTTOM')
102 self.Status.t:SetPoint('LEFT')
103 local translationEnd, translationStart
104 self.Status:SetScript('OnUpdate', function(status)
105 local translateTo
106 if numLoaded < numShown then
107 translateTo = (numLoaded/numShown) * status:GetWidth()
108 status.t:SetWidth(translateTo)
109 else
110 translateTo = status:GetWidth()
111 status.t:SetWidth(translateTo)
112 end
113 end)
114 236
115 self:SetAllPoints(WorldMapFrame.UIElementsFrame) 237 self:SetAllPoints(WorldMapFrame.UIElementsFrame)
116 for k,v in pairs( ToggleButton) do 238 self:UpdateArtifactPower()
117 self.Toggle:SetScript(k,v)
118 end
119
120 self:UpdateBounties('SETUP') 239 self:UpdateBounties('SETUP')
121
122 self:Show() 240 self:Show()
123 end 241 end
124 callbacks.ClickWorldMapActionButton = function(WorldQuests) 242
125 WorldQuests:Refresh('CLICK_MAP_ACTION_BUTTON') 243 function Module:OnMapInfo(isBrokenIsle, isZoomedOut, mapAreaID, isNewMap, isMapOpen)
126 end 244 if isNewMap or self.isStale then
127 callbacks.WorldMap_UpdateQuestBonusObjectives = function(WorldQuests) 245 print('|cFF0088FFOnMapInfo()|r, mapAreaID =', mapAreaID,'visible =', isMapOpen, 'changed =', isNewMap)
128 WorldQuests:UpdateTaskPOIs() 246 layoutDirty = true
129 end 247 self:Refresh('WORLD_MAP_CHANGED')
130 callbacks.WorldMapFrame_UpdateMap = function(WorldQuests) 248 end
131 WorldQuests:RefreshIfChanged('WMF_UPDATE')
132 end
133 callbacks.WorldMapScrollFrame_ReanchorQuestPOIs = function (WorldQuests)
134 WorldQuests:RefreshIfChanged('WMF_REANCHOR')
135 end
136
137 callbacks[BountyBoard] = {}
138 callbacks[BountyBoard].SetSelectedBountyIndex = function(WorldQuests)
139 WorldQuests:UpdateBounties('BOUNTY_SELECTED')
140 WorldQuests:Refresh('BOUNTY_SELECTED')
141 end
142
143 callbacks[ActionButton] = {}
144 callbacks[ActionButton].UpdateCastingState = function(WorldQuests)
145 WorldQuests:Refresh('CASTING_STATE_CHANGED')
146 end 249 end
147 250
148 function Module:OnConfigUpdate() 251 function Module:OnConfigUpdate()
149 --print('|cFFFFFF00OnConfigUpdate()|r') 252 --print('|cFFFFFF00OnConfigUpdate()|r')
150 if db.Config.FadeWhileGrouped then 253 if db.Config.FadeWhileGrouped then
156 if not db.Config.EnablePins then 259 if not db.Config.EnablePins then
157 for _, pin in pairs(db.QuestsByID) do 260 for _, pin in pairs(db.QuestsByID) do
158 pin:SetShown(false) 261 pin:SetShown(false)
159 end 262 end
160 end 263 end
161
162 ToggleButton.OnShow(self.Toggle)
163 end
164
165 local InternalHideButton = function(button, index)
166 button:Hide()
167 end
168 local InternalShowButton = function(button, index)
169 button:Show()
170 end 264 end
171 265
172 function Module:OnSecureHook(callbackName, func, ...) 266 function Module:OnSecureHook(callbackName, func, ...)
173 --rprint('|cFFFF4400'..callbackName..'|r', ...) 267 --rprint('|cFFFF4400'..callbackName..'|r', ...)
174 func(self, ...) 268 func(self, ...)
175 end 269 end
176 270
177 local defaults = {} 271 function Module:UpdateModifierState()
178 local REWARD_UNKNOWN = 768 272
179 function Module:OnLoad() 273 end
180 --print('|cFFFF4400'..self:GetName()..':OnLoad()')
181
182 self:SetParent(WorldMapFrame.UIElementsFrame)
183 WorldPlan:AddHandler(self, defaults)
184
185 for areaID, fileName in pairs(WORLD_QUEST_MAPS) do
186 db.QuestsByZone[areaID] = {}
187 end
188
189 -- WORLD_MAP_UPDATE and PLAYER_ENTERING_WORLD are passed down from a higher level
190 self:RegisterEvent('WORLD_QUEST_COMPLETED_BY_SPELL')
191 self:RegisterEvent('SUPER_TRACKED_QUEST_CHANGED')
192 self:RegisterEvent('SKILL_LINES_CHANGED')
193 --self:RegisterEvent('CURRENT_SPELL_CAST_CHANGED')
194 self:RegisterEvent('ARTIFACT_UPDATE')
195 self:RegisterEvent('QUEST_LOG_UPDATE')
196 end
197
198 local artifactKnowledgeMultiplier
199 local superTrackedQuestID
200 function Module:OnEvent (event, ...)
201
202 print('|cFFFFFF00OnEvent() '..event..'|r', GetTime(), ...)
203 if (event == 'QUEST_LOG_UPDATE') then
204 self:UpdateBounties(event)
205 elseif event == 'WORLD_QUEST_COMPLETED_BY_SPELL' then
206 local questID = ...
207 if questID and db.QuestsByID[questID] then
208 db.QuestsByID[questID].complete = true
209 self:ReleasePin(db.QuestsByID[questID])
210 end
211 self:Refresh(event)
212 elseif event == 'SKILL_LINES_CHANGED' or event == 'CURRENT_SPELL_CAST_CHANGED' then
213 self:Refresh(event)
214 elseif event == 'ARTIFACT_UPDATE' then
215 local akCheck = C_ArtifactUI.GetArtifactKnowledgeMultiplier()
216 if akCheck and (akCheck ~= artifactKnowledgeMultiplier) then
217 if artifactKnowledgeMultiplier then
218 --print('push artifact knowledge update', artifactKnowledgeMultiplier, 'to', akCheck)
219 for index, pin in pairs( db.QuestsByID) do
220 if pin.rewardType == REWARD_ARTIFACT_POWER then
221 db.log(pin.questID .. ' ' .. tostring(pin.title) .. ' Flagged for artifact power.')
222 pin.itemNumber = 0
223 pin.dataLoaded = nil
224 end
225 end
226 else
227
228 print('artifact knowledge multiplier is known', akCheck)
229 end
230 artifactKnowledgeMultiplier = akCheck
231 end
232 elseif event == 'SUPER_TRACKED_QUEST_CHANGED' then
233 if superTrackedQuestID and db.QuestsByID[superTrackedQuestID] then
234 db.QuestsByID[superTrackedQuestID].isStale = true
235 end
236 local newID = GetSuperTrackedQuestID()
237 if newID and db.QuestsByID[newID] then
238 db.QuestsByID[newID].isStale = true
239 end
240 end
241 end
242
243
244 function Module:OnUpdate(sinceLast)
245
246 if self.refreshBenchMarkTicker then
247 --print(self.refreshBenchMarkTicker)
248 self.refreshBenchMarkTicker = self.refreshBenchMarkTicker - 1
249
250 if self.refreshBenchMarkTicker == 0 then
251
252 self.refreshTime = floor((GetTime() - self.refreshBenchMark) * 1000)
253 self.debugMessage:SetText(self.refreshTime)
254 self.refreshBenchMarkTicker = nil
255 end
256 else
257 self.refreshBenchMark = GetTime()
258 end
259
260 if self.filtersDirty or self.isStale then
261 self:Refresh()
262 end
263 if #db.UpdatedPins >= 1 then
264 --print('|cFF00FF88pending update', #db.UpdatedPins)
265 self:UpdateNext()
266 end
267
268 end
269
270 function Module:OnMapInfo(isBrokenIsle, isZoomedOut, mapAreaID, isNewMap, isMapOpen)
271 if isNewMap or self.isStale then
272 print('|cFF0088FFOnMapInfo()|r, mapAreaID =', mapAreaID,'visible =', isMapOpen, 'changed =', isNewMap)
273 layoutDirty = true
274 self:Refresh('WORLD_MAP_CHANGED')
275 else
276
277 --print('|cFFFFFF00'..self:GetName()..':OnMapInfo()|r, mapAreaID =', mapAreaID,'visible =', isMapOpen, 'changed =', isNewMap)
278 end
279 end
280
281 274
282 function Module:UpdateTaskPOIs() 275 function Module:UpdateTaskPOIs()
283 canTargetQuests = SpellCanTargetQuest() 276 canTargetQuests = SpellCanTargetQuest()
284 local func = canTargetQuests and 'Show' or 'Hide'
285 for i = 1, NUM_WORLDMAP_TASK_POIS do 277 for i = 1, NUM_WORLDMAP_TASK_POIS do
286 local button = _G['WorldMapFrameTaskPOI'..i] 278 local poiFrame = _G['WorldMapFrameTaskPOI'..i]
287 if button and button.worldQuest then 279 if poiFrame and poiFrame.worldQuest then
288 button[func](button) 280 local pin = db.QuestsByID[poiFrame.questID]
289 end 281 if pin and pin.used and canTargetQuests and IsQuestIDValidSpellTarget(pin.questID) then
290 end 282 poiFrame:Show()
291 end 283 else
292 284 poiFrame:Hide()
293 local bountyQuests = {} 285 end
294 local bountyInfo = {} 286 end
295 287 end
296 local bountyDisplayLocation, bountyLockedQuestID, selectedBountyIndex, selectedBountyQuestID 288 end
289 -- re-anchors and scales pins that have had either of these changed due to data loading delays
290 function Module:UpdateNext()
291 --print('|cFF00FF88UpdateNext()')
292 local pin = tremove(db.UpdatedPins)
293
294 -- criteria state is asserted independently
295 pin:CheckFilterRules()
296 local scaleFactor = SCALE_FACTORS[(pin.dataLoaded and not pin.filtered) and scaleConstant or 1]
297 --print(pin.title, pin.dataLoaded and not pin.filtered, scaleFactor)
298 if pin.used then
299 pin:SetAnchor(nil, pin.x, pin.y, self.hostWidth, self.hostHeight, scaleFactor)
300 if pin:IsVisible() then
301 pin:Refresh()
302 else
303 pin.isStale = true
304 end
305 end
306 end
307
297 function Module:UpdateBounties(...) 308 function Module:UpdateBounties(...)
298 print('|cFF00FF88BountyInfo()|r', ...) 309 print('|cFF00FF88BountyInfo()|r', ...)
299 wipe(db.BountiesByFactionID) 310 wipe(db.BountiesByFactionID)
300 wipe(db.BountiesByQuestID) 311 wipe(db.BountiesByQuestID)
301 312
318 end 329 end
319 end 330 end
320 bountiesDirty = nil 331 bountiesDirty = nil
321 end 332 end
322 333
323 334 -- check current artifact knowledge and update pins accordingly
324 local totalPins = 0 335 function Module:UpdateArtifactPower(overrideLevel)
325 local TQ_GetQuestLocation = C_TaskQuest.GetQuestLocation 336 if InCombatLockdown() then
326 function Module:AcquirePin (info) 337 artifactPowerDirty = true
327 local questID = info.questId 338 return
328 if not questID then 339 end
329 return nil 340
330 end 341 print('|cFF00FF88UpdateArtifactPower()|r')
331 342 local _, akLevel = GetCurrencyInfo(1171)
332 if not QuestUtils_IsQuestWorldQuest(questID) then 343 if overrideLevel then
333 return nil 344 akLevel = overrideLevel
334 end 345 end
335 346
336 -- if we're grabbing a pin, the filters need to be checked 347 --db.print('current AK', akLevel)
337 local pin = db.QuestsByID[questID] 348 if akLevel and (akLevel ~= artifactKnowledgeLevel) or (not artifactKnowledgeLevel) then
338 if not pin then 349 --print('new ak level', akLevel)
339 local numFree = #db.FreePins 350 db.log('AK update ' .. tostring(artifactKnowledgeLevel) .. ' to '.. tostring(akLevel))
340 if numFree >= 1 then 351 for _, pin in pairs(db.QuestsByID) do
341 pin = tremove(db.FreePins, numFree) 352 if (pin.rewardType == REWARD_ARTIFACT_POWER) then
342 --print('|cFF00FF00Re-using', pin:GetName()) 353 print(pin.title, pin.itemNumber)
343 else 354 local newAP = pin:UpdateArtifactPower()
344 totalPins = totalPins + 1 355 if newAP then
345 local name = 'WorldPlanQuestMarker' .. numOverlays 356 pin.itemNumber = newAP
346 --print('|cFF00FF00Creating', name) 357 print(newAP)
347 pin = CreateFrame('Frame', name, WorldMapPOIFrame, 'WorldPlanQuestPin') 358 else
348 359 pin.dataLoaded = nil
349 pin:SetID(totalPins) 360 end
350 numOverlays = numOverlays + 1
351 --pin.iconBorder:SetVertexColor(0,0,0,1)
352 end
353 pin.questID = questID
354 pin.worldQuest = true
355 pin.throttle = pin.updateRate
356 pin.isNew = true
357 pin.currentWidth = nil
358 db.QuestsByID[questID] = pin
359 tinsert(db.UsedPins, pin)
360
361 end
362
363 if pin and info then
364 pin.inProgress = info.inProgress
365 pin.floor = info.floor
366 pin.numObjectives = info.numObjectives or 0
367 if info.x and info.y then
368 if (info.x ~= pin.x) or (info.y ~= pin.y) then
369 pin.isStale = true 361 pin.isStale = true
370 --rprint('|cFFFF4400SetCoords|r', info.x, info.y) 362 end
371 end 363 end
372 364 artifactKnowledgeLevel = akLevel
373 end 365 end
374 end 366 artifactPowerDirty = nil
375
376 pin.x = info.x or pin.x
377 pin.y = info.y or pin.y
378
379 if not HaveQuestData(questID) then
380 TQ_RequestPreloadRewardData(questID);
381 end
382
383
384 if (not pin.dataLoaded) then
385 local dataLoaded = pin:GetData()
386 if dataLoaded then
387 WorldPlan.dataFlush = true
388 else
389 isDataLoaded = false
390 end
391 end
392
393
394 pin.isActive = TQ_IsActive(questID)
395 pin:GetCriteriaState()
396 pin:CheckFilterRules()
397 --rprint(pin:GetID(), pin.filtered, pin.used)
398
399 return pin
400 end
401
402 -- remove from index and add it to the recycling heap
403 function Module:ReleasePin (pin)
404
405 local id = pin.questID
406 if id then
407 db.QuestsByID[id] = nil
408
409 for i, zone in pairs(db.QuestsByZone) do
410 --print('-', i, zone[i])
411 zone[id] = nil
412 end
413 db.TasksByID[id] = nil
414 end
415 pin:Reset()
416 tinsert(db.FreePins, pin)
417
418 WorldPlan.dataFlush = true
419 --print('|cFF00FF00-'.. (pin.mapID and GetMapNameByID(pin.mapID) or '???') ..'|r', id, pin.title)
420 end
421
422 -- re-anchors and scales pins that have had either of these changed due to data loading delays
423 function Module:UpdateNext()
424 --print('|cFF00FF88UpdateNext()')
425 local pin = tremove(db.UpdatedPins)
426 pin:CheckFilterRules()
427
428 local scaleFactor = SCALE_FACTORS[(pin.dataLoaded and not pin.filtered) and scaleConstant or 1]
429 --print(pin.title, pin.dataLoaded and not pin.filtered, scaleFactor)
430 if pin.used then
431 pin:SetAnchor(nil, pin.x, pin.y, self.hostWidth, self.hostHeight, scaleFactor)
432 pin:OnShow()
433 end
434
435
436 end
437
438 function Module:Debug(...)
439 print(...)
440 end 367 end
441 368
442 local msg = '|cFF00FF88WorldQuests:Refresh()|r|cFF00FFFF' 369 local msg = '|cFF00FF88WorldQuests:Refresh()|r|cFF00FFFF'
443 local lastRefresh
444 function Module:Refresh(...) 370 function Module:Refresh(...)
445 --
446
447 if not self:IsVisible() then 371 if not self:IsVisible() then
448 print('|cFFFF4400Refresh()|r', ...) 372 print('|cFFFF4400Refresh()|r', ...)
449 --layoutDirty = true 373 --layoutDirty = true
450 return 374 return
451 else 375 else
480 --print(' bounties dirty, pushing that') 404 --print(' bounties dirty, pushing that')
481 self:UpdateBounties() 405 self:UpdateBounties()
482 end 406 end
483 --]] 407 --]]
484 408
485 409 if artifactPowerDirty and not InCombatLockdown() then
410 self:UpdateArtifactPower()
411 end
486 -- calculate quests shown 412 -- calculate quests shown
487 numShown = 0 413 numShown = 0
488 numLoaded = 0 414 numLoaded = 0
489 for questID, pin in pairs(db.QuestsByID) do 415 for questID, pin in pairs(db.QuestsByID) do
490 local oV = pin:IsShown() 416 local oV = pin:IsShown()
508 end 434 end
509 --]] 435 --]]
510 pin.hideReason = "Not used in map area " .. (db.currentMapID) 436 pin.hideReason = "Not used in map area " .. (db.currentMapID)
511 pin:SetShown(false) 437 pin:SetShown(false)
512 end 438 end
513 end 439
514 440 end
515
516 --print('flags ', layoutDirty, self.isStale) 441 --print('flags ', layoutDirty, self.isStale)
517 --print(' ', numShown, 'shown,', numLoaded, 'with data') 442 --print(' ', numShown, 'shown,', numLoaded, 'with data')
518 if numShown > numLoaded then 443
519 self.Status:Show()
520 end
521 444
522 -- 445 --
523 self.refreshBenchMark = GetTime() 446 self.refreshBenchMark = GetTime()
524 self.refreshBenchMarkTicker = 2 447 self.refreshBenchMarkTicker = 2
525 print('starting bench', self.refreshBenchMark) 448 print('starting bench', self.refreshBenchMark)
526 449
527 -- 450 --
528 451
529 layoutDirty = nil 452 layoutDirty = nil
530 self.isStale = nil 453 self.isStale = nil
531 self.sizesDirty = nil 454 self.sizesDirty = nil
532 self.isZoomDirty = nil 455 self.isZoomDirty = nil
533 456
534 end 457 if WorldPlanSummary then
535 458 WorldPlanSummary.isStale = true
536 local refreshReason 459 end
460
461 WorldPlan.dataFlush = true
462 end
463
537 function Module:RefreshIfChanged(event) 464 function Module:RefreshIfChanged(event)
538 local scaleCheck = WorldMapDetailFrame:GetScale() 465 local scaleCheck = WorldMapDetailFrame:GetScale()
539 refreshReason = nil 466 refreshReason = nil
540 if scaleCheck ~= currentScale then 467 if scaleCheck ~= currentScale then
541 refreshReason = 'map scale updated' 468 refreshReason = 'map scale updated'
546 end 473 end
547 if not refreshReason then 474 if not refreshReason then
548 return 475 return
549 end 476 end
550 477
551
552 if self:IsVisible() then 478 if self:IsVisible() then
553 print('|cFF00FFFFRefreshIfChanged()|r', refreshReason) 479 print('|cFF00FFFFRefreshIfChanged()|r', refreshReason)
554 self:Refresh(event) 480 self:Refresh(event)
555 else 481 else
556 print('|cFF00FFFFRefreshIfChanged()|r', refreshReason) 482 print('|cFF00FFFFRefreshIfChanged()|r', refreshReason)
557 self.isStale = true 483 self.isStale = true
558 end 484 end
559 end 485 end
560 486
561 -- update visibility states of all pins 487 -- marks a pin set for passive update
562 function Module:MarkAllPins(pins) 488 function Module:MarkAllPins(pins)
563 --print(' |cFFFFFF00'..self:GetName()..':MarkAllPins()|r', pins) 489 --print(' |cFFFFFF00'..self:GetName()..':MarkAllPins()|r', pins)
564 pins = pins or db.QuestsByID 490 pins = pins or db.QuestsByID
565 for questID, pin in pairs(pins) do 491 for questID, pin in pairs(pins) do
566 pin.isStale = true 492 pin.isStale = true
567 --rprint('|cFF00FF00filter', pin.questID, pin.filtered, 'used:', pin.used) 493 --rprint('|cFF00FF00filter', pin.questID, pin.filtered, 'used:', pin.used)
568 end 494 end
569 end 495 end
570 496
571 -- Updates quest markers in taskInfo while associating them with the given map 497 -- Walks the current map tree and fires updates as needed
498 function Module:UpdateAnchors ()
499 wipe(self.UsedPositions)
500 print(' |cFF00FF00'..self:GetName()..':UpdateAnchors()')
501 local hostWidth, hostHeight = WorldMapPOIFrame:GetSize()
502
503 if (hostWidth ~= self.hostWidth) or (hostHeight ~= self.hostHeight) then
504 self.hostWidth, self.hostHeight = hostWidth, hostHeight
505 layoutDirty = true
506 end
507
508 --rprint('|cFF00FF00'..self:GetName()..':UpdateAnchors()')
509 local mapFileName, textureHeight, textureWidth, isMicroDungeon, microDungeonMapName = GetMapInfo()
510 if isMicroDungeon then
511 return
512 end
513
514 isDataLoaded = true
515 local taskInfo = TQ_GetQuestsForPlayerByMapID(db.currentMapID)
516 if taskInfo then
517 self:UpdateQuestsForMap(taskInfo, db.currentMapID)
518 end
519 local numZones = MC_GetNumZones(db.currentMapID)
520 if numZones then
521 for i = 1, numZones do
522 local mapAreaID = MC_GetZoneInfo(db.currentMapID, i)
523 local taskInfo = TQ_GetQuestsForPlayerByMapID(mapAreaID, db.currentMapID)
524
525 db.QuestsByZone[mapAreaID] = db.QuestsByZone[mapAreaID] or {}
526
527 if taskInfo then
528 self:UpdateQuestsForMap(taskInfo, mapAreaID)
529 end
530 end
531 end
532 end
533
534 -- Applies map association to the pins corresponding with each TaskInfo item
572 function Module:UpdateQuestsForMap(taskInfo, mapID) 535 function Module:UpdateQuestsForMap(taskInfo, mapID)
573 print('|cFF00FF00UpdateQuestsForMap()|r', GetMapNameByID(mapID), GetMapNameByID(db.currentMapID), layoutDirty) 536 print('|cFF00FF00UpdateQuestsForMap()|r', GetMapNameByID(mapID), GetMapNameByID(db.currentMapID), layoutDirty)
574 if db.QuestsByZone[mapID] then 537 if db.QuestsByZone[mapID] then
575 wipe(db.QuestsByZone[mapID]) 538 wipe(db.QuestsByZone[mapID])
576 end 539 elseif db.isBrokenIsle then
577 540 continentScanned = true
541 end
578 542
579 for index, info in pairs(taskInfo) do 543 for index, info in pairs(taskInfo) do
580
581 local questID, x, y = info.questId, info.x, info.y 544 local questID, x, y = info.questId, info.x, info.y
582 local pin = self:AcquirePin(info) 545 local pin = self:AcquirePin(info)
583 546
584 if pin then 547 if pin then
585 pin.used = true 548 pin.used = true
586 print(pin.title, pin.isStale, layoutDirty, (pin.owningFrame ~= WorldMapFrame)) 549 print(pin.title, pin.isStale, layoutDirty, (pin.owningFrame ~= WorldMapFrame))
587 if pin:IsShown() and (layoutDirty or pin.isStale or (pin.owningFrame ~= WorldMapFrame)) then 550 if pin:IsShown() and (layoutDirty or pin.isStale or (pin.owningFrame ~= WorldMapFrame)) then
588 local scaleFactor = SCALE_FACTORS[(pin.dataLoaded and not pin.filtered) and scaleConstant or 1] 551 local scaleFactor = SCALE_FACTORS[(not pin.filtered and scaleConstant) or 1]
589 pin.owningFrame = WorldMapFrame 552 pin.owningFrame = WorldMapFrame
590 pin:SetAnchor(WorldMapPOIFrame, x, y, self.hostWidth, self.hostHeight, scaleFactor) 553 pin:SetAnchor(WorldMapPOIFrame, x, y, self.hostWidth, self.hostHeight, scaleFactor)
591 if pin.isStale then 554 if pin.isStale then
592 pin:Refresh('WORLDMAP_REFRESH ' .. GetTime()) 555 pin:Refresh('WORLDMAP_REFRESH ' .. GetTime())
593 end 556 end
598 end 561 end
599 562
600 if db.QuestsByZone[mapID] and pin.used then 563 if db.QuestsByZone[mapID] and pin.used then
601 db.QuestsByZone[mapID][questID] = pin 564 db.QuestsByZone[mapID][questID] = pin
602 end 565 end
603 566 end
604 end 567 end
605 end 568 end
606 end 569
607 570 -- locates or creates a corresponding pin frame for the provided TaskInfo data
608 -- Used to refresh the visible quest markers 571 function Module:AcquirePin (info)
609 function Module:UpdateAnchors () 572 local questID = info.questId
610 wipe(self.UsedPositions) 573 if not (questID and QuestUtils_IsQuestWorldQuest(questID)) then
611 print(' |cFF00FF00'..self:GetName()..':UpdateAnchors()') 574 return nil
612 local hostWidth, hostHeight = WorldMapPOIFrame:GetSize() 575 end
613 576
614 if (hostWidth ~= self.hostWidth) or (hostHeight ~= self.hostHeight) then 577 local pin = db.QuestsByID[questID]
615 self.hostWidth, self.hostHeight = hostWidth, hostHeight 578 if not pin then
616 layoutDirty = true 579 local numFree = #db.FreePins
617 end 580 if numFree >= 1 then
618 581 pin = tremove(db.FreePins, numFree)
619 582 print('|cFF00FF00Re-using', pin:GetName())
620 --rprint('|cFF00FF00'..self:GetName()..':UpdateAnchors()') 583 else
621 local mapFileName, textureHeight, textureWidth, isMicroDungeon, microDungeonMapName = GetMapInfo() 584 totalPins = totalPins + 1
622 if isMicroDungeon then 585 local name = 'WorldPlanQuestMarker' .. numOverlays
623 return 586 print('|cFF00FF00Creating', name)
624 end 587 pin = CreateFrame('Frame', name, WorldMapPOIFrame, 'WorldPlanQuestPin')
625 588
626 isDataLoaded = true 589 pin:SetID(totalPins)
627 local taskInfo = TQ_GetQuestsForPlayerByMapID(db.currentMapID) 590 numOverlays = numOverlays + 1
628 if taskInfo then 591 --pin.iconBorder:SetVertexColor(0,0,0,1)
629 self:UpdateQuestsForMap(taskInfo, db.currentMapID) 592 end
630 end 593 pin.questID = questID
631 local numZones = MC_GetNumZones(db.currentMapID) 594 pin.worldQuest = true
632 if numZones then 595 pin.throttle = pin.updateRate
633 for i = 1, numZones do 596 pin.isNew = true
634 local mapAreaID = MC_GetZoneInfo(db.currentMapID, i) 597 pin.currentWidth = nil
635 local taskInfo = TQ_GetQuestsForPlayerByMapID(mapAreaID, db.currentMapID) 598 db.QuestsByID[questID] = pin
636 599 tinsert(db.UsedPins, pin)
637 db.QuestsByZone[mapAreaID] = db.QuestsByZone[mapAreaID] or {} 600 end
638 601
639 if taskInfo then 602 if IsQuestComplete(questID) then
640 self:UpdateQuestsForMap(taskInfo, mapAreaID) 603 pin:Release()
641 end 604 return nil
642 end 605 elseif info then
643 end 606 pin.inProgress = info.inProgress
644 end 607 pin.floor = info.floor
645 608 pin.numObjectives = info.numObjectives or 0
646 function ToggleButton:OnShow() 609 if info.x and info.y then
647 self:SetChecked(db.Config.EnablePins and true or false) 610 if (info.x ~= pin.x) or (info.y ~= pin.y) then
648 end 611 pin.isStale = true
649 function ToggleButton:OnClick() 612 --rprint('|cFFFF4400SetCoords|r', info.x, info.y)
650 --print(self:GetChecked()) 613 end
651 db.Config.EnablePins = self:GetChecked() 614 end
652 _G.WorldPlan:OnConfigUpdate() 615 end
653 end 616
617 pin.x = info.x or pin.x
618 pin.y = info.y or pin.y
619
620 if not HaveQuestRewardData(questID) then
621 TQ_RequestPreloadRewardData(questID);
622 end
623
624 if (not pin.dataLoaded) then
625 local dataLoaded = pin:GetData()
626 if dataLoaded then
627 WorldPlan.dataFlush = true
628 else
629 isDataLoaded = false
630 end
631 end
632
633 pin.isActive = TQ_IsActive(questID)
634 pin:GetCriteriaState()
635 pin:CheckFilterRules()
636 --rprint(pin:GetID(), pin.filtered, pin.used)
637 return pin
638 end
639
640 function Module:Debug(...)
641 print(...)
642 end