-------------------------------------------------------------------------------- -- Nanami-UI: MapReveal -- Reveal unexplored world map areas -- Adapted from ShaguTweaks-extras worldmap-reveal approach -- Uses LibMapOverlayData (from !Libs) supplemented with Turtle WoW zones -------------------------------------------------------------------------------- SFrames.MapReveal = SFrames.MapReveal or {} local MapReveal = SFrames.MapReveal local origWorldMapFrame_Update = nil local overlayDBPatched = false local errata = { ["Interface\\WorldMap\\Tirisfal\\BRIGHTWATERLAKE"] = { offsetX = { 587, 584 } }, ["Interface\\WorldMap\\Silverpine\\BERENSPERIL"] = { offsetY = { 417, 415 } }, } -- Turtle WoW new/modified zones not present in LibMapOverlayData local TurtleWoW_Zones = { ["StonetalonMountains"] = { "SUNROCKRETREAT:512:256:256:256", "WINDSHEARCRAG:256:256:512:256", "MIRKFALLONLAKE:512:512:256:0", "THECHARREDVALE:256:512:256:256", "STONETALONPEAK:256:256:256:0", "WEBWINDERPATH:256:512:512:256", "AMANIALOR:512:256:0:0", "GRIMTOTEMPOST:512:256:512:512", "CAMPAPARAJE:512:256:512:512", "MALAKAJIN:512:256:512:512", "BOULDERSLIDERAVINE:256:256:512:512", "SISHIRCANYON:256:512:512:256", "VENTURECOMPANYCAMP:256:512:256:0", "BLACKSANDOILFIELDS:512:512:0:0", "POWDERTOWN:256:256:256:256", "BRAMBLETHORNPASS:512:512:512:256", "BAELHARDUL:512:256:512:256", "BROKENCLIFFMINE:256:512:256:0", "THEEARTHENRING:512:256:256:256", }, ["UpperKarazhan2f"] = { "OUTLAND:1024:768:0:0", }, ["GrimReaches"] = { "DUNKITHAS:512:256:256:256", "THEGRIMHOLLOW:512:512:256:256", "LAKEKITHAS:512:256:256:256", "SLATEBEARDSFORGE:512:256:256:256", "THEHIGHPASS:256:256:256:256", "SALGAZMINES:256:256:512:256", "EASTRIDGEOUTPOST:512:512:256:0", "BAGGOTHSRAMPART:256:512:256:0", "RUINSOFSTOLGAZKEEP:256:256:256:0", "GROLDANSEXCAVATION:256:512:512:0", "ZARMGETHSTRONGHOLD:512:256:256:0", "GETHKAR:512:256:256:0", "ZARMGETHPOINT:512:256:256:0", "SHATTERBLADEPOST:256:256:512:0", "BRANGARSFOLLY:256:256:512:0", "BARLEYCRESTFARMSTEAD:512:512:256:0", }, ["Balor"] = { "GULLWINGWRECKAGE:512:256:0:0", "BILGERATCOMPOUND:256:256:256:0", "SIOUTPOST:256:512:512:256", "RUINSOFBREEZEHAVEN:512:256:256:256", "CROAKINGPLATEAU:512:512:256:0", "LANGSTONORCHARD:256:256:256:256", "SORROWMORELAKE:256:256:256:256", "SCURRYINGTHICKET:256:512:256:0", "STORMWROUGHTCASTLE:512:256:256:256", "STORMREAVERSPIRE:512:512:256:256", "WINDROCKCLIFFS:256:512:256:256", "TREACHEROUSCRAGS:512:512:256:256", "VANDERFARMSTEAD:256:256:256:256", "GRAHANESTATE:256:256:256:256", "STORMBREAKERPOINT:512:512:512:0", }, ["Northwind"] = { "MERCHANTSHIGHROAD:512:512:256:256", "AMBERSHIRE:512:256:256:256", "AMBERWOODKEEP:512:256:0:256", "CRYSTALFALLS:512:512:512:256", "CRAWFORDWINERY:256:256:512:256", "NORTHWINDLOGGINGCAMP:256:512:256:0", "WITCHCOVEN:256:256:256:0", "RUINSOFBIRKHAVEN:512:512:512:0", "SHERWOODQUARRY:512:512:512:0", "BLACKROCKBREACH:512:512:512:0", "GRIMMENLAKE:256:512:512:256", "ABBEYGARDENS:256:256:512:0", "STILLHEARTPORT:512:512:0:0", "TOWEROFMAGILOU:512:512:0:0", "BRISTLEWHISKERCAVERN:256:512:512:0", "NORTHRIDGEPOINT:512:512:256:0", "CINDERFALLPASS:512:512:512:256", }, } local function IsTurtleWoW() return TargetHPText and TargetHPPercText end local function GetOverlayDB() return MapOverlayData or LibMapOverlayData or zMapOverlayData or mapOverlayData end local function PatchOverlayDB() if overlayDBPatched then return end overlayDBPatched = true if not IsTurtleWoW() then return end local db = GetOverlayDB() if not db then return end for zone, data in pairs(TurtleWoW_Zones) do db[zone] = data end end local function GetConfig() if not SFramesDB or type(SFramesDB.MapReveal) ~= "table" then return { enabled = true, unexploredAlpha = 0.7 } end return SFramesDB.MapReveal end local function NextPowerOf2(n) local p = 16 while p < n do p = p * 2 end return p end local function DoMapRevealUpdate() local db = GetOverlayDB() if not db then return end local mapFileName = GetMapInfo and GetMapInfo() if not mapFileName then mapFileName = "World" end local zoneData = db[mapFileName] if not zoneData then return end local prefix = "Interface\\WorldMap\\" .. mapFileName .. "\\" local numExploredOverlays = GetNumMapOverlays and GetNumMapOverlays() or 0 local explored = {} for i = 1, numExploredOverlays do local textureName = GetMapOverlayInfo(i) if textureName and textureName ~= "" then explored[textureName] = true end end local cfg = GetConfig() local dimR, dimG, dimB = 0.4, 0.4, 0.4 if cfg.unexploredAlpha then dimR = cfg.unexploredAlpha dimG = cfg.unexploredAlpha dimB = cfg.unexploredAlpha end local textureCount = 0 for idx = 1, table.getn(zoneData) do local entry = zoneData[idx] local _, _, name, sW, sH, sX, sY = string.find(entry, "^(%u+):(%d+):(%d+):(%d+):(%d+)$") if not name then _, _, name, sW, sH, sX, sY = string.find(entry, "^([^:]+):(%d+):(%d+):(%d+):(%d+)$") end if name then local textureWidth = tonumber(sW) local textureHeight = tonumber(sH) local offsetX = tonumber(sX) local offsetY = tonumber(sY) local textureName = prefix .. name local isExplored = explored[textureName] if cfg.enabled or isExplored then if errata[textureName] then local e = errata[textureName] if e.offsetX and e.offsetX[1] == offsetX then offsetX = e.offsetX[2] end if e.offsetY and e.offsetY[1] == offsetY then offsetY = e.offsetY[2] end end local numTexturesHorz = math.ceil(textureWidth / 256) local numTexturesVert = math.ceil(textureHeight / 256) local neededTextures = textureCount + (numTexturesHorz * numTexturesVert) if neededTextures > NUM_WORLDMAP_OVERLAYS then for j = NUM_WORLDMAP_OVERLAYS + 1, neededTextures do WorldMapDetailFrame:CreateTexture("WorldMapOverlay" .. j, "ARTWORK") end NUM_WORLDMAP_OVERLAYS = neededTextures end for row = 1, numTexturesVert do local texturePixelHeight, textureFileHeight if row < numTexturesVert then texturePixelHeight = 256 textureFileHeight = 256 else texturePixelHeight = math.mod(textureHeight, 256) if texturePixelHeight == 0 then texturePixelHeight = 256 end textureFileHeight = NextPowerOf2(texturePixelHeight) end for col = 1, numTexturesHorz do if textureCount > NUM_WORLDMAP_OVERLAYS then return end local texture = _G["WorldMapOverlay" .. (textureCount + 1)] local texturePixelWidth, textureFileWidth if col < numTexturesHorz then texturePixelWidth = 256 textureFileWidth = 256 else texturePixelWidth = math.mod(textureWidth, 256) if texturePixelWidth == 0 then texturePixelWidth = 256 end textureFileWidth = NextPowerOf2(texturePixelWidth) end texture:SetWidth(texturePixelWidth) texture:SetHeight(texturePixelHeight) texture:SetTexCoord(0, texturePixelWidth / textureFileWidth, 0, texturePixelHeight / textureFileHeight) texture:ClearAllPoints() texture:SetPoint("TOPLEFT", "WorldMapDetailFrame", "TOPLEFT", offsetX + (256 * (col - 1)), -(offsetY + (256 * (row - 1)))) local tileIndex = ((row - 1) * numTexturesHorz) + col texture:SetTexture(textureName .. tileIndex) if not isExplored then texture:SetVertexColor(dimR, dimG, dimB, 1) else texture:SetVertexColor(1, 1, 1, 1) end texture:Show() textureCount = textureCount + 1 end end end end end end function MapReveal:Initialize() local db = GetOverlayDB() if not db then SFrames:Print("MapReveal: LibMapOverlayData 未找到,地图揭示功能不可用。") return end PatchOverlayDB() if not origWorldMapFrame_Update and WorldMapFrame_Update then origWorldMapFrame_Update = WorldMapFrame_Update WorldMapFrame_Update = function() for i = 1, NUM_WORLDMAP_OVERLAYS do local tex = _G["WorldMapOverlay" .. i] if tex then tex:Hide() end end origWorldMapFrame_Update() local cfg = GetConfig() if cfg.enabled then DoMapRevealUpdate() end end end end function MapReveal:Toggle() if not SFramesDB then SFramesDB = {} end if type(SFramesDB.MapReveal) ~= "table" then SFramesDB.MapReveal = { enabled = true, unexploredAlpha = 0.7 } end SFramesDB.MapReveal.enabled = not SFramesDB.MapReveal.enabled if SFramesDB.MapReveal.enabled then SFrames:Print("地图迷雾揭示: |cff00ff00已开启|r") if not origWorldMapFrame_Update and WorldMapFrame_Update then self:Initialize() end else SFrames:Print("地图迷雾揭示: |cffff0000已关闭|r") end if WorldMapFrame and WorldMapFrame:IsShown() then WorldMapFrame_Update() end end function MapReveal:SetAlpha(alpha) if not SFramesDB or type(SFramesDB.MapReveal) ~= "table" then return end SFramesDB.MapReveal.unexploredAlpha = alpha if SFramesDB.MapReveal.enabled and WorldMapFrame and WorldMapFrame:IsShown() then WorldMapFrame_Update() end end function MapReveal:Refresh() if WorldMapFrame and WorldMapFrame:IsShown() then WorldMapFrame_Update() end end