comparison WorldPlan.lua @ 29:c1612c2c1840

WorldPlan: - Optimizations to in a lot of areas that should lead to better load-times and snappier world map. * Responding to quest log and map events by setting flags instead of tailing into the complete works. * Using a generic getter function for resolving pin visual attributes. and making use of blizzard constants for sanity's sake.
author Nenue
date Thu, 27 Oct 2016 13:50:56 -0400
parents 4a7e89bffbcb
children 8cb750e79952
comparison
equal deleted inserted replaced
28:3f4368c4a49b 29:c1612c2c1840
8 8
9 Issues: 9 Issues:
10 Dalaran quests aren't visible until that map has been specifically viewed by the player. 10 Dalaran quests aren't visible until that map has been specifically viewed by the player.
11 --]] 11 --]]
12 12
13 WorldPlanCore = {} 13 local ICON_UNKNOWN = "Interface\\ICONS\\inv_misc_questionmark"
14 local ICON_MONEY = "Interface\\Buttons\\UI-GroupLoot-Coin-Up"
15
16 local POI_BORDER_MASK = "Interface\\Minimap\\UI-Minimap-Background"
17 local POI_BORDER_FILL = "Interface\\BUTTONS\\YELLOWORANGE64"
18 local POI_BORDER_BLUE = "Interface\\BUTTONS\\GRADBLUE"
19 local POI_BORDER_RED = "Interface\\BUTTONS\\RedGrad64"
20 local POI_BORDER_YELLOW = "Interface\\BUTTONS\\YELLOWORANGE64"
21 local POI_BORDER_GREEN = "Interface\\BUTTONS\\GREENGRAD64"
22
23 WorldPlanCore = {
24 defaults = {},
25
26 }
14 WorldPlanPOIMixin = {} 27 WorldPlanPOIMixin = {}
15 WorldPlanFilterPinMixin = {} 28 WorldPlanFilterPinMixin = {}
16 local WorldPlanFlightMapMixin = setmetatable({}, {__tostring = function() return 'FlightMapHandler' end}) 29 local WorldPlanFlightMapMixin = setmetatable({}, {__tostring = function() return 'FlightMapHandler' end})
17 local WorldQuests = setmetatable({ QuestsByID = {}, freePins = {} }, {__tostring = function() return 'QuestHandler' end}) 30 local WorldQuests = setmetatable({ QuestsByID = {}, freePins = {} }, {__tostring = function() return 'QuestHandler' end})
18 local FilterBar = setmetatable({ SummaryHeaders = {} }, {__tostring = function() return 'FilterBar' end}) 31 local FilterBar = setmetatable({ SummaryHeaders = {} }, {__tostring = function() return 'FilterBar' end})
28 local iprint = DEVIAN_WORKSPACE and function(...) _G.print('ItemScan', ...) end or function() end 41 local iprint = DEVIAN_WORKSPACE and function(...) _G.print('ItemScan', ...) end or function() end
29 local wqprint = DEVIAN_WORKSPACE and function(...) _G.print('WorldQuests', ...) end or function() end 42 local wqprint = DEVIAN_WORKSPACE and function(...) _G.print('WorldQuests', ...) end or function() end
30 local fbprint = DEVIAN_WORKSPACE and function(...) _G.print('FilterBar', ...) end or function() end 43 local fbprint = DEVIAN_WORKSPACE and function(...) _G.print('FilterBar', ...) end or function() end
31 44
32 local wipe, tremove, tinsert, pairs, floor, tContains = table.wipe, table.remove, table.insert, pairs, floor, tContains 45 local wipe, tremove, tinsert, pairs, floor, tContains = table.wipe, table.remove, table.insert, pairs, floor, tContains
33 local TQ_GetQuestInfoByQuestID = C_TaskQuest.GetQuestInfoByQuestID -- Return the name of a quest with a given ID
34 local TQ_GetQuestsForPlayerByMapID = C_TaskQuest.GetQuestsForPlayerByMapID -- This function is not yet documented 46 local TQ_GetQuestsForPlayerByMapID = C_TaskQuest.GetQuestsForPlayerByMapID -- This function is not yet documented
35 local TQ_GetQuestTimeLeftMinutes = C_TaskQuest.GetQuestTimeLeftMinutes 47 local TQ_GetQuestZoneID = C_TaskQuest.GetQuestZoneID
36 local TQ_RequestPreloadRewardData = C_TaskQuest.RequestPreloadRewardData
37 local TQ_GetQuestLocation = C_TaskQuest.GetQuestLocation
38 local TQ_IsActive = C_TaskQuest.IsActive 48 local TQ_IsActive = C_TaskQuest.IsActive
39 local ITEM_QUALITY_COLORS = ITEM_QUALITY_COLORS 49 local ITEM_QUALITY_COLORS = ITEM_QUALITY_COLORS
40 local WorldMap_DoesWorldQuestInfoPassFilters = WorldMap_DoesWorldQuestInfoPassFilters 50 local WorldMap_DoesWorldQuestInfoPassFilters = WorldMap_DoesWorldQuestInfoPassFilters
41 local QuestMapFrame_IsQuestWorldQuest = QuestMapFrame_IsQuestWorldQuest 51 local QuestMapFrame_IsQuestWorldQuest = QuestMapFrame_IsQuestWorldQuest
42 local GameTooltip = GameTooltip 52 local GameTooltip = GameTooltip
61 [HIGHMOUNTAIN_ID] = 'Highmountain', [STORMHEIM_ID] = 'Stormheim', [SURAMAR_ID] = 'Suramar', [EOA_ID] = 'EyeOfAszhara', } 71 [HIGHMOUNTAIN_ID] = 'Highmountain', [STORMHEIM_ID] = 'Stormheim', [SURAMAR_ID] = 'Suramar', [EOA_ID] = 'EyeOfAszhara', }
62 -- default color templates 72 -- default color templates
63 local ARTIFACT_COLOR = ITEM_QUALITY_COLORS[LE_ITEM_QUALITY_ARTIFACT] 73 local ARTIFACT_COLOR = ITEM_QUALITY_COLORS[LE_ITEM_QUALITY_ARTIFACT]
64 local MONEY_COLOR = {hex ='|cFFFFFF00', r=1, g=1, b=0} 74 local MONEY_COLOR = {hex ='|cFFFFFF00', r=1, g=1, b=0}
65 local COMMON_COLOR = ITEM_QUALITY_COLORS[LE_ITEM_QUALITY_COMMON] 75 local COMMON_COLOR = ITEM_QUALITY_COLORS[LE_ITEM_QUALITY_COMMON]
66 76 local DEFAULT_TYPE = {
67 local ICON_UNKNOWN = "Interface\\ICONS\\inv_misc_questionmark"
68 local ICON_MONEY = "Interface\\Buttons\\UI-GroupLoot-Coin-Up"
69
70 local POI_BORDER_MASK = "Interface\\Minimap\\UI-Minimap-Background"
71 local POI_BORDER_FILL = "Interface\\BUTTONS\\YELLOWORANGE64"
72 local POI_BORDER_BLUE = "Interface\\BUTTONS\\GRADBLUE"
73 local POI_BORDER_RED = "Interface\\BUTTONS\\RedGrad64"
74 local POI_BORDER_YELLOW = "Interface\\BUTTONS\\YELLOWORANGE64"
75 local POI_BORDER_GREEN = "Interface\\BUTTONS\\GREENGRAD64"
76
77 local REWARD_CASH = 1001
78 local REWARD_ARTIFACT_POWER = 1002
79 local REWARD_GEAR = 1003
80 local REWARD_CURRENCY = 1004
81 local REWARD_ITEM = 1005
82 local REWARD_REAGENT = 1006
83
84 local POI_DEFAULT_TYPE = {
85 a = 1, 77 a = 1,
86 r = 1, g = 1, b = 1, 78 r = 1, g = 1, b = 1,
87 x = 0, y = 0, 79 x = 0, y = 0,
88 desaturated = true, 80 desaturated = true,
89 pinMask = POI_BORDER_MASK, 81 pinMask = POI_BORDER_MASK,
112 NoIcon = true, 104 NoIcon = true,
113 TimeleftStage = 1, 105 TimeleftStage = 1,
114 showNumber = false, 106 showNumber = false,
115 } 107 }
116 } 108 }
117 local POI_REWARD_TYPE = setmetatable({}, { 109
118 __newindex = function(t, k, v) 110
119 if type(v) == 'table' then
120 setmetatable(v, {__index = POI_DEFAULT_TYPE})
121 end
122 rawset(t,k,v)
123 end
124 })
125 local POI_FILTER_STYLE = setmetatable({ 111 local POI_FILTER_STYLE = setmetatable({
126 continentBorder = 2, 112 continentBorder = 2,
127 zoneBorder = 2, 113 zoneBorder = 2,
128 }, {__index = POI_DEFAULT_TYPE}) 114 }, {__index = DEFAULT_TYPE})
129
130 local LE_QUEST_TAG_TYPE_PVP = LE_QUEST_TAG_TYPE_PVP
131 local LE_QUEST_TAG_TYPE_PET_BATTLE = LE_QUEST_TAG_TYPE_PET_BATTLE
132 local LE_QUEST_TAG_TYPE_DUNGEON = LE_QUEST_TAG_TYPE_DUNGEON
133 local LE_QUEST_TAG_TYPE_PROFESSION = LE_QUEST_TAG_TYPE_PROFESSION
134 local LE_QUEST_TAG_TYPE_NORMAL = LE_QUEST_TAG_TYPE_NORMAL
135
136 -- Pin color/display variables
137 POI_REWARD_TYPE[REWARD_ITEM] = {
138 r = 1, g = 1, b = 1,
139 }
140 POI_REWARD_TYPE[REWARD_REAGENT] = {
141 r = 0, g = 1, b = 1,
142 }
143 POI_REWARD_TYPE[REWARD_ARTIFACT_POWER] = {
144 r = 1, g = .25, b = .5,
145 hasNumeric = true,
146 numberRGB = {1, 1, 1},
147 }
148 POI_REWARD_TYPE[REWARD_GEAR] = {
149 r = .1, g = .2, b = 1,
150 }
151 POI_REWARD_TYPE[REWARD_CURRENCY] = {
152 r = 1, g = 1, b = 0,
153 hasNumeric = true,
154 numberRGB = {1, 1, 1},
155 }
156 POI_REWARD_TYPE[REWARD_CASH] = {
157 r = 0, g = 0, b = 0,
158 --x = 0, y = -1,
159 --mask = ICON_MONEY,
160 --continentBorder = 1,
161 --zoneBorder = 1,
162 }
163
164 115
165 116
166 local defaults = { 117 local defaults = {
167 defaultPinStyle = POI_DEFAULT_TYPE, 118 defaultPinStyle = POI_DEFAULT_TYPE,
168 rewardStyle = POI_REWARD_TYPE, 119 rewardStyle = POI_REWARD_TYPE,
174 EnablePins = true, 125 EnablePins = true,
175 FadeWhileGrouped = true, 126 FadeWhileGrouped = true,
176 } 127 }
177 128
178 -- Summary header structure 129 -- Summary header structure
130
131 local REWARD_CASH = WORLD_QUEST_REWARD_TYPE_FLAG_GOLD
132 local REWARD_ARTIFACT_POWER = WORLD_QUEST_REWARD_TYPE_FLAG_ARTIFACT_POWER
133 local REWARD_GEAR = WORLD_QUEST_REWARD_TYPE_FLAG_EQUIPMENT
134 local REWARD_CURRENCY = WORLD_QUEST_REWARD_TYPE_FLAG_ORDER_RESOURCES
135 local REWARD_REAGENT = WORLD_QUEST_REWARD_TYPE_FLAG_MATERIALS
136
137
138 local LE_QUEST_TAG_TYPE_PVP = LE_QUEST_TAG_TYPE_PVP
139 local LE_QUEST_TAG_TYPE_PET_BATTLE = LE_QUEST_TAG_TYPE_PET_BATTLE
140 local LE_QUEST_TAG_TYPE_DUNGEON = LE_QUEST_TAG_TYPE_DUNGEON
141 local LE_QUEST_TAG_TYPE_PROFESSION = LE_QUEST_TAG_TYPE_PROFESSION
142 local LE_QUEST_TAG_TYPE_NORMAL = LE_QUEST_TAG_TYPE_NORMAL
179 local POI_FILTER_OPTIONS = { 143 local POI_FILTER_OPTIONS = {
180 { label = 'Filters', texture = "Interface\\WorldMap\\WorldMap-Icon" }, 144 { label = 'Filters', texture = "Interface\\WorldMap\\WorldMap-Icon" },
181 { filterKey= 'rewardType', filterValue = REWARD_ARTIFACT_POWER, label = 'Artifact Power', texture = "Interface\\ICONS\\inv_7xp_inscription_talenttome01" }, 145 { filterKey= 'rewardType', filterValue = REWARD_ARTIFACT_POWER, label = 'Artifact Power', texture = "Interface\\ICONS\\inv_7xp_inscription_talenttome01" },
182 { filterKey= 'rewardType', filterValue = REWARD_CURRENCY,label = 'Currency', texture = "Interface\\ICONS\\inv_misc_elvencoins" }, 146 { filterKey= 'rewardType', filterValue = REWARD_CURRENCY,label = 'Order Resources', texture = "Interface\\ICONS\\inv_misc_elvencoins" },
183 { filterKey= 'rewardType', filterValue = REWARD_ITEM, label = 'Item', texture = "Interface\\ICONS\\inv_crate_01" },
184 { filterKey= 'rewardType', filterValue = REWARD_GEAR, label = 'Equipment', texture = "Interface\\ICONS\\garrison_bluearmorupgrade" }, 147 { filterKey= 'rewardType', filterValue = REWARD_GEAR, label = 'Equipment', texture = "Interface\\ICONS\\garrison_bluearmorupgrade" },
185 { filterKey= 'rewardType', filterValue = REWARD_REAGENT, label = 'Reagents', texture = 1417744 }, 148 { filterKey= 'rewardType', filterValue = REWARD_REAGENT, label = 'Materials', texture = 1417744 },
186 { filterKey= 'rewardType', filterValue = REWARD_CASH, label = 'Reagents', texture = ICON_MONEY }, 149 { filterKey= 'rewardType', filterValue = REWARD_CASH, label = 'Gold', texture = ICON_MONEY },
187 { filterKey= 'worldQuestType', filterValue = LE_QUEST_TAG_TYPE_PVP, label = 'PvP', texture = "Interface\\Icons\\Ability_PVP_GladiatorMedallion", spacing = 10 }, 150 { filterKey= 'worldQuestType', filterValue = LE_QUEST_TAG_TYPE_PVP, label = 'PvP', texture = "Interface\\Icons\\Ability_PVP_GladiatorMedallion", spacing = 10 },
188 { filterKey= 'worldQuestType', filterValue = LE_QUEST_TAG_TYPE_PET_BATTLE, label = 'Pet Battle', texture = "Interface\\Icons\\PetJournalPortrait", }, 151 { filterKey= 'worldQuestType', filterValue = LE_QUEST_TAG_TYPE_PET_BATTLE, label = 'Pet Battle', texture = "Interface\\Icons\\PetJournalPortrait", },
189 { filterKey= 'worldQuestType', filterValue = LE_QUEST_TAG_TYPE_DUNGEON, label = 'Dungeon', texture = "Interface\\LFGFRAME\\UI-LFR-PORTRAIT", }, 152 { filterKey= 'worldQuestType', filterValue = LE_QUEST_TAG_TYPE_DUNGEON, label = 'Dungeon', texture = "Interface\\LFGFRAME\\UI-LFR-PORTRAIT", },
190 { filterKey= 'worldQuestType', filterValue = LE_QUEST_TAG_TYPE_PROFESSION, label = 'Profession', texture = "Interface\\ICONS\\70_professions_scroll_02", }, 153 { filterKey= 'worldQuestType', filterValue = LE_QUEST_TAG_TYPE_PROFESSION, label = 'Profession', texture = "Interface\\ICONS\\70_professions_scroll_02", },
191 } 154 }
248 end 211 end
249 end 212 end
250 return frame 213 return frame
251 end 214 end
252 215
253 -- use tooltip object to extract item details
254 local ParseItemReward = function(questID)
255 local rewardType = REWARD_ITEM
256 local name, icon, quantity, quality, _, itemID = GetQuestLogRewardInfo(1, questID)
257 if not itemID then
258 return REWARD_ITEM
259 end
260
261 scanner:SetOwner(WorldPlan, "ANCHOR_NONE")
262 scanner:SetItemByID(itemID)
263 local ttl1 = _G['WorldPlanTooltipTextLeft1']
264 local ttl2 = _G['WorldPlanTooltipTextLeft2']
265 local ttl3 = _G['WorldPlanTooltipTextLeft3']
266 local ttl4 = _G['WorldPlanTooltipTextLeft4']
267 if ttl2 then
268 local text = ttl2:GetText()
269 -- Artifact Power
270 if text and text:match("|cFFE6CC80") then
271 --print('AP token!', text)
272 local power
273 if ttl4 then
274 local text = ttl4:GetText()
275 --print('tip line 4', text)
276 if text then
277 power = text:gsub("%p", ""):match("%d+")
278 power = tonumber(power)
279 end
280
281 end
282 rewardType = REWARD_ARTIFACT_POWER
283 icon = "Interface\\ICONS\\inv_7xp_inscription_talenttome01"
284 quantity = power
285 elseif text and text:match("Item Level") then
286 --print('equipment!', text)
287 rewardType = REWARD_GEAR
288 quantity = text:match("Item Level ([%d\+]+)")
289 end
290 end
291 if ttl3 then
292 local text = ttl3:GetText()
293 -- Crafting Reagent
294 if text and text:match("Crafting Reagent") then
295 --print('reagent', text)
296 rewardType = REWARD_REAGENT
297 end
298 end
299 iprint(' item:', name, rewardType, icon, quantity)
300 return rewardType, icon, quantity, name, itemID
301 end
302 216
303 -- update a masked texture without messing up its blending mask 217 -- update a masked texture without messing up its blending mask
304 local SetMaskedTexture = function(region, file, mask) 218 local SetMaskedTexture = function(region, file, mask)
305 mask = mask or POI_BORDER_MASK 219 mask = mask or POI_BORDER_MASK
306 region:SetMask(nil) 220 region:SetMask(nil)
328 end 242 end
329 DEFAULT_CHAT_FRAME:AddMessage("|cFF0088FFWorldPlan|r: " .. msg) 243 DEFAULT_CHAT_FRAME:AddMessage("|cFF0088FFWorldPlan|r: " .. msg)
330 end 244 end
331 245
332 function WorldPlan:OnLoad () 246 function WorldPlan:OnLoad ()
247
248 self.Types = setmetatable({}, {
249 __newindex = function(t, k, v)
250 print('adding type', k)
251 if type(v) == 'table' then
252 v = setmetatable(v, {__index = function(t,k)
253 print('##deferring to default key', k)
254 return DEFAULT_TYPE[k]
255 end})
256 end
257 rawset(t,k,v)
258 end
259 })
260
261 local rgbWhite = {1, 1, 1}
262 self.Types[REWARD_REAGENT] = { r = 0, g = 1, b = 1 }
263 self.Types[REWARD_ARTIFACT_POWER] = { r = 1, g = .25, b = .5, hasNumeric = true, numberRGB = rgbWhite }
264 self.Types[REWARD_GEAR] = { r = .1, g = .2, b = 1 }
265 self.Types[REWARD_CURRENCY] = { r = 1, g = 1, b = 0, hasNumeric = true, numberRGB = rgbWhite, }
266 self.Types[REWARD_CASH] = { r = 0, g = 0, b = 0, }
267
268 for index, color in pairs(ITEM_QUALITY_COLORS) do
269 self.Types[(index+127)] = { r = color.r, g = color.g, b = color.b, hex = color.hex, }
270 end
271
333 WorldPlan = self 272 WorldPlan = self
334 scanner = _G.WorldPlanTooltip 273 scanner = _G.WorldPlanTooltip
335 wmtt = _G.WorldMapTooltip 274 wmtt = _G.WorldMapTooltip
336 WorldMapPOIFrame = _G.WorldMapPOIFrame 275 WorldMapPOIFrame = _G.WorldMapPOIFrame
337 276
417 end 356 end
418 end 357 end
419 self.initialized = true 358 self.initialized = true
420 359
421 hooksecurefunc("UIDropDownMenu_Initialize", self.OnDropDownInitialize) 360 hooksecurefunc("UIDropDownMenu_Initialize", self.OnDropDownInitialize)
361 end
362
363 function WorldPlan:GetTypeInfo(typeID)
364 local info, extraInfo
365 if (not typeID) or (not self.Types[typeID]) then
366 qprint('## sent default type')
367 info = DEFAULT_TYPE
368 else
369 qprint('## sent defined type', typeID)
370 info = self.Types[typeID]
371 end
372
373 if isContinentMap then
374 extraInfo = info.continent
375 qprint('### continent subtype', extraInfo)
376 else
377 extraInfo = info.zone
378
379 qprint('### zone subtype', extraInfo)
380 end
381 return info, extraInfo
382 end
383
384 do
385 local timeStates = {
386 {maxSeconds = 60,
387 r=1, g=0.25, b =0, format = function (minutes) return '|cFFFF4400'.. minutes .. 'm' end,
388 },
389 {maxSeconds = 240,
390 r=1, g=.5, b=0, format = function(minutes) return '|cFFFF4400'.. floor(minutes/60) .. 'h' end,
391 },
392 {maxSeconds = 1440,
393 r=1, g=1, b=0, format = function(minutes) return '|cFFFFFF00'.. floor(minutes/60) .. 'h' end,
394 },
395 {maxSeconds = 10081,
396 r=0, g=1, b=0,
397 }, -- 7 days + 1 minute
398 }
399 -- Generates a timeleft string
400 function WorldPlan:GetTimeInfo(timeLeft, limit)
401 limit = limit or #timeStates
402 for index = 1, limit do
403 local state = timeStates[index]
404 if timeLeft <= state.maxSeconds then
405 local text
406 if state.format then
407 text = state.format(timeLeft)
408 end
409 return text, index
410 end
411 end
412 return nil, nil
413 end
422 end 414 end
423 415
424 function WorldPlan:RefreshAll (forced) 416 function WorldPlan:RefreshAll (forced)
425 if not self.initialized then 417 if not self.initialized then
426 return 418 return
524 info.func = DropDown_OnClick 516 info.func = DropDown_OnClick
525 UIDropDownMenu_AddButton(info) 517 UIDropDownMenu_AddButton(info)
526 end 518 end
527 519
528 function WorldQuests:Setup() 520 function WorldQuests:Setup()
521
522
523 for mapID, mapName in pairs(WORLD_QUEST_MAPS) do
524 QuestsByZone[mapID] = {}
525 end
526
527
529 -- refresh positions any time blizzard does so (i.e. mousewheel zoom) 528 -- refresh positions any time blizzard does so (i.e. mousewheel zoom)
530 hooksecurefunc("WorldMapScrollFrame_ReanchorQuestPOIs", function() 529 hooksecurefunc("WorldMapScrollFrame_ReanchorQuestPOIs", function()
531 self:Refresh(true) 530 self:Refresh(true)
532 end) 531 end)
533 532
546 function WorldQuests:OnEvent (event, ...) 545 function WorldQuests:OnEvent (event, ...)
547 print('|cFFFFFF00'..tostring(self)..':OnEvent()'..event..'|r', GetTime(), ...) 546 print('|cFFFFFF00'..tostring(self)..':OnEvent()'..event..'|r', GetTime(), ...)
548 if event == 'QUEST_LOG_UPDATE' then 547 if event == 'QUEST_LOG_UPDATE' then
549 local questID, added = ... 548 local questID, added = ...
550 if questID and added then 549 if questID and added then
551 self:GetPinByQuestID(questID) 550 local questPOI = self:AcquirePin(questID)
551 self.hasUpdate, self.isPending = questPOI:RefreshData()
552 else 552 else
553 self:GetPinsForMap() 553 self:RefreshData()
554 end 554 end
555 print('WorldMapFrame', WorldMapFrame:IsVisible(), 'doRefresh:', hasNewQuestPins) 555 print('WorldMapFrame', WorldMapFrame:IsVisible(), 'doRefresh:', hasNewQuestPins)
556 if WorldMapFrame:IsVisible() and hasNewQuestPins then 556 if WorldMapFrame:IsVisible() and hasNewQuestPins then
557 self:Refresh(true) 557 self:Refresh(true)
558 end 558 end
564 end 564 end
565 elseif event == 'SKILL_LINES_CHANGED' then 565 elseif event == 'SKILL_LINES_CHANGED' then
566 self:Refresh(true) 566 self:Refresh(true)
567 end 567 end
568 end 568 end
569 569 local TQ_GetQuestLocation = C_TaskQuest.GetQuestLocation
570 function WorldQuests:AcquirePin (questID, pinTable) 570 function WorldQuests:AcquirePin (questID, mapID)
571 local pin = QuestsByID[questID] 571 local pin = QuestsByID[questID]
572 local isNew = false 572 local isNew = false
573 if not pin then 573 if not pin then
574 isNew = true 574 isNew = true
575 local numFree = #self.freePins 575 local numFree = #self.freePins
578 --print('|cFF00FF00Re-using', pin:GetName()) 578 --print('|cFF00FF00Re-using', pin:GetName())
579 else 579 else
580 local name = 'WorldPlanQuestMarker' .. NumPinFrames 580 local name = 'WorldPlanQuestMarker' .. NumPinFrames
581 --print('|cFF00FF00Creating', name) 581 --print('|cFF00FF00Creating', name)
582 pin = CreateFrame('Frame', name, WorldMapPOIFrame, 'WorldPlanQuestPin') 582 pin = CreateFrame('Frame', name, WorldMapPOIFrame, 'WorldPlanQuestPin')
583
583 pin:SetFrameStrata('HIGH') 584 pin:SetFrameStrata('HIGH')
584
585 NumPinFrames = NumPinFrames + 1 585 NumPinFrames = NumPinFrames + 1
586
587 --pin.iconBorder:SetVertexColor(0,0,0,1) 586 --pin.iconBorder:SetVertexColor(0,0,0,1)
588 587 end
589 end 588 pin:SetID(questID)
590 QuestsByID[questID] = pin
591 pin.isNew = true 589 pin.isNew = true
592 pin.currentWidth = nil 590 pin.currentWidth = nil
593 591
594 -- used by TaskPOI_x scripts 592 -- used by TaskPOI_x scripts
595 pin.questID = questID 593 pin.questID = questID
596 pin.worldQuest = true 594 pin.worldQuest = true
597 595
598 pin.Reset = function(self) 596 QuestsByID[questID] = pin
599 WorldQuests:GetPinByQuestID(questID)
600 end
601 else 597 else
602 --print('|cFF00FF00Using', pin:GetName()) 598 --print('|cFF00FF00Using', pin:GetName())
603 end 599 end
604 600 mapID = mapID or TQ_GetQuestZoneID(questID)
605 -- set display flags accordingly 601 QuestsByZone[mapID][questID] = pin
606 if pinTable then 602
607 for k,v in pairs(pinTable) do
608 pin[k] = v
609 end
610 end
611 pin.throttle = nil
612 pin.timeThreschold = nil
613 return pin, isNew 603 return pin, isNew
614 end 604 end
615 605
616 -- remove from index and add it to the recycling heap 606 -- remove from index and add it to the recycling heap
617 function WorldQuests:ReleasePin (pin) 607 function WorldQuests:ReleasePin (pin)
632 tinsert(self.freePins, pin) 622 tinsert(self.freePins, pin)
633 print('|cFFFF4400Clearing out', pin:GetName(),id) 623 print('|cFFFF4400Clearing out', pin:GetName(),id)
634 end 624 end
635 625
636 -- create of update quest pins for a map and its underlying zones 626 -- create of update quest pins for a map and its underlying zones
637 function WorldQuests:GetPinsForMap (mapID) 627 function WorldQuests:RefreshData (mapID)
638 local print = wqprint 628 local print = wqprint
639 mapID = mapID or GetCurrentMapAreaID() 629 mapID = mapID or GetCurrentMapAreaID()
640 superTrackedID = GetSuperTrackedQuestID() 630 superTrackedID = GetSuperTrackedQuestID()
641 if not mapID then 631 if not mapID then
642 -- info not available yet 632 -- info not available yet
643 return 633 return
644 end 634 end
645 if mapID == BROKEN_ISLES_ID then 635 if mapID == BROKEN_ISLES_ID then
646 hasPendingQuestData = nil 636 self.hasUpdate = false
647 print('|cFF00FFFFRefreshQuestsForMap|r', mapID, GetMapNameByID(mapID), superTrackedID) 637 print('|cFF00FFFFRefreshQuestsForMap|r', mapID, GetMapNameByID(mapID), superTrackedID)
648 self.fullSearch = true 638 self.fullSearch = true
649 for i = 1, MC_GetNumZones(mapID) do 639 for i = 1, MC_GetNumZones(mapID) do
650 local submapID, name, depth = MC_GetZoneInfo(mapID, i) 640 local submapID, name, depth = MC_GetZoneInfo(mapID, i)
651 self:GetPinsForMap(submapID) 641 self:RefreshData(submapID)
652 end 642 end
653 self.fullSearch = nil 643 self.fullSearch = nil
654 elseif QuestsByZone[mapID] then 644 elseif QuestsByZone[mapID] then
655 local taskInfo = TQ_GetQuestsForPlayerByMapID(mapID) 645 local taskInfo = TQ_GetQuestsForPlayerByMapID(mapID)
656 local quest = QuestsByZone[mapID] 646 local quest = QuestsByZone[mapID]
658 if taskInfo and #taskInfo >= 1 then 648 if taskInfo and #taskInfo >= 1 then
659 print('|cFF00FFFFRefreshQuestsForMap|r', mapID, GetMapNameByID(mapID), #taskInfo) 649 print('|cFF00FFFFRefreshQuestsForMap|r', mapID, GetMapNameByID(mapID), #taskInfo)
660 wipe(QuestsByZone[mapID]) 650 wipe(QuestsByZone[mapID])
661 ZoneInfo[mapID] = taskInfo 651 ZoneInfo[mapID] = taskInfo
662 for taskID, info in pairs(taskInfo) do 652 for taskID, info in pairs(taskInfo) do
653 print('-', taskID)
663 local questID = info.questId 654 local questID = info.questId
664
665 info.mapID = mapID 655 info.mapID = mapID
666 QuestsByZone[mapID][questID] = self:GetPinByQuestID(questID, info) 656 local questPOI = self:AcquirePin(questID, mapID)
657 local hasUpdate, isPending = questPOI:RefreshData(taskInfo)
658 self.hasUpdate = (self.hasUpdate or hasUpdate)
659 self.isPending = (self.isPending or isPending)
667 numQuests = numQuests + 1 660 numQuests = numQuests + 1
668 end 661 end
669 end 662 end
670 end 663 end
671 end 664
672 665 print(' hasUpdate:', self.hasUpdate, 'isPending:', self.isPending, 'timer:', self.OnNext)
673 -- create or update the pin using the given questID and C_TaskQuest results 666 if self.hasUpdate then
674 function WorldQuests:GetPinByQuestID (questID, taskInfo) 667 self.OnNext = self.OnNext or C_Timer.NewTimer(0.25, function()
675 668 self:Refresh(true)
676 local questTitle, rewardIcon, rewardName, rewardCount, rewardStyle, rewardType, itemID, quantity, quality, _ 669 self.OnNext = nil
677 local pin = self:AcquirePin(questID, taskInfo) 670 end)
678 671 end
679 if pin.isNew then
680 if not hasNewQuestPins then
681 print('triggering new quest pins event')
682 end
683
684 hasNewQuestPins = true
685 end
686
687 if not HaveQuestData(questID) then
688 print('|cFFFF4400Retrieval failed.')
689 TQ_RequestPreloadRewardData(questID)
690 hasPendingQuestData = true
691 else
692 wqprint('|cFF00FF88Quest Data Received|r')
693 pin.mapID = pin.mapID or C_TaskQuest.GetQuestZoneID(questID)
694
695 -- set reward category
696 local numRewards = GetNumQuestLogRewards(questID)
697 local numCurrency = GetNumQuestLogRewardCurrencies(questID)
698 local money = GetQuestLogRewardMoney(questID)
699 if numRewards >= 1 then
700 rewardType, rewardIcon, rewardCount, rewardName, itemID = ParseItemReward(questID)
701 elseif numCurrency >= 1 then
702 rewardName, rewardIcon, rewardCount = GetQuestLogRewardCurrencyInfo(1, questID)
703 rewardType = REWARD_CURRENCY
704 elseif money >= 1 then
705 rewardIcon = ICON_MONEY
706 rewardName = GetMoneyString(money)
707 rewardType = REWARD_CASH
708 end
709 rewardStyle = POI_REWARD_TYPE[rewardType] or POI_DEFAULT_TYPE
710
711 pin.itemNumber = rewardCount or pin.itemNumber
712 pin.rewardType = rewardType or REWARD_ITEM
713 pin.style = rewardStyle
714 QuestsByID[questID] = pin
715
716 -- title, faction, capped state
717 local questTitle, factionID, capped = TQ_GetQuestInfoByQuestID(questID)
718 if factionID then
719 QuestsByFaction[factionID] = QuestsByFaction[factionID] or {}
720 QuestsByFaction[factionID][questID] = pin
721 end
722 pin.factionID = factionID
723 pin.capped = capped
724
725 -- set tag details
726 local tagID, tagName, worldQuestType, rarity, isElite, tradeskillLineIndex = GetQuestTagInfo(questID);
727 local tagAtlas
728 if worldQuestType == LE_QUEST_TAG_TYPE_PET_BATTLE then
729 tagAtlas = "worldquest-icon-petbattle"
730 elseif worldQuestType == LE_QUEST_TAG_TYPE_PVP then
731 tagAtlas = "worldquest-icon-pvp-ffa"
732 elseif worldQuestType == LE_QUEST_TAG_TYPE_PROFESSION then
733 local id = tradeskillLineIndex and select(7, GetProfessionInfo(tradeskillLineIndex))
734 if id then
735 tagAtlas = WORLD_QUEST_ICONS_BY_PROFESSION[id]
736 end
737 elseif worldQuestType == LE_QUEST_TAG_TYPE_DUNGEON then
738 tagAtlas = "worldquest-icon-dungeon"
739 end
740
741 pin.tagID = tagID
742 pin.tagName = tagName
743 pin.worldQuestType = worldQuestType
744 pin.isElite = isElite
745 pin.tradeskillLineIndex = tradeskillLineIndex
746 pin.rarity = rarity
747 pin.tagAtlas = tagAtlas
748
749 -- flag unresolved info
750 if not (rewardIcon and rewardName) then
751 if not pin.isPending then
752 pin.isPending = true
753 TQ_RequestPreloadRewardData (questID)
754 pin.rewardType = pin.rewardType or REWARD_ITEM
755 pin.style = pin.style or POI_REWARD_TYPE[REWARD_ITEM]
756
757 if not hasPendingQuestData then
758 hasPendingQuestData = true
759 PlaySoundKitID(229)
760 end
761 --WorldPlan:print('|cFFFFFF00'..tostring(pin.title)..'|r waiting on texture info')
762 end
763 else
764 if (rewardIcon and rewardName) then
765 --WorldPlan:print('|cFF00FF00'..tostring(pin.title)..'|r has info', rewardIcon, rewardName)
766 pin.hasUpdate = true
767 end
768 pin.isPending = nil
769 end
770
771 pin.title = questTitle or "|cFFFF0000Retrieving..."
772 pin.itemTexture = rewardIcon or pin.itemTexture
773 pin.itemName = rewardName or pin.itemName
774
775 qprint(' |cFF00FFFF'..questID..'|r:->', (HaveQuestData(questID) and "|cFF00FF00HaveQuestData" or "-"), (C_TaskQuest.IsActive(questID) and "|cFF88FF00IsActive|r" or ""))
776 qprint(' ', pin.title, pin.itemTexture, 'rewardType:', pin.rewardType, 'tag:', pin.tagID, 'style', pin.style )
777 end
778 return QuestsByID[questID]
779 end 672 end
780 673
781 function WorldQuests:Refresh(forced) 674 function WorldQuests:Refresh(forced)
782 local print = wqprint 675 local print = wqprint
783 print('|cFF00FF88'..tostring(self)..':Refresh()|r') 676 print('|cFF00FF88'..tostring(self)..':Refresh()|r')
1169 if numQuests >= 1 then 1062 if numQuests >= 1 then
1170 numHeaders = numHeaders + 1 1063 numHeaders = numHeaders + 1
1171 local button = blocks[numHeaders] 1064 local button = blocks[numHeaders]
1172 if not blocks[numHeaders] then 1065 if not blocks[numHeaders] then
1173 button = CreateFrame('Button', 'WorldPlanFilterButton'..numHeaders, WorldMapScrollFrame, 'WorldPlanFilterPin') 1066 button = CreateFrame('Button', 'WorldPlanFilterButton'..numHeaders, WorldMapScrollFrame, 'WorldPlanFilterPin')
1067 for k,v in pairs(info)do print(k,v) end
1174 button.iconBorder:SetTexture(info.fill or POI_BORDER_FILL) 1068 button.iconBorder:SetTexture(info.fill or POI_BORDER_FILL)
1175 button.iconBorder:SetMask(info.mask or POI_BORDER_MASK) 1069 button.iconBorder:SetMask(info.mask or POI_BORDER_MASK)
1176 button.iconBorder:SetDesaturated(info.desaturated) 1070 button.iconBorder:SetDesaturated(info.desaturated)
1177 button.supertrackBorder:SetTexture(info.fill or POI_BORDER_FILL) 1071 button.supertrackBorder:SetTexture(info.fill or POI_BORDER_FILL)
1178 button.supertrackBorder:SetMask(info.mask or POI_BORDER_MASK) 1072 button.supertrackBorder:SetMask(info.mask or POI_BORDER_MASK)
1218 1112
1219 self.icon:ClearAllPoints() 1113 self.icon:ClearAllPoints()
1220 self.icon:SetTexture(info.texture) 1114 self.icon:SetTexture(info.texture)
1221 self.icon:SetAllPoints(self) 1115 self.icon:SetAllPoints(self)
1222 self.supertrackBorder:Hide() 1116 self.supertrackBorder:Hide()
1223 self.label:SetText(numQuests) 1117 self.count:SetText(numQuests)
1224 self:Show() 1118 self:Show()
1225 end 1119 end
1226 1120
1227 1121
1228 self.itemTexture = self.texture 1122 self.itemTexture = self.texture
1323 SetTimedCallbackForAllPins(0, function(self) self.FadeIn:Play() self.FlashIn:Play() end) 1217 SetTimedCallbackForAllPins(0, function(self) self.FadeIn:Play() self.FlashIn:Play() end)
1324 SetTimedCallbackForAllPins(5, function(self) self.PendingFade:Play() end) 1218 SetTimedCallbackForAllPins(5, function(self) self.PendingFade:Play() end)
1325 SetTimedCallbackForAllPins(8, function(self) self.PendingFade:Stop() end) 1219 SetTimedCallbackForAllPins(8, function(self) self.PendingFade:Stop() end)
1326 end 1220 end
1327 --%end-debug% 1221 --%end-debug%
1328
1329 for mapID, mapName in pairs(WORLD_QUEST_MAPS) do
1330 QuestsByZone[mapID] = {}
1331 end
1332 for index, color in pairs(ITEM_QUALITY_COLORS) do
1333 POI_REWARD_TYPE[index] = {
1334 r = color.r, g = color.g, b = color.b,
1335 hex = color.hex,
1336 }
1337 end