696 lines
23 KiB
Lua
696 lines
23 KiB
Lua
--------------------------------------------------------------------------------
|
|
-- Nanami-UI: MapReveal -- Reveal unexplored world map areas
|
|
-- Adapted from ShaguTweaks-extras worldmap-reveal approach
|
|
-- Uses LibMapOverlayData (from !Libs) supplemented with Turtle WoW zones
|
|
-- Features persistent overlay discovery via GetMapOverlayInfo() API
|
|
--------------------------------------------------------------------------------
|
|
|
|
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 } },
|
|
}
|
|
|
|
-- Zones only in TurtleWoW_Zones: not in patched WorldMapOverlay.dbc but needed for fog reveal
|
|
local TurtleWoW_Zones = {
|
|
["UpperKarazhan2f"] = {
|
|
"OUTLAND:1024:768:0:0",
|
|
},
|
|
}
|
|
|
|
-- Runtime-discovered overlay data (populated by scanning and passive collection)
|
|
local scannedOverlays = {}
|
|
|
|
local function IsTurtleWoW()
|
|
return TargetHPText and TargetHPPercText
|
|
end
|
|
|
|
local function GetOverlayDB()
|
|
return MapOverlayData or LibMapOverlayData or zMapOverlayData or mapOverlayData
|
|
end
|
|
|
|
local function SafeSetMapToCurrentZone()
|
|
if not SetMapToCurrentZone then
|
|
return
|
|
end
|
|
if SFrames and SFrames.CallWithPreservedBattlefieldMinimap then
|
|
return SFrames:CallWithPreservedBattlefieldMinimap(SetMapToCurrentZone)
|
|
end
|
|
return pcall(SetMapToCurrentZone)
|
|
end
|
|
|
|
local function SafeSetMapZoom(continent, zone)
|
|
if not SetMapZoom then
|
|
return
|
|
end
|
|
if SFrames and SFrames.CallWithPreservedBattlefieldMinimap then
|
|
return SFrames:CallWithPreservedBattlefieldMinimap(SetMapZoom, continent, zone)
|
|
end
|
|
return pcall(SetMapZoom, continent, zone)
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- Persistence: save/load discovered overlay data to SFramesDB
|
|
--------------------------------------------------------------------------------
|
|
local function GetGlobalDB()
|
|
if not SFramesGlobalDB then SFramesGlobalDB = {} end
|
|
return SFramesGlobalDB
|
|
end
|
|
|
|
local function LoadPersistedData()
|
|
local gdb = GetGlobalDB()
|
|
local saved = gdb.MapRevealScanData
|
|
if type(saved) ~= "table" then return end
|
|
|
|
local count = 0
|
|
for zone, overlays in pairs(saved) do
|
|
if type(overlays) == "table" and table.getn(overlays) > 0 then
|
|
if not scannedOverlays[zone] or table.getn(scannedOverlays[zone]) < table.getn(overlays) then
|
|
scannedOverlays[zone] = overlays
|
|
count = count + 1
|
|
end
|
|
end
|
|
end
|
|
return count
|
|
end
|
|
|
|
local function SavePersistedData()
|
|
local gdb = GetGlobalDB()
|
|
if type(gdb.MapRevealScanData) ~= "table" then
|
|
gdb.MapRevealScanData = {}
|
|
end
|
|
|
|
for zone, overlays in pairs(scannedOverlays) do
|
|
local existing = gdb.MapRevealScanData[zone]
|
|
if not existing or table.getn(existing) < table.getn(overlays) then
|
|
gdb.MapRevealScanData[zone] = overlays
|
|
end
|
|
end
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- Overlay name index for deduplication when merging
|
|
--------------------------------------------------------------------------------
|
|
local function BuildOverlayIndex(overlayList)
|
|
local idx = {}
|
|
if not overlayList then return idx end
|
|
for i = 1, table.getn(overlayList) do
|
|
local entry = overlayList[i]
|
|
local _, _, name = string.find(entry, "^([^:]+):")
|
|
if name then
|
|
idx[string.upper(name)] = i
|
|
end
|
|
end
|
|
return idx
|
|
end
|
|
|
|
local function MergeScannedDataIntoDB()
|
|
local db = GetOverlayDB()
|
|
if not db then return end
|
|
|
|
for zone, data in pairs(scannedOverlays) do
|
|
if not db[zone] then
|
|
db[zone] = data
|
|
else
|
|
local existingIdx = BuildOverlayIndex(db[zone])
|
|
for i = 1, table.getn(data) do
|
|
local _, _, newName = string.find(data[i], "^([^:]+):")
|
|
if newName and not existingIdx[string.upper(newName)] then
|
|
table.insert(db[zone], data[i])
|
|
existingIdx[string.upper(newName)] = table.getn(db[zone])
|
|
end
|
|
end
|
|
end
|
|
end
|
|
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
|
|
if table.getn(data) > 0 then
|
|
db[zone] = data
|
|
end
|
|
end
|
|
|
|
MergeScannedDataIntoDB()
|
|
end
|
|
|
|
local function MergeOverlaysForZone(zone)
|
|
local db = GetOverlayDB()
|
|
if not db or not scannedOverlays[zone] then return end
|
|
|
|
if not db[zone] then
|
|
db[zone] = scannedOverlays[zone]
|
|
return
|
|
end
|
|
|
|
local existingIdx = BuildOverlayIndex(db[zone])
|
|
local data = scannedOverlays[zone]
|
|
for i = 1, table.getn(data) do
|
|
local _, _, newName = string.find(data[i], "^([^:]+):")
|
|
if newName and not existingIdx[string.upper(newName)] then
|
|
table.insert(db[zone], data[i])
|
|
existingIdx[string.upper(newName)] = table.getn(db[zone])
|
|
end
|
|
end
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- Passive overlay discovery: captures explored overlay data from the API
|
|
-- every time the world map updates, discovering new overlays automatically
|
|
--------------------------------------------------------------------------------
|
|
local function PassiveCollectOverlays()
|
|
local mapFile = GetMapInfo and GetMapInfo()
|
|
if not mapFile or mapFile == "" or mapFile == "World" then return end
|
|
|
|
local numOverlays = GetNumMapOverlays and GetNumMapOverlays() or 0
|
|
if numOverlays == 0 then return end
|
|
|
|
local currentOverlays = {}
|
|
local hasNew = false
|
|
|
|
for i = 1, numOverlays do
|
|
local texName, texW, texH, offX, offY = GetMapOverlayInfo(i)
|
|
if texName and texName ~= "" then
|
|
local _, _, name = string.find(texName, "\\([^\\]+)$")
|
|
if name then
|
|
name = string.upper(name)
|
|
table.insert(currentOverlays, name .. ":" .. texW .. ":" .. texH .. ":" .. offX .. ":" .. offY)
|
|
end
|
|
end
|
|
end
|
|
|
|
if table.getn(currentOverlays) == 0 then return end
|
|
|
|
if not scannedOverlays[mapFile] then
|
|
scannedOverlays[mapFile] = currentOverlays
|
|
hasNew = true
|
|
else
|
|
local existingIdx = BuildOverlayIndex(scannedOverlays[mapFile])
|
|
for i = 1, table.getn(currentOverlays) do
|
|
local _, _, newName = string.find(currentOverlays[i], "^([^:]+):")
|
|
if newName and not existingIdx[string.upper(newName)] then
|
|
table.insert(scannedOverlays[mapFile], currentOverlays[i])
|
|
existingIdx[string.upper(newName)] = table.getn(scannedOverlays[mapFile])
|
|
hasNew = true
|
|
end
|
|
end
|
|
end
|
|
|
|
if hasNew then
|
|
MergeOverlaysForZone(mapFile)
|
|
SavePersistedData()
|
|
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
|
|
|
|
local loadedCount = LoadPersistedData()
|
|
PatchOverlayDB()
|
|
|
|
if loadedCount and loadedCount > 0 then
|
|
MergeScannedDataIntoDB()
|
|
end
|
|
|
|
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()
|
|
|
|
PassiveCollectOverlays()
|
|
|
|
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
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- Map Scanner: enumerate all continents/zones, collect overlay data from
|
|
-- explored areas, discover new zones, and merge into the overlay database.
|
|
-- Usage: /nui mapscan or SFrames.MapReveal:ScanAllMaps()
|
|
--------------------------------------------------------------------------------
|
|
local scanFrame = nil
|
|
local scanQueue = {}
|
|
local scanIndex = 0
|
|
local scanRunning = false
|
|
local scanResults = {}
|
|
local scanNewZones = {}
|
|
local scanUpdatedZones = {}
|
|
local savedMapC, savedMapZ = 0, 0
|
|
|
|
local function ExtractOverlayName(fullPath)
|
|
if not fullPath or fullPath == "" then return nil end
|
|
local _, _, name = string.find(fullPath, "\\([^\\]+)$")
|
|
return name and string.upper(name) or nil
|
|
end
|
|
|
|
local function ProcessScanZone()
|
|
if scanIndex > table.getn(scanQueue) then
|
|
MapReveal:FinishScan()
|
|
return
|
|
end
|
|
|
|
local entry = scanQueue[scanIndex]
|
|
SafeSetMapZoom(entry.cont, entry.zone)
|
|
|
|
local mapFile = GetMapInfo and GetMapInfo() or ""
|
|
if mapFile == "" then
|
|
scanIndex = scanIndex + 1
|
|
return
|
|
end
|
|
|
|
local numOverlays = GetNumMapOverlays and GetNumMapOverlays() or 0
|
|
if numOverlays > 0 then
|
|
local overlays = {}
|
|
for i = 1, numOverlays do
|
|
local texName, texW, texH, offX, offY = GetMapOverlayInfo(i)
|
|
if texName and texName ~= "" then
|
|
local name = ExtractOverlayName(texName)
|
|
if name then
|
|
table.insert(overlays, name .. ":" .. texW .. ":" .. texH .. ":" .. offX .. ":" .. offY)
|
|
end
|
|
end
|
|
end
|
|
|
|
if table.getn(overlays) > 0 then
|
|
local db = GetOverlayDB()
|
|
local existing = db and db[mapFile]
|
|
|
|
if not existing then
|
|
scanNewZones[mapFile] = overlays
|
|
scanResults[mapFile] = { overlays = overlays, status = "new", count = table.getn(overlays) }
|
|
else
|
|
local existingIdx = BuildOverlayIndex(existing)
|
|
local newEntries = 0
|
|
for i = 1, table.getn(overlays) do
|
|
local _, _, oName = string.find(overlays[i], "^([^:]+):")
|
|
if oName and not existingIdx[string.upper(oName)] then
|
|
newEntries = newEntries + 1
|
|
end
|
|
end
|
|
|
|
if newEntries > 0 then
|
|
scanUpdatedZones[mapFile] = overlays
|
|
scanResults[mapFile] = {
|
|
overlays = overlays, status = "updated",
|
|
count = table.getn(existing) + newEntries,
|
|
oldCount = table.getn(existing)
|
|
}
|
|
else
|
|
scanResults[mapFile] = { status = "ok", count = table.getn(existing) }
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
scanIndex = scanIndex + 1
|
|
end
|
|
|
|
function MapReveal:FinishScan()
|
|
scanRunning = false
|
|
if scanFrame then
|
|
scanFrame:SetScript("OnUpdate", nil)
|
|
end
|
|
|
|
if savedMapZ > 0 then
|
|
SafeSetMapZoom(savedMapC, savedMapZ)
|
|
elseif savedMapC > 0 then
|
|
SafeSetMapZoom(savedMapC, 0)
|
|
else
|
|
SafeSetMapToCurrentZone()
|
|
end
|
|
|
|
local cf = DEFAULT_CHAT_FRAME
|
|
local newCount = 0
|
|
local updCount = 0
|
|
local newOverlayCount = 0
|
|
|
|
for zone, overlays in pairs(scanNewZones) do
|
|
newCount = newCount + 1
|
|
scannedOverlays[zone] = overlays
|
|
end
|
|
for zone, overlays in pairs(scanUpdatedZones) do
|
|
updCount = updCount + 1
|
|
if not scannedOverlays[zone] then
|
|
scannedOverlays[zone] = overlays
|
|
else
|
|
local existingIdx = BuildOverlayIndex(scannedOverlays[zone])
|
|
for i = 1, table.getn(overlays) do
|
|
local _, _, oName = string.find(overlays[i], "^([^:]+):")
|
|
if oName and not existingIdx[string.upper(oName)] then
|
|
table.insert(scannedOverlays[zone], overlays[i])
|
|
existingIdx[string.upper(oName)] = table.getn(scannedOverlays[zone])
|
|
newOverlayCount = newOverlayCount + 1
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
MergeScannedDataIntoDB()
|
|
SavePersistedData()
|
|
|
|
cf:AddMessage("|cffffb3d9[Nanami-UI]|r 地图扫描完成!")
|
|
cf:AddMessage(string.format(" 扫描了 |cff00ff00%d|r 个区域", table.getn(scanQueue)))
|
|
|
|
if newCount > 0 then
|
|
cf:AddMessage(string.format(" 发现 |cff00ff00%d|r 个新区域 (已自动添加迷雾数据):", newCount))
|
|
for zone, overlays in pairs(scanNewZones) do
|
|
cf:AddMessage(" |cff00ffff" .. zone .. "|r (" .. table.getn(overlays) .. " 个覆盖层)")
|
|
end
|
|
end
|
|
|
|
if updCount > 0 then
|
|
cf:AddMessage(string.format(" 更新了 |cffffff00%d|r 个区域 (发现更多已探索覆盖层):", updCount))
|
|
for zone, info in pairs(scanResults) do
|
|
if info.status == "updated" then
|
|
cf:AddMessage(" |cffffff00" .. zone .. "|r (" .. (info.oldCount or 0) .. " -> " .. info.count .. ")")
|
|
end
|
|
end
|
|
end
|
|
|
|
if newCount == 0 and updCount == 0 then
|
|
cf:AddMessage(" 所有区域数据已是最新,未发现变动。")
|
|
end
|
|
|
|
cf:AddMessage(" 数据已自动保存,下次登录无需重新扫描。")
|
|
cf:AddMessage(" 提示: 新发现的区域仅记录已探索区域的覆盖层,完全探索后再次扫描可获取完整数据。")
|
|
|
|
if WorldMapFrame and WorldMapFrame:IsShown() then
|
|
WorldMapFrame_Update()
|
|
end
|
|
end
|
|
|
|
function MapReveal:ScanAllMaps()
|
|
if scanRunning then
|
|
SFrames:Print("地图扫描正在进行中...")
|
|
return
|
|
end
|
|
|
|
local db = GetOverlayDB()
|
|
if not db then
|
|
SFrames:Print("MapReveal: 未找到覆盖层数据库,无法扫描。")
|
|
return
|
|
end
|
|
|
|
scanRunning = true
|
|
scanQueue = {}
|
|
scanIndex = 1
|
|
scanResults = {}
|
|
scanNewZones = {}
|
|
scanUpdatedZones = {}
|
|
|
|
savedMapC = GetCurrentMapContinent and GetCurrentMapContinent() or 0
|
|
savedMapZ = GetCurrentMapZone and GetCurrentMapZone() or 0
|
|
|
|
local numContinents = 0
|
|
if GetMapContinents then
|
|
local continents = { GetMapContinents() }
|
|
numContinents = table.getn(continents)
|
|
end
|
|
|
|
for c = 1, numContinents do
|
|
local zones = { GetMapZones(c) }
|
|
for z = 1, table.getn(zones) do
|
|
table.insert(scanQueue, { cont = c, zone = z, name = zones[z] or "" })
|
|
end
|
|
end
|
|
|
|
SFrames:Print("开始扫描所有地图... (共 " .. table.getn(scanQueue) .. " 个区域)")
|
|
|
|
if not scanFrame then
|
|
scanFrame = CreateFrame("Frame")
|
|
end
|
|
|
|
local scanElapsed = 0
|
|
scanFrame:SetScript("OnUpdate", function()
|
|
scanElapsed = scanElapsed + (arg1 or 0)
|
|
if scanElapsed < 0.02 then return end
|
|
scanElapsed = 0
|
|
|
|
if not scanRunning then return end
|
|
local batch = 0
|
|
while scanIndex <= table.getn(scanQueue) and batch < 5 do
|
|
ProcessScanZone()
|
|
batch = batch + 1
|
|
end
|
|
if scanIndex > table.getn(scanQueue) then
|
|
MapReveal:FinishScan()
|
|
end
|
|
end)
|
|
end
|
|
|
|
function MapReveal:ExportScannedData()
|
|
local cf = DEFAULT_CHAT_FRAME
|
|
local hasData = false
|
|
|
|
for zone, overlays in pairs(scannedOverlays) do
|
|
hasData = true
|
|
cf:AddMessage("|cffffb3d9[MapReveal Export]|r |cff00ffff" .. zone .. "|r = {")
|
|
for _, entry in ipairs(overlays) do
|
|
cf:AddMessage(' "' .. entry .. '",')
|
|
end
|
|
cf:AddMessage("}")
|
|
end
|
|
|
|
if not hasData then
|
|
cf:AddMessage("|cffffb3d9[MapReveal]|r 没有扫描到的新数据可导出。先运行 /nui mapscan")
|
|
end
|
|
end
|
|
|
|
function MapReveal:ShowStats()
|
|
local cf = DEFAULT_CHAT_FRAME
|
|
local db = GetOverlayDB()
|
|
cf:AddMessage("|cffffb3d9[MapReveal]|r 覆盖层数据统计:")
|
|
|
|
local dbZones, dbOverlays = 0, 0
|
|
if db then
|
|
for zone, data in pairs(db) do
|
|
dbZones = dbZones + 1
|
|
dbOverlays = dbOverlays + table.getn(data)
|
|
end
|
|
end
|
|
cf:AddMessage(string.format(" 数据库: |cff00ff00%d|r 个区域, |cff00ff00%d|r 个覆盖层", dbZones, dbOverlays))
|
|
|
|
local scanZones, scanOverlays = 0, 0
|
|
for zone, data in pairs(scannedOverlays) do
|
|
scanZones = scanZones + 1
|
|
scanOverlays = scanOverlays + table.getn(data)
|
|
end
|
|
cf:AddMessage(string.format(" 已发现: |cff00ff00%d|r 个区域, |cff00ff00%d|r 个覆盖层 (通过扫描/浏览)", scanZones, scanOverlays))
|
|
|
|
local savedZones = 0
|
|
local gdb = GetGlobalDB()
|
|
if type(gdb.MapRevealScanData) == "table" then
|
|
for _ in pairs(gdb.MapRevealScanData) do
|
|
savedZones = savedZones + 1
|
|
end
|
|
end
|
|
cf:AddMessage(string.format(" 已持久化: |cff00ff00%d|r 个区域", savedZones))
|
|
|
|
cf:AddMessage(" 提示: 打开世界地图浏览各区域可自动发现新覆盖层数据")
|
|
end
|
|
|
|
function MapReveal:ClearSavedData()
|
|
local gdb = GetGlobalDB()
|
|
gdb.MapRevealScanData = nil
|
|
scannedOverlays = {}
|
|
SFrames:Print("地图扫描数据已清除。重新加载UI后生效。")
|
|
end
|