comparison WorldPlan.lua @ 0:3830a592cb0f

initial commmit
author Nenue
date Tue, 11 Oct 2016 17:20:37 -0400
parents
children 232617b8bcd5
comparison
equal deleted inserted replaced
-1:000000000000 0:3830a592cb0f
1 -- Veneer
2 -- WorldPlan.lua
3 -- Created: 8/16/2016 8:19 AM
4 -- %file-revision%
5 --[[
6 Summary:
7 Adds reward icons to the world quest POI markers, and adds said markers to the continent map.
8
9 Issues:
10 Dalaran quests aren't visible until that map has been specifically viewed by the player.
11 --]]
12
13 WorldPlanCore = {}
14 WorldPlanPOIMixin = {}
15 WorldPlanFilterPinMixin = {}
16 local WorldPlanFlightMapMixin = setmetatable({}, {__tostring = function() return 'FlightMapHandler' end})
17 local WorldQuests = setmetatable({ QuestsByID = {}, freePins = {} }, {__tostring = function() return 'QuestHandler' end})
18 local FilterBar = setmetatable({ SummaryHeaders = {} }, {__tostring = function() return 'FilterBar' end})
19
20 local WorldPlan = WorldPlanCore
21 local QuestPOI = WorldPlanPOIMixin
22 local FilterPin = WorldPlanFilterPinMixin
23 local WP_VERSION = "1.0"
24
25 local print = DEVIAN_WORKSPACE and function(...) _G.print('WP', ...) end or function() end
26 local wipe, tremove, tinsert, pairs, floor, tContains = table.wipe, table.remove, table.insert, pairs, floor, tContains
27 local TQ_GetQuestInfoByQuestID = C_TaskQuest.GetQuestInfoByQuestID -- Return the name of a quest with a given ID
28 local TQ_GetQuestsForPlayerByMapID = C_TaskQuest.GetQuestsForPlayerByMapID -- This function is not yet documented
29 local TQ_GetQuestTimeLeftMinutes = C_TaskQuest.GetQuestTimeLeftMinutes
30 local TQ_RequestPreloadRewardData = C_TaskQuest.RequestPreloadRewardData
31 local TQ_GetQuestLocation = C_TaskQuest.GetQuestLocation
32 local TQ_IsActive = C_TaskQuest.IsActive
33 local ITEM_QUALITY_COLORS = ITEM_QUALITY_COLORS
34 local WorldMap_DoesWorldQuestInfoPassFilters = WorldMap_DoesWorldQuestInfoPassFilters
35 local QuestMapFrame_IsQuestWorldQuest = QuestMapFrame_IsQuestWorldQuest
36 local GameTooltip = GameTooltip
37 local GetItemIcon = GetItemIcon
38
39
40 local GetMapInfo, QuestPOIGetIconInfo = GetMapInfo, QuestPOIGetIconInfo
41 local GetQuestTagInfo, HaveQuestData = GetQuestTagInfo, HaveQuestData
42 local GetNumQuestLogRewards, GetNumQuestLogRewardCurrencies, GetQuestLogRewardMoney = GetNumQuestLogRewards, GetNumQuestLogRewardCurrencies, GetQuestLogRewardMoney
43 local GetQuestLogRewardInfo, GetQuestLogRewardCurrencyInfo, GetMoneyString = GetQuestLogRewardInfo, GetQuestLogRewardCurrencyInfo, GetMoneyString
44
45 local GetCurrentMapAreaID, GetMapNameByID, GetSuperTrackedQuestID = GetCurrentMapAreaID, GetMapNameByID, GetSuperTrackedQuestID
46 local MC_GetNumZones, MC_GetZoneInfo = C_MapCanvas.GetNumZones, C_MapCanvas.GetZoneInfo
47
48 local qprint = DEVIAN_WORKSPACE and function(...) _G.print('POI', ...) end or function() end
49 local iprint = DEVIAN_WORKSPACE and function(...) _G.print('ItemScan', ...) end or function() end
50
51 local SearchFaction
52 local PinBaseIndex = 1600
53 local ShowAllProfessionQuests = false
54 local DisplayContinentSummary = true
55 local DisplayContinentPins = true
56 local NotifyWhenNewQuests = true
57 local PinRewardFilter, PinTagFilter
58 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
59
60 -- maps where we do our own anchors
61 local CONTINENT_MAPS = { [BROKEN_ISLES_ID] = BROKEN_ISLES_ID, }
62 local WORLD_QUEST_MAPS = { [DALARAN_ID] = 'Dalaran70', [AZSUNA_ID] = 'Azsuna', [VALSHARAH_ID] = "Val'sharah",
63 [HIGHMOUNTAIN_ID] = 'Highmountain', [STORMHEIM_ID] = 'Stormheim', [SURAMAR_ID] = 'Suramar', [EOA_ID] = 'EyeOfAszhara', }
64 -- 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
69 -- operating flags
70 local superTrackedID
71 local currentMapName
72 local hasNewQuestPins
73 local isContinentMap
74
75 local ICON_UNKNOWN = "Interface\\ICONS\\inv_misc_questionmark"
76 local ICON_MONEY = "Interface\\Buttons\\UI-GroupLoot-Coin-Up"
77
78 local POI_BORDER_MASK = "Interface\\Minimap\\UI-Minimap-Background"
79 local POI_BORDER_FILL = "Interface\\BUTTONS\\YELLOWORANGE64"
80 local POI_BORDER_BLUE = "Interface\\BUTTONS\\GRADBLUE"
81 local POI_BORDER_RED = "Interface\\BUTTONS\\RedGrad64"
82 local POI_BORDER_YELLOW = "Interface\\BUTTONS\\YELLOWORANGE64"
83 local POI_BORDER_GREEN = "Interface\\BUTTONS\\GREENGRAD64"
84
85 local REWARD_CASH = 1001
86 local REWARD_ARTIFACT_POWER = 1002
87 local REWARD_GEAR = 1003
88 local REWARD_CURRENCY = 1004
89 local REWARD_ITEM = 1005
90 local REWARD_REAGENT = 1006
91
92 local POI_DEFAULT_TYPE = {
93 a = 1,
94 r = 1, g = 1, b = 1,
95 x = 0, y = 0,
96 desaturated = true,
97 mask = POI_BORDER_MASK,
98 texture = POI_BORDER_FILL,
99 continent = {
100 PinSize = 18,
101 Border = 3,
102 TrackingBorder = 2,
103 TagSize = 6,
104 TimeleftStage = 3,
105 },
106 zone = {
107 PinSize = 22,
108 Border = 3,
109 TrackingBorder = 2,
110 TagSize = 12,
111 TimeleftStage = 3,
112 },
113 minimized = {
114 PinSize = 4,
115 Border = 1,
116 TrackingBorder = 2,
117 NoIcon = true,
118 TimeleftStage = 1,
119 }
120 }
121 local POI_REWARD_TYPE = setmetatable({}, {
122 __newindex = function(t, k, v)
123 if type(v) == 'table' then
124 setmetatable(v, {__index = POI_DEFAULT_TYPE})
125 end
126 rawset(t,k,v)
127 end
128 })
129 local POI_FILTER_STYLE = setmetatable({
130 continentBorder = 2,
131 zoneBorder = 2,
132 }, {__index = POI_DEFAULT_TYPE})
133
134 local LE_QUEST_TAG_TYPE_PVP = LE_QUEST_TAG_TYPE_PVP
135 local LE_QUEST_TAG_TYPE_PET_BATTLE = LE_QUEST_TAG_TYPE_PET_BATTLE
136 local LE_QUEST_TAG_TYPE_DUNGEON = LE_QUEST_TAG_TYPE_DUNGEON
137 local LE_QUEST_TAG_TYPE_PROFESSION = LE_QUEST_TAG_TYPE_PROFESSION
138 local LE_QUEST_TAG_TYPE_NORMAL = LE_QUEST_TAG_TYPE_NORMAL
139
140 -- Pin color/display variables
141 POI_REWARD_TYPE[REWARD_ITEM] = {
142 r = 1, g = 1, b = 1,
143 }
144 POI_REWARD_TYPE[REWARD_REAGENT] = {
145 r = 0, g = 1, b = 1,
146 }
147 POI_REWARD_TYPE[REWARD_ARTIFACT_POWER] = {
148 r = 1, g = .25, b = .5,
149 showNumber = true,
150 }
151 POI_REWARD_TYPE[REWARD_GEAR] = {
152 r = .1, g = .2, b = 1,
153 }
154 POI_REWARD_TYPE[REWARD_CURRENCY] = {
155 r = 1, g = 1, b = 0,
156 }
157 POI_REWARD_TYPE[REWARD_CASH] = {
158 r = 0, g = 0, b = 0,
159 --x = 0, y = -1,
160 --mask = ICON_MONEY,
161 --continentBorder = 1,
162 --zoneBorder = 1,
163 }
164
165
166 -- Summary header structure
167 local POI_FILTER_OPTIONS = {
168 { label = 'Filters', texture = "Interface\\WorldMap\\WorldMap-Icon" },
169 { filterKey= 'rewardType', filterValue = REWARD_ARTIFACT_POWER, label = 'Artifact Power', texture = "Interface\\ICONS\\inv_7xp_inscription_talenttome01" },
170 { filterKey= 'rewardType', filterValue = REWARD_CURRENCY,label = 'Currency', texture = "Interface\\ICONS\\inv_misc_elvencoins" },
171 { filterKey= 'rewardType', filterValue = REWARD_ITEM, label = 'Item', texture = "Interface\\ICONS\\inv_crate_01" },
172 { filterKey= 'rewardType', filterValue = REWARD_GEAR, label = 'Equipment', texture = "Interface\\ICONS\\garrison_bluearmorupgrade" },
173 { filterKey= 'rewardType', filterValue = REWARD_REAGENT, label = 'Reagents', texture = 1417744 },
174 { filterKey= 'rewardType', filterValue = REWARD_CASH, label = 'Reagents', texture = ICON_MONEY },
175 { filterKey= 'worldQuestType', filterValue = LE_QUEST_TAG_TYPE_PVP, label = 'PvP', texture = "Interface\\Icons\\Ability_PVP_GladiatorMedallion", spacing = 10 },
176 { filterKey= 'worldQuestType', filterValue = LE_QUEST_TAG_TYPE_PET_BATTLE, label = 'Pet Battle', texture = "Interface\\Icons\\PetJournalPortrait", },
177 { filterKey= 'worldQuestType', filterValue = LE_QUEST_TAG_TYPE_DUNGEON, label = 'Dungeon', texture = "Interface\\LFGFRAME\\UI-LFR-PORTRAIT", },
178 }
179
180 local PIN_TIME_CONTEXT = {
181 {max = 60,
182 r=1, g=0.25, b =0, format = function (minutes) return '|cFFFF4400'.. minutes .. 'm' end,
183 continentAlpha = 1, swipeTime = 1440,
184 },
185 {max = 240,
186 r=1, g=.5, b=0, format = function(minutes) return '|cFFFF4400'.. floor(minutes/60) .. 'h' end,
187 continentAlpha = 1, swipeTime = 1440,
188 },
189 {max = 1440,
190 r=1, g=1, b=0, format = function(minutes) return '|cFFFFFF00'.. floor(minutes/60) .. 'h' end,
191 continentAlpha = .55, swipeTime = 1440
192 },
193 {max = 10081,
194 r=0, g=1, b=0,
195 continentAlpha = .3,
196 }, -- 7 days + 1 minute
197 }
198
199 local numPins = 0
200 local QuestsByZone = {}
201 local QuestsByFaction = {}
202 local QuestsByReward = {}
203 local QuestsByTag = {}
204 local QuestsByID = {}
205 local QuestPositions = {}
206 local FilterInclusions = {rewardType = {}, worldQuestType = {}}
207 local FilterExclusions = {rewardType = {}, worldQuestType = {}}
208 local ZoneInfo = {}
209 local SummaryHeaders = {}
210
211 local FreePins = {}
212 local NumPinFrames = 1
213
214 local hasPendingQuestData
215 local notifyPlayed
216 local scanner, wmtt, WorldMapPOIFrame
217
218
219 local tasksQueue = {}
220 local function OnNext (func)
221 if #tasksQueue == 0 then
222 _G.WorldPlan:SetScript('OnUpdate', function()
223 local func = tremove(tasksQueue, 1)
224 if func then
225 func()
226 end
227 if #tasksQueue == 0 then
228 _G.WorldPlan:SetScript('OnUpdate', nil)
229 end
230 end)
231 end
232 tinsert(tasksQueue, func)
233 end
234
235 -- combines templates
236 local function DoMixins(frame,...)
237 for i = 1, select('#', ...) do
238 for k,v in pairs(select(i,...)) do
239 frame[k] = v
240 end
241 end
242 return frame
243 end
244
245 -- use tooltip object to extract item details
246 local ParseItemReward = function(questID)
247 local rewardType = REWARD_ITEM
248 local name, icon, quantity, quality, _, itemID = GetQuestLogRewardInfo(1, questID)
249 if not itemID then
250 return REWARD_ITEM
251 end
252
253 scanner:SetOwner(WorldPlan, "ANCHOR_NONE")
254 scanner:SetItemByID(itemID)
255 local ttl1 = _G['WorldPlanTooltipTextLeft1']
256 local ttl2 = _G['WorldPlanTooltipTextLeft2']
257 local ttl3 = _G['WorldPlanTooltipTextLeft3']
258 local ttl4 = _G['WorldPlanTooltipTextLeft4']
259 if ttl2 then
260 local text = ttl2:GetText()
261 -- Artifact Power
262 if text and text:match("|cFFE6CC80") then
263 --print('AP token!', text)
264 local power
265 if ttl4 then
266 local text = ttl4:GetText()
267 --print('tip line 4', text)
268 if text then
269 power = text:gsub("%p", ""):match("%d+")
270 power = tonumber(power)
271 end
272
273 end
274 rewardType = REWARD_ARTIFACT_POWER
275 icon = "Interface\\ICONS\\inv_7xp_inscription_talenttome01"
276 quantity = power
277 elseif text and text:match("Item Level") then
278 --print('equipment!', text)
279 rewardType = REWARD_GEAR
280 quantity = text:match("Item Level ([%d\+]+)")
281 end
282 end
283 if ttl3 then
284 local text = ttl3:GetText()
285 -- Crafting Reagent
286 if text and text:match("Crafting Reagent") then
287 --print('reagent', text)
288 rewardType = REWARD_REAGENT
289 end
290 end
291 iprint(' item:', name, rewardType, icon, quantity)
292 return rewardType, icon, quantity, name, itemID
293 end
294
295 -- update a masked texture without messing up its blending mask
296 local SetMaskedTexture = function(region, file, mask)
297 mask = mask or POI_BORDER_MASK
298 region:SetMask(nil)
299 region:SetTexture(file)
300 region:SetMask(mask)
301 end
302
303 -- tracking menu toggler
304 local DropDown_OnClick = function(self)
305 local key = self.value
306 if key then
307 if WorldPlanData[key] then
308 WorldPlanData[key] = nil
309 else
310 WorldPlanData[key] = true
311 end
312 end
313 end
314
315 function WorldPlan:print(...)
316 local msg
317 for i = 1, select('#', ...) do
318 msg = (msg and (msg .. ' ') or '') .. tostring(select(i, ...))
319 end
320 DEFAULT_CHAT_FRAME:AddMessage("|cFF0088FFWorldPlan|r: " .. msg)
321 end
322
323 function WorldPlan:OnLoad ()
324 WorldPlan = self
325 scanner = _G.WorldPlanTooltip
326 wmtt = _G.WorldMapTooltip
327 WorldMapPOIFrame = _G.WorldMapPOIFrame
328
329 WorldPlan:print('v'..WP_VERSION)
330
331 self:RegisterEvent("QUESTLINE_UPDATE")
332 self:RegisterEvent("QUEST_LOG_UPDATE")
333 self:RegisterEvent("WORLD_MAP_UPDATE")
334 self:RegisterEvent("WORLD_QUEST_COMPLETED_BY_SPELL")
335 self:RegisterEvent("SUPER_TRACKED_QUEST_CHANGED")
336 self:RegisterEvent("SKILL_LINES_CHANGED")
337 self:RegisterEvent("ARTIFACT_XP_UPDATE")
338 self:RegisterEvent("ADDON_LOADED")
339
340 WorldPlan.modules = {
341 WorldQuests, FilterBar, WorldPlanFlightMapMixin,
342 }
343 hooksecurefunc("UIDropDownMenu_Initialize", self.OnDropDownInitialize)
344 end
345
346 function WorldPlan:OnEvent (event, ...)
347 print()
348 print(event, ...)
349 if event == 'ADDON_LOADED' then
350 local addon = ...
351 if addon == "Blizzard_FlightMap" then
352 print('do mixin junk')
353 self.OnFlightMapLoaded()
354
355 end
356 if IsLoggedIn() and not self.initialized then
357 self:Setup()
358 end
359 elseif event == 'WORLD_MAP_UPDATE' then
360 self:RefreshAll()
361 end
362 for i, module in ipairs(self.modules) do
363 if module.OnEvent then
364 print('forwarding to', tostring(module))
365 module:OnEvent(event, ...)
366 end
367 end
368 end
369
370
371 function WorldPlan:Setup ()
372 if not WorldPlanData then
373 WorldPlanData = {key = 0 }
374 end
375 WorldPlanData.key = (WorldPlanData.key or 0) + 1
376 self.db = WorldPlanData
377
378 for i, module in ipairs(self.modules) do
379 if module.Setup then module:Setup() end
380 if not module.RegisterEvent then
381 module.RegisterEvent = self.RegisterEvent
382 end
383 end
384 self.initialized = true
385
386 end
387
388 function WorldPlan:RefreshAll (forced)
389 for i, module in ipairs(self.modules) do
390 if module.Refresh then
391 module:Refresh()
392 end
393 end
394 end
395 function WorldPlan:UpdateAnchors ()
396 for i, module in ipairs(self.modules) do
397 if module.UpdateAnchors then
398 module:UpdateAnchors()
399 end
400 end
401 end
402
403 -- insert visual options into the tracking button menu
404 WorldPlan.OnDropDownInitialize = function (self, callback, dropType)
405 if self ~= WorldMapFrameDropDown then
406 return
407 end
408
409 local info = UIDropDownMenu_CreateInfo()
410 info.text = ""
411 info.isTitle = true
412 UIDropDownMenu_AddButton(info)
413 info.text = "|cFF00AAFFWorldPlan|r"
414 info.isTitle = true
415 UIDropDownMenu_AddButton(info)
416 info.isTitle = nil
417 info.disabled = nil
418 info.keepShownOnClick = true
419 info.tooltipOnButton = 1
420
421 info.text = "Hidden World Quests"
422 info.isNotRadio = true
423 info.value = "ShowAllProfessionQuests"
424 info.checked = ShowAllProfessionQuests
425 info.tooltipTitle = "Hidden Quests"
426 info.tooltipText = "Display work order and profession-related quests that are skipped by the default UI."
427 info.func = DropDown_OnClick
428 UIDropDownMenu_AddButton(info)
429
430 info.text = "Show Continent Pins"
431 info.isNotRadio = true
432 info.value = "DisplayContinentPins"
433 info.checked = DisplayContinentPins
434 info.tooltipTitle = "Continent Pins"
435 info.tooltipText = "Display quest pins on the continent map (may get cramped)."
436 info.func = DropDown_OnClick
437 UIDropDownMenu_AddButton(info)
438
439 info.text = "Show Summary"
440 info.isNotRadio = true
441 info.value = "DisplayContinentSummary"
442 info.tooltipTitle = "Summary Bar"
443 info.tooltipText = "Display a summary of active world quests. Note: requires directly viewing Broken Isle and Dalaran maps to gain complete info."
444 info.checked = DisplayContinentSummary
445 info.func = DropDown_OnClick
446 UIDropDownMenu_AddButton(info)
447 end
448
449 function WorldQuests:Setup()
450 -- refresh positions any time blizzard does so (i.e. mousewheel zoom)
451 hooksecurefunc("WorldMapScrollFrame_ReanchorQuestPOIs", function()
452 self:Refresh()
453 end)
454
455 -- hide the original world quest POIs
456 hooksecurefunc("WorldMap_UpdateQuestBonusObjectives", function()
457 for i = 1, NUM_WORLDMAP_TASK_POIS do
458 local button = _G['WorldMapFrameTaskPOI'..i]
459 if button and button.worldQuest then
460 button:Hide()
461 end
462 end
463 end)
464
465
466 end
467
468 function WorldQuests:OnEvent (event, ...)
469 print('|cFFFFFF00'..tostring(self)..':OnEvent()'..event..'|r', ...)
470 if event == 'QUEST_LOG_UPDATE' then
471 local questID, added = ...
472 if questID and added then
473 self:GetPinByQuestID(questID)
474 else
475 self:GetPinsForMap()
476 end
477 elseif event == 'WORLD_QUEST_COMPLETED_BY_SPELL' then
478 local questID = ...
479 if questID and QuestsByID[questID] then
480 self:ReleasePin(QuestsByID[questID])
481 end
482 elseif event == 'SKILL_LINES_CHANGED' then
483 self:Refresh()
484 end
485 end
486
487 function WorldQuests:AcquirePin (questID, pinTable)
488 local pin = QuestsByID[questID]
489 local isNew = false
490 if not pin then
491 isNew = true
492 local numFree = #self.freePins
493 if numFree >= 1 then
494 pin = tremove(self.freePins, numFree)
495 --print('|cFF00FF00Re-using', pin:GetName())
496 else
497 local name = 'WorldPlanQuestMarker' .. NumPinFrames
498 --print('|cFF00FF00Creating', name)
499 pin = CreateFrame('Frame', name, WorldMapPOIFrame, 'WorldPlanQuestPin')
500 pin:SetFrameStrata('HIGH')
501 pin:SetScript('OnEnter', function(self)
502 TaskPOI_OnEnter(self)
503 end)
504 pin:SetScript('OnLeave', function(self)
505 TaskPOI_OnLeave(self)
506 end)
507 pin:SetScript('OnMouseDown', TaskPOI_OnClick)
508
509 NumPinFrames = NumPinFrames + 1
510
511 --pin.iconBorder:SetVertexColor(0,0,0,1)
512
513 end
514 QuestsByID[questID] = pin
515 pin.isNew = true
516 pin.currentWidth = nil
517
518 -- used by TaskPOI_x scripts
519 pin.questID = questID
520 pin.worldQuest = true
521 else
522 --print('|cFF00FF00Using', pin:GetName())
523 end
524
525 -- set display flags accordingly
526 if pinTable then
527 for k,v in pairs(pinTable) do
528 pin[k] = v
529 end
530 end
531 pin.throttle = nil
532 pin.timeThreschold = nil
533 return pin, isNew
534 end
535
536 -- remove from index and add it to the recycling heap
537 function WorldQuests:ReleasePin (pin)
538
539 local id = pin.questId
540 if id then
541 QuestsByID[id] = nil
542 for i, zone in pairs(QuestsByZone) do
543 print('-', i, zone[i])
544 zone[id] = nil
545 end
546 end
547 if pin.factionID then
548 QuestsByFaction[pin.factionID][id] = nil
549 end
550 pin:Hide()
551 pin:ClearAllPoints()
552 tinsert(self.freePins, pin)
553 print('|cFFFF4400Clearing out', pin:GetName(),id)
554 end
555
556 -- create of update quest pins for a map and its underlying zones
557 function WorldQuests:GetPinsForMap (mapID)
558 mapID = mapID or GetCurrentMapAreaID()
559 superTrackedID = GetSuperTrackedQuestID()
560 if not mapID then
561 -- info not available yet
562 return
563 end
564 if mapID == BROKEN_ISLES_ID then
565 hasPendingQuestData = nil
566 print('|cFF00FFFFRefreshQuestsForMap|r', mapID, GetMapNameByID(mapID), superTrackedID)
567 self.fullSearch = true
568 for i = 1, MC_GetNumZones(mapID) do
569 local submapID, name, depth = MC_GetZoneInfo(mapID, i)
570 self:GetPinsForMap(submapID)
571 end
572 self.fullSearch = nil
573 elseif QuestsByZone[mapID] then
574 local taskInfo = TQ_GetQuestsForPlayerByMapID(mapID)
575 local quest = QuestsByZone[mapID]
576 local numQuests = 0
577 if taskInfo and #taskInfo >= 1 then
578 print('|cFF00FFFFRefreshQuestsForMap|r', mapID, GetMapNameByID(mapID), #taskInfo)
579 wipe(QuestsByZone[mapID])
580 ZoneInfo[mapID] = taskInfo
581 for taskID, info in pairs(taskInfo) do
582 local questID = info.questId
583
584 info.mapID = mapID
585 QuestsByZone[mapID][questID] = self:GetPinByQuestID(questID, info)
586 numQuests = numQuests + 1
587 end
588 end
589 end
590 if hasNewQuestPins and not self.fullSearch then
591 print('|cFF00FF00NEW PINS DO ANCHOR THINGS')
592 self:Refresh ()
593 hasNewQuestPins = nil
594 end
595 end
596
597 -- create or update the pin using the given questID and C_TaskQuest results
598 function WorldQuests:GetPinByQuestID (questID, taskInfo)
599 if (QuestMapFrame_IsQuestWorldQuest (questID)) then
600 local questTitle, rewardIcon, rewardName, rewardCount, rewardStyle, rewardType, itemID, quantity, quality, _
601 local pin = self:AcquirePin(questID, taskInfo)
602
603 if pin.isNew then
604 if not hasNewQuestPins then
605 print('triggering new quest pins event')
606 end
607
608 hasNewQuestPins = true
609 end
610
611 if not HaveQuestData(questID) then
612 print('|cFFFF4400Retrieval failed.')
613 TQ_RequestPreloadRewardData(questID)
614 hasPendingQuestData = true
615 else
616 print('|cFF00FF88HaveQuestData|r')
617 pin.mapID = pin.mapID or C_TaskQuest.GetQuestZoneID(questID)
618
619 -- set reward category
620 local numRewards = GetNumQuestLogRewards(questID)
621 local numCurrency = GetNumQuestLogRewardCurrencies(questID)
622 local money = GetQuestLogRewardMoney(questID)
623 if numRewards >= 1 then
624 rewardType, rewardIcon, rewardCount, rewardName, itemID = ParseItemReward(questID)
625 elseif numCurrency >= 1 then
626 rewardName, rewardIcon, rewardCount = GetQuestLogRewardCurrencyInfo(1, questID)
627 rewardType = REWARD_CURRENCY
628 elseif money >= 1 then
629 rewardIcon = ICON_MONEY
630 rewardName = GetMoneyString(money)
631 rewardType = REWARD_CASH
632 end
633 rewardStyle = POI_REWARD_TYPE[rewardType] or POI_DEFAULT_TYPE
634
635 pin.itemNumber = rewardCount or pin.itemNumber
636 pin.rewardType = rewardType or REWARD_ITEM
637 pin.style = rewardStyle
638 QuestsByID[questID] = pin
639
640 -- title, faction, capped state
641 local questTitle, factionID, capped = TQ_GetQuestInfoByQuestID(questID)
642 if factionID then
643 QuestsByFaction[factionID] = QuestsByFaction[factionID] or {}
644 QuestsByFaction[factionID][questID] = pin
645 end
646 pin.title = questTitle or "|cFFFF0000Retrieving..."
647 pin.factionID = factionID
648 pin.capped = capped
649
650 -- set tag details
651 local tagID, tagName, worldQuestType, rarity, isElite, tradeskillLineIndex = GetQuestTagInfo(questID);
652 local tagAtlas
653 if worldQuestType == LE_QUEST_TAG_TYPE_PET_BATTLE then
654 tagAtlas = "worldquest-icon-petbattle"
655 elseif worldQuestType == LE_QUEST_TAG_TYPE_PVP then
656 tagAtlas = "worldquest-icon-pvp-ffa"
657 elseif worldQuestType == LE_QUEST_TAG_TYPE_PROFESSION then
658 local id = tradeskillLineIndex and select(7, GetProfessionInfo(tradeskillLineIndex))
659 if id then
660 tagAtlas = WORLD_QUEST_ICONS_BY_PROFESSION[id]
661 end
662 elseif worldQuestType == LE_QUEST_TAG_TYPE_DUNGEON then
663 tagAtlas = "worldquest-icon-dungeon"
664 end
665 pin.tagID = tagID
666 pin.tagName = tagName
667 pin.worldQuestType = worldQuestType
668 pin.isElite = isElite
669 pin.tradeskillLineIndex = tradeskillLineIndex
670 pin.rarity = rarity
671 pin.tagAtlas = tagAtlas
672 end
673
674 -- flag unresolved info
675 if not (rewardIcon and rewardName) then
676 if not pin.isPending then
677 pin.isPending = true
678 TQ_RequestPreloadRewardData (questID)
679 pin.rewardType = pin.rewardType or REWARD_ITEM
680 pin.style = pin.style or POI_REWARD_TYPE[REWARD_ITEM]
681
682 if not hasPendingQuestData then
683 hasPendingQuestData = true
684 PlaySoundKitID(229)
685 end
686 --WorldPlan:print('|cFFFFFF00'..tostring(pin.title)..'|r waiting on texture info')
687 end
688 else
689 if (rewardIcon and rewardName) then
690 --WorldPlan:print('|cFF00FF00'..tostring(pin.title)..'|r has info', rewardIcon, rewardName)
691 pin.hasUpdate = true
692 end
693 pin.isPending = nil
694 end
695 pin.itemTexture = rewardIcon or pin.itemTexture
696 pin.itemName = rewardName or pin.itemName
697
698 qprint(' |cFF00FFFF'..questID..'|r:->', (HaveQuestData(questID) and "|cFF00FF00HaveQuestData" or "-"), (C_TaskQuest.IsActive(questID) and "|cFF88FF00IsActive|r" or ""))
699 qprint(' ', pin.title, pin.itemTexture, 'rewardType:', pin.rewardType, 'tag:', pin.tagID, 'style', pin.style )
700 end
701 return QuestsByID[questID]
702 end
703
704 function WorldQuests:Refresh(forced)
705 print('pushing |cFF00FF88'..tostring(self)..':Refresh()|r')
706 if not WorldMapPOIFrame:IsVisible() then
707 return
708 end
709 self:Reset()
710 self:UpdateAnchors()
711 self:Cleanup ()
712 end
713
714 -- prepares elements for a map update
715 function WorldQuests:Reset ()
716 wipe(QuestPositions)
717 wipe(QuestsByReward)
718 wipe(QuestsByTag)
719 for questID, pin in pairs(QuestsByID) do
720 pin.used = nil
721 end
722 qprint(tostring(self)..':|cFFFFFF00Reset()|r')
723 end
724
725 -- update visibility states of all pins
726 function WorldQuests:UpdateAnchors (submapID)
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 DisplayContinentPins) then
736 print('not updating map for reasons')
737 return
738 end
739 print('|cFF88FF00'..tostring(self)..':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 = 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 if pin:IsShowable(true) then
754 pin:SetFrameLevel(PinBaseIndex+numPins)
755 pin:SetAnchor(WorldMapPOIFrame, currentMap, mapWidth, mapHeight)
756 pin.used = true
757 numPins = numPins + 1
758 end
759 end
760 end
761 end
762
763
764
765
766 -- shows, animates, or hides pins based on their current visibility flags
767 local debug_show = {}
768 local debug_animate = {}
769 local debug_hide = {}
770 function WorldQuests:Cleanup ()
771 local showQuestPOI = GetCVarBool("questPOI")
772 print('|cFFFFFF00'..tostring(self)..':Cleanup()|r')
773 wipe(QuestsByReward)
774 wipe(QuestsByTag)
775 wipe(debug_show)
776 wipe(debug_animate)
777 wipe(debug_hide)
778 local mapID = GetCurrentMapAreaID()
779 isContinentMap = (mapID == BROKEN_ISLES_ID)
780
781 -- continent or zone sizing
782 local subStyle = isContinentMap and 'continent' or 'zone'
783
784 numPins = 0
785 for questID, pin in pairs(QuestsByID) do
786 -- can we show it?
787 if showQuestPOI and (pin.used) then
788 pin.subStyle = pin.filtered and 'minimized' or subStyle
789 pin:GetSizeMetrics()
790
791
792 -- is it a new quest?
793 if pin.isNew then
794 if not pin.isAnimating then
795 pin.isAnimating = true
796 OnNext(function()
797 pin.isNew = nil
798 pin:Show()
799 pin.FadeIn:Play()
800 end)
801 if not notifyPlayed then
802 notifyPlayed = true
803 PlaySoundKitID(23404)
804 end
805 tinsert(debug_animate,questID)
806 end
807 else
808 -- hard show existing pin
809 pin:Show()
810 tinsert(debug_show,questID)
811 end
812 else
813 pin:Hide()
814 tinsert(debug_hide,questID)
815 end
816
817 -- is it part of the current map?
818 if pin.used then
819 local rewardType = pin.rewardType
820 local tagType = pin.worldQuestType
821 if rewardType then
822 QuestsByReward[rewardType] = QuestsByReward[rewardType] or {}
823 tinsert(QuestsByReward[rewardType], pin)
824 end
825 if tagType then
826 QuestsByTag[tagType] = QuestsByTag[tagType] or {}
827 tinsert(QuestsByTag[tagType], pin)
828 end
829 end
830 end
831 print(' adding:', table.concat(debug_animate, ',' ))
832 print(' showing:', table.concat(debug_show, ',' ))
833 hasNewQuestPins = nil
834 end
835
836 -- data provider manipulations for the taxi map
837 WorldPlan.OnFlightMapLoaded = function()
838 if true then return end
839 -- todo: figure out how to layer inside the map canvas
840 local res = {}
841 local t = {}
842 for k,v in pairs(FlightMapFrame) do
843 tinsert(res, tostring(k))
844 end
845
846 table.sort(res)
847 for i, k in ipairs(res) do
848 print(k)
849 end
850 hooksecurefunc(FlightMapFrame, 'RefreshAll', function(self)
851 print('|cFF0088FFWQDP RefreshAllData ', GetTime())
852
853 WorldPlan:GetPinsForMap(self:GetMapID())
854
855 for pin in self:EnumerateAllPins() do
856 if pin.worldQuest then
857 --print('got pin #', pin.questID)
858 local wp = QuestsByID[pin.questID]
859 if wp then
860 wp:ClearAllPoints()
861 wp:SetParent(FlightMapFrame.ScrollContainer)
862 wp:SetFrameStrata('MEDIUM')
863 wp:SetPoint('CENTER', pin, 'CENTER')
864 wp:Show()
865 end
866 end
867 end
868 end)
869 end
870
871
872
873 local throttle = 0
874 local tooltip = CreateFrame ("GameTooltip", "VeneerWorldQuestsScanner", nil, "GameTooltipTemplate")
875 local tooltipLine1 = _G['VeneerWorldQuestsScannerTextLeft1']
876 local tooltipLine3 = _G['VeneerWorldQuestsScannerTextLeft3']
877 local GetTime, mod = GetTime, mod
878
879 function QuestPOI:OnLoad()
880 self:RegisterEvent('SUPER_TRACKED_QUEST_CHANGED')
881 end
882
883 function QuestPOI:OnEvent(event, ...)
884 if event == 'SUPER_TRACKED_QUEST_CHANGED' then
885 if self:IsVisible() then
886 self:Refresh()
887 end
888 end
889 end
890
891 local PIN_UPDATE_DELAY = .016
892 local TOP_PIN_ID
893 function QuestPOI:OnUpdate (sinceLast)
894 -- control update check intervals
895 self.throttle = (self.throttle or PIN_UPDATE_DELAY) - sinceLast
896 if self.throttle <= 0 then
897 -- factor overtime into the throttle timer
898 self.throttle = PIN_UPDATE_DELAY - self.throttle
899 else
900 return
901 end
902
903 -- query for reward data if it wasn't found in the original scan
904 local questID = self.questID
905 if self.isPending then
906 WorldQuests:GetPinByQuestID(questID)
907 if not (self.PendingFade:IsPlaying() or self.isAnimating) then
908 self.PendingFade:Play()
909 end
910 return
911 else
912 if self.PendingFade:IsPlaying() then
913 self.PendingFade:Stop()
914 end
915 end
916
917 if self.hasUpdate then
918 self:Refresh()
919 self.hasUpdate = nil
920 end
921
922 -- update time elements
923 local tl = self.timeThreschold
924 local timeLeft = TQ_GetQuestTimeLeftMinutes(questID)
925 if timeLeft > 0 then
926 for i, context in ipairs(PIN_TIME_CONTEXT) do
927 if i > self.TimeleftStage then
928 self.timeLabel:SetText(nil)
929 break
930 end
931
932
933 if timeLeft <= context.max then
934 if tl ~= i then
935 tl = i
936 end
937
938 if context.format then
939 self.timeLabel:SetText(context.format(timeLeft))
940 else
941 self.timeLabel:SetText(nil)
942 end
943 break
944 end
945 end
946 else
947 -- remove self in a timely manner
948 if not self.isPending then
949 self:Hide()
950 end
951 end
952 self.timeThreschold = tl
953
954 if self:IsMouseOver() then
955 self.MouseGlow:Show()
956 else
957 self.MouseGlow:Hide()
958 end
959 end
960
961 function QuestPOI:OnShow ()
962 qprint('|cFFFFFF00["'..tostring(self.title)..'"]|r:OnShow()')
963 -- pop this on principle
964 self:Refresh()
965 end
966 function QuestPOI:OnHide()
967 --qprint('|cFFFFFF00["'..tostring(self.title)..'"]|r:OnHide()')
968 end
969 function QuestPOI:Refresh ()
970 print('|cFF00FF88["'..tostring(self.title)..'"]|r:Refresh()', tostring(self.title), "|T"..tostring(self.itemTexture)..":12:12|t", tostring(self.itemName))
971 qprint(self.style)
972
973 local questID = self.questId
974 local style = self.style
975 local borderMask = style.mask
976 local borderFill = style.texture
977 local iconBorder = self.iconBorder
978 local icon = self.icon
979 local count = self.count
980
981 --WorldPlan:print(tostring(self.title), "|T"..tostring(self.itemTexture)..":16:16|t", tostring(self.itemName))
982 SetMaskedTexture(icon, self.itemTexture or ICON_UNKNOWN, borderMask)
983 icon:SetAllPoints(self)
984
985 if self.itemName then
986 local color = self.rewardColor or COMMON_COLOR
987 if self.itemNumber and self.target then
988 self.count:SetText(color.hex .. tostring(self.itemNumber))
989 else
990 self.count:SetText(nil)
991 end
992 end
993
994 SetMaskedTexture(iconBorder, borderFill, borderMask)
995 local border = (self.rewardType and POI_REWARD_TYPE[self.rewardType]) or (WORLD_QUEST_QUALITY_COLORS[self.rarity] or COMMON_COLOR)
996 iconBorder:SetVertexColor(border.r, border.g, border.b, border.a)
997 iconBorder:SetDesaturated(true)
998
999 local trackingBorder = self.supertrackBorder
1000
1001 self.highlight:SetMask(nil)
1002 if questID == GetSuperTrackedQuestID() then
1003 trackingBorder:SetVertexColor(0,0,0,1)
1004 else
1005 trackingBorder:SetVertexColor(0,0,0,0.5)
1006 end
1007 self.highlight:SetAllPoints(trackingBorder)
1008
1009 SetMaskedTexture(trackingBorder, borderFill, borderMask)
1010 self.highlight:SetMask(borderMask)
1011
1012 local qType = self.worldQuestType
1013 self.tagIcon:SetAtlas(self.tagAtlas)
1014 self.tagIcon:SetTexCoord(0,1,0,1)
1015
1016
1017 if self.isElite then
1018 self.EliteDecal:Show()
1019 else
1020 self.EliteDecal:Hide()
1021 end
1022
1023 if style.showNumber then
1024 self.label:SetText(self.itemNumber)
1025 else
1026 self.label:SetText(nil)
1027 end
1028 qprint('|cFF88FF00updated', questID, self.title, self.rewardType, (style.showNumber and self.itemNumber) or '')
1029 end
1030
1031 function QuestPOI:SetAnchor(frame, mapID, mapWidth, mapHeight)
1032 self:ClearAllPoints()
1033 local dX, dY = TQ_GetQuestLocation(self.questID, mapID)
1034 if not dX or dX == 0 then
1035 local _, x, y = QuestPOIGetIconInfo(self.questID)
1036 if x and floor(x) ~= 0 then
1037 dX, dY = x, y
1038 else
1039 dX, dY = self.x, self.y
1040 end
1041 end
1042 self.x = dX
1043 self.y = dY
1044
1045 print(' |cFF00FF00'..self.questID..':|r', format("%0.2f %0.2f", dX, dY))
1046
1047 local pX = (dX * mapWidth)
1048 local pY = (-dY * mapHeight)
1049
1050 self:SetParent(WorldMapPOIFrame)
1051 self:SetPoint('CENTER', frame, 'TOPLEFT', pX, pY)
1052 end
1053
1054
1055 function QuestPOI:IsShowable (ignoreFilters)
1056 local qType = self.worldQuestType
1057 local rType = self.rewardType
1058 self.filtered = nil
1059 print(' |cFFFF4400IsShowable()|r', self.tradeskillLineIndex, self.title)
1060
1061 local whiteListed, blackListed
1062 for filterKey, includes in pairs(FilterInclusions) do
1063 local controlValue = self[filterKey]
1064 if FilterInclusions[filterKey][controlValue] then
1065 whiteListed = true
1066 break
1067 end
1068 if FilterExclusions[filterKey][controlValue] then
1069 blackListed = true
1070 end
1071 end
1072 print(blackListed, whiteListed)
1073 self.filtered = (blackListed and (not whiteListed))
1074
1075 if not TQ_IsActive(self.questID) then
1076 print(' quest is dead')
1077 return false
1078 end
1079 if qType == LE_QUEST_TAG_TYPE_PROFESSION then
1080
1081 if not (ShowAllProfessionQuests or (self.tradeskillLineIndex and GetProfessionInfo(self.tradeskillLineIndex))) then
1082 print(' non-profession')
1083 return false
1084 end
1085 end
1086 return true
1087 end
1088
1089 function QuestPOI:UpdateTimer (timeLeft, timeType)
1090 print('|cFF0088FFUpdatePinTimer()|r')
1091 end
1092
1093 --- Re-acquires size information and triggers things
1094 function QuestPOI:GetSizeMetrics (style, subStyle)
1095 self.style = self.style or POI_DEFAULT_TYPE
1096 self.subStyle = self.subStyle or 'continent'
1097
1098 style = style or self.style
1099 subStyle = style[subStyle or self.subStyle]
1100
1101
1102 self.currentWidth = subStyle.PinSize
1103 self.borderSize = subStyle.Border
1104 self.trackingBorderSize = subStyle.TrackingBorder
1105 self.tagSize = subStyle.TagSize
1106 self.TimeleftStage = subStyle.TimeleftStage
1107 self.NoIcon = subStyle.NoIcon
1108
1109 self:SetSize(self.currentWidth, self.currentWidth)
1110 end
1111
1112 -- triggered by OnSizeChanged script
1113 function QuestPOI:OnSizeChanged ()
1114 local iconBorder = self.iconBorder
1115 local trackingBorder = self.supertrackBorder
1116 local tag = self.tagIcon
1117 local style = self.style or POI_DEFAULT_TYPE
1118 local mask = style.mask or POI_BORDER_FILL
1119
1120 self.icon:SetMask(nil)
1121 self.iconBorder:SetMask(nil)
1122 self.supertrackBorder:SetMask(nil)
1123
1124
1125 local borderWidth = self.borderSize
1126 local trackingWidth = self.trackingBorderSize
1127
1128 iconBorder:ClearAllPoints()
1129 iconBorder:SetPoint('BOTTOMLEFT', self, 'BOTTOMLEFT', -borderWidth + (style.x or 0), -borderWidth + (style.y or 0))
1130 iconBorder:SetPoint('TOPRIGHT', self, 'TOPRIGHT', borderWidth + (style.x or 0), borderWidth + (style.y or 0))
1131
1132 trackingBorder:ClearAllPoints()
1133 trackingBorder:SetPoint('BOTTOMLEFT', iconBorder, 'BOTTOMLEFT', -trackingWidth, -trackingWidth)
1134 trackingBorder:SetPoint('TOPRIGHT', iconBorder, 'TOPRIGHT', trackingWidth, trackingWidth)
1135
1136 if self.tagSize then
1137 tag:Show()
1138 tag:ClearAllPoints()
1139 tag:SetPoint('BOTTOMRIGHT', self, 'BOTTOMRIGHT', borderWidth, -borderWidth)
1140 else
1141 tag:Hide()
1142 end
1143
1144 self.icon:SetMask(mask)
1145 self.iconBorder:SetMask(mask)
1146 self.supertrackBorder:SetMask(mask)
1147
1148 if self.NoIcon then
1149 self.icon:Hide()
1150 else
1151 self.icon:Show()
1152 end
1153
1154 end
1155
1156
1157
1158 function FilterBar:OnEvent(event)
1159 if event == 'QUEST_LOG_UPDATE' then
1160 self:Refresh()
1161 end
1162 end
1163
1164 function FilterBar:PassesFilterSet(filterKey, pin)
1165 local passesFilter = true
1166 for filterKey, filters in pairs(QuestFilters) do
1167 for rewardType, value in pairs(QuestFilters[filterKey]) do
1168 if value == 1 and rewardType == pin[filterKey] then
1169 passesFilter = true
1170 elseif value == -1 and rewardType == pin[filterKey] then
1171 passesFilter = false
1172 end
1173 end
1174 end
1175 return passesFilter
1176 end
1177
1178 local debug_headers = {}
1179 function FilterBar:Refresh()
1180 local mapID = GetCurrentMapAreaID()
1181 local blocks = self.SummaryHeaders
1182 local numHeaders = 0
1183 local lastButton
1184 local pinSize, borderSize, trackingSize = 20, 2, 2
1185 print('|cFF00FF88'..tostring(self)..':Refresh()|r')
1186 for index, info in pairs(POI_FILTER_OPTIONS) do
1187 local numQuests = 0
1188 local quests = QuestsByZone[mapID] or QuestsByID
1189
1190 for questID, pin in pairs(quests) do
1191 if pin.used then
1192 if not info.filterKey then
1193 numQuests = numQuests + 1
1194 elseif pin[info.filterKey] == info.filterValue then
1195 numQuests = numQuests + 1
1196 end
1197 end
1198 end
1199 print(tostring(index).. ' ("'..tostring(info.label)..'"'.. tostring(rewardFilter).. ', '..tostring(tagFilter) .. ', '..tostring(numQuests)..')')
1200
1201 if numQuests >= 1 then
1202 numHeaders = numHeaders + 1
1203 local button = blocks[numHeaders]
1204 if not blocks[numHeaders] then
1205 button = CreateFrame('Button', 'WorldPlanFilterButton'..numHeaders, WorldMapScrollFrame, 'WorldPlanFilterPin')
1206 button.iconBorder:SetTexture(info.fill or POI_BORDER_FILL)
1207 button.iconBorder:SetMask(info.mask or POI_BORDER_MASK)
1208 button.iconBorder:SetDesaturated(info.desaturated)
1209 button.supertrackBorder:SetTexture(info.fill or POI_BORDER_FILL)
1210 button.supertrackBorder:SetMask(info.mask or POI_BORDER_MASK)
1211 button.supertrackBorder:SetDesaturated(true)
1212 blocks[numHeaders] = button
1213 end
1214
1215 button:SetID(index)
1216 button.lastButton = lastButton
1217 button:Refresh(info, (numHeaders == 1), numQuests)
1218 button:Show()
1219 lastButton = button
1220 end
1221
1222 end
1223 -- hide trailing buttons
1224 for i = numHeaders + 1, #POI_FILTER_OPTIONS do
1225 if blocks[i] then
1226 blocks[i]:Hide()
1227 end
1228 end
1229 end
1230
1231
1232 function FilterPin:Refresh(info, isFirst, numQuests)
1233 info = info or POI_FILTER_OPTIONS[self:GetID()]
1234 isFirst = isFirst or self.isFirst
1235 numQuests = numQuests or self.numQuests
1236
1237 self.isFirst = isFirst
1238 self.numQuests = numQuests
1239 self.filterKey = info.filterKey
1240 self.filterValue = info.filterValue
1241 self.tagID = info.tagID
1242
1243 self.icon:ClearAllPoints()
1244 self.icon:SetTexture(info.texture)
1245 self.icon:SetAllPoints(self)
1246 self.supertrackBorder:Hide()
1247 self.label:SetText(numQuests)
1248 self:Show()
1249
1250
1251 if isFirst then
1252 self:SetPoint('TOP', WorldMapFrame.UIElementsFrame.TrackingOptionsButton, 'BOTTOM', 0, -5)
1253 else
1254 self:SetPoint('TOPRIGHT', self.lastButton, 'BOTTOMRIGHT', 0, -(3*2 + 1 + (info.spacing or 0)))
1255 end
1256
1257 print(self.filterKey, self.filterValue)
1258 local r, g, b, a = 1,1,1,1
1259 if self.filterKey then
1260 if FilterInclusions[self.filterKey][self.filterValue] == true then
1261 r, g, b = 0, 1, 0
1262 elseif FilterExclusions[self.filterKey][self.filterValue] then
1263 r, g, b = 1, 0, 0
1264 end
1265 end
1266 self.iconBorder:SetVertexColor(r, g, b, a)
1267
1268
1269 self:GetSizeMetrics()
1270 end
1271
1272 function FilterPin:OnLoad()
1273 self:RegisterForClicks('AnyUp')
1274 self:SetFrameStrata('HIGH')
1275 self:SetFrameLevel(151)
1276 self:SetScript('OnUpdate', nil)
1277 end
1278
1279 function FilterPin:OnUpdate ()
1280
1281 end
1282
1283 function FilterPin:OnEnter ()
1284 local filter = POI_FILTER_OPTIONS[self:GetID()]
1285 local mapID = GetCurrentMapAreaID()
1286 local quests = (mapID == BROKEN_ISLES_ID) and QuestsByID or QuestsByZone[mapID]
1287 if quests then
1288 GameTooltip:SetOwner(self, 'ANCHOR_RIGHT')
1289 GameTooltip:AddLine(filter.label)
1290 local filterKey = self.filterKey
1291 local filterValue = self.filterValue
1292 if filterKey then
1293 for questID, pin in pairs(quests) do
1294 if pin.used and not pin.filtered then
1295 if pin[filterKey] == filterValue then
1296 local style = pin.style or POI_FILTER_STYLE
1297 GameTooltip:AddLine(pin.title)
1298 end
1299 end
1300 end
1301 else
1302 GameTooltip:AddLine('Reset all filters')
1303 end
1304 GameTooltip:Show()
1305 end
1306 end
1307 function FilterPin:OnLeave ()
1308 if GameTooltip:IsOwned(self) then
1309 GameTooltip:Hide()
1310 end
1311 end
1312
1313 -- shift-click: reset filter
1314 -- click: rotate through include(1), exclude(-1), ignore(nil)
1315 function FilterPin:OnClick (button)
1316 local filterKey = self.filterKey
1317 local filterValue = self.filterValue
1318
1319 print('click', filterKey, filterValue)
1320
1321 if not filterKey then
1322 -- resetting
1323 for k,v in pairs(FilterInclusions) do
1324 wipe(v)
1325 end
1326 for k,v in pairs(FilterExclusions) do
1327 wipe(v)
1328 end
1329 else
1330 local setExclude = (button == 'RightButton')
1331 if IsControlKeyDown() then
1332 if setExclude then
1333 if FilterExclusions[filterKey][filterValue] then
1334 FilterExclusions[filterKey][filterValue] = nil
1335 else
1336 FilterExclusions[filterKey][filterValue] = true
1337 end
1338 FilterInclusions[filterKey][filterValue] = nil
1339 else
1340 if FilterInclusions[filterKey][filterValue] == true then
1341 FilterInclusions[filterKey][filterValue] = nil
1342 else
1343 FilterInclusions[filterKey][filterValue] = true
1344 end
1345 FilterExclusions[filterKey][filterValue] = nil
1346 end
1347 elseif IsShiftKeyDown() then
1348 FilterInclusions[filterKey][filterValue] = nil
1349 FilterExclusions[filterKey][filterValue] = nil
1350 else
1351 print('limit to', filterKey, filterValue)
1352 if setExclude then
1353 FilterExclusions[filterKey][filterValue] = true
1354 FilterInclusions[filterKey][filterValue] = nil
1355 else
1356 FilterInclusions[filterKey][filterValue] = true
1357 FilterExclusions[filterKey][filterValue] = nil
1358 end
1359
1360 for k, info in ipairs(POI_FILTER_OPTIONS) do
1361 if info.filterKey and ((info.filterKey ~= filterKey) or (info.filterValue ~= filterValue)) then
1362 if setExclude then
1363 FilterExclusions[info.filterKey][info.filterValue] = nil
1364 FilterInclusions[info.filterKey][info.filterValue] = true
1365 else
1366 FilterExclusions[info.filterKey][info.filterValue] = true
1367 FilterInclusions[info.filterKey][info.filterValue] = nil
1368 end
1369
1370 end
1371 end
1372
1373 end
1374 end
1375
1376
1377 WorldPlan:RefreshAll()
1378 end
1379
1380 --%debug%
1381 local SetTimedCallbackForAllPins = function(seconds, callback)
1382 C_Timer.After(seconds, function()
1383 for id, pin in pairs(QuestsByID) do
1384 callback(pin)
1385 end
1386 end)
1387 end
1388
1389 SLASH_WORLDPLAN1 = "/worldplan"
1390 SLASH_WORLDPLAN2 = "/wp"
1391 SlashCmdList.WORLDPLAN = function()
1392 print('command pop')
1393 WorldPlan:GetPinsForMap()
1394 WorldPlan:RefreshPins()
1395
1396 SetTimedCallbackForAllPins(0, function(self) self.FadeIn:Play() self.FlashIn:Play() end)
1397 SetTimedCallbackForAllPins(5, function(self) self.PendingFade:Play() end)
1398 SetTimedCallbackForAllPins(8, function(self) self.PendingFade:Stop() end)
1399 end
1400 --%end-debug%
1401
1402 for mapID, mapName in pairs(WORLD_QUEST_MAPS) do
1403 QuestsByZone[mapID] = {}
1404 end
1405 for index, color in pairs(ITEM_QUALITY_COLORS) do
1406 POI_REWARD_TYPE[index] = {
1407 r = color.r, g = color.g, b = color.b,
1408 hex = color.hex,
1409 }
1410 end