From 3848c59f3fae3ae76ffb6fa0b25e864f222f76b9 Mon Sep 17 00:00:00 2001 From: praxis <889+praxis@noreply.octowow.st> Date: Sun, 13 Sep 2026 09:51:58 +0000 Subject: [PATCH] Add modules/mapreveal.lua --- modules/mapreveal.lua | 215 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 215 insertions(+) create mode 100644 modules/mapreveal.lua diff --git a/modules/mapreveal.lua b/modules/mapreveal.lua new file mode 100644 index 0000000..d827596 --- /dev/null +++ b/modules/mapreveal.lua @@ -0,0 +1,215 @@ +pfUI:RegisterModule("mapreveal", "vanilla:tbc", function () + if Cartographer then return end + if METAMAP_TITLE then return end + + pfUI.mapreveal = {} + function pfUI.mapreveal:UpdateConfig() + WorldMapFrame_Update() + end + + pfUI.mapreveal.onmap = CreateFrame("CheckButton", "pfUI_mapreveal_onmap", WorldMapFrame, "UICheckButtonTemplate") + pfUI.mapreveal.onmap:SetNormalTexture("") + pfUI.mapreveal.onmap:SetPushedTexture("") + pfUI.mapreveal.onmap:SetHighlightTexture("") + pfUI.mapreveal.onmap.text = _G["pfUI_mapreveal_onmapText"] + CreateBackdrop(pfUI.mapreveal.onmap, nil, true) + pfUI.mapreveal.onmap:SetWidth(14) + pfUI.mapreveal.onmap:SetHeight(14) + pfUI.mapreveal.onmap:SetPoint("LEFT", WorldMapZoomOutButton, "RIGHT", 20, 0) + pfUI.mapreveal.onmap.text:SetPoint("LEFT", pfUI.mapreveal.onmap, "RIGHT", 2, 0) + pfUI.mapreveal.onmap.text:SetText(T["Reveal Unexplored Areas"]) + pfUI.mapreveal.onmap:SetScript("OnShow", function() + this:SetChecked(C.appearance.worldmap.mapreveal == "1") + end) + pfUI.mapreveal.onmap:SetScript("OnClick", function () + if this:GetChecked() then + C.appearance.worldmap.mapreveal = "1" + else + C.appearance.worldmap.mapreveal = "0" + end + pfUI.mapreveal:UpdateConfig() + end) + + local function unpack_hash(prefix, hash) + local _, stored_prefix, textureName, textureWidth, textureHeight, offsetX, offsetY, mapPointX, mapPointY, name + _, _, stored_prefix, textureName, textureWidth, textureHeight, offsetX, offsetY = string.find(hash, "^([|]?)([^:]+):([^:]+):([^:]+):([^:]+):([^:]+)") + if (not textureName or not offsetY) then + return + end + if (offsetY) then + _, _, mapPointX, mapPointY = string.find(hash,"^[|]?[^:]+:[^:]+:[^:]+:[^:]+:[^:]+:([^:]+):([^:]+)") + end + if (not mapPointY) then + mapPointX = 0 mapPointY = 0 + end + if (stored_prefix ~= "|") then + name = textureName + textureName = string.format("%s%s",prefix,textureName) + end + return textureName, textureWidth + 0, textureHeight + 0, offsetX + 0, offsetY + 0, mapPointX + 0, mapPointY + 0, name + end + + local explores = {} + local explorecaches = {} + local alreadyknown = {} -- per-zone accumulator: { [zone] = { [texName] = true } } + + -- Own texture pool - separate from Blizzard's WorldMapOverlay textures + local pfOverlays = {} + local pfOverlayMax = 0 + + local function pfGetOverlay(idx) + if not pfOverlays[idx] then + pfOverlays[idx] = WorldMapDetailFrame:CreateTexture("pfReveal"..idx, "BORDER") + end + return pfOverlays[idx] + end + + local exploreEnter = function() + WorldMapTooltip:ClearLines() + WorldMapTooltip:SetOwner(this, "ANCHOR_TOP") + WorldMapTooltip:AddLine(T["Exploration Point"]..":", .3, 1, .8) + WorldMapTooltip:AddLine(this.name, 1, 1, 1) + WorldMapTooltip:Show() + + if not explorecaches[this.name] then return end + if C.appearance.worldmap.mapreveal == "0" then return end + for texture in pairs(explorecaches[this.name]) do + texture:SetVertexColor(1,1,1,1) + end + end + + local exploreLeave = function() + WorldMapTooltip:Hide() + if not explorecaches[this.name] then return end + if C.appearance.worldmap.mapreveal == "0" then return end + local r,g,b,a = GetStringColor(C.appearance.worldmap.mapreveal_color) + for texture in pairs(explorecaches[this.name]) do + texture:SetVertexColor(r,g,b,a) + end + end + + -- overlay data with lazy init + local overlayData = setmetatable(pfMapOverlayData, {__index = function(t,k) + local v = {} + rawset(t,k,v) + return v + end}) + + local function pfWorldMapFrame_Update() + -- clear stale caches + for k in pairs(explorecaches) do explorecaches[k] = nil end + + -- hide all our textures from last frame + for i = 1, pfOverlayMax do + pfOverlays[i]:Hide() + end + + local r,g,b,a = GetStringColor(C.appearance.worldmap.mapreveal_color) + local mapFileName = GetMapInfo() + if not mapFileName then mapFileName = "World" end + + local prefix = string.format("Interface\\WorldMap\\%s\\", mapFileName) + local numOverlays = GetNumMapOverlays() + + -- accumulate explored overlays per zone (never clear, only add) + if not alreadyknown[mapFileName] then alreadyknown[mapFileName] = {} end + for i = 1, numOverlays do + local texName = GetMapOverlayInfo(i) + if texName then alreadyknown[mapFileName][string.upper(texName)] = true end + end + + local zoneKnown = alreadyknown[mapFileName] + + -- hide explore icons + for _, frame in pairs(explores) do frame:Hide() end + + local zoneData = overlayData[mapFileName] + local textureCount = 0 + + for i, hash in ipairs(zoneData) do + local textureName, textureWidth, textureHeight, offsetX, offsetY, mapPointX, mapPointY, name = unpack_hash(prefix, hash) + if not textureName then break end + + -- explore magnifying glass icon + explores[i] = explores[i] or CreateFrame("Frame", nil, WorldMapDetailFrame) + local explore = explores[i] + explore:SetWidth(16) + explore:SetHeight(16) + explore:SetPoint("TOPLEFT", "WorldMapDetailFrame", "TOPLEFT", offsetX + textureWidth/2, -offsetY - textureHeight/2) + explore:SetScript("OnEnter", exploreEnter) + explore:SetScript("OnLeave", exploreLeave) + explore:EnableMouse(true) + explore:SetFrameLevel(255) + explore.name = mapFileName .. " (" .. name .. ")" + explore.tex = explore.tex or explore:CreateTexture("", "OVERLAY") + explore.tex:SetBlendMode("ADD") + explore.tex:SetTexCoord(.08, .92, .08, .92) + explore.tex:SetAllPoints() + + if C.appearance.worldmap.mapexploration == "1" and not zoneKnown[string.upper(textureName)] then + explore.tex:SetTexture("Interface\\WorldMap\\WorldMap-MagnifyingGlass") + explore:Show() + else + explore:Hide() + end + + -- render overlay texture tiles on BORDER draw layer + -- Blizzard's explored overlays on ARTWORK draw on top of BORDER + if C.appearance.worldmap.mapreveal == "1" then + local numH = math.ceil(textureWidth / 256) + local numV = math.ceil(textureHeight / 256) + local texPixW, texFileW, texPixH, texFileH + + for j = 1, numV do + if j < numV then + texPixH = 256 + texFileH = 256 + else + texPixH = mod(textureHeight, 256) + if texPixH == 0 then texPixH = 256 end + texFileH = 16 + while texFileH < texPixH do texFileH = texFileH * 2 end + end + + for k = 1, numH do + textureCount = textureCount + 1 + local tex = pfGetOverlay(textureCount) + + if k < numH then + texPixW = 256 + texFileW = 256 + else + texPixW = mod(textureWidth, 256) + if texPixW == 0 then texPixW = 256 end + texFileW = 16 + while texFileW < texPixW do texFileW = texFileW * 2 end + end + + tex:SetWidth(texPixW) + tex:SetHeight(texPixH) + tex:SetTexCoord(0, texPixW/texFileW, 0, texPixH/texFileH) + tex:ClearAllPoints() + tex:SetPoint("TOPLEFT", "WorldMapDetailFrame", "TOPLEFT", offsetX + 256*(k-1), -(offsetY + 256*(j-1))) + tex:SetTexture(string.format("%s%s", textureName, ((j-1)*numH + k))) + + explorecaches[name] = explorecaches[name] or {} + explorecaches[name][tex] = true + + tex:SetVertexColor(r,g,b,a) + tex:Show() + end + end + end + end + + pfOverlayMax = math.max(pfOverlayMax, textureCount) + end + + -- hook WorldMapFrame_Update + local origUpdate = _G.WorldMapFrame_Update + _G.WorldMapFrame_Update = function(...) + origUpdate(unpack(arg)) + pfWorldMapFrame_Update() + end + +end) \ No newline at end of file