changeset 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 e8679ecb48d8
children 0100d923d8c3
files FilterBar.lua FilterBar.xml FollowerList.lua FollowerList.xml QuestPOI.lua WorldPlan.lua WorldPlan.toc WorldPlan.xml WorldQuests.lua WorldQuests.xml
diffstat 10 files changed, 639 insertions(+), 679 deletions(-) [+]
line wrap: on
line diff
--- a/FilterBar.lua	Tue Nov 01 10:48:50 2016 -0400
+++ b/FilterBar.lua	Wed Nov 02 17:25:07 2016 -0400
@@ -5,6 +5,7 @@
 --
 
 local print = DEVIAN_WORKSPACE and function(...) _G.print('FilterBar', ...) end or nop
+local wprint = DEVIAN_WORKSPACE and function(...) _G.print('WP', ...) end or function() end
 local wipe, ipairs, pairs = table.wipe, ipairs, pairs
 
 local REWARD_CASH = WORLD_QUEST_REWARD_TYPE_FLAG_GOLD
@@ -18,7 +19,26 @@
 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 familiars = {
+  [42159] = {npc = 106552, name = 'Nightwatcher Merayl'},
+  [40277] = {npc = 97804, name = 'Tiffany Nelson'},
+  [40298] = {npc = 99182, name = 'Sir Galveston'},
+  [40282] = {npc=  99150, name = 'Grixis Tinypop'},
+  [40278] = {npc = 98270, name = 'Robert Craig'},
+  [48195] = {npc = 105250, name = 'Aulier'},
+  [41990] = {npc = 105674, name = 'Varenne'},
+  [41860] = {npc = 104970, name = 'Xorvasc'},
+  [40299] = {npc = 99210, name = 'Bodhi Sunwayver'},
+  [42442] = {npc = 107489, name = 'Amalia'},
+  [40280] = {npc = 99077, name = 'Bredda Tenderhide'},
+  [41687] = {npc = 104553, name = 'Odrogg'},
+  [41944] = {npc = 105455, name = 'Trapper Jarrun'},
+  [40337] = {npc = 97709, name = 'Master Tamer Flummox'},
+  [40279] = {npc = 99035, name = 'Durian Strongfruit'}
+}
+local familiars_id = 9696
+
 local DEFAULT_FILTER_LAYOUT = {
   PinSize = 22,
   Border = 3,
@@ -51,11 +71,7 @@
 WorldPlanFilterPinMixin = {}
 
 function WorldPlanSummaryMixin:OnLoad()
-  self:RegisterEvent('QUEST_LOG_UPDATE')
-  self:RegisterEvent('WORLD_MAP_UPDATE')
-
   WorldPlan:AddHandler(self, defaults)
-
   for index, info in ipairs(DEFAULT_FILTER_LIST) do
     info.zone = DEFAULT_FILTER_LAYOUT
     info.continent = DEFAULT_FILTER_LAYOUT
@@ -68,32 +84,36 @@
 
 
 function WorldPlanSummaryMixin:OnEvent(event)
-  self:Refresh()
+  print('|cFF00FF88'..self:GetName()..':OnEvent()', event)
+  self.isStale = true
 end
 
 local bountyIndex
 local debug_headers = {}
 
 function WorldPlanSummaryMixin:Setup()
+  print('|cFF00FF88'..self:GetName()..':Setup()')
   self:GetFilters()
 end
 
 
-function WorldPlanSummaryMixin:OnEvent(event,...)
-  self.isStale = true
+function WorldPlanSummaryMixin:OnUpdate()
+  if self.isStale then
+    wprint('|cFF00FF00pushing update')
+    self:Refresh()
+  end
 end
-function WorldPlanSummaryMixin:OnUpdate()
+
+function WorldPlanSummaryMixin:OnShow()
+  print('|cFF00FF88'..self:GetName()..':OnShow()')
   if self.isStale then
     self:Refresh()
   end
 end
 
-function WorldPlanSummaryMixin:OnShow()
-  self:Refresh()
-end
-
 function WorldPlanSummaryMixin:GetFilters()
 
+  print('|cFF00FFFF'..self:GetName()..':GetFilters()')
 
   wipe(self.filterList)
 
@@ -127,22 +147,22 @@
   self:GetFilters()
 end
 
-function WorldPlanSummaryMixin:Refresh(forced)
-  self:Update(forced)
+function WorldPlanSummaryMixin:Refresh()
+  self:Update()
 end
 
 local filterFill = "Interface\\BUTTONS\\YELLOWORANGE64"
 local filterMask = "Interface\\Minimap\\UI-Minimap-Background"
 
 local questResults = {{}}
-function WorldPlanSummaryMixin:Update(forced)
+function WorldPlanSummaryMixin:Update()
   local blocks = self.buttons
   local relativeFrame = WorldMapFrame.UIElementsFrame.TrackingOptionsButton
   local numHeaders = 0
-  print('|cFF00FF88'..tostring(self)..':Refresh()|r', 'currentMap=',self.currentMapID)
+  print('|cFF00FF88'..self:GetName()..':Update()|r', 'currentMap=',WorldPlan.currentMapID)
 
 
-  local quests = WorldPlanQuests.QuestsByZone[self.currentMapID] or WorldPlanQuests.QuestsByID
+  local quests = WorldPlanQuests.QuestsByZone[WorldPlan.currentMapID] or WorldPlanQuests.QuestsByID
   local foundQuests = questResults[1]
   for index, info in ipairs(self.filterList) do
     local numQuests = 0
@@ -267,7 +287,7 @@
   local desaturated = false
   if self.cVar then
     self.iconBorder:SetVertexColor(1, 1, 1, 1)
-    if GetCVarBool(self.cVar) == true then
+    if GetCVarBool(self.cVar) then
       self.icon:SetVertexColor(1,1,1,1)
       self:SetAlpha(1)
     else
@@ -300,6 +320,7 @@
 function WorldPlanFilterPinMixin:OnUpdate ()
 end
 
+
 function WorldPlanFilterPinMixin:OnLeave ()
   if GameTooltip:IsOwned(self) then
     GameTooltip:Hide()
@@ -320,8 +341,22 @@
 
   if not filterKey then
     wipe(WorldPlan.UsedFilters)
+    for i, info in ipairs(DEFAULT_FILTER_LIST) do
+      if info.cVar then
+        SetCVar(info.cVar, 1)
+      end
+    end
+
   elseif self.cVar then
-    SetCVar(self.cVar, (GetCVarBool(self.cVar) and 0) or 1)
+      for i, info in ipairs(DEFAULT_FILTER_LIST) do
+        if info.cVar then
+          if (info.cVar ~= self.cVar) and (button == 'LeftButton') then
+            SetCVar(info.cVar, 0)
+          else
+            SetCVar(info.cVar, 1)
+          end
+        end
+      end
   else
     local setInclude = (button == 'LeftButton')
     local flushValue
@@ -332,5 +367,5 @@
       WorldPlan.UsedFilters[filterKey] = filterValue
     end
   end
-  WorldPlan:Refresh()
+  WorldPlan:Refresh(true)
 end
\ No newline at end of file
--- a/FilterBar.xml	Tue Nov 01 10:48:50 2016 -0400
+++ b/FilterBar.xml	Wed Nov 02 17:25:07 2016 -0400
@@ -5,6 +5,7 @@
     <Scripts>
       <OnLoad method="OnLoad" />
       <OnEvent method="OnEvent" />
+      <OnShow method="OnShow" />
     </Scripts>
 
   </Frame>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FollowerList.lua	Wed Nov 02 17:25:07 2016 -0400
@@ -0,0 +1,11 @@
+ClassPlanFollowerMixin = {}
+local c = ClassPlanFollowerMixin
+function c:OnEvent(event, arg)
+
+end
+
+function c:GetPlayerData(event, arg) end
+
+function c:UpdateItems() end
+
+function c:Reanchor() end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FollowerList.xml	Wed Nov 02 17:25:07 2016 -0400
@@ -0,0 +1,11 @@
+<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
+..\FrameXML\UI.xsd">
+  <Script file="FollowerList.lua" />
+  <Frame name="$parentFollowerList" parent="ClassOrderPlan"parentKey="FollowerList"  parentArray="Handlers" mixin="ClassPlanFollowerMixin">
+    <Scripts>
+      <OnEvent method="OnEvent" />
+      <OnUpdate method="OnUpdate" />
+      <OnShow method="OnShow" />
+    </Scripts>
+  </Frame>
+</Ui>
\ No newline at end of file
--- a/QuestPOI.lua	Tue Nov 01 10:48:50 2016 -0400
+++ b/QuestPOI.lua	Wed Nov 02 17:25:07 2016 -0400
@@ -4,15 +4,21 @@
 -- %file-revision%
 --
 
+WorldPlanPOIMixin = {}
 local TQ_GetQuestInfoByQuestID = C_TaskQuest.GetQuestInfoByQuestID -- Return the name of a quest with a given ID
 local TQ_GetQuestLocation = C_TaskQuest.GetQuestLocation
 local TQ_GetQuestTimeLeftMinutes = C_TaskQuest.GetQuestTimeLeftMinutes
 local TQ_IsActive = C_TaskQuest.IsActive
 local TQ_RequestPreloadRewardData = C_TaskQuest.RequestPreloadRewardData
 local QuestPOIGetIconInfo, WorldMapPOIFrame =  QuestPOIGetIconInfo, WorldMapPOIFrame
+local WorldMap_DoesWorldQuestInfoPassFilters = WorldMap_DoesWorldQuestInfoPassFilters
+local QuestMapFrame_IsQuestWorldQuest = QuestMapFrame_IsQuestWorldQuest
+local GameTooltip = GameTooltip
+local GetItemIcon = GetItemIcon
 
-local print = DEVIAN_WORKSPACE and function(...) _G.print('WP', ...) end or function() end
+local print = DEVIAN_WORKSPACE and function(...) _G.print('POI', ...) 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 wqprint = DEVIAN_WORKSPACE and function(...) _G.print('WorldQuests', ...) end or function() end
 local iprint = DEVIAN_WORKSPACE and function(...) _G.print('ItemScan', ...) end or function() end
 local QuestPOI = WorldPlanPOIMixin
@@ -77,29 +83,32 @@
 
 -- Pin color/display variables
 
-  local familiars = {
-      [42159] = {npc = 106552, name = 'Nightwatcher Merayl'},
-      [40277] = {npc = 97804, name = 'Tiffany Nelson'},
-      [40298] = {npc = 99182, name = 'Sir Galveston'},
-      [40282] = {npc=  99150, name = 'Grixis Tinypop'},
-      [40278] = {npc = 98270, name = 'Robert Craig'},
-      [48195] = {npc = 105250, name = 'Aulier'},
-      [41990] = {npc = 105674, name = 'Varenne'},
-      [41860] = {npc = 104970, name = 'Xorvasc'},
-      [40299] = {npc = 99210, name = 'Bodhi Sunwayver'},
-      [42442] = {npc = 107489, name = 'Amalia'},
-      [40280] = {npc = 99077, name = 'Bredda Tenderhide'},
-      [41687] = {npc = 104553, name = 'Odrogg'},
-      [41944] = {npc = 105455, name = 'Trapper Jarrun'},
-      [40337] = {npc = 97709, name = 'Master Tamer Flummox'},
-      [40279] = {npc = 99035, name = 'Durian Strongfruit'}
-  }
-  local familiars_id = 9696
+local familiars = {
+    [42159] = {npc = 106552, name = 'Nightwatcher Merayl'},
+    [40277] = {npc = 97804, name = 'Tiffany Nelson'},
+    [40298] = {npc = 99182, name = 'Sir Galveston'},
+    [40282] = {npc=  99150, name = 'Grixis Tinypop'},
+    [40278] = {npc = 98270, name = 'Robert Craig'},
+    [48195] = {npc = 105250, name = 'Aulier'},
+    [41990] = {npc = 105674, name = 'Varenne'},
+    [41860] = {npc = 104970, name = 'Xorvasc'},
+    [40299] = {npc = 99210, name = 'Bodhi Sunwayver'},
+    [42442] = {npc = 107489, name = 'Amalia'},
+    [40280] = {npc = 99077, name = 'Bredda Tenderhide'},
+    [41687] = {npc = 104553, name = 'Odrogg'},
+    [41944] = {npc = 105455, name = 'Trapper Jarrun'},
+    [40337] = {npc = 97709, name = 'Master Tamer Flummox'},
+    [40279] = {npc = 99035, name = 'Durian Strongfruit'}
+}
+local familiars_id = 9696
+
+
+-- update a masked texture without messing up its blending mask
 
 
 -- update a masked texture without messing up its blending mask
 local SetMaskedTexture = function(region, file, mask)
-  mask = mask or POI_BORDER_MASK
+  mask = mask or "Interface\\Minimap\\UI-Minimap-Background"
   region:SetMask(nil)
   region:SetTexture(file)
   region:SetMask(mask)
@@ -242,7 +251,7 @@
 
   local questID = self:GetID()
   local questTitle, rewardIcon, rewardName, rewardCount, rewardStyle, rewardType, itemID, quantity, quality, _
-  local hasUpdate, isPending = (self.hasUpdate or self.isNew), self.isPending
+  local hasUpdate, isPending = (self.isStale or self.isNew), self.isPending
 
 
   if not HaveQuestData(questID) then
@@ -317,7 +326,7 @@
     self.title = questTitle or "|cFFFF0000Retrieving..."
     self.itemTexture = rewardIcon or self.itemTexture
     self.itemName = rewardName or self.itemName
-    self.hasUpdate = hasUpdate
+    self.isStale = hasUpdate
     self.isPending = isPending
 
 
@@ -338,14 +347,14 @@
 function WorldPlanPOIMixin:ShowNew()
   self:SetShown(true)
   self.isNew = nil
-  self.hasUpdate = true
+  self.isStale = true
   self.FadeIn:Play()
 end
 
 function WorldPlanPOIMixin:OnShow ()
-  qprint('|cFFFFFF00["'..tostring(self.title)..'"]|r:OnShow() update:', self.hasUpdate, 'new:', self.isNew, 'animation:', self.isAnimating)
+  qprint('|cFFFFFF00["'..tostring(self.title)..'"]|r:OnShow() update:', self.isStale, 'new:', self.isNew, 'animation:', self.isAnimating)
   -- pop this on principle
-  if self.hasUpdate then
+  if self.isStale then
     self:Refresh()
   end
 
@@ -355,7 +364,7 @@
 end
 
 function WorldPlanPOIMixin:SetAnchor(frame, mapID, mapWidth, mapHeight)
-  qprint('  |cFF00FF00'..self:GetName()..':SetAnchor()|r', self.questID, mapID, mapWidth)
+  --qprint('  |cFF00FF00'..self:GetName()..':SetAnchor()|r', self.questID, mapID, mapWidth)
   self:ClearAllPoints()
   local dX, dY = TQ_GetQuestLocation(self.questID)
   if not dX or dX == 0 then
@@ -388,7 +397,7 @@
 
 function WorldPlanPOIMixin:OnEvent(event, ...)
   if event == 'SUPER_TRACKED_QUEST_CHANGED' then
-    self.hasUpdate = true
+    self.isStale = true
   end
 end
 
@@ -397,8 +406,8 @@
 local TOP_PIN_ID
 function WorldPlanPOIMixin:OnUpdate (sinceLast)
 
-  if self.hasUpdate then
-    wqprint('|cFFFFFF00push poi update')
+  if self.isStale then
+    print('|cFFFFFF00push poi update')
     self:Refresh()
     return
   end
@@ -457,7 +466,6 @@
 
 function WorldPlanPOIMixin:Refresh ()
   local db = WorldPlan.db
-  local print = wqprint
   print('|cFF00FF88'..self:GetName()..'|r:Refresh()')
 
 
@@ -492,10 +500,10 @@
 
     if self.hasNumeric then
       if subStyle.numberFontObject then
-        wqprint('change font', _G[subStyle.numberFontObject]:GetName())
+        --wqprint('change font', _G[subStyle.numberFontObject]:GetName())
         self.count:SetFontObject(_G[subStyle.numberFontObject])
       end
-      wqprint('filtered:', self.filtered, 'showNumber:', self.showNumber)
+      --wqprint('filtered:', self.filtered, 'showNumber:', self.showNumber)
 
       self.count:SetShown(self.showNumber)
       self.count:SetText(self.itemNumber)
@@ -540,36 +548,103 @@
 
 
   self:UpdateSize()
-  self.hasUpdate = nil
+  self.isStale = nil
 end
 
-function WorldPlanFilterPinMixin:OnEnter ()
-  local filter = WorldPlan.FilterOptions[self:GetID()]
-  local mapID = GetCurrentMapAreaID()
-  local quests = (mapID == WorldPlan.BrokenIsleID) and WorldPlan.QuestsByID or WorldPlan.QuestsByZone[mapID]
-  if quests then
-    GameTooltip:SetOwner(self, 'ANCHOR_RIGHT')
-    GameTooltip:AddLine(filter.label)
-    local filterKey = self.filterKey
-    local filterValue = self.filterValue
-    if filterKey then
-      for questID, pin in pairs(quests) do
-        if pin.used and not pin.filtered then
-          if  pin[filterKey] == filterValue then
-            local style = pin.style or WorldPlan.FilterStyle
 
-            if familiars[questID] then
-              GameTooltip:AddLine(pin.title,0,1,0)
-            else
-              GameTooltip:AddLine(pin.title,1,1,1)
-            end
 
-          end
-        end
-      end
-    else
-      GameTooltip:AddLine('Reset all filters')
+
+function QuestPOI:IsShowable ()
+  local print = wqprint
+  local db = WorldPlan.db
+  local qType = self.worldQuestType
+  local rType = self.rewardType
+  self.filtered = nil
+  self.used = true
+
+
+  self.questId  = self:GetID()
+  if not (WorldMap_DoesWorldQuestInfoPassFilters(self, false, true)) then
+    self.filtered = true
+  end
+
+  for filterKey, value in pairs(WorldPlan.UsedFilters) do
+    if self[filterKey] ~= value then
+      self.filtered = true
     end
-    GameTooltip:Show()
   end
+
+  if not TQ_IsActive(self.questID) then
+    self.used = nil
+  elseif qType == LE_QUEST_TAG_TYPE_PROFESSION then
+    if not (db.ShowAllProfessionQuests or (self.tradeskillLineIndex and GetProfessionInfo(self.tradeskillLineIndex))) then
+      self.used = nil
+    end
+  end
+  print('  |cFFFF4400IsShowable()|r', self.used, self.filtered, self.title)
+  return self.used, self.filtered
+end
+
+function QuestPOI:UpdateTimer (timeLeft, timeType)
+  print('|cFF0088FFUpdatePinTimer()|r')
+end
+
+--- Fixes icons upon size update
+function QuestPOI:UpdateSize (style, subStyle)
+  style = style or self.style
+  subStyle = subStyle or self.subStyle
+
+  --qprint('|cFF00FF88'..self:GetName()..'|r:UpdateSize()', style, subStyle)
+
+  self.currentWidth = subStyle.PinSize
+  self.borderSize = subStyle.Border
+  self.trackingBorderSize = subStyle.TrackingBorder
+  self.tagSize = subStyle.TagSize
+  self.TimeleftStage = subStyle.TimeleftStage
+  self.NoIcon = subStyle.NoIcon
+
+
+  self:SetSize(self.currentWidth, self.currentWidth)
+
+  local icon = self.icon
+  local iconBorder = self.iconBorder
+  local trackingBorder = self.supertrackBorder
+  local tag = self.tagIcon
+  local pinMask = style.pinMask
+  local rewardMask = style.rewardMask
+
+  if self.NoIcon then
+    self.icon:Hide()
+  else
+    self.icon:Show()
+    icon:SetMask(nil)
+    icon:SetMask(rewardMask)
+    icon:SetTexture(self.icon:GetTexture())
+  end
+  iconBorder:SetMask(nil)
+  trackingBorder:SetMask(nil)
+
+
+  local borderWidth = self.borderSize
+  local trackingWidth = self.trackingBorderSize
+
+  iconBorder:ClearAllPoints()
+  iconBorder:SetPoint('BOTTOMLEFT', self, 'BOTTOMLEFT', -borderWidth + (style.x or 0), -borderWidth + (style.y or 0))
+  iconBorder:SetPoint('TOPRIGHT', self, 'TOPRIGHT', borderWidth + (style.x or 0), borderWidth + (style.y or 0))
+
+  trackingBorder:ClearAllPoints()
+  trackingBorder:SetPoint('BOTTOMLEFT', iconBorder, 'BOTTOMLEFT', -trackingWidth, -trackingWidth)
+  trackingBorder:SetPoint('TOPRIGHT', iconBorder, 'TOPRIGHT', trackingWidth, trackingWidth)
+
+  if self.tagSize then
+    tag:Show()
+    tag:ClearAllPoints()
+    tag:SetPoint('BOTTOMRIGHT', self, 'BOTTOMRIGHT', borderWidth, -borderWidth)
+  else
+    tag:Hide()
+  end
+
+  --qprint('using mask:', mask, self.name )
+  iconBorder:SetMask(pinMask)
+  trackingBorder:SetMask(pinMask)
 end
\ No newline at end of file
--- a/WorldPlan.lua	Tue Nov 01 10:48:50 2016 -0400
+++ b/WorldPlan.lua	Wed Nov 02 17:25:07 2016 -0400
@@ -2,77 +2,33 @@
 -- Created: 8/16/2016 8:19 AM
 -- %file-revision%
 
-local addonName, db = ...
-
-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 = {},
   modules = {},
-}
-WorldPlanQuestsMixin = {
+  FilterOptions = {},
+  UsedFilters = {},
   QuestsByZone = {},
   QuestsByID = {},
-  freePins = {},
+  TaskQueue = {},
 }
