Mercurial > wow > worldplan
view WorldQuests.lua @ 43:77c2ffb5c7f5 v1.0-rc11
- Removed possible refresh loop occurring in non-BrokenIsle zones
author | Nenue |
---|---|
date | Sun, 25 Dec 2016 15:47:17 -0500 |
parents | 79e5e96e5f18 |
children | db570c6a0ffb |
line wrap: on
line source
-- WorldPlan -- WorldQuests.lua -- Created: 11/2/2016 3:40 PM -- %file-revision% local _, db = ... 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('WorldQuests', ...) end or function() end local rprint = DEVIAN_WORKSPACE and function(...) _G.print('WQRefresh', ...) end or function() end local qprint = DEVIAN_WORKSPACE and function(...) _G.print('POI', ...) end or function() end local wprint = DEVIAN_WORKSPACE and function(...) _G.print('WP', ...) end or function() end local mprint = DEVIAN_WORKSPACE and function(...) _G.print('Canvas', ...) end or function() end local PinBaseIndex = 1200 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 NumPinFrames = 1 WorldQuests.TasksByID = {} --%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:OnUpdate(sinceLast) if self.filtersDirty or self.isStale then self:Refresh() end end function WorldQuests:Setup() print('|cFFFF4400'..self:GetName()..':Setup()') for mapID, mapName in pairs(WORLD_QUEST_MAPS) do db.QuestsByZone[mapID] = {} end -- refresh positions any time blizzard does so (i.e. mousewheel zoom) hooksecurefunc("WorldMapScrollFrame_ReanchorQuestPOIs", function() print('|cFFFF4400WorldMapScrollFrame_ReanchorQuestPOIs') self:Refresh(true) end) -- hide the original world quest POIs hooksecurefunc("WorldMap_UpdateQuestBonusObjectives", function() print('|cFFFF4400WorldMap_UpdateQuestBonusObjectives') 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 defaults = {} local REWARD_UNKNOWN = 768 function WorldQuests:OnLoad() print('|cFFFF4400'..self:GetName()..':OnLoad()') self:SetParent(WorldMapFrame) WorldPlan:AddHandler(self, defaults) local rgbWhite = {1, 1, 1 } WorldPlan:AddTypeInfo(self, REWARD_UNKNOWN, { r = 1, g = 1, b = 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 = 1, g = 1, b = .32, pinMask = false, rewardMask = false }) for areaID, fileName in pairs(WORLD_QUEST_MAPS) do db.QuestsByZone[areaID] = {} end -- WORLD_MAP_UPDATE and PLAYER_ENTERING_WORLD are passed down from a higher level self:RegisterEvent('WORLD_QUEST_COMPLETED_BY_SPELL') self:RegisterEvent('SKILL_LINES_CHANGED') WorldMapPOIFrame = _G.WorldMapPOIFrame end function WorldQuests:OnMapInfo() if self:IsVisible() then self:Refresh() else self.isStale = true end end function WorldQuests:OnEvent (event, ...) 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) questPOI:GetQuestInfo() questPOI.isStale = true self.isStale = true else self:Refresh(true) end print('WorldMapFrame', WorldMapFrame:IsVisible(), 'hasUpdates:', self.isStale) elseif event == 'WORLD_QUEST_COMPLETED_BY_SPELL' then local questID = ... if questID and db.QuestsByID[questID] then self:ReleasePin(db.QuestsByID[questID]) rprint('|cFFFF4400release|r', questID) end elseif event == 'SKILL_LINES_CHANGED' then self:SetFilteredPins() end end local totalPins = 0 local TQ_GetQuestLocation = C_TaskQuest.GetQuestLocation function WorldQuests:AcquirePin (info) local questID = info.questId if not questID then return nil end if not QuestUtils_IsQuestWorldQuest(questID) then return nil end local pin = db.QuestsByID[questID] if not pin then local numFree = #db.FreePins if numFree >= 1 then pin = tremove(db.FreePins, numFree) --print('|cFF00FF00Re-using', pin:GetName()) else totalPins = totalPins + 1 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 pin:SetID(totalPins) NumPinFrames = NumPinFrames + 1 --pin.iconBorder:SetVertexColor(0,0,0,1) end pin.questID = questID pin.worldQuest = true pin.throttle = 1 pin.isNew = true pin.currentWidth = nil db.QuestsByID[questID] = pin tinsert(db.UsedPins, pin) end if pin and info then pin.inProgress = info.inProgress pin.floor = info.floor pin.numObjectives = info.numObjectives or 0 if info.x and info.y then pin.x = info.x or pin.x pin.y = info.y or pin.y rprint('|cFFFF4400coords|r', info.x, info.y) end end pin:GetData() C_TaskQuest.RequestPreloadRewardData(info.questId) return pin end -- remove from index and add it to the recycling heap function WorldQuests:ReleasePin (pin) local id = pin.questID if id then db.QuestsByID[id] = nil for i, zone in pairs(db.QuestsByZone) do print('-', i, zone[i]) zone[id] = nil end db.TasksByID[id] = nil end pin:SetShown(false) pin:ClearAllPoints() tinsert(db.FreePins, pin) print('|cFF00FF00-'.. (pin.mapID and GetMapNameByID(pin.mapID) or '???') ..'|r', id, pin.title) end function WorldQuests:GetBonusObjectives() local tasksTable = GetTasksTable() if tasksTable ~= nil then print('|cFF00FF88'..self:GetName()..':BonusObjectives()|r ') self.numTasks = #tasksTable for i, taskID in ipairs(tasksTable) do if not QuestUtils_IsQuestWorldQuest(taskID) then local info = db.TasksByID[taskID] if not info then local isInArea, isOnMap, numObjectives, taskName, displayAsObjective = GetTaskInfo(taskID) if isOnMap then print(' * '..i, taskID, GetTaskInfo(taskID)) info = { questID = taskID, numObjectives = numObjectives, title = taskName, isInArea = isInArea, isOnMap = isOnMap, displayAsObjective = displayAsObjective, worldQuest = false, isPending = false, isNew = true, } db.TasksByID[taskID] = info local pin = self:AcquirePin(taskID) for k,v in pairs(info) do pin[k] = v end pin:GetBonusObjectiveInfo(info) end end end end end end -- use tooltip object to extract item details function WorldQuests:GetRewardHeader(questID) local name, icon, quantity, quality, _, itemID = GetQuestLogRewardInfo(1, questID) local scanner = _G.WorldPlanTooltip local print = qprint if not itemID then return end --print('GetRewardHeader', questID) scanner:SetOwner(WorldPlan, "ANCHOR_NONE") scanner:SetItemByID(itemID) scanner:Show() local ttl1 = _G['WorldPlanTooltipTextLeft1'] local ttl2 = _G['WorldPlanTooltipTextLeft2'] local ttl3 = _G['WorldPlanTooltipTextLeft3'] local ttl4 = _G['WorldPlanTooltipTextLeft4'] --print(ttl2, ttl3, ttl4) if ttl2 then local text = ttl2:GetText() -- Artifact Power --print(text) if text then if text:match("|cFFE6CC80") then --print('AP token!', text) local power if ttl4 then local text = ttl4:GetText() --print('tip line 4', text) if text then power = text:gsub("%p", ""):match("%d+") power = tonumber(power) end end return REWARD_ARTIFACT_POWER, "Interface\\ICONS\\inv_7xp_inscription_talenttome01", power, name, itemID, quality elseif text:match("Item Level") then --print('equipment!', text) quantity = text:match("Item Level ([%d\+]+)") return REWARD_GEAR, icon, quantity, name, itemID, quality elseif text:match("Crafting Reagent") then --print('|cFFFF4400it is a reagent', text) return REWARD_REAGENT, icon, quantity, name, itemID, quality end end end if ttl3 then local text = ttl3:GetText() if text and text:match("Crafting Reagent") then --print('|cFFFF4400it is a reagent', text) return REWARD_REAGENT, icon, quantity, name, itemID, quality end end return 128, icon, quantity, name, itemID, quality end local GetCurrentMapAreaID, GetMapNameByID= GetCurrentMapAreaID, GetMapNameByID local wipe, pairs = wipe, pairs -- create of update quest pins for a map and its underlying zones function WorldQuests:UpdateWorldQuests (mapID) mapID = mapID or db.currentMapID if not mapID then -- info not available yet return end print('|cFF00FF88'..self:GetName()..':UpdateWorldQuests()|r', 'map:', mapID, 'realMap:', db.currentMapID) self.isStale = nil print('|cFF00FFFFContinent:|r', BROKEN_ISLES_ID, GetMapNameByID(BROKEN_ISLES_ID)) self.isRecursed = true for i = 1, MC_GetNumZones(BROKEN_ISLES_ID) do local submapID, name, depth = MC_GetZoneInfo(BROKEN_ISLES_ID, i) local taskInfo = TQ_GetQuestsForPlayerByMapID(submapID, BROKEN_ISLES_ID) if taskInfo then local zoneName = GetMapNameByID(submapID) print('|cFF00FFFF Zone:|r', submapID, zoneName, #taskInfo) db.QuestsByZone[submapID] = db.QuestsByZone[submapID] or {} for i, info in ipairs(taskInfo) do if HaveQuestData(info.questId) then rprint('|cFF44FF44update|r', info.questId, zoneName) local questID = info.questId local pin = self:AcquirePin(questID) local pin = db.QuestsByID[questID] if pin then pin.isStale = true if pin.isPending then self.isPending = true end end else rprint('|cFFFF4400no data|r', info.questId, zoneName) end end end end self:GetBonusObjectives() print(' hasUpdate:', self.isStale, 'isPending:', self.isPending, 'timer:', (self.OnNext and 'waiting' or '')) --WorldPlan.isStale = (self.isStale or WorldPlan.isStale) if self.isStale and self:IsVisible() then self:Refresh() end end function WorldQuests:Report() for i, pin in ipairs(db.UsedPins) do db:print(i, pin.questID, pin.title) end for id, pin in pairs(db.QuestsByID) do db:print(id, pin.worldQuestType, pin.rewardType, pin.title) end end function WorldQuests:Refresh(fromUser) self.currentMapID = GetCurrentMapAreaID() print('|cFF00FF88'..self:GetName()..':Refresh()|r', fromUser or '|cFFFFFF00internal') if not self:IsVisible() then print(' not visible, flag for later') self.isStale = true return end wprint(' |cFF00FF88'..self:GetName()..':Refresh()|r', fromUser or '|cFFFFFF00internal') for index, pin in pairs(db.QuestsByID) do pin.used = nil pin:SetShown(false) end self:SetFilteredPins(db.QuestsByID) self:UpdateAnchors(nil, fromUser) self:Cleanup (fromUser) self.isStale = nil end -- update visibility states of all pins function WorldQuests:SetFilteredPins(pins) print(' |cFFFFFF00'..self:GetName()..':SetFilteredPins()|r', pins) pins = pins or db.QuestsByID for questID, pin in pairs(pins) do pin.filtered = pin:IsFiltered() pin.isStale = true rprint('|cFF00FF00filter', pin.questID, pin.filtered, 'used:', pin.used) end end local abs = math.abs function WorldQuests:UpdateQuestButton(info, mapID) local questID, x, y = info.questId, info.x, info.y local pin = self:AcquirePin(info) if not pin then return end print('~ ', pin.mapID, pin.questID, pin.title) rprint('|cFF00FF00update|r', x, y, pin.title) pin:IsShowable() if x and y then pin.x = x pin.y = y pin:SetFrameLevel(PinBaseIndex+numPins) pin:SetPoint('CENTER', self.hostFrame, 'TOPLEFT', self.hostWidth * pin.x, -self.hostHeight * pin.y) pin.throttle = 1 pin:SetShown(pin.used) tinsert(self.UsedPositions, pin) end pin.owningFrame = self.hostFrame pin:SetParent(self.hostFrame) if mapID then if not db.QuestsByZone[mapID] then db.QuestsByZone[mapID] = {} end db.QuestsByZone[mapID][questID] = pin end end function WorldQuests:UpdateMap(taskInfo, mapID) print('Map', GetMapNameByID(mapID), GetMapNameByID(self.currentMapID)) for index, info in pairs(taskInfo) do self:UpdateQuestButton(info, mapID) end end function WorldQuests:UpdateAnchors (fromUser) wipe(self.UsedPositions) print(' |cFF00FF00'..self:GetName()..':UpdateAnchors()', fromUser) self.hostFrame = WorldMapPOIFrame self.hostWidth, self.hostHeight = self.hostFrame:GetSize() self.nudgeThrescholdX = 16/self.hostWidth self.nudgeThrescholdY = 16/self.hostHeight local print = rprint print('|cFF00FF00'..self:GetName()..':UpdateAnchors()', fromUser) local mapFileName, textureHeight, textureWidth, isMicroDungeon, microDungeonMapName = GetMapInfo() if isMicroDungeon then return end numPins = 0 local taskInfo = TQ_GetQuestsForPlayerByMapID(self.currentMapID) if taskInfo then self:UpdateMap(taskInfo, self.currentMapID) end local numZones = MC_GetNumZones(self.currentMapID) if numZones then for i = 1, numZones do local mapAreaID = MC_GetZoneInfo(self.currentMapID, i) local taskInfo = TQ_GetQuestsForPlayerByMapID(mapAreaID, self.currentMapID) if taskInfo then self:UpdateMap(taskInfo, mapAreaID) end end end if self.filtersDirty then self:SetFilteredPins(db.QuestsByID) end end -- shows, animates, or hides pins based on their current visibility flags function WorldQuests:Cleanup (fromUser) print('|cFFFFFF00'..self:GetName()..':Cleanup()|r') local print = rprint print('|cFFFFFF00'..self:GetName()..':Cleanup()|r') --local showQuestPOI = db.Config.EnablePins for questID, pin in pairs(db.QuestsByID) do local oV = pin:IsShown() if pin.used then pin:SetShown(true) pin.throttle = 1 if oV == false then print('|cFF00FF00cleanup +|r', questID, pin.title) end else if oV == true then print('|cFFFF4400 -|r', questID, pin.title) end end if pin.worldQuest and (not C_TaskQuest.IsActive(pin.questID)) then self:ReleasePin(pin) end pin.isStale = true end end