Mercurial > wow > worldplan
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WorldQuests.lua Wed Nov 02 17:25:07 2016 -0400 @@ -0,0 +1,354 @@ +-- WorldPlan +-- WorldQuests.lua +-- Created: 11/2/2016 3:40 PM +-- %file-revision% + +WorldPlanQuestsMixin = { + QuestsByZone = {}, + QuestsByID = {}, + freePins = {}, +} +local WorldQuests = WorldPlanQuestsMixin + +local MC_GetNumZones, MC_GetZoneInfo = C_MapCanvas.GetNumZones, C_MapCanvas.GetZoneInfo +local TQ_GetQuestsForPlayerByMapID = C_TaskQuest.GetQuestsForPlayerByMapID -- This function is not yet documented +local TQ_GetQuestZoneID = C_TaskQuest.GetQuestZoneID +local GetMapInfo = GetMapInfo +local print = DEVIAN_WORKSPACE and function(...) _G.print('WP', ...) end or function() end +local qprint = DEVIAN_WORKSPACE and function(...) _G.print('POI', ...) end or function() end +local wqprint = DEVIAN_WORKSPACE and function(...) _G.print('WorldQuests', ...) end or function() end +local wprint = DEVIAN_WORKSPACE and function(...) _G.print('WP', ...) end or function() end + + +local PinBaseIndex = 1600 +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 +local WORLD_QUEST_MAPS = { [DALARAN_ID] = 'Dalaran70', [AZSUNA_ID] = 'Azsuna', [VALSHARAH_ID] = "Val'sharah", + [HIGHMOUNTAIN_ID] = 'Highmountain', [STORMHEIM_ID] = 'Stormheim', [SURAMAR_ID] = 'Suramar', [EOA_ID] = 'EyeOfAszhara', } + +local REWARD_CASH = WORLD_QUEST_REWARD_TYPE_FLAG_GOLD +local REWARD_ARTIFACT_POWER = WORLD_QUEST_REWARD_TYPE_FLAG_ARTIFACT_POWER +local REWARD_GEAR = WORLD_QUEST_REWARD_TYPE_FLAG_EQUIPMENT +local REWARD_CURRENCY = WORLD_QUEST_REWARD_TYPE_FLAG_ORDER_RESOURCES +local REWARD_REAGENT = WORLD_QUEST_REWARD_TYPE_FLAG_MATERIALS + + +local numPins = 0 +local ZoneInfo = {} +local NumPinFrames = 1 + + +--%debug% +local SetTimedCallbackForAllPins = function(seconds, callback) + C_Timer.After(seconds, function() + for id, pin in pairs(WorldPlanQuests.QuestsByID) do + callback(pin) + end + end) +end + +function WorldQuests:Setup() + + + for mapID, mapName in pairs(WORLD_QUEST_MAPS) do + self.QuestsByZone[mapID] = {} + end + + + -- refresh positions any time blizzard does so (i.e. mousewheel zoom) + hooksecurefunc("WorldMapScrollFrame_ReanchorQuestPOIs", function() + self:Refresh(true) + end) + + -- hide the original world quest POIs + hooksecurefunc("WorldMap_UpdateQuestBonusObjectives", function() + for i = 1, NUM_WORLDMAP_TASK_POIS do + local button = _G['WorldMapFrameTaskPOI'..i] + if button and button.worldQuest then + button:Hide() + end + end + end) +end +local WorldMapPOIFrame +local defaults = {} +function WorldQuests:OnLoad() + print('|cFF00FF88'..self:GetName()..':OnLoad') + + WorldPlan:AddHandler(self, defaults) + + local rgbWhite = {1, 1, 1} + WorldPlan:AddTypeInfo(self, REWARD_REAGENT, { r = 0, g = 1, b = 1 }) + WorldPlan:AddTypeInfo(self, REWARD_ARTIFACT_POWER, { r = 1, g = .25, b = .5, hasNumeric = true, numberRGB = rgbWhite }) + WorldPlan:AddTypeInfo(self, REWARD_GEAR, { r = .1, g = .2, b = 1 }) + WorldPlan:AddTypeInfo(self, REWARD_CURRENCY, { r = 1, g = 1, b = 0, hasNumeric = true, numberRGB = {1,1,0}, }) + WorldPlan:AddTypeInfo(self, REWARD_CASH, { r = 0, g = 0, b = 0, }) + + for areaID, fileName in pairs(WORLD_QUEST_MAPS) do + self.QuestsByZone[areaID] = {} + end + + self:RegisterEvent('WORLD_QUEST_COMPLETED_BY_SPELL') + self:RegisterEvent('SKILL_LINES_CHANGED') + + WorldMapPOIFrame = _G.WorldMapPOIFrame + +end + +function WorldQuests:OnEvent (event, ...) + local print = wqprint + print('|cFFFFFF00'..self:GetName()..':OnEvent()'..event..'|r', GetTime(), ...) + if event == 'QUEST_LOG_UPDATE' then + local questID, added = ... + if questID and added then + local questPOI = self:AcquirePin(questID) + self.isStale, self.isPending = questPOI:RefreshData() + else + self:RefreshData() + end + print('WorldMapFrame', WorldMapFrame:IsVisible(), 'hasUpdates:', self.isStale) + elseif event == 'WORLD_MAP_UPDATE' then + self.isStale = true + elseif event == 'WORLD_QUEST_COMPLETED_BY_SPELL' then + local questID = ... + if questID and self.QuestsByID[questID] then + self:ReleasePin(self.QuestsByID[questID]) + end + elseif event == 'SKILL_LINES_CHANGED' then + self.isStale = true + end +end + +local TQ_GetQuestLocation = C_TaskQuest.GetQuestLocation +function WorldQuests:AcquirePin (questID, mapID) + local pin = self.QuestsByID[questID] + local isNew = false + if not pin then + isNew = true + local numFree = #self.freePins + if numFree >= 1 then + pin = tremove(self.freePins, numFree) + --print('|cFF00FF00Re-using', pin:GetName()) + else + local name = 'WorldPlanQuestMarker' .. NumPinFrames + --print('|cFF00FF00Creating', name) + pin = CreateFrame('Frame', name, WorldMapPOIFrame, 'WorldPlanQuestPin') + + pin:SetFrameStrata('HIGH') + pin.GetTypeInfo = function(frame, typeID) + return self:GetTypeInfo(typeID) + end + NumPinFrames = NumPinFrames + 1 + --pin.iconBorder:SetVertexColor(0,0,0,1) + end + pin:SetID(questID) + pin.isNew = true + pin.currentWidth = nil + + -- used by TaskPOI_x scripts + pin.questID = questID + pin.worldQuest = true + + self.QuestsByID[questID] = pin + else + --print('|cFF00FF00Using', pin:GetName()) + end + mapID = mapID or TQ_GetQuestZoneID(questID) + self.QuestsByZone[mapID][questID] = pin + + return pin, isNew +end + +-- remove from index and add it to the recycling heap +function WorldQuests:ReleasePin (pin) + + local id = pin.questId + if id then + self.QuestsByID[id] = nil + for i, zone in pairs(self.QuestsByZone) do + print('-', i, zone[i]) + zone[id] = nil + end + end + pin:Hide() + pin:ClearAllPoints() + tinsert(self.freePins, pin) + print('|cFFFF4400Clearing out', pin:GetName(),id) +end + +-- create of update quest pins for a map and its underlying zones +function WorldQuests:RefreshData (mapID) + local print = wqprint + mapID = mapID or GetCurrentMapAreaID() + superTrackedID = GetSuperTrackedQuestID() + if not mapID then + -- info not available yet + return + end + + print('|cFF00FF88'..self:GetName()..':RefreshData()|r', 'map:', mapID, 'realMap:', GetCurrentMapAreaID()) + + if mapID == BROKEN_ISLES_ID then + self.isStale = false + print('|cFF00FFFFContinent:|r', mapID, GetMapNameByID(mapID), superTrackedID) + self.fullSearch = true + for i = 1, MC_GetNumZones(mapID) do + local submapID, name, depth = MC_GetZoneInfo(mapID, i) + self:RefreshData(submapID) + end + self.fullSearch = nil + elseif self.QuestsByZone[mapID] then + local taskInfo = TQ_GetQuestsForPlayerByMapID(mapID) + local numQuests = 0 + if taskInfo and #taskInfo >= 1 then + print('|cFF00FFFF Zone:|r', mapID, GetMapNameByID(mapID), #taskInfo) + wipe(self.QuestsByZone[mapID]) + ZoneInfo[mapID] = taskInfo + qprint('|cFFFF4400START of', GetMapNameByID(mapID)) + for taskID, info in pairs(taskInfo) do + local questID = info.questId + info.mapID = mapID + local questPOI = self:AcquirePin(questID, mapID) + local hasUpdate, isPending = questPOI:RefreshData(info) + self.isStale = (self.isStale or hasUpdate) + self.isPending = (self.isPending or isPending) + numQuests = numQuests + 1 + end + qprint('|cFFFF4400END of', GetMapNameByID(mapID)) + end + end + + if not self.fullSearch then + print(' hasUpdate:', self.isStale, 'isPending:', self.isPending, 'timer:', (self.OnNext and 'waiting' or '')) + --WorldPlan.isStale = (self.isStale or WorldPlan.isStale) + end + +end + +function WorldQuests:Refresh() + local print = wqprint + print('|cFF00FF88'..self:GetName()..':Refresh()|r') + self:Reset() + self:UpdateAnchors() + self:Cleanup () +end + +-- prepares elements for a map update +function WorldQuests:Reset () + local print = wqprint + print('|cFF00FF88'..self:GetName()..':Reset()|r') + for questID, pin in pairs(self.QuestsByID) do + pin.used = nil + end +end + +-- update visibility states of all pins +function WorldQuests:UpdateAnchors (submapID) + + local print = wqprint + local db = WorldPlan.db + local mapFileName, textureHeight, textureWidth, isMicroDungeon, microDungeonMapName = GetMapInfo() + if isMicroDungeon then + return + end + + local currentMap = GetCurrentMapAreaID() + local submapID = submapID or currentMap + + if submapID == BROKEN_ISLES_ID and (not db.DisplayContinentPins) then + print('not updating map for reasons') + return + end + print('|cFF88FF00'..self:GetName()..':UpdateAnchors|r', submapID, GetMapNameByID(submapID), 'pin count:', numPins) + local numZones = MC_GetNumZones(submapID) + if numZones then + for i = 1, numZones do + local subMapID = MC_GetZoneInfo(submapID, i) + self:UpdateAnchors(subMapID) + end + end + local pins = self.QuestsByZone[submapID] + + if pins then + local hostFrame = WorldMapPOIFrame + local mapWidth, mapHeight = hostFrame:GetSize() + for questID, pin in pairs(pins) do + pin:IsShowable() + if pin.used then + pin.hasUpdate = true + pin:SetFrameLevel(PinBaseIndex+ (pin.whiteListed and 200 or 0) +numPins) + print('level', PinBaseIndex+ (pin.whiteListed and 200 or 0) +numPins) + pin:SetAnchor(WorldMapPOIFrame, currentMap, mapWidth, mapHeight) + numPins = numPins + 1 + end + end + end +end + +-- shows, animates, or hides pins based on their current visibility flags +local debug_show = {} +local debug_animate = {} +local debug_hide = {} +function WorldQuests:Cleanup () + local print = wqprint + local showQuestPOI = db.EnablePins + print('|cFFFFFF00'..tostring(self)..':Cleanup()|r') + local mapID = GetCurrentMapAreaID() + isContinentMap = (mapID == BROKEN_ISLES_ID) + + wipe(debug_show) + wipe(debug_animate) + wipe(debug_hide) + -- continent or zone sizing + local fadeGrouped = (db.FadeWhileGrouped and IsInGroup()) + + numPins = 0 + for questID, pin in pairs(self.QuestsByID) do + -- can we show it? + if showQuestPOI and (pin.used) then + + pin.isStale = true + if fadeGrouped then + pin:SetAlpha(0.25) + else + pin:SetAlpha(1) + end + -- is it a new quest? + if pin.isNew then + if not pin.isAnimating then + pin.isAnimating = true + WorldPlan:OnNext(function() + pin:ShowNew() + end) + tinsert(debug_animate,questID) + else + + print('animating? ', questID, 'filtered:', pin.filtered) + end + -- trap new but animating pins here + else + -- hard show existing pin + --print('refresh #', questID, 'filtered:', pin.filtered, 'hasUpdate', pin.hasUpdate) + pin:Show() + tinsert(debug_show,questID) + end + else + if pin:IsShown() then + tinsert(debug_hide,questID) + end + pin.isAnimating = nil + pin.FadeIn:Stop() + pin:Hide() + end + end + print(' adding:', table.concat(debug_animate, ',' )) + print(' refresh:', table.concat(debug_show, ',' )) + print(' hiding:', table.concat(debug_hide, ',' )) + hasNewQuestPins = nil + notifyPlayed = nil + self.isStale = nil +end + +function WorldQuests:FilterCheckByID(questID) + local pin = WorldQuests:GetPinByQuestID(questID) + return pin:IsShowable() +end