From 8644c7d80528673bafa12e04e8712fdb568212f9 Mon Sep 17 00:00:00 2001 From: wowaddonmaker Date: Wed, 18 Mar 2026 19:31:20 -0400 Subject: [PATCH 1/9] [worktree-rename] Rename addon to EasyFind-rares Original addon name: EasyFind --- EasyFind.toc => EasyFind-rares.toc | 2 +- MapSearch.lua | 6 +++--- UI.lua | 2 +- Utils.lua | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) rename EasyFind.toc => EasyFind-rares.toc (93%) diff --git a/EasyFind.toc b/EasyFind-rares.toc similarity index 93% rename from EasyFind.toc rename to EasyFind-rares.toc index 8b46360..1d530ba 100644 --- a/EasyFind.toc +++ b/EasyFind-rares.toc @@ -1,5 +1,5 @@ ## Interface: 120005, 120001, 120000 -## Title: EasyFind +## Title: EasyFind (rares) ## Notes: Search and locate UI elements and map locations with ease ## Author: justawower ## Version: 1.3.1 diff --git a/MapSearch.lua b/MapSearch.lua index 0d059d6..c7cb9e3 100644 --- a/MapSearch.lua +++ b/MapSearch.lua @@ -12,7 +12,7 @@ local mmin, mmax, mpi = Utils.mmin, Utils.mmax, Utils.mpi local pcall, xpcall, tostring = Utils.pcall, Utils.xpcall, Utils.tostring local ErrorHandler = Utils.ErrorHandler -local LIGHTNING_BOLT_TEX = "Interface\\AddOns\\EasyFind\\textures\\lightning-bolt" +local LIGHTNING_BOLT_TEX = "Interface\\AddOns\\EasyFind-rares\\textures\\lightning-bolt" local GOLD_COLOR = ns.GOLD_COLOR local YELLOW_HIGHLIGHT = ns.YELLOW_HIGHLIGHT local DEFAULT_OPACITY = ns.DEFAULT_OPACITY @@ -97,7 +97,7 @@ local INDICATOR_STYLES = { preRotated = false, -- Needs mpi rotation to point down }, ["EasyFind Arrow"] = { - texture = "Interface\\AddOns\\EasyFind\\Images\\arrow-hq", + texture = "Interface\\AddOns\\EasyFind-rares\\Images\\arrow-hq", texCoord = nil, preRotated = true, -- Already points down, no rotation needed }, @@ -472,7 +472,7 @@ local function CreateWaypointTracker() local layer = nearTrackFrame:CreateTexture(nil, "OVERLAY", nil, i) layer:SetSize(ringSize, ringSize) layer:SetPoint("CENTER", Minimap, "CENTER", 0, 0) - layer:SetTexture("Interface\\AddOns\\EasyFind\\textures\\near-track-ring") + layer:SetTexture("Interface\\AddOns\\EasyFind-rares\\textures\\near-track-ring") layer:SetBlendMode("ADD") layer:SetVertexColor(1, 1, 0.3, 1) ringLayers[i] = layer diff --git a/UI.lua b/UI.lua index caea5df..a0bb98c 100644 --- a/UI.lua +++ b/UI.lua @@ -26,7 +26,7 @@ local IsShiftKeyDown = IsShiftKeyDown local GetCursorPosition = GetCursorPosition local wipe = wipe -local LIGHTNING_BOLT_TEX = "Interface\\AddOns\\EasyFind\\textures\\lightning-bolt" +local LIGHTNING_BOLT_TEX = "Interface\\AddOns\\EasyFind-rares\\textures\\lightning-bolt" local searchFrame local resultsFrame diff --git a/Utils.lua b/Utils.lua index 7a8d325..d56af2d 100644 --- a/Utils.lua +++ b/Utils.lua @@ -126,8 +126,8 @@ ns.SEARCHBAR_FONT = "EasyFindSearchFont" -- Custom 3-part search bar border with chamfered corners. -- Fill (BACKGROUND) and border (ARTWORK) use identical shapes from custom TGA textures. -- Fill is tinted black with tunable opacity; border uses Blizzard's action bar gray. -local SEARCH_TEX_FILL = "Interface\\AddOns\\EasyFind\\Textures\\SearchBarFill" -local SEARCH_TEX_BORDER = "Interface\\AddOns\\EasyFind\\Textures\\SearchBarBorder" +local SEARCH_TEX_FILL = "Interface\\AddOns\\EasyFind-rares\\Textures\\SearchBarFill" +local SEARCH_TEX_BORDER = "Interface\\AddOns\\EasyFind-rares\\Textures\\SearchBarBorder" local SEARCH_CAP_W = 8 local SEARCH_TEX_W = 64 local TC_LEFT = {0, SEARCH_CAP_W / SEARCH_TEX_W, 0, 1} From add332604ea5ab928e9292b54018627a556e8f66 Mon Sep 17 00:00:00 2001 From: wowaddonmaker Date: Fri, 20 Mar 2026 13:52:56 -0400 Subject: [PATCH 2/9] Add rare mob search with auto-track, fix multi-pin overlap and nav waypoint resolution --- Core.lua | 2 + MapSearch.lua | 326 +++++++++++++++++++++++++++++++++++++++++++++++--- Options.lua | 14 ++- 3 files changed, 322 insertions(+), 20 deletions(-) diff --git a/Core.lua b/Core.lua index c07ea8b..0e1c3e0 100644 --- a/Core.lua +++ b/Core.lua @@ -95,7 +95,9 @@ local DB_DEFAULTS = { instances = true, travel = true, services = true, + rares = true, }, + alwaysShowRares = false, -- Persistent rare tracking: show active rares on map without searching uiSearchFilters = { -- UI search category filters ui = true, mounts = false, diff --git a/MapSearch.lua b/MapSearch.lua index c7cb9e3..71c4c40 100644 --- a/MapSearch.lua +++ b/MapSearch.lua @@ -39,8 +39,11 @@ local SetUserWaypoint = C_Map.SetUserWaypoint local GetAreaPOIForMap = C_AreaPoiInfo and C_AreaPoiInfo.GetAreaPOIForMap local GetAreaPOIInfo = C_AreaPoiInfo and C_AreaPoiInfo.GetAreaPOIInfo local GetDelvesForMap = C_AreaPoiInfo and C_AreaPoiInfo.GetDelvesForMap +local GetVignettes = C_VignetteInfo and C_VignetteInfo.GetVignettes +local GetVignetteInfo = C_VignetteInfo and C_VignetteInfo.GetVignetteInfo local GetVignettePosition = C_VignetteInfo and C_VignetteInfo.GetVignettePosition local GetTaxiNodesForMap = C_TaxiMap and C_TaxiMap.GetTaxiNodesForMap +local SetSuperTrackedVignette = C_SuperTrack and C_SuperTrack.SetSuperTrackedVignette local GetDungeonEntrancesForMap = C_EncounterJournal and C_EncounterJournal.GetDungeonEntrancesForMap local HasUserWaypoint = C_Map.HasUserWaypoint local ClearUserWaypoint = C_Map.ClearUserWaypoint @@ -333,6 +336,9 @@ local isGlobalSearch = false -- Tracks which search bar triggered the current s local activePinState = nil -- {mapID, x, y, icon, category} - survives map close/reopen local mapIsMaximized = false -- Tracks WorldMapFrame maximize state for search bar repositioning local cachedWorldZones -- Built once per session by GetAllWorldZones +local rareTrackCache = {} -- [vignetteGUID] = rare entry, persists across scans for auto-track +local rareTrackMapID = nil -- mapID the cache is valid for +local efTrackedVignetteGUID = nil -- GUID we explicitly set via SetSuperTrackedVignette (rares only) -- Reusable tables for OnSearchTextChanged (wiped each call to avoid per-keystroke allocations) local reuseAllPOIs = {} @@ -631,16 +637,38 @@ local function CreateWaypointTracker() end end - -- Cross-zone: prefer intermediate nav waypoint (portal, boat, etc.) + -- Prefer intermediate nav waypoint (portal, boat, etc.) when the + -- game's navigation mesh routes through one. Walk up the map + -- hierarchy (zone → parent → continent) because the waypoint may + -- be on a different zone than the player. cachedIsNavWaypoint = false - if not sameZone and pMapID and C_SuperTrack.GetNextWaypointForMap then - local navX, navY = C_SuperTrack.GetNextWaypointForMap(pMapID) - if navX and navY and (navX ~= 0 or navY ~= 0) - and navX >= 0 and navX <= 1 and navY >= 0 and navY <= 1 then - wpMapID = pMapID - wpX = navX - wpY = navY - cachedIsNavWaypoint = true + if pMapID and C_SuperTrack.GetNextWaypointForMap then + local navMapID, navX, navY + local tryMap = pMapID + for _ = 1, 5 do + if not tryMap then break end + local nx, ny = C_SuperTrack.GetNextWaypointForMap(tryMap) + if nx and ny and (nx ~= 0 or ny ~= 0) + and nx >= 0 and nx <= 1 and ny >= 0 and ny <= 1 then + navMapID = tryMap + navX = nx + navY = ny + break + end + local info = GetMapInfo(tryMap) + tryMap = info and info.parentMapID + end + if navMapID and navX then + -- Only use nav waypoint if it differs from the actual destination + local dx = navX - (wpX or 0) + local dy = navY - (wpY or 0) + local isSameMap = wpMapID == navMapID + if not isSameMap or (dx * dx + dy * dy) > 0.001 then + wpMapID = navMapID + wpX = navX + wpY = navY + cachedIsNavWaypoint = true + end end end @@ -865,7 +893,20 @@ loadingScreenFrame:RegisterEvent("SUPER_TRACKING_CHANGED") loadingScreenFrame:RegisterEvent("NAVIGATION_DESTINATION_REACHED") loadingScreenFrame:RegisterEvent("SUPER_TRACKING_PATH_UPDATED") loadingScreenFrame:RegisterEvent("CVAR_UPDATE") +loadingScreenFrame:RegisterEvent("VIGNETTES_UPDATED") loadingScreenFrame:SetScript("OnEvent", function(_, event, isInitialLogin, isReloadingUI) + if event == "VIGNETTES_UPDATED" then + -- Refresh cached position only when tracking a rare WE set (not game-tracked portals) + if efTrackedVignetteGUID then + local trackedGUID = C_SuperTrack.GetSuperTrackedVignette and C_SuperTrack.GetSuperTrackedVignette() + if trackedGUID and trackedGUID == efTrackedVignetteGUID then + cachedWPMapID = nil + cachedWPWorldX = nil + cachedWPWorldY = nil + end + end + return + end if event == "CVAR_UPDATE" then -- isInitialLogin is repurposed here as the cvar name arg if isInitialLogin == "rotateMinimap" then @@ -926,6 +967,11 @@ loadingScreenFrame:SetScript("OnEvent", function(_, event, isInitialLogin, isRel cachedWPWorldX = nil cachedWPWorldY = nil cachedCrossContinent = nil + -- Clear stale rare tracking GUID when tracking target changes + local currentVig = C_SuperTrack.GetSuperTrackedVignette and C_SuperTrack.GetSuperTrackedVignette() + if efTrackedVignetteGUID and currentVig ~= efTrackedVignetteGUID then + efTrackedVignetteGUID = nil + end -- Hide stale glow so it doesn't linger at the old target's position if superTrackGlow and superTrackGlow:IsShown() then superTrackGlow.animGroup:Stop() @@ -1133,7 +1179,7 @@ local CATEGORY_ICONS = { repairvendor = 136465, barber = 3852099, transmogrifier = 1598183, - rare = "Interface\\Icons\\INV_Misc_Head_Dragon_01", + rare = { file = 1121272, coords = { 0.7796, 0.8381, 0.1934, 0.2531 } }, treasure = "Interface\\Icons\\INV_Misc_Bag_10", catalyst = "Interface\\Icons\\INV_10_GearUpgrade_Catalyst_Charged", greatvault = "Interface\\Icons\\INV_Misc_Lockbox_1", @@ -1750,6 +1796,7 @@ function MapSearch:CreateSearchFrame() { key = "instances", label = "Instances" }, { key = "travel", label = "Travel" }, { key = "services", label = "Services" }, + { key = "rares", label = "Rares" }, } local localFilterDropdown = MapSearch:CreateFilterDropdown( @@ -1757,6 +1804,49 @@ function MapSearch:CreateSearchFrame() "localSearchFilters", localFilterBtn, searchFrame, editBox ) + -- "Auto-track" toggle on the Rares filter row + do + local raresRow = localFilterDropdown.rows[#LOCAL_FILTER_OPTIONS] -- last row = Rares + raresRow:SetHitRectInsets(0, 65, 0, 0) + local trackBtn = CreateFrame("Button", nil, raresRow) + trackBtn:SetSize(60, 18) + trackBtn:SetPoint("RIGHT", raresRow, "RIGHT", -2, 0) + trackBtn:SetFrameLevel(raresRow:GetFrameLevel() + 1) + local trackLabel = trackBtn:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall") + trackLabel:SetPoint("RIGHT") + trackLabel:SetText("Auto-track") + trackBtn.label = trackLabel + + local function UpdateAutoTrackColor() + if EasyFind.db.alwaysShowRares then + trackLabel:SetTextColor(GOLD_COLOR[1], GOLD_COLOR[2], GOLD_COLOR[3]) + else + trackLabel:SetTextColor(0.5, 0.5, 0.5) + end + end + UpdateAutoTrackColor() + + trackBtn:SetScript("OnClick", function() + EasyFind.db.alwaysShowRares = not EasyFind.db.alwaysShowRares + UpdateAutoTrackColor() + MapSearch:UpdateRareTracking() + end) + trackBtn:SetScript("OnEnter", function(self) + GameTooltip:SetOwner(self, "ANCHOR_RIGHT") + if EasyFind.db.alwaysShowRares then + GameTooltip:SetText("Auto-track: |cFF00FF00ON|r") + GameTooltip:AddLine("Active rares are always shown on the map.\nClick to disable.", 1, 1, 1, true) + else + GameTooltip:SetText("Auto-track: OFF") + GameTooltip:AddLine("Click to always show active rares on the map.", 1, 1, 1, true) + end + GameTooltip:Show() + end) + trackBtn:SetScript("OnLeave", GameTooltip_Hide) + + localFilterDropdown:HookScript("OnShow", UpdateAutoTrackColor) + end + searchFrame.filterBtn = localFilterBtn searchFrame.filterDropdown = localFilterDropdown @@ -4550,6 +4640,12 @@ function MapSearch:HookWorldMap() activePinState = nil end end + -- Show tracked rares when no search pins to restore + if not activePinState and EasyFind.db.alwaysShowRares then + C_Timer.After(0, function() + self:UpdateRareTracking() + end) + end end) WorldMapFrame:HookScript("OnHide", function() @@ -4721,6 +4817,29 @@ function MapSearch:HookWorldMap() activePinState = nil end self:ClearZoneHighlight() + -- Re-scan rares for the new zone + if EasyFind.db.alwaysShowRares then + C_Timer.After(0, function() self:UpdateRareTracking() end) + end + end + end) + + -- Live-refresh search results when rares spawn or despawn nearby + local vignetteFrame = CreateFrame("Frame") + vignetteFrame:RegisterEvent("VIGNETTES_UPDATED") + vignetteFrame:SetScript("OnEvent", function() + if isGlobalSearch then return end + local editBox = searchFrame and searchFrame.editBox + if editBox and editBox:HasFocus() then + local text = editBox:GetText() + if text and #text >= 2 then + MapSearch:OnSearchTextChanged(text) + return + end + end + -- Refresh always-on rare pins when not actively searching + if EasyFind.db.alwaysShowRares then + MapSearch:UpdateRareTracking() end end) end @@ -5212,6 +5331,111 @@ function MapSearch:GetStaticLocations() return results end +function MapSearch:ScanVignettes() + local rares = {} + if not GetVignettes then return rares end + + local mapID = WorldMapFrame:GetMapID() + if not mapID then return rares end + + local guids = GetVignettes() + if not guids then return rares end + + for _, guid in ipairs(guids) do + local info = GetVignetteInfo and GetVignetteInfo(guid) + if info and info.name and not info.isDead then + local atlas = info.atlasName + if atlas == "VignetteKill" or atlas == "VignetteKillElite" then + local pos = GetVignettePosition(guid, mapID) + if pos then + rares[#rares + 1] = { + name = info.name, + category = "rare", + icon = CATEGORY_ICONS.rare, + x = pos.x, + y = pos.y, + vignetteGUID = guid, + keywords = {"rare", "rares"}, + } + end + end + end + end + + -- Aggregate "Rares" entry always present so the tracking toggle is accessible + local instances = {} + for _, rare in ipairs(rares) do + instances[#instances + 1] = rare + end + rares[#rares + 1] = { + name = "Rares", + category = "rare", + icon = CATEGORY_ICONS.rare, + keywords = {"rare", "rares"}, + isAggregate = true, + allInstances = instances, + } + + return rares +end + +function MapSearch:UpdateRareTracking() + if not EasyFind.db.alwaysShowRares then return end + if not WorldMapFrame or not WorldMapFrame:IsShown() then return end + -- Don't override active search + local editBox = searchFrame and searchFrame.editBox + if editBox and editBox:GetText() ~= "" then return end + + local mapID = WorldMapFrame:GetMapID() + if not mapID then return end + + -- Clear cache on zone change + if mapID ~= rareTrackMapID then + wipe(rareTrackCache) + rareTrackMapID = mapID + end + + -- Merge fresh scan into cache (updates positions of in-range rares) + local rares = self:ScanVignettes() + for _, rare in ipairs(rares) do + if not rare.isAggregate and rare.vignetteGUID then + rareTrackCache[rare.vignetteGUID] = rare + end + end + + -- Prune dead rares; keep out-of-range ones at last known position + for guid, rare in pairs(rareTrackCache) do + local info = GetVignetteInfo and GetVignetteInfo(guid) + if info then + if info.isDead then + rareTrackCache[guid] = nil + else + -- Still in range: refresh position + local pos = GetVignettePosition(guid, mapID) + if pos then + rare.x = pos.x + rare.y = pos.y + end + end + end + -- info == nil means out of range, keep at last known position + end + + -- Build display list from cache + local individuals = {} + for _, rare in pairs(rareTrackCache) do + if rare.x and rare.y then + individuals[#individuals + 1] = rare + end + end + + if #individuals > 0 then + self:ShowMultipleWaypoints(individuals) + else + self:ClearHighlight() + end +end + function MapSearch:ScanMapPOIs() local pois = {} local mapID = WorldMapFrame:GetMapID() @@ -5387,13 +5611,14 @@ function MapSearch:GetPinInfo(pin) end end - -- Vignettes (rares, treasures) + -- Vignettes: treasures only. Rares handled by ScanVignettes() (provides GUID for super-tracking) if pin.vignetteInfo then - name = pin.vignetteInfo.name - pinType = "vignette" - category = "rare" if pin.vignetteInfo.vignetteType == 2 then + name = pin.vignetteInfo.name + pinType = "vignette" category = "treasure" + else + return nil end end @@ -5521,6 +5746,10 @@ function MapSearch:OnSearchTextChanged(text) else self:HideResults() end + -- Resume always-on rare tracking when search is cleared + if EasyFind.db.alwaysShowRares and (not text or text == "") then + C_Timer.After(0, function() self:UpdateRareTracking() end) + end return end @@ -5661,6 +5890,9 @@ function MapSearch:OnSearchTextChanged(text) -- Get flight master locations for current map local flightMasters = self:ScanFlightMasters() + -- Scan active rares via vignette API + local vignetteRares = self:ScanVignettes() + -- Coordinate-based sources first (dungeon entrances, flight masters) so they -- take priority over pin-only entries from ScanMapPOIs during deduplication. -- Pin-only entries lack x/y and go through HighlightPin (no icon), while @@ -5691,6 +5923,17 @@ function MapSearch:OnSearchTextChanged(text) end end + for _, rare in ipairs(vignetteRares) do + if not rare.isAggregate then + if not zoneNames[slower(rare.name)] and not existingNames[slower(rare.name)] then + tinsert(allPOIs, rare) + existingNames[slower(rare.name)] = true + end + else + tinsert(allPOIs, rare) + end + end + -- Dynamic pins and static locations added after, skipping duplicates for _, poi in ipairs(dynamicPOIs) do if not zoneNames[slower(poi.name)] and not existingNames[slower(poi.name)] then @@ -5746,6 +5989,8 @@ function MapSearch:OnSearchTextChanged(text) dominated = true elseif (parentCat == "service" or cat == "service") and filters.services == false then dominated = true + elseif cat == "rare" and filters.rares == false then + dominated = true end if not dominated then tinsert(filteredResults, r) @@ -5894,9 +6139,9 @@ function MapSearch:SearchPOIs(pois, query) end end - -- Attach duplicates info to results + -- Attach duplicates info to results (skip entries with pre-populated allInstances) for _, result in ipairs(results) do - if result.duplicateKey and duplicates[result.duplicateKey] then + if not result.allInstances and result.duplicateKey and duplicates[result.duplicateKey] then result.allInstances = duplicates[result.duplicateKey] end end @@ -6060,7 +6305,7 @@ function MapSearch:ShowResults(results) -- Show navigate button for local search results with coordinates local hasCoords = not isGlobalSearch - and ((data.x and data.y) or (data.allInstances and #data.allInstances > 1)) + and ((data.x and data.y) or (data.allInstances and #data.allInstances >= 1)) if hasCoords and resultRow.navBtn then resultRow.navBtn:ClearAllPoints() resultRow.navBtn:SetPoint("CENTER", resultRow, "LEFT", navBtnCenterX - ROW_INSET, 0) @@ -6430,13 +6675,27 @@ function MapSearch:SelectResult(data) return end - -- Check if this POI has multiple instances (duplicates) + -- Check if this POI has multiple instances (duplicates) or aggregate if data.allInstances and #data.allInstances > 1 then -- Show ALL instances on the map self:ShowMultipleWaypoints(data.allInstances) + elseif data.allInstances and #data.allInstances == 1 then + local single = data.allInstances[1] + if single.x and single.y then + self:ShowWaypointAt(single.x, single.y, single.icon, single.category) + if single.vignetteGUID and SetSuperTrackedVignette then + efTrackedVignetteGUID = single.vignetteGUID + SetSuperTrackedVignette(single.vignetteGUID) + end + end elseif data.x and data.y then -- Single POI with coordinates self:ShowWaypointAt(data.x, data.y, data.icon, data.category) + -- Activate built-in navigation arrow for rares + if data.vignetteGUID and SetSuperTrackedVignette then + efTrackedVignetteGUID = data.vignetteGUID + SetSuperTrackedVignette(data.vignetteGUID) + end elseif data.pin then -- Dynamic pin with no coords - highlight it directly self:HighlightPin(data.pin) @@ -6490,10 +6749,15 @@ function MapSearch:ShowMultipleWaypoints(instances) self.extraIndicators = {} end + -- Sort north-to-south (ascending y) so southern pins render on top + tsort(instances, function(a, b) return (a.y or 0) < (b.y or 0) end) + -- Show each instance with pin, highlight box, and indicator for i, instance in ipairs(instances) do if instance.x and instance.y then local pin, highlight, ind + -- Stagger frame levels so each pin group fully covers the previous one + local baseLevel = 1998 + i * 3 if i == 1 then -- Use the main frames for first instance @@ -6617,6 +6881,14 @@ function MapSearch:ShowMultipleWaypoints(instances) ind = self.extraIndicators[i-1] end + -- Ensure consistent strata and staggered levels so overlapping pins stack cleanly + highlight:SetFrameStrata("TOOLTIP") + pin:SetFrameStrata("TOOLTIP") + ind:SetFrameStrata("TOOLTIP") + highlight:SetFrameLevel(baseLevel) + pin:SetFrameLevel(baseLevel + 1) + ind:SetFrameLevel(baseLevel + 2) + -- Position and show the pin pin:SetSize(iconSize, iconSize) pin:ClearAllPoints() @@ -6841,6 +7113,11 @@ function MapSearch:GetPreviewCoords(data) local currentMapID = WorldMapFrame:GetMapID() if data.allInstances and #data.allInstances > 1 then return { instances = data.allInstances } + elseif data.allInstances and #data.allInstances == 1 then + local single = data.allInstances[1] + if single.x and single.y then + return { x = single.x, y = single.y, icon = single.icon, category = single.category } + end end -- Determine the best known coords and their associated map local px, py, pIcon, pCat, pMapID @@ -7330,11 +7607,12 @@ function MapSearch:SearchForUI(query) local existingNames = {} if isLocal then - -- Local: same 4 sources as the real local search + -- Local: same sources as the real local search local dynamicPOIs = self:ScanMapPOIs() local staticLocations = self:GetStaticLocations() local dungeonEntrances = self:ScanDungeonEntrances() local flightMasters = self:ScanFlightMasters() + local vignetteRares = self:ScanVignettes() for _, entrance in ipairs(dungeonEntrances) do pois[#pois + 1] = entrance @@ -7346,6 +7624,16 @@ function MapSearch:SearchForUI(query) existingNames[slower(fm.name)] = true end end + for _, rare in ipairs(vignetteRares) do + if not rare.isAggregate then + if not existingNames[slower(rare.name)] then + pois[#pois + 1] = rare + existingNames[slower(rare.name)] = true + end + else + pois[#pois + 1] = rare + end + end for _, poi in ipairs(dynamicPOIs) do if not existingNames[slower(poi.name)] then pois[#pois + 1] = poi diff --git a/Options.lua b/Options.lua index 7d26248..1b7fc47 100644 --- a/Options.lua +++ b/Options.lua @@ -827,8 +827,20 @@ function Options:Initialize() end) optionsFrame.minimapBtnCheckbox = minimapBtnCheckbox + local rareTrackCheckbox = CreateCheckbox(sec3, "RareTrack", "Always Show Rares on Map", + "When enabled, active rare mobs are always displayed as pins on the world map without needing to search.\n\nThis can also be toggled from the \"Rares\" search result row.") + rareTrackCheckbox:SetPoint("TOPLEFT", loginMessageCheckbox, "BOTTOMLEFT", 0, -4) + rareTrackCheckbox:SetChecked(EasyFind.db.alwaysShowRares or false) + rareTrackCheckbox:SetScript("OnClick", function(self) + EasyFind.db.alwaysShowRares = self:GetChecked() + if ns.MapSearch then + ns.MapSearch:UpdateRareTracking() + end + end) + optionsFrame.rareTrackCheckbox = rareTrackCheckbox + local indicatorLabel = sec3:CreateFontString(nil, "OVERLAY", "GameFontNormal") - indicatorLabel:SetPoint("TOPLEFT", loginMessageCheckbox, "BOTTOMLEFT", 4, -10) + indicatorLabel:SetPoint("TOPLEFT", rareTrackCheckbox, "BOTTOMLEFT", 4, -10) indicatorLabel:SetText("Indicator Style:") local indicatorChoices = {"EasyFind Arrow", "Classic Quest Arrow", "Minimap Player Arrow", "Low-res Gauntlet", "HD Gauntlet"} From b87e54828dd19097dca166f986f058596b108bf3 Mon Sep 17 00:00:00 2001 From: wowaddonmaker Date: Fri, 20 Mar 2026 14:51:49 -0400 Subject: [PATCH 3/9] Fix rare tracking: dead rare cleanup, sub-zone detection, nav waypoint hierarchy, and stale pin cleanup --- MapSearch.lua | 67 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 42 insertions(+), 25 deletions(-) diff --git a/MapSearch.lua b/MapSearch.lua index 71c4c40..1aec162 100644 --- a/MapSearch.lua +++ b/MapSearch.lua @@ -338,6 +338,7 @@ local mapIsMaximized = false -- Tracks WorldMapFrame maximize state for search local cachedWorldZones -- Built once per session by GetAllWorldZones local rareTrackCache = {} -- [vignetteGUID] = rare entry, persists across scans for auto-track local rareTrackMapID = nil -- mapID the cache is valid for +local rareDeadGUIDs = {} -- GUIDs confirmed dead/despawned, blocked from re-entering cache local efTrackedVignetteGUID = nil -- GUID we explicitly set via SetSuperTrackedVignette (rares only) -- Reusable tables for OnSearchTextChanged (wiped each call to avoid per-keystroke allocations) @@ -535,7 +536,14 @@ local function CreateWaypointTracker() return end - -- Resolve waypoint world position once (refreshed by USER_WAYPOINT_UPDATED / SUPER_TRACKING_CHANGED) + -- Resolve waypoint world position. Cached for static targets (user waypoints), + -- re-resolved every frame for moving targets (rares we're super-tracking). + local trackingOurRare = efTrackedVignetteGUID + and C_SuperTrack.GetSuperTrackedVignette + and C_SuperTrack.GetSuperTrackedVignette() == efTrackedVignetteGUID + if trackingOurRare then + cachedWPWorldX = nil + end if not cachedWPWorldX then local wpMapID, wpX, wpY if hasUserWP then @@ -896,15 +904,6 @@ loadingScreenFrame:RegisterEvent("CVAR_UPDATE") loadingScreenFrame:RegisterEvent("VIGNETTES_UPDATED") loadingScreenFrame:SetScript("OnEvent", function(_, event, isInitialLogin, isReloadingUI) if event == "VIGNETTES_UPDATED" then - -- Refresh cached position only when tracking a rare WE set (not game-tracked portals) - if efTrackedVignetteGUID then - local trackedGUID = C_SuperTrack.GetSuperTrackedVignette and C_SuperTrack.GetSuperTrackedVignette() - if trackedGUID and trackedGUID == efTrackedVignetteGUID then - cachedWPMapID = nil - cachedWPWorldX = nil - cachedWPWorldY = nil - end - end return end if event == "CVAR_UPDATE" then @@ -5337,6 +5336,7 @@ function MapSearch:ScanVignettes() local mapID = WorldMapFrame:GetMapID() if not mapID then return rares end + local playerMapID = GetBestMapForUnit("player") local guids = GetVignettes() if not guids then return rares end @@ -5346,7 +5346,11 @@ function MapSearch:ScanVignettes() if info and info.name and not info.isDead then local atlas = info.atlasName if atlas == "VignetteKill" or atlas == "VignetteKillElite" then + -- Try viewed map first, fall back to player's zone (sub-zone mismatch) local pos = GetVignettePosition(guid, mapID) + if not pos and playerMapID and playerMapID ~= mapID then + pos = GetVignettePosition(guid, playerMapID) + end if pos then rares[#rares + 1] = { name = info.name, @@ -5389,36 +5393,40 @@ function MapSearch:UpdateRareTracking() local mapID = WorldMapFrame:GetMapID() if not mapID then return end - -- Clear cache on zone change + -- Only show rare pins when viewing the player's zone + local playerMapID = GetBestMapForUnit("player") + if mapID ~= playerMapID then + self:ClearHighlight() + return + end + + -- Clear caches on zone change if mapID ~= rareTrackMapID then wipe(rareTrackCache) + wipe(rareDeadGUIDs) rareTrackMapID = mapID end - -- Merge fresh scan into cache (updates positions of in-range rares) + -- Merge fresh scan into cache, skipping GUIDs confirmed dead local rares = self:ScanVignettes() + local activeGUIDs = {} for _, rare in ipairs(rares) do - if not rare.isAggregate and rare.vignetteGUID then + if not rare.isAggregate and rare.vignetteGUID and not rareDeadGUIDs[rare.vignetteGUID] then + activeGUIDs[rare.vignetteGUID] = true + rare.inRange = true rareTrackCache[rare.vignetteGUID] = rare end end - -- Prune dead rares; keep out-of-range ones at last known position + -- Prune: if a rare was in range last update but is now gone, it died/despawned. + -- Mark as dead so it won't re-enter the cache from corpse vignettes. for guid, rare in pairs(rareTrackCache) do - local info = GetVignetteInfo and GetVignetteInfo(guid) - if info then - if info.isDead then + if not activeGUIDs[guid] then + if rare.inRange then rareTrackCache[guid] = nil - else - -- Still in range: refresh position - local pos = GetVignettePosition(guid, mapID) - if pos then - rare.x = pos.x - rare.y = pos.y - end + rareDeadGUIDs[guid] = true end end - -- info == nil means out of range, keep at last known position end -- Build display list from cache @@ -6944,6 +6952,15 @@ function MapSearch:ShowMultipleWaypoints(instances) end end + -- Hide leftover extra frames from previous calls with more instances + if self.extraPins then + for j = #instances, #self.extraPins do + if self.extraPins[j] then self.extraPins[j]:Hide() end + if self.extraHighlights and self.extraHighlights[j] then self.extraHighlights[j]:Hide() end + if self.extraIndicators and self.extraIndicators[j] then self.extraIndicators[j]:Hide() end + end + end + -- Auto-track on minimap if requested by navigate button if self.autoTrackNextPin then self.autoTrackNextPin = nil From 8ff8e61fbc223ef3ba6ddc312efef0f3434cd050 Mon Sep 17 00:00:00 2001 From: wowaddonmaker Date: Fri, 20 Mar 2026 22:06:20 -0400 Subject: [PATCH 4/9] Fix dot-notation buttonFrame, SafeCallMethod guards, and StaticLocations cleanup --- Highlight.lua | 2 +- Rescaler.lua | 4 +- StaticLocations.lua | 174 ++++++++++++++++++++++---------------------- 3 files changed, 90 insertions(+), 90 deletions(-) diff --git a/Highlight.lua b/Highlight.lua index f8cf047..8d3dc9c 100644 --- a/Highlight.lua +++ b/Highlight.lua @@ -281,7 +281,7 @@ function Highlight:UpdateGuide() -- Step 1 type: Highlight a button directly (like micro menu buttons) if step.buttonFrame then - local targetFrame = _G[step.buttonFrame] + local targetFrame = Utils.GetFrameByPath(step.buttonFrame) or _G[step.buttonFrame] if targetFrame and targetFrame:IsShown() then -- Check if user clicked it (frame that button opens is now visible) local nextStep = currentGuide.steps[currentStepIndex + 1] diff --git a/Rescaler.lua b/Rescaler.lua index 6440844..ad4182d 100644 --- a/Rescaler.lua +++ b/Rescaler.lua @@ -748,7 +748,7 @@ function Rescaler:Enter(mode) -- Dim backdrop local bg = GetOrCreateBackdrop() bg:Show() - bg:EnableKeyboard(true) + SafeCallMethod(bg, "EnableKeyboard", true) -- Preview results (fake rows so user sees the results area) local resultsAbove = (mode == "ui" and EasyFind.db.uiResultsAbove) @@ -903,7 +903,7 @@ function Rescaler:Exit(reopenOptions) donePanel = nil end if backdrop then - backdrop:EnableKeyboard(false) + SafeCallMethod(backdrop, "EnableKeyboard", false) backdrop:Hide() end diff --git a/StaticLocations.lua b/StaticLocations.lua index a1db488..4ae88cb 100644 --- a/StaticLocations.lua +++ b/StaticLocations.lua @@ -8,35 +8,35 @@ ns.STATIC_LOCATIONS = { }, [84] = { -- Stormwind City { name = "Innkeeper", category = "innkeeper", x = 0.6076649384171665, y = 0.7474117877548194, keywords = {"inn", "innkeeper", "hearth", "rest"} }, - { name = "Personal Bank", category = "bank", x = 0.6287458295533704, y = 0.7815457034658084, keywords = {"bank", "vault", "storage"} }, - { name = "Guild Vault", category = "bank", x = 0.6353951605252898, y = 0.799470813899537, keywords = {"bank", "vault", "storage"} }, + { name = "Bank", category = "bank", x = 0.6287458295533704, y = 0.7815457034658084, keywords = {"bank", "vault", "storage"} }, + { name = "Guild Vault", category = "guildbank", x = 0.6353951605252898, y = 0.799470813899537, keywords = {"bank", "vault", "storage"} }, { name = "PvP Mount Vendor", category = "vendor", x = 0.768484854436593, y = 0.6515890235802723, keywords = {"vendor", "merchant", "shop"} }, { name = "Legacy PvP Vendors", category = "pvpvendor", x = 0.7523755481674743, y = 0.6725438473103125, keywords = {"pvp", "honor", "conquest", "vendor"} }, { name = "Deeprun Tram", category = "tram", x = 0.6666872667606668, y = 0.3468250224608364, keywords = {"tram", "deeprun"} }, - { name = "Personal Bank", category = "bank", x = 0.6448791374651772, y = 0.2852704736326513, keywords = {"bank", "vault", "storage"} }, - { name = "Guild Vault", category = "bank", x = 0.657062636416047, y = 0.2719092533262282, keywords = {"bank", "vault", "storage"} }, + { name = "Bank", category = "bank", x = 0.6448791374651772, y = 0.2852704736326513, keywords = {"bank", "vault", "storage"} }, + { name = "Guild Vault", category = "guildbank", x = 0.657062636416047, y = 0.2719092533262282, keywords = {"bank", "vault", "storage"} }, { name = "Training Dummies", category = "trainingdummy", x = 0.7981892074620177, y = 0.6390044377338833, keywords = {"training", "dummy", "dummies", "target", "practice"} }, { name = "Chromie", category = "chromie", x = 0.5570498939412215, y = 0.1731803309699413, keywords = {"chromie", "timewalking", "time", "leveling"} }, { name = "Inscription Trainer", category = "prof_inscription", x = 0.4986017644405365, y = 0.7380831241607666, keywords = {"profession", "trainer", "inscription", "glyph"} }, { name = "Honor & Conquest Quartermasters", category = "quartermaster", x = 0.7564612627029419, y = 0.6661708354949951, keywords = {"quartermaster", "vendor", "gear", "pvp"} }, - { name = "Rogue", category = "classtrainer", x = 0.8000873923301697, y = 0.7070390582084656, keywords = {"trainer", "class", "rogue"} }, + { name = "Rogue Trainer", category = "classtrainer_rogue", x = 0.8000873923301697, y = 0.7070390582084656, keywords = {"trainer", "class", "rogue"} }, { name = "Trading Post", category = "tradingpost", x = 0.5099332928657532, y = 0.7184862494468689, keywords = {"tmog", "xmog", "trading post", "tender"} }, { name = "Innkeeper", category = "innkeeper", x = 0.6438179612159729, y = 0.3245589137077332, keywords = {"inn", "innkeeper", "hearth", "rest", "tavern"} }, { name = "Guild Master & Vendor", category = "guildservices", x = 0.644954264163971, y = 0.769818127155304, keywords = {"guild", "tabard", "registrar"} }, { name = "Stormwind Harbor", category = "boat", x = 0.4217675030231476, y = 0.4986781179904938, keywords = {"boat", "ship", "ferry", "travel"} }, - { name = "Dwarven District Bank", category = "bank", x = 0.6469756364822388, y = 0.2866156697273254, keywords = {"bank", "vault", "storage"} }, + { name = "Bank", category = "bank", x = 0.6469756364822388, y = 0.2866156697273254, keywords = {"bank", "vault", "storage"} }, { name = "Enchanting Trainer", category = "prof_enchanting", x = 0.531129002571106, y = 0.7417089939117432, keywords = {"profession", "trainer", "enchanting"} }, { name = "Battle Pet Trainer", category = "trainer", x = 0.6948685050010681, y = 0.2515559792518616, keywords = {"trainer", "class"} }, - { name = "Shaman", category = "classtrainer", x = 0.7872968912124634, y = 0.7087392210960388, keywords = {"trainer", "class", "shaman"} }, - { name = "Monk", category = "classtrainer", x = 0.8032164573669434, y = 0.7010206580162048, keywords = {"trainer", "class", "monk"} }, + { name = "Shaman Trainer", category = "classtrainer_shaman", x = 0.7872968912124634, y = 0.7087392210960388, keywords = {"trainer", "class", "shaman"} }, + { name = "Monk Trainer", category = "classtrainer_monk", x = 0.8032164573669434, y = 0.7010206580162048, keywords = {"trainer", "class", "monk"} }, { name = "Fishing Trainer", category = "prof_fishing", x = 0.5479564666748047, y = 0.695954442024231, keywords = {"profession", "trainer", "fishing"} }, { name = "Innkeeper", category = "innkeeper", x = 0.6086640954017639, y = 0.7483740448951721, keywords = {"inn", "innkeeper", "hearth", "rest", "tavern"} }, { name = "Transmogrification", category = "transmogrifier", x = 0.5037522315979004, y = 0.6054830551147461, keywords = {"transmog", "transmogrifier", "appearance"} }, - { name = "Demon Hunter", category = "classtrainer", x = 0.4008559286594391, y = 0.7816379070281982, keywords = {"trainer", "class", "demon hunter", "dh"} }, - { name = "Warlock", category = "classtrainer", x = 0.7952552437782288, y = 0.698750913143158, keywords = {"trainer", "class", "warlock"} }, - { name = "Trade District Bank", category = "bank", x = 0.6278526782989502, y = 0.7810840606689453, keywords = {"bank", "vault", "storage"} }, + { name = "Demon Hunter Trainer", category = "classtrainer_demonhunter", x = 0.4008559286594391, y = 0.7816379070281982, keywords = {"trainer", "class", "demon hunter", "dh"} }, + { name = "Warlock Trainer", category = "classtrainer_warlock", x = 0.7952552437782288, y = 0.698750913143158, keywords = {"trainer", "class", "warlock"} }, + { name = "Bank", category = "bank", x = 0.6278526782989502, y = 0.7810840606689453, keywords = {"bank", "vault", "storage"} }, { name = "Engineering Trainer", category = "prof_engineering", x = 0.6283552050590515, y = 0.3192913830280304, keywords = {"profession", "trainer", "engineering"} }, - { name = "Mage", category = "classtrainer", x = 0.8014620542526245, y = 0.6955747008323669, keywords = {"trainer", "class", "mage"} }, + { name = "Mage Trainer", category = "classtrainer_mage", x = 0.8014620542526245, y = 0.6955747008323669, keywords = {"trainer", "class", "mage"} }, { name = "Herbalism Trainer", category = "prof_herbalism", x = 0.5519677400588989, y = 0.8492006063461304, keywords = {"profession", "trainer", "herbalism", "herb"} }, { name = "Justice & Valor Quartermasters", category = "quartermaster", x = 0.7913053035736084, y = 0.6983883380889893, keywords = {"quartermaster", "vendor", "gear"} }, { name = "Dwarven District Stable Master", category = "stablemaster", x = 0.6721125841140747, y = 0.3772968649864197, keywords = {"stable", "pet"} }, @@ -45,19 +45,19 @@ ns.STATIC_LOCATIONS = { { name = "Old Town Stable Master", category = "stablemaster", x = 0.7780223488807678, y = 0.6729971766471863, keywords = {"stable", "pet"} }, { name = "Tailoring Trainer", category = "prof_tailoring", x = 0.540519118309021, y = 0.8164535164833069, keywords = {"profession", "trainer", "tailoring", "cloth"} }, { name = "Leatherworking Trainer", category = "prof_leatherworking", x = 0.7242438197135925, y = 0.6233569383621216, keywords = {"profession", "trainer", "leatherworking", "leather", "lw"} }, - { name = "Hunter", category = "classtrainer", x = 0.7912596464157104, y = 0.7139011025428772, keywords = {"trainer", "class", "hunter"} }, + { name = "Hunter Trainer", category = "classtrainer_hunter", x = 0.7912596464157104, y = 0.7139011025428772, keywords = {"trainer", "class", "hunter"} }, { name = "Mining Trainer", category = "prof_mining", x = 0.596139132976532, y = 0.3765117228031158, keywords = {"profession", "trainer", "mining", "ore"} }, - { name = "Warrior", category = "classtrainer", x = 0.8000873923301697, y = 0.7070390582084656, keywords = {"trainer", "class", "warrior"} }, - { name = "Paladin", category = "classtrainer", x = 0.7915494441986084, y = 0.694753885269165, keywords = {"trainer", "class", "paladin"} }, + { name = "Warrior Trainer", category = "classtrainer_warrior", x = 0.8000873923301697, y = 0.7070390582084656, keywords = {"trainer", "class", "warrior"} }, + { name = "Paladin Trainer", category = "classtrainer_paladin", x = 0.7915494441986084, y = 0.694753885269165, keywords = {"trainer", "class", "paladin"} }, { name = "Skinning Trainer", category = "prof_skinning", x = 0.7242438197135925, y = 0.6233569383621216, keywords = {"profession", "trainer", "skinning"} }, { name = "Jewelcrafting Trainer", category = "prof_jewelcrafting", x = 0.6338410973548889, y = 0.6161665916442871, keywords = {"profession", "trainer", "jewelcrafting", "gem", "jc"} }, { name = "Alchemy Trainer", category = "prof_alchemy", x = 0.5519677400588989, y = 0.8492006063461304, keywords = {"profession", "trainer", "alchemy", "potion", "flask"} }, { name = "Innkeeper", category = "innkeeper", x = 0.3970444798469544, y = 0.6654699444770813, keywords = {"inn", "innkeeper", "hearth", "rest", "tavern"} }, { name = "First Aid Trainer", category = "prof_firstaid", x = 0.5218287706375122, y = 0.4540798366069794, keywords = {"profession", "trainer", "first aid", "bandage"} }, - { name = "Druid", category = "classtrainer", x = 0.7922032475471497, y = 0.6870524883270264, keywords = {"trainer", "class", "druid"} }, + { name = "Druid Trainer", category = "classtrainer_druid", x = 0.7922032475471497, y = 0.6870524883270264, keywords = {"trainer", "class", "druid"} }, { name = "Barber", category = "barber", x = 0.6130751371383667, y = 0.6554045677185059, keywords = {"barber", "appearance", "haircut"} }, { name = "Blacksmithing Trainer", category = "prof_blacksmithing", x = 0.6366161704063416, y = 0.3700879216194153, keywords = {"profession", "trainer", "blacksmithing", "bs"} }, - { name = "Priest", category = "classtrainer", x = 0.7892311811447144, y = 0.6978873014450073, keywords = {"trainer", "class", "priest"} }, + { name = "Priest Trainer", category = "classtrainer_priest", x = 0.7892311811447144, y = 0.6978873014450073, keywords = {"trainer", "class", "priest"} }, { name = "Archaeology Trainer", category = "prof_archaeology", x = 0.8574860692024231, y = 0.2582310140132904, keywords = {"profession", "trainer", "archaeology", "artifact", "dig"} }, { name = "Riding", category = "ridingtrainer", x = 0.7736784219741821, y = 0.677047073841095, keywords = {"riding", "mount", "trainer"} }, { name = "Auction House", category = "auctionhouse", x = 0.6159144639968872, y = 0.7224318981170654, keywords = {"auction", "ah"} }, @@ -76,11 +76,11 @@ ns.STATIC_LOCATIONS = { { name = "Legacy PvP Vendors", category = "pvpvendor", x = 0.3907181451218901, y = 0.7160247475023476, keywords = {"pvp", "honor", "conquest", "vendor"} }, { name = "Barber", category = "barber", x = 0.405973110312379, y = 0.6073163816757083, keywords = {"barber", "appearance", "haircut"} }, { name = "Auction House", category = "auctionhouse", x = 0.6665740470612707, y = 0.3681707022076322, keywords = {"auction", "ah"} }, - { name = "Guild Vault", category = "bank", x = 0.6773102339443291, y = 0.5161664325660642, keywords = {"bank", "vault", "storage"} }, - { name = "Personal Bank", category = "bank", x = 0.6765155942130037, y = 0.5161664325660642, keywords = {"bank", "vault", "storage"} }, + { name = "Guild Vault", category = "guildbank", x = 0.6773102339443291, y = 0.5161664325660642, keywords = {"bank", "vault", "storage"} }, + { name = "Bank", category = "bank", x = 0.6765155942130037, y = 0.5161664325660642, keywords = {"bank", "vault", "storage"} }, { name = "Auction House", category = "auctionhouse", x = 0.5349350017752525, y = 0.7363798847906623, keywords = {"auction", "ah"} }, - { name = "Guild Vault", category = "bank", x = 0.490665680028789, y = 0.8229210799901849, keywords = {"bank", "vault", "storage"} }, - { name = "Personal Bank", category = "bank", x = 0.4886792057331894, y = 0.8235170427750655, keywords = {"bank", "vault", "storage"} }, + { name = "Guild Vault", category = "guildbank", x = 0.490665680028789, y = 0.8229210799901849, keywords = {"bank", "vault", "storage"} }, + { name = "Bank", category = "bank", x = 0.4886792057331894, y = 0.8235170427750655, keywords = {"bank", "vault", "storage"} }, { name = "Innkeeper", category = "innkeeper", x = 0.5422792184385153, y = 0.7836225401418597, keywords = {"inn", "innkeeper", "hearth", "rest"} }, { name = "Trading Post", category = "tradingpost", x = 0.4855013309342473, y = 0.7614878981268949, keywords = {"tmog", "xmog", "trading post", "tender"} }, { name = "Guild Vendor", category = "vendor", x = 0.4728320593471657, y = 0.7919164356998947, keywords = {"vendor", "merchant", "shop"} }, @@ -100,38 +100,38 @@ ns.STATIC_LOCATIONS = { { name = "Silvermoon City (TBC) Portal", category = "portal", x = 0.5534060347087141, y = 0.9048671105834006, keywords = {"portal", "teleport", "mage"} }, { name = "Chromie", category = "chromie", x = 0.4049942125152197, y = 0.7963960938417369, keywords = {"chromie", "timewalking", "time", "leveling"} }, { name = "Inscription Trainer", category = "prof_inscription", x = 0.5585606098175049, y = 0.5556620359420776, keywords = {"profession", "trainer", "inscription", "glyph"} }, - { name = "Rogue", category = "classtrainer", x = 0.7546135783195496, y = 0.4743320047855377, keywords = {"trainer", "class", "rogue"} }, + { name = "Rogue Trainer", category = "classtrainer_rogue", x = 0.7546135783195496, y = 0.4743320047855377, keywords = {"trainer", "class", "rogue"} }, { name = "Guild Master & Vendor", category = "guildservices", x = 0.4703111052513123, y = 0.7957051396369934, keywords = {"guild", "tabard", "registrar"} }, { name = "Leatherworking Trainer", category = "prof_leatherworking", x = 0.6030706763267517, y = 0.5507729649543762, keywords = {"profession", "trainer", "leatherworking", "leather"} }, { name = "Enchanting Trainer", category = "prof_enchanting", x = 0.5315502285957336, y = 0.4830420613288879, keywords = {"profession", "trainer", "enchanting"} }, { name = "Battle Pet Trainer", category = "trainer", x = 0.5256081223487854, y = 0.5926775932312012, keywords = {"trainer", "class"} }, - { name = "Shaman", category = "classtrainer", x = 0.7341176867485046, y = 0.4310666918754578, keywords = {"trainer", "class", "shaman"} }, - { name = "Monk", category = "classtrainer", x = 0.7567005753517151, y = 0.4360591769218445, keywords = {"trainer", "class", "monk"} }, + { name = "Shaman Trainer", category = "classtrainer_shaman", x = 0.7341176867485046, y = 0.4310666918754578, keywords = {"trainer", "class", "shaman"} }, + { name = "Monk Trainer", category = "classtrainer_monk", x = 0.7567005753517151, y = 0.4360591769218445, keywords = {"trainer", "class", "monk"} }, { name = "Fishing Trainer", category = "prof_fishing", x = 0.6658633947372437, y = 0.4195621311664581, keywords = {"profession", "trainer", "fishing"} }, { name = "Transmogrification", category = "transmogrifier", x = 0.5770488977432251, y = 0.6514323353767395, keywords = {"transmog", "transmogrifier", "appearance"} }, - { name = "Warlock", category = "classtrainer", x = 0.7461960315704346, y = 0.4737443327903748, keywords = {"trainer", "class", "warlock"} }, + { name = "Warlock Trainer", category = "classtrainer_warlock", x = 0.7461960315704346, y = 0.4737443327903748, keywords = {"trainer", "class", "warlock"} }, { name = "Archaeology Trainer", category = "prof_archaeology", x = 0.4905875325202942, y = 0.705586850643158, keywords = {"profession", "trainer", "archaeology", "artifact", "dig"} }, { name = "Engineering Trainer", category = "prof_engineering", x = 0.5698520541191101, y = 0.5631312131881714, keywords = {"profession", "trainer", "engineering"} }, { name = "Eastern Zeppelin Tower", category = "zeppelin", x = 0.5106810927391052, y = 0.5545409917831421, keywords = {"zeppelin", "airship", "travel"} }, { name = "Herbalism Trainer", category = "prof_herbalism", x = 0.5429980158805847, y = 0.5090776681900024, keywords = {"profession", "trainer", "herbalism", "herb"} }, { name = "Cooking Trainer", category = "prof_cooking", x = 0.5672934055328369, y = 0.6152087450027466, keywords = {"profession", "trainer", "cooking", "food"} }, { name = "Training Dummies", category = "trainingdummy", x = 0.640222430229187, y = 0.3269507586956024, keywords = {"training", "dummy", "dummies", "target", "practice"} }, - { name = "Mage", category = "classtrainer", x = 0.7469552159309387, y = 0.4360162913799286, keywords = {"trainer", "class", "mage"} }, + { name = "Mage Trainer", category = "classtrainer_mage", x = 0.7469552159309387, y = 0.4360162913799286, keywords = {"trainer", "class", "mage"} }, { name = "Stable Master", category = "stablemaster", x = 0.6213608980178833, y = 0.3527404367923737, keywords = {"stable", "pet"} }, - { name = "Paladin", category = "classtrainer", x = 0.73198401927948, y = 0.4739259481430054, keywords = {"trainer", "class", "paladin"} }, - { name = "Hunter", category = "classtrainer", x = 0.7391543388366699, y = 0.4358006715774536, keywords = {"trainer", "class", "hunter"} }, - { name = "Priest", category = "classtrainer", x = 0.7267191410064697, y = 0.4691919684410095, keywords = {"trainer", "class", "priest"} }, - { name = "Warrior", category = "classtrainer", x = 0.7375099062919617, y = 0.471106231212616, keywords = {"trainer", "class", "warrior"} }, + { name = "Paladin Trainer", category = "classtrainer_paladin", x = 0.73198401927948, y = 0.4739259481430054, keywords = {"trainer", "class", "paladin"} }, + { name = "Hunter Trainer", category = "classtrainer_hunter", x = 0.7391543388366699, y = 0.4358006715774536, keywords = {"trainer", "class", "hunter"} }, + { name = "Priest Trainer", category = "classtrainer_priest", x = 0.7267191410064697, y = 0.4691919684410095, keywords = {"trainer", "class", "priest"} }, + { name = "Warrior Trainer", category = "classtrainer_warrior", x = 0.7375099062919617, y = 0.471106231212616, keywords = {"trainer", "class", "warrior"} }, { name = "Blacksmithing Trainer", category = "prof_blacksmithing", x = 0.7482906579971313, y = 0.3529510498046875, keywords = {"profession", "trainer", "blacksmithing"} }, { name = "Skinning Trainer", category = "prof_skinning", x = 0.6030706763267517, y = 0.5507729649543762, keywords = {"profession", "trainer", "skinning"} }, { name = "Alchemy Trainer", category = "prof_alchemy", x = 0.5554092526435852, y = 0.4657505452632904, keywords = {"profession", "trainer", "alchemy", "potion", "flask"} }, { name = "Mining Trainer", category = "prof_mining", x = 0.723098635673523, y = 0.3490014374256134, keywords = {"profession", "trainer", "mining", "ore"} }, { name = "First Aid Trainer", category = "prof_firstaid", x = 0.3850615918636322, y = 0.864109456539154, keywords = {"profession", "trainer", "first aid", "bandage"} }, { name = "Battlemasters", category = "battlemasters", x = 0.7444835305213928, y = 0.4525915086269379, keywords = {"pvp", "battlemaster", "arena", "battleground", "bg"} }, - { name = "Druid", category = "classtrainer", x = 0.7293332815170288, y = 0.432799369096756, keywords = {"trainer", "class", "druid"} }, + { name = "Druid Trainer", category = "classtrainer_druid", x = 0.7293332815170288, y = 0.432799369096756, keywords = {"trainer", "class", "druid"} }, { name = "Jewelcrafting Trainer", category = "prof_jewelcrafting", x = 0.7248741984367371, y = 0.3430972099304199, keywords = {"profession", "trainer", "jewelcrafting", "gem"} }, { name = "Western Zeppelin Tower", category = "zeppelin", x = 0.4452389180660248, y = 0.6449190378189087, keywords = {"zeppelin", "airship", "travel"} }, - { name = "Demon Hunter", category = "classtrainer", x = 0.4876908957958221, y = 0.5688652396202087, keywords = {"trainer", "class", "demon hunter", "dh"} }, + { name = "Demon Hunter Trainer", category = "classtrainer_demonhunter", x = 0.4876908957958221, y = 0.5688652396202087, keywords = {"trainer", "class", "demon hunter", "dh"} }, { name = "Riding", category = "ridingtrainer", x = 0.613136351108551, y = 0.3460921943187714, keywords = {"riding", "mount", "trainer"} }, { name = "Tailoring Trainer", category = "prof_tailoring", x = 0.5984829664230347, y = 0.589553952217102, keywords = {"profession", "trainer", "tailoring", "cloth"} }, { name = "Resonance Crystal Quartermaster", category = "quartermaster", x = 0.505689027556145, y = 0.4027231529896209, keywords = {"quartermaster", "vendor", "gear"} }, @@ -141,37 +141,37 @@ ns.STATIC_LOCATIONS = { }, [87] = { -- Ironforge { name = "Inscription Trainer", category = "prof_inscription", x = 0.601420521736145, y = 0.4407650828361511, keywords = {"profession", "trainer", "inscription", "glyph"} }, - { name = "Rogue", category = "classtrainer", x = 0.5190926194190979, y = 0.1489546447992325, keywords = {"trainer", "class", "rogue"} }, + { name = "Rogue Trainer", category = "classtrainer_rogue", x = 0.5190926194190979, y = 0.1489546447992325, keywords = {"trainer", "class", "rogue"} }, { name = "Guild Master & Vendor", category = "guildservices", x = 0.3577685058116913, y = 0.8563575744628906, keywords = {"guild", "tabard", "registrar"} }, { name = "Leatherworking Trainer", category = "prof_leatherworking", x = 0.3971395492553711, y = 0.3331452906131744, keywords = {"profession", "trainer", "leatherworking", "leather", "lw"} }, { name = "Enchanting Trainer", category = "prof_enchanting", x = 0.6108319163322449, y = 0.4444193840026856, keywords = {"profession", "trainer", "enchanting"} }, { name = "Tailoring Trainer", category = "prof_tailoring", x = 0.434314638376236, y = 0.2850033044815064, keywords = {"profession", "trainer", "tailoring", "cloth"} }, - { name = "Shaman", category = "classtrainer", x = 0.5537391304969788, y = 0.2906508445739746, keywords = {"trainer", "class", "shaman"} }, - { name = "Monk", category = "classtrainer", x = 0.1945307105779648, y = 0.5303891897201538, keywords = {"trainer", "class", "monk"} }, + { name = "Shaman Trainer", category = "classtrainer_shaman", x = 0.5537391304969788, y = 0.2906508445739746, keywords = {"trainer", "class", "shaman"} }, + { name = "Monk Trainer", category = "classtrainer_monk", x = 0.1945307105779648, y = 0.5303891897201538, keywords = {"trainer", "class", "monk"} }, { name = "Fishing Trainer", category = "prof_fishing", x = 0.4785294234752655, y = 0.05433798208832741, keywords = {"profession", "trainer", "fishing"} }, - { name = "Mage", category = "classtrainer", x = 0.2692385017871857, y = 0.1095127537846565, keywords = {"trainer", "class", "mage"} }, - { name = "Warlock", category = "classtrainer", x = 0.501970112323761, y = 0.06783315539360046, keywords = {"trainer", "class", "warlock"} }, + { name = "Mage Trainer", category = "classtrainer_mage", x = 0.2692385017871857, y = 0.1095127537846565, keywords = {"trainer", "class", "mage"} }, + { name = "Warlock Trainer", category = "classtrainer_warlock", x = 0.501970112323761, y = 0.06783315539360046, keywords = {"trainer", "class", "warlock"} }, { name = "Archaeology Trainer", category = "prof_archaeology", x = 0.7558303475379944, y = 0.1112584099173546, keywords = {"profession", "trainer", "archaeology", "artifact", "dig"} }, { name = "Engineering Trainer", category = "prof_engineering", x = 0.6787666082382202, y = 0.4365341365337372, keywords = {"profession", "trainer", "engineering"} }, { name = "Herbalism Trainer", category = "prof_herbalism", x = 0.5559383034706116, y = 0.5920326709747314, keywords = {"profession", "trainer", "herbalism", "herb"} }, { name = "Cooking Trainer", category = "prof_cooking", x = 0.5957422852516174, y = 0.3763981759548187, keywords = {"profession", "trainer", "cooking", "food"} }, - { name = "Hunter", category = "classtrainer", x = 0.6831146478652954, y = 0.8601873517036438, keywords = {"trainer", "class", "hunter"} }, + { name = "Hunter Trainer", category = "classtrainer_hunter", x = 0.6831146478652954, y = 0.8601873517036438, keywords = {"trainer", "class", "hunter"} }, { name = "Battlemaster", category = "battlemasters", x = 0.7034778594970703, y = 0.897300660610199, keywords = {"pvp", "battlemaster", "arena", "battleground", "bg"} }, { name = "Auction House", category = "auctionhouse", x = 0.2504501938819885, y = 0.7356813549995422, keywords = {"auction", "ah"} }, - { name = "Warrior", category = "classtrainer", x = 0.6831146478652954, y = 0.8601873517036438, keywords = {"trainer", "class", "warrior"} }, - { name = "Paladin", category = "classtrainer", x = 0.2692385017871857, y = 0.1095127537846565, keywords = {"trainer", "class", "paladin"} }, + { name = "Warrior Trainer", category = "classtrainer_warrior", x = 0.6831146478652954, y = 0.8601873517036438, keywords = {"trainer", "class", "warrior"} }, + { name = "Paladin Trainer", category = "classtrainer_paladin", x = 0.2692385017871857, y = 0.1095127537846565, keywords = {"trainer", "class", "paladin"} }, { name = "Skinning Trainer", category = "prof_skinning", x = 0.3971395492553711, y = 0.3331452906131744, keywords = {"profession", "trainer", "skinning"} }, { name = "Alchemy Trainer", category = "prof_alchemy", x = 0.6681411266326904, y = 0.5482500791549683, keywords = {"profession", "trainer", "alchemy", "potion", "flask"} }, { name = "Mining Trainer", category = "prof_mining", x = 0.5095180869102478, y = 0.2574237585067749, keywords = {"profession", "trainer", "mining", "ore"} }, { name = "First Aid Trainer", category = "prof_firstaid", x = 0.5559383034706116, y = 0.5920326709747314, keywords = {"profession", "trainer", "first aid", "bandage"} }, { name = "Jewelcrafting Trainer", category = "prof_jewelcrafting", x = 0.5095180869102478, y = 0.2574237585067749, keywords = {"profession", "trainer", "jewelcrafting", "gem", "jc"} }, { name = "Blacksmithing Trainer", category = "prof_blacksmithing", x = 0.5015999674797058, y = 0.4316450357437134, keywords = {"profession", "trainer", "blacksmithing", "bs"} }, - { name = "Druid", category = "classtrainer", x = 0.08458348363637924, y = 0.9706183671951294, keywords = {"trainer", "class", "druid"} }, + { name = "Druid Trainer", category = "classtrainer_druid", x = 0.08458348363637924, y = 0.9706183671951294, keywords = {"trainer", "class", "druid"} }, { name = "Barber", category = "barber", x = 0.2576498985290527, y = 0.5121992230415344, keywords = {"barber", "appearance", "haircut"} }, { name = "Stable Master", category = "stablemaster", x = 0.6936774253845215, y = 0.8357920050621033, keywords = {"stable", "pet"} }, - { name = "Priest", category = "classtrainer", x = 0.2692385017871857, y = 0.1095127537846565, keywords = {"trainer", "class", "priest"} }, + { name = "Priest Trainer", category = "classtrainer_priest", x = 0.2692385017871857, y = 0.1095127537846565, keywords = {"trainer", "class", "priest"} }, { name = "Innkeeper", category = "innkeeper", x = 0.2010810524225235, y = 0.533050000667572, keywords = {"inn", "innkeeper", "hearth", "rest", "tavern"} }, - { name = "Bank of Ironforge", category = "bank", x = 0.3514816761016846, y = 0.6115733981132507, keywords = {"bank", "vault", "storage"} }, + { name = "Bank", category = "bank", x = 0.3514816761016846, y = 0.6115733981132507, keywords = {"bank", "vault", "storage"} }, { name = "Mailbox", category = "mailbox", x = 0.2111763656139374, y = 0.5239894986152649, keywords = {"mail", "mailbox"} }, { name = "Deeprun Tram", category = "tram", x = 0.7697482787140112, y = 0.5135215968859295, keywords = {"tram", "deeprun"} }, { name = "Decor Specialist", category = "decor", x = 0.2433828642934768, y = 0.4352018766676832, keywords = {"decor", "decoration", "housing", "furniture"} }, @@ -179,7 +179,7 @@ ns.STATIC_LOCATIONS = { [88] = { -- Thunder Bluff { name = "Innkeeper", category = "innkeeper", x = 0.4569665789604187, y = 0.641059160232544, keywords = {"inn", "innkeeper", "hearth", "rest", "tavern"} }, { name = "Stable Master", category = "stablemaster", x = 0.4482096433639526, y = 0.6038814783096313, keywords = {"stable", "pet"} }, - { name = "Rogue", category = "classtrainer", x = 0.59992516040802, y = 0.8470568656921387, keywords = {"trainer", "class", "rogue"} }, + { name = "Rogue Trainer", category = "classtrainer_rogue", x = 0.59992516040802, y = 0.8470568656921387, keywords = {"trainer", "class", "rogue"} }, { name = "Tailoring Trainer", category = "prof_tailoring", x = 0.4309437274932861, y = 0.4400903582572937, keywords = {"profession", "trainer", "tailoring", "cloth"} }, { name = "Skinning Trainer", category = "prof_skinning", x = 0.445969432592392, y = 0.4290848076343536, keywords = {"profession", "trainer", "skinning"} }, { name = "Mining Trainer", category = "prof_mining", x = 0.3464803099632263, y = 0.5736576914787292, keywords = {"profession", "trainer", "mining", "ore"} }, @@ -188,22 +188,22 @@ ns.STATIC_LOCATIONS = { { name = "Jewelcrafting Trainer", category = "prof_jewelcrafting", x = 0.3503701686859131, y = 0.5376694202423096, keywords = {"profession", "trainer", "jewelcrafting", "gem"} }, { name = "Inscription Trainer", category = "prof_inscription", x = 0.2903009653091431, y = 0.2146790027618408, keywords = {"profession", "trainer", "inscription", "glyph"} }, { name = "Guild Master & Vendor", category = "guildservices", x = 0.372778445482254, y = 0.6416770219802856, keywords = {"guild", "tabard", "registrar"} }, - { name = "Hunter", category = "classtrainer", x = 0.6045043468475342, y = 0.8138888478279114, keywords = {"trainer", "class", "hunter"} }, + { name = "Hunter Trainer", category = "classtrainer_hunter", x = 0.6045043468475342, y = 0.8138888478279114, keywords = {"trainer", "class", "hunter"} }, { name = "Herbalism Trainer", category = "prof_herbalism", x = 0.4964621365070343, y = 0.413474828004837, keywords = {"profession", "trainer", "herbalism", "herb"} }, { name = "Auction House", category = "auctionhouse", x = 0.3972314894199371, y = 0.5005820989608765, keywords = {"auction", "ah"} }, - { name = "Warrior", category = "classtrainer", x = 0.6045043468475342, y = 0.8138888478279114, keywords = {"trainer", "class", "warrior"} }, - { name = "Paladin", category = "classtrainer", x = 0.620454728603363, y = 0.7965409159660339, keywords = {"trainer", "class", "paladin"} }, - { name = "Shaman", category = "classtrainer", x = 0.2284181416034699, y = 0.2005379796028137, keywords = {"trainer", "class", "shaman"} }, - { name = "Monk", category = "classtrainer", x = 0.2218656688928604, y = 0.1819817125797272, keywords = {"trainer", "class", "monk"} }, + { name = "Warrior Trainer", category = "classtrainer_warrior", x = 0.6045043468475342, y = 0.8138888478279114, keywords = {"trainer", "class", "warrior"} }, + { name = "Paladin Trainer", category = "classtrainer_paladin", x = 0.620454728603363, y = 0.7965409159660339, keywords = {"trainer", "class", "paladin"} }, + { name = "Shaman Trainer", category = "classtrainer_shaman", x = 0.2284181416034699, y = 0.2005379796028137, keywords = {"trainer", "class", "shaman"} }, + { name = "Monk Trainer", category = "classtrainer_monk", x = 0.2218656688928604, y = 0.1819817125797272, keywords = {"trainer", "class", "monk"} }, { name = "Alchemy Trainer", category = "prof_alchemy", x = 0.4688589572906494, y = 0.3385436534881592, keywords = {"profession", "trainer", "alchemy", "potion", "flask"} }, - { name = "Mage", category = "classtrainer", x = 0.3076971471309662, y = 0.3035368323326111, keywords = {"trainer", "class", "mage"} }, + { name = "Mage Trainer", category = "classtrainer_mage", x = 0.3076971471309662, y = 0.3035368323326111, keywords = {"trainer", "class", "mage"} }, { name = "First Aid Trainer", category = "prof_firstaid", x = 0.3029099404811859, y = 0.2106630206108093, keywords = {"profession", "trainer", "first aid", "bandage"} }, { name = "Fishing Trainer", category = "prof_fishing", x = 0.5610012412071228, y = 0.4589618444442749, keywords = {"profession", "trainer", "fishing"} }, { name = "Engineering Trainer", category = "prof_engineering", x = 0.3614219725131989, y = 0.5982116460800171, keywords = {"profession", "trainer", "engineering"} }, - { name = "Druid", category = "classtrainer", x = 0.7450819611549377, y = 0.2979888617992401, keywords = {"trainer", "class", "druid"} }, + { name = "Druid Trainer", category = "classtrainer_druid", x = 0.7450819611549377, y = 0.2979888617992401, keywords = {"trainer", "class", "druid"} }, { name = "Archaeology Trainer", category = "prof_archaeology", x = 0.7503945827484131, y = 0.2809877097606659, keywords = {"profession", "trainer", "archaeology", "artifact", "dig"} }, { name = "Enchanting Trainer", category = "prof_enchanting", x = 0.4512883126735687, y = 0.3830786943435669, keywords = {"profession", "trainer", "enchanting"} }, - { name = "Priest", category = "classtrainer", x = 0.3076971471309662, y = 0.3035368323326111, keywords = {"trainer", "class", "priest"} }, + { name = "Priest Trainer", category = "classtrainer_priest", x = 0.3076971471309662, y = 0.3035368323326111, keywords = {"trainer", "class", "priest"} }, { name = "Blacksmithing Trainer", category = "prof_blacksmithing", x = 0.3945163488388062, y = 0.5601218938827515, keywords = {"profession", "trainer", "blacksmithing"} }, { name = "Bank", category = "bank", x = 0.4718787968158722, y = 0.5860607624053955, keywords = {"bank", "vault", "storage"} }, { name = "Mailbox", category = "mailbox", x = 0.4525092840194702, y = 0.5943952798843384, keywords = {"mail", "mailbox"} }, @@ -211,42 +211,42 @@ ns.STATIC_LOCATIONS = { }, [89] = { -- Darnassus { name = "Inscription Trainer", category = "prof_inscription", x = 0.5610339641571045, y = 0.3240092992782593, keywords = {"profession", "trainer", "inscription", "glyph"} }, - { name = "Rogue", category = "classtrainer", x = 0.382161945104599, y = 0.3335497379302979, keywords = {"trainer", "class", "rogue"} }, + { name = "Rogue Trainer", category = "classtrainer_rogue", x = 0.382161945104599, y = 0.3335497379302979, keywords = {"trainer", "class", "rogue"} }, { name = "Guild Master & Vendor", category = "guildservices", x = 0.64167320728302, y = 0.3779489099979401, keywords = {"guild", "tabard", "registrar"} }, { name = "Leatherworking Trainer", category = "prof_leatherworking", x = 0.6051824688911438, y = 0.3680183589458466, keywords = {"profession", "trainer", "leatherworking", "leather", "lw"} }, { name = "Enchanting Trainer", category = "prof_enchanting", x = 0.567731499671936, y = 0.3100880086421967, keywords = {"profession", "trainer", "enchanting"} }, { name = "Tailoring Trainer", category = "prof_tailoring", x = 0.5971101522445679, y = 0.3747355341911316, keywords = {"profession", "trainer", "tailoring", "cloth"} }, - { name = "Shaman", category = "classtrainer", x = 0.4395330548286438, y = 0.7888287901878357, keywords = {"trainer", "class", "shaman"} }, - { name = "Monk", category = "classtrainer", x = 0.4719819128513336, y = 0.6022868156433105, keywords = {"trainer", "class", "monk"} }, + { name = "Shaman Trainer", category = "classtrainer_shaman", x = 0.4395330548286438, y = 0.7888287901878357, keywords = {"trainer", "class", "shaman"} }, + { name = "Monk Trainer", category = "classtrainer_monk", x = 0.4719819128513336, y = 0.6022868156433105, keywords = {"trainer", "class", "monk"} }, { name = "Fishing Trainer", category = "prof_fishing", x = 0.4905998408794403, y = 0.6118044853210449, keywords = {"profession", "trainer", "fishing"} }, - { name = "Mage", category = "classtrainer", x = 0.3764275312423706, y = 0.8041823506355286, keywords = {"trainer", "class", "mage"} }, - { name = "Warlock", category = "classtrainer", x = 0.4993959367275238, y = 0.1595237851142883, keywords = {"trainer", "class", "warlock"} }, + { name = "Mage Trainer", category = "classtrainer_mage", x = 0.3764275312423706, y = 0.8041823506355286, keywords = {"trainer", "class", "mage"} }, + { name = "Warlock Trainer", category = "classtrainer_warlock", x = 0.4993959367275238, y = 0.1595237851142883, keywords = {"trainer", "class", "warlock"} }, { name = "Archaeology Trainer", category = "prof_archaeology", x = 0.4263090193271637, y = 0.8335782289505005, keywords = {"profession", "trainer", "archaeology", "artifact", "dig"} }, - { name = "The Bank", category = "bank", x = 0.4385271966457367, y = 0.5122512578964233, keywords = {"bank", "vault", "storage"} }, + { name = "Bank", category = "bank", x = 0.4385271966457367, y = 0.5122512578964233, keywords = {"bank", "vault", "storage"} }, { name = "Herbalism Trainer", category = "prof_herbalism", x = 0.4919048845767975, y = 0.6887502074241638, keywords = {"profession", "trainer", "herbalism", "herb"} }, { name = "Cooking Trainer", category = "prof_cooking", x = 0.4990169703960419, y = 0.3660706877708435, keywords = {"profession", "trainer", "cooking", "food"} }, - { name = "Hunter", category = "classtrainer", x = 0.439339280128479, y = 0.2797083556652069, keywords = {"trainer", "class", "hunter"} }, + { name = "Hunter Trainer", category = "classtrainer_hunter", x = 0.439339280128479, y = 0.2797083556652069, keywords = {"trainer", "class", "hunter"} }, { name = "Battlemaster", category = "battlemasters", x = 0.5636013150215149, y = 0.469264417886734, keywords = {"pvp", "battlemaster", "arena", "battleground", "bg"} }, { name = "Auction House", category = "auctionhouse", x = 0.5509998798370361, y = 0.586335301399231, keywords = {"auction", "ah"} }, - { name = "Warrior", category = "classtrainer", x = 0.5891916751861572, y = 0.4991542994976044, keywords = {"trainer", "class", "warrior"} }, - { name = "Paladin", category = "classtrainer", x = 0.4380285739898682, y = 0.7856951951980591, keywords = {"trainer", "class", "paladin"} }, + { name = "Warrior Trainer", category = "classtrainer_warrior", x = 0.5891916751861572, y = 0.4991542994976044, keywords = {"trainer", "class", "warrior"} }, + { name = "Paladin Trainer", category = "classtrainer_paladin", x = 0.4380285739898682, y = 0.7856951951980591, keywords = {"trainer", "class", "paladin"} }, { name = "Skinning Trainer", category = "prof_skinning", x = 0.6042606830596924, y = 0.3730811476707459, keywords = {"profession", "trainer", "skinning"} }, { name = "Alchemy Trainer", category = "prof_alchemy", x = 0.53958660364151, y = 0.3784358203411102, keywords = {"profession", "trainer", "alchemy", "potion", "flask"} }, { name = "Mining Trainer", category = "prof_mining", x = 0.5015771389007568, y = 0.3309343457221985, keywords = {"profession", "trainer", "mining", "ore"} }, { name = "First Aid Trainer", category = "prof_firstaid", x = 0.5177118182182312, y = 0.3061926662921906, keywords = {"profession", "trainer", "first aid", "bandage"} }, { name = "Jewelcrafting Trainer", category = "prof_jewelcrafting", x = 0.5416538715362549, y = 0.3085660338401794, keywords = {"profession", "trainer", "jewelcrafting", "gem", "jc"} }, { name = "Blacksmithing Trainer", category = "prof_blacksmithing", x = 0.5688128471374512, y = 0.5258578658103943, keywords = {"profession", "trainer", "blacksmithing", "bs"} }, - { name = "Druid", category = "classtrainer", x = 0.4007770419120789, y = 0.2712371349334717, keywords = {"trainer", "class", "druid"} }, + { name = "Druid Trainer", category = "classtrainer_druid", x = 0.4007770419120789, y = 0.2712371349334717, keywords = {"trainer", "class", "druid"} }, { name = "Engineering Trainer", category = "prof_engineering", x = 0.496679037809372, y = 0.3277494311332703, keywords = {"profession", "trainer", "engineering"} }, { name = "Stable Master", category = "stablemaster", x = 0.4318239986896515, y = 0.2895421087741852, keywords = {"stable", "pet"} }, - { name = "Priest", category = "classtrainer", x = 0.4303822219371796, y = 0.7842159271240234, keywords = {"trainer", "class", "priest"} }, + { name = "Priest Trainer", category = "classtrainer_priest", x = 0.4303822219371796, y = 0.7842159271240234, keywords = {"trainer", "class", "priest"} }, { name = "Innkeeper", category = "innkeeper", x = 0.6267794370651245, y = 0.3225485384464264, keywords = {"inn", "innkeeper", "hearth", "rest", "tavern"} }, { name = "Mailbox", category = "mailbox", x = 0.4494788348674774, y = 0.5086278319358826, keywords = {"mail", "mailbox"} }, }, [90] = { -- Undercity { name = "Innkeeper", category = "innkeeper", x = 0.6798121929168701, y = 0.3726189136505127, keywords = {"inn", "innkeeper", "hearth", "rest", "tavern"} }, { name = "Herbalism Trainer", category = "prof_herbalism", x = 0.5460033416748047, y = 0.4996925890445709, keywords = {"profession", "trainer", "herbalism", "herb"} }, - { name = "Locksmith", category = "classtrainer", x = 0.8547717332839966, y = 0.5908311009407043, keywords = {"trainer", "class", "warlock"} }, + { name = "Warlock Trainer", category = "classtrainer_warlock", x = 0.8547717332839966, y = 0.5908311009407043, keywords = {"trainer", "class", "warlock"} }, { name = "Cooking Trainer", category = "prof_cooking", x = 0.6238527894020081, y = 0.439919501543045, keywords = {"profession", "trainer", "cooking", "food"} }, { name = "Inscription Trainer", category = "prof_inscription", x = 0.6122032403945923, y = 0.5864292979240417, keywords = {"profession", "trainer", "inscription", "glyph"} }, { name = "Stable Master", category = "stablemaster", x = 0.6737987399101257, y = 0.380820631980896, keywords = {"stable", "pet"} }, @@ -263,7 +263,7 @@ ns.STATIC_LOCATIONS = { { name = "First Aid Trainer", category = "prof_firstaid", x = 0.7358880043029785, y = 0.5597472786903381, keywords = {"profession", "trainer", "first aid", "bandage"} }, { name = "Enchanting Trainer", category = "prof_enchanting", x = 0.6181081533432007, y = 0.6083453297615051, keywords = {"profession", "trainer", "enchanting"} }, { name = "Bat Handler", category = "flightmaster", x = 0.6272369623184204, y = 0.4874920547008514, keywords = {"flight", "fly", "taxi", "fp"} }, - { name = "Druid", category = "classtrainer", x = 0.5531388521194458, y = 0.5025806427001953, keywords = {"trainer", "class", "druid"} }, + { name = "Druid Trainer", category = "classtrainer_druid", x = 0.5531388521194458, y = 0.5025806427001953, keywords = {"trainer", "class", "druid"} }, { name = "Archaeology Trainer", category = "prof_archaeology", x = 0.7542334794998169, y = 0.3764782547950745, keywords = {"profession", "trainer", "archaeology", "artifact", "dig"} }, { name = "Barber", category = "barber", x = 0.7063195705413818, y = 0.47016641497612, keywords = {"barber", "appearance", "haircut"} }, { name = "Engineering Trainer", category = "prof_engineering", x = 0.7606632113456726, y = 0.7332465648651123, keywords = {"profession", "trainer", "engineering"} }, @@ -274,53 +274,53 @@ ns.STATIC_LOCATIONS = { }, [103] = { -- The Exodar { name = "Inscription Trainer", category = "prof_inscription", x = 0.3961431086063385, y = 0.3940853476524353, keywords = {"profession", "trainer", "inscription", "glyph"} }, - { name = "Rogue", category = "classtrainer", x = 0.5149957537651062, y = 0.8673011064529419, keywords = {"trainer", "class", "rogue"} }, + { name = "Rogue Trainer", category = "classtrainer_rogue", x = 0.5149957537651062, y = 0.8673011064529419, keywords = {"trainer", "class", "rogue"} }, { name = "Guild Master & Vendor", category = "guildservices", x = 0.5333545804023743, y = 0.6955084204673767, keywords = {"guild", "tabard", "registrar"} }, { name = "Leatherworking Trainer", category = "prof_leatherworking", x = 0.6644139289855957, y = 0.7504408955574036, keywords = {"profession", "trainer", "leatherworking", "leather", "lw"} }, { name = "Enchanting Trainer", category = "prof_enchanting", x = 0.4031462073326111, y = 0.3917857706546783, keywords = {"profession", "trainer", "enchanting"} }, { name = "Tailoring Trainer", category = "prof_tailoring", x = 0.6410404443740845, y = 0.6852360367774963, keywords = {"profession", "trainer", "tailoring", "cloth"} }, { name = "Stable Master", category = "stablemaster", x = 0.6030951738357544, y = 0.2587911486625671, keywords = {"stable", "pet"} }, - { name = "Monk", category = "classtrainer", x = 0.5466530323028564, y = 0.8223327994346619, keywords = {"trainer", "class", "monk"} }, + { name = "Monk Trainer", category = "classtrainer_monk", x = 0.5466530323028564, y = 0.8223327994346619, keywords = {"trainer", "class", "monk"} }, { name = "Fishing Trainer", category = "prof_fishing", x = 0.3035022914409638, y = 0.1654299646615982, keywords = {"profession", "trainer", "fishing"} }, - { name = "Mage", category = "classtrainer", x = 0.4670200645923615, y = 0.6228672862052917, keywords = {"trainer", "class", "mage"} }, - { name = "Warlock", category = "classtrainer", x = 0.4886894822120667, y = 0.1091349571943283, keywords = {"trainer", "class", "warlock"} }, + { name = "Mage Trainer", category = "classtrainer_mage", x = 0.4670200645923615, y = 0.6228672862052917, keywords = {"trainer", "class", "mage"} }, + { name = "Warlock Trainer", category = "classtrainer_warlock", x = 0.4886894822120667, y = 0.1091349571943283, keywords = {"trainer", "class", "warlock"} }, { name = "Archaeology Trainer", category = "prof_archaeology", x = 0.3364339470863342, y = 0.6636090278625488, keywords = {"profession", "trainer", "archaeology", "artifact", "dig"} }, { name = "Engineering Trainer", category = "prof_engineering", x = 0.5464122295379639, y = 0.9220924973487854, keywords = {"profession", "trainer", "engineering"} }, { name = "Innkeeper", category = "innkeeper", x = 0.5959975719451904, y = 0.2153959572315216, keywords = {"inn", "innkeeper", "hearth", "rest", "tavern"} }, { name = "Herbalism Trainer", category = "prof_herbalism", x = 0.2778580784797669, y = 0.6251523494720459, keywords = {"profession", "trainer", "herbalism", "herb"} }, { name = "Cooking Trainer", category = "prof_cooking", x = 0.5565381050109863, y = 0.2681139707565308, keywords = {"profession", "trainer", "cooking", "food"} }, - { name = "Hunter", category = "classtrainer", x = 0.4654114842414856, y = 0.893653929233551, keywords = {"trainer", "class", "hunter"} }, + { name = "Hunter Trainer", category = "classtrainer_hunter", x = 0.4654114842414856, y = 0.893653929233551, keywords = {"trainer", "class", "hunter"} }, { name = "Bank", category = "bank", x = 0.4577451944351196, y = 0.4388139843940735, keywords = {"bank", "vault", "storage"} }, - { name = "Warrior", category = "classtrainer", x = 0.551427960395813, y = 0.8298094868659973, keywords = {"trainer", "class", "warrior"} }, + { name = "Warrior Trainer", category = "classtrainer_warrior", x = 0.551427960395813, y = 0.8298094868659973, keywords = {"trainer", "class", "warrior"} }, { name = "Blacksmithing Trainer", category = "prof_blacksmithing", x = 0.6123679280281067, y = 0.8962647914886475, keywords = {"profession", "trainer", "blacksmithing", "bs"} }, { name = "Skinning Trainer", category = "prof_skinning", x = 0.6580739617347717, y = 0.748767077922821, keywords = {"profession", "trainer", "skinning"} }, { name = "Alchemy Trainer", category = "prof_alchemy", x = 0.2824005782604218, y = 0.6154590249061584, keywords = {"profession", "trainer", "alchemy", "potion", "flask"} }, { name = "Mining Trainer", category = "prof_mining", x = 0.5945789217948914, y = 0.8713036179542542, keywords = {"profession", "trainer", "mining", "ore"} }, { name = "First Aid Trainer", category = "prof_firstaid", x = 0.3892354667186737, y = 0.2218526154756546, keywords = {"profession", "trainer", "first aid", "bandage"} }, { name = "Battlemasters", category = "battlemasters", x = 0.2893082201480866, y = 0.5546520352363586, keywords = {"pvp", "battlemaster", "arena", "battleground", "bg"} }, - { name = "Druid", category = "classtrainer", x = 0.4060790538787842, y = 0.9406250715255737, keywords = {"trainer", "class", "druid"} }, - { name = "Shaman", category = "classtrainer", x = 0.3088023662567139, y = 0.3388830423355103, keywords = {"trainer", "class", "shaman"} }, - { name = "Paladin", category = "classtrainer", x = 0.3885733485221863, y = 0.8070628046989441, keywords = {"trainer", "class", "paladin"} }, - { name = "Priest", category = "classtrainer", x = 0.3971840143203735, y = 0.5191040635108948, keywords = {"trainer", "class", "priest"} }, + { name = "Druid Trainer", category = "classtrainer_druid", x = 0.4060790538787842, y = 0.9406250715255737, keywords = {"trainer", "class", "druid"} }, + { name = "Shaman Trainer", category = "classtrainer_shaman", x = 0.3088023662567139, y = 0.3388830423355103, keywords = {"trainer", "class", "shaman"} }, + { name = "Paladin Trainer", category = "classtrainer_paladin", x = 0.3885733485221863, y = 0.8070628046989441, keywords = {"trainer", "class", "paladin"} }, + { name = "Priest Trainer", category = "classtrainer_priest", x = 0.3971840143203735, y = 0.5191040635108948, keywords = {"trainer", "class", "priest"} }, { name = "Auction House", category = "auctionhouse", x = 0.6312944293022156, y = 0.5836717486381531, keywords = {"auction", "ah"} }, { name = "Jewelcrafting Trainer", category = "prof_jewelcrafting", x = 0.45197394490242, y = 0.2498501837253571, keywords = {"profession", "trainer", "jewelcrafting", "gem", "jc"} }, { name = "Mailbox", category = "mailbox", x = 0.5121573805809021, y = 0.4311224222183228, keywords = {"mail", "mailbox"} }, }, [110] = { -- Silvermoon City - { name = "Rogue", category = "classtrainer", x = 0.8007701635360718, y = 0.5120617747306824, keywords = {"trainer", "class", "rogue"} }, + { name = "Rogue Trainer", category = "classtrainer_rogue", x = 0.8007701635360718, y = 0.5120617747306824, keywords = {"trainer", "class", "rogue"} }, { name = "Silvermoon City, Mailbox", category = "mailbox", x = 0.879634439945221, y = 0.5083430409431458, keywords = {"mail", "mailbox"} }, { name = "Guild Master & Vendor", category = "guildservices", x = 0.7795149683952332, y = 0.8292056918144226, keywords = {"guild", "tabard", "registrar"} }, - { name = "Hunter", category = "classtrainer", x = 0.8344984650611877, y = 0.2720524668693543, keywords = {"trainer", "class", "hunter"} }, - { name = "Warrior", category = "classtrainer", x = 0.8094464540481567, y = 0.3768416345119476, keywords = {"trainer", "class", "warrior"} }, - { name = "Paladin", category = "classtrainer", x = 0.9178013801574707, y = 0.3753415048122406, keywords = {"trainer", "class", "paladin"} }, - { name = "Shaman", category = "classtrainer", x = 0.7174996733665466, y = 0.557788074016571, keywords = {"trainer", "class", "shaman"} }, - { name = "Monk", category = "classtrainer", x = 0.8296730518341064, y = 0.3984853625297546, keywords = {"trainer", "class", "monk"} }, + { name = "Hunter Trainer", category = "classtrainer_hunter", x = 0.8344984650611877, y = 0.2720524668693543, keywords = {"trainer", "class", "hunter"} }, + { name = "Warrior Trainer", category = "classtrainer_warrior", x = 0.8094464540481567, y = 0.3768416345119476, keywords = {"trainer", "class", "warrior"} }, + { name = "Paladin Trainer", category = "classtrainer_paladin", x = 0.9178013801574707, y = 0.3753415048122406, keywords = {"trainer", "class", "paladin"} }, + { name = "Shaman Trainer", category = "classtrainer_shaman", x = 0.7174996733665466, y = 0.557788074016571, keywords = {"trainer", "class", "shaman"} }, + { name = "Monk Trainer", category = "classtrainer_monk", x = 0.8296730518341064, y = 0.3984853625297546, keywords = {"trainer", "class", "monk"} }, { name = "Alchemy Trainer", category = "prof_alchemy", x = 0.6706629991531372, y = 0.1810963451862335, keywords = {"profession", "trainer", "alchemy", "potion", "flask"} }, - { name = "Mage", category = "classtrainer", x = 0.5826275944709778, y = 0.1925737410783768, keywords = {"trainer", "class", "mage"} }, - { name = "Druid", category = "classtrainer", x = 0.7140853404998779, y = 0.557202160358429, keywords = {"trainer", "class", "druid"} }, + { name = "Mage Trainer", category = "classtrainer_mage", x = 0.5826275944709778, y = 0.1925737410783768, keywords = {"trainer", "class", "mage"} }, + { name = "Druid Trainer", category = "classtrainer_druid", x = 0.7140853404998779, y = 0.557202160358429, keywords = {"trainer", "class", "druid"} }, { name = "Innkeeper", category = "innkeeper", x = 0.80031418800354, y = 0.5956547260284424, keywords = {"inn", "innkeeper", "hearth", "rest", "tavern"} }, - { name = "Warlock", category = "classtrainer", x = 0.7610905766487122, y = 0.4362403452396393, keywords = {"trainer", "class", "warlock"} }, - { name = "Priest", category = "classtrainer", x = 0.5428659319877625, y = 0.2686304748058319, keywords = {"trainer", "class", "priest"} }, + { name = "Warlock Trainer", category = "classtrainer_warlock", x = 0.7610905766487122, y = 0.4362403452396393, keywords = {"trainer", "class", "warlock"} }, + { name = "Priest Trainer", category = "classtrainer_priest", x = 0.5428659319877625, y = 0.2686304748058319, keywords = {"trainer", "class", "priest"} }, { name = "Innkeeper", category = "innkeeper", x = 0.80031418800354, y = 0.5956547260284424, keywords = {"inn", "innkeeper", "hearth", "rest", "tavern"} }, { name = "Stable Master", category = "stablemaster", x = 0.8282662630081177, y = 0.3097585141658783, keywords = {"stable", "pet"} }, { name = "Mailbox", category = "mailbox", x = 0.879634439945221, y = 0.5083430409431458, keywords = {"mail", "mailbox"} }, @@ -415,8 +415,8 @@ ns.STATIC_LOCATIONS = { { name = "Trading Post", category = "tradingpost", x = 0.4481041519808515, y = 0.5564175485241932, keywords = {"tmog", "xmog", "trading post", "tender"} }, { name = "Limited Time Trading Post", category = "tradingpost", x = 0.4769078164914132, y = 0.5201866703974088, keywords = {"tmog", "xmog", "trading post", "tender"} }, { name = "Innkeeper", category = "innkeeper", x = 0.4487001156877553, y = 0.4673510012048201, keywords = {"inn", "innkeeper", "hearth", "rest"} }, - { name = "Personal Bank", category = "bank", x = 0.5344711616237862, y = 0.4476868296660796, keywords = {"bank", "vault", "storage"} }, - { name = "Guild Vault", category = "bank", x = 0.5446903626858112, y = 0.4358468471675652, keywords = {"bank", "vault", "storage"} }, + { name = "Bank", category = "bank", x = 0.5344711616237862, y = 0.4476868296660796, keywords = {"bank", "vault", "storage"} }, + { name = "Guild Vault", category = "guildbank", x = 0.5446903626858112, y = 0.4358468471675652, keywords = {"bank", "vault", "storage"} }, { name = "Auction House", category = "auctionhouse", x = 0.5645526467105717, y = 0.4785488209149129, keywords = {"auction", "ah"} }, { name = "Gear Crafting Vendor", category = "vendor", x = 0.5768161835555375, y = 0.5618194942432952, keywords = {"vendor", "merchant", "shop"} }, { name = "Barber", category = "barber", x = 0.5863460635979354, y = 0.5226981300360082, keywords = {"barber", "appearance", "haircut"} }, From e841f6cad15d488a7d1f9469b269391b54814752 Mon Sep 17 00:00:00 2001 From: wowaddonmaker Date: Fri, 20 Mar 2026 22:06:23 -0400 Subject: [PATCH 5/9] Add Great Vault entry and bypass EncounterJournal protected SetTab via selectedTab --- Database.lua | 4 +++- UI.lua | 61 ++++++++++++++++++++++++++++++---------------------- 2 files changed, 38 insertions(+), 27 deletions(-) diff --git a/Database.lua b/Database.lua index 50bd875..8a445e1 100644 --- a/Database.lua +++ b/Database.lua @@ -1387,7 +1387,9 @@ function Database:BuildUIDatabase() buttonFrame = "EJMicroButton", steps = {{ buttonFrame = "EJMicroButton" }}, children = { - { name = "Journeys", keywords = {"journeys", "journey", "adventure journeys"}, category = "Adventure Guide", steps = {{ waitForFrame = "EncounterJournal", tabIndex = 1, text = "Click the Journeys tab" }} }, + { name = "Journeys", keywords = {"journeys", "journey", "adventure journeys"}, category = "Adventure Guide", steps = {{ waitForFrame = "EncounterJournal", tabIndex = 1, text = "Click the Journeys tab" }}, children = { + { name = "Great Vault (Rewards)", keywords = {"great vault", "vault", "weekly rewards", "weekly chest", "rewards"}, category = "Adventure Guide", icon = { file = 1121272, coords = { 0.2007, 0.2407, 0.5456, 0.5862 } }, steps = {{ buttonFrame = "EncounterJournalInstanceSelect.GreatVaultButton" }} }, + }}, { name = "Traveler's Log", keywords = {"traveler", "travelers log", "traveler log", "travel log"}, category = "Adventure Guide", steps = {{ waitForFrame = "EncounterJournal", tabIndex = 2, text = "Click the Traveler's Log tab" }} }, { name = "Suggested Content", keywords = {"suggested", "suggested content", "recommendations"}, category = "Adventure Guide", steps = {{ waitForFrame = "EncounterJournal", tabIndex = 3, text = "Click the Suggested Content tab" }} }, { name = "Dungeons (Journal)", keywords = {"dungeon journal", "dungeon guide", "dungeon encounters", "dungeon bosses"}, category = "Adventure Guide", steps = {{ waitForFrame = "EncounterJournal", tabIndex = 4, text = "Click the Dungeons tab" }} }, diff --git a/UI.lua b/UI.lua index a0bb98c..603d1bb 100644 --- a/UI.lua +++ b/UI.lua @@ -160,7 +160,15 @@ local function SetRowIcon(btn, kind, value, iconSize) if kind == "atlas" then btn.icon:SetAtlas(value) elseif kind == "file" or kind == "path" then - btn.icon:SetTexture(value) + if type(value) == "table" and value.file then + btn.icon:SetTexture(value.file) + if value.coords then + local c = value.coords + btn.icon:SetTexCoord(c[1], c[2], c[3], c[4]) + end + else + btn.icon:SetTexture(value) + end elseif kind == "hidden" then btn.icon:Hide() return @@ -787,8 +795,8 @@ function UI:CreateSearchFrame() -- Keyboard capture frame for navigating results without editbox focus navFrame = CreateFrame("Frame", nil, searchFrame) navFrame:SetSize(1, 1) - navFrame:EnableKeyboard(false) - navFrame:SetPropagateKeyboardInput(false) + Utils.SafeCallMethod(navFrame, "EnableKeyboard", false) + Utils.SafeCallMethod(navFrame, "SetPropagateKeyboardInput", false) local function HandleNavKeyDown(key) if key == "LSHIFT" or key == "RSHIFT" or key == "LCTRL" or key == "RCTRL" @@ -831,7 +839,7 @@ function UI:CreateSearchFrame() SetToolbarFocus(#controls) elseif toolbarFocus == 2 then ClearToolbarFocus() - navFrame:EnableKeyboard(false) + Utils.SafeCallMethod(navFrame, "EnableKeyboard", false) searchFrame.editBox:SetFocus() else SetToolbarFocus(toolbarFocus - 1) @@ -852,7 +860,7 @@ function UI:CreateSearchFrame() local controls = GetToolbarControls() if toolbarFocus == 1 then ClearToolbarFocus() - navFrame:EnableKeyboard(false) + Utils.SafeCallMethod(navFrame, "EnableKeyboard", false) searchFrame.editBox:SetFocus() elseif toolbarFocus >= #controls then SetToolbarFocus(1) @@ -878,7 +886,7 @@ function UI:CreateSearchFrame() else selectedIndex = 0 toggleFocused = false - navFrame:EnableKeyboard(false) + Utils.SafeCallMethod(navFrame, "EnableKeyboard", false) if searchFrame.StopKeyRepeat then searchFrame.StopKeyRepeat() end UI:UpdateSelectionHighlight(true) end @@ -910,7 +918,7 @@ function UI:CreateSearchFrame() editBox:HookScript("OnKeyDown", function(self, key) if key ~= "TAB" then return end self:ClearFocus() - navFrame:EnableKeyboard(true) + Utils.SafeCallMethod(navFrame, "EnableKeyboard", true) if IsShiftKeyDown() then SetToolbarFocus(1) else @@ -3302,10 +3310,10 @@ function UI:UpdateSelectionHighlight(skipRefocus) if searchFrame.editBox:HasFocus() then searchFrame.editBox:ClearFocus() end - navFrame:EnableKeyboard(true) + Utils.SafeCallMethod(navFrame, "EnableKeyboard", true) else local wasNavigating = navFrame:IsKeyboardEnabled() - navFrame:EnableKeyboard(false) + Utils.SafeCallMethod(navFrame, "EnableKeyboard", false) if searchFrame.StopKeyRepeat then searchFrame.StopKeyRepeat() end if wasNavigating and not skipRefocus and not searchFrame.editBox:HasFocus() then searchFrame.editBox:SetFocus() @@ -3529,19 +3537,6 @@ function UI:DirectOpen(data) -- If final step is highlight-only, execute all but the last, then highlight it. local executeCount = finalStepNavigable and totalSteps or (totalSteps - 1) - -- Stop before any step that would call protected functions (taint). - -- EncounterJournal:SetTab() is a protected C++ method triggered by EJ tab clicks. - -- Execute all steps up to (but not including) the first protected step, - -- then hand off to the guided highlight for the rest. - for i = 1, executeCount do - local s = steps[i] - if s.waitForFrame == "EncounterJournal" and s.tabIndex then - executeCount = i - 1 - finalStepNavigable = false - break - end - end - -- If there's nothing to execute programmatically (single highlight-only step), -- just start the normal guide. if executeCount == 0 then @@ -3559,11 +3554,25 @@ function UI:DirectOpen(data) local step = steps[i] if step.buttonFrame then - local stepFrame = _G[step.buttonFrame] + -- EncounterJournal: set selectedTab BEFORE opening so Blizzard's + -- own init calls SetTab with our value (clean call stack, no taint) + if step.buttonFrame == "EJMicroButton" then + local nextStep = steps[i + 1] + if nextStep and nextStep.waitForFrame == "EncounterJournal" and nextStep.tabIndex then + EncounterJournal_LoadUI() + EncounterJournal.selectedTab = nextStep.tabIndex + ShowUIPanel(EncounterJournal) + -- Skip the tab step, continue from the step after it + executeFrom(i + 2) + return + end + end + local stepFrame = Utils.GetFrameByPath(step.buttonFrame) or _G[step.buttonFrame] if stepFrame then ClickButton(stepFrame) end end if step.waitForFrame and step.tabIndex then + local resync = false if step.waitForFrame == "CharacterFrame" then if needsCurrencyResync and step.tabIndex == 3 then @@ -3586,7 +3595,7 @@ function UI:DirectOpen(data) executeFrom(resume) end) return - else + elseif step.waitForFrame ~= "EncounterJournal" then ClickButton(Highlight:GetTabButton(step.waitForFrame, step.tabIndex)) end end @@ -3663,9 +3672,9 @@ function UI:DirectOpen(data) end end - -- All navigable steps executed; highlight the final step if needed + -- Hand off remaining steps to the guided highlight if not finalStepNavigable and Highlight then - Highlight:StartGuideAtStep(data, totalSteps) + Highlight:StartGuideAtStep(data, executeCount + 1) end end From d9e92892b5e5d2292ea0eaec21b1853868e8003b Mon Sep 17 00:00:00 2001 From: wowaddonmaker Date: Fri, 20 Mar 2026 22:06:27 -0400 Subject: [PATCH 6/9] Fix rare tracking, move auto-track to Map tab, sync filter toggle with options --- MapSearch.lua | 85 ++++++++++++++++++++++++++++++++++++++++++++------- Options.lua | 45 ++++++++++++++++----------- 2 files changed, 101 insertions(+), 29 deletions(-) diff --git a/MapSearch.lua b/MapSearch.lua index 1aec162..7d8916b 100644 --- a/MapSearch.lua +++ b/MapSearch.lua @@ -1147,11 +1147,26 @@ local CATEGORY_ICONS = { raid = { file = 1121272, coords = { 0.2056, 0.2397, 0.4986, 0.5327 } }, delve = { file = 1121272, coords = { 0.0104, 0.0541, 0.3990, 0.4427 } }, bank = 136453, + guildbank = 136453, + personalbank = 136453, auctionhouse = 136452, innkeeper = 136458, trainer = 136463, proftrainer = 136463, classtrainer = { file = 131016, coords = { 0.000, 0.250, 0.375, 0.500 } }, + classtrainer_deathknight = "atlas:classicon-deathknight", + classtrainer_demonhunter = "atlas:classicon-demonhunter", + classtrainer_druid = "atlas:classicon-druid", + classtrainer_evoker = "atlas:classicon-evoker", + classtrainer_hunter = "atlas:classicon-hunter", + classtrainer_mage = "atlas:classicon-mage", + classtrainer_monk = "atlas:classicon-monk", + classtrainer_paladin = "atlas:classicon-paladin", + classtrainer_priest = "atlas:classicon-priest", + classtrainer_rogue = "atlas:classicon-rogue", + classtrainer_shaman = "atlas:classicon-shaman", + classtrainer_warlock = "atlas:classicon-warlock", + classtrainer_warrior = "atlas:classicon-warrior", prof_alchemy = "Interface\\Icons\\Trade_Alchemy", prof_blacksmithing = "Interface\\Icons\\Trade_BlackSmithing", prof_cooking = "Interface\\Icons\\INV_Misc_Food_15", @@ -1403,7 +1418,7 @@ function MapSearch:CreateFilterDropdown(globalName, options, dbKey, toggleBtn, a -- Preserve and restore it so the user can keep toggling. local savedKb = navFrame and navFrame:IsKeyboardEnabled() row:Click() - if savedKb and navFrame then navFrame:EnableKeyboard(true) end + if savedKb and navFrame then Utils.SafeCallMethod(navFrame, "EnableKeyboard", true) end end end @@ -1829,6 +1844,9 @@ function MapSearch:CreateSearchFrame() EasyFind.db.alwaysShowRares = not EasyFind.db.alwaysShowRares UpdateAutoTrackColor() MapSearch:UpdateRareTracking() + if ns.optionsFrame and ns.optionsFrame.rareTrackCheckbox then + ns.optionsFrame.rareTrackCheckbox:SetChecked(EasyFind.db.alwaysShowRares) + end end) trackBtn:SetScript("OnEnter", function(self) GameTooltip:SetOwner(self, "ANCHOR_RIGHT") @@ -1844,6 +1862,47 @@ function MapSearch:CreateSearchFrame() trackBtn:SetScript("OnLeave", GameTooltip_Hide) localFilterDropdown:HookScript("OnShow", UpdateAutoTrackColor) + + -- "Experimental" flashing tag on the Rares label + local expTag = CreateFrame("Frame", nil, localFilterDropdown) + expTag:EnableMouse(true) + expTag:SetFrameStrata("TOOLTIP") + local expText = expTag:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") + expText:SetPoint("CENTER") + expText:SetText("NEW") + expText:SetTextColor(1, 1, 1) + expText:SetShadowColor(0.3, 0.9, 1.0, 1) + expText:SetShadowOffset(1, -1) + local textW = expText:GetStringWidth() + 4 + expTag:SetSize(textW, 14) + for _, region in pairs({raresRow:GetRegions()}) do + if region.GetText and region:GetText() == "Rares" then + expTag:SetPoint("LEFT", region, "RIGHT", 3, 0) + break + end + end + -- Pulsing glow behind text + local expGlow = expTag:CreateTexture(nil, "BACKGROUND") + expGlow:SetPoint("CENTER") + expGlow:SetSize(textW + 24, 24) + expGlow:SetAtlas("collections-newglow") + expGlow:SetVertexColor(0.3, 0.85, 1.0, 0.5) + expGlow:SetBlendMode("ADD") + -- Glow pulse animation (text stays at 100%, only glow pulses) + local glowPulse = expGlow:CreateAnimationGroup() + glowPulse:SetLooping("BOUNCE") + local flash = glowPulse:CreateAnimation("Alpha") + flash:SetFromAlpha(0.8) + flash:SetToAlpha(0.1) + flash:SetDuration(1.5) + glowPulse:Play() + expTag:SetScript("OnEnter", function(self) + GameTooltip:SetOwner(self, "ANCHOR_TOPLEFT", 0, 16) + GameTooltip:SetText("New Feature") + GameTooltip:AddLine("Rare mob tracking is new and still being refined. If you encounter any issues or have suggestions, please share feedback on CurseForge or GitHub.", 1, 1, 1, true) + GameTooltip:Show() + end) + expTag:SetScript("OnLeave", GameTooltip_Hide) end searchFrame.filterBtn = localFilterBtn @@ -2295,8 +2354,8 @@ function MapSearch:CreateSearchFrame() -- Keyboard capture frame for navigating results without editbox focus navFrame = CreateFrame("Frame", nil, searchFrame) navFrame:SetSize(1, 1) - navFrame:EnableKeyboard(false) - navFrame:SetPropagateKeyboardInput(false) + Utils.SafeCallMethod(navFrame, "EnableKeyboard", false) + Utils.SafeCallMethod(navFrame, "SetPropagateKeyboardInput", false) local function HandleNavKeyDown(key) if key == "LSHIFT" or key == "RSHIFT" or key == "LCTRL" or key == "RCTRL" @@ -2372,7 +2431,7 @@ function MapSearch:CreateSearchFrame() -- Ctrl+Tab: switch between local and global search bars ClearToolbarFocus() selectedResultIndex = 0 - navFrame:EnableKeyboard(false) + Utils.SafeCallMethod(navFrame, "EnableKeyboard", false) if isGlobalSearch then MapSearch:FocusLocalSearch() else @@ -2446,7 +2505,7 @@ function MapSearch:CreateSearchFrame() else selectedResultIndex = 0 navBtnFocused = false - navFrame:EnableKeyboard(false) + Utils.SafeCallMethod(navFrame, "EnableKeyboard", false) if MapSearch.StopKeyRepeat then MapSearch.StopKeyRepeat() end MapSearch:UpdateSelectionHighlight(true) end @@ -2484,14 +2543,14 @@ function MapSearch:CreateSearchFrame() local controls = GetToolbarControls() if #controls > 0 then self:ClearFocus() - navFrame:EnableKeyboard(true) + Utils.SafeCallMethod(navFrame, "EnableKeyboard", true) SetToolbarFocus(#controls) end else local controls = GetToolbarControls() if #controls > 0 then self:ClearFocus() - navFrame:EnableKeyboard(true) + Utils.SafeCallMethod(navFrame, "EnableKeyboard", true) SetToolbarFocus(1) elseif resultsFrame and resultsFrame:IsShown() and selectedResultIndex == 0 then MapSearch:MoveSelection(1) @@ -5384,7 +5443,10 @@ function MapSearch:ScanVignettes() end function MapSearch:UpdateRareTracking() - if not EasyFind.db.alwaysShowRares then return end + if not EasyFind.db.alwaysShowRares then + self:ClearHighlight() + return + end if not WorldMapFrame or not WorldMapFrame:IsShown() then return end -- Don't override active search local editBox = searchFrame and searchFrame.editBox @@ -6419,7 +6481,8 @@ function MapSearch:HideResults() self._lastResults = nil if MapSearch.StopKeyRepeat then MapSearch.StopKeyRepeat() end if MapSearch.ClearToolbarFocus then MapSearch.ClearToolbarFocus() end - if navFrame then navFrame:EnableKeyboard(false) end + if navFrame then Utils.SafeCallMethod(navFrame, "EnableKeyboard", false) end + if not resultsFrame then return end resultsFrame:Hide() end @@ -6514,7 +6577,7 @@ function MapSearch:UpdateSelectionHighlight(skipRefocus) if eb and eb:HasFocus() then eb:ClearFocus() end - navFrame:EnableKeyboard(true) + Utils.SafeCallMethod(navFrame, "EnableKeyboard", true) -- Keyboard preview: show pin for selected result local resultRow = resultButtons[selectedResultIndex] if resultRow and resultRow.data then @@ -6548,7 +6611,7 @@ function MapSearch:UpdateSelectionHighlight(skipRefocus) end end local wasNavigating = navFrame:IsKeyboardEnabled() - navFrame:EnableKeyboard(false) + Utils.SafeCallMethod(navFrame, "EnableKeyboard", false) if MapSearch.StopKeyRepeat then MapSearch.StopKeyRepeat() end if wasNavigating and not skipRefocus and eb and not eb:HasFocus() then eb:SetFocus() diff --git a/Options.lua b/Options.lua index 1b7fc47..21d31dd 100644 --- a/Options.lua +++ b/Options.lua @@ -508,6 +508,7 @@ function Options:Initialize() -- Create the main options frame (fixed size) optionsFrame = CreateFrame("Frame", "EasyFindOptionsFrame", UIParent, "BackdropTemplate") + ns.optionsFrame = optionsFrame optionsFrame:SetSize(FRAME_W, FRAME_H) if EasyFind.db.optionsPosition then local pos = EasyFind.db.optionsPosition @@ -698,7 +699,7 @@ function Options:Initialize() keybindBtn.waitingForKey = false keybindBtn:SetText(GetCurrentKeybindText(action)) keybindBtn:UnlockHighlight() - keybindBtn:EnableKeyboard(false) + Utils.SafeCallMethod(keybindBtn, "EnableKeyboard", false) keybindBtn:SetScript("OnKeyDown", nil) end @@ -709,7 +710,7 @@ function Options:Initialize() keybindBtn.waitingForKey = true keybindBtn:SetText("Press a key...") keybindBtn:LockHighlight() - keybindBtn:EnableKeyboard(true) + Utils.SafeCallMethod(keybindBtn, "EnableKeyboard", true) keybindBtn:SetScript("OnKeyDown", function(self, key) if key == "LSHIFT" or key == "RSHIFT" or key == "LCTRL" or key == "RCTRL" or key == "LALT" or key == "RALT" then @@ -827,20 +828,8 @@ function Options:Initialize() end) optionsFrame.minimapBtnCheckbox = minimapBtnCheckbox - local rareTrackCheckbox = CreateCheckbox(sec3, "RareTrack", "Always Show Rares on Map", - "When enabled, active rare mobs are always displayed as pins on the world map without needing to search.\n\nThis can also be toggled from the \"Rares\" search result row.") - rareTrackCheckbox:SetPoint("TOPLEFT", loginMessageCheckbox, "BOTTOMLEFT", 0, -4) - rareTrackCheckbox:SetChecked(EasyFind.db.alwaysShowRares or false) - rareTrackCheckbox:SetScript("OnClick", function(self) - EasyFind.db.alwaysShowRares = self:GetChecked() - if ns.MapSearch then - ns.MapSearch:UpdateRareTracking() - end - end) - optionsFrame.rareTrackCheckbox = rareTrackCheckbox - local indicatorLabel = sec3:CreateFontString(nil, "OVERLAY", "GameFontNormal") - indicatorLabel:SetPoint("TOPLEFT", rareTrackCheckbox, "BOTTOMLEFT", 4, -10) + indicatorLabel:SetPoint("TOPLEFT", loginMessageCheckbox, "BOTTOMLEFT", 4, -10) indicatorLabel:SetText("Indicator Style:") local indicatorChoices = {"EasyFind Arrow", "Classic Quest Arrow", "Minimap Player Arrow", "Low-res Gauntlet", "HD Gauntlet"} @@ -1182,9 +1171,25 @@ function Options:Initialize() end) optionsFrame.globalNavCheckbox = globalNavCheckbox + local rareTrackCheckbox = CreateCheckbox(sec2, "RareTrack", "Auto-track Rares", + "When enabled, active rare mobs are always displayed as pins on the world map without needing to search.\n\nThis can also be toggled from the filter dropdown on the zone search bar.") + rareTrackCheckbox:SetPoint("TOPLEFT", mapSpeedBox, "BOTTOMLEFT", 0, -4) + rareTrackCheckbox:SetChecked(EasyFind.db.alwaysShowRares or false) + rareTrackCheckbox:SetScript("OnClick", function(self) + EasyFind.db.alwaysShowRares = self:GetChecked() + if ns.MapSearch then + ns.MapSearch:UpdateRareTracking() + if ns.MapSearch.UpdateAutoTrackLabel then + ns.MapSearch:UpdateAutoTrackLabel() + end + end + end) + optionsFrame.rareTrackCheckbox = rareTrackCheckbox + local resizeMapBtn = CreateFrame("Button", nil, sec2, "UIPanelButtonTemplate") resizeMapBtn:SetSize(160, 22) - resizeMapBtn:SetPoint("BOTTOMLEFT", sec2, "BOTTOMLEFT", 8, 32) + resizeMapBtn:SetPoint("RIGHT", sec2, "RIGHT", -8, 0) + resizeMapBtn:SetPoint("TOP", mapEnableCheckbox, "TOP", 0, 0) resizeMapBtn:SetText("Resize Map Search") resizeMapBtn:SetScript("OnClick", function() if ns.Rescaler then ns.Rescaler:Enter("map") end @@ -1209,7 +1214,7 @@ function Options:Initialize() tooltip = "Map search results appear above the bar instead of below.\nApplies to both local and global map search bars.", callback = function() if ns.MapSearch and ns.MapSearch.RefreshResultsAnchor then ns.MapSearch:RefreshResultsAnchor() end end }, }, nil, FLYOUT_W) - searchBarGroup:SetPoint("TOPLEFT", mapSpeedBox, "BOTTOMLEFT", 0, -8) + searchBarGroup:SetPoint("TOPLEFT", rareTrackCheckbox, "BOTTOMLEFT", 0, -2) searchBarGroup:SetPoint("RIGHT", sec2, "RIGHT", -8, 0) searchBarGroup.label:SetWidth(85) searchBarGroup.label:SetJustifyH("LEFT") @@ -1338,7 +1343,7 @@ function Options:Initialize() end) mapControls = { - resizeMapBtn, resetMapBtn, resetMapPosBtn, localNavCheckbox, globalNavCheckbox, + resizeMapBtn, resetMapBtn, resetMapPosBtn, localNavCheckbox, globalNavCheckbox, rareTrackCheckbox, searchBarGroup, mapPinGroup, minimapGroup, automationGroup } UpdateMapToggleVisual() @@ -1718,6 +1723,7 @@ function Options:DoResetAll() EasyFind.db.localSearchFilters = { instances = true, travel = true, services = true } EasyFind.db.uiSearchFilters = { ui = true, mounts = false, toys = false, pets = false, map = false } EasyFind.db.uiMapSearchLocal = true + EasyFind.db.alwaysShowRares = false EasyFind.db.optionsPosition = nil if optionsFrame then @@ -1775,6 +1781,7 @@ function Options:DoResetAll() optionsFrame.loginMessageCheckbox:SetChecked(true) optionsFrame.uiResultsAboveCheckbox:SetChecked(false) optionsFrame.minimapBtnCheckbox:SetChecked(true) + if optionsFrame.rareTrackCheckbox then optionsFrame.rareTrackCheckbox:SetChecked(false) end if optionsFrame.searchBarGroup then optionsFrame.searchBarGroup:UpdateVisuals() end if optionsFrame.mapPinGroup then optionsFrame.mapPinGroup:UpdateVisuals() end if optionsFrame.minimapGroup then optionsFrame.minimapGroup:UpdateVisuals() end @@ -1892,9 +1899,11 @@ function Options:DoResetMap() EasyFind.db.pinsCollapsed = false EasyFind.db.globalSearchFilters = { zones = true, dungeons = true, raids = true, delves = true } EasyFind.db.localSearchFilters = { instances = true, travel = true, services = true } + EasyFind.db.alwaysShowRares = false optionsFrame.localNavCheckbox:SetChecked(false) optionsFrame.globalNavCheckbox:SetChecked(false) + if optionsFrame.rareTrackCheckbox then optionsFrame.rareTrackCheckbox:SetChecked(false) end if ns.MapSearch and ns.MapSearch.UpdateMapModeBtns then ns.MapSearch:UpdateMapModeBtns() end if optionsFrame.searchBarGroup then optionsFrame.searchBarGroup:UpdateVisuals() end if optionsFrame.mapPinGroup then optionsFrame.mapPinGroup:UpdateVisuals() end From b64ac52dd5dc52d64e10e71ff5c1d41e1fd9f322 Mon Sep 17 00:00:00 2001 From: wowaddonmaker Date: Fri, 20 Mar 2026 23:38:16 -0400 Subject: [PATCH 7/9] Update changelog and README for v1.4.0 --- CHANGELOG.md | 18 ++++++++++++++++++ README.md | 1 + 2 files changed, 19 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c9f66c6..d705901 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,24 @@ All notable changes to EasyFind will be documented in this file. --- +## [1.4.0] - 2026-03-20 + +### Added +- **Rare Mob Tracking**: Active rare mobs in your zone appear as searchable pins on the world map. Search "rare" in the zone bar to see all nearby rares, or click individual rare names to track them with the minimap supertrack arrow +- **Auto-track Rares**: Toggle in the zone search filter dropdown or the Map options tab. When enabled, all active rares are automatically pinned on the map without searching. Pins persist at last known position when rares leave detection range and clear when killed +- **Great Vault (Rewards)**: Great vault rewards panel now searchable in UI search +- **"NEW" Feature Labels**: New or experimental features display a glowing label with a tooltip encouraging feedback + +### Fixed +- **Adventure Guide Fast Mode**: Direct open now works for all Adventure Guide tabs (Journeys, Dungeons, Raids, etc.) +- **Combat Lockdown**: Fixed errors that could occur when reloading the UI during combat or by taking portals +- **Nav Waypoint Tracking**: Minimap guide circle now correctly follows portal redirects when the portal is in a neighboring zone + +### Changed +- **StaticLocations Cleanup**: Standardized bank and guild vault naming across all zones + +--- + ## [1.3.1] - 2026-03-17 ### Added diff --git a/README.md b/README.md index dbdf741..bcfdad1 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,7 @@ Locate places and NPCs across Azeroth: * Stable masters, void storage, and guild services * The Great Vault, Creation Catalyst, and Trading Post * Chromie (Timewalking Campaigns) +* Rare mobs (with optional auto-tracking that always shows active rares on the map) Search the zone of the map you're currently focused on with the local bar (left side), or search across all of Azeroth with the global bar (right side). Map search results also appear in the UI search bar when the Map Search filter is enabled. From e387de733e7b827ac5d37f109775f4dfdb0aa637 Mon Sep 17 00:00:00 2001 From: wowaddonmaker Date: Fri, 20 Mar 2026 23:48:01 -0400 Subject: [PATCH 8/9] [worktree-rename] Revert addon rename (EasyFind-rares -> EasyFind) --- EasyFind-rares.toc => EasyFind.toc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename EasyFind-rares.toc => EasyFind.toc (89%) diff --git a/EasyFind-rares.toc b/EasyFind.toc similarity index 89% rename from EasyFind-rares.toc rename to EasyFind.toc index 1d530ba..379783b 100644 --- a/EasyFind-rares.toc +++ b/EasyFind.toc @@ -1,8 +1,8 @@ ## Interface: 120005, 120001, 120000 -## Title: EasyFind (rares) +## Title: EasyFind ## Notes: Search and locate UI elements and map locations with ease ## Author: justawower -## Version: 1.3.1 +## Version: 1.4.0 ## IconTexture: 136460 ## Category: UI ## AddonCompartmentFunc: EasyFind_OnAddonCompartmentClick From 4d725564c38ebfbd3c4b8d101ddf917a34c55296 Mon Sep 17 00:00:00 2001 From: wowaddonmaker Date: Sat, 21 Mar 2026 00:10:27 -0400 Subject: [PATCH 9/9] Fix luacheck warnings and add missing globals --- .luacheckrc | 6 ++++-- MapSearch.lua | 12 ------------ Rescaler.lua | 1 + 3 files changed, 5 insertions(+), 14 deletions(-) diff --git a/.luacheckrc b/.luacheckrc index 0cd60a8..482581c 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -19,6 +19,7 @@ globals = { "BINDING_NAME_EASYFIND_FOCUS", "BINDING_NAME_EASYFIND_TOGGLE_FOCUS", "BINDING_NAME_EASYFIND_CLEAR", + "EncounterJournal", } -- WoW API globals (read-only) @@ -33,7 +34,7 @@ read_globals = { "GetAddOnMetadata", "GetAtlasInfo", "GetMinimapShape", "GetBindingKey", "GetCurrentBindingSet", "SaveBindings", "SetBinding", "GetCategoryInfo", "GetPlayerFacing", - "SetPortraitTexture", "ToggleWorldMap", "ToggleDropDownMenu", + "SetPortraitTexture", "ShowUIPanel", "ToggleWorldMap", "ToggleDropDownMenu", "InterfaceOptions_AddCategory", "InCombatLockdown", "IsShiftKeyDown", "IsMouseButtonDown", "IsAltKeyDown", "IsControlKeyDown", "IsInGroup", "IsInInstance", "IsIndoors", "UnitIsGroupLeader", @@ -48,7 +49,7 @@ read_globals = { "CharacterStatsPane", "PaperDollTitlesPane", "PaperDollEquipmentManagerPane", "CurrencyFrame", "SpellBookFrame", "PlayerSpellsFrame", "CollectionsJournal", - "EncounterJournal", "PVEFrame", "ReputationFrame", "TokenFrame", + "PVEFrame", "ReputationFrame", "TokenFrame", "GroupFinderFrame", "LFGListFrame", "HelpFrame", "ClassTalentFrame", "GuildMicroButton", "StoreMicroButton", "PlayerFrame", "StoreFrame", "LFDParentFrame", "RaidFinderFrame", @@ -57,6 +58,7 @@ read_globals = { "PVPQueueFrame", "AchievementFrameCategories_ExpandToCategory", "AchievementFrameCategories_UpdateDataProvider", + "EncounterJournal_LoadUI", "PanelTemplates_SetTab", "Menu", "ScrollBoxConstants", -- C_* namespaces diff --git a/MapSearch.lua b/MapSearch.lua index 7d8916b..8ecb4f1 100644 --- a/MapSearch.lua +++ b/MapSearch.lua @@ -631,19 +631,7 @@ local function CreateWaypointTracker() return end - -- Zone check: is the pin in the player's current zone? local pMapID = GetBestMapForUnit("player") - local pinZoneID = cachedPinMapID or wpMapID - local sameZone = false - if pMapID and pMapID == pinZoneID then - sameZone = true - elseif pMapID then - local pInfo = GetMapInfo(pMapID) - local pinInfo = GetMapInfo(pinZoneID) - if pInfo and pinInfo and pInfo.name == pinInfo.name then - sameZone = true - end - end -- Prefer intermediate nav waypoint (portal, boat, etc.) when the -- game's navigation mesh routes through one. Walk up the map diff --git a/Rescaler.lua b/Rescaler.lua index ad4182d..efb79a6 100644 --- a/Rescaler.lua +++ b/Rescaler.lua @@ -6,6 +6,7 @@ ns.Rescaler = Rescaler local Utils = ns.Utils local mmax, mmin, mfloor = Utils.mmax, Utils.mmin, Utils.mfloor local tinsert = Utils.tinsert +local SafeCallMethod = Utils.SafeCallMethod local GOLD_COLOR = ns.GOLD_COLOR local DARK_PANEL_BG = ns.DARK_PANEL_BG