diff --git a/TomTom.toc b/TomTom.toc
index d5557fc..99ab918 100755
--- a/TomTom.toc
+++ b/TomTom.toc
@@ -1,4 +1,4 @@
-## Interface: 70200
+## Interface: 70300
## Title: TomTom
## Author: jnwhiteh
## Version: @project-version@
diff --git a/libs/HereBeDragons-1.0/HereBeDragons-1.0.lua b/libs/HereBeDragons-1.0/HereBeDragons-1.0.lua
index 3379d06..6db3fca 100755
--- a/libs/HereBeDragons-1.0/HereBeDragons-1.0.lua
+++ b/libs/HereBeDragons-1.0/HereBeDragons-1.0.lua
@@ -1,6 +1,6 @@
-- HereBeDragons is a data API for the World of Warcraft mapping system
-local MAJOR, MINOR = "HereBeDragons-1.0", 21
+local MAJOR, MINOR = "HereBeDragons-1.0", 33
assert(LibStub, MAJOR .. " requires LibStub")
local HereBeDragons, oldversion = LibStub:NewLibrary(MAJOR, MINOR)
@@ -18,8 +18,6 @@ HereBeDragons.transforms = HereBeDragons.transforms or {}
HereBeDragons.callbacks = CBH:New(HereBeDragons, nil, nil, false)
-local IsLegion = select(4, GetBuildInfo()) >= 70000
-
-- constants
local TERRAIN_MATCH = "_terrain%d+$"
@@ -28,6 +26,7 @@ local PI2 = math.pi * 2
local atan2 = math.atan2
local pairs, ipairs = pairs, ipairs
local type = type
+local band = bit.band
-- WoW API upvalues
local UnitPosition = UnitPosition
@@ -61,9 +60,13 @@ local instanceIDOverrides = {
[1465] = 1116, -- Tanaan
-- Legion
[1478] = 1220, -- Temple of Elune Scenario (Val'Sharah)
+ [1495] = 1220, -- Protection Paladin Artifact Scenario (Stormheim)
+ [1498] = 1220, -- Havoc Demon Hunter Artifact Scenario (Suramar)
[1502] = 1220, -- Dalaran Underbelly
[1533] = 0, -- Karazhan Artifact Scenario
[1612] = 1220, -- Feral Druid Artifact Scenario (Suramar)
+ [1626] = 1220, -- Suramar Withered Scenario
+ [1662] = 1220, -- Suramar Invasion Scenario
}
-- unregister and store all WORLD_MAP_UPDATE registrants, to avoid excess processing when
@@ -86,7 +89,7 @@ local function RestoreWMU()
end
-- gather map info, but only if this isn't an upgrade (or the upgrade version forces a re-map)
-if not oldversion or oldversion < 21 then
+if not oldversion or oldversion < 33 then
-- wipe old data, if required, otherwise the upgrade path isn't triggered
if oldversion then
wipe(mapData)
@@ -111,13 +114,18 @@ if not oldversion or oldversion < 21 then
-- main draenor garrison maps
[971] = true,
[976] = true,
+
+ -- legion class halls
+ [1072] = { Z = 10, mapFile = "TrueshotLodge" }, -- true shot lodge
+ [1077] = { Z = 7, mapFile = "TheDreamgrove" }, -- dreamgrove
}
local function processTransforms()
wipe(transforms)
for _, tID in ipairs(GetWorldMapTransforms()) do
- local terrainMapID, newTerrainMapID, _, _, transformMinY, transformMaxY, transformMinX, transformMaxX, offsetY, offsetX = GetWorldMapTransformInfo(tID)
- if offsetY ~= 0 or offsetX ~= 0 then
+ local terrainMapID, newTerrainMapID, _, _, transformMinY, transformMaxY, transformMinX, transformMaxX, offsetY, offsetX, flags = GetWorldMapTransformInfo(tID)
+ -- flag 4 indicates the transform is only for the flight map
+ if band(flags, 4) ~= 4 and (offsetY ~= 0 or offsetX ~= 0) then
local transform = {
instanceID = terrainMapID,
newInstanceID = newTerrainMapID,
@@ -181,7 +189,7 @@ if not oldversion or oldversion < 21 then
-- store the original instance id (ie. not remapped for map transforms) for micro dungeons
mapData[id].originalInstance = originalInstanceID
- local mapFile = GetMapInfo()
+ local mapFile = type(REMAP_FIXUP_EXEMPT[id]) == "table" and REMAP_FIXUP_EXEMPT[id].mapFile or GetMapInfo()
if mapFile then
-- remove phased terrain from the map names
mapFile = mapFile:gsub(TERRAIN_MATCH, "")
@@ -191,6 +199,13 @@ if not oldversion or oldversion < 21 then
end
local C, Z = GetCurrentMapContinent(), GetCurrentMapZone()
+
+ -- maps that remap generally have wrong C/Z info, so allow the fixup table to override it
+ if type(REMAP_FIXUP_EXEMPT[id]) == "table" then
+ C = REMAP_FIXUP_EXEMPT[id].C or C
+ Z = REMAP_FIXUP_EXEMPT[id].Z or Z
+ end
+
mapData[id].C = C or -100
mapData[id].Z = Z or -100
@@ -204,22 +219,17 @@ if not oldversion or oldversion < 21 then
end
end
- local floors
- if IsLegion then
- floors = { GetNumDungeonMapLevels() }
+ -- retrieve floors
+ local floors = { GetNumDungeonMapLevels() }
- -- offset floors for terrain map
- if DungeonUsesTerrainMap() then
- for i = 1, #floors do
- floors[i] = floors[i] + 1
- end
- end
- else
- floors = {}
- for f = 1, GetNumDungeonMapLevels() do
- floors[f] = f
+ -- offset floors for terrain map
+ if DungeonUsesTerrainMap() then
+ for i = 1, #floors do
+ floors[i] = floors[i] + 1
end
end
+
+ -- check for fake floors
if #floors == 0 and GetCurrentMapDungeonLevel() > 0 then
floors[1] = GetCurrentMapDungeonLevel()
mapData[id].fakefloor = GetCurrentMapDungeonLevel()
@@ -244,7 +254,7 @@ if not oldversion or oldversion < 21 then
-- setup microdungeon storage if the its a zone map or has no floors of its own
if (mapData[id].C > 0 and mapData[id].Z > 0) or mapData[id].numFloors == 0 then
if not microDungeons[originalInstanceID] then
- microDungeons[originalInstanceID] = {}
+ microDungeons[originalInstanceID] = { global = {} }
end
end
end
@@ -259,8 +269,19 @@ if not oldversion or oldversion < 21 then
-- check if this zone can have microdungeons
if microDungeons[originalTerrainMapID] then
- microDungeons[originalTerrainMapID][floorIndex] = { maxX - minX, maxY - minY, maxX, maxY }
- microDungeons[originalTerrainMapID][floorIndex].instance = terrainMapID
+ -- store per-zone info
+ if not microDungeons[originalTerrainMapID][parentWorldMapID] then
+ microDungeons[originalTerrainMapID][parentWorldMapID] = {}
+ end
+
+ microDungeons[originalTerrainMapID][parentWorldMapID][floorIndex] = { maxX - minX, maxY - minY, maxX, maxY }
+ microDungeons[originalTerrainMapID][parentWorldMapID][floorIndex].instance = terrainMapID
+
+ -- store global info, as some microdungeon are associated to the wrong zone when phasing is involved (garrison, and more)
+ -- but only store the first, since there can be overlap on the same continent otherwise
+ if not microDungeons[originalTerrainMapID].global[floorIndex] then
+ microDungeons[originalTerrainMapID].global[floorIndex] = microDungeons[originalTerrainMapID][parentWorldMapID][floorIndex]
+ end
end
end
end
@@ -297,16 +318,6 @@ if not oldversion or oldversion < 21 then
mapData[WORLDMAP_AZEROTH_ID].Z = 0
mapData[WORLDMAP_AZEROTH_ID].name = WORLD_MAP
- -- we only have data for legion clients, zeroing the coordinates
- -- and niling out the floors temporarily disables the logic on live
- if not IsLegion then
- mapData[WORLDMAP_AZEROTH_ID][1] = 0
- mapData[WORLDMAP_AZEROTH_ID][2] = 0
- mapData[WORLDMAP_AZEROTH_ID][3] = 0
- mapData[WORLDMAP_AZEROTH_ID][4] = 0
- mapData[WORLDMAP_AZEROTH_ID].floors = {}
- end
-
-- alliance draenor garrison
if mapData[971] then
mapData[971].Z = 5
@@ -405,14 +416,19 @@ local function getMapDataTable(mapID, level)
if type(level) == "number" and level > 0 then
if data.floors[level] then
return data.floors[level]
- elseif data.originalInstance and microDungeons[data.originalInstance] and microDungeons[data.originalInstance][level] then
- return microDungeons[data.originalInstance][level]
+ elseif data.originalInstance and microDungeons[data.originalInstance] then
+ if microDungeons[data.originalInstance][mapID] and microDungeons[data.originalInstance][mapID][level] then
+ return microDungeons[data.originalInstance][mapID][level]
+ elseif microDungeons[data.originalInstance].global[level] then
+ return microDungeons[data.originalInstance].global[level]
+ end
end
else
return data
end
end
+local StartUpdateTimer
local function UpdateCurrentPosition()
UnregisterWMU()
@@ -447,10 +463,10 @@ local function UpdateCurrentPosition()
if prevContinent then
SetMapZoom(prevContinent)
else
- if prevMapID and prevMapID ~= newMapID then
+ -- reset map if it changed, or we need to go back to level 0
+ if prevMapID and (prevMapID ~= newMapID or (prevLevel ~= newLevel and prevLevel == 0)) then
SetMapByID(prevMapID)
end
- -- and level
if prevLevel and prevLevel > 0 then
SetDungeonMapLevel(prevLevel)
end
@@ -466,6 +482,31 @@ local function UpdateCurrentPosition()
currentPlayerZoneMapID, currentPlayerLevel, currentMapFile, currentMapIsMicroDungeon = newMapID, newLevel, microFile or mapFile, isMicroDungeon
HereBeDragons.callbacks:Fire("PlayerZoneChanged", currentPlayerZoneMapID, currentPlayerLevel, currentMapFile, currentMapIsMicroDungeon)
end
+
+ -- start a timer to update in micro dungeons since multi-level micro dungeons do not reliably fire events
+ if isMicroDungeon then
+ StartUpdateTimer()
+ end
+end
+
+-- upgradeable timer callback, don't want to keep calling the old function if the library is upgraded
+HereBeDragons.UpdateCurrentPosition = UpdateCurrentPosition
+local function UpdateTimerCallback()
+ -- signal that the timer ran
+ HereBeDragons.updateTimerActive = nil
+
+ -- run update now
+ HereBeDragons.UpdateCurrentPosition()
+end
+
+function StartUpdateTimer()
+ if not HereBeDragons.updateTimerActive then
+ -- prevent running multiple timers
+ HereBeDragons.updateTimerActive = true
+
+ -- and queue an update
+ C_Timer.After(1, UpdateTimerCallback)
+ end
end
local function OnEvent(frame, event, ...)
@@ -573,6 +614,7 @@ end
function HereBeDragons:GetWorldCoordinatesFromZone(x, y, zone, level)
local data = getMapDataTable(zone, level)
if not data or data[0] == 0 or data[1] == 0 then return nil, nil, nil end
+ if not x or not y then return nil, nil, nil end
local width, height, left, top = data[1], data[2], data[3], data[4]
x, y = left - width * x, top - height * y
@@ -589,6 +631,7 @@ end
function HereBeDragons:GetZoneCoordinatesFromWorld(x, y, zone, level, allowOutOfBounds)
local data = getMapDataTable(zone, level)
if not data or data[0] == 0 or data[1] == 0 then return nil, nil end
+ if not x or not y then return nil, nil end
local width, height, left, top = data[1], data[2], data[3], data[4]
x, y = (left - x) / width, (top - y) / height
@@ -625,6 +668,7 @@ end
-- @param dY destination Y
-- @return distance, deltaX, deltaY
function HereBeDragons:GetWorldDistance(instanceID, oX, oY, dX, dY)
+ if not oX or not oY or not dX or not dY then return nil, nil, nil end
local deltaX, deltaY = dX - oX, dY - oY
return (deltaX * deltaX + deltaY * deltaY)^0.5, deltaX, deltaY
end
@@ -685,7 +729,7 @@ end
function HereBeDragons:GetUnitWorldPosition(unitId)
-- get the current position
local y, x, z, instanceID = UnitPosition(unitId)
- if not x or not y then return nil, nil, nil end
+ if not x or not y then return nil, nil, instanceIDOverrides[instanceID] or instanceID end
-- return transformed coordinates
return applyCoordinateTransforms(x, y, instanceID)
@@ -697,7 +741,7 @@ end
function HereBeDragons:GetPlayerWorldPosition()
-- get the current position
local y, x, z, instanceID = UnitPosition("player")
- if not x or not y then return nil, nil, nil end
+ if not x or not y then return nil, nil, instanceIDOverrides[instanceID] or instanceID end
-- return transformed coordinates
return applyCoordinateTransforms(x, y, instanceID)
diff --git a/libs/HereBeDragons-1.0/HereBeDragons-Pins-1.0.lua b/libs/HereBeDragons-1.0/HereBeDragons-Pins-1.0.lua
index cc004d8..58b706c 100755
--- a/libs/HereBeDragons-1.0/HereBeDragons-Pins-1.0.lua
+++ b/libs/HereBeDragons-1.0/HereBeDragons-Pins-1.0.lua
@@ -1,6 +1,6 @@
-- HereBeDragons-Pins is a library to show pins/icons on the world map and minimap
-local MAJOR, MINOR = "HereBeDragons-Pins-1.0", 13
+local MAJOR, MINOR = "HereBeDragons-Pins-1.0", 16
assert(LibStub, MAJOR .. " requires LibStub")
local pins, oldversion = LibStub:NewLibrary(MAJOR, MINOR)
@@ -170,6 +170,16 @@ local function UpdateMinimapPins(force)
facing = lastFacing
end
+ -- check for all values to be available (starting with 7.1.0, instances don't report coordinates)
+ if not x or not y or (rotateMinimap and not facing) then
+ minimapPinCount = 0
+ for pin, data in pairs(activeMinimapPins) do
+ pin:Hide()
+ activeMinimapPins[pin] = nil
+ end
+ return
+ end
+
local newScale = pins.Minimap:GetScale()
if minimapScale ~= newScale then
minimapScale = newScale
@@ -239,6 +249,12 @@ local function UpdateMinimapIconPosition()
facing = lastFacing
end
+ -- check for all values to be available (starting with 7.1.0, instances don't report coordinates)
+ if not x or not y or (rotateMinimap and not facing) then
+ UpdateMinimapPins()
+ return
+ end
+
local refresh
local newScale = pins.Minimap:GetScale()
if minimapScale ~= newScale then
@@ -623,7 +639,7 @@ function pins:GetVectorToIcon(icon)
if not data then return nil, nil end
local x, y, instance = HBD:GetPlayerWorldPosition()
- if instance ~= data.instanceID then return nil end
+ if not x or not y or instance ~= data.instanceID then return nil end
return HBD:GetWorldVector(instance, x, y, data.x, data.y)
end