-WorldPlanPOIMixin = {}
-WorldPlanFilterPinMixin = setmetatable({ QuestsByID = {}, freePins = {} }, {__tostring = function() return 'QuestHandler' end})
-local WorldPlanFlightMapMixin = setmetatable({}, {__tostring = function() return 'FlightMapHandler' end})
-local WorldQuests = WorldPlanQuestsMixin
+local WorldPlan = WorldPlanCore
 
-
-local WorldPlan = WorldPlanCore
-local QuestPOI = WorldPlanPOIMixin
-local FilterPin = WorldPlanFilterPinMixin
+local print = DEVIAN_WORKSPACE and function(...) _G.print('WP', ...) end or function() end
 local WP_VERSION = "1.0"
-
-local db
-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 iprint = DEVIAN_WORKSPACE and function(...) _G.print('ItemScan', ...) end or function() end
-local wqprint = DEVIAN_WORKSPACE and function(...) _G.print('WorldQuests', ...) end or function() end
-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_GetQuestsForPlayerByMapID = C_TaskQuest.GetQuestsForPlayerByMapID -- This function is not yet documented
-local TQ_GetQuestZoneID = C_TaskQuest.GetQuestZoneID
-local TQ_IsActive = C_TaskQuest.IsActive
+local tinsert, pairs, floor = table.insert, pairs, floor
 local ITEM_QUALITY_COLORS = ITEM_QUALITY_COLORS
