Quantcast

Initial update to POI integration plugin

James Whitehead II [01-24-11 - 15:58]
Initial update to POI integration plugin

Currently, most of the old features should work properly, only there is
now a limitation that it will only work with objective waypoints that
are in your current zone, in particular with the ones on the watch
frame. I will likely change it so that the ones on the world map work
properly, but this will be in a separate commit.
Filename
TomTom_POIIntegration.lua
diff --git a/TomTom_POIIntegration.lua b/TomTom_POIIntegration.lua
index c8dde74..f4b7e2f 100644
--- a/TomTom_POIIntegration.lua
+++ b/TomTom_POIIntegration.lua
@@ -1,22 +1,6 @@
-local hookEnabled = true;
-local modifier;
-local watchframeHookEnabled = false;
-
-local function POIAnchorToCoord(poiframe)
-    local point, relto, relpoint, x, y = poiframe:GetPoint()
-    local frame = WorldMapDetailFrame
-    local width = frame:GetWidth()
-    local height = frame:GetHeight()
-    local scale = frame:GetScale() / poiframe:GetScale()
-    local cx = (x / scale) / width
-    local cy = (-y / scale) / height
-
-    if cx < 0 or cx > 1 or cy < 0 or cy > 1 then
-        return nil, nil
-    end
-
-    return cx * 100, cy * 100
-end
+local enableClicks = true       -- True if waypoint-clicking is enabled to set points
+local enableClosest = true      -- True if 'Automatic' quest waypoints are enabled
+local modifier                  -- A string representing click-modifiers "CAS", etc.

 local modTbl = {
     C = IsControlKeyDown,
@@ -24,45 +8,140 @@ local modTbl = {
     S = IsShiftKeyDown,
 }

-local function findQuestFrameFromQuestIndex(questId)
-    -- Try to find the correct quest frame
-    for i = 1, MAX_NUM_QUESTS do
-        local questFrame = _G["WorldMapQuestFrame"..i];
-        if ( not questFrame ) then
+local astrolabe = DongleStub("Astrolabe-1.0")
+
+-- This function and the related events/hooks are used to automatically
+-- update the crazy arrow to the closest quest waypoint.
+local lastWaypoint
+local scanning          -- This function is not re-entrant, stop that
+
+local function ObjectivesChanged()
+    -- This function should only run if enableClosest is set
+    if not enableClosest then
+        return
+    end
+
+    -- This function may be called while we are processing this function
+    -- so stop that from happening.
+    if scanning then
+        return
+    else
+        scanning = true
+    end
+
+    local map, floor = GetCurrentMapAreaID()
+    local floors = astrolabe:GetNumFloors(map)
+    floor = floors == 0 and 0 or 1
+
+    local px, py = GetPlayerMapPosition("player")
+
+    -- Bail out if we can't get the player's position
+    if not px or not py or px <= 0 or py <= 0 then
+        scanning = false
+        return
+    end
+
+    -- THIS CVAR MUST BE CHANGED BACK!
+    local cvar = GetCVarBool("questPOI")
+    SetCVar("questPOI", 1)
+
+    local closest
+    local closestdist = math.huge
+
+    -- This function relies on the above CVar being set, and updates the icon
+    -- position information so it can be queries via the API
+    QuestPOIUpdateIcons()
+
+    -- Scan through every quest that is tracked, and find the closest one
+    local watchIndex = 1
+    while true do
+        local questIndex = GetQuestIndexForWatch(watchIndex)
+
+        if not questIndex then
             break
-        elseif ( questFrame.questId == questId ) then
-            return questFrame
         end
+
+        local qid = select(9, GetQuestLogTitle(questIndex))
+        local completed, x, y, objective = QuestPOIGetIconInfo(qid)
+
+        if x and y then
+            local dist, xd, yd = astrolabe:ComputeDistance(map, floor, px, py, map, floor, x, y)
+            if dist < closestdist then
+                closest = watchIndex
+            end
+        end
+        watchIndex = watchIndex + 1
     end
-end

-local function setQuestWaypoint(self)
-    local c, z = GetCurrentMapContinent(), GetCurrentMapZone();
-    local x, y = POIAnchorToCoord(self)
+    if closest then
+        local questIndex = GetQuestIndexForWatch(closest)
+        local title = GetQuestLogTitle(questIndex)
+        local qid = select(9, GetQuestLogTitle(questIndex))
+        local completed, x, y, objective = QuestPOIGetIconInfo(qid)
+
+        if completed then
+            title = "Turn in: " .. title
+        end
+
+        local setWaypoint = true
+        if lastWaypoint then
+            -- This is a hack that relies on the UID format, do not use this
+            -- in your addons, please.
+            local pm, pf, px, py = unpack(lastWaypoint)
+            if map == pm and floor == pf and x == px and y == py and lastWaypoint.title == title then
+                -- This is the same waypoint, do nothing
+                setWaypoint = false
+            else
+                -- This is a new waypoint, clear the previous one
+                TomTom:RemoveWaypoint(lastWaypoint)
+            end
+        end

-    local qid = self.questId
+        if setWaypoint then
+            -- Set the new waypoint
+            lastWaypoint = TomTom:AddMFWaypoint(map, floor, x, y, {
+                title = title,
+                persistent = false,
+            })

-    local title;
-    if self.quest and self.quest.questLogIndex then
-        title = GetQuestLogTitle(self.quest.questLogIndex)
-    elseif self.questLogIndex then
-        title = GetQuestLogTitle(self.questLogIndex)
+            -- Check and see if the Crazy arrow is empty, and use it if so
+            if TomTom:IsCrazyArrowEmpty() then
+                TomTom:SetCrazyArrow(lastWaypoint, TomTom.profile.arrow.arrival, title)
+            end
+        end
     else
-        title = "Quest #" .. qid .. " POI"
+        -- No closest waypoint was found, so remove one if its already set
+        if lastWaypoint then
+            TomTom:RemoveWaypoint(lastWaypoint)
+            lastWaypoint = nil
+        end
     end

-    local uid = TomTom:AddZWaypoint(c, z, x, y, title)
-    return uid
+    SetCVar("questPOI", cvar and 1 or 0)
+    scanning = false
 end

--- desc, persistent, minimap, world, custom_callbacks, silent, crazy)
+local eventFrame = CreateFrame("Frame")
+eventFrame:RegisterEvent("QUEST_POI_UPDATE")
+eventFrame:RegisterEvent("QUEST_LOG_UPDATE")
+hooksecurefunc("WatchFrame_Update", function(self)
+    ObjectivesChanged()
+end)
+
+eventFrame:SetScript("OnEvent", function(self, event, ...)
+    if event == "QUEST_POI_UPDATE" then
+        ObjectivesChanged()
+    elseif event == "QUEST_LOG_UPDATE" then
+        ObjectivesChanged()
+    end
+end)
+
+local poiclickwaypoints = {}
 local function poi_OnClick(self, button)
-    -- Are we enabled?
-    if not hookEnabled then
+    if not enableClicks then
         return
     end

-    -- Is this the right button/modifier?
     if button == "RightButton" then
         for i = 1, #modifier do
             local mod = modifier:sub(i, i)
@@ -75,17 +154,43 @@ local function poi_OnClick(self, button)
         return
     end

-    if self.parentName == "WatchFrameLines" then
-        local questFrame = findQuestFrameFromQuestIndex(self.questId)
-        if not questFrame then
-            return
-        else
-            self = questFrame.poiIcon
+    -- Run our logic, and set a waypoint for this button
+    local m, f = GetCurrentMapAreaID()
+
+    local questIndex = self.quest and self.quest.questLogIndex
+    if not questIndex and self.index then
+        questIndex = GetQuestIndexForWatch(self.index)
+    end
+
+    if not questIndex then
+        return
+    end
+
+    local title = GetQuestLogTitle(questIndex)
+    local qid = select(9, GetQuestLogTitle(questIndex))
+    local completed, x, y, objective = QuestPOIGetIconInfo(qid)
+    if completed then
+        title = "Turn in: " .. title
+    end
+
+    local key = TomTom:GetKeyArgs(m, f, x, y, title)
+
+    local alreadySet = false
+    if poiclickwaypoints[key] then
+        local uid = poiclickwaypoints[key]
+        -- Check to see if it has been removed by the user
+        if TomTom:IsValidWaypoint(uid) then
+            alreadySet = true
         end
     end

-    return setQuestWaypoint(self)
- end
+    if not alreadySet then
+        local uid = TomTom:AddMFWaypoint(m, f, x, y, {
+            title = title,
+        })
+        poiclickwaypoints[key] = uid
+    end
+end

 local hooked = {}
 hooksecurefunc("QuestPOI_DisplayButton", function(parentName, buttonType, buttonIndex, questId)
@@ -97,56 +202,27 @@ hooksecurefunc("QuestPOI_DisplayButton", function(parentName, buttonType, button
          poiButton:RegisterForClicks("AnyUp")
          hooked[buttonName] = true
       end
-end)
-
-local setPoints = {}
-
--- This code will enable auto-tracking of closest quest objectives.  To
--- accomplish this, it hooks the WatchFrame_Update function, and when it
--- is called, it sets a waypoint to the closest quest id.
-local function updateClosestPOI()
-    local questIndex = GetQuestIndexForWatch(1);
-    if ( questIndex ) then
-        local title, level, questTag, suggestedGroup, isHeader, isCollapsed, isComplete, isDaily, questID = GetQuestLogTitle(questIndex);
-        local playerMoney = GetMoney();
-        local requiredMoney = GetQuestLogRequiredMoney(questIndex);
-        local numObjectives = GetNumQuestLeaderBoards(questIndex);
-        if ( isComplete and isComplete < 0 ) then
-            isComplete = false;
-        elseif ( numObjectives == 0 and playerMoney >= requiredMoney ) then
-            isComplete = true;
-        end

-        -- check filters
-        local filterOK = true;
-        if ( isComplete and bit.band(WATCHFRAME_FILTER_TYPE, WATCHFRAME_FILTER_COMPLETED_QUESTS) ~= WATCHFRAME_FILTER_COMPLETED_QUESTS ) then
-            filterOK = false;
-        elseif ( bit.band(WATCHFRAME_FILTER_TYPE, WATCHFRAME_FILTER_REMOTE_ZONES) ~= WATCHFRAME_FILTER_REMOTE_ZONES and not LOCAL_MAP_QUESTS[questID] ) then
-            filterOK = false;
-        end
+      -- Check to see if there is a swap button
+      local swapName = "poi" .. parentName .. "_Swap"
+      local swapButton = _G[swapName]

-        if filterOK then
-            -- Set a waypoint for this POI, it should be the higehst
-            local questFrame = findQuestFrameFromQuestIndex(questID)
-            if questFrame then
-                for idx, uid in ipairs(setPoints) do
-                    TomTom:RemoveWaypoint(uid)
-                end
-                local uid = setQuestWaypoint(questFrame.poiIcon)
-                table.insert(setPoints, uid)
-            end
-        end
-    end
-end
-
-hooksecurefunc("WatchFrame_Update", function()
-    if watchframeHookEnabled then
-        updateClosestPOI()
-    end
+      if not hooked[swapName] and swapButton then
+          swapButton:HookScript("OnClick", poi_OnClick)
+          swapButton:RegisterForClicks("AnyUp")
+          hooked[swapName] = true
+      end
 end)

 function TomTom:EnableDisablePOIIntegration()
-    hookEnabled = TomTom.profile.poi.enable
+    enableClicks= TomTom.profile.poi.enable
     modifier = TomTom.profile.poi.modifier
-    watchframeHookEnabled = TomTom.profile.poi.setClosest
+    enableClosest = TomTom.profile.poi.setClosest
+
+    if not enableClosest and lastWaypoint then
+        TomTom:RemoveWaypoint(lastWaypoint)
+        lastWaypoint = nil
+    elseif enableClosest then
+        ObjectivesChanged()
+    end
 end