ElvUI/Core/MapInfo.lua

171 lines
6.0 KiB
Lua
Raw Normal View History

2020-11-13 14:27:50 -05:00
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
local pairs = pairs
local IsFalling = IsFalling
local CreateFrame = CreateFrame
local UnitPosition = UnitPosition
local GetUnitSpeed = GetUnitSpeed
local CreateVector2D = CreateVector2D
local GetRealZoneText = GetRealZoneText
local GetMinimapZoneText = GetMinimapZoneText
local C_Map_GetMapInfo = C_Map.GetMapInfo
local C_Map_GetBestMapForUnit = C_Map.GetBestMapForUnit
local C_Map_GetWorldPosFromMapPos = C_Map.GetWorldPosFromMapPos
local Enum_UIMapType = Enum.UIMapType
local MapUtil_GetMapParentInfo = MapUtil.GetMapParentInfo
E.MapInfo = {}
function E:MapInfo_Update()
local mapID = C_Map_GetBestMapForUnit('player')
local mapInfo = mapID and C_Map_GetMapInfo(mapID)
E.MapInfo.name = (mapInfo and mapInfo.name) or nil
E.MapInfo.mapType = (mapInfo and mapInfo.mapType) or nil
E.MapInfo.parentMapID = (mapInfo and mapInfo.parentMapID) or nil
E.MapInfo.mapID = mapID or nil
E.MapInfo.zoneText = (mapID and E:GetZoneText(mapID)) or nil
E.MapInfo.subZoneText = GetMinimapZoneText() or nil
E.MapInfo.realZoneText = GetRealZoneText() or nil
local continent = mapID and MapUtil_GetMapParentInfo(mapID, Enum_UIMapType.Continent, true)
E.MapInfo.continentParentMapID = (continent and continent.parentMapID) or nil
E.MapInfo.continentMapType = (continent and continent.mapType) or nil
E.MapInfo.continentMapID = (continent and continent.mapID) or nil
E.MapInfo.continentName = (continent and continent.name) or nil
E:MapInfo_CoordsUpdate()
end
local coordsWatcher = CreateFrame('Frame')
function E:MapInfo_CoordsStart()
E.MapInfo.coordsWatching = true
E.MapInfo.coordsFalling = nil
coordsWatcher:SetScript('OnUpdate', E.MapInfo_OnUpdate)
if E.MapInfo.coordsStopTimer then
E:CancelTimer(E.MapInfo.coordsStopTimer)
E.MapInfo.coordsStopTimer = nil
end
end
function E:MapInfo_CoordsStopWatching()
E.MapInfo.coordsWatching = nil
E.MapInfo.coordsStopTimer = nil
coordsWatcher:SetScript('OnUpdate', nil)
end
function E:MapInfo_CoordsStop(event)
if event == 'CRITERIA_UPDATE' then
if not E.MapInfo.coordsFalling then return end -- stop if we weren't falling
if (GetUnitSpeed('player') or 0) > 0 then return end -- we are still moving!
E.MapInfo.coordsFalling = nil -- we were falling!
elseif (event == 'PLAYER_STOPPED_MOVING' or event == 'PLAYER_CONTROL_GAINED') and IsFalling() then
E.MapInfo.coordsFalling = true
return
end
if not E.MapInfo.coordsStopTimer then
E.MapInfo.coordsStopTimer = E:ScheduleTimer('MapInfo_CoordsStopWatching', 0.5)
end
end
function E:MapInfo_CoordsUpdate()
if E.MapInfo.mapID then
E.MapInfo.x, E.MapInfo.y = E:GetPlayerMapPos(E.MapInfo.mapID)
else
E.MapInfo.x, E.MapInfo.y = nil, nil
end
if E.MapInfo.x and E.MapInfo.y then
E.MapInfo.xText = E:Round(100 * E.MapInfo.x, 2)
E.MapInfo.yText = E:Round(100 * E.MapInfo.y, 2)
else
E.MapInfo.xText, E.MapInfo.yText = nil, nil
end
end
function E:MapInfo_OnUpdate(elapsed)
self.lastUpdate = (self.lastUpdate or 0) + elapsed
if self.lastUpdate > 0.1 then
E:MapInfo_CoordsUpdate()
self.lastUpdate = 0
end
end
-- This code fixes C_Map.GetPlayerMapPosition memory leak.
-- Fix stolen from NDui (and modified by Simpy). Credit: siweia.
local mapRects, tempVec2D = {}, CreateVector2D(0, 0)
function E:GetPlayerMapPos(mapID)
tempVec2D.x, tempVec2D.y = UnitPosition('player')
if not tempVec2D.x then return end
local mapRect = mapRects[mapID]
if not mapRect then
local _, pos1 = C_Map_GetWorldPosFromMapPos(mapID, CreateVector2D(0, 0))
local _, pos2 = C_Map_GetWorldPosFromMapPos(mapID, CreateVector2D(1, 1))
if not pos1 or not pos2 then return end
mapRect = {pos1, pos2}
mapRect[2]:Subtract(mapRect[1])
mapRects[mapID] = mapRect
end
tempVec2D:Subtract(mapRect[1])
return (tempVec2D.y/mapRect[2].y), (tempVec2D.x/mapRect[2].x)
end
-- Code taken from LibTourist-3.0 and rewritten to fit our purpose
local localizedMapNames = {}
local ZoneIDToContinentName = {
[104] = 'Outland',
[107] = 'Outland',
}
local MapIdLookupTable = {
[101] = 'Outland',
[104] = 'Shadowmoon Valley',
[107] = 'Nagrand',
}
local function LocalizeZoneNames()
local mapInfo
for mapID, englishName in pairs(MapIdLookupTable) do
mapInfo = C_Map_GetMapInfo(mapID)
-- Add combination of English and localized name to lookup table
if mapInfo and mapInfo.name and not localizedMapNames[englishName] then
localizedMapNames[englishName] = mapInfo.name
end
end
end
LocalizeZoneNames()
--Add ' (Outland)' to the end of zone name for Nagrand and Shadowmoon Valley, if mapID matches Outland continent.
--We can then use this function when we need to compare the players own zone against return values from stuff like GetFriendInfo and GetGuildRosterInfo,
--which adds the ' (Outland)' part unlike the GetRealZoneText() API.
function E:GetZoneText(mapID)
if not (mapID and E.MapInfo.name) then return end
local continent, zoneName = ZoneIDToContinentName[mapID]
if continent and continent == 'Outland' then
if E.MapInfo.name == localizedMapNames.Nagrand or E.MapInfo.name == 'Nagrand' then
zoneName = localizedMapNames.Nagrand..' ('..localizedMapNames.Outland..')'
elseif E.MapInfo.name == localizedMapNames['Shadowmoon Valley'] or E.MapInfo.name == 'Shadowmoon Valley' then
zoneName = localizedMapNames['Shadowmoon Valley']..' ('..localizedMapNames.Outland..')'
end
end
return zoneName or E.MapInfo.name
end
E:RegisterEvent('CRITERIA_UPDATE', 'MapInfo_CoordsStop') -- when the player goes into an animation (landing)
E:RegisterEvent('PLAYER_STARTED_MOVING', 'MapInfo_CoordsStart')
E:RegisterEvent('PLAYER_STOPPED_MOVING', 'MapInfo_CoordsStop')
E:RegisterEvent('PLAYER_CONTROL_LOST', 'MapInfo_CoordsStart')
E:RegisterEvent('PLAYER_CONTROL_GAINED', 'MapInfo_CoordsStop')
E:RegisterEventForObject('LOADING_SCREEN_DISABLED', E.MapInfo, E.MapInfo_Update)
E:RegisterEventForObject('ZONE_CHANGED_NEW_AREA', E.MapInfo, E.MapInfo_Update)
E:RegisterEventForObject('ZONE_CHANGED_INDOORS', E.MapInfo, E.MapInfo_Update)
E:RegisterEventForObject('ZONE_CHANGED', E.MapInfo, E.MapInfo_Update)