-local WorldMap_DoesWorldQuestInfoPassFilters = WorldMap_DoesWorldQuestInfoPassFilters
-local QuestMapFrame_IsQuestWorldQuest = QuestMapFrame_IsQuestWorldQuest
-local GameTooltip = GameTooltip
-local GetItemIcon = GetItemIcon
-
-
-local GetMapInfo, QuestPOIGetIconInfo = GetMapInfo, QuestPOIGetIconInfo
-local GetQuestTagInfo, HaveQuestData =  GetQuestTagInfo, HaveQuestData
-local GetNumQuestLogRewards, GetNumQuestLogRewardCurrencies, GetQuestLogRewardMoney = GetNumQuestLogRewards, GetNumQuestLogRewardCurrencies, GetQuestLogRewardMoney
-local GetQuestLogRewardInfo, GetQuestLogRewardCurrencyInfo, GetMoneyString = GetQuestLogRewardInfo, GetQuestLogRewardCurrencyInfo, GetMoneyString
-
+local BROKEN_ISLES_ID = 1007
 local GetCurrentMapAreaID, GetMapNameByID, GetSuperTrackedQuestID = GetCurrentMapAreaID, GetMapNameByID, GetSuperTrackedQuestID
-local MC_GetNumZones, MC_GetZoneInfo = C_MapCanvas.GetNumZones, C_MapCanvas.GetZoneInfo
-
 
 -- default color templates
