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