--------------------------
--[[ Settings ]]
--------------------------
local FadeAlpha=0.5;
----------------------------------
--[[ Helper Functions ]]
----------------------------------
local function DummyFunc() end-- Surprise for later
local GetNearestFlightPath; do-- name,distance=function()
local function GetRealCoordBounds()
local _,zx1,zy1,zx2,zy2=GetCurrentMapDungeonLevel();
zx1,zy1,zx2,zy2=zx1 or 0,zy1 or 0,zx2 or 0,zy2 or 0;
if zx1~=0 and zy1~=0 and zx2~=0 and zy2~=0 then return zx1,zy1,zx2,zy2; end-- Level-Specific Coords
_,zx1,zy1,zx2,zy2=GetCurrentMapZone();
zx1,zy1,zx2,zy2=zx1 or 0,zy1 or 0,zx2 or 0,zy2 or 0;
if zx1~=0 and zy1~=0 and zx2~=0 and zy2~=0 then return zx1,zy1,zx2,zy2; end-- General Map Coords
return nil,nil,nil,nil;-- No real coords
end
local function GetRealCoords(x,y)
if not (x and y and x~=0 and y~=0) then return nil,nil; end-- Invalid coords
local zx1,zy1,zx2,zy2=GetRealCoordBounds();
if not zx1 then return nil,nil; end-- No real coords
return (zx2-zx1)*x+zx1,(zy2-zy1)*y+zy1;
end
function GetNearestFlightPath()
-- Disable event to save CPU
local framelist={GetFramesRegisteredForEvent("WORLD_MAP_UPDATE")};
for _,frame in ipairs(framelist) do frame:UnregisterEvent("WORLD_MAP_UPDATE"); end
-- Save MapID and select current zone (MapID is invalid if viewing a continent, store that too)
local mapid,continent=GetCurrentMapAreaID(),GetCurrentMapContinent();
SetMapToCurrentZone();
local lowdist,lowname;
if GetCurrentMapContinent()==8 and GetCurrentMapZone()~=3 then-- Only work on outdoor Broken Isles zones (exclude Dalaran; Flight Whistle doesn't work there)
local py,px=UnitPosition("player");
for i=1,GetNumMapLandmarks() do
local id,name,_,_,x,y=GetMapLandmarkInfo(i);
x,y=GetRealCoords(x,y);
if id==5 then-- Flight paths are landmark ID 5
local dist=(px-x)^2+(py-y)^2;
if not lowdist or dist<lowdist then
lowdist,lowname=dist,name;-- Capture our shortest distance
end
end
end
if lowdist then lowdist=lowdist^0.5; end-- Apply square root outside of loop to save CPU
end
-- Restore map and enable event
if mapid>=0 then SetMapByID(mapid); else SetMapZoom(continent); end
for _,frame in ipairs(framelist) do frame:RegisterEvent("WORLD_MAP_UPDATE"); end
return lowname,lowdist;-- Most significant return is the name, distance is secondary
end
end
local NearestFlightPoint; do-- Tooltip pulls live data, POIs will use cached data since messing with WORLD_MAP_UPDATE causes problems there
local function UpdateFlightPointData()
NearestFlightPoint=GetNearestFlightPath();
C_Timer.After(0.5,UpdateFlightPointData);
end
UpdateFlightPointData();
end
--------------------------
--[[ API and Hooks ]]
--------------------------
local LastPOIState=false;
local function FadePOIs(fade)
if fade==nil then
fade=LastPOIState;-- Try to reapply if we're doing an update run
else
if fade==LastPOIState then return; end-- Don't run this function again if we're setting the state to what's already applied
LastPOIState=fade;-- Update our upvalue
end
do local px,py=GetPlayerMapPosition("player");-- Simple map presence check
if not (px and py and px~=0 and py~=0) then fade=false; end-- Force restore if we're not on the map
end
-- Find our nearest flight path
local name=NearestFlightPoint;
if not name then fade=false; end-- Don't fade if we didn't find any flight paths
-- Apply fade to POIs
for i=1,math.min(GetNumMapLandmarks(),NUM_WORLDMAP_POIS) do-- Sanity check (don't run on POIs that haven't been created yet)
local poi=_G["WorldMapFramePOI"..i];
if poi.landmarkType==5 then-- Flight paths are landmark ID 5
poi:SetAlpha((poi.name~=name and fade) and FadeAlpha or 1);
if poi.name==name and fade then
WorldMapPing:SetPoint("CENTER",poi);-- Move WorldMapPing
WorldMapPing.SetPoint=DummyFunc;-- Stop WorldMapButton_OnUpdate() from resetting our position
WorldMapPing.Ping:Play();-- Play animation
end
else
poi:SetAlpha(1);-- Update in case map changed and we have new POIs
end
end
end
-- Hook switching zone maps and WorldMapFrame animations
local function UpdateFade() FadePOIs(nil); end
hooksecurefunc("WorldMap_UpdateLandmarks",UpdateFade);
WorldMapFrame.AnimAlphaIn:HookScript("OnFinished",UpdateFade);
WorldMapFrame.AnimAlphaOut:HookScript("OnFinished",UpdateFade);
WorldMapPing.Ping:HookScript("OnStop",function(self) WorldMapPing.SetPoint=nil; end);-- Restore normal behavior by removing our modification
-- Hook Flight Whistle tooltip
GameTooltip:HookScript("OnTooltipSetItem",function(self,...)
local _,link=self:GetItem();
if link and link:find("|Hitem:141605[:|]") then
local name,dist=GetNearestFlightPath();
if name and dist then self:AddDoubleLine(name,BreakUpLargeNumbers(math.floor(dist)).." yds",0.5,0.5,0.5,0.5,0.5,0.5); end
end
end);
--------------------------
--[[ Event Handler ]]
--------------------------
local EventFrame=CreateFrame("Frame");
EventFrame:RegisterUnitEvent("UNIT_SPELLCAST_START","player");
EventFrame:RegisterUnitEvent("UNIT_SPELLCAST_STOP","player");
EventFrame:RegisterUnitEvent("UNIT_SPELLCAST_INTERRUPTED","player");
EventFrame:RegisterUnitEvent("UNIT_SPELLCAST_SUCCEEDED","player");
EventFrame:SetScript("OnEvent",function(self,event,unit,_,_,_,spellid)
if spellid==227334 then-- SpellID of Flight Whistle
FadePOIs(event=="UNIT_SPELLCAST_START");-- Fade on start, restore on others
end
end);