Quantcast

Initial revamp for 4.X mapping system

James Whitehead II [01-16-11 - 22:36]
Initial revamp for 4.X mapping system

There are many things still broken and not quite working, but I am
trying to test them as much and as quickly as possible.
Filename
TomTom.lua
TomTom.toc
TomTom_Config.lua
TomTom_CrazyArrow.lua
TomTom_POIIntegration.lua
TomTom_Waypoints.lua
libs/LibMapData-1.0/library.lua
diff --git a/TomTom.lua b/TomTom.lua
index 62dbf13..7f77a93 100755
--- a/TomTom.lua
+++ b/TomTom.lua
@@ -5,6 +5,8 @@
 -- Simple localization table for messages
 local L = TomTomLocals
 local ldb = LibStub("LibDataBroker-1.1")
+local astrolabe = DongleStub("Astrolabe-1.0")
+local lmd = LibStub("LibMapData-1.0")

 -- Create the addon object
 TomTom = {
@@ -24,82 +26,6 @@ TomTom = {
 if TomTom.version == "wowi:revision" then TomTom.version = "SVN" end
 if TomTom.version == "@project-version@" then TomTom.version = "SCM" end

---[[--------------------------------------------------------------------------
---  Astrolabe compatability library
-----------------------------------------------------------------------------]]
-
-local compat = {}
-TomTom.compat = compat
-
-do
-    local Astrolabe = DongleStub("Astrolabe-1.0")
-
-    local orig = GetCurrentMapAreaID()
-
-    -- Create a lookup table from mapID to c,z pairs
-    local mapcz = {}
-    for cid, zlist in ipairs{GetMapContinents()} do
-        for zid, mapid in ipairs{GetMapZones(cid)} do
-            SetMapZoom(cid, zid)
-            local mapid = GetCurrentMapAreaID()
-            mapcz[mapid] = {cid, zid}
-        end
-    end
-
-    SetMapByID(orig)
-
-    -- Speed up minimap updates
-    Astrolabe.MinimapUpdateTime = 0.1
-
-    -- This function takes the mapID return from the Astrolabe function
-    -- and converts it to a c,z,x,y tuple
-    function compat:GetCurrentPlayerPosition()
-        local map, floor, x, y = Astrolabe:GetCurrentPlayerPosition()
-        local cz = mapcz[map]
-        if cz then
-            local c, z = unpack(cz)
-            return c, z, x, y
-        end
-    end
-
-    function compat:GetCurrentPlayerCoords()
-        local map, floor, x, y = Astrolabe:GetCurrentPlayerPosition()
-        return x, y
-    end
-
-    function compat:GetDirectionToIcon(...)
-        return Astrolabe:GetDirectionToIcon(...)
-    end
-
-    function compat:GetDistanceToIcon(...)
-        return Astrolabe:GetDistanceToIcon(...)
-    end
-
-    function compat:RemoveIconFromMinimap(...)
-        return Astrolabe:RemoveIconFromMinimap(...)
-    end
-
-    function compat:IsIconOnEdge(...)
-        return Astrolabe:IsIconOnEdge(...)
-    end
-
-    function compat:PlaceIconOnMinimap(icon, c, z, x, y)
-        local mapId = Astrolabe:GetMapID(c, z)
-        local floors = Astrolabe:GetNumFloors(mapId)
-        local floor = floors == 0 and 0 or 1
-        return Astrolabe:PlaceIconOnMinimap(icon, mapId, floor, x, y)
-    end
-
-    function compat:PlaceIconOnWorldMap(frame, icon, c, z, x, y)
-        local mapId = Astrolabe:GetMapID(c, z)
-        local floors = Astrolabe:GetNumFloors(mapId)
-        local floor = floors == 0 and 0 or 1
-
-        return Astrolabe:PlaceIconOnWorldMap(frame, icon, mapId, floor, x, y)
-    end
-
-end
-
 TomTom.eventFrame:SetScript("OnEvent", function(self, event, ...)
 	local method = TomTom.events[event]
 	if method and TomTom[method] then
@@ -112,7 +38,7 @@ TomTom:RegisterEvent("ADDON_LOADED")
 -- Local definitions
 local GetCurrentCursorPosition
 local WorldMap_OnUpdate
-local Block_OnClick,Block_OnUpdate,BlockOnEnter,BlockOnLeave
+local Block_OnClick,Block_OnUpdate,Block_OnEnter,Block_OnLeave
 local Block_OnDragStart,Block_OnDragStop
 local callbackTbl
 local RoundCoords
@@ -138,6 +64,7 @@ function TomTom:ADDON_LOADED(event, addon)
 					height = 30,
 					width = 100,
 					fontsize = 12,
+                    throttle = 0.2,
 				},
 				mapcoords = {
 					playerenable = true,
@@ -203,13 +130,18 @@ function TomTom:ADDON_LOADED(event, addon)
 		}

 		self.waydefaults = {
+            global = {
+                converted = {
+                    ["*"] = {},
+                },
+            },
 			profile = {
 				["*"] = {},
 			},
 		}

 		self.db = LibStub("AceDB-3.0"):New("TomTomDB", self.defaults, "Default")
-		self.waydb = LibStub("AceDB-3.0"):New("TomTomWaypoints", self.waydefaults)
+		self.waydb = LibStub("AceDB-3.0"):New("TomTomWaypointsMF", self.waydefaults)

 		self.db.RegisterCallback(self, "OnProfileChanged", "ReloadOptions")
 		self.db.RegisterCallback(self, "OnProfileCopied", "ReloadOptions")
@@ -223,13 +155,13 @@ function TomTom:ADDON_LOADED(event, addon)

 		self.dropdown = CreateFrame("Frame", "TomTomDropdown", nil, "UIDropDownMenuTemplate")

+        -- Both the waypoints and waypointprofile tables are going to contain subtables for each
+        -- of the mapids that might exist. Under these will be a hash of key/waypoint pairs consisting
+        -- of the waypoints for the given map file.
 		self.waypoints = waypoints
 		self.waypointprofile = self.waydb.profile

 		self:RegisterEvent("PLAYER_LEAVING_WORLD")
-		self:RegisterEvent("PLAYER_ENTERING_WORLD", "ZoneChanged")
-		self:RegisterEvent("ZONE_CHANGED_NEW_AREA", "ZoneChanged")
-		self:RegisterEvent("WORLD_MAP_UPDATE", "ZoneChanged")
 		self:RegisterEvent("CHAT_MSG_ADDON")

 		self:ReloadOptions()
@@ -245,6 +177,9 @@ function TomTom:ADDON_LOADED(event, addon)

 			local coordFeedFrame = CreateFrame("Frame")
 			local throttle, counter = self.db.profile.feeds.coords_throttle, 0
+            function TomTom:_privateupdatecoordthrottle(x)
+                throttle = x
+            end

 			coordFeedFrame:SetScript("OnUpdate", function(self, elapsed)
 				counter = counter + elapsed
@@ -253,19 +188,63 @@ function TomTom:ADDON_LOADED(event, addon)
 				end

 				counter = 0
-				local x,y = compat:GetCurrentPlayerCoords()
-				local opt = TomTom.db.profile
+                local m, f, x, y = TomTom:GetCurrentPlayerPosition()

 				if x and y then
-					feed_coords.text = string.format("%s", RoundCoords(x, y, opt.feeds.coords_accuracy))
+                    local opt = TomTom.db.profile.feeds
+					feed_coords.text = string.format("%s", RoundCoords(x, y, opt.coords_accuracy))
 				end
 			end)
 		end
 	end
 end

-function TomTom:UpdateCoordFeedThrottle()
-    throttle = self.db.profile.feeds.coords_throttle
+-- Some utility functions that can pack/unpack data from a waypoint
+
+-- Returns a hashable 'key' for a given waypoint consisting of the
+-- map, floor, x, y and the waypoints title. This isn't truly
+-- unique, but should be close enough to determine duplicates, etc.
+function TomTom:GetKey(waypoint)
+    local m,f,x,y = unpack(waypoint)
+    return self:GetKeyArgs(m, f, x, y, waypoint.title)
+end
+
+function TomTom:GetKeyArgs(m, f, x, y, title)
+    if not f then
+        local floors = astrolabe:GetNumFloors(m)
+        f = floors == 0 and 0 or 1
+    end
+
+    return string.format("%d:%d:%d:%d:%s", m, f, x, y, tostring(title))
+end
+
+local flipFixFrame = CreateFrame("Frame", "TomTomMapFlipFixFrame", UIParent)
+do
+    local throttle = 0.25
+    local counter = 0
+    flipFixFrame:SetScript("OnUpdate", function(self, elapsed)
+        counter = counter + elapsed
+        if counter >= throttle then
+            counter = counter - throttle
+            if not WorldMapFrame:IsVisible() and not WorldMapFrame:IsShown() then
+                local x, y = GetPlayerMapPosition("player")
+                if x <= 0 or y <= 0 then
+                    -- Flip the map, do not flip it back
+                    SetMapToCurrentZone()
+                end
+            end
+        end
+    end)
+end
+
+function TomTom:GetCurrentPlayerPosition()
+    -- Try to get the position without 'flipping' the map
+    local m, f, x, y = astrolabe:GetUnitPosition("player", false)
+    if m and x and y and not (x <= 0 or y <= 0) then
+        local floors = astrolabe:GetNumFloors(m)
+        local floor = floors == 0 and 0 or 1
+        return m, floor, x, y
+    end
 end

 function TomTom:ReloadOptions()
@@ -278,34 +257,47 @@ function TomTom:ReloadOptions()
     self:EnableDisablePOIIntegration()
 end

-function TomTom:ReloadWaypoints()
-	local pc, pz = GetCurrentMapContinent(), GetCurrentMapZone()
+function TomTom:ClearAllWaypoints()
+    for mapId, entries in pairs(waypoints) do
+        for key, waypoint in pairs(entries) do
+            -- The waypoint IS the UID now
+            self:ClearWaypoint(waypoint)
+        end
+    end
+end

-	for uid,value in pairs(waypoints) do
-		self:ClearWaypoint(uid)
-	end
+function TomTom:ReloadWaypoints()
+    self:ClearAllWaypoints()

 	waypoints = {}
 	self.waypoints = waypoints
 	self.waypointprofile = self.waydb.profile

-	for zone,data in pairs(self.waypointprofile) do
-		local c,z = self:GetCZ(zone)
-		local same = (c == pc) and (z == pz)
+    local cm, cf, cx, cy = astrolabe:GetCurrentPlayerPosition()
+
+	for mapId,data in pairs(self.waypointprofile) do
+		local same = mapId == cm
 		local minimap = self.profile.minimap.enable and (self.profile.minimap.otherzone or same)
 		local world = self.profile.worldmap.enable and (self.profile.worldmap.otherzone or same)
-		for idx,waypoint in ipairs(data) do
-			local coord,title = waypoint:match("^(%d+):(.*)$")
-			if not title:match("%S") then title = nil end
-			local x,y = self:GetXY(coord)
-			self:AddZWaypoint(c, z, x*100, y*100, title, false, minimap, world, nil, true)
+		for key,waypoint in pairs(data) do
+            local m,f,x,y = unpack(waypoint)
+            local title = waypoint.title
+
+            self:AddMFWaypoint(m, f, x, y, {
+                desc = title,
+                title = title,
+                persistent = waypoint.persistent,
+                minimap = minimap,
+                world = world,
+                custom_callbacks = nil,
+                silent = true,
+            })
 		end
 	end
 end

-function TomTom:ZoneChanged()
-	-- Update the visibility of the coordinate box
-	self:ShowHideCoordBlock()
+function TomTom:UpdateCoordFeedThrottle()
+    self:_privateupdatecoordthrottle(self.db.profile.feeds.coords_throttle)
 end

 -- Hook some global functions so we know when the world map size changes
@@ -435,15 +427,14 @@ WorldMapButton_OnClick = function(self, ...)
 			end
 		end

-		-- Actually try to add a note
-		local c,z = GetCurrentMapContinent(), GetCurrentMapZone()
+        local m,f = GetCurrentMapAreaID()
 		local x,y = GetCurrentCursorPosition()

-		if z == 0 then
+		if not m then
 			return origScript and origScript(self, ...) or true
 		end

-		local uid = TomTom:AddZWaypoint(c,z,x*100,y*100)
+		local uid = TomTom:AddMFWaypoint(m,f,x,y)
 	else
 		return origScript and origScript(self, ...) or true
 	end
@@ -497,7 +488,7 @@ local dropdown_info = {
 			text = L["Set as waypoint arrow"],
 			func = function()
 				local uid = TomTom.dropdown.uid
-				local data = waypoints[uid]
+                local data = uid
 				TomTom:SetCrazyArrow(uid, TomTom.profile.arrow.arrival, data.title or L["TomTom waypoint"])
 			end,
 		},
@@ -511,8 +502,8 @@ local dropdown_info = {
 			text = L["Remove waypoint"],
 			func = function()
 				local uid = TomTom.dropdown.uid
-				local data = waypoints[uid]
-				TomTom:RemoveWaypoint(uid)
+				local data = uid
+                TomTom:RemoveWaypoint(uid)
 				--TomTom:PrintF("Removing waypoint %0.2f, %0.2f in %s", data.x, data.y, data.zone)
 			end,
 		},
@@ -520,9 +511,10 @@ local dropdown_info = {
 			text = L["Remove all waypoints from this zone"],
 			func = function()
 				local uid = TomTom.dropdown.uid
-				local data = waypoints[uid]
-				for uid in pairs(waypoints[data.zone]) do
-					TomTom:RemoveWaypoint(uid)
+				local data = uid
+                local mapId = data[1]
+				for key, waypoint in pairs(waypoints[mapId]) do
+					TomTom:RemoveWaypoint(waypoint)
 				end
 			end,
 		},
@@ -543,32 +535,21 @@ local dropdown_info = {
 				return TomTom:UIDIsSaved(TomTom.dropdown.uid)
 			end,
 			func = function()
-				-- Check to see if it's already saved
-				local uid = TomTom.dropdown.uid
-				if TomTom:UIDIsSaved(uid) then
-					local data = waypoints[uid]
-					if data then
-						local key = string.format("%d:%s", data.coord, data.title or "")
-						local zone = data.zone
-						local sv = TomTom.waypointprofile[zone]
-
-						-- Find the entry in the saved variable
-						for idx,entry in ipairs(sv) do
-							if entry == key then
-								table.remove(sv, idx)
-								return
-							end
-						end
-					end
-				else
-					local data = waypoints[uid]
-					if data then
-						local key = string.format("%d:%s", data.coord, data.title or "")
-						local zone = data.zone
-						local sv = TomTom.waypointprofile[zone]
-						table.insert(sv, key)
-					end
-				end
+                -- Add/remove it from the SV file
+                local uid = TomTom.dropdown.uid
+                local data = waypoints[uid]
+                if data then
+                    local key = TomTom:GetKey(data)
+                    local mapId = data[1]
+
+                    if mapId then
+                        if UIDIsSavedTomTom.waypointprofile[mapId][key] then
+                            TomTom.waypointprofile[mapId][key] = nil
+                        else
+                            TomTom.waypointprofile[mapId][key] = data
+                        end
+                    end
+                end
 			end,
 		},
 	},
@@ -646,47 +627,38 @@ function TomTom:InitializeDropdown(uid)
 	UIDropDownMenu_Initialize(self.dropdown, init_dropdown)
 end

-function TomTom:GetData(uid)
-    local data = waypoints[uid]
-    return data
-end
-
 function TomTom:UIDIsSaved(uid)
-	local data = waypoints[uid]
+	local data = uid
 	if data then
-		local key = string.format("%d:%s", data.coord, data.title or "")
-		local zone = data.zone
-		local sv = TomTom.waypointprofile[zone]
-
-		-- Find the entry in the saved variable
-		for idx,entry in ipairs(sv) do
-			if entry == key then
-				return true
-			end
-		end
+        local key = TomTom:GetKey(data)
+        local mapId = data[1]
+
+        if data then
+            return not not TomTom.waypointprofile[mapId][key]
+        end
 	end
 	return false
 end

 function TomTom:SendWaypoint(uid, channel)
-	local data = waypoints[uid]
-	local msg = string.format("%s:%d:%s", data.zone, data.coord, data.title or "")
-	SendAddonMessage("TOMTOM2", msg, channel)
+	local data = uid
+    local m, f, x, y = unpack(data)
+	local msg = string.format("%d:%d:%f:%f:%s", m, f, x, y, data.title or "")
+	SendAddonMessage("TOMTOM3", msg, channel)
 end

 function TomTom:CHAT_MSG_ADDON(event, prefix, data, channel, sender)
-	if prefix ~= "TOMTOM2" then return end
+	if prefix ~= "TOMTOM3" then return end
 	if sender == UnitName("player") then return end

-	local zone,coord,title = string.split(":", data)
+	local m,f,x,y,title = string.split(":", data)
 	if not title:match("%S") then
 		title = string.format(L["Waypoint from %s"], sender)
 	end

-	local c,z = self:GetCZ(zone)
-	local x,y = self:GetXY(tonumber(coord))
-	self:AddZWaypoint(c, z, x*100, y*100, title)
-	local msg = string.format(L["|cffffff78TomTom|r: Added '%s' (sent from %s) to zone %s"], title, sender, zone)
+    local zoneName = lmd:MapLocalize(m)
+	self:AddMFWaypoint(m, f, x, y, title)
+	local msg = string.format(L["|cffffff78TomTom|r: Added '%s' (sent from %s) to zone %s"], title, sender, zoneName)
 	ChatFrame1:AddMessage(msg)
 end

@@ -708,7 +680,7 @@ local function _world_onclick(event, uid, self, button)
 end

 local function _both_tooltip_show(event, tooltip, uid, dist)
-	local data = waypoints[uid]
+	local data = uid

 	tooltip:SetText(data.title or L["TomTom waypoint"])
 	if dist and tonumber(dist) then
@@ -716,7 +688,10 @@ local function _both_tooltip_show(event, tooltip, uid, dist)
 	else
 		tooltip:AddLine(L["Unknown distance"])
 	end
-	tooltip:AddLine(string.format(L["%s (%.2f, %.2f)"], data.zone, data.x, data.y), 0.7, 0.7, 0.7)
+    local m,f,x,y = unpack(data)
+    local zoneName = lmd:MapLocalize(m)
+
+	tooltip:AddLine(string.format(L["%s (%.2f, %.2f)"], zoneName, x*100, y*100), 0.7, 0.7, 0.7)
 	tooltip:Show()
 end

@@ -757,50 +732,38 @@ local function _both_ping_arrival(event, uid, range, distance, lastdistance)
 end

 local function _remove(event, uid)
-	local data = waypoints[uid]
-	local key = string.format("%d:%s", data.coord, data.title or "")
-	local zone = data.zone
-	local sv = TomTom.waypointprofile[zone]
-
-	-- Find the entry in the saved variable
-	for idx,entry in ipairs(sv) do
-		if entry == key then
-			table.remove(sv, idx)
-			break
-		end
-	end
+	local data = uid
+    local key = TomTom:GetKey(data)
+    local mapId = data[1]
+	local sv = TomTom.waypointprofile[mapId]
+
+    if sv and sv[key] then
+        sv[key] = nil
+    end

 	-- Remove this entry from the waypoints table
-	waypoints[uid] = nil
-	if waypoints[zone] then
-		waypoints[zone][uid] = nil
+	if waypoints[mapId] then
+		waypoints[mapId][key] = nil
 	end
 end

 local function noop() end

 function TomTom:RemoveWaypoint(uid)
-	local data = waypoints[uid]
+	local data = uid
 	self:ClearWaypoint(uid)

-	if data then
-		local key = string.format("%d:%s", data.coord, data.title or "")
-		local zone = data.zone
-		local sv = TomTom.waypointprofile[zone]
-
-		-- Find the entry in the saved variable
-		for idx,entry in ipairs(sv) do
-			if entry == key then
-				table.remove(sv, idx)
-				break
-			end
-		end
-	end
+    local key = TomTom:GetKey(data)
+    local mapId = data[1]
+	local sv = TomTom.waypointprofile[mapId]
+
+    if sv and sv[key] then
+        sv[key] = nil
+    end

 	-- Remove this entry from the waypoints table
-	waypoints[uid] = nil
-	if data and data.zone and waypoints[data.zone] then
-		waypoints[data.zone][uid] = nil
+	if waypoints[mapId] then
+		waypoints[mapId][key] = nil
 	end
 end

@@ -813,13 +776,39 @@ function TomTom:AddWaypoint(x, y, desc, persistent, minimap, world, silent)
 		return
 	end

-	return self:AddZWaypoint(c, z, x, y, desc, persistent, minimap, world, silent)
+	return self:AddZWaypoint(c, z, x/100, y/100, desc, persistent, minimap, world, nil, silent)
 end

 function TomTom:AddZWaypoint(c, z, x, y, desc, persistent, minimap, world, custom_callbacks, silent, crazy)
+    -- Convert the c,z,x,y tuple to m,f,x,y and pass the work off to AddMFWaypoint()
+    local mapId, floor = astrolabe:GetMapID(c, z)
+    if not mapId then
+        return
+    end
+
+    return self:AddMFWaypoint(mapId, floor, x/100, y/100, {
+        title = desc,
+        persistent = persistent,
+        minimap = minimap,
+        world = world,
+        custom_callbacks = custom_callbacks,
+        silent = silent,
+        crazy = crazy,
+    })
+end
+
+function TomTom:AddMFWaypoint(m, f, x, y, opts)
+    opts = opts or {}
+
+    print("AddMFWaypoint", m, f, x, y, opts and opts.title)
+    if opts then
+        for k,v in pairs(opts) do
+            print("option:", k, v)
+        end
+    end
 	local callbacks
-	if custom_callbacks then
-		callbacks = custom_callbacks
+	if opts.custom_callbacks then
+		callbacks = opts.custom_callbacks
 	else
 		callbacks = {
 			minimap = {
@@ -854,150 +843,98 @@ function TomTom:AddZWaypoint(c, z, x, y, desc, persistent, minimap, world, custo
         end
 	end

-
 	-- Default values
-	if persistent == nil then persistent = self.profile.persistence.savewaypoints end
-	if minimap == nil then minimap = self.profile.minimap.enable end
-	if world == nil then world = self.profile.worldmap.enable end
-	if crazy == nil then crazy = self.profile.arrow.autoqueue end
+	if opts.persistent == nil then opts.persistent = self.profile.persistence.savewaypoints end
+	if opts.minimap == nil then opts.minimap = self.profile.minimap.enable end
+	if opts.world == nil then opts.world = self.profile.worldmap.enable end
+	if opts.crazy == nil then opts.crazy = self.profile.arrow.autoqueue end

-	local coord = self:GetCoord(x / 100, y / 100)
-	local zone = self:GetMapFile(c, z)
+    local zoneName = lmd:MapLocalize(m)

-	if not zone then
+    if not astrolabe:GetMapInfo(m) then
 		return
 	end

+    -- Get the default map floor, if necessary
+    if not f then
+        local floors = astrolabe:GetNumFloors(m)
+        f = floors == 0 and 0 or 1
+    end
+
 	-- Ensure there isn't already a waypoint at this location
-	if waypoints[zone] then
-		for uid in pairs(waypoints[zone]) do
-			local data = waypoints[uid]
-			if data.title == desc and data.coord == coord then
-				-- This is a duplicate waypoint, so return that uid
-				return uid
-			end
-		end
-	end
+    local key = self:GetKey({m, f, x, y, title = opts.title})
+    if waypoints[m] and waypoints[m][key] then
+        return waypoints[m][key]
+    end

-	local uid = self:SetWaypoint(c,z,x/100,y/100, callbacks, minimap, world)
-	if crazy then
-		self:SetCrazyArrow(uid, self.profile.arrow.arrival, desc)
-	end
+    -- uid is the 'new waypoint' called this for historical reasons
+    local uid = {m, f, x, y, title = opts.title}

-	waypoints[uid] = {
-		title = desc,
-		coord = coord,
-		x = x,
-		y = y,
-		zone = zone,
-	}
+    -- Copy over any options, so we have em
+    for k,v in pairs(opts) do
+        if not uid[k] then
+            uid[k] = v
+        end
+    end

-	if not waypoints[zone] then
-		waypoints[zone] = {}
+    -- No need to convert x and y because they're already 0-1 instead of 0-100
+	self:SetWaypoint(uid, callbacks, opts.minimap, opts.world)
+	if opts.crazy then
+		self:SetCrazyArrow(uid, self.profile.arrow.arrival, opts.title)
 	end

-	waypoints[zone][uid] = true
+    waypoints[m] = waypoints[m] or {}
+    waypoints[m][key] = uid

 	-- If this is a persistent waypoint, then add it to the waypoints table
-	if persistent then
-		local data = string.format("%d:%s", coord, desc or "")
-		table.insert(self.waypointprofile[zone], data)
+	if opts.persistent then
+        self.waypointprofile[m][key] = uid
 	end

-	if not silent and self.profile.general.announce then
-		local ctxt = RoundCoords(x/100, y/100, 2)
-        local msg = string.format(L["|cffffff78TomTom:|r Added a waypoint (%s%s%s) in %s"], desc and desc or "", desc and " - " or "", ctxt, zone)
+	if not opts.silent and self.profile.general.announce then
+		local ctxt = RoundCoords(x, y, 2)
+        local desc = opts.desc and opts.desc or ""
+        local sep = opts.desc and " - " or ""
+        local msg = string.format(L["|cffffff78TomTom:|r Added a waypoint (%s%s%s) in %s"], desc, sep, ctxt, zoneName)
 		ChatFrame1:AddMessage(msg)
 	end

 	return uid
 end

-function TomTom:WaypointExists(c, z, x, y, desc)
-    local coord = self:GetCoord(x / 100, y / 100)
-    local zone = self:GetMapFile(c, z)
-
-    if not zone then
-        return
+-- Check to see if a given uid/waypoint is actually set somewhere
+function TomTom:IsValidWaypoint(waypoint)
+    local m = waypoint[1]
+    local key = self:GetKey(waypoint)
+    if waypoints[m] and waypoints[m][key] then
+        return true
+    else
+        return false
     end
+end

-    if waypoints[zone] then
-        for uid in pairs(waypoints[zone]) do
-            local data = waypoints[uid]
-            if data.title == desc then
-                return true
-            else
-                return false
-            end
-        end
+function TomTom:WaypointMFExists(m, f, x, y, desc)
+    local key = self:GetKeyArgs(m, f, x, y, desc)
+    if waypoints[m] and waypoints[m][key] then
+        return true
+    else
+        return false
     end
 end

-function TomTom:SetCustomWaypoint(c,z,x,y,callback,minimap,world, silent)
-	return self:AddZWaypoint(c, z, x, y, desc, false, minimap, world, callback, silent)
+function TomTom:WaypointExists(c, z, x, y, desc)
+    local m, f = astrolabe:GetMapID(c, z)
+    return self:WaypointMFExists(m, f, x, y, desc)
 end

-do
-    -- Code to convert between a MapFile ane a C,Z tuple
-    -- This no longer can use Astrolabe to build these tables
-
-    local Astrolabe = DongleStub("Astrolabe-1.0")
-    -- Code taken from HandyNotes, thanks Xinhuan
-    ---------------------------------------------------------
-    -- Public functions for plugins to convert between MapFile <-> C,Z
-    --
-    local continentMapFile = {
-        [WORLDMAP_COSMIC_ID] = "Cosmic", -- That constant is -1
-        [0] = "World",
-        [1] = "Kalimdor",
-        [2] = "Azeroth",
-        [3] = "Expansion01",
-        [4] = "Northrend",
-        [5] = "TheMaelstromContinent",
-    }
-    local mapCZtoFile = {}
-    _G.mc = mapCZtoFile
-    local reverseMapFileC = {}
-    local reverseMapFileZ = {}
-
-    for cid, zlist in pairs{GetMapContinents()} do
-        for zid, zname in pairs{GetMapZones(cid)} do
-            SetMapZoom(cid, zid)
-            local mapFile = GetMapInfo()
-            reverseMapFileC[mapFile] = cid
-            reverseMapFileZ[mapFile] = zid
-            mapCZtoFile[cid] = mapCZtoFile[cid] or {}
-            mapCZtoFile[cid][zid] = mapCZtoFile[cid][zid] or {}
-            mapCZtoFile[cid][zid] = mapFile
-        end
-    end
-
-    for cid, mapFile in pairs(continentMapFile) do
-        reverseMapFileC[mapFile] = cid
-        reverseMapFileZ[mapFile] = 0
-        mapCZtoFile[cid] = mapCZtoFile[cid] or {}
-        mapCZtoFile[cid][0] = mapCZtoFile[cid][0] or {}
-        mapCZtoFile[cid][0] = mapFile
-    end
-
-    function TomTom:GetMapFile(C, Z)
-        if not C or not Z then return end
-        local c = mapCZtoFile[C]
-        if c then
-            return c[Z]
-        end
-    end
-    function TomTom:GetCZ(mapFile)
-        return reverseMapFileC[mapFile], reverseMapFileZ[mapFile]
-    end
+function TomTom:SetCustomWaypoint(c,z,x,y,callback,minimap,world,silent)
+	return self:AddZWaypoint(c, z, x, y, nil, false, minimap, world, callback, silent)
 end

--- Public functions for plugins to convert between coords <--> x,y
-function TomTom:GetCoord(x, y)
-	return floor(x * 10000 + 0.5) * 10000 + floor(y * 10000 + 0.5)
-end
-function TomTom:GetXY(id)
-	return floor(id / 10000) / 10000, (id % 10000) / 10000
+function TomTom:SetCustomMFWaypoint(m, f, x, y, opts)
+    opts.persistent = false
+
+    return self:AddMFWaypoint(m, f, x, y, opts)
 end

 do
@@ -1025,7 +962,7 @@ do
 	end

 	function WorldMap_OnUpdate(self, elapsed)
-		local x,y = compat:GetCurrentPlayerCoords()
+		local m,f,x,y = TomTom:GetCurrentPlayerPosition()
 		local opt = TomTom.db.profile

 		if not x or not y then
@@ -1045,17 +982,23 @@ do
 end

 do
+    local bcounter = 0
 	function Block_OnUpdate(self, elapsed)
-		local x,y = compat:GetCurrentPlayerCoords()
-		local opt = TomTom.db.profile
+        bcounter = bcounter + elapsed
+        if bcounter > TomTom.profile.block.throttle then
+            bcounter = bcounter - TomTom.profile.block.throttle

-		if not x or not y then
-			-- Hide the frame when we have no coordinates
-			self:Hide()
-		else
-			self.Text:SetFormattedText("%s", RoundCoords(x, y, opt.block.accuracy))
-		end
-	end
+            local m,f,x,y = astrolabe:GetCurrentPlayerPosition()
+
+            local opt = TomTom.db.profile
+            if not x or not y then
+                local blank = ("-"):rep(8)
+                self.Text:SetText(blank)
+            else
+                self.Text:SetFormattedText("%s", RoundCoords(x, y, opt.block.accuracy))
+            end
+        end
+    end

 	function Block_OnDragStart(self, button, down)
 		if not TomTom.db.profile.block.lock then
@@ -1068,10 +1011,10 @@ do
 	end

     function Block_OnClick(self, button, down)
-        local c,z,x,y = compat:GetCurrentPlayerPosition()
-        local zone = TomTom:GetMapFile(c, z)
-        local desc = format("%s: %.2f, %.2f", zone, x*100, y*100)
-        TomTom:AddZWaypoint(c, z, x*100, y*100, desc)
+        local m,f,x,y = TomTom:GetCurrentPlayerPosition()
+        local zoneName = lmd:MapLocalize(m,f)
+        local desc = format("%s: %.2f, %.2f", zoneName, x*100, y*100)
+        TomTom:AddZWaypoint(m, f, x, y, desc)
     end
 end

@@ -1083,36 +1026,28 @@ local function usage()
 	ChatFrame1:AddMessage(L["|cffffff78/way reset <zone>|r - Resets all waypoints in zone"])
 end

-local zlist = {}
-for cidx,c in ipairs{GetMapContinents()} do
-	for zidx,z in ipairs{GetMapZones(cidx)} do
-		zlist[z:lower():gsub("[%L]", "")] = {cidx, zidx, z}
-	end
-end
-
 function TomTom:GetClosestWaypoint()
-	local c,z,x,y = compat:GetCurrentPlayerPosition()
-	local zone = TomTom:GetMapFile(c, z)
-	local closest_uid = nil
+    local m,f,x,y = self:GetCurrentPlayerPosition()
+	local closest_waypoint = nil
 	local closest_dist = nil
-	if waypoints[zone] then
-		for uid in pairs(waypoints[zone]) do
-			local dist,x,y = TomTom:GetDistanceToWaypoint(uid)
+	if waypoints[m] then
+		for key, waypoint in pairs(waypoints[m]) do
+            local dist, x, y = TomTom:GetDistanceToWaypoint(waypoint)
 			if (dist and closest_dist == nil) or (dist and dist < closest_dist) then
 				closest_dist = dist
-				closest_uid = uid
+				closest_waypoint = waypoint
 			end
 		end
 	end
 	if closest_dist then
-		return closest_uid
+		return closest_waypoint
 	end
 end

 function TomTom:SetClosestWaypoint()
 	local uid = self:GetClosestWaypoint()
 	if uid then
-		local data = waypoints[uid]
+		local data = uid
 		TomTom:SetCrazyArrow(uid, TomTom.profile.arrow.arrival, data.title)
 	end
 end
@@ -1126,14 +1061,22 @@ end
 SLASH_TOMTOM_WAYBACK1 = "/wayb"
 SLASH_TOMTOM_WAYBACK2 = "/wayback"
 SlashCmdList["TOMTOM_WAYBACK"] = function(msg)
-	local backc,backz,backx,backy = compat:GetCurrentPlayerPosition()
-	TomTom:AddZWaypoint(backc, backz, backx*100, backy*100, L["Wayback"])
+	local backc,backz,backx,backy = TomTom:GetCurrentPlayerPosition()
+	TomTom:AddZWaypoint(backc, backz, backx, backy, L["Wayback"])
 end

 SLASH_TOMTOM_WAY1 = "/way"
 SLASH_TOMTOM_WAY2 = "/tway"
 SLASH_TOMTOM_WAY3 = "/tomtomway"

+local nameToMapId = {}
+local mapIds = lmd:GetAllMapIDs()
+
+for idx, mapId in ipairs(mapIds) do
+    local mapName = lmd:MapLocalize(mapId)
+    nameToMapId[mapName] = mapId
+end
+
 local wrongseparator = "(%d)" .. (tonumber("1.1") and "," or ".") .. "(%d)"
 local rightseparator =   "%1" .. (tonumber("1.1") and "." or ",") .. "%2"

@@ -1164,9 +1107,10 @@ SlashCmdList["TOMTOM_WAY"] = function(msg)
 			local matches = {}
 			zone = zone:lower():gsub("[%L]", "")

-			for z,entry in pairs(zlist) do
-				if z:match(zone) then
-					table.insert(matches, entry)
+			for name,mapId in pairs(nameToMapId) do
+                local lname = name:lower()
+				if lname:match(zone) then
+					table.insert(matches, lname)
 				end
 			end

@@ -1175,24 +1119,21 @@ SlashCmdList["TOMTOM_WAY"] = function(msg)
 				ChatFrame1:AddMessage(msg)
 				return
 			elseif #matches > 1 then
-				local poss = {}
-				for k,v in pairs(matches) do
-					table.insert(poss, v[3])
-				end
-				table.sort(poss)
+				table.sort(matches)

-				ChatFrame1:AddMessage(string.format(L["Found multiple matches for zone '%s'.  Did you mean: %s"], tokens[2], table.concat(poss, ", ")))
+				ChatFrame1:AddMessage(string.format(L["Found multiple matches for zone '%s'.  Did you mean: %s"], tokens[2], table.concat(matches, ", ")))
 				return
 			end

-			local c,z,name = unpack(matches[1])
-			local zone = TomTom:GetMapFile(c, z)
-			if waypoints[zone] then
-				for uid in pairs(waypoints[zone]) do
+            local zoneName = matches[1]
+            local mapId = nameToMapId[zoneName]
+
+			if waypoints[mapId] then
+				for key, uid in pairs(waypoints[mapId]) do
 					TomTom:RemoveWaypoint(uid)
 				end
 			else
-				ChatFrame1:AddMessage(L["There were no waypoints to remove in %s"]:format(name))
+				ChatFrame1:AddMessage(L["There were no waypoints to remove in %s"]:format(zoneName))
 			end
 		end
 	elseif tokens[1] and not tonumber(tokens[1]) then
@@ -1211,15 +1152,16 @@ SlashCmdList["TOMTOM_WAY"] = function(msg)

 		if desc then desc = table.concat(tokens, " ", zoneEnd + 3) end

-		-- Find a fuzzy match for the zone
-		local matches = {}
-		zone = zone:lower():gsub("[%L]", "")
+        -- Find a fuzzy match for the zone
+        local matches = {}
+        zone = zone:lower():gsub("[%L]", "")

-		for z,entry in pairs(zlist) do
-			if z:match(zone) then
-				table.insert(matches, entry)
-			end
-		end
+        for name,mapId in pairs(nameToMapId) do
+            local lname = name:lower()
+            if lname:match(zone) then
+                table.insert(matches, lname)
+            end
+        end

 		if #matches ~= 1 then
 				local msg = string.format(L["Found %d possible matches for zone %s.  Please be more specific"], #matches, tokens[1])
@@ -1227,7 +1169,8 @@ SlashCmdList["TOMTOM_WAY"] = function(msg)
 			return
 		end

-		local c,z,name = unpack(matches[1])
+		local zoneName = matches[1]
+        local mapId = nameToMapId[zoneName]

 		if not x or not tonumber(x) then
 			return usage()
@@ -1237,7 +1180,7 @@ SlashCmdList["TOMTOM_WAY"] = function(msg)

 		x = tonumber(x)
 		y = tonumber(y)
-		TomTom:AddZWaypoint(c, z, x, y, desc)
+		TomTom:AddMFWaypoint(mapId, nil, x, y, desc)
 	elseif tonumber(tokens[1]) then
 		-- A vanilla set command
 		local x,y,desc = unpack(tokens)
@@ -1257,5 +1200,3 @@ SlashCmdList["TOMTOM_WAY"] = function(msg)
 		return usage()
 	end
 end
-
-
diff --git a/TomTom.toc b/TomTom.toc
index 4fed039..ed93b19 100755
--- a/TomTom.toc
+++ b/TomTom.toc
@@ -6,7 +6,7 @@
 ## Notes-zhCN:一个简单的导航助手。
 ## Notes-ruRU: Удобный портативный навигатор по игровой карте
 ## Author: Cladhaire
-## SavedVariables: TomTomDB, TomTomWaypoints
+## SavedVariables: TomTomDB, TomTomWaypoints, TomTomWaypointsMF

 ## X-Localizations: enUS, enGB, deDE, zhCN, ruRU, zhTW
 ## X-CompatibleLocales: enUS, enGB, deDE, frFR, esES, esMX, zhCN, zhTW, koKR, ruRU
@@ -20,6 +20,7 @@ libs\AceEvent-3.0\AceEvent-3.0.xml
 libs\AceDB-3.0\AceDB-3.0.xml
 libs\AceDBOptions-3.0\AceDBOptions-3.0.xml
 libs\LibDataBroker-1.1\LibDataBroker-1.1.lua
+libs\LibMapData-1.0\library.lua

 Localization.enUS.lua
 Localization.deDE.lua
diff --git a/TomTom_Config.lua b/TomTom_Config.lua
index c3dadef..08eb0be 100644
--- a/TomTom_Config.lua
+++ b/TomTom_Config.lua
@@ -88,8 +88,17 @@ local function createconfig()
 				min = 0, max = 2, step = 1,
 				arg = "block.accuracy",
 			},
+            coords_throttle = {
+				type = "range",
+				order = 5,
+				name = L["Update throttle"],
+				desc = L["Controls the frequency of updates for the coordinate block."],
+				width = "double",
+				min = 0, max = 2.0, step = 0.05,
+				arg = "block.throttle",
+			},
 			display = {
-				order = 4,
+				order = 5,
 				type = "group",
 				inline = true,
 				name = L["Display Settings"],
diff --git a/TomTom_CrazyArrow.lua b/TomTom_CrazyArrow.lua
index 20f424a..d72cbf2 100644
--- a/TomTom_CrazyArrow.lua
+++ b/TomTom_CrazyArrow.lua
@@ -1,6 +1,6 @@
 --[[--------------------------------------------------------------------------
 --  TomTom - A navigational assistant for World of Warcraft
---
+--
 --  CrazyTaxi: A crazy-taxi style arrow used for waypoint navigation.
 --    concept taken from MapNotes2 (Thanks to Mery for the idea, along
 --    with the artwork.)
@@ -85,7 +85,7 @@ local active_point, arrive_distance, showDownArrow, point_title
 function TomTom:SetCrazyArrow(uid, dist, title)
 	active_point = uid
 	arrive_distance = dist
-	point_title = title
+	point_title = title

 	if self.profile.arrow.enable then
 		wayframe.title:SetText(title or "Unknown waypoint")
@@ -112,7 +112,7 @@ local function OnUpdate(self, elapsed)

 	-- The only time we cannot calculate the distance is when the waypoint
 	-- is on another continent, or we are in an instance
-	if not dist or IsInInstance() then
+	if not dist then
 		if not TomTom:IsValidWaypoint(active_point) then
 			active_point = nil
 			-- Change the crazy arrow to point at the closest waypoint
@@ -145,7 +145,7 @@ local function OnUpdate(self, elapsed)
 			count = 0
 		end

-		cell = count
+		local cell = count
 		local column = cell % 9
 		local row = floor(cell / 9)

@@ -172,10 +172,10 @@ local function OnUpdate(self, elapsed)
 		local gr,gg,gb = unpack(TomTom.db.profile.arrow.goodcolor)
 		local mr,mg,mb = unpack(TomTom.db.profile.arrow.middlecolor)
 		local br,bg,bb = unpack(TomTom.db.profile.arrow.badcolor)
-		local r,g,b = ColorGradient(perc, br, bg, bb, mr, mg, mb, gr, gg, gb)
+		local r,g,b = ColorGradient(perc, br, bg, bb, mr, mg, mb, gr, gg, gb)
 		arrow:SetVertexColor(r,g,b)

-		cell = floor(angle / twopi * 108 + 0.5) % 108
+		local cell = floor(angle / twopi * 108 + 0.5) % 108
 		local column = cell % 9
 		local row = floor(cell / 9)

@@ -208,11 +208,11 @@ local function OnUpdate(self, elapsed)

 		if speed > 0 then
 			local eta = math.abs(dist / speed)
-			tta:SetFormattedText("%01d:%02d", eta / 60, eta % 60)
+			tta:SetFormattedText("%01d:%02d", eta / 60, eta % 60)
 		else
 			tta:SetText("***")
 		end
-
+
 		last_distance = dist
 		tta_throttle = 0
 	end
@@ -429,12 +429,12 @@ local function wayframe_OnEvent(self, event, arg1, ...)
 				local gr,gg,gb = unpack(TomTom.db.profile.arrow.goodcolor)
 				local mr,mg,mb = unpack(TomTom.db.profile.arrow.middlecolor)
 				local br,bg,bb = unpack(TomTom.db.profile.arrow.badcolor)
-				local r,g,b = ColorGradient(perc, br, bg, bb, mr, mg, mb, gr, gg, gb)
+				local r,g,b = ColorGradient(perc, br, bg, bb, mr, mg, mb, gr, gg, gb)
 				feed_crazy.iconR = r
 				feed_crazy.iconG = g
 				feed_crazy.iconB = b

-				cell = floor(angle / twopi * 108 + 0.5) % 108
+				local cell = floor(angle / twopi * 108 + 0.5) % 108
 				local column = cell % 9
 				local row = floor(cell / 9)

@@ -480,7 +480,7 @@ wayframe:SetScript("OnEvent", wayframe_OnEvent)
 -- into consideration.  This can be accomplished by subtracting
 -- GetPlayerFacing() from the angle before passing it in.
 function TomTom:SetCrazyArrowDirection(angle)
-    cell = floor(angle / twopi * 108 + 0.5) % 108
+    local cell = floor(angle / twopi * 108 + 0.5) % 108
     local column = cell % 9
     local row = floor(cell / 9)

diff --git a/TomTom_POIIntegration.lua b/TomTom_POIIntegration.lua
index 27fc1d9..c8dde74 100644
--- a/TomTom_POIIntegration.lua
+++ b/TomTom_POIIntegration.lua
@@ -83,7 +83,7 @@ local function poi_OnClick(self, button)
             self = questFrame.poiIcon
         end
     end
-
+
     return setQuestWaypoint(self)
  end

@@ -91,7 +91,7 @@ local hooked = {}
 hooksecurefunc("QuestPOI_DisplayButton", function(parentName, buttonType, buttonIndex, questId)
       local buttonName = "poi"..tostring(parentName)..tostring(buttonType).."_"..tostring(buttonIndex);
       local poiButton = _G[buttonName];
-
+
       if not hooked[buttonName] then
          poiButton:HookScript("OnClick", poi_OnClick)
          poiButton:RegisterForClicks("AnyUp")
@@ -109,13 +109,13 @@ local function updateClosestPOI()
     if ( questIndex ) then
         local title, level, questTag, suggestedGroup, isHeader, isCollapsed, isComplete, isDaily, questID = GetQuestLogTitle(questIndex);
         local playerMoney = GetMoney();
-        local requiredMoney = GetQuestLogRequiredMoney(questIndex);
-        numObjectives = GetNumQuestLeaderBoards(questIndex);
+        local requiredMoney = GetQuestLogRequiredMoney(questIndex);
+        local numObjectives = GetNumQuestLeaderBoards(questIndex);
         if ( isComplete and isComplete < 0 ) then
             isComplete = false;
         elseif ( numObjectives == 0 and playerMoney >= requiredMoney ) then
-            isComplete = true;
-        end
+            isComplete = true;
+        end

         -- check filters
         local filterOK = true;
@@ -123,7 +123,7 @@ local function updateClosestPOI()
             filterOK = false;
         elseif ( bit.band(WATCHFRAME_FILTER_TYPE, WATCHFRAME_FILTER_REMOTE_ZONES) ~= WATCHFRAME_FILTER_REMOTE_ZONES and not LOCAL_MAP_QUESTS[questID] ) then
             filterOK = false;
-        end
+        end

         if filterOK then
             -- Set a waypoint for this POI, it should be the higehst
diff --git a/TomTom_Waypoints.lua b/TomTom_Waypoints.lua
index 3b6379b..0be1094 100644
--- a/TomTom_Waypoints.lua
+++ b/TomTom_Waypoints.lua
@@ -8,8 +8,7 @@
 --  TomTom:AddZWaypoint() and TomTom:RemoveWaypoint() instead.
 ----------------------------------------------------------------------------]]

--- Import compat library
-local compat = TomTom.compat
+local astrolabe = DongleStub("Astrolabe-1.0")

 -- Create a tooltip to be used when mousing over waypoints
 local tooltip = CreateFrame("GameTooltip", "TomTomTooltip", UIParent, "GameTooltipTemplate")
@@ -33,39 +32,6 @@ local minimapParent = Minimap
 local pool = {}
 local all_points = {}

--- Create a mapping from uniqueID to waypoint
-local getuid,resolveuid
-do
-	local uidmap = {}
-	local uid = 0
-	function getuid(obj)
-		-- Ensure the object doesn't already have a uid mapping
-		for k,v in pairs(uidmap) do
-			if obj == v then
-				error("Attempt to re-use an object without clearing identifier")
-			end
-		end
-
-		-- Establish the new mapping
-		uid = uid + 1
-
-		uidmap[uid] = obj
-
-		return uid
-	end
-
-	function resolveuid(uid, remove)
-		-- Return the object that corresponds to the UID
-		local obj = uidmap[uid]
-
-		if remove then
-			uidmap[uid] = nil
-		end
-
-		return obj
-	end
-end
-
 -- Local declarations
 local Minimap_OnEnter,Minimap_OnLeave,Minimap_OnUpdate,Minimap_OnClick,Minimap_OnEvent
 local Arrow_OnUpdate
@@ -77,7 +43,7 @@ local rad_135 = math.rad(135)
 local function rotateArrow(self)
 	if self.disabled then return end

-	local angle = compat:GetDirectionToIcon(self)
+	local angle = astrolabe:GetDirectionToIcon(self)
 	if not angle then return self:Hide() end
 	angle = angle + rad_135

@@ -98,12 +64,15 @@ function TomTom:ReparentMinimap(minimap)
     end
 end

+local waypointMap = {}
+
+function TomTom:SetWaypoint(waypoint, callbacks, show_minimap, show_world)
+    local m, f, x, y = unpack(waypoint)

-function TomTom:SetWaypoint(c, z, x, y, callbacks, show_minimap, show_world)
 	-- Try to acquire a waypoint from the frame pool
 	local point = table.remove(pool)

-	if not point then
+    if not point then
 		point = {}

 		local minimap = CreateFrame("Button", nil, minimapParent)
@@ -127,7 +96,7 @@ function TomTom:SetWaypoint(c, z, x, y, callbacks, show_minimap, show_world)
 		minimap.arrow:SetWidth(40)
 		minimap.arrow:Hide()

-		-- Add the behavior scripts
+		-- Add the behavior scripts
 		minimap:SetScript("OnEnter", Minimap_OnEnter)
 		minimap:SetScript("OnLeave", Minimap_OnLeave)
 		minimap:SetScript("OnUpdate", Minimap_OnUpdate)
@@ -158,8 +127,10 @@ function TomTom:SetWaypoint(c, z, x, y, callbacks, show_minimap, show_world)
 		point.minimap = minimap
 	end

-	point.c = c
-	point.z = z
+    waypointMap[waypoint] = point
+
+	point.m = m
+	point.f = f
 	point.x = x
 	point.y = y
 	point.show_world = show_world
@@ -182,13 +153,13 @@ function TomTom:SetWaypoint(c, z, x, y, callbacks, show_minimap, show_world)
 	-- Link the actual frames back to the waypoint object
 	point.minimap.point = point
 	point.worldmap.point = point
-	point.uid = getuid(point)
+	point.uid = waypoint

 	-- Place the waypoint
-	compat:PlaceIconOnMinimap(point.minimap, c, z, x, y)
+	astrolabe:PlaceIconOnMinimap(point.minimap, m, f, x, y)

 	if show_world then
-		compat:PlaceIconOnWorldMap(TomTomMapOverlay, point.worldmap, c, z, x, y)
+		astrolabe:PlaceIconOnWorldMap(TomTomMapOverlay, point.worldmap, m, f, x, y)
 	else
 		point.worldmap.disabled = true
 	end
@@ -205,17 +176,10 @@ function TomTom:SetWaypoint(c, z, x, y, callbacks, show_minimap, show_world)
 		point.minimap.disabled = false
 		rotateArrow(point.minimap)
 	end
-
-	return point.uid
-end
-
-function TomTom:IsValidWaypoint(uid)
-	local obj = resolveuid(uid, false)
-	return obj and true or false
 end

 function TomTom:HideWaypoint(uid, minimap, worldmap)
-	local point = resolveuid(uid)
+    local point = waypointMap[uid]
 	if point then
 		if minimap then
 			point.minimap.disabled = true
@@ -224,13 +188,13 @@ function TomTom:HideWaypoint(uid, minimap, worldmap)

 		if worldmap then
 			point.worldmap.disabled = true
-			point.worldmap:Hide()
+			point.worldmap:Hide()
 		end
 	end
 end

 function TomTom:ShowWaypoint(uid)
-	local point = resolveuid(uid)
+	local point = waypointMap[uid]
 	if point then
 		point.minimap.disabled = not point.data.show_minimap
 		point.minimap:Show()
@@ -242,9 +206,9 @@ end

 -- This function removes the waypoint from the active set
 function TomTom:ClearWaypoint(uid)
-	local point = resolveuid(uid, true)
+    local point = waypointMap[uid]
 	if point then
-		compat:RemoveIconFromMinimap(point.minimap)
+		astrolabe:RemoveIconFromMinimap(point.minimap)
 		point.minimap:Hide()
 		point.worldmap:Hide()

@@ -264,13 +228,13 @@ function TomTom:ClearWaypoint(uid)
 end

 function TomTom:GetDistanceToWaypoint(uid)
-	local point = resolveuid(uid)
-	return point and compat:GetDistanceToIcon(point.minimap)
+    local point = waypointMap[uid]
+	return point and astrolabe:GetDistanceToIcon(point.minimap)
 end

 function TomTom:GetDirectionToWaypoint(uid)
-	local point = resolveuid(uid)
-	return point and compat:GetDirectionToIcon(point.minimap)
+	local point = waypointMap[uid]
+	return point and astrolabe:GetDirectionToIcon(point.minimap)
 end

 do
@@ -334,10 +298,10 @@ do
 	local minimap_count = 0

 	function Minimap_OnUpdate(self, elapsed)
-		local dist,x,y = compat:GetDistanceToIcon(self)
+		local dist,x,y = astrolabe:GetDistanceToIcon(self)
 		local disabled = self.disabled

-		if not dist or IsInInstance() then
+		if not dist then
 			self:Hide()
 			return
 		end
@@ -349,7 +313,7 @@ do
 		-- Reset the counter
 		minimap_count = 0

-		local edge = compat:IsIconOnEdge(self)
+		local edge = astrolabe:IsIconOnEdge(self)
 		local data = self.point
 		local callbacks = data.callbacks

@@ -360,7 +324,7 @@ do
 				self.arrow:Show()

 				-- Rotate the icon, as required
-				local angle = compat:GetDirectionToIcon(self)
+				local angle = astrolabe:GetDirectionToIcon(self)
 				angle = angle + rad_135

 				if GetCVar("rotateMinimap") == "1" then
@@ -423,7 +387,7 @@ do
 					callback("distance", data.uid, distance, dist, data.lastdist)
 				end
 				data.state = newstate
-			end
+			end

 			-- Update the last distance with the current distance
 			data.lastdist = dist
@@ -437,9 +401,9 @@ do
 			end

 			local data = self.point
-			if data.worldmap and data.show_world and not disabled then
-				local x,y = compat:PlaceIconOnWorldMap(TomTomMapOverlay, self, data.c, data.z, data.x, data.y)
-                local pdata = TomTom:GetData(data.uid) or {}
+			if data.worldmap and data.show_world and not self.disabled then
+				local x,y = astrolabe:PlaceIconOnWorldMap(TomTomMapOverlay, self, data.m, data.f, data.x, data.y)
+                local pdata = data.uid

 				if (x and y and (0 < x and x <= 1) and (0 < y and y <= 1)) then
 					self:Show()
@@ -455,8 +419,8 @@ do
 	function Minimap_OnEvent(self, event, ...)
 		if event == "PLAYER_ENTERING_WORLD" then
 			local data = self.point
-			if data and data.uid and resolveuid(data.uid) then
-				compat:PlaceIconOnMinimap(self, data.c, data.z, data.x, data.y)
+			if data and data.uid and waypointMap[data.uid] then
+				astrolabe:PlaceIconOnMinimap(self, data.m, data.f, data.x, data.y)
 			end
 		end
 	end
diff --git a/libs/LibMapData-1.0/library.lua b/libs/LibMapData-1.0/library.lua
new file mode 100644
index 0000000..2f8fc2f
--- /dev/null
+++ b/libs/LibMapData-1.0/library.lua
@@ -0,0 +1,1376 @@
+--[[
+	Library contains a dataset for Map file names and floors giving the raw map data
+	it also has a few functions to help determine distance and directions.
+--]]
+local MAJOR, MINOR = "LibMapData-1.0", tonumber("80") or 999
+assert(LibStub, MAJOR.." requires LibStub")
+
+local lib = LibStub:NewLibrary(MAJOR, MINOR)
+if not lib then return end
+lib.callbacks = lib.callbacks or LibStub("CallbackHandler-1.0"):New(lib)
+
+local watchFrame = CreateFrame("Frame")
+local lastMap, lastFloor = nil,0
+local mapData = {}
+local mapToLocal = {}
+local localToMap = {}
+local idToMap = {}
+local GetPlayerFacing, GetPlayerMapPosition,SetMapToCurrentZone = GetPlayerFacing, GetPlayerMapPosition, SetMapToCurrentZone
+local atan2 = math.atan2
+local PI2 = math.pi*2
+local floor = math.floor
+local type,assert = type,assert
+--- Constants
+lib.MAP_NORMAL = 0
+lib.MAP_INSTANCE = 1
+lib.MAP_RAID = 2
+lib.MAP_BG = 3
+ -- estimated world map size
+local worldMapWidth = 47714.278579261
+local worlMapHeight = 31809.64857610083
+
+local contOffsets = {
+	[1] = {-8590.40725049343,5628.692856102324},
+	[2] = {18542.31220836664, 3585.574573158966},
+	[3] = {0,0},
+	[4] = {16020.94044398222,454.2451915717977},
+}
+
+local transforms_x = {
+	[1] = 10133.3330078125,
+	[2] = -2400.0,
+	[3] = 0,
+	[4] = 0,
+}
+local transforms_y = {
+	[1] = 17600.0,
+	[2] = 2400.0,
+	[3] = 0,
+	[4] = 0,
+}
+
+do
+	-- Format:
+	-- floors = number of floors
+	-- area_id = in game area id
+	-- floor_index = width,height, ulX,ulY, lrXx,lrY, mapid
+	local emptyMaps = {
+		['floors'] = 0,['name'] = WORLD_MAP, ['continent'] = 0, ['phase'] = 0, ['map_type'] = 0,
+		[1] = {0,0,0,0,0,0,0}
+	}
+	setmetatable(mapData, { __index = function(t, k) if k then DEFAULT_CHAT_FRAME:AddMessage("LibMapData-1.0 is missing data for "..k) end; return emptyMaps end })
+	setmetatable(idToMap, { __index = function(t, k) if k then DEFAULT_CHAT_FRAME:AddMessage("LibMapData-1.0 is missing data for area id "..k) end; return k end})
+	setmetatable(mapToLocal, { __index = function(t,k) if k then DEFAULT_CHAT_FRAME:AddMessage("LibMapData-1.0 is missing localized data for "..k) end; return k end})
+		mapData[758] = {
+			['floors'] = 3, ['name'] = "TheBastionofTwilight", ['rzti'] = 671, ['map_type'] = 2, ['continent'] = 0, ['transform'] = 0,
+			[1] = { 1078.33402252197,718.889984130859,1184.77001953125,-899.846984863281,106.435997009277,-180.957000732422 },
+			[2] = { 778.343017578125,518.894958496094,1034.77001953125,-1289.84997558594,256.427001953125,-770.955017089844 },
+			[3] = { 1042.34202575684,694.894958496094,1267.27001953125,-1402.84997558594,224.927993774414,-707.955017089844 },
+		}
+		mapData[721] = {
+			['floors'] = 7, ['name'] = "BlackrockSpire", ['rzti'] = 229, ['map_type'] = 1, ['continent'] = 0, ['transform'] = 0,
+			[1] = { 886.839014053345,591.226013183594,876.252014160156,-286.828002929688,-10.5869998931885,304.398010253906 },
+			[2] = { 886.839014053345,591.226013183594,876.252014160156,-286.828002929688,-10.5869998931885,304.398010253906 },
+			[3] = { 886.839014053345,591.226013183594,876.252014160156,-286.828002929688,-10.5869998931885,304.398010253906 },
+			[4] = { 886.839014053345,591.226013183594,876.252014160156,-286.828002929688,-10.5869998931885,304.398010253906 },
+			[5] = { 886.839014053345,591.226013183594,876.252014160156,-286.828002929688,-10.5869998931885,304.398010253906 },
+			[6] = { 886.839014053345,591.226013183594,876.252014160156,-286.828002929688,-10.5869998931885,304.398010253906 },
+			[7] = { 886.839014053345,591.226013183594,876.252014160156,-286.828002929688,-10.5869998931885,304.398010253906 },
+		}
+		mapData[684] = {
+			['floors'] = 0, ['name'] = "RuinsofGilneas", ['rzti'] = 0, ['map_type'] = 0, ['continent'] = 1, ['transform'] = 0,
+			[1] = {3145.83325195312,2097.91668701172,-3439.58325195312,-533.333312988281,-293.75,-2631.25},
+		}
+		mapData[462] = {
+			['floors'] = 0, ['name'] = "EversongWoods", ['rzti'] = 530, ['map_type'] = 0, ['continent'] = 2, ['transform'] = 1,
+			[1] = {4925.0,3283.3330078125,4487.5,11041.666015625,9412.5,7758.3330078125},
+		}
+		mapData[499] = {
+			['floors'] = 0, ['name'] = "Sunwell", ['rzti'] = 530, ['map_type'] = 0, ['continent'] = 2, ['transform'] = 1,
+			[1] = {3327.0830078125,2218.7490234375,5302.0830078125,13568.7490234375,8629.166015625,11350.0},
+		}
+		mapData[536] = {
+			['floors'] = 1, ['name'] = "VioletHold", ['rzti'] = 608, ['map_type'] = 1, ['continent'] = 0, ['transform'] = 0,
+			[1] = { 256.22900390625,170.820068359375,-665.346984863281,1813.34997558594,-921.575988769531,1984.17004394531 },
+		}
+		mapData[610] = {
+			['floors'] = 0, ['name'] = "VashjirKelpForest", ['rzti'] = 0, ['map_type'] = 0, ['continent'] = 1, ['transform'] = 0,
+			[1] = {2802.0830078125,1868.75024414062,-5070.8330078125,-4018.74975585938,-2268.75,-5887.5},
+		}
+		mapData[37] = {
+			['floors'] = 0, ['name'] = "StranglethornJungle", ['rzti'] = 0, ['map_type'] = 0, ['continent'] = 1, ['transform'] = 0,
+			[1] = {4099.99987792969,2733.3330078125,-1743.74987792969,-11016.666015625,2356.25,-13749.9990234375},
+		}
+		mapData[481] = {
+			['floors'] = 0, ['name'] = "ShattrathCity", ['rzti'] = 530, ['map_type'] = 0, ['continent'] = 3, ['transform'] = 1,
+			[1] = {1306.25,870.833374023438,-6135.2587890625,-1473.95446777344,-4829.0087890625,-2344.78784179688},
+		}
+		mapData[759] = {
+			['floors'] = 3, ['name'] = "HallsofOrigination", ['rzti'] = 644, ['map_type'] = 1, ['continent'] = 0, ['transform'] = 0,
+			[1] = { 1531.7509765625,1021.16730546951,304.781005859375,-1018.17004394531,-1226.96997070312,2.99726152420044 },
+			[2] = { 1272.75503540039,848.503425598145,1115.2900390625,-934.835021972656,-157.464996337891,-86.3315963745117 },
+			[3] = { 1128.76898193359,752.512664794922,403.294006347656,-884.84033203125,-725.474975585938,-132.327667236328 },
+		}
+		mapData[685] = {
+			['floors'] = 0, ['name'] = "RuinsofGilneasCity", ['rzti'] = 0, ['map_type'] = 0, ['continent'] = 1, ['transform'] = 0,
+			[1] = {889.583251953125,593.749877929688,-1933.33325195312,-1306.25,-1043.75,-1899.99987792969},
+		}
+		mapData[463] = {
+			['floors'] = 0, ['name'] = "Ghostlands", ['rzti'] = 530, ['map_type'] = 0, ['continent'] = 2, ['transform'] = 1,
+			[1] = {3300.0,2199.99951171875,5283.3330078125,8266.666015625,8583.3330078125,6066.66650390625},
+		}
+		mapData[241] = {
+			['floors'] = 0, ['name'] = "Moonglade", ['rzti'] = 1, ['map_type'] = 0, ['continent'] = 2, ['transform'] = 0,
+			[1] = {2308.33325195312,1539.5830078125,1381.25,8491.666015625,3689.58325195312,6952.0830078125},
+		}
+		mapData[611] = {
+			['floors'] = 0, ['name'] = "GilneasCity", ['rzti'] = 654, ['map_type'] = 0, ['continent'] = 0, ['transform'] = 0,
+			[1] = {889.583251953125,593.749877929688,-1933.33325195312,-1306.25,-1043.75,-1899.99987792969},
+		}
+		mapData[19] = {
+			['floors'] = 0, ['name'] = "BlastedLands", ['rzti'] = 0, ['map_type'] = 0, ['continent'] = 1, ['transform'] = 0,
+			[1] = {3662.5,2441.666015625,1193.75,-10583.3330078125,4856.25,-13024.9990234375},
+		}
+		mapData[704] = {
+			['floors'] = 2, ['name'] = "BlackrockDepths", ['rzti'] = 230, ['map_type'] = 1, ['continent'] = 0, ['transform'] = 0,
+			[1] = { 1407.06097412109,938.040756225586,884.723999023438,248.639663696289,-522.336975097656,1186.68041992188 },
+			[2] = { 1507.06097412109,1004.70742797852,934.723999023438,495.302825927734,-572.336975097656,1500.01025390625 },
+		}
+		mapData[482] = {
+			['floors'] = 0, ['name'] = "NetherstormArena", ['rzti'] = 566, ['map_type'] = 3, ['continent'] = 0, ['transform'] = 0,
+			[1] = {2270.83319091797,1514.58337402344,-2660.41650390625,2918.75,-389.583312988281,1404.16662597656},
+		}
+		mapData[38] = {
+			['floors'] = 0, ['name'] = "SwampOfSorrows", ['rzti'] = 0, ['map_type'] = 0, ['continent'] = 1, ['transform'] = 0,
+			[1] = {2508.3330078125,1672.9169921875,2081.25,-9535.416015625,4589.5830078125,-11208.3330078125},
+		}
+		mapData[760] = {
+			['floors'] = 1, ['name'] = "RazorfenDowns", ['rzti'] = 129, ['map_type'] = 1, ['continent'] = 0, ['transform'] = 0,
+			[1] = { 709.048950195312,472.699951171875,-570.890991210938,2209.85009765625,-1279.93994140625,2682.55004882812 },
+		}
+		mapData[686] = {
+			['floors'] = 0, ['name'] = "ZulFarrak", ['rzti'] = 209, ['map_type'] = 1, ['continent'] = 0, ['transform'] = 0,
+			[1] = {1383.33322143555,922.916625976562,-1624.99987792969,2052.08325195312,-241.666656494141,1129.16662597656},
+		}
+		mapData[464] = {
+			['floors'] = 0, ['name'] = "AzuremystIsle", ['rzti'] = 530, ['map_type'] = 0, ['continent'] = 1, ['transform'] = 1,
+			[1] = {4070.8330078125,2714.5830078125,10500.0,-2793.75,14570.8330078125,-5508.3330078125},
+		}
+		mapData[501] = {
+			['floors'] = 0, ['name'] = "LakeWintergrasp", ['rzti'] = 571, ['map_type'] = 0, ['continent'] = 4, ['transform'] = 0,
+			[1] = {2974.99987792969,1983.33325195312,-4329.16650390625,5716.66650390625,-1354.16662597656,3733.33325195312},
+		}
+		mapData[20] = {
+			['floors'] = 0, ['name'] = "Tirisfal", ['rzti'] = 0, ['map_type'] = 0, ['continent'] = 1, ['transform'] = 0,
+			[1] = {4518.74987792969,3012.49981689453,-3033.33325195312,3837.49975585938,1485.41662597656,824.999938964844},
+		}
+		mapData[520] = {
+			['floors'] = 1, ['name'] = "TheNexus", ['rzti'] = 576, ['map_type'] = 1, ['continent'] = 0, ['transform'] = 0,
+			[1] = { 1101.2809753418,734.1875,708.068969726562,64.0755004882812,-393.212005615234,798.263000488281 },
+		}
+		mapData[261] = {
+			['floors'] = 0, ['name'] = "Silithus", ['rzti'] = 1, ['map_type'] = 0, ['continent'] = 2, ['transform'] = 0,
+			[1] = {4058.33325195312,2706.24951171875,-2983.33325195312,-5872.91650390625,1075.0,-8579.166015625},
+		}
+		mapData[39] = {
+			['floors'] = 0, ['name'] = "Westfall", ['rzti'] = 0, ['map_type'] = 0, ['continent'] = 1, ['transform'] = 0,
+			[1] = {3499.99981689453,2333.3330078125,-3016.66650390625,-9400.0,483.333312988281,-11733.3330078125},
+		}
+		mapData[761] = {
+			['floors'] = 1, ['name'] = "RazorfenKraul", ['rzti'] = 47, ['map_type'] = 1, ['continent'] = 0, ['transform'] = 0,
+			[1] = { 736.449951171875,490.959838867188,-1322.46997070312,1858.68005371094,-2058.919921875,2349.63989257812 },
+		}
+		mapData[687] = {
+			['floors'] = 1, ['name'] = "TheTempleOfAtalHakkar", ['rzti'] = 109, ['map_type'] = 1, ['continent'] = 0, ['transform'] = 0,
+			[1] = { 695.028991699219,463.352981567383,252.27099609375,-718.518981933594,-442.757995605469,-255.166000366211 },
+		}
+		mapData[613] = {
+			['floors'] = 0, ['name'] = "Vashjir", ['rzti'] = 0, ['map_type'] = 0, ['continent'] = 1, ['transform'] = 0,
+			[1] = {6945.83276367188,4631.24975585938,-8754.166015625,-3720.83325195312,-1808.33325195312,-8352.0830078125},
+		}
+		mapData[502] = {
+			['floors'] = 0, ['name'] = "ScarletEnclave", ['rzti'] = 609, ['map_type'] = 0, ['continent'] = 0, ['transform'] = 0,
+			[1] = {3162.5,2108.33337402344,4047.91650390625,3087.5,7210.41650390625,979.166625976562},
+		}
+		mapData[539] = {
+			['floors'] = 0, ['name'] = "GilneasX", ['rzti'] = 638, ['map_type'] = 0, ['continent'] = 0, ['transform'] = 0,
+			[1] = {3145.83325195312,2097.91668701172,-3439.58325195312,-533.333312988281,-293.75,-2631.25},
+		}
+		mapData[21] = {
+			['floors'] = 0, ['name'] = "Silverpine", ['rzti'] = 0, ['map_type'] = 0, ['continent'] = 1, ['transform'] = 0,
+			[1] = {4199.99975585938,2799.99987792969,-3449.99975585938,1666.66662597656,750.0,-1133.33325195312},
+		}
+		mapData[465] = {
+			['floors'] = 0, ['name'] = "Hellfire", ['rzti'] = 530, ['map_type'] = 0, ['continent'] = 3, ['transform'] = 1,
+			[1] = {5164.5830078125,3443.74987792969,-5539.5830078125,1481.25,-375.0,-1962.49987792969},
+		}
+		mapData[521] = {
+			['floors'] = 2, ['name'] = "CoTStratholme", ['rzti'] = 595, ['map_type'] = 1, ['continent'] = 0, ['transform'] = 0,
+			[1] = {1824.99993896484,1216.66650390625,-2152.08325195312,2297.91650390625,-327.083312988281,1081.25},
+			[2] = { 1125.29998779297,750.199951171875,-731.059997558594,1891.76000976562,-1856.35998535156,2641.9599609375 },
+		}
+		mapData[40] = {
+			['floors'] = 0, ['name'] = "Wetlands", ['rzti'] = 0, ['map_type'] = 0, ['continent'] = 1, ['transform'] = 0,
+			[1] = {4135.41668701172,2756.25,389.583312988281,-2147.91650390625,4525.0,-4904.16650390625},
+		}
+		mapData[762] = {
+			['floors'] = 4, ['name'] = "ScarletMonastery", ['rzti'] = 189, ['map_type'] = 1, ['continent'] = 0, ['transform'] = 0,
+			[1] = { 619.983947753906,413.32275390625,-947.986022949219,1616.85864257812,-1567.96997070312,2030.18139648438 },
+			[2] = { 320.190994262695,213.460494995117,482.463989257812,93.9055023193359,162.272994995117,307.365997314453 },
+			[3] = { 612.69660949707,408.4599609375,562.424011230469,1600.64001464844,-50.2725982666016,2009.09997558594 },
+			[4] = { 703.300048828125,468.86669921875,-1040.68994140625,812.423706054688,-1743.98999023438,1281.29040527344 },
+		}
+		mapData[688] = {
+			['floors'] = 3, ['name'] = "BlackfathomDeeps", ['rzti'] = 48, ['map_type'] = 1, ['continent'] = 0, ['transform'] = 0,
+			[1] = { 884.220001220703,589.479972839355,381.295989990234,-677.14697265625,-502.924011230469,-87.6669998168945 },
+			[2] = { 884.220031738281,589.480010986328,581.296020507812,-927.14697265625,-302.924011230469,-337.666961669922 },
+			[3] = { 284.224004268646,189.482666015625,281.298004150391,-877.148315429688,-2.92600011825562,-687.665649414062 },
+		}
+		mapData[614] = {
+			['floors'] = 0, ['name'] = "VashjirDepths", ['rzti'] = 0, ['map_type'] = 0, ['continent'] = 1, ['transform'] = 0,
+			[1] = {4075.0,2716.66650390625,-8233.3330078125,-4906.25,-4158.3330078125,-7622.91650390625},
+		}
+		mapData[540] = {
+			['floors'] = 0, ['name'] = "IsleofConquest", ['rzti'] = 628, ['map_type'] = 3, ['continent'] = 0, ['transform'] = 0,
+			[1] = {2650.0,1766.66658401489,-525.0,1708.33325195312,2125.0,-58.3333320617676},
+		}
+		mapData[281] = {
+			['floors'] = 0, ['name'] = "Winterspring", ['rzti'] = 1, ['map_type'] = 0, ['continent'] = 2, ['transform'] = 0,
+			[1] = {6149.99987792969,4100.0,991.666625976562,8793.75,7141.66650390625,4693.75},
+		}
+		mapData[22] = {
+			['floors'] = 0, ['name'] = "WesternPlaguelands", ['rzti'] = 0, ['map_type'] = 0, ['continent'] = 1, ['transform'] = 0,
+			[1] = {4299.99990844727,2866.66653442383,-416.666656494141,3366.66650390625,3883.33325195312,499.999969482422},
+		}
+		mapData[466] = {
+			['floors'] = 0, ['name'] = "Expansion01", ['rzti'] = 530, ['map_type'] = 0, ['continent'] = 3, ['transform'] = 1,
+			[1] = {17464.078125,11642.71875,-12996.0390625,5821.359375,4468.0390625,-5821.359375},
+		}
+		mapData[4] = {
+			['floors'] = 0, ['name'] = "Durotar", ['rzti'] = 1, ['map_type'] = 0, ['continent'] = 2, ['transform'] = 0,
+			[1] = {5287.49963378906,3524.99987792969,1962.49987792969,1808.33325195312,7249.99951171875,-1716.66662597656},
+		}
+		mapData[41] = {
+			['floors'] = 0, ['name'] = "Teldrassil", ['rzti'] = 1, ['map_type'] = 0, ['continent'] = 2, ['transform'] = 0,
+			[1] = {5874.99975585938,3916.66650390625,-4235.41650390625,11847.916015625,1639.58325195312,7931.24951171875},
+		}
+		mapData[485] = {
+			['floors'] = 0, ['name'] = "Northrend", ['rzti'] = 571, ['map_type'] = 0, ['continent'] = 4, ['transform'] = 0,
+			[1] = {17751.3984375,11834.2650146484,-9217.15234375,10593.375,8534.24609375,-1240.89001464844},
+		}
+		mapData[522] = {
+			['floors'] = 1, ['name'] = "Ahnkahet", ['rzti'] = 619, ['map_type'] = 1, ['continent'] = 0, ['transform'] = 0,
+			[1] = { 972.41796875,648.279022216797,1205.71997070312,200.404998779297,233.302001953125,848.684020996094 },
+		}
+		mapData[763] = {
+			['floors'] = 4, ['name'] = "Scholomance", ['rzti'] = 289, ['map_type'] = 1, ['continent'] = 0, ['transform'] = 0,
+			[1] = { 320.048904418945,213.36499786377,68.6389007568359,104.333000183105,-251.410003662109,317.697998046875 },
+			[2] = { 440.049011230469,293.366405487061,128.639007568359,44.3325996398926,-311.410003662109,337.699005126953 },
+			[3] = { 410.077995300293,273.385799407959,113.638999938965,34.3212013244629,-296.438995361328,307.707000732422 },
+			[4] = { 531.042007446289,354.028198242188,174.121994018555,-66.3211975097656,-356.920013427734,287.707000732422 },
+		}
+		mapData[689] = {
+			['floors'] = 0, ['name'] = "StranglethornVale", ['rzti'] = 0, ['map_type'] = 0, ['continent'] = 1, ['transform'] = 0,
+			[1] = {6552.0830078125,4368.75,-2977.08325195312,-10964.5830078125,3574.99975585938,-15333.3330078125},
+		}
+		mapData[615] = {
+			['floors'] = 0, ['name'] = "VashjirRuins", ['rzti'] = 0, ['map_type'] = 0, ['continent'] = 1, ['transform'] = 0,
+			[1] = {4849.99963378906,3233.3330078125,-6681.24951171875,-4756.25,-1831.24987792969,-7989.5830078125},
+		}
+		mapData[23] = {
+			['floors'] = 0, ['name'] = "EasternPlaguelands", ['rzti'] = 0, ['map_type'] = 0, ['continent'] = 1, ['transform'] = 0,
+			[1] = {4031.25,2687.49987792969,2287.5,3704.16650390625,6318.75,1016.66662597656},
+		}
+		mapData[467] = {
+			['floors'] = 0, ['name'] = "Zangarmarsh", ['rzti'] = 530, ['map_type'] = 0, ['continent'] = 3, ['transform'] = 1,
+			[1] = {5027.08349609375,3352.08325195312,-9475.0,1935.41662597656,-4447.91650390625,-1416.66662597656},
+		}
+		mapData[504] = {
+			['floors'] = 2, ['name'] = "Dalaran", ['rzti'] = 571, ['map_type'] = 0, ['continent'] = 4, ['transform'] = 0,
+			[1] = { 830.015014648438,553.33984375,-222.494995117188,5513.330078125,-1052.51000976562,6066.669921875 },
+			[2] = { 563.223999023438,375.48974609375,-352.64599609375,5599.85009765625,-915.869995117188,5975.33984375 },
+		}
+		mapData[541] = {
+			['floors'] = 0, ['name'] = "HrothgarsLanding", ['rzti'] = 571, ['map_type'] = 0, ['continent'] = 4, ['transform'] = 0,
+			[1] = {3677.08312988281,2452.083984375,-2797.91650390625,10781.25,879.166625976562,8329.166015625},
+		}
+		mapData[708] = {
+			['floors'] = 0, ['name'] = "TolBarad", ['rzti'] = 732, ['map_type'] = 0, ['continent'] = 0, ['transform'] = 0,
+			[1] = {2014.58329248428,1343.75,-2010.41662597656,-560.416625976562,4.16666650772095,-1904.16662597656},
+		}
+		mapData[301] = {
+			['floors'] = 0, ['name'] = "StormwindCity", ['rzti'] = 0, ['map_type'] = 0, ['continent'] = 1, ['transform'] = 0,
+			[1] = {1737.499958992,1158.3330078125,-1722.91662597656,-7995.8330078125,14.5833330154419,-9154.166015625},
+		}
+		mapData[42] = {
+			['floors'] = 0, ['name'] = "Darkshore", ['rzti'] = 1, ['map_type'] = 0, ['continent'] = 2, ['transform'] = 0,
+			[1] = {6464.5830078125,4310.41625976562,-3016.66650390625,8222.916015625,3447.91650390625,3912.49975585938},
+		}
+		mapData[486] = {
+			['floors'] = 0, ['name'] = "BoreanTundra", ['rzti'] = 571, ['map_type'] = 0, ['continent'] = 4, ['transform'] = 0,
+			[1] = {5764.5830078125,3843.74987792969,-8570.8330078125,4897.91650390625,-2806.25,1054.16662597656},
+		}
+		mapData[523] = {
+			['floors'] = 3, ['name'] = "UtgardeKeep", ['rzti'] = 574, ['map_type'] = 1, ['continent'] = 0, ['transform'] = 0,
+			[1] = { 734.580993652344,489.721500396729,310.406005859375,25.6665000915527,-424.174987792969,515.388000488281 },
+			[2] = { 481.081008911133,320.720293045044,238.156005859375,-16.3332996368408,-242.925003051758,304.386993408203 },
+			[3] = { 736.581008911133,491.054512023926,510.906005859375,-75.3335037231445,-225.675003051758,415.721008300781 },
+		}
+		mapData[542] = {
+			['floors'] = 1, ['name'] = "TheArgentColiseum", ['rzti'] = 650, ['map_type'] = 1, ['continent'] = 0, ['transform'] = 0,
+			[1] = { 369.986186981201,246.657989501953,41.255199432373,446.360992431641,-328.730987548828,693.018981933594 },
+		}
+		mapData[764] = {
+			['floors'] = 7, ['name'] = "ShadowfangKeep", ['rzti'] = 33, ['map_type'] = 1, ['continent'] = 0, ['transform'] = 0,
+			[1] = { 352.430053710938,234.953392028809,-2003.76989746094,-319.882995605469,-2356.19995117188,-84.9296035766602 },
+			[2] = { 212.4267578125,141.61799621582,-2147.556640625,-303.214996337891,-2359.9833984375,-161.59700012207 },
+			[3] = { 152.429931640625,101.619964599609,-2103.77001953125,-193.216033935547,-2256.19995117188,-91.5960693359375 },
+			[4] = { 152.429931640625,101.624694824219,-2103.77001953125,-193.214996337891,-2256.19995117188,-91.5903015136719 },
+			[5] = { 152.429931640625,101.624694824219,-2103.77001953125,-193.214996337891,-2256.19995117188,-91.5903015136719 },
+			[6] = { 198.429931640625,132.286605834961,-2080.77001953125,-182.546005249023,-2279.19995117188,-50.2593994140625 },
+			[7] = { 272.429931640625,181.619903564453,-2023.77001953125,-278.216003417969,-2296.19995117188,-96.5960998535156 },
+		}
+		mapData[690] = {
+			['floors'] = 1, ['name'] = "TheStockade", ['rzti'] = 34, ['map_type'] = 1, ['continent'] = 0, ['transform'] = 0,
+			[1] = { 378.15299987793,252.102495193481,188.330993652344,-31.4694995880127,-189.822006225586,220.632995605469 },
+		}
+		mapData[24] = {
+			['floors'] = 0, ['name'] = "HillsbradFoothills", ['rzti'] = 0, ['map_type'] = 0, ['continent'] = 1, ['transform'] = 0,
+			[1] = {4862.49987792969,3241.66662597656,-1849.99987792969,1481.25,3012.5,-1760.41662597656},
+		}
+		mapData[61] = {
+			['floors'] = 0, ['name'] = "ThousandNeedles", ['rzti'] = 1, ['map_type'] = 0, ['continent'] = 2, ['transform'] = 0,
+			[1] = {4399.99969482422,2933.3330078125,433.333312988281,-3966.66650390625,4833.3330078125,-6899.99951171875},
+		}
+		mapData[709] = {
+			['floors'] = 0, ['name'] = "TolBaradDailyArea", ['rzti'] = 732, ['map_type'] = 0, ['continent'] = 0, ['transform'] = 0,
+			[1] = {1837.5,1224.99993896484,-2412.5,377.083312988281,-575.0,-847.916625976562},
+		}
+		mapData[43] = {
+			['floors'] = 0, ['name'] = "Ashenvale", ['rzti'] = 1, ['map_type'] = 0, ['continent'] = 2, ['transform'] = 0,
+			[1] = {5766.66638183594,3843.74987792969,-1699.99987792969,4672.91650390625,4066.66650390625,829.166625976562},
+		}
+		mapData[524] = {
+			['floors'] = 2, ['name'] = "UtgardePinnacle", ['rzti'] = 575, ['map_type'] = 1, ['continent'] = 0, ['transform'] = 0,
+			[1] = { 548.936019897461,365.957015991211,697.559020996094,186.919998168945,148.623001098633,552.877014160156 },
+			[2] = { 756.179943084717,504.119003295898,747.557983398438,157.839004516602,-8.6219596862793,661.9580078125 },
+		}
+		mapData[765] = {
+			['floors'] = 2, ['name'] = "Stratholme", ['rzti'] = 329, ['map_type'] = 1, ['continent'] = 0, ['transform'] = 0,
+			[1] = { 705.719970703125,470.47998046875,3617.67993164062,3338.96997070312,2911.9599609375,3809.44995117188 },
+			[2] = { 1005.72045898438,670.480224609375,3967.68017578125,3498.96997070312,2961.95971679688,4169.4501953125 },
+		}
+		mapData[691] = {
+			['floors'] = 4, ['name'] = "Gnomeregan", ['rzti'] = 90, ['map_type'] = 1, ['continent'] = 0, ['transform'] = 0,
+			[1] = { 769.667999267578,513.111999511719,277.772003173828,-694.0,-491.89599609375,-180.888000488281 },
+			[2] = { 769.667999267578,513.111999511719,77.7720031738281,-714.0,-691.89599609375,-200.888000488281 },
+			[3] = { 869.667999267578,579.778015136719,127.772003173828,-967.3330078125,-741.89599609375,-387.554992675781 },
+			[4] = { 869.669708251953,579.779998779297,-72.9992980957031,-937.333984375,-942.669006347656,-357.553985595703 },
+		}
+		mapData[321] = {
+			['floors'] = 1, ['name'] = "Orgrimmar", ['rzti'] = 1, ['map_type'] = 0, ['continent'] = 2, ['transform'] = 0,
+			[1] = {1739.375,1159.58349609375,3506.35400390625,2486.66674804688,5245.72900390625,1327.08325195312},
+		}
+		mapData[543] = {
+			['floors'] = 2, ['name'] = "TheArgentColiseum", ['rzti'] = 649, ['map_type'] = 2, ['continent'] = 0, ['transform'] = 0,
+			[1] = { 369.986186981201,246.657989501953,41.255199432373,446.360992431641,-328.730987548828,693.018981933594 },
+			[2] = { 739.996017456055,493.330017089844,211.259994506836,433.023986816406,-528.736022949219,926.35400390625 },
+		}
+		mapData[747] = {
+			['floors'] = 0, ['name'] = "LostCityofTolvir", ['rzti'] = 755, ['map_type'] = 1, ['continent'] = 0, ['transform'] = 0,
+			[1] = {970.833251953125,647.9169921875,1004.16662597656,-10591.666015625,1974.99987792969,-11239.5830078125},
+		}
+		mapData[673] = {
+			['floors'] = 0, ['name'] = "TheCapeOfStranglethorn", ['rzti'] = 0, ['map_type'] = 0, ['continent'] = 1, ['transform'] = 0,
+			[1] = {3945.83312988281,2631.25,-2108.33325195312,-12516.666015625,1837.49987792969,-15147.916015625},
+		}
+		mapData[81] = {
+			['floors'] = 0, ['name'] = "StonetalonMountains", ['rzti'] = 1, ['map_type'] = 0, ['continent'] = 2, ['transform'] = 0,
+			[1] = {5899.99987792969,3933.33312988281,-3902.08325195312,3404.16650390625,1997.91662597656,-529.166625976562},
+		}
+		mapData[488] = {
+			['floors'] = 0, ['name'] = "Dragonblight", ['rzti'] = 571, ['map_type'] = 0, ['continent'] = 4, ['transform'] = 0,
+			[1] = {5608.33312988281,3739.58337402344,-3627.08325195312,5575.0,1981.24987792969,1835.41662597656},
+		}
+		mapData[525] = {
+			['floors'] = 2, ['name'] = "HallsofLightning", ['rzti'] = 602, ['map_type'] = 1, ['continent'] = 0, ['transform'] = 0,
+			[1] = { 566.235015869141,377.489990234375,282.549011230469,1157.05004882812,-283.686004638672,1534.5400390625 },
+			[2] = { 708.237014770508,472.160034179688,538.549011230469,959.719970703125,-169.688003540039,1431.88000488281 },
+		}
+		mapData[766] = {
+			['floors'] = 3, ['name'] = "AhnQiraj", ['rzti'] = 531, ['map_type'] = 2, ['continent'] = 0, ['transform'] = 0,
+			[1] = { 2777.54411315918,1851.6904296875,-138.07600402832,-9510.98046875,-2915.6201171875,-7659.2900390625 },
+			[2] = { 977.559936523438,651.7001953125,-1538.06994628906,-8703.5,-2515.6298828125,-8051.7998046875 },
+			[3] = { 577.559936523438,385.0400390625,-1738.06994628906,-8720.169921875,-2315.6298828125,-8335.1298828125 },
+		}
+		mapData[692] = {
+			['floors'] = 2, ['name'] = "Uldaman", ['rzti'] = 70, ['map_type'] = 1, ['continent'] = 0, ['transform'] = 0,
+			[1] = { 893.668014526367,595.778991699219,248.54899597168,-391.472991943359,-645.119018554688,204.305999755859 },
+			[2] = { 492.570419311523,328.380493164062,-52.5485992431641,-57.7734985351562,-545.119018554688,270.606994628906 },
+		}
+		mapData[26] = {
+			['floors'] = 0, ['name'] = "Hinterlands", ['rzti'] = 0, ['map_type'] = 0, ['continent'] = 1, ['transform'] = 0,
+			[1] = {3850.0,2566.66662597656,1575.0,1466.66662597656,5425.0,-1100.0},
+		}
+		mapData[544] = {
+			['floors'] = 0, ['name'] = "TheLostIsles", ['rzti'] = 648, ['map_type'] = 0, ['continent'] = 0, ['transform'] = 0,
+			[1] = {4514.5830078125,3010.41665649414,-4383.3330078125,2881.25,131.25,-129.166656494141},
+		}
+		mapData[748] = {
+			['floors'] = 0, ['name'] = "Uldum_terrain1", ['rzti'] = 1, ['map_type'] = 0, ['continent'] = 2, ['transform'] = 0,
+			[1] = {6193.74975585938,4129.16650390625,-2441.66650390625,-8029.16650390625,3752.08325195312,-12158.3330078125},
+		}
+		mapData[341] = {
+			['floors'] = 0, ['name'] = "Ironforge", ['rzti'] = 0, ['map_type'] = 0, ['continent'] = 1, ['transform'] = 0,
+			[1] = {790.625061035156,527.6044921875,713.591369628906,-4569.2412109375,1504.21643066406,-5096.845703125},
+		}
+		mapData[526] = {
+			['floors'] = 1, ['name'] = "Ulduar77", ['rzti'] = 599, ['map_type'] = 1, ['continent'] = 0, ['transform'] = 0,
+			[1] = { 920.196014404297,613.466064453125,-206.324005126953,762.443969726562,-1126.52001953125,1375.91003417969 },
+		}
+		mapData[767] = {
+			['floors'] = 2, ['name'] = "ThroneofTides", ['rzti'] = 643, ['map_type'] = 1, ['continent'] = 0, ['transform'] = 0,
+			[1] = { 998.171936035156,665.447998046875,-308.898010253906,-679.447998046875,-1307.06994628906,-14.0 },
+			[2] = { 998.171936035156,665.447998046875,-308.898010253906,-329.447998046875,-1307.06994628906,336.0 },
+		}
+		mapData[27] = {
+			['floors'] = 0, ['name'] = "DunMorogh", ['rzti'] = 0, ['map_type'] = 0, ['continent'] = 1, ['transform'] = 0,
+			[1] = {4897.91650390625,3264.5830078125,-2137.5,-3941.66650390625,2760.41650390625,-7206.24951171875},
+		}
+		mapData[101] = {
+			['floors'] = 0, ['name'] = "Desolace", ['rzti'] = 1, ['map_type'] = 0, ['continent'] = 2, ['transform'] = 0,
+			[1] = {4495.8330078125,2997.91656494141,-4233.3330078125,452.083312988281,262.5,-2545.83325195312},
+		}
+		mapData[471] = {
+			['floors'] = 0, ['name'] = "TheExodar", ['rzti'] = 530, ['map_type'] = 0, ['continent'] = 1, ['transform'] = 1,
+			[1] = {1056.7705078125,704.687744140625,11066.3671875,-3609.68334960938,12123.1376953125,-4314.37109375},
+		}
+		mapData[545] = {
+			['floors'] = 0, ['name'] = "Gilneas", ['rzti'] = 654, ['map_type'] = 0, ['continent'] = 0, ['transform'] = 0,
+			[1] = {3145.83325195312,2097.91668701172,-3439.58325195312,-533.333312988281,-293.75,-2631.25},
+		}
+		mapData[749] = {
+			['floors'] = 1, ['name'] = "WailingCaverns", ['rzti'] = 43, ['map_type'] = 1, ['continent'] = 0, ['transform'] = 0,
+			[1] = { 936.475006103516,624.315994262695,375.946014404297,-410.14599609375,-560.528991699219,214.169998168945 },
+		}
+		mapData[490] = {
+			['floors'] = 0, ['name'] = "GrizzlyHills", ['rzti'] = 571, ['map_type'] = 0, ['continent'] = 4, ['transform'] = 0,
+			[1] = {5249.99987792969,3499.99987792969,1110.41662597656,5516.66650390625,6360.41650390625,2016.66662597656},
+		}
+		mapData[527] = {
+			['floors'] = 1, ['name'] = "TheEyeofEternity", ['rzti'] = 616, ['map_type'] = 2, ['continent'] = 0, ['transform'] = 0,
+			[1] = { 430.070068359375,286.713012695312,-1036.7099609375,611.127990722656,-1466.78002929688,897.841003417969 },
+		}
+		mapData[601] = {
+			['floors'] = 1, ['name'] = "TheForgeofSouls", ['rzti'] = 632, ['map_type'] = 1, ['continent'] = 0, ['transform'] = 0,
+			[1] = { 1448.09985351562,965.400390625,-1686.03002929688,4814.52978515625,-3134.1298828125,5779.93017578125 },
+		}
+		mapData[9] = {
+			['floors'] = 0, ['name'] = "Mulgore", ['rzti'] = 1, ['map_type'] = 0, ['continent'] = 2, ['transform'] = 0,
+			[1] = {5449.99975585938,3633.33325195312,-2204.16650390625,-168.75,3245.83325195312,-3802.08325195312},
+		}
+		mapData[768] = {
+			['floors'] = 1, ['name'] = "TheStonecore", ['rzti'] = 725, ['map_type'] = 1, ['continent'] = 0, ['transform'] = 0,
+			[1] = { 1317.12899780273,878.086975097656,-384.121002197266,797.482971191406,-1701.25,1675.56994628906 },
+		}
+		mapData[28] = {
+			['floors'] = 0, ['name'] = "SearingGorge", ['rzti'] = 0, ['map_type'] = 0, ['continent'] = 1, ['transform'] = 0,
+			[1] = {2231.24984741211,1487.49951171875,322.916656494141,-6100.0,2554.16650390625,-7587.49951171875},
+		}
+		mapData[750] = {
+			['floors'] = 2, ['name'] = "Maraudon", ['rzti'] = 349, ['map_type'] = 1, ['continent'] = 0, ['transform'] = 0,
+			[1] = { 975.0,650.0,827.5,550.0,-147.5,1200.0 },
+			[2] = { 1637.5,1091.66600036621,1158.75,-208.332992553711,-478.75,883.3330078125 },
+		}
+		mapData[121] = {
+			['floors'] = 0, ['name'] = "Feralas", ['rzti'] = 1, ['map_type'] = 0, ['continent'] = 2, ['transform'] = 0,
+			[1] = {6949.99975585938,4633.3330078125,-5441.66650390625,-2366.66650390625,1508.33325195312,-6999.99951171875},
+		}
+		mapData[491] = {
+			['floors'] = 0, ['name'] = "HowlingFjord", ['rzti'] = 571, ['map_type'] = 0, ['continent'] = 4, ['transform'] = 0,
+			[1] = {6045.83288574219,4031.24981689453,1397.91662597656,3116.66650390625,7443.74951171875,-914.583312988281},
+		}
+		mapData[528] = {
+			['floors'] = 4, ['name'] = "Nexus80", ['rzti'] = 578, ['map_type'] = 1, ['continent'] = 0, ['transform'] = 0,
+			[1] = { 514.706970214844,343.138977050781,-787.252990722656,877.070983886719,-1301.9599609375,1220.2099609375 },
+			[2] = { 664.706970214844,443.138977050781,-712.252990722656,927.070983886719,-1376.9599609375,1370.2099609375 },
+			[3] = { 514.706970214844,343.138977050781,-787.252990722656,927.070983886719,-1301.9599609375,1270.2099609375 },
+			[4] = { 294.700988769531,196.463989257812,-897.258972167969,990.406005859375,-1191.9599609375,1186.86999511719 },
+		}
+		mapData[602] = {
+			['floors'] = 0, ['name'] = "PitofSaron", ['rzti'] = 658, ['map_type'] = 1, ['continent'] = 0, ['transform'] = 0,
+			[1] = {1533.33331298828,1022.91667175293,-839.583312988281,1256.25,693.75,233.33332824707},
+		}
+		mapData[769] = {
+			['floors'] = 1, ['name'] = "Skywall", ['rzti'] = 657, ['map_type'] = 1, ['continent'] = 0, ['transform'] = 0,
+			[1] = { 2018.72503662109,1345.81802368164,910.934997558594,-1457.15002441406,-1107.7900390625,-111.332000732422 },
+		}
+		mapData[473] = {
+			['floors'] = 0, ['name'] = "ShadowmoonValley", ['rzti'] = 530, ['map_type'] = 0, ['continent'] = 3, ['transform'] = 1,
+			[1] = {5500.0,3666.66638183594,-4225.0,-1947.91662597656,1275.0,-5614.5830078125},
+		}
+		mapData[510] = {
+			['floors'] = 0, ['name'] = "CrystalsongForest", ['rzti'] = 571, ['map_type'] = 0, ['continent'] = 4, ['transform'] = 0,
+			[1] = {2722.91662597656,1814.5830078125,-1443.75,6502.0830078125,1279.16662597656,4687.5},
+		}
+		mapData[362] = {
+			['floors'] = 0, ['name'] = "ThunderBluff", ['rzti'] = 1, ['map_type'] = 0, ['continent'] = 2, ['transform'] = 0,
+			[1] = {1043.74993896484,695.833312988281,-516.666625976562,-849.999938964844,527.083312988281,-1545.83325195312},
+		}
+		mapData[29] = {
+			['floors'] = 0, ['name'] = "BurningSteppes", ['rzti'] = 0, ['map_type'] = 0, ['continent'] = 1, ['transform'] = 0,
+			[1] = {3152.08319091797,2099.99951171875,464.583312988281,-6985.41650390625,3616.66650390625,-9085.416015625},
+		}
+		mapData[751] = {
+			['floors'] = 0, ['name'] = "TheMaelstromContinent", ['rzti'] = 4294967295, ['map_type'] = 0, ['continent'] = 0, ['transform'] = 0,
+			[1] = {0.0,0.0,-0.0,0.0,-0.0,0.0},
+		}
+		mapData[677] = {
+			['floors'] = 0, ['name'] = "BattleforGilneas", ['rzti'] = 728, ['map_type'] = 1, ['continent'] = 0, ['transform'] = 0,
+			[1] = {889.583251953125,593.749877929688,-1933.33325195312,-1306.25,-1043.75,-1899.99987792969},
+		}
+		mapData[640] = {
+			['floors'] = 0, ['name'] = "Deepholm", ['rzti'] = 646, ['map_type'] = 0, ['continent'] = 0, ['transform'] = 0,
+			[1] = {5099.99987792969,3399.99987792969,-3052.08325195312,2795.83325195312,2047.91662597656,-604.166625976562},
+		}
+		mapData[492] = {
+			['floors'] = 0, ['name'] = "IcecrownGlacier", ['rzti'] = 571, ['map_type'] = 0, ['continent'] = 4, ['transform'] = 0,
+			[1] = {6270.83331298828,4181.25,-5443.75,9427.0830078125,827.083312988281,5245.8330078125},
+		}
+		mapData[529] = {
+			['floors'] = 6, ['name'] = "Ulduar", ['rzti'] = 603, ['map_type'] = 2, ['continent'] = 0, ['transform'] = 0,
+			[1] = {3287.49987792969,2191.66662597656,-1583.33325195312,1168.75,1704.16662597656,-1022.91662597656},
+			[2] = { 669.450988769531,446.300048828125,445.234985351562,1392.7099609375,-224.216003417969,1839.01000976562 },
+			[3] = { 1328.46099853516,885.639892578125,674.739990234375,1679.0400390625,-653.721008300781,2564.67993164062 },
+			[4] = { 910.5,607.0,315.75,1612.0,-594.75,2219.0 },
+			[5] = { 1569.4599609375,1046.30004882812,-1684.98999023438,2122.53002929688,-3254.44995117188,3168.830078125 },
+			[6] = { 619.468994140625,412.97998046875,310.014007568359,1834.77001953125,-309.454986572266,2247.75 },
+		}
+		mapData[603] = {
+			['floors'] = 1, ['name'] = "HallsofReflection", ['rzti'] = 668, ['map_type'] = 1, ['continent'] = 0, ['transform'] = 0,
+			[1] = { 879.02001953125,586.01953125,-1469.98999023438,5126.990234375,-2349.01000976562,5713.009765625 },
+		}
+		mapData[11] = {
+			['floors'] = 0, ['name'] = "Barrens", ['rzti'] = 1, ['map_type'] = 0, ['continent'] = 2, ['transform'] = 0,
+			[1] = {5745.83332824707,3831.24987792969,-202.08332824707,1810.41662597656,5543.75,-2020.83325195312},
+		}
+		mapData[381] = {
+			['floors'] = 0, ['name'] = "Darnassus", ['rzti'] = 1, ['map_type'] = 0, ['continent'] = 2, ['transform'] = 0,
+			[1] = {1539.58337402344,1027.0830078125,-3187.5,10464.5830078125,-1647.91662597656,9437.5},
+		}
+		mapData[770] = {
+			['floors'] = 0, ['name'] = "TwilightHighlands_terrain1", ['rzti'] = 0, ['map_type'] = 0, ['continent'] = 1, ['transform'] = 0,
+			[1] = {5270.8330078125,3514.5830078125,2437.5,-2156.25,7708.3330078125,-5670.8330078125},
+		}
+		mapData[696] = {
+			['floors'] = 1, ['name'] = "MoltenCore", ['rzti'] = 409, ['map_type'] = 2, ['continent'] = 0, ['transform'] = 0,
+			[1] = { 1264.80006408691,843.199066162109,1395.56005859375,459.860992431641,130.759994506836,1303.06005859375 },
+		}
+		mapData[141] = {
+			['floors'] = 0, ['name'] = "Dustwallow", ['rzti'] = 1, ['map_type'] = 0, ['continent'] = 2, ['transform'] = 0,
+			[1] = {5250.00006103516,3499.99975585938,974.999938964844,-2033.33325195312,6225.0,-5533.3330078125},
+		}
+		mapData[30] = {
+			['floors'] = 0, ['name'] = "Elwynn", ['rzti'] = 0, ['map_type'] = 0, ['continent'] = 1, ['transform'] = 0,
+			[1] = {3470.83325195312,2314.5830078125,-1535.41662597656,-7939.5830078125,1935.41662597656,-10254.166015625},
+		}
+		mapData[752] = {
+			['floors'] = 1, ['name'] = "BaradinHold", ['rzti'] = 757, ['map_type'] = 2, ['continent'] = 0, ['transform'] = 0,
+			[1] = { 585.0,390.0,-1032.5,125.0,-1617.5,515.0 },
+		}
+		mapData[678] = {
+			['floors'] = 0, ['name'] = "Gilneas_terrain1", ['rzti'] = 654, ['map_type'] = 0, ['continent'] = 0, ['transform'] = 0,
+			[1] = {3145.83325195312,2097.91668701172,-3439.58325195312,-533.333312988281,-293.75,-2631.25},
+		}
+		mapData[493] = {
+			['floors'] = 0, ['name'] = "SholazarBasin", ['rzti'] = 571, ['map_type'] = 0, ['continent'] = 4, ['transform'] = 0,
+			[1] = {4356.25,2904.16650390625,-6929.16650390625,7287.49951171875,-2572.91650390625,4383.3330078125},
+		}
+		mapData[530] = {
+			['floors'] = 1, ['name'] = "Gundrak", ['rzti'] = 604, ['map_type'] = 1, ['continent'] = 0, ['transform'] = 0,
+			[1] = { 905.033050537109,603.35009765625,-259.886993408203,1465.52001953125,-1164.92004394531,2068.8701171875 },
+		}
+		mapData[604] = {
+			['floors'] = 8, ['name'] = "IcecrownCitadel", ['rzti'] = 631, ['map_type'] = 2, ['continent'] = 0, ['transform'] = 0,
+			[1] = { 1355.47009277344,903.647033691406,-1384.32995605469,-764.840026855469,-2739.80004882812,138.807006835938 },
+			[2] = { 1067.0,711.333690643311,-1631.0,-754.6669921875,-2698.0,-43.3333015441895 },
+			[3] = { 195.469970703125,130.315002441406,-2116.330078125,-580.31298828125,-2311.80004882812,-449.997985839844 },
+			[4] = { 773.710083007812,515.810302734375,-1993.56994628906,4012.40991210938,-2767.28002929688,4528.22021484375 },
+			[5] = { 1148.73999023438,765.820068359375,-2216.06005859375,4002.40991210938,-3364.80004882812,4768.22998046875 },
+			[6] = { 373.7099609375,249.1298828125,-2586.57006835938,4455.75,-2960.28002929688,4704.8798828125 },
+			[7] = { 293.260009765625,195.507019042969,2271.55004882812,410.2919921875,1978.2900390625,605.799011230469 },
+			[8] = { 247.929931640625,165.287994384766,2648.26000976562,414.108001708984,2400.330078125,579.39599609375 },
+		}
+		mapData[382] = {
+			['floors'] = 0, ['name'] = "Undercity", ['rzti'] = 0, ['map_type'] = 0, ['continent'] = 1, ['transform'] = 0,
+			[1] = {959.375030517578,640.104125976562,-873.192626953125,1877.9453125,86.1824035644531,1237.84118652344},
+		}
+		mapData[697] = {
+			['floors'] = 0, ['name'] = "ZulGurub", ['rzti'] = 309, ['map_type'] = 2, ['continent'] = 0, ['transform'] = 0,
+			[1] = {1877.08325195312,1252.0830078125,693.75,-11308.3330078125,2570.83325195312,-12560.416015625},
+		}
+		mapData[512] = {
+			['floors'] = 0, ['name'] = "StrandoftheAncients", ['rzti'] = 607, ['map_type'] = 3, ['continent'] = 0, ['transform'] = 0,
+			[1] = {1743.74993896484,1162.49993896484,-787.5,1883.33325195312,956.249938964844,720.833312988281},
+		}
+		mapData[401] = {
+			['floors'] = 0, ['name'] = "AlteracValley", ['rzti'] = 30, ['map_type'] = 3, ['continent'] = 0, ['transform'] = 0,
+			[1] = {4237.49987792969,2824.99987792969,-1781.24987792969,1085.41662597656,2456.25,-1739.58325195312},
+		}
+		mapData[475] = {
+			['floors'] = 0, ['name'] = "BladesEdgeMountains", ['rzti'] = 530, ['map_type'] = 0, ['continent'] = 3, ['transform'] = 1,
+			[1] = {5424.99975585938,3616.66638183594,-8845.8330078125,4408.3330078125,-3420.83325195312,791.666625976562},
+		}
+		mapData[753] = {
+			['floors'] = 2, ['name'] = "BlackrockCaverns", ['rzti'] = 645, ['map_type'] = 1, ['continent'] = 0, ['transform'] = 0,
+			[1] = { 1019.50793457031,679.672319412231,-439.932006835938,6.66666984558105,-1459.43994140625,686.338989257812 },
+			[2] = { 1019.50793457031,679.672319412231,-239.932006835938,6.66666984558105,-1259.43994140625,686.338989257812 },
+		}
+		mapData[679] = {
+			['floors'] = 0, ['name'] = "Gilneas_terrain2", ['rzti'] = 654, ['map_type'] = 0, ['continent'] = 0, ['transform'] = 0,
+			[1] = {3145.83325195312,2097.91668701172,-3439.58325195312,-533.333312988281,-293.75,-2631.25},
+		}
+		mapData[531] = {
+			['floors'] = 0, ['name'] = "TheObsidianSanctum", ['rzti'] = 615, ['map_type'] = 2, ['continent'] = 0, ['transform'] = 0,
+			[1] = {1162.49991798401,775.0,-1133.33325195312,3616.66650390625,29.1666660308838,2841.66650390625},
+		}
+		mapData[605] = {
+			['floors'] = 0, ['name'] = "Kezan", ['rzti'] = 648, ['map_type'] = 0, ['continent'] = 0, ['transform'] = 0,
+			[1] = {1352.08319091797,900.00048828125,-2129.16650390625,-7731.24951171875,-777.083312988281,-8631.25},
+		}
+		mapData[13] = {
+			['floors'] = 0, ['name'] = "Kalimdor", ['rzti'] = 1, ['map_type'] = 0, ['continent'] = 2, ['transform'] = 0,
+			[1] = {36799.810546875,24533.2001953125,-17066.599609375,12799.900390625,19733.2109375,-11733.2998046875},
+		}
+		mapData[161] = {
+			['floors'] = 0, ['name'] = "Tanaris", ['rzti'] = 1, ['map_type'] = 0, ['continent'] = 2, ['transform'] = 0,
+			[1] = {7212.49951553345,4808.3330078125,62.4999961853027,-5770.8330078125,7274.99951171875,-10579.166015625},
+		}
+		mapData[772] = {
+			['floors'] = 0, ['name'] = "AhnQirajTheFallenKingdom", ['rzti'] = 1, ['map_type'] = 0, ['continent'] = 2, ['transform'] = 0,
+			[1] = {4049.99983215332,2700.0,-3891.66650390625,-8033.3330078125,158.33332824707,-10733.3330078125},
+		}
+		mapData[32] = {
+			['floors'] = 0, ['name'] = "DeadwindPass", ['rzti'] = 0, ['map_type'] = 0, ['continent'] = 1, ['transform'] = 0,
+			[1] = {2499.99993896484,1666.6669921875,833.333312988281,-9866.666015625,3333.33325195312,-11533.3330078125},
+		}
+		mapData[476] = {
+			['floors'] = 0, ['name'] = "BloodmystIsle", ['rzti'] = 530, ['map_type'] = 0, ['continent'] = 1, ['transform'] = 1,
+			[1] = {3262.4990234375,2174.99993896484,10075.0,-758.333312988281,13337.4990234375,-2933.33325195312},
+		}
+		mapData[754] = {
+			['floors'] = 2, ['name'] = "BlackwingDescent", ['rzti'] = 669, ['map_type'] = 2, ['continent'] = 0, ['transform'] = 0,
+			[1] = { 849.69401550293,566.462341070175,675.585021972656,-567.461975097656,-174.108993530273,-0.999634027481079 },
+			[2] = { 999.692977905273,666.462005615234,750.583984375,-307.462005615234,-249.108993530273,359.0 },
+		}
+		mapData[717] = {
+			['floors'] = 0, ['name'] = "RuinsofAhnQiraj", ['rzti'] = 509, ['map_type'] = 2, ['continent'] = 0, ['transform'] = 0,
+			[1] = {2512.49987792969,1675.0,-3035.41650390625,-8233.3330078125,-522.916625976562,-9908.3330078125},
+		}
+		mapData[680] = {
+			['floors'] = 1, ['name'] = "Ragefire", ['rzti'] = 389, ['map_type'] = 1, ['continent'] = 0, ['transform'] = 0,
+			[1] = { 738.864013671875,492.576202392578,285.993011474609,-452.953002929688,-452.871002197266,39.6231994628906 },
+		}
+		mapData[606] = {
+			['floors'] = 0, ['name'] = "Hyjal", ['rzti'] = 1, ['map_type'] = 0, ['continent'] = 2, ['transform'] = 0,
+			[1] = {4245.83337402344,2831.24975585938,929.166625976562,6195.8330078125,5175.0,3364.58325195312},
+		}
+		mapData[14] = {
+			['floors'] = 0, ['name'] = "Azeroth", ['rzti'] = 0, ['map_type'] = 0, ['continent'] = 1, ['transform'] = 0,
+			[1] = {40741.181640625,27149.6875,-18171.970703125,11176.34375,22569.2109375,-15973.34375},
+		}
+		mapData[495] = {
+			['floors'] = 0, ['name'] = "TheStormPeaks", ['rzti'] = 571, ['map_type'] = 0, ['continent'] = 4, ['transform'] = 0,
+			[1] = {7112.49963378906,4741.666015625,-1841.66662597656,10197.916015625,5270.8330078125,5456.25},
+		}
+		mapData[532] = {
+			['floors'] = 1, ['name'] = "VaultofArchavon", ['rzti'] = 624, ['map_type'] = 2, ['continent'] = 0, ['transform'] = 0,
+			[1] = { 1398.25500488281,932.170013427734,812.518981933594,-634.080017089844,-585.736022949219,298.089996337891 },
+		}
+		mapData[773] = {
+			['floors'] = 1, ['name'] = "ThroneoftheFourWinds", ['rzti'] = 754, ['map_type'] = 2, ['continent'] = 0, ['transform'] = 0,
+			[1] = { 1500.0,1000.0,-25.0,-550.0,-1525.0,450.0 },
+		}
+		mapData[736] = {
+			['floors'] = 0, ['name'] = "GilneasBattleground2", ['rzti'] = 761, ['map_type'] = 3, ['continent'] = 0, ['transform'] = 0,
+			[1] = {1302.0832824707,868.75,-1745.83325195312,1604.16662597656,-443.749969482422,735.416625976562},
+		}
+		mapData[699] = {
+			['floors'] = 6, ['name'] = "DireMaul", ['rzti'] = 429, ['map_type'] = 1, ['continent'] = 0, ['transform'] = 0,
+			[1] = { 1275.0,850.0,387.5,200.0,-887.5,1050.0 },
+			[2] = { 525.0,350.0,-125.0,-150.0,-650.0,200.0 },
+			[3] = { 487.5,325.0,-231.25,-150.0,-718.75,175.0 },
+			[4] = { 750.0,500.0,-325.0,-250.0,-1075.0,250.0 },
+			[5] = { 800.000801086426,533.333999633789,900.0,-281.6669921875,99.9991989135742,251.667007446289 },
+			[6] = { 975.0,650.0,862.5,-200.0,-112.5,450.0 },
+		}
+		mapData[477] = {
+			['floors'] = 0, ['name'] = "Nagrand", ['rzti'] = 530, ['map_type'] = 0, ['continent'] = 3, ['transform'] = 1,
+			[1] = {5525.0,3683.33316802979,-10295.8330078125,41.6666641235352,-4770.8330078125,-3641.66650390625},
+		}
+		mapData[181] = {
+			['floors'] = 0, ['name'] = "Aszhara", ['rzti'] = 1, ['map_type'] = 0, ['continent'] = 2, ['transform'] = 0,
+			[1] = {5514.58349609375,3677.08337402344,3372.91650390625,5381.25,8887.5,1704.16662597656},
+		}
+		mapData[755] = {
+			['floors'] = 4, ['name'] = "BlackwingLair", ['rzti'] = 469, ['map_type'] = 2, ['continent'] = 0, ['transform'] = 0,
+			[1] = { 499.428039550781,332.94970703125,1344.05004882812,-7727.06982421875,844.622009277344,-7394.1201171875 },
+			[2] = { 649.427062988281,432.94970703125,1379.05004882812,-7777.06982421875,729.622985839844,-7344.1201171875 },
+			[3] = { 649.427062988281,432.94970703125,1369.05004882812,-7757.06982421875,719.622985839844,-7324.1201171875 },
+			[4] = { 649.427062988281,432.94970703125,1419.05004882812,-7637.06982421875,769.622985839844,-7204.1201171875 },
+		}
+		mapData[718] = {
+			['floors'] = 1, ['name'] = "OnyxiasLair", ['rzti'] = 249, ['map_type'] = 2, ['continent'] = 0, ['transform'] = 0,
+			[1] = { 483.117988586426,322.078788757324,371.734985351562,-223.832992553711,-111.383003234863,98.2457962036133 },
+		}
+		mapData[681] = {
+			['floors'] = 0, ['name'] = "TheLostIsles_terrain1", ['rzti'] = 648, ['map_type'] = 0, ['continent'] = 0, ['transform'] = 0,
+			[1] = {4514.5830078125,3010.41665649414,-4383.3330078125,2881.25,131.25,-129.166656494141},
+		}
+		mapData[607] = {
+			['floors'] = 0, ['name'] = "SouthernBarrens", ['rzti'] = 1, ['map_type'] = 0, ['continent'] = 2, ['transform'] = 0,
+			[1] = {7412.5,4941.66665649414,-1356.25,204.166656494141,6056.25,-4737.5},
+		}
+		mapData[496] = {
+			['floors'] = 0, ['name'] = "ZulDrak", ['rzti'] = 571, ['map_type'] = 0, ['continent'] = 4, ['transform'] = 0,
+			[1] = {4993.75,3329.16650390625,600.0,7668.74951171875,5593.75,4339.5830078125},
+		}
+		mapData[533] = {
+			['floors'] = 3, ['name'] = "AzjolNerub", ['rzti'] = 601, ['map_type'] = 1, ['continent'] = 0, ['transform'] = 0,
+			[1] = { 752.973999023438,501.983001708984,30.0,292.141998291016,-722.973999023438,794.125 },
+			[2] = { 292.973999023438,195.315979003906,-400.0,450.473999023438,-692.973999023438,645.789978027344 },
+			[3] = { 367.5,245.0,-462.125,395.0,-829.625,640.0 },
+		}
+		mapData[737] = {
+			['floors'] = 0, ['name'] = "TheMaelstrom", ['rzti'] = 730, ['map_type'] = 0, ['continent'] = 0, ['transform'] = 0,
+			[1] = {1550.0,1033.33325195312,-1556.25,1370.83325195312,-6.25,337.5},
+		}
+		mapData[700] = {
+			['floors'] = 0, ['name'] = "TwilightHighlands", ['rzti'] = 0, ['map_type'] = 0, ['continent'] = 1, ['transform'] = 0,
+			[1] = {5270.8330078125,3514.5830078125,2437.5,-2156.25,7708.3330078125,-5670.8330078125},
+		}
+		mapData[626] = {
+			['floors'] = 0, ['name'] = "TwinPeaks", ['rzti'] = 726, ['map_type'] = 3, ['continent'] = 0, ['transform'] = 0,
+			[1] = {1214.58325195312,810.41650390625,-931.249938964844,2266.66650390625,283.333312988281,1456.25},
+		}
+		mapData[34] = {
+			['floors'] = 0, ['name'] = "Duskwood", ['rzti'] = 0, ['map_type'] = 0, ['continent'] = 1, ['transform'] = 0,
+			[1] = {2699.99993896484,1800.0,-833.333312988281,-9716.666015625,1866.66662597656,-11516.666015625},
+		}
+		mapData[478] = {
+			['floors'] = 0, ['name'] = "TerokkarForest", ['rzti'] = 530, ['map_type'] = 0, ['continent'] = 3, ['transform'] = 1,
+			[1] = {5399.99975585938,3600.00006103516,-7083.3330078125,-999.999938964844,-1683.33325195312,-4600.0},
+		}
+		mapData[182] = {
+			['floors'] = 0, ['name'] = "Felwood", ['rzti'] = 1, ['map_type'] = 0, ['continent'] = 2, ['transform'] = 0,
+			[1] = {6062.49963378906,4041.66625976562,-1797.91662597656,7237.49951171875,4264.5830078125,3195.83325195312},
+		}
+		mapData[756] = {
+			['floors'] = 2, ['name'] = "TheDeadmines", ['rzti'] = 36, ['map_type'] = 1, ['continent'] = 0, ['transform'] = 0,
+			[1] = { 559.264007568359,372.842502593994,796.622009277344,-337.509002685547,237.358001708984,35.3334999084473 },
+			[2] = { 499.263000488281,332.842300415039,1016.61999511719,-267.509002685547,517.356994628906,65.3332977294922 },
+		}
+		mapData[682] = {
+			['floors'] = 0, ['name'] = "TheLostIsles_terrain2", ['rzti'] = 648, ['map_type'] = 0, ['continent'] = 0, ['transform'] = 0,
+			[1] = {4514.5830078125,3010.41665649414,-4383.3330078125,2881.25,131.25,-129.166656494141},
+		}
+		mapData[16] = {
+			['floors'] = 0, ['name'] = "Arathi", ['rzti'] = 0, ['map_type'] = 0, ['continent'] = 1, ['transform'] = 0,
+			[1] = {3477.08325195312,2318.74984741211,1127.08325195312,-141.666656494141,4604.16650390625,-2460.41650390625},
+		}
+		mapData[534] = {
+			['floors'] = 2, ['name'] = "DrakTharonKeep", ['rzti'] = 600, ['map_type'] = 1, ['continent'] = 0, ['transform'] = 0,
+			[1] = { 619.941009521484,413.293991088867,927.010009765625,-595.859985351562,307.069000244141,-182.565994262695 },
+			[2] = { 619.941009521484,413.293991088867,1002.01000976562,-595.859985351562,382.069000244141,-182.565994262695 },
+		}
+		mapData[201] = {
+			['floors'] = 0, ['name'] = "UngoroCrater", ['rzti'] = 1, ['map_type'] = 0, ['continent'] = 2, ['transform'] = 0,
+			[1] = {3699.99981689453,2466.66650390625,-533.333312988281,-5966.66650390625,3166.66650390625,-8433.3330078125},
+		}
+		mapData[35] = {
+			['floors'] = 0, ['name'] = "LochModan", ['rzti'] = 0, ['map_type'] = 0, ['continent'] = 1, ['transform'] = 0,
+			[1] = {2758.33312988281,1839.5830078125,1993.74987792969,-4487.5,4752.0830078125,-6327.0830078125},
+		}
+		mapData[479] = {
+			['floors'] = 0, ['name'] = "Netherstorm", ['rzti'] = 530, ['map_type'] = 0, ['continent'] = 3, ['transform'] = 1,
+			[1] = {5574.99967193604,3716.66674804688,-5483.3330078125,5456.25,91.6666641235352,1739.58325195312},
+		}
+		mapData[757] = {
+			['floors'] = 1, ['name'] = "GrimBatol", ['rzti'] = 670, ['map_type'] = 1, ['continent'] = 0, ['transform'] = 0,
+			[1] = { 869.047431945801,579.364990234375,952.780029296875,-880.986999511719,83.7325973510742,-301.622009277344 },
+		}
+		mapData[720] = {
+			['floors'] = 0, ['name'] = "Uldum", ['rzti'] = 1, ['map_type'] = 0, ['continent'] = 2, ['transform'] = 0,
+			[1] = {6193.74975585938,4129.16650390625,-2441.66650390625,-8029.16650390625,3752.08325195312,-12158.3330078125},
+		}
+		mapData[683] = {
+			['floors'] = 0, ['name'] = "Hyjal_terrain1", ['rzti'] = 1, ['map_type'] = 0, ['continent'] = 2, ['transform'] = 0,
+			[1] = {4245.83337402344,2831.24975585938,929.166625976562,6195.8330078125,5175.0,3364.58325195312},
+		}
+		mapData[17] = {
+			['floors'] = 0, ['name'] = "Badlands", ['rzti'] = 0, ['map_type'] = 0, ['continent'] = 1, ['transform'] = 0,
+			[1] = {3070.83325195312,2045.8330078125,1902.08325195312,-5854.16650390625,4972.91650390625,-7899.99951171875},
+		}
+		mapData[461] = {
+			['floors'] = 0, ['name'] = "ArathiBasin", ['rzti'] = 529, ['map_type'] = 3, ['continent'] = 0, ['transform'] = 0,
+			[1] = {1756.24992370605,1170.83325195312,-1858.33325195312,1508.33325195312,-102.08332824707,337.5},
+		}
+		mapData[535] = {
+			['floors'] = 6, ['name'] = "Naxxramas", ['rzti'] = 533, ['map_type'] = 2, ['continent'] = 0, ['transform'] = 0,
+			[1] = { 1093.830078125,729.219970703125,3734.10009765625,2886.61010742188,2640.27001953125,3615.830078125 },
+			[2] = { 1093.830078125,729.219970703125,4234.10009765625,2886.61010742188,3140.27001953125,3615.830078125 },
+			[3] = { 1200.0,800.0,3787.0,2336.0,2587.0,3136.0 },
+			[4] = { 1200.330078125,800.219970703125,4287.35009765625,2336.61010742188,3087.02001953125,3136.830078125 },
+			[5] = { 2069.80981445312,1379.8798828125,4400.08984375,2311.34008789062,2330.28002929688,3691.21997070312 },
+			[6] = { 655.93994140625,437.2900390625,5522.2900390625,3379.25,4866.35009765625,3816.5400390625 },
+		}
+		mapData[609] = {
+			['floors'] = 0, ['name'] = "TheRubySanctum", ['rzti'] = 724, ['map_type'] = 2, ['continent'] = 0, ['transform'] = 0,
+			[1] = {752.083312988281,502.083251953125,-902.083312988281,3429.16650390625,-150.0,2927.08325195312},
+		}
+		mapData[36] = {
+			['floors'] = 0, ['name'] = "Redridge", ['rzti'] = 0, ['map_type'] = 0, ['continent'] = 1, ['transform'] = 0,
+			[1] = {2568.74987792969,1712.5,1479.16662597656,-8514.5830078125,4047.91650390625,-10227.0830078125},
+		}
+		mapData[443] = {
+			['floors'] = 0, ['name'] = "WarsongGulch", ['rzti'] = 489, ['map_type'] = 3, ['continent'] = 0, ['transform'] = 0,
+			[1] = {1145.83331298828,764.583312988281,-2041.66662597656,1627.08325195312,-895.833312988281,862.499938964844},
+		}
+		mapData[480] = {
+			['floors'] = 0, ['name'] = "SilvermoonCity", ['rzti'] = 530, ['map_type'] = 0, ['continent'] = 2, ['transform'] = 1,
+			[1] = {1211.45849609375,806.7705078125,6400.75,10153.708984375,7612.20849609375,9346.9384765625},
+		}
+	-- Create Reverse map
+	for k,v in pairs(mapData) do
+		idToMap[v['name']] = k
+	end
+
+	-- Phasing Hacks
+	idToMap['Hyjal_terrain1'] = idToMap['Hyjal']
+
+	-- Build the localized name list.
+	local continentList = {GetMapContinents()}
+	for cID = 1, #continentList do
+		SetMapZoom(cID, 0)
+		local mapfile = GetMapInfo()
+		local cname = continentList[cID]
+		mapToLocal[mapfile] = cname
+		localToMap[cname] = mapfile
+		mapData[idToMap[mapfile]].continent = cID
+		for zID, zname in ipairs({GetMapZones(cID)}) do
+			SetMapZoom(cID, zID)
+			local mapfile = GetMapInfo()
+			-- L: X1, T: Y1, R: X2, B: Y2 New GetCurrentMapZone
+			mapToLocal[mapfile] = zname
+			localToMap[zname] = mapfile
+			mapData[idToMap[mapfile]].continent = cID
+			-- Phasing Hacks
+			if mapfile == "Hyjal_terrain1" then
+				mapToLocal["Hyjal"] = zname
+				mapData[idToMap["Hyjal"]].continent = cID
+			end
+		end
+	end
+
+	for k,v in pairs(mapData) do
+		local rName = rawget(mapToLocal,v.name)
+		if rName == nil and v.rzti then
+			mapToLocal[v.name] = GetRealZoneText(v.rzti)
+		end
+		SetMapByID(k)
+		local _,l,t,r,b = GetCurrentMapZone()
+		if l and l ~= 0 and t and t~= 0 and r and r ~= 0 and b and b ~= 0 and v.floors == 0 then
+			v[1][3] = -l
+			v[1][4] = t
+			v[1][5] = -r
+			v[1][6] = b
+		end
+	end
+end
+
+--- API to encode a location in game
+-- @param x
+-- @param y
+-- @param mapLevel
+-- @return encoded location number
+function lib:EncodeLoc(x,y,level)
+	local level = level or 0
+	if x > 0.9999 then
+		x = 0.9999
+	end
+	if y > 0.9999 then
+		y = 0.9999
+	end
+	return floor( x * 10000 + 0.5 ) * 1000000 + floor( y * 10000  + 0.5 ) * 100 + level
+end
+
+--- API to decode a location num
+-- @param location id
+-- @return x,y,level
+function lib:DecodeLoc(id)
+	return floor(id/1000000)/10000, floor(id % 1000000 / 100)/10000, id % 100
+end
+
+--- API to list all zones
+-- @param (optional) table to store results in
+-- @return a table of zones
+function lib:GetAllMapIDs(storage)
+	local t = storage or {}
+	local i = 1
+	for k,v in pairs(mapData) do
+		t[i] = k
+		i= i + 1
+	end
+	return t
+end
+
+--- API to list raids
+-- @param (optional) table to store results in
+-- @return a table containing the raid area ids
+function lib:GetRaids(storage)
+	local t = storage or {}
+	local i = 1
+	for k,v in pairs(mapData) do
+		if v.map_type == 2 then
+			t[i] = k
+			i = i + 1
+		end
+	end
+	return t
+end
+
+--- API to list dungeons
+-- @param (optional) table to store results in
+-- @return a table containing the dungeon area ids
+function lib:GetDungeons(storage)
+	local t = storage or {}
+	local i = 1
+	for k,v in pairs(mapData) do
+		if v.map_type == 1 then
+			t[i] = k
+			i = i + 1
+		end
+	end
+	return t
+end
+
+
+--- API to get the continent for a given map
+-- @param the map file or id to check
+-- @return the in-game continent index
+function lib:GetContinentFromMap(mapfile)
+	if type(mapfile) == "string" then
+		mapfile = idToMap[mapfile]
+	end
+	if mapfile == WORLDMAP_COSMIC_ID then return -1 end
+	return mapData[mapfile].continent
+end
+
+--- API to list zones by continent
+-- @param Continent index
+-- @param (optional) table to store results in
+-- @return a table containing the zone area ids
+function lib:GetZonesForContinent(continent, storage)
+	local t = storage or {}
+	if continent < 1 then
+		return t
+	end
+	local i = 1
+	for k,v in pairs(mapData) do
+		if v.continent == continent then
+			t[i] = k
+			i = i + 1
+		end
+	end
+	return t
+end
+--- API to determine is a map is a continent
+-- @param mapfile or area id to check
+-- @return true if a continent
+function lib:IsContinentMap(mapfile)
+	if type(mapfile) == "string" then
+		mapfile = idToMap[mapfile]
+	end
+	if mapfile == WORLDMAP_COSMIC_ID then return true end
+	if mapfile == 466 or mapfile == 485 or mapfile == 13 or mapfile == 14 or mapfile == 751 then
+		return true
+	end
+	return false
+end
+
+--[[
+	The upper lft, lower right coords are the position within the continent map
+	so to figure out location on a given continent, we need to upscale the x,y to the continent
+--]]
+
+--- API to get distance and direction to a target in the same map
+-- @param mapfile to use
+-- @param targetX coords
+-- @param targetY coords
+-- @return distance,angle where distance is yards and angle is radians
+function lib:DistanceAndDirection(mapfile,floor,targetX, targetY)
+	local srcX,srcY = GetPlayerMapPosition("player")
+	local distance,xd,yd = self:Distance(mapfile,floor,srcX,srcY,targetX,targetY)
+	local radians =  atan2(xd,-yd)
+	if radians > 0 then
+		radians = PI2 - radians
+	else
+		radians = -radians
+	end
+	return distance,radians
+end
+
+--- API to calc the distance between 2 locations within the same mapfile
+-- @param mapfile or area_id
+-- @param floor to use
+-- @param srcX starting x
+-- @param srcY starting y
+-- @param dstX destination x
+-- @param dstY destination y
+-- @return distance, xdelta, ydelta where distance is the total distance, xdelta is the delta of the x values and ydelta is the detla of y values all in yards
+function lib:Distance(mapfile,floor, srcX,srcY,dstX,dstY)
+	assert(floor == nil or (type(floor) == "number" and floor))
+	local width = 0
+	local height = 0
+	if type(mapfile) == "string" then
+		mapfile = idToMap[mapfile]
+	end
+	if mapfile == WORLDMAP_COSMIC_ID then return 0,0,0 end
+	local data = mapData[mapfile]
+	local fl = data[floor]
+	if floor and floor <= data['floors'] and floor > 0 then
+		width, height  = fl[1],fl[2]
+	else
+		fl = data[1]
+		width,height = fl[1], fl[2]
+	end
+	local x = (dstX - srcX) * width
+	local y = (dstY - srcY) * height
+	return (x*x + y*y)^0.5,x,y
+end
+
+--- API to convert an x,y (yards) in a given zone up to the world map
+-- @param mapfile
+-- @param x in yards
+-- @param y in yards
+-- @return the x,y point in world map yards
+function lib:ConvertToWorldPoint(mapfile,x,y)
+   	if type(mapfile) == "string" then
+		mapfile = idToMap[mapfile]
+	end
+	if mapfile == WORLDMAP_COSMIC_ID then return 0 end
+	local fl = mapData[mapfile]
+	-- Convert to continet data
+	local x1,y1 = self:ConvertToContinent(mapfile,0,x,y)
+	return x1 + contOffsets[fl.continent], y1 + contOffsets[fl.continent]
+end
+
+--- API to convert from the world poistion in yars to the world map scale
+-- @param x the world map x point in yards
+-- @param y in the world map yard point
+-- @return x,y in world map frame scale
+function lib:ConvertFromWorldPoint(x,y)
+	return x/worldMapWidth, y/worldMapHeight
+end
+
+-- API to convert from continent x,y (in yards) to zone x,y
+-- @param map the map to use
+-- @param floor the floor to use
+-- @param x in yards
+-- @param y in yards
+-- @return x,y in zone scale
+function lib:ConvertFromContinent(map,floor,x,y)
+	if type(map) == "string" then
+		map = idToMap[map]
+	end
+	if map == WORLDMAP_COSMIC_ID then return 0,0 end
+	local zx1,zy1 = self:GetMapUpperLeft(map,floor)
+	local zx2,zy2 = self:GetMapLowerRight(map,floor)
+	local x,y = (x-zx1)/(zx1-zx2), (y-zy1)/(zy2-zy1)
+	if mapData[map].transform == 1 then
+		x = x - transforms_x[mapData[map].continent]
+		y = y - transforms_y[mapData[map].continent]
+	end
+	return x,y
+end
+
+-- API to convert to continent x,y (in yards) from zone x,y
+-- @param map the map to use
+-- @param floor the floor to use
+-- @param x in yards
+-- @param y in yards
+-- @return x,y in continent scale
+function lib:ConvertToContinent(map,floor, x,y)
+	if type(map) == "string" then
+		map = idToMap[map]
+	end
+	if map == WORLDMAP_COSMIC_ID then return 0,0 end
+	local zx1,zy1 = self:GetMapUpperLeft(map,floor)
+	local zx2,zy2 = self:GetMapLowerRight(map,floor)
+	local x,y =  zx1 + (zx2-zx1)*x,zy1 + (zy2-zy1)*y
+	if mapData[map].transform == 1 then
+		x = x + transforms_x[mapData[map].continent]
+		y = y + transforms_y[mapData[map].continent]
+	end
+	return x,-y
+end
+
+--- API to calc the distance between 2 locations across map files
+-- @param srcMap or area_id
+-- @param srcFloor to use
+-- @param srcX starting x
+-- @param srcY starting y
+-- @param dstMap destination map file
+-- @param dstFloor destination floor
+-- @param dstX destination x
+-- @param dstY destination y
+-- @return distance, xdelta, ydelta where distance is the total distance, xdelta is the delta of the x values and ydelta is the detla of y values all in yards
+function lib:DistanceWithinContinent(srcMap,srcFloor, srcX, srcY, dstMap, dstFloor, dstX, dstY)
+	assert(srcFloor == nil or (type(srcFloor) == "number" and srcFloor))
+	assert(dstFloor == nil or (type(dstFloor) == "number" and dstFloor))
+	if type(dstMap) == "string" then
+		dstMap = idToMap[dstMap]
+	end
+	if type(srcMap) == "string" then
+		srcMap = idToMap[srcMap]
+	end
+
+	if srcMap == WORLDMAP_COSMIC_ID or dstMap == WORLDMAP_COSMIC_ID then
+		return 0,0,0
+	end
+
+	if mapData[srcMap].continent ~= mapData[dstMap].continent then
+		return 0,0,0
+	end
+	local startX, startY = self:ConvertToContinent(srcMap,srcFloor, srcX, srcY)
+	local endX, endY = self:ConvertToContinent(dstMap,dstFloor, dstX, dstY)
+	local x = (endX - startX)
+	local y = (endY - startY)
+	return (x*x+y*y)^0.5,x,y
+end
+
+--- API to convert coords to yards
+-- @param mapfile or area_id
+-- @param floor
+-- @param x coord
+-- @param y coord
+-- @return x,y as yards
+function lib:PointToYards(mapfile,floor, x, y)
+	assert(floor == nil or (type(floor) == "number" and floor))
+	local width = 0
+	local height = 0
+	if type(mapfile) == "string" then
+		mapfile = idToMap[mapfile]
+	end
+	if mapfile == WORLDMAP_COSMIC_ID then return 0,0 end
+	local data = mapData[mapfile]
+	local fl = data[floor]
+	if floor and floor <= data['floors'] and floor > 0 then
+		width, height  = fl[1],fl[2]
+	else
+		fl = data[1]
+		width,height = fl[1], fl[2]
+	end
+	return x * width, y * height
+end
+
+--- API to convert from yards to a point
+-- @param mapfile or area_id
+-- @param floor
+-- @param x coord in yards
+-- @param y coord in yards
+-- @return x,y as a fractional point
+function lib:YardsToPoint(mapfile,floor,x,y)
+	assert(floor == nil or (type(floor) == "number" and floor))
+	local width = 0
+	local height = 0
+	if type(mapfile) == "string" then
+		mapfile = idToMap[mapfile]
+	end
+	if mapfile == WORLDMAP_COSMIC_ID then return 0,0 end
+	local data = mapData[mapfile]
+	local fl = data[floor]
+	if floor and floor <= data['floors'] and floor > 0 then
+		width, height  = fl[1],fl[2]
+	else
+		local fl = data[1]
+		width,height = fl[1], fl[2]
+	end
+	return x/width, y/height
+end
+
+
+--- API to get the number of floors of a given map
+-- @param mapfile the mapfile you wish to check or area id from GetCurrentMapAreaID()
+-- @return number of floors or 0 if no floors exist
+-- @usage floors = lib:MapFloors(GetMapInfo())
+function lib:MapFloors(mapfile)
+	if type(mapfile) == "string" then
+		mapfile = idToMap[mapfile]
+	end
+	if mapfile == WORLDMAP_COSMIC_ID then return 0 end
+	local fl = mapData[mapfile]['floors']
+	if fl == 1 then
+		fl = 0
+	end
+	return fl
+end
+
+--- API to get area id for a given map file
+-- @param mapfile to check
+-- @return area_id or 0 if the map doesnt exist
+-- @usage aid = lib:MapAreaId(GetMapInfo())
+function lib:MapAreaId(mapfile)
+	assert(mapfile and type(mapfile) == "string")
+	return idToMap[mapfile]
+end
+
+--- API to get localized name of a given map file
+-- @param mapfile or area id to check, note area id is more accurate
+-- @return the localized map name or nil
+-- @usage lname = lib:MapLocalized(GetMapInfo())
+function lib:MapLocalize(mapfile)
+	if type(mapfile) == "number" then
+		mapfile = mapData[mapfile]['name']
+	end
+	if mapfile == WORLDMAP_COSMIC_ID then return WORLD_MAP end
+	return mapToLocal[mapfile]
+end
+
+--- API to get the width,height of a given map
+-- @param mapfile you wish to interrogate or area id from GetCurrentMapAreaID()
+-- @param floor optional floor you wish to examine
+-- @return width,height in yards or 0,0 if no data exists. Will add a message to the DEFAULT_CHAT_FRAME
+-- @usage local w,h = lib:MapArea(GetMapInfo(),GetCurrentMapDungeonLevel())
+function lib:MapArea(mapfile,floor)
+	assert(floor == nil or (type(floor) == "number" and floor))
+	if type(mapfile) == "string" then
+		mapfile = idToMap[mapfile]
+	end
+	if mapfile == WORLDMAP_COSMIC_ID then return 0,0 end
+	local data = mapData[mapfile]
+	local fl = data[floor]
+	if floor and floor <= data['floors'] and floor > 0 then
+		return fl[1],fl[2]
+	else
+		if floor and floor > 0 then
+			return 0,0
+		end
+		fl = data[1]
+		return fl[1], fl[2]
+	end
+end
+
+
+--- API to get the upper left x,y of a given map
+-- @param mapfile you wish to interrogate or area id from GetCurrentMapAreaID()
+-- @param floor optional floor you wish to examine
+-- @return x,y or the upper left corner or 0,0 if no data exists. Will add a message to the DEFAULT_CHAT_FRAME
+-- @usage local x,y = lib:MapUpperLeft(GetMapInfo(),GetCurrentMapDungeonLevel())
+function lib:GetMapUpperLeft(mapfile, floor)
+	assert(floor == nil or (floor and floor >= 0))
+	if type(mapfile) == "string" then
+		mapfile = idToMap[mapfile]
+	end
+	if mapfile == WORLDMAP_COSMIC_ID then return 0,0 end
+	local data = mapData[mapfile]
+	local fl = data[floor + 1]
+	if floor and floor <= data['floors'] then
+		return fl[3],fl[4]
+	else
+		if floor and floor > 0 then
+			return 0,0
+		end
+		fl = data[1]
+		return fl[3],fl[4]
+	end
+end
+
+--- API to get the lower right x,y of a given map
+-- @param mapfile you wish to interrogate or area id from GetCurrentMapAreaID()
+-- @param floor optional floor you wish to examine
+-- @return x,y or the lower right corner or 0,0 if no data exists. Will add a message to the DEFAULT_CHAT_FRAME
+-- @usage local x,y = lib:MapLowerRight(GetMapInfo(),GetCurrentMapDungeonLevel())
+function lib:GetMapLowerRight(mapfile, floor)
+	assert(floor == nil or (floor and floor >= 0))
+	if type(mapfile) == "string" then
+		mapfile = idToMap[mapfile]
+	end
+	if mapfile == WORLDMAP_COSMIC_ID then return 0,0 end
+	local data = mapData[mapfile]
+	local fl = data[floor + 1]
+	if floor and floor <= data['floors'] then
+		return fl[5],fl[6]
+	else
+		if floor and floor > 0 then
+			return 0,0
+		end
+		fl = data[1]
+		return fl[5],fl[6]
+	end
+end
+
+--- API to force a zone change check
+-- calling this method will fire a callback
+-- @param force, optional if you want to force a check even if data hasnt changed
+-- @return void
+function lib:ZoneChanged(force)
+	if WorldMapFrame:IsVisible() then return end
+	SetMapToCurrentZone()
+	local x,y = GetPlayerMapPosition("player")
+	-- if the player is in an instance without a map then dont fire anything
+	if x == 0 and y == 0 then
+		return
+	end
+	local map = GetMapInfo()
+	if map == nil then
+		return
+	end
+	local floor = GetCurrentMapDungeonLevel()
+	if map ~= lastMap or floor ~= lastFloor or force then
+		local w,h = self:MapArea(map,floor)
+		self.callbacks:Fire("MapChanged",map,floor,w,h)
+		lastMap = map
+		lastFloor = floor
+	end
+end
+
+-- Turn on events on someone registers for them
+function lib.callbacks:OnUsed()
+	watchFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
+	watchFrame:RegisterEvent("ZONE_CHANGED")
+	watchFrame:RegisterEvent("ZONE_CHANGED_NEW_AREA")
+	watchFrame:RegisterEvent("ZONE_CHANGED_INDOORS")
+	lib:ZoneChanged(true)
+end
+
+-- turn off events once we no longer have listeners
+function lib.callbacks:OnUnused()
+	watchFrame:UnregisterAllEvents()
+end
+watchFrame:SetScript("OnEvent", function(frame,event,...)
+	lib:ZoneChanged(false)
+end)
+
+--@alpha@
+function lib:Test()
+	-- Validate map files are all present.
+	for continent in pairs({GetMapContinents()}) do
+		local zones = { GetMapZones(continent) }
+		print("Continent "..continent)
+		for zone, name in pairs(zones) do
+			SetMapZoom(continent, zone)
+			local mapFile = GetMapInfo()
+			local area_id = GetCurrentMapAreaID()
+			local w,h = self:MapArea(mapFile)
+			local aid = self:MapAreaId(mapFile)
+			if w == 0 and h == 0 then
+				error("Failed to find map "..mapFile)
+			end
+			if area_id ~= aid then
+				error(mapFile.." area id mismatch")
+			end
+		end
+	end
+	print("All Tests passed")
+end
\ No newline at end of file