Mercurial > wow > worldplan
comparison WorldQuests.lua @ 33:be4db60219ca
WorldPlan:
- Toggling a reward filter cancels out other types by default. Use right mouse to clear.
- Fixed filter bar info falling out of sync after player-triggered world map updates.
ClassPlan:
- Available missions are now recorded; the mission list can be toggled between in-progress and available by clicking the heading.
author | Nenue |
---|---|
date | Wed, 02 Nov 2016 17:25:07 -0400 |
parents | |
children | 0100d923d8c3 |
comparison
equal
deleted
inserted
replaced
32:e8679ecb48d8 | 33:be4db60219ca |
---|---|
1 -- WorldPlan | |
2 -- WorldQuests.lua | |
3 -- Created: 11/2/2016 3:40 PM | |
4 -- %file-revision% | |
5 | |
6 WorldPlanQuestsMixin = { | |
7 QuestsByZone = {}, | |
8 QuestsByID = {}, | |
9 freePins = {}, | |
10 } | |
11 local WorldQuests = WorldPlanQuestsMixin | |
12 | |
13 local MC_GetNumZones, MC_GetZoneInfo = C_MapCanvas.GetNumZones, C_MapCanvas.GetZoneInfo | |
14 local TQ_GetQuestsForPlayerByMapID = C_TaskQuest.GetQuestsForPlayerByMapID -- This function is not yet documented | |
15 local TQ_GetQuestZoneID = C_TaskQuest.GetQuestZoneID | |
16 local GetMapInfo = GetMapInfo | |
17 local print = DEVIAN_WORKSPACE and function(...) _G.print('WP', ...) end or function() end | |
18 local qprint = DEVIAN_WORKSPACE and function(...) _G.print('POI', ...) end or function() end | |
19 local wqprint = DEVIAN_WORKSPACE and function(...) _G.print('WorldQuests', ...) end or function() end | |
20 local wprint = DEVIAN_WORKSPACE and function(...) _G.print('WP', ...) end or function() end | |
21 | |
22 | |
23 local PinBaseIndex = 1600 | |
24 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 | |
25 local WORLD_QUEST_MAPS = { [DALARAN_ID] = 'Dalaran70', [AZSUNA_ID] = 'Azsuna', [VALSHARAH_ID] = "Val'sharah", | |
26 [HIGHMOUNTAIN_ID] = 'Highmountain', [STORMHEIM_ID] = 'Stormheim', [SURAMAR_ID] = 'Suramar', [EOA_ID] = 'EyeOfAszhara', } | |
27 | |
28 local REWARD_CASH = WORLD_QUEST_REWARD_TYPE_FLAG_GOLD | |
29 local REWARD_ARTIFACT_POWER = WORLD_QUEST_REWARD_TYPE_FLAG_ARTIFACT_POWER | |
30 local REWARD_GEAR = WORLD_QUEST_REWARD_TYPE_FLAG_EQUIPMENT | |
31 local REWARD_CURRENCY = WORLD_QUEST_REWARD_TYPE_FLAG_ORDER_RESOURCES | |
32 local REWARD_REAGENT = WORLD_QUEST_REWARD_TYPE_FLAG_MATERIALS | |
33 | |
34 | |
35 local numPins = 0 | |
36 local ZoneInfo = {} | |
37 local NumPinFrames = 1 | |
38 | |
39 | |
40 --%debug% | |
41 local SetTimedCallbackForAllPins = function(seconds, callback) | |
42 C_Timer.After(seconds, function() | |
43 for id, pin in pairs(WorldPlanQuests.QuestsByID) do | |
44 callback(pin) | |
45 end | |
46 end) | |
47 end | |
48 | |
49 function WorldQuests:Setup() | |
50 | |
51 | |
52 for mapID, mapName in pairs(WORLD_QUEST_MAPS) do | |
53 self.QuestsByZone[mapID] = {} | |
54 end | |
55 | |
56 | |
57 -- refresh positions any time blizzard does so (i.e. mousewheel zoom) | |
58 hooksecurefunc("WorldMapScrollFrame_ReanchorQuestPOIs", function() | |
59 self:Refresh(true) | |
60 end) | |
61 | |
62 -- hide the original world quest POIs | |
63 hooksecurefunc("WorldMap_UpdateQuestBonusObjectives", function() | |
64 for i = 1, NUM_WORLDMAP_TASK_POIS do | |
65 local button = _G['WorldMapFrameTaskPOI'..i] | |
66 if button and button.worldQuest then | |
67 button:Hide() | |
68 end | |
69 end | |
70 end) | |
71 end | |
72 local WorldMapPOIFrame | |
73 local defaults = {} | |
74 function WorldQuests:OnLoad() | |
75 print('|cFF00FF88'..self:GetName()..':OnLoad') | |
76 | |
77 WorldPlan:AddHandler(self, defaults) | |
78 | |
79 local rgbWhite = {1, 1, 1} | |
80 WorldPlan:AddTypeInfo(self, REWARD_REAGENT, { r = 0, g = 1, b = 1 }) | |
81 WorldPlan:AddTypeInfo(self, REWARD_ARTIFACT_POWER, { r = 1, g = .25, b = .5, hasNumeric = true, numberRGB = rgbWhite }) | |
82 WorldPlan:AddTypeInfo(self, REWARD_GEAR, { r = .1, g = .2, b = 1 }) | |
83 WorldPlan:AddTypeInfo(self, REWARD_CURRENCY, { r = 1, g = 1, b = 0, hasNumeric = true, numberRGB = {1,1,0}, }) | |
84 WorldPlan:AddTypeInfo(self, REWARD_CASH, { r = 0, g = 0, b = 0, }) | |
85 | |
86 for areaID, fileName in pairs(WORLD_QUEST_MAPS) do | |
87 self.QuestsByZone[areaID] = {} | |
88 end | |
89 | |
90 self:RegisterEvent('WORLD_QUEST_COMPLETED_BY_SPELL') | |
91 self:RegisterEvent('SKILL_LINES_CHANGED') | |
92 | |
93 WorldMapPOIFrame = _G.WorldMapPOIFrame | |
94 | |
95 end | |
96 | |
97 function WorldQuests:OnEvent (event, ...) | |
98 local print = wqprint | |
99 print('|cFFFFFF00'..self:GetName()..':OnEvent()'..event..'|r', GetTime(), ...) | |
100 if event == 'QUEST_LOG_UPDATE' then | |
101 local questID, added = ... | |
102 if questID and added then | |
103 local questPOI = self:AcquirePin(questID) | |
104 self.isStale, self.isPending = questPOI:RefreshData() | |
105 else | |
106 self:RefreshData() | |
107 end | |
108 print('WorldMapFrame', WorldMapFrame:IsVisible(), 'hasUpdates:', self.isStale) | |
109 elseif event == 'WORLD_MAP_UPDATE' then | |
110 self.isStale = true | |
111 elseif event == 'WORLD_QUEST_COMPLETED_BY_SPELL' then | |
112 local questID = ... | |
113 if questID and self.QuestsByID[questID] then | |
114 self:ReleasePin(self.QuestsByID[questID]) | |
115 end | |
116 elseif event == 'SKILL_LINES_CHANGED' then | |
117 self.isStale = true | |
118 end | |
119 end | |
120 | |
121 local TQ_GetQuestLocation = C_TaskQuest.GetQuestLocation | |
122 function WorldQuests:AcquirePin (questID, mapID) | |
123 local pin = self.QuestsByID[questID] | |
124 local isNew = false | |
125 if not pin then | |
126 isNew = true | |
127 local numFree = #self.freePins | |
128 if numFree >= 1 then | |
129 pin = tremove(self.freePins, numFree) | |
130 --print('|cFF00FF00Re-using', pin:GetName()) | |
131 else | |
132 local name = 'WorldPlanQuestMarker' .. NumPinFrames | |
133 --print('|cFF00FF00Creating', name) | |
134 pin = CreateFrame('Frame', name, WorldMapPOIFrame, 'WorldPlanQuestPin') | |
135 | |
136 pin:SetFrameStrata('HIGH') | |
137 pin.GetTypeInfo = function(frame, typeID) | |
138 return self:GetTypeInfo(typeID) | |
139 end | |
140 NumPinFrames = NumPinFrames + 1 | |
141 --pin.iconBorder:SetVertexColor(0,0,0,1) | |
142 end | |
143 pin:SetID(questID) | |
144 pin.isNew = true | |
145 pin.currentWidth = nil | |
146 | |
147 -- used by TaskPOI_x scripts | |
148 pin.questID = questID | |
149 pin.worldQuest = true | |
150 | |
151 self.QuestsByID[questID] = pin | |
152 else | |
153 --print('|cFF00FF00Using', pin:GetName()) | |
154 end | |
155 mapID = mapID or TQ_GetQuestZoneID(questID) | |
156 self.QuestsByZone[mapID][questID] = pin | |
157 | |
158 return pin, isNew | |
159 end | |
160 | |
161 -- remove from index and add it to the recycling heap | |
162 function WorldQuests:ReleasePin (pin) | |
163 | |
164 local id = pin.questId | |
165 if id then | |
166 self.QuestsByID[id] = nil | |
167 for i, zone in pairs(self.QuestsByZone) do | |
168 print('-', i, zone[i]) | |
169 zone[id] = nil | |
170 end | |
171 end | |
172 pin:Hide() | |
173 pin:ClearAllPoints() | |
174 tinsert(self.freePins, pin) | |
175 print('|cFFFF4400Clearing out', pin:GetName(),id) | |
176 end | |
177 | |
178 -- create of update quest pins for a map and its underlying zones | |
179 function WorldQuests:RefreshData (mapID) | |
180 local print = wqprint | |
181 mapID = mapID or GetCurrentMapAreaID() | |
182 superTrackedID = GetSuperTrackedQuestID() | |
183 if not mapID then | |
184 -- info not available yet | |
185 return | |
186 end | |
187 | |
188 print('|cFF00FF88'..self:GetName()..':RefreshData()|r', 'map:', mapID, 'realMap:', GetCurrentMapAreaID()) | |
189 | |
190 if mapID == BROKEN_ISLES_ID then | |
191 self.isStale = false | |
192 print('|cFF00FFFFContinent:|r', mapID, GetMapNameByID(mapID), superTrackedID) | |
193 self.fullSearch = true | |
194 for i = 1, MC_GetNumZones(mapID) do | |
195 local submapID, name, depth = MC_GetZoneInfo(mapID, i) | |
196 self:RefreshData(submapID) | |
197 end | |
198 self.fullSearch = nil | |
199 elseif self.QuestsByZone[mapID] then | |
200 local taskInfo = TQ_GetQuestsForPlayerByMapID(mapID) | |
201 local numQuests = 0 | |
202 if taskInfo and #taskInfo >= 1 then | |
203 print('|cFF00FFFF Zone:|r', mapID, GetMapNameByID(mapID), #taskInfo) | |
204 wipe(self.QuestsByZone[mapID]) | |
205 ZoneInfo[mapID] = taskInfo | |
206 qprint('|cFFFF4400START of', GetMapNameByID(mapID)) | |
207 for taskID, info in pairs(taskInfo) do | |
208 local questID = info.questId | |
209 info.mapID = mapID | |
210 local questPOI = self:AcquirePin(questID, mapID) | |
211 local hasUpdate, isPending = questPOI:RefreshData(info) | |
212 self.isStale = (self.isStale or hasUpdate) | |
213 self.isPending = (self.isPending or isPending) | |
214 numQuests = numQuests + 1 | |
215 end | |
216 qprint('|cFFFF4400END of', GetMapNameByID(mapID)) | |
217 end | |
218 end | |
219 | |
220 if not self.fullSearch then | |
221 print(' hasUpdate:', self.isStale, 'isPending:', self.isPending, 'timer:', (self.OnNext and 'waiting' or '')) | |
222 --WorldPlan.isStale = (self.isStale or WorldPlan.isStale) | |
223 end | |
224 | |
225 end | |
226 | |
227 function WorldQuests:Refresh() | |
228 local print = wqprint | |
229 print('|cFF00FF88'..self:GetName()..':Refresh()|r') | |
230 self:Reset() | |
231 self:UpdateAnchors() | |
232 self:Cleanup () | |
233 end | |
234 | |
235 -- prepares elements for a map update | |
236 function WorldQuests:Reset () | |
237 local print = wqprint | |
238 print('|cFF00FF88'..self:GetName()..':Reset()|r') | |
239 for questID, pin in pairs(self.QuestsByID) do | |
240 pin.used = nil | |
241 end | |
242 end | |
243 | |
244 -- update visibility states of all pins | |
245 function WorldQuests:UpdateAnchors (submapID) | |
246 | |
247 local print = wqprint | |
248 local db = WorldPlan.db | |
249 local mapFileName, textureHeight, textureWidth, isMicroDungeon, microDungeonMapName = GetMapInfo() | |
250 if isMicroDungeon then | |
251 return | |
252 end | |
253 | |
254 local currentMap = GetCurrentMapAreaID() | |
255 local submapID = submapID or currentMap | |
256 | |
257 if submapID == BROKEN_ISLES_ID and (not db.DisplayContinentPins) then | |
258 print('not updating map for reasons') | |
259 return | |
260 end | |
261 print('|cFF88FF00'..self:GetName()..':UpdateAnchors|r', submapID, GetMapNameByID(submapID), 'pin count:', numPins) | |
262 local numZones = MC_GetNumZones(submapID) | |
263 if numZones then | |
264 for i = 1, numZones do | |
265 local subMapID = MC_GetZoneInfo(submapID, i) | |
266 self:UpdateAnchors(subMapID) | |
267 end | |
268 end | |
269 local pins = self.QuestsByZone[submapID] | |
270 | |
271 if pins then | |
272 local hostFrame = WorldMapPOIFrame | |
273 local mapWidth, mapHeight = hostFrame:GetSize() | |
274 for questID, pin in pairs(pins) do | |
275 pin:IsShowable() | |
276 if pin.used then | |
277 pin.hasUpdate = true | |
278 pin:SetFrameLevel(PinBaseIndex+ (pin.whiteListed and 200 or 0) +numPins) | |
279 print('level', PinBaseIndex+ (pin.whiteListed and 200 or 0) +numPins) | |
280 pin:SetAnchor(WorldMapPOIFrame, currentMap, mapWidth, mapHeight) | |
281 numPins = numPins + 1 | |
282 end | |
283 end | |
284 end | |
285 end | |
286 | |
287 -- shows, animates, or hides pins based on their current visibility flags | |
288 local debug_show = {} | |
289 local debug_animate = {} | |
290 local debug_hide = {} | |
291 function WorldQuests:Cleanup () | |
292 local print = wqprint | |
293 local showQuestPOI = db.EnablePins | |
294 print('|cFFFFFF00'..tostring(self)..':Cleanup()|r') | |
295 local mapID = GetCurrentMapAreaID() | |
296 isContinentMap = (mapID == BROKEN_ISLES_ID) | |
297 | |
298 wipe(debug_show) | |
299 wipe(debug_animate) | |
300 wipe(debug_hide) | |
301 -- continent or zone sizing | |
302 local fadeGrouped = (db.FadeWhileGrouped and IsInGroup()) | |
303 | |
304 numPins = 0 | |
305 for questID, pin in pairs(self.QuestsByID) do | |
306 -- can we show it? | |
307 if showQuestPOI and (pin.used) then | |
308 | |
309 pin.isStale = true | |
310 if fadeGrouped then | |
311 pin:SetAlpha(0.25) | |
312 else | |
313 pin:SetAlpha(1) | |
314 end | |
315 -- is it a new quest? | |
316 if pin.isNew then | |
317 if not pin.isAnimating then | |
318 pin.isAnimating = true | |
319 WorldPlan:OnNext(function() | |
320 pin:ShowNew() | |
321 end) | |
322 tinsert(debug_animate,questID) | |
323 else | |
324 | |
325 print('animating? ', questID, 'filtered:', pin.filtered) | |
326 end | |
327 -- trap new but animating pins here | |
328 else | |
329 -- hard show existing pin | |
330 --print('refresh #', questID, 'filtered:', pin.filtered, 'hasUpdate', pin.hasUpdate) | |
331 pin:Show() | |
332 tinsert(debug_show,questID) | |
333 end | |
334 else | |
335 if pin:IsShown() then | |
336 tinsert(debug_hide,questID) | |
337 end | |
338 pin.isAnimating = nil | |
339 pin.FadeIn:Stop() | |
340 pin:Hide() | |
341 end | |
342 end | |
343 print(' adding:', table.concat(debug_animate, ',' )) | |
344 print(' refresh:', table.concat(debug_show, ',' )) | |
345 print(' hiding:', table.concat(debug_hide, ',' )) | |
346 hasNewQuestPins = nil | |
347 notifyPlayed = nil | |
348 self.isStale = nil | |
349 end | |
350 | |
351 function WorldQuests:FilterCheckByID(questID) | |
352 local pin = WorldQuests:GetPinByQuestID(questID) | |
353 return pin:IsShowable() | |
354 end |