comparison WorldPlan.lua @ 33:be4db60219ca

WorldPlan: - Toggling a reward filter cancels out other types by default. Use right mouse to clear. - Fixed filter bar info falling out of sync after player-triggered world map updates. ClassPlan: - Available missions are now recorded; the mission list can be toggled between in-progress and available by clicking the heading.
author Nenue
date Wed, 02 Nov 2016 17:25:07 -0400
parents e8679ecb48d8
children 0100d923d8c3
comparison
equal deleted inserted replaced
32:e8679ecb48d8 33:be4db60219ca
1 -- WorldPlan.lua 1 -- WorldPlan.lua
2 -- Created: 8/16/2016 8:19 AM 2 -- Created: 8/16/2016 8:19 AM
3 -- %file-revision% 3 -- %file-revision%
4 4
5 local addonName, db = ...
6
7 local ICON_UNKNOWN = "Interface\\ICONS\\inv_misc_questionmark"
8 local ICON_MONEY = "Interface\\Buttons\\UI-GroupLoot-Coin-Up"
9
10 local POI_BORDER_MASK = "Interface\\Minimap\\UI-Minimap-Background"
11 local POI_BORDER_FILL = "Interface\\BUTTONS\\YELLOWORANGE64"
12 local POI_BORDER_BLUE = "Interface\\BUTTONS\\GRADBLUE"
13 local POI_BORDER_RED = "Interface\\BUTTONS\\RedGrad64"
14 local POI_BORDER_YELLOW = "Interface\\BUTTONS\\YELLOWORANGE64"
15 local POI_BORDER_GREEN = "Interface\\BUTTONS\\GREENGRAD64"
16
17 WorldPlanCore = { 5 WorldPlanCore = {
18 defaults = {}, 6 defaults = {},
19 modules = {}, 7 modules = {},
20 } 8 FilterOptions = {},
21 WorldPlanQuestsMixin = { 9 UsedFilters = {},
22 QuestsByZone = {}, 10 QuestsByZone = {},
23 QuestsByID = {}, 11 QuestsByID = {},
24 freePins = {}, 12 TaskQueue = {},
25 } 13 }
26 WorldPlanPOIMixin = {}
27 WorldPlanFilterPinMixin = setmetatable({ QuestsByID = {}, freePins = {} }, {__tostring = function() return 'QuestHandler' end})
28 local WorldPlanFlightMapMixin = setmetatable({}, {__tostring = function() return 'FlightMapHandler' end})
29 local WorldQuests = WorldPlanQuestsMixin
30
31
32 local WorldPlan = WorldPlanCore 14 local WorldPlan = WorldPlanCore
33 local QuestPOI = WorldPlanPOIMixin 15
34 local FilterPin = WorldPlanFilterPinMixin 16 local print = DEVIAN_WORKSPACE and function(...) _G.print('WP', ...) end or function() end
35 local WP_VERSION = "1.0" 17 local WP_VERSION = "1.0"
36 18 local tinsert, pairs, floor = table.insert, pairs, floor
37 local db
38 local print = DEVIAN_WORKSPACE and function(...) _G.print('WP', ...) end or function() end
39 local qprint = DEVIAN_WORKSPACE and function(...) _G.print('POI', ...) end or function() end
40 local iprint = DEVIAN_WORKSPACE and function(...) _G.print('ItemScan', ...) end or function() end
41 local wqprint = DEVIAN_WORKSPACE and function(...) _G.print('WorldQuests', ...) end or function() end
42 local fbprint = DEVIAN_WORKSPACE and function(...) _G.print('FilterBar', ...) end or function() end
43
44 local wipe, tremove, tinsert, pairs, floor, tContains = table.wipe, table.remove, table.insert, pairs, floor, tContains
45 local TQ_GetQuestsForPlayerByMapID = C_TaskQuest.GetQuestsForPlayerByMapID -- This function is not yet documented
46 local TQ_GetQuestZoneID = C_TaskQuest.GetQuestZoneID
47 local TQ_IsActive = C_TaskQuest.IsActive
48 local ITEM_QUALITY_COLORS = ITEM_QUALITY_COLORS 19 local ITEM_QUALITY_COLORS = ITEM_QUALITY_COLORS
49 local WorldMap_DoesWorldQuestInfoPassFilters = WorldMap_DoesWorldQuestInfoPassFilters 20 local BROKEN_ISLES_ID = 1007
50 local QuestMapFrame_IsQuestWorldQuest = QuestMapFrame_IsQuestWorldQuest
51 local GameTooltip = GameTooltip
52 local GetItemIcon = GetItemIcon
53
54
55 local GetMapInfo, QuestPOIGetIconInfo = GetMapInfo, QuestPOIGetIconInfo
56 local GetQuestTagInfo, HaveQuestData = GetQuestTagInfo, HaveQuestData
57 local GetNumQuestLogRewards, GetNumQuestLogRewardCurrencies, GetQuestLogRewardMoney = GetNumQuestLogRewards, GetNumQuestLogRewardCurrencies, GetQuestLogRewardMoney
58 local GetQuestLogRewardInfo, GetQuestLogRewardCurrencyInfo, GetMoneyString = GetQuestLogRewardInfo, GetQuestLogRewardCurrencyInfo, GetMoneyString
59
60 local GetCurrentMapAreaID, GetMapNameByID, GetSuperTrackedQuestID = GetCurrentMapAreaID, GetMapNameByID, GetSuperTrackedQuestID 21 local GetCurrentMapAreaID, GetMapNameByID, GetSuperTrackedQuestID = GetCurrentMapAreaID, GetMapNameByID, GetSuperTrackedQuestID
61 local MC_GetNumZones, MC_GetZoneInfo = C_MapCanvas.GetNumZones, C_MapCanvas.GetZoneInfo
62
63 22
64 -- default color templates 23 -- default color templates
65 local ARTIFACT_COLOR = ITEM_QUALITY_COLORS[LE_ITEM_QUALITY_ARTIFACT]
66 local MONEY_COLOR = {hex ='|cFFFFFF00', r=1, g=1, b=0}
67 local COMMON_COLOR = ITEM_QUALITY_COLORS[LE_ITEM_QUALITY_COMMON]
68 local DEFAULT_TYPE = { 24 local DEFAULT_TYPE = {
69 a = 1, 25 a = 1,
70 r = 1, g = 1, b = 1, 26 r = 1, g = 1, b = 1,
71 x = 0, y = 0, 27 x = 0, y = 0,
72 desaturated = true, 28 desaturated = true,
73 pinMask = POI_BORDER_MASK, 29 pinMask = "Interface\\Minimap\\UI-Minimap-Background",
74 rewardMask = POI_BORDER_MASK, 30 rewardMask = "Interface\\Minimap\\UI-Minimap-Background",
75 texture = POI_BORDER_FILL, 31 texture = "Interface\\BUTTONS\\YELLOWORANGE64",
76 continent = { 32 continent = {
77 PinSize = 14, 33 PinSize = 14,
78 Border = 2, 34 Border = 2,
79 TrackingBorder = 1, 35 TrackingBorder = 1,
80 TagSize = 6, 36 TagSize = 6,
111 NotifyWhenNewQuests = true, 67 NotifyWhenNewQuests = true,
112 EnablePins = true, 68 EnablePins = true,
113 FadeWhileGrouped = true, 69 FadeWhileGrouped = true,
114 } 70 }
115 71
116 -- Summary header structure
117
118 local REWARD_CASH = WORLD_QUEST_REWARD_TYPE_FLAG_GOLD
119 local REWARD_ARTIFACT_POWER = WORLD_QUEST_REWARD_TYPE_FLAG_ARTIFACT_POWER
120 local REWARD_GEAR = WORLD_QUEST_REWARD_TYPE_FLAG_EQUIPMENT
121 local REWARD_CURRENCY = WORLD_QUEST_REWARD_TYPE_FLAG_ORDER_RESOURCES
122 local REWARD_REAGENT = WORLD_QUEST_REWARD_TYPE_FLAG_MATERIALS
123
124
125 local LE_QUEST_TAG_TYPE_PVP = LE_QUEST_TAG_TYPE_PVP
126 local LE_QUEST_TAG_TYPE_PET_BATTLE = LE_QUEST_TAG_TYPE_PET_BATTLE
127 local LE_QUEST_TAG_TYPE_DUNGEON = LE_QUEST_TAG_TYPE_DUNGEON
128 local LE_QUEST_TAG_TYPE_PROFESSION = LE_QUEST_TAG_TYPE_PROFESSION
129 local LE_QUEST_TAG_TYPE_NORMAL = LE_QUEST_TAG_TYPE_NORMAL
130 WorldPlanCore.BrokenIsleID = BROKEN_ISLES_ID
131 WorldPlanCore.FilterStyle = POI_FILTER_STYLE
132
133 WorldPlanCore.FilterOptions = {}
134 WorldPlanCore.UsedFilters = {}
135
136
137 -- operating flags 72 -- operating flags
138 local superTrackedID 73 local superTrackedID
139 local currentMapName 74 local currentMapName
140 local hasNewQuestPins 75 local hasNewQuestPins
141 local isContinentMap 76 local isContinentMap
142 local numPins = 0
143 local FilterInclusions = {rewardType = {}, worldQuestType = {}, factionID = {}}
144 local NotificationTypes = {}
145 local ZoneInfo = {}
146 local SummaryHeaders = {}
147
148 local FreePins = {}
149 local NumPinFrames = 1
150
151 local hasPendingQuestData 77 local hasPendingQuestData
152 local notifyPlayed 78 local notifyPlayed
153 local scanner, wmtt, WorldMapPOIFrame 79 local scanner, wmtt, WorldMapPOIFrame
154 80
155
156 local tasksQueue = {}
157 local function OnNext (func)
158 if #tasksQueue == 0 then
159 _G.WorldPlan:SetScript('OnUpdate', function()
160 local func = tremove(tasksQueue, 1)
161 if func then
162 func()
163 end
164 if #tasksQueue == 0 then
165 _G.WorldPlan:SetScript('OnUpdate', nil)
166 end
167 end)
168 end
169 print('inserting task #', #tasksQueue+1, func)
170 tinsert(tasksQueue, func)
171 end
172
173 -- update a masked texture without messing up its blending mask
174 local SetMaskedTexture = function(region, file, mask)
175 mask = mask or POI_BORDER_MASK
176 region:SetMask(nil)
177 region:SetTexture(file)
178 region:SetMask(mask)
179 end
180 81
181 -- tracking menu toggler 82 -- tracking menu toggler
182 local DropDown_OnClick = function(self) 83 local DropDown_OnClick = function(self)
183 local key = self.value 84 local key = self.value
184 if key then 85 if key then
186 WorldPlanData[key] = nil 87 WorldPlanData[key] = nil
187 else 88 else
188 WorldPlanData[key] = true 89 WorldPlanData[key] = true
189 end 90 end
190 end 91 end
191 WorldPlan:Refresh() 92 _G.WorldPlan:Refresh()
192 end 93 end
193 94
194 function WorldPlan:print(...) 95 function WorldPlan:print(...)
195 local msg 96 local msg
196 for i = 1, select('#', ...) do 97 for i = 1, select('#', ...) do
236 for index, color in pairs(ITEM_QUALITY_COLORS) do 137 for index, color in pairs(ITEM_QUALITY_COLORS) do
237 self:AddTypeInfo(self, index, { r = color.r, g = color.g, b = color.b, hex = color.hex, }) 138 self:AddTypeInfo(self, index, { r = color.r, g = color.g, b = color.b, hex = color.hex, })
238 end 139 end
239 140
240 WorldPlan = self 141 WorldPlan = self
241 scanner = _G.WorldPlanTooltip
242 wmtt = _G.WorldMapTooltip
243 WorldMapPOIFrame = _G.WorldMapPOIFrame
244 142
245 WorldPlan:print('v'..WP_VERSION) 143 WorldPlan:print('v'..WP_VERSION)
246 144
247 self:RegisterEvent("QUESTLINE_UPDATE") 145 self:RegisterEvent("QUESTLINE_UPDATE")
248 self:RegisterEvent("QUEST_LOG_UPDATE") 146 self:RegisterEvent("QUEST_LOG_UPDATE")
258 function WorldPlan:OnShow() 156 function WorldPlan:OnShow()
259 print(self:GetName()..':OnShow()') 157 print(self:GetName()..':OnShow()')
260 if self.isStale then 158 if self.isStale then
261 self:Refresh() 159 self:Refresh()
262 end 160 end
263
264 end 161 end
265 162
266 function WorldPlan:OnEvent (event, ...) 163 function WorldPlan:OnEvent (event, ...)
267 print() 164 print()
268 print(event, self.initialized) 165 print(event, 'init:', self.initialized)
269 if event == 'ADDON_LOADED' then 166 if event == 'ADDON_LOADED' then
270 local addon = ... 167 local addon = ...
271 if addon == "Blizzard_FlightMap" then 168 if addon == "Blizzard_FlightMap" then
272 print('do mixin junk') 169 print('do mixin junk')
273 self.OnFlightMapLoaded() 170 self.OnFlightMapLoaded()
274 171
275 end 172 end
276 if IsLoggedIn() and not self.initialized then 173 if IsLoggedIn() and not self.initialized then
277 self:Setup() 174 self:Setup()
278 end 175 end
279 elseif event == 'WORLD_MAP_UPDATE' then 176 else
280 self.currentMapID = GetCurrentMapAreaID() 177 if event == 'WORLD_MAP_UPDATE' then
281 print('|cFFFF4400currentMapID =', self.currentMapID) 178 self.currentMapID = GetCurrentMapAreaID()
179 self.isContinentMap = (self.currentMapID == BROKEN_ISLES_ID)
180 print('|cFFFF4400currentMapID =', self.currentMapID)
181 --self.isStale = true
182 end
183
184 for i, module in ipairs(self.modules) do
185 if module.OnEvent then
186 print(' |cFF0088FF'..module:GetName() .. ':OnEvent()|r')
187 module:OnEvent(event, ...)
188 end
189 end
190 end
191 end
192
193 function WorldPlanCore:OnNext(func)
194 tinsert(self.TaskQueue, func)
195 end
196
197 function WorldPlanCore:OnUpdate()
198 if #self.TaskQueue >= 1 then
199 local func = tremove(self.TaskQueue, 1)
200 if func then
201 func()
202 end
203
204 end
205
206 if self.isStale then
207 print('|cFF00FF00pushing global update')
208 self.isStale = nil
282 self:Refresh() 209 self:Refresh()
283 else 210 else
284 for i, module in ipairs(self.modules) do 211 for i, module in ipairs(self.modules) do
285 if module.OnEvent then 212 if module.isStale then
286 print('forwarding to', tostring(module)) 213 print('|cFF00FF00internal '..module:GetName()..':Refresh()|r')
287 module:OnEvent(event, ...) 214 module:Refresh()
288 end 215 end
289 end 216 end
290 end 217 end
291 end 218 end
292
293 219
294 function WorldPlan:Setup () 220 function WorldPlan:Setup ()
295 if not WorldPlanData then 221 if not WorldPlanData then
296 WorldPlanData = {key = 0 } 222 WorldPlanData = {key = 0 }
297 end 223 end
321 end 247 end
322 end 248 end
323 self.initialized = true 249 self.initialized = true
324 250
325 hooksecurefunc("UIDropDownMenu_Initialize", self.OnDropDownInitialize) 251 hooksecurefunc("UIDropDownMenu_Initialize", self.OnDropDownInitialize)
252
253 hooksecurefunc("WorldMapTrackingOptionsDropDown_OnClick", function(button)
254 print("|cFF0088FFWorldMapTrackingOptionsDropDown_OnClick|r")
255 local value = button.value
256 if (value == "worldQuestFilterOrderResources" or value == "worldQuestFilterArtifactPower" or
257 value == "worldQuestFilterProfessionMaterials" or value == "worldQuestFilterGold" or
258 value == "worldQuestFilterEquipment") then
259 self:Refresh(true)
260 end
261 end)
326 end 262 end
327 263
328 function WorldPlan:AddTypeInfo(owner, id, info) 264 function WorldPlan:AddTypeInfo(owner, id, info)
329 self.Types[owner] = self.Types[owner] or {} 265 self.Types[owner] = self.Types[owner] or {}
330 self.Types[owner][id] = info 266 self.Types[owner][id] = info
396 if not self.initialized then 332 if not self.initialized then
397 return 333 return
398 end 334 end
399 335
400 for i, module in ipairs(self.modules) do 336 for i, module in ipairs(self.modules) do
401 if module.Reset then
402 print(module, 'Reset()')
403 module:Reset()
404 end
405 end
406
407 for i, module in ipairs(self.modules) do
408 if module.Refresh then 337 if module.Refresh then
409 print(module, 'Refresh()') 338 print('|cFF00FF00external '..module:GetName()..':Refresh()|r')
410 module:Refresh() 339 module:Refresh(forced)
411 end
412 end
413
414 for i, module in ipairs(self.modules) do
415 if module.Cleanup then
416 print(module, 'Cleanup()')
417 module:Cleanup()
418 end
419 end
420 end
421 function WorldPlan:UpdateAnchors ()
422 for i, module in ipairs(self.modules) do
423 if module.UpdateAnchors then
424 module:UpdateAnchors()
425 end 340 end
426 end 341 end
427 end 342 end
428 343
429 -- insert visual options into the tracking button menu 344 -- insert visual options into the tracking button menu
492 end 407 end
493 408
494 -------------------------------------------------------------------------------------------------------------------- 409 --------------------------------------------------------------------------------------------------------------------
495 -------------------------------------------------------------------------------------------------------------------- 410 --------------------------------------------------------------------------------------------------------------------
496 411
497 local PinBaseIndex = 1600
498 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
499
500 -- maps where we do our own anchors
501 local CONTINENT_MAPS = { [BROKEN_ISLES_ID] = BROKEN_ISLES_ID, }
502 local WORLD_QUEST_MAPS = { [DALARAN_ID] = 'Dalaran70', [AZSUNA_ID] = 'Azsuna', [VALSHARAH_ID] = "Val'sharah",
503 [HIGHMOUNTAIN_ID] = 'Highmountain', [STORMHEIM_ID] = 'Stormheim', [SURAMAR_ID] = 'Suramar', [EOA_ID] = 'EyeOfAszhara', }
504
505 function WorldQuests:Setup()
506
507
508 for mapID, mapName in pairs(WORLD_QUEST_MAPS) do
509 self.QuestsByZone[mapID] = {}
510 end
511
512
513 -- refresh positions any time blizzard does so (i.e. mousewheel zoom)
514 hooksecurefunc("WorldMapScrollFrame_ReanchorQuestPOIs", function()
515 self:Refresh(true)
516 end)
517
518 -- hide the original world quest POIs
519 hooksecurefunc("WorldMap_UpdateQuestBonusObjectives", function()
520 for i = 1, NUM_WORLDMAP_TASK_POIS do
521 local button = _G['WorldMapFrameTaskPOI'..i]
522 if button and button.worldQuest then
523 button:Hide()
524 end
525 end
526 end)
527
528 hooksecurefunc("WorldMapTrackingOptionsDropDown_OnClick", function(button)
529 print("|cFF0088FFWorldMapTrackingOptionsDropDown_OnClick|r")
530 local value = button.value
531 if (value == "worldQuestFilterOrderResources" or value == "worldQuestFilterArtifactPower" or
532 value == "worldQuestFilterProfessionMaterials" or value == "worldQuestFilterGold" or
533 value == "worldQuestFilterEquipment") then
534 self:Refresh(true)
535 end
536 end)
537 end
538
539 local defaults = {}
540 function WorldQuests:OnLoad()
541 print('|cFF00FF88'..self:GetName()..':OnLoad')
542
543 WorldPlan:AddHandler(self, defaults)
544
545 local rgbWhite = {1, 1, 1}
546 WorldPlan:AddTypeInfo(self, REWARD_REAGENT, { r = 0, g = 1, b = 1 })
547 WorldPlan:AddTypeInfo(self, REWARD_ARTIFACT_POWER, { r = 1, g = .25, b = .5, hasNumeric = true, numberRGB = rgbWhite })
548 WorldPlan:AddTypeInfo(self, REWARD_GEAR, { r = .1, g = .2, b = 1 })
549 WorldPlan:AddTypeInfo(self, REWARD_CURRENCY, { r = 1, g = 1, b = 0, hasNumeric = true, numberRGB = {1,1,0}, })
550 WorldPlan:AddTypeInfo(self, REWARD_CASH, { r = 0, g = 0, b = 0, })
551
552 for areaID, fileName in pairs(WORLD_QUEST_MAPS) do
553 self.QuestsByZone[areaID] = {}
554 end
555
556 self:RegisterEvent('QUEST_LOG_UPDATE')
557 self:RegisterEvent('WORLD_QUEST_COMPLETED_BY_SPELL')
558 self:RegisterEvent('SKILL_LINES_CHANGED')
559
560
561 end
562
563 function WorldQuests:OnEvent (event, ...)
564 local print = wqprint
565 print('|cFFFFFF00'..self:GetName()..':OnEvent()'..event..'|r', GetTime(), ...)
566 if event == 'QUEST_LOG_UPDATE' then
567 local questID, added = ...
568 if questID and added then
569 local questPOI = self:AcquirePin(questID)
570 self.hasUpdate, self.isPending = questPOI:RefreshData()
571 else
572 self:RefreshData()
573 end
574 print('WorldMapFrame', WorldMapFrame:IsVisible(), 'hasUpdates:', self.hasUpdate)
575 elseif event == 'WORLD_QUEST_COMPLETED_BY_SPELL' then
576 local questID = ...
577 if questID and self.QuestsByID[questID] then
578 self:ReleasePin(self.QuestsByID[questID])
579 end
580 elseif event == 'SKILL_LINES_CHANGED' then
581 self.hasUpdate = true
582 end
583 end
584
585 function WorldQuests:OnUpdate()
586 if self.hasUpdate then
587 wqprint('|cFF00FF00pushing update')
588 self:Refresh(true)
589 end
590 end
591
592 local TQ_GetQuestLocation = C_TaskQuest.GetQuestLocation
593 function WorldQuests:AcquirePin (questID, mapID)
594 local pin = self.QuestsByID[questID]
595 local isNew = false
596 if not pin then
597 isNew = true
598 local numFree = #self.freePins
599 if numFree >= 1 then
600 pin = tremove(self.freePins, numFree)
601 --print('|cFF00FF00Re-using', pin:GetName())
602 else
603 local name = 'WorldPlanQuestMarker' .. NumPinFrames
604 --print('|cFF00FF00Creating', name)
605 pin = CreateFrame('Frame', name, WorldMapPOIFrame, 'WorldPlanQuestPin')
606
607 pin:SetFrameStrata('HIGH')
608 pin.GetTypeInfo = function(frame, typeID)
609 return self:GetTypeInfo(typeID)
610 end
611 NumPinFrames = NumPinFrames + 1
612 --pin.iconBorder:SetVertexColor(0,0,0,1)
613 end
614 pin:SetID(questID)
615 pin.isNew = true
616 pin.currentWidth = nil
617
618 -- used by TaskPOI_x scripts
619 pin.questID = questID
620 pin.worldQuest = true
621
622 self.QuestsByID[questID] = pin
623 else
624 --print('|cFF00FF00Using', pin:GetName())
625 end
626 mapID = mapID or TQ_GetQuestZoneID(questID)
627 self.QuestsByZone[mapID][questID] = pin
628
629 return pin, isNew
630 end
631
632 -- remove from index and add it to the recycling heap
633 function WorldQuests:ReleasePin (pin)
634
635 local id = pin.questId
636 if id then
637 self.QuestsByID[id] = nil
638 for i, zone in pairs(self.QuestsByZone) do
639 print('-', i, zone[i])
640 zone[id] = nil
641 end
642 end
643 pin:Hide()
644 pin:ClearAllPoints()
645 tinsert(self.freePins, pin)
646 print('|cFFFF4400Clearing out', pin:GetName(),id)
647 end
648
649 -- create of update quest pins for a map and its underlying zones
650 function WorldQuests:RefreshData (mapID)
651 local print = wqprint
652 mapID = mapID or GetCurrentMapAreaID()
653 superTrackedID = GetSuperTrackedQuestID()
654 if not mapID then
655 -- info not available yet
656 return
657 end
658
659 print('|cFF00FF88'..self:GetName()..':RefreshData()|r', 'map:', mapID, 'realMap:', GetCurrentMapAreaID())
660
661 if mapID == BROKEN_ISLES_ID then
662 self.hasUpdate = false
663 print('|cFF00FFFFContinent:|r', mapID, GetMapNameByID(mapID), superTrackedID)
664 self.fullSearch = true
665 for i = 1, MC_GetNumZones(mapID) do
666 local submapID, name, depth = MC_GetZoneInfo(mapID, i)
667 self:RefreshData(submapID)
668 end
669 self.fullSearch = nil
670 elseif self.QuestsByZone[mapID] then
671 local taskInfo = TQ_GetQuestsForPlayerByMapID(mapID)
672 local numQuests = 0
673 if taskInfo and #taskInfo >= 1 then
674 print('|cFF00FFFF Zone:|r', mapID, GetMapNameByID(mapID), #taskInfo)
675 wipe(self.QuestsByZone[mapID])
676 ZoneInfo[mapID] = taskInfo
677 qprint('|cFFFF4400START of', GetMapNameByID(mapID))
678 for taskID, info in pairs(taskInfo) do
679 local questID = info.questId
680 info.mapID = mapID
681 local questPOI = self:AcquirePin(questID, mapID)
682 local hasUpdate, isPending = questPOI:RefreshData(info)
683 self.hasUpdate = (self.hasUpdate or hasUpdate)
684 self.isPending = (self.isPending or isPending)
685 numQuests = numQuests + 1
686 end
687 qprint('|cFFFF4400END of', GetMapNameByID(mapID))
688 end
689 end
690
691 if not self.fullSearch then
692 print(' hasUpdate:', self.hasUpdate, 'isPending:', self.isPending, 'timer:', (self.OnNext and 'waiting' or ''))
693
694 end
695
696 end
697
698 function WorldQuests:Refresh(forced)
699 local print = wqprint
700 print('|cFF00FF88'..self:GetName()..':Refresh()|r')
701 if not WorldMapPOIFrame:IsVisible() then
702 return
703 end
704 if forced then
705 self:Reset()
706 end
707 self:UpdateAnchors()
708
709 if forced then
710 self:Cleanup ()
711 end
712 end
713
714 -- prepares elements for a map update
715 function WorldQuests:Reset ()
716 local print = wqprint
717 print('|cFF00FF88'..self:GetName()..':Reset()|r')
718 for questID, pin in pairs(self.QuestsByID) do
719 pin.used = nil
720 end
721 end
722
723 -- update visibility states of all pins
724 function WorldQuests:UpdateAnchors (submapID)
725 local print = wqprint
726 local db = WorldPlan.db
727 local mapFileName, textureHeight, textureWidth, isMicroDungeon, microDungeonMapName = GetMapInfo()
728 if isMicroDungeon then
729 return
730 end
731
732 local currentMap = GetCurrentMapAreaID()
733 local submapID = submapID or currentMap
734
735 if submapID == BROKEN_ISLES_ID and (not db.DisplayContinentPins) then
736 print('not updating map for reasons')
737 return
738 end
739 print('|cFF88FF00'..self:GetName()..':UpdateAnchors|r', submapID, GetMapNameByID(submapID), 'pin count:', numPins)
740 local numZones = MC_GetNumZones(submapID)
741 if numZones then
742 for i = 1, numZones do
743 local subMapID = MC_GetZoneInfo(submapID, i)
744 self:UpdateAnchors(subMapID)
745 end
746 end
747 local pins = self.QuestsByZone[submapID]
748
749 if pins then
750 local hostFrame = WorldMapPOIFrame
751 local mapWidth, mapHeight = hostFrame:GetSize()
752 for questID, pin in pairs(pins) do
753 pin:IsShowable()
754 if pin.used then
755 pin.hasUpdate = true
756 pin:SetFrameLevel(PinBaseIndex+ (pin.whiteListed and 200 or 0) +numPins)
757 print('level', PinBaseIndex+ (pin.whiteListed and 200 or 0) +numPins)
758 pin:SetAnchor(WorldMapPOIFrame, currentMap, mapWidth, mapHeight)
759 numPins = numPins + 1
760 end
761 end
762 end
763 end
764
765 -- shows, animates, or hides pins based on their current visibility flags
766 local debug_show = {}
767 local debug_animate = {}
768 local debug_hide = {}
769 function WorldQuests:Cleanup ()
770 local print = wqprint
771 local showQuestPOI = db.EnablePins
772 print('|cFFFFFF00'..tostring(self)..':Cleanup()|r')
773 local mapID = GetCurrentMapAreaID()
774 isContinentMap = (mapID == BROKEN_ISLES_ID)
775
776 wipe(debug_show)
777 wipe(debug_animate)
778 wipe(debug_hide)
779 -- continent or zone sizing
780 local fadeGrouped = (db.FadeWhileGrouped and IsInGroup())
781
782 numPins = 0
783 for questID, pin in pairs(self.QuestsByID) do
784 -- can we show it?
785 if showQuestPOI and (pin.used) then
786
787 pin.hasUpdate = true
788 if fadeGrouped then
789 pin:SetAlpha(0.25)
790 else
791 pin:SetAlpha(1)
792 end
793 -- is it a new quest?
794 if pin.isNew then
795 if not pin.isAnimating then
796 pin.isAnimating = true
797 OnNext(function()
798 pin:ShowNew()
799 end)
800 if not notifyPlayed then
801 for k,v in pairs(NotificationTypes) do
802 if v[pin[k]] then
803 notifyPlayed = true
804 PlaySoundKitID(23404)
805 end
806 end
807 end
808 tinsert(debug_animate,questID)
809 else
810
811 print('animating? ', questID, 'filtered:', pin.filtered)
812 end
813 -- trap new but animating pins here
814 else
815 -- hard show existing pin
816 print('refresh #', questID, 'filtered:', pin.filtered, 'hasUpdate', pin.hasUpdate)
817 pin:Show()
818 tinsert(debug_show,questID)
819 end
820 else
821 if pin:IsShown() then
822 tinsert(debug_hide,questID)
823 end
824 pin.isAnimating = nil
825 pin.FadeIn:Stop()
826 pin:Hide()
827 end
828 end
829 print(' adding:', table.concat(debug_animate, ',' ))
830 print(' refresh:', table.concat(debug_show, ',' ))
831 print(' hiding:', table.concat(debug_hide, ',' ))
832 hasNewQuestPins = nil
833 notifyPlayed = nil
834 self.hasUpdate = nil
835 end
836 412
837 -- data provider manipulations for the taxi map 413 -- data provider manipulations for the taxi map
838 WorldPlan.OnFlightMapLoaded = function() 414 WorldPlan.OnFlightMapLoaded = function()
839 if true then return end 415 if true then return end
840 -- todo: figure out how to layer inside the map canvas 416 -- todo: figure out how to layer inside the map canvas
869 end) 445 end)
870 end 446 end
871 447
872 448
873 449
874 local throttle = 0 450
875 local tooltip = CreateFrame ("GameTooltip", "VeneerWorldQuestsScanner", nil, "GameTooltipTemplate") 451
876 local tooltipLine1 = _G['VeneerWorldQuestsScannerTextLeft1'] 452
877 local tooltipLine3 = _G['VeneerWorldQuestsScannerTextLeft3']
878 local GetTime, mod = GetTime, mod
879
880
881
882
883 function WorldQuests:FilterCheckByID(questID)
884 local pin = WorldQuests:GetPinByQuestID(questID)
885 return pin:IsShowable()
886 end
887
888
889 function QuestPOI:IsShowable ()
890 local print = wqprint
891 local db = WorldPlan.db
892 local qType = self.worldQuestType
893 local rType = self.rewardType
894 self.filtered = nil
895 self.used = true
896
897 print(' |cFFFF4400IsShowable()|r', self.title)
898
899 self.questId = self:GetID()
900 if not (WorldMap_DoesWorldQuestInfoPassFilters(self, false, true)) then
901 self.filtered = true
902 end
903
904 for filterKey, value in pairs(WorldPlan.UsedFilters) do
905 if self[filterKey] ~= value then
906 self.filtered = true
907 end
908 end
909
910 if not TQ_IsActive(self.questID) then
911 self.used = nil
912 elseif qType == LE_QUEST_TAG_TYPE_PROFESSION then
913 if not (db.ShowAllProfessionQuests or (self.tradeskillLineIndex and GetProfessionInfo(self.tradeskillLineIndex))) then
914 self.used = nil
915 end
916 end
917 return self.used, self.filtered
918 end
919
920 function QuestPOI:UpdateTimer (timeLeft, timeType)
921 print('|cFF0088FFUpdatePinTimer()|r')
922 end
923
924 --- Fixes icons upon size update
925 function QuestPOI:UpdateSize (style, subStyle)
926 style = style or self.style
927 subStyle = subStyle or self.subStyle
928
929 --qprint('|cFF00FF88'..self:GetName()..'|r:UpdateSize()', style, subStyle)
930
931 self.currentWidth = subStyle.PinSize
932 self.borderSize = subStyle.Border
933 self.trackingBorderSize = subStyle.TrackingBorder
934 self.tagSize = subStyle.TagSize
935 self.TimeleftStage = subStyle.TimeleftStage
936 self.NoIcon = subStyle.NoIcon
937
938
939 self:SetSize(self.currentWidth, self.currentWidth)
940
941 local icon = self.icon
942 local iconBorder = self.iconBorder
943 local trackingBorder = self.supertrackBorder
944 local tag = self.tagIcon
945 local pinMask = style.pinMask
946 local rewardMask = style.rewardMask
947
948 if self.NoIcon then
949 self.icon:Hide()
950 else
951 self.icon:Show()
952 icon:SetMask(nil)
953 icon:SetMask(rewardMask)
954 icon:SetTexture(self.icon:GetTexture())
955 end
956 iconBorder:SetMask(nil)
957 trackingBorder:SetMask(nil)
958
959
960 local borderWidth = self.borderSize
961 local trackingWidth = self.trackingBorderSize
962
963 iconBorder:ClearAllPoints()
964 iconBorder:SetPoint('BOTTOMLEFT', self, 'BOTTOMLEFT', -borderWidth + (style.x or 0), -borderWidth + (style.y or 0))
965 iconBorder:SetPoint('TOPRIGHT', self, 'TOPRIGHT', borderWidth + (style.x or 0), borderWidth + (style.y or 0))
966
967 trackingBorder:ClearAllPoints()
968 trackingBorder:SetPoint('BOTTOMLEFT', iconBorder, 'BOTTOMLEFT', -trackingWidth, -trackingWidth)
969 trackingBorder:SetPoint('TOPRIGHT', iconBorder, 'TOPRIGHT', trackingWidth, trackingWidth)
970
971 if self.tagSize then
972 tag:Show()
973 tag:ClearAllPoints()
974 tag:SetPoint('BOTTOMRIGHT', self, 'BOTTOMRIGHT', borderWidth, -borderWidth)
975 else
976 tag:Hide()
977 end
978
979 --qprint('using mask:', mask, self.name )
980 iconBorder:SetMask(pinMask)
981 trackingBorder:SetMask(pinMask)
982
983
984 end
985
986
987
988 --%debug%
989 local SetTimedCallbackForAllPins = function(seconds, callback)
990 C_Timer.After(seconds, function()
991 for id, pin in pairs(WorldPlanQuests.QuestsByID) do
992 callback(pin)
993 end
994 end)
995 end
996 453
997 SLASH_WORLDPLAN1 = "/worldplan" 454 SLASH_WORLDPLAN1 = "/worldplan"
998 SLASH_WORLDPLAN2 = "/wp" 455 SLASH_WORLDPLAN2 = "/wp"
999 SlashCmdList.WORLDPLAN = function() 456 SlashCmdList.WORLDPLAN = function()
1000 print('command pop') 457 print('command pop')