-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 DEFAULT_TYPE = {
   a = 1,
   r = 1, g = 1, b = 1,
   x = 0, y = 0,
   desaturated = true,
-  pinMask = POI_BORDER_MASK,
-  rewardMask = POI_BORDER_MASK,
-  texture = POI_BORDER_FILL,
+  pinMask = "Interface\\Minimap\\UI-Minimap-Background",
+  rewardMask = "Interface\\Minimap\\UI-Minimap-Background",
+  texture = "Interface\\BUTTONS\\YELLOWORANGE64",
   continent = {
     PinSize = 14,
     Border = 2,
@@ -113,71 +69,16 @@
   FadeWhileGrouped = true,
 }
 
--- 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
-WorldPlanCore.BrokenIsleID = BROKEN_ISLES_ID
-WorldPlanCore.FilterStyle = POI_FILTER_STYLE
-
-WorldPlanCore.FilterOptions = {}
-WorldPlanCore.UsedFilters = {}
-
-
 -- operating flags
 local superTrackedID
 local currentMapName
 local hasNewQuestPins
 local isContinentMap
-local numPins = 0
-local FilterInclusions = {rewardType = {}, worldQuestType = {}, factionID = {}}
-local NotificationTypes = {}
-local ZoneInfo = {}
-local SummaryHeaders = {}
-
-local FreePins = {}
-local NumPinFrames = 1
-
 local hasPendingQuestData
 local notifyPlayed
 local scanner, wmtt, WorldMapPOIFrame
 
 
-local tasksQueue = {}
-local function OnNext (func)
-  if #tasksQueue == 0 then
-    _G.WorldPlan:SetScript('OnUpdate', function()
-      local func = tremove(tasksQueue, 1)
-      if func then
-        func()
-      end
-      if #tasksQueue == 0 then
-        _G.WorldPlan:SetScript('OnUpdate', nil)
-      end
-    end)
-  end
-  print('inserting task #', #tasksQueue+1, func)
-  tinsert(tasksQueue, func)
-end
-
--- update a masked texture without messing up its blending mask
-local SetMaskedTexture = function(region, file, mask)
-  mask = mask or POI_BORDER_MASK
-  region:SetMask(nil)
-  region:SetTexture(file)
-  region:SetMask(mask)
-end
-
 -- tracking menu toggler
 local DropDown_OnClick = function(self)
   local key = self.value
@@ -188,7 +89,7 @@
       WorldPlanData[key] = true
     end
   end
-  WorldPlan:Refresh()
+  _G.WorldPlan:Refresh()
 end
 
 function WorldPlan:print(...)
@@ -238,9 +139,6 @@
   end
 
   WorldPlan = self
-  scanner = _G.WorldPlanTooltip
-  wmtt = _G.WorldMapTooltip
-  WorldMapPOIFrame = _G.WorldMapPOIFrame
 
   WorldPlan:print('v'..WP_VERSION)
 
@@ -260,12 +158,11 @@
   if self.isStale then
     self:Refresh()
   end
-
 end
 
 function WorldPlan:OnEvent (event, ...)
   print()
-  print(event, self.initialized)
+  print(event, 'init:', self.initialized)
   if event == 'ADDON_LOADED' then
     local addon = ...
     if addon == "Blizzard_FlightMap" then
@@ -276,20 +173,49 @@
     if IsLoggedIn() and not self.initialized then
       self:Setup()
     end
-  elseif event == 'WORLD_MAP_UPDATE' then
-    self.currentMapID = GetCurrentMapAreaID()
-    print('|cFFFF4400currentMapID =', self.currentMapID)
-    self:Refresh()
   else
+    if event == 'WORLD_MAP_UPDATE' then
+      self.currentMapID = GetCurrentMapAreaID()
+      self.isContinentMap = (self.currentMapID == BROKEN_ISLES_ID)
+      print('|cFFFF4400currentMapID =', self.currentMapID)
+      --self.isStale = true
+    end
+
     for i, module in ipairs(self.modules) do
       if module.OnEvent then
-        print('forwarding to', tostring(module))
+        print('  |cFF0088FF'..module:GetName() .. ':OnEvent()|r')
         module:OnEvent(event, ...)
       end
     end
   end
 end
 
+function WorldPlanCore:OnNext(func)
+  tinsert(self.TaskQueue, func)
+end
+
+function WorldPlanCore:OnUpdate()
+  if #self.TaskQueue >= 1 then
+  local func = tremove(self.TaskQueue, 1)
+  if func then
+    func()
+  end
+
+  end
+
+  if self.isStale then
+    print('|cFF00FF00pushing global update')
+    self.isStale = nil
+    self:Refresh()
+  else
+    for i, module in ipairs(self.modules) do
+      if module.isStale then
+        print('|cFF00FF00internal '..module:GetName()..':Refresh()|r')
+        module:Refresh()
+      end
+    end
+  end
+end
 
 function WorldPlan:Setup ()
   if not WorldPlanData then
@@ -323,6 +249,16 @@
   self.initialized = true
 
   hooksecurefunc("UIDropDownMenu_Initialize", self.OnDropDownInitialize)
+
+  hooksecurefunc("WorldMapTrackingOptionsDropDown_OnClick", function(button)
+    print("|cFF0088FFWorldMapTrackingOptionsDropDown_OnClick|r")
+    local value = button.value
+    if (value == "worldQuestFilterOrderResources" or value == "worldQuestFilterArtifactPower" or
+        value == "worldQuestFilterProfessionMaterials" or value == "worldQuestFilterGold" or
+        value == "worldQuestFilterEquipment") then
+      self:Refresh(true)
+    end
+  end)
 end
 
 function WorldPlan:AddTypeInfo(owner, id, info)
@@ -398,30 +334,9 @@
   end
 
   for i, module in ipairs(self.modules) do
-    if module.Reset then
-      print(module, 'Reset()')
-      module:Reset()
-    end
-  end
-
-  for i, module in ipairs(self.modules) do
     if module.Refresh then
-      print(module, 'Refresh()')
-      module:Refresh()
-    end
-  end
-
-  for i, module in ipairs(self.modules) do
-    if module.Cleanup then
-      print(module, 'Cleanup()')
-      module:Cleanup()
-    end
-  end
-end
-function WorldPlan:UpdateAnchors ()
-  for i, module in ipairs(self.modules) do
-    if module.UpdateAnchors then
-      module:UpdateAnchors()
+      print('|cFF00FF00external '..module:GetName()..':Refresh()|r')
+      module:Refresh(forced)
     end
   end
 end
@@ -494,345 +409,6 @@
 --------------------------------------------------------------------------------------------------------------------
 --------------------------------------------------------------------------------------------------------------------
 
-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
-
--- maps where we do our own anchors
-local CONTINENT_MAPS = { [BROKEN_ISLES_ID] = BROKEN_ISLES_ID, }
-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', }
-
-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)
-
-  hooksecurefunc("WorldMapTrackingOptionsDropDown_OnClick", function(button)
-    print("|cFF0088FFWorldMapTrackingOptionsDropDown_OnClick|r")
-    local value = button.value
-    if (value == "worldQuestFilterOrderResources" or value == "worldQuestFilterArtifactPower" or
-        value == "worldQuestFilterProfessionMaterials" or value == "worldQuestFilterGold" or
-        value == "worldQuestFilterEquipment") then
-      self:Refresh(true)
-    end
-  end)
-end
-
-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('QUEST_LOG_UPDATE')
-  self:RegisterEvent('WORLD_QUEST_COMPLETED_BY_SPELL')
-  self:RegisterEvent('SKILL_LINES_CHANGED')
-
-
-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.hasUpdate, self.isPending = questPOI:RefreshData()
-    else
-      self:RefreshData()
-    end
-    print('WorldMapFrame', WorldMapFrame:IsVisible(), 'hasUpdates:', self.hasUpdate)
-  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.hasUpdate = true
-  end
-end
-
-function WorldQuests:OnUpdate()
-  if self.hasUpdate then
-    wqprint('|cFF00FF00pushing update')
-    self:Refresh(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.hasUpdate = 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.hasUpdate = (self.hasUpdate 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.hasUpdate, 'isPending:', self.isPending, 'timer:', (self.OnNext and 'waiting' or ''))
-
-  end
-
-end
-
-function WorldQuests:Refresh(forced)
-  local print = wqprint
-  print('|cFF00FF88'..self:GetName()..':Refresh()|r')
-  if not WorldMapPOIFrame:IsVisible() then
-    return
-  end
-  if forced then
-    self:Reset()
-  end
-  self:UpdateAnchors()
-
-  if forced then
-    self:Cleanup ()
-  end
-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.hasUpdate = 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
-          OnNext(function()
-            pin:ShowNew()
-          end)
-          if not notifyPlayed then
-            for k,v in pairs(NotificationTypes) do
-              if v[pin[k]] then
-                notifyPlayed = true
-                PlaySoundKitID(23404)
-              end
-            end
-          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.hasUpdate = nil
-end
 
 -- data provider manipulations for the taxi map
 WorldPlan.OnFlightMapLoaded = function()
@@ -871,129 +447,10 @@
 
 
 
-local throttle = 0
-local tooltip = CreateFrame ("GameTooltip", "VeneerWorldQuestsScanner", nil, "GameTooltipTemplate")
-local tooltipLine1 = _G['VeneerWorldQuestsScannerTextLeft1']
-local tooltipLine3 = _G['VeneerWorldQuestsScannerTextLeft3']
-local GetTime, mod = GetTime, mod
 
 
 
 
-function WorldQuests:FilterCheckByID(questID)
-  local pin = WorldQuests:GetPinByQuestID(questID)
-  return pin:IsShowable()
-end
-
-
-function QuestPOI:IsShowable ()
-  local print = wqprint
-  local db = WorldPlan.db
-  local qType = self.worldQuestType
-  local rType = self.rewardType
-  self.filtered = nil
-  self.used = true
-
-  print('  |cFFFF4400IsShowable()|r', self.title)
-
-  self.questId  = self:GetID()
-  if not (WorldMap_DoesWorldQuestInfoPassFilters(self, false, true)) then
-    self.filtered = true
-  end
-
-  for filterKey, value in pairs(WorldPlan.UsedFilters) do
-    if self[filterKey] ~= value then
-      self.filtered = true
-    end
-  end
-
-  if not TQ_IsActive(self.questID) then
-    self.used = nil
-  elseif qType == LE_QUEST_TAG_TYPE_PROFESSION then
-    if not (db.ShowAllProfessionQuests or (self.tradeskillLineIndex and GetProfessionInfo(self.tradeskillLineIndex))) then
-      self.used = nil
-    end
-  end
-  return self.used, self.filtered
-end
-
-function QuestPOI:UpdateTimer (timeLeft, timeType)
-  print('|cFF0088FFUpdatePinTimer()|r')
-end
-
---- Fixes icons upon size update
-function QuestPOI:UpdateSize (style, subStyle)
-  style = style or self.style
-  subStyle = subStyle or self.subStyle
-
-  --qprint('|cFF00FF88'..self:GetName()..'|r:UpdateSize()', style, subStyle)
-
-  self.currentWidth = subStyle.PinSize
-  self.borderSize = subStyle.Border
-  self.trackingBorderSize = subStyle.TrackingBorder
-  self.tagSize = subStyle.TagSize
-  self.TimeleftStage = subStyle.TimeleftStage
-  self.NoIcon = subStyle.NoIcon
-
-
-  self:SetSize(self.currentWidth, self.currentWidth)
-
-  local icon = self.icon
-  local iconBorder = self.iconBorder
-  local trackingBorder = self.supertrackBorder
-  local tag = self.tagIcon
-  local pinMask = style.pinMask
-  local rewardMask = style.rewardMask
-
-  if self.NoIcon then
-    self.icon:Hide()
-  else
-    self.icon:Show()
-    icon:SetMask(nil)
-    icon:SetMask(rewardMask)
-    icon:SetTexture(self.icon:GetTexture())
-  end
-  iconBorder:SetMask(nil)
-  trackingBorder:SetMask(nil)
-
-
-  local borderWidth = self.borderSize
-  local trackingWidth = self.trackingBorderSize
-
-  iconBorder:ClearAllPoints()
-  iconBorder:SetPoint('BOTTOMLEFT', self, 'BOTTOMLEFT', -borderWidth + (style.x or 0), -borderWidth + (style.y or 0))
-  iconBorder:SetPoint('TOPRIGHT', self, 'TOPRIGHT', borderWidth + (style.x or 0), borderWidth + (style.y or 0))
-
-  trackingBorder:ClearAllPoints()
-  trackingBorder:SetPoint('BOTTOMLEFT', iconBorder, 'BOTTOMLEFT', -trackingWidth, -trackingWidth)
-  trackingBorder:SetPoint('TOPRIGHT', iconBorder, 'TOPRIGHT', trackingWidth, trackingWidth)
-
-  if self.tagSize then
-    tag:Show()
-    tag:ClearAllPoints()
-    tag:SetPoint('BOTTOMRIGHT', self, 'BOTTOMRIGHT', borderWidth, -borderWidth)
-  else
-    tag:Hide()
-  end
-
-  --qprint('using mask:', mask, self.name )
-  iconBorder:SetMask(pinMask)
-  trackingBorder:SetMask(pinMask)
-
-
-end
-
-
-
---%debug%
-local SetTimedCallbackForAllPins = function(seconds, callback)
-  C_Timer.After(seconds, function()
-    for id, pin in pairs(WorldPlanQuests.QuestsByID) do
-      callback(pin)
-    end
-  end)
-end
-
 SLASH_WORLDPLAN1 = "/worldplan"
 SLASH_WORLDPLAN2 = "/wp"
 SlashCmdList.WORLDPLAN = function()
--- a/WorldPlan.toc	Tue Nov 01 10:48:50 2016 -0400
+++ b/WorldPlan.toc	Wed Nov 02 17:25:07 2016 -0400
@@ -10,5 +10,6 @@
 ## OptionalDeps: Veneer
 
 WorldPlan.xml
+WorldQuests.xml
 FilterBar.xml
 ClassPlan.xml
--- a/WorldPlan.xml	Tue Nov 01 10:48:50 2016 -0400
+++ b/WorldPlan.xml	Wed Nov 02 17:25:07 2016 -0400
@@ -150,13 +150,6 @@
     <Scripts>
       <OnLoad method="OnLoad" />
       <OnEvent method="OnEvent" />
-    </Scripts>
-  </Frame>
-
-  <Frame name="$parentQuests" mixin="WorldPlanQuestsMixin" parent="WorldPlan">
-    <Scripts>
-      <OnLoad method="OnLoad" />
-      <OnEvent method="OnEvent" />
       <OnUpdate method="OnUpdate" />
       <OnShow method="OnShow" />
     </Scripts>
--- /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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WorldQuests.xml	Wed Nov 02 17:25:07 2016 -0400
@@ -0,0 +1,14 @@
+<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
+..\FrameXML\UI.xsd">
+  <Script file="WorldQuests.lua" />
+
+
+  <Frame name="$parentQuests" mixin="WorldPlanQuestsMixin" parent="WorldPlan">
+    <Scripts>
+      <OnLoad method="OnLoad" />
+      <OnEvent method="OnEvent" />
+      <OnShow method="OnShow" />
+    </Scripts>
+  </Frame>
+
+  </Ui>
\ No newline at end of file