Mercurial > wow > worldplan
diff 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 |
line wrap: on
line diff
--- a/WorldPlan.lua Thu Oct 27 06:19:05 2016 -0400 +++ b/WorldPlan.lua Thu Oct 27 13:50:56 2016 -0400 @@ -10,7 +10,20 @@ Dalaran quests aren't visible until that map has been specifically viewed by the player. --]] -WorldPlanCore = {} +local ICON_UNKNOWN = "Interface\\ICONS\\inv_misc_questionmark" +local ICON_MONEY = "Interface\\Buttons\\UI-GroupLoot-Coin-Up" + +local POI_BORDER_MASK = "Interface\\Minimap\\UI-Minimap-Background" +local POI_BORDER_FILL = "Interface\\BUTTONS\\YELLOWORANGE64" +local POI_BORDER_BLUE = "Interface\\BUTTONS\\GRADBLUE" +local POI_BORDER_RED = "Interface\\BUTTONS\\RedGrad64" +local POI_BORDER_YELLOW = "Interface\\BUTTONS\\YELLOWORANGE64" +local POI_BORDER_GREEN = "Interface\\BUTTONS\\GREENGRAD64" + +WorldPlanCore = { + defaults = {}, + +} WorldPlanPOIMixin = {} WorldPlanFilterPinMixin = {} local WorldPlanFlightMapMixin = setmetatable({}, {__tostring = function() return 'FlightMapHandler' end}) @@ -30,11 +43,8 @@ local fbprint = DEVIAN_WORKSPACE and function(...) _G.print('FilterBar', ...) end or function() end local wipe, tremove, tinsert, pairs, floor, tContains = table.wipe, table.remove, table.insert, pairs, floor, tContains -local TQ_GetQuestInfoByQuestID = C_TaskQuest.GetQuestInfoByQuestID -- Return the name of a quest with a given ID local TQ_GetQuestsForPlayerByMapID = C_TaskQuest.GetQuestsForPlayerByMapID -- This function is not yet documented -local TQ_GetQuestTimeLeftMinutes = C_TaskQuest.GetQuestTimeLeftMinutes -local TQ_RequestPreloadRewardData = C_TaskQuest.RequestPreloadRewardData -local TQ_GetQuestLocation = C_TaskQuest.GetQuestLocation +local TQ_GetQuestZoneID = C_TaskQuest.GetQuestZoneID local TQ_IsActive = C_TaskQuest.IsActive local ITEM_QUALITY_COLORS = ITEM_QUALITY_COLORS local WorldMap_DoesWorldQuestInfoPassFilters = WorldMap_DoesWorldQuestInfoPassFilters @@ -63,25 +73,7 @@ local ARTIFACT_COLOR = ITEM_QUALITY_COLORS[LE_ITEM_QUALITY_ARTIFACT] local MONEY_COLOR = {hex ='|cFFFFFF00', r=1, g=1, b=0} local COMMON_COLOR = ITEM_QUALITY_COLORS[LE_ITEM_QUALITY_COMMON] - -local ICON_UNKNOWN = "Interface\\ICONS\\inv_misc_questionmark" -local ICON_MONEY = "Interface\\Buttons\\UI-GroupLoot-Coin-Up" - -local POI_BORDER_MASK = "Interface\\Minimap\\UI-Minimap-Background" -local POI_BORDER_FILL = "Interface\\BUTTONS\\YELLOWORANGE64" -local POI_BORDER_BLUE = "Interface\\BUTTONS\\GRADBLUE" -local POI_BORDER_RED = "Interface\\BUTTONS\\RedGrad64" -local POI_BORDER_YELLOW = "Interface\\BUTTONS\\YELLOWORANGE64" -local POI_BORDER_GREEN = "Interface\\BUTTONS\\GREENGRAD64" - -local REWARD_CASH = 1001 -local REWARD_ARTIFACT_POWER = 1002 -local REWARD_GEAR = 1003 -local REWARD_CURRENCY = 1004 -local REWARD_ITEM = 1005 -local REWARD_REAGENT = 1006 - -local POI_DEFAULT_TYPE = { +local DEFAULT_TYPE = { a = 1, r = 1, g = 1, b = 1, x = 0, y = 0, @@ -114,53 +106,12 @@ showNumber = false, } } -local POI_REWARD_TYPE = setmetatable({}, { - __newindex = function(t, k, v) - if type(v) == 'table' then - setmetatable(v, {__index = POI_DEFAULT_TYPE}) - end - rawset(t,k,v) - end -}) + + local POI_FILTER_STYLE = setmetatable({ continentBorder = 2, zoneBorder = 2, -}, {__index = POI_DEFAULT_TYPE}) - -local LE_QUEST_TAG_TYPE_PVP = LE_QUEST_TAG_TYPE_PVP -local LE_QUEST_TAG_TYPE_PET_BATTLE = LE_QUEST_TAG_TYPE_PET_BATTLE -local LE_QUEST_TAG_TYPE_DUNGEON = LE_QUEST_TAG_TYPE_DUNGEON -local LE_QUEST_TAG_TYPE_PROFESSION = LE_QUEST_TAG_TYPE_PROFESSION -local LE_QUEST_TAG_TYPE_NORMAL = LE_QUEST_TAG_TYPE_NORMAL - --- Pin color/display variables -POI_REWARD_TYPE[REWARD_ITEM] = { - r = 1, g = 1, b = 1, -} -POI_REWARD_TYPE[REWARD_REAGENT] = { - r = 0, g = 1, b = 1, -} -POI_REWARD_TYPE[REWARD_ARTIFACT_POWER] = { - r = 1, g = .25, b = .5, - hasNumeric = true, - numberRGB = {1, 1, 1}, -} -POI_REWARD_TYPE[REWARD_GEAR] = { - r = .1, g = .2, b = 1, -} -POI_REWARD_TYPE[REWARD_CURRENCY] = { - r = 1, g = 1, b = 0, - hasNumeric = true, - numberRGB = {1, 1, 1}, -} -POI_REWARD_TYPE[REWARD_CASH] = { - r = 0, g = 0, b = 0, - --x = 0, y = -1, - --mask = ICON_MONEY, - --continentBorder = 1, - --zoneBorder = 1, -} - +}, {__index = DEFAULT_TYPE}) local defaults = { @@ -176,14 +127,26 @@ } -- Summary header structure + +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 LE_QUEST_TAG_TYPE_PVP = LE_QUEST_TAG_TYPE_PVP +local LE_QUEST_TAG_TYPE_PET_BATTLE = LE_QUEST_TAG_TYPE_PET_BATTLE +local LE_QUEST_TAG_TYPE_DUNGEON = LE_QUEST_TAG_TYPE_DUNGEON +local LE_QUEST_TAG_TYPE_PROFESSION = LE_QUEST_TAG_TYPE_PROFESSION +local LE_QUEST_TAG_TYPE_NORMAL = LE_QUEST_TAG_TYPE_NORMAL local POI_FILTER_OPTIONS = { { label = 'Filters', texture = "Interface\\WorldMap\\WorldMap-Icon" }, { filterKey= 'rewardType', filterValue = REWARD_ARTIFACT_POWER, label = 'Artifact Power', texture = "Interface\\ICONS\\inv_7xp_inscription_talenttome01" }, - { filterKey= 'rewardType', filterValue = REWARD_CURRENCY,label = 'Currency', texture = "Interface\\ICONS\\inv_misc_elvencoins" }, - { filterKey= 'rewardType', filterValue = REWARD_ITEM, label = 'Item', texture = "Interface\\ICONS\\inv_crate_01" }, + { filterKey= 'rewardType', filterValue = REWARD_CURRENCY,label = 'Order Resources', texture = "Interface\\ICONS\\inv_misc_elvencoins" }, { filterKey= 'rewardType', filterValue = REWARD_GEAR, label = 'Equipment', texture = "Interface\\ICONS\\garrison_bluearmorupgrade" }, - { filterKey= 'rewardType', filterValue = REWARD_REAGENT, label = 'Reagents', texture = 1417744 }, - { filterKey= 'rewardType', filterValue = REWARD_CASH, label = 'Reagents', texture = ICON_MONEY }, + { filterKey= 'rewardType', filterValue = REWARD_REAGENT, label = 'Materials', texture = 1417744 }, + { filterKey= 'rewardType', filterValue = REWARD_CASH, label = 'Gold', texture = ICON_MONEY }, { filterKey= 'worldQuestType', filterValue = LE_QUEST_TAG_TYPE_PVP, label = 'PvP', texture = "Interface\\Icons\\Ability_PVP_GladiatorMedallion", spacing = 10 }, { filterKey= 'worldQuestType', filterValue = LE_QUEST_TAG_TYPE_PET_BATTLE, label = 'Pet Battle', texture = "Interface\\Icons\\PetJournalPortrait", }, { filterKey= 'worldQuestType', filterValue = LE_QUEST_TAG_TYPE_DUNGEON, label = 'Dungeon', texture = "Interface\\LFGFRAME\\UI-LFR-PORTRAIT", }, @@ -250,55 +213,6 @@ return frame end --- use tooltip object to extract item details -local ParseItemReward = function(questID) - local rewardType = REWARD_ITEM - local name, icon, quantity, quality, _, itemID = GetQuestLogRewardInfo(1, questID) - if not itemID then - return REWARD_ITEM - end - - scanner:SetOwner(WorldPlan, "ANCHOR_NONE") - scanner:SetItemByID(itemID) - local ttl1 = _G['WorldPlanTooltipTextLeft1'] - local ttl2 = _G['WorldPlanTooltipTextLeft2'] - local ttl3 = _G['WorldPlanTooltipTextLeft3'] - local ttl4 = _G['WorldPlanTooltipTextLeft4'] - if ttl2 then - local text = ttl2:GetText() - -- Artifact Power - if text and 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 - rewardType = REWARD_ARTIFACT_POWER - icon = "Interface\\ICONS\\inv_7xp_inscription_talenttome01" - quantity = power - elseif text and text:match("Item Level") then - --print('equipment!', text) - rewardType = REWARD_GEAR - quantity = text:match("Item Level ([%d\+]+)") - end - end - if ttl3 then - local text = ttl3:GetText() - -- Crafting Reagent - if text and text:match("Crafting Reagent") then - --print('reagent', text) - rewardType = REWARD_REAGENT - end - end - iprint(' item:', name, rewardType, icon, quantity) - return rewardType, icon, quantity, name, itemID -end -- update a masked texture without messing up its blending mask local SetMaskedTexture = function(region, file, mask) @@ -330,6 +244,31 @@ end function WorldPlan:OnLoad () + + self.Types = setmetatable({}, { + __newindex = function(t, k, v) + print('adding type', k) + if type(v) == 'table' then + v = setmetatable(v, {__index = function(t,k) + print('##deferring to default key', k) + return DEFAULT_TYPE[k] + end}) + end + rawset(t,k,v) + end + }) + + local rgbWhite = {1, 1, 1} + self.Types[REWARD_REAGENT] = { r = 0, g = 1, b = 1 } + self.Types[REWARD_ARTIFACT_POWER] = { r = 1, g = .25, b = .5, hasNumeric = true, numberRGB = rgbWhite } + self.Types[REWARD_GEAR] = { r = .1, g = .2, b = 1 } + self.Types[REWARD_CURRENCY] = { r = 1, g = 1, b = 0, hasNumeric = true, numberRGB = rgbWhite, } + self.Types[REWARD_CASH] = { r = 0, g = 0, b = 0, } + + for index, color in pairs(ITEM_QUALITY_COLORS) do + self.Types[(index+127)] = { r = color.r, g = color.g, b = color.b, hex = color.hex, } + end + WorldPlan = self scanner = _G.WorldPlanTooltip wmtt = _G.WorldMapTooltip @@ -421,6 +360,59 @@ hooksecurefunc("UIDropDownMenu_Initialize", self.OnDropDownInitialize) end +function WorldPlan:GetTypeInfo(typeID) + local info, extraInfo + if (not typeID) or (not self.Types[typeID]) then + qprint('## sent default type') + info = DEFAULT_TYPE + else + qprint('## sent defined type', typeID) + info = self.Types[typeID] + end + + if isContinentMap then + extraInfo = info.continent + qprint('### continent subtype', extraInfo) + else + extraInfo = info.zone + + qprint('### zone subtype', extraInfo) + end + return info, extraInfo +end + +do + local timeStates = { + {maxSeconds = 60, + r=1, g=0.25, b =0, format = function (minutes) return '|cFFFF4400'.. minutes .. 'm' end, + }, + {maxSeconds = 240, + r=1, g=.5, b=0, format = function(minutes) return '|cFFFF4400'.. floor(minutes/60) .. 'h' end, + }, + {maxSeconds = 1440, + r=1, g=1, b=0, format = function(minutes) return '|cFFFFFF00'.. floor(minutes/60) .. 'h' end, + }, + {maxSeconds = 10081, + r=0, g=1, b=0, + }, -- 7 days + 1 minute + } + -- Generates a timeleft string + function WorldPlan:GetTimeInfo(timeLeft, limit) + limit = limit or #timeStates + for index = 1, limit do + local state = timeStates[index] + if timeLeft <= state.maxSeconds then + local text + if state.format then + text = state.format(timeLeft) + end + return text, index + end + end + return nil, nil + end +end + function WorldPlan:RefreshAll (forced) if not self.initialized then return @@ -526,6 +518,13 @@ end function WorldQuests:Setup() + + + for mapID, mapName in pairs(WORLD_QUEST_MAPS) do + QuestsByZone[mapID] = {} + end + + -- refresh positions any time blizzard does so (i.e. mousewheel zoom) hooksecurefunc("WorldMapScrollFrame_ReanchorQuestPOIs", function() self:Refresh(true) @@ -548,9 +547,10 @@ if event == 'QUEST_LOG_UPDATE' then local questID, added = ... if questID and added then - self:GetPinByQuestID(questID) + local questPOI = self:AcquirePin(questID) + self.hasUpdate, self.isPending = questPOI:RefreshData() else - self:GetPinsForMap() + self:RefreshData() end print('WorldMapFrame', WorldMapFrame:IsVisible(), 'doRefresh:', hasNewQuestPins) if WorldMapFrame:IsVisible() and hasNewQuestPins then @@ -566,8 +566,8 @@ self:Refresh(true) end end - -function WorldQuests:AcquirePin (questID, pinTable) +local TQ_GetQuestLocation = C_TaskQuest.GetQuestLocation +function WorldQuests:AcquirePin (questID, mapID) local pin = QuestsByID[questID] local isNew = false if not pin then @@ -580,14 +580,12 @@ local name = 'WorldPlanQuestMarker' .. NumPinFrames --print('|cFF00FF00Creating', name) pin = CreateFrame('Frame', name, WorldMapPOIFrame, 'WorldPlanQuestPin') + pin:SetFrameStrata('HIGH') - NumPinFrames = NumPinFrames + 1 - --pin.iconBorder:SetVertexColor(0,0,0,1) - end - QuestsByID[questID] = pin + pin:SetID(questID) pin.isNew = true pin.currentWidth = nil @@ -595,21 +593,13 @@ pin.questID = questID pin.worldQuest = true - pin.Reset = function(self) - WorldQuests:GetPinByQuestID(questID) - end + QuestsByID[questID] = pin else --print('|cFF00FF00Using', pin:GetName()) end + mapID = mapID or TQ_GetQuestZoneID(questID) + QuestsByZone[mapID][questID] = pin - -- set display flags accordingly - if pinTable then - for k,v in pairs(pinTable) do - pin[k] = v - end - end - pin.throttle = nil - pin.timeThreschold = nil return pin, isNew end @@ -634,7 +624,7 @@ end -- create of update quest pins for a map and its underlying zones -function WorldQuests:GetPinsForMap (mapID) +function WorldQuests:RefreshData (mapID) local print = wqprint mapID = mapID or GetCurrentMapAreaID() superTrackedID = GetSuperTrackedQuestID() @@ -643,12 +633,12 @@ return end if mapID == BROKEN_ISLES_ID then - hasPendingQuestData = nil + self.hasUpdate = false print('|cFF00FFFFRefreshQuestsForMap|r', mapID, GetMapNameByID(mapID), superTrackedID) self.fullSearch = true for i = 1, MC_GetNumZones(mapID) do local submapID, name, depth = MC_GetZoneInfo(mapID, i) - self:GetPinsForMap(submapID) + self:RefreshData(submapID) end self.fullSearch = nil elseif QuestsByZone[mapID] then @@ -660,122 +650,25 @@ wipe(QuestsByZone[mapID]) ZoneInfo[mapID] = taskInfo for taskID, info in pairs(taskInfo) do + print('-', taskID) local questID = info.questId - info.mapID = mapID - QuestsByZone[mapID][questID] = self:GetPinByQuestID(questID, info) + local questPOI = self:AcquirePin(questID, mapID) + local hasUpdate, isPending = questPOI:RefreshData(taskInfo) + self.hasUpdate = (self.hasUpdate or hasUpdate) + self.isPending = (self.isPending or isPending) numQuests = numQuests + 1 end end end -end --- create or update the pin using the given questID and C_TaskQuest results -function WorldQuests:GetPinByQuestID (questID, taskInfo) - - local questTitle, rewardIcon, rewardName, rewardCount, rewardStyle, rewardType, itemID, quantity, quality, _ - local pin = self:AcquirePin(questID, taskInfo) - - if pin.isNew then - if not hasNewQuestPins then - print('triggering new quest pins event') - end - - hasNewQuestPins = true - end - - if not HaveQuestData(questID) then - print('|cFFFF4400Retrieval failed.') - TQ_RequestPreloadRewardData(questID) - hasPendingQuestData = true - else - wqprint('|cFF00FF88Quest Data Received|r') - pin.mapID = pin.mapID or C_TaskQuest.GetQuestZoneID(questID) - - -- set reward category - local numRewards = GetNumQuestLogRewards(questID) - local numCurrency = GetNumQuestLogRewardCurrencies(questID) - local money = GetQuestLogRewardMoney(questID) - if numRewards >= 1 then - rewardType, rewardIcon, rewardCount, rewardName, itemID = ParseItemReward(questID) - elseif numCurrency >= 1 then - rewardName, rewardIcon, rewardCount = GetQuestLogRewardCurrencyInfo(1, questID) - rewardType = REWARD_CURRENCY - elseif money >= 1 then - rewardIcon = ICON_MONEY - rewardName = GetMoneyString(money) - rewardType = REWARD_CASH - end - rewardStyle = POI_REWARD_TYPE[rewardType] or POI_DEFAULT_TYPE - - pin.itemNumber = rewardCount or pin.itemNumber - pin.rewardType = rewardType or REWARD_ITEM - pin.style = rewardStyle - QuestsByID[questID] = pin - - -- title, faction, capped state - local questTitle, factionID, capped = TQ_GetQuestInfoByQuestID(questID) - if factionID then - QuestsByFaction[factionID] = QuestsByFaction[factionID] or {} - QuestsByFaction[factionID][questID] = pin - end - pin.factionID = factionID - pin.capped = capped - - -- set tag details - local tagID, tagName, worldQuestType, rarity, isElite, tradeskillLineIndex = GetQuestTagInfo(questID); - local tagAtlas - if worldQuestType == LE_QUEST_TAG_TYPE_PET_BATTLE then - tagAtlas = "worldquest-icon-petbattle" - elseif worldQuestType == LE_QUEST_TAG_TYPE_PVP then - tagAtlas = "worldquest-icon-pvp-ffa" - elseif worldQuestType == LE_QUEST_TAG_TYPE_PROFESSION then - local id = tradeskillLineIndex and select(7, GetProfessionInfo(tradeskillLineIndex)) - if id then - tagAtlas = WORLD_QUEST_ICONS_BY_PROFESSION[id] - end - elseif worldQuestType == LE_QUEST_TAG_TYPE_DUNGEON then - tagAtlas = "worldquest-icon-dungeon" - end - - pin.tagID = tagID - pin.tagName = tagName - pin.worldQuestType = worldQuestType - pin.isElite = isElite - pin.tradeskillLineIndex = tradeskillLineIndex - pin.rarity = rarity - pin.tagAtlas = tagAtlas - - -- flag unresolved info - if not (rewardIcon and rewardName) then - if not pin.isPending then - pin.isPending = true - TQ_RequestPreloadRewardData (questID) - pin.rewardType = pin.rewardType or REWARD_ITEM - pin.style = pin.style or POI_REWARD_TYPE[REWARD_ITEM] - - if not hasPendingQuestData then - hasPendingQuestData = true - PlaySoundKitID(229) - end - --WorldPlan:print('|cFFFFFF00'..tostring(pin.title)..'|r waiting on texture info') - end - else - if (rewardIcon and rewardName) then - --WorldPlan:print('|cFF00FF00'..tostring(pin.title)..'|r has info', rewardIcon, rewardName) - pin.hasUpdate = true - end - pin.isPending = nil - end - - pin.title = questTitle or "|cFFFF0000Retrieving..." - pin.itemTexture = rewardIcon or pin.itemTexture - pin.itemName = rewardName or pin.itemName - - qprint(' |cFF00FFFF'..questID..'|r:->', (HaveQuestData(questID) and "|cFF00FF00HaveQuestData" or "-"), (C_TaskQuest.IsActive(questID) and "|cFF88FF00IsActive|r" or "")) - qprint(' ', pin.title, pin.itemTexture, 'rewardType:', pin.rewardType, 'tag:', pin.tagID, 'style', pin.style ) + print(' hasUpdate:', self.hasUpdate, 'isPending:', self.isPending, 'timer:', self.OnNext) + if self.hasUpdate then + self.OnNext = self.OnNext or C_Timer.NewTimer(0.25, function() + self:Refresh(true) + self.OnNext = nil + end) end - return QuestsByID[questID] end function WorldQuests:Refresh(forced) @@ -1171,6 +1064,7 @@ local button = blocks[numHeaders] if not blocks[numHeaders] then button = CreateFrame('Button', 'WorldPlanFilterButton'..numHeaders, WorldMapScrollFrame, 'WorldPlanFilterPin') + for k,v in pairs(info)do print(k,v) end button.iconBorder:SetTexture(info.fill or POI_BORDER_FILL) button.iconBorder:SetMask(info.mask or POI_BORDER_MASK) button.iconBorder:SetDesaturated(info.desaturated) @@ -1220,7 +1114,7 @@ self.icon:SetTexture(info.texture) self.icon:SetAllPoints(self) self.supertrackBorder:Hide() - self.label:SetText(numQuests) + self.count:SetText(numQuests) self:Show() end @@ -1325,13 +1219,3 @@ SetTimedCallbackForAllPins(8, function(self) self.PendingFade:Stop() end) end --%end-debug% - -for mapID, mapName in pairs(WORLD_QUEST_MAPS) do - QuestsByZone[mapID] = {} -end -for index, color in pairs(ITEM_QUALITY_COLORS) do - POI_REWARD_TYPE[index] = { - r = color.r, g = color.g, b = color.b, - hex = color.hex, - } -end