From 1b302f7f22910ecd5901b8f41bda4ca67cf269d5 Mon Sep 17 00:00:00 2001 From: James Whitehead II Date: Mon, 24 Jan 2011 15:58:51 +0000 Subject: [PATCH] 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. --- TomTom_POIIntegration.lua | 270 +++++++++++++++++++++++++++++---------------- 1 file changed, 173 insertions(+), 97 deletions(-) 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 -- 1.7.9.5