Mercurial > wow > worldplan
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') |