Quantcast

Moving over to AceDB and removing dependecy on Dongle

James Whitehead Ii [03-22-08 - 12:00]
Moving over to AceDB and removing dependecy on Dongle

* Reconfigured options screens
Filename
TomTom.lua
TomTom.toc
TomTom_Config.lua
TomTom_Waypoints.lua
diff --git a/TomTom.lua b/TomTom.lua
index 40a7ad4..1a755e8 100755
--- a/TomTom.lua
+++ b/TomTom.lua
@@ -7,7 +7,27 @@ local L = TomTomLocals
 local Astrolabe = DongleStub("Astrolabe-0.4")

 -- Create the addon object
-TomTom = {}
+TomTom = {
+	events = {},
+	eventFrame = CreateFrame("Frame"),
+	RegisterEvent = function(self, event, method)
+		self.eventFrame:RegisterEvent(event)
+		self.events[event] = event or method
+	end,
+	UnregisterEvent = function(self, event)
+		self.eventFrame:UnregisterEvent(event)
+		self.events[event] = nil
+	end,
+}
+
+TomTom.eventFrame:SetScript("OnEvent", function(self, event, ...)
+	local method = TomTom.events[event]
+	if method and TomTom[method] then
+		TomTom[method](TomTom, event, ...)
+	end
+end)
+
+TomTom:RegisterEvent("ADDON_LOADED")

 -- Local definitions
 local GetCurrentCursorPosition
@@ -19,80 +39,100 @@ local RoundCoords

 local waypoints = {}

-function TomTom:Initialize()
-	self.defaults = {
-		profile = {
-			block = {
-				enable = true,
-				accuracy = 2,
-				bordercolor = {1, 0.8, 0, 0.8},
-				bgcolor = {0, 0, 0, 0.4},
-				lock = false,
-				height = 30,
-				width = 100,
-				fontsize = 12,
-			},
-			mapcoords = {
-				playerenable = true,
-				playeraccuracy = 2,
-				cursorenable = true,
-				cursoraccuracy = 2,
-			},
-			arrow = {
-				enable = true,
-				goodcolor = {0, 1, 0},
-				badcolor = {1, 0, 0},
-				middlecolor = {1, 1, 0},
-				arrival = 15,
-				lock = false,
-				showtta = true,
+function TomTom:ADDON_LOADED(event, addon)
+	if addon == "TomTom" then
+		self:UnregisterEvent("ADDON_LOADED")
+		self.defaults = {
+			profile = {
+				block = {
+					enable = true,
+					accuracy = 2,
+					bordercolor = {1, 0.8, 0, 0.8},
+					bgcolor = {0, 0, 0, 0.4},
+					lock = false,
+					height = 30,
+					width = 100,
+					fontsize = 12,
+				},
+				mapcoords = {
+					playerenable = true,
+					playeraccuracy = 2,
+					cursorenable = true,
+					cursoraccuracy = 2,
+				},
+				arrow = {
+					enable = true,
+					goodcolor = {0, 1, 0},
+					badcolor = {1, 0, 0},
+					middlecolor = {1, 1, 0},
+					arrival = 15,
+					lock = false,
+					showtta = true,
+				},
+				minimap = {
+					enable = true,
+					otherzone = true,
+					tooltip = true,
+				},
+				worldmap = {
+					enable = true,
+					otherzone = true,
+					tooltip = true,
+					clickcreate = true,
+				},
+				comm = {
+					enable = true,
+					prompt = false,
+				},
+				persistence = {
+					cleardistance = 10,
+					savewaypoints = true,
+				},
 			},
-			minimap = {
-				enable = true,
-				otherzone = true,
-				tooltip = true,
-			},
-			worldmap = {
-				enable = true,
-				otherzone = true,
-				tooltip = true,
-				clickcreate = true,
-			},
-			comm = {
-				enable = true,
-				prompt = false,
-			},
-			persistence = {
-				cleardistance = 10,
-				savewaypoints = true,
-			},
-		},
-	}
+		}

-	self.db = self:InitializeDB("TomTomDB", self.defaults)
+		self.waydefaults = {
+			profile = {
+				["*"] = {},
+			},
+		}
+
+		self.db = LibStub("AceDB-3.0"):New("TomTomDB", self.defaults, "Default")
+		self.waydb = LibStub("AceDB-3.0"):New("TomTomWaypoints", self.waydefaults)
+		self.db.RegisterCallback(self, "OnProfileChanged", "ReloadOptions")
+		self.db.RegisterCallback(self, "OnProfileCopied", "ReloadOptions")
+		self.db.RegisterCallback(self, "OnProfileReset", "ReloadOptions")
+		self.waydb.RegisterCallback(self, "OnProfileChanged", "ReloadWaypoints")
+		self.waydb.RegisterCallback(self, "OnProfileCopied", "ReloadWaypoints")
+		self.waydb.RegisterCallback(self, "OnProfileReset", "ReloadWaypoints")
+
+		self.tooltip = CreateFrame("GameTooltip", "TomTomTooltip", nil, "GameTooltipTemplate")
+		self.dropdown = CreateFrame("Frame", "TomTomDropdown", nil, "UIDropDownMenuTemplate")
+
+		self:RegisterEvent("PLAYER_LEAVING_WORLD")
+		self:RegisterEvent("PLAYER_ENTERING_WORLD")
+		self:RegisterEvent("ZONE_CHANGED_NEW_AREA")
+		self:RegisterEvent("WORLD_MAP_UPDATE")
+		self:RegisterEvent("CHAT_MSG_ADDON")
+
+		self:ReloadOptions()
+	end
+end

-	self.tooltip = CreateFrame("GameTooltip", "TomTomTooltip", nil, "GameTooltipTemplate")
-	self.dropdown = CreateFrame("Frame", "TomTomDropdown", nil, "UIDropDownMenuTemplate")
+function TomTom:ReloadOptions()
+	-- This handles the reloading of all options
+	self.profile = self.db.profile

-	self:RegisterEvent("PLAYER_LEAVING_WORLD")
-	self:RegisterEvent("PLAYER_ENTERING_WORLD")
-	self:RegisterEvent("ZONE_CHANGED_NEW_AREA")
-	self:RegisterEvent("WORLD_MAP_UPDATE")
-	self:RegisterEvent("CHAT_MSG_ADDON")
+	self:ShowHideWorldCoords()
+	self:ShowHideCoordBlock()

-	-- Push the arrival distance into the callback table
-	local cleardistance = self.db.profile.persistence.cleardistance
-	if cleardistance > 0 then
-		callbackTbl.distance[cleardistance] = function(event, uid)
-			TomTom:RemoveWaypoint(uid)
-		end
-		callbackTbl.distance[cleardistance+1] = function() end
-	end
+end

-	self:ShowHideWorldCoords()
-	self:ShowHideBlockCoords()
+function TomTom:ReloadWaypoints()
 end

+
+
 function TomTom:ShowHideWorldCoords()
 	-- Bail out if we're not supposed to be showing this frame
 	if self.db.profile.mapcoords.playerenable or self.db.profile.mapcoords.cursorenable then
@@ -126,7 +166,7 @@ function TomTom:ShowHideWorldCoords()
 	end
 end

-function TomTom:ShowHideBlockCoords()
+function TomTom:ShowHideCoordBlock()
 	-- Bail out if we're not supposed to be showing this frame
 	if self.db.profile.block.enable then
 		-- Create the frame if it doesn't exist
@@ -239,7 +279,7 @@ local dropdown_info = {
 				local uid = TomTom.dropdown.uid
 				local data = waypoints[uid]
 				TomTom:RemoveWaypoint(uid)
-				TomTom:PrintF("Removing waypoint %0.2f, %0.2f in %s", data.x, data.y, data.zone)
+				--TomTom:PrintF("Removing waypoint %0.2f, %0.2f in %s", data.x, data.y, data.zone)
 			end,
 		},
 	}
@@ -265,29 +305,65 @@ local function init_dropdown(level)
 	end
 end

-callbackTbl = {
-	onclick = function(event, uid, self, button)
-		TomTom.dropdown.uid = uid
-		UIDropDownMenu_Initialize(TomTom.dropdown, init_dropdown)
-		ToggleDropDownMenu(1, nil, TomTom.dropdown, "cursor", 0, 0)
-	end,
-	tooltip_show = function(event, tooltip, uid, dist)
-		local data = waypoints[uid]
+--[[-------------------------------------------------------------------
+--  Define callback functions
+-------------------------------------------------------------------]]--
+local function _both_onclick(event, uid, self, button)
+	TomTom.dropdown.uid = uid
+	UIDropDownMenu_Initialize(TomTom.dropdown, init_dropdown)
+	ToggleDropDownMenu(1, nil, TomTom.dropdown, "cursor", 0, 0)
+end

-		tooltip:SetText(data.title or "TomTom waypoint")
-		tooltip:AddLine(string.format("%s yards away", math.floor(dist)), 1, 1, 1)
-		tooltip:AddLine(string.format("%s (%.2f, %.2f)", data.zone, data.x, data.y), 0.7, 0.7, 0.7)
-		tooltip:Show()
-	end,
-	tooltip_update = function(event, tooltip, uid, dist)
-		tooltip.lines[2]:SetFormattedText("%s yards away", math.floor(dist), 1, 1, 1)
-	end,
-	distance = {
-	},
-}
+local function _both_tooltip_show(event, tooltip, uid, dist)
+	local data = waypoints[uid]
+
+	tooltip:SetText(data.title or "TomTom waypoint")
+	tooltip:AddLine(string.format("%s yards away", math.floor(dist)), 1, 1, 1)
+	tooltip:AddLine(string.format("%s (%.2f, %.2f)", data.zone, data.x, data.y), 0.7, 0.7, 0.7)
+	tooltip:Show()
+end
+
+local function _minimap_tooltip_show(event, tooltip, uid, dist)
+	if not TomTom.db.profile.minimap.tooltip then
+		tooltip:Hide()
+		return
+	end
+	return _both_tooltip_show(event, tooltip, uid, dist)
+end
+
+local function _world_tooltip_show(event, tooltip, uid, dist)
+	if not TomTom.db.profile.worldmap.tooltip then
+		tooltip:Hide()
+		return
+	end
+	return _both_tooltip_show(event, tooltip, uid, dist)
+end
+
+local function _both_tooltip_update(event, tooltip, uid, dist)
+	tooltip.lines[2]:SetFormattedText("%s yards away", math.floor(dist), 1, 1, 1)
+end
+
+local function _both_clear_distance(event, uid, range, distance, lastdistance)
+	self:RemoveWaypoint(uid)
+end
+
+local function _both_remove(event, uid)
+	local data = waypoints[uid]
+	local sv = self.db.profile.waypoints[data.zone]
+
+	-- Find the entry in the saved variable
+	for idx,entry in ipairs(sv) do
+		if entry.uid == uid then
+			table.remove(sv, idx)
+			break
+		end
+	end
+end
+
+local function noop() end

 -- TODO: Make this not suck
-function TomTom:AddWaypoint(x,y,desc)
+function TomTom:AddWaypoint(x, y, desc, persistent, noWorld)
 	local oc,oz = Astrolabe:GetCurrentPlayerPosition()
 	SetMapToCurrentZone()
 	local c,z = Astrolabe:GetCurrentPlayerPosition()
@@ -296,25 +372,57 @@ function TomTom:AddWaypoint(x,y,desc)
 	end

 	if not c or not z or c < 1 then
-		self:Print("Cannot find a valid zone to place the coordinates")
+		--self:Print("Cannot find a valid zone to place the coordinates")
 		return
 	end

-	return self:AddZWaypoint(c,z,x,y,desc)
+	return self:AddZWaypoint(c, z, x, y, desc, persistent, noWorld)
 end

-function TomTom:AddZWaypoint(c,z,x,y,desc)
-	local uid = self:SetWaypoint(c,z,x/100,y/100, callbackTbl)
+function TomTom:AddZWaypoint(c, z, x, y, desc, persistent, noWorld)
+	local callbacks = {
+		minimap = {
+			onclick = _both_onclick,
+			tooltip_show = _minimap_tooltip_show,
+			tooltip_update = _both_tooltip_update,
+		},
+		world = {
+			onclick = _both_onclick,
+			tooltip_show = _world_tooltip_show,
+			tooltip_update = _both_tooltip_show,
+		},
+		distance = {},
+	}
+
+	if persistent == nil then
+		persistent = self.db.profile.persistence.savewaypoints
+	end
+
+	if not persistent then
+		local cleardistance = self.db.profile.persistence.cleardistance
+		callbacks.distance[cleardistance] = _both_clear_distance
+		callbacks.distance[cleardistance+1] = noop
+	end
+
+	local uid = self:SetWaypoint(c,z,x/100,y/100, callbacks, (not noWorld))
 	self:SetCrazyArrow(uid, self.db.profile.arrow.arrival, desc)

-	-- Store this waypoint in the uid
+	local coord = self:GetCoord(x / 100, y / 100)
+	local zone = self:GetMapFile(c, z)
+
 	waypoints[uid] = {
 		title = desc,
-		coord = self:GetCoord(x / 100 , y / 100),
-		zone = self:GetMapFile(c,z),
+		coord = coord,
 		x = x,
 		y = y,
+		zone = zone,
 	}
+
+	-- If this is a persistent waypoint, then add it to the waypoints table
+	if persistent then
+		local data = string.format("%d:%s", coord, title or "")
+		table.insert(self.db.profile.waypoints[zone], data)
+	end
 end

 -- Code taken from HandyNotes, thanks Xinhuan
@@ -364,8 +472,6 @@ function TomTom:GetXY(id)
 	return floor(id / 10000) / 10000, (id % 10000) / 10000
 end

-TomTom = DongleStub("Dongle-1.1"):New("TomTom", TomTom)
-
 do
 	function GetCurrentCursorPosition()
 		-- Coordinate calculation code taken from CT_MapMod
@@ -435,7 +541,6 @@ SlashCmdList["WAY"] = function(msg)
 	if not desc:match("%S") then desc = nil end

 	x,y = tonumber(x), tonumber(y)
-	TomTom:PrintF("Adding waypoint %d %d", x, y)
+	--TomTom:PrintF("Adding waypoint %d %d", x, y)
 	TomTom:AddWaypoint(x, y, desc)
 end
-
diff --git a/TomTom.toc b/TomTom.toc
index 1d5a8a6..1e12ce6 100755
--- a/TomTom.toc
+++ b/TomTom.toc
@@ -1,7 +1,7 @@
 ## Interface: 20400
 ## Title: TomTom
 ## Notes: Acts as your portable navigation assistant
-## SavedVariables: TomTomDB
+## SavedVariables: TomTomDB, TomTomWaypoints
 ## OptionalDeps: Dongle

 Dongle.lua
@@ -11,6 +11,9 @@ libs\LibStub\LibStub.lua
 libs\CallbackHandler-1.0\CallbackHandler-1.0.xml
 libs\AceGUI-3.0\AceGUI-3.0.xml
 libs\AceConfig-3.0\AceConfig-3.0.xml
+libs\AceEvent-3.0\AceEvent-3.0.xml
+libs\AceDB-3.0\AceDB-3.0.xml
+libs\AceDBOptions-3.0\AceDBOptions-3.0.xml

 Localization.enUS.lua

diff --git a/TomTom_Config.lua b/TomTom_Config.lua
index 6e90e18..45930a3 100644
--- a/TomTom_Config.lua
+++ b/TomTom_Config.lua
@@ -1,368 +1,393 @@
-local options = {}
-local db = {}
+local function createconfig()
+	local options = {}

-local L = TomTomLocals
+	local L = TomTomLocals

-options.type = "group"
-options.name = "TomTom"
+	options.type = "group"
+	options.name = "TomTom"

-local function get(info)
-	local ns,opt = string.split(".", info.arg)
-	local val = TomTom.db.profile[ns][opt]
-	--TomTom:Print("get", ns, opt, val)
-	if type(val) == "table" then
-		return unpack(val)
-	else
-		return val
+	local function get(info)
+		local ns,opt = string.split(".", info.arg)
+		local val = TomTom.db.profile[ns][opt]
+		--TomTom:Print("get", ns, opt, val)
+		if type(val) == "table" then
+			return unpack(val)
+		else
+			return val
+		end
 	end
-end

-local function set(info, arg1, arg2, arg3, arg4)
-	local ns,opt = string.split(".", info.arg)
-	--TomTom:Print("set", ns, opt, arg1, arg2, arg3, arg4)
-	if arg2 then
-		local entry = TomTom.db.profile[ns][opt]
-		entry[1] = arg1
-		entry[2] = arg2
-		entry[3] = arg3
-		entry[4] = arg4
-	else
-		TomTom.db.profile[ns][opt] = arg1
-	end
+	local function set(info, arg1, arg2, arg3, arg4)
+		local ns,opt = string.split(".", info.arg)
+		--TomTom:Print("set", ns, opt, arg1, arg2, arg3, arg4)
+		if arg2 then
+			local entry = TomTom.db.profile[ns][opt]
+			entry[1] = arg1
+			entry[2] = arg2
+			entry[3] = arg3
+			entry[4] = arg4
+		else
+			TomTom.db.profile[ns][opt] = arg1
+		end

-	if ns == "block" then
-		TomTom:ShowHideBlockCoords()
-	elseif ns == "mapcoords" then
-		TomTom:ShowHideWorldCoords()
+		if ns == "block" then
+			TomTom:ShowHideCoordBlock()
+		elseif ns == "mapcoords" then
+			TomTom:ShowHideWorldCoords()
+		end
 	end
-end

-options.args = {}
+	options.args = {}

-options.args.coordblock = {
-   type = "group",
-   name = L["Coordinate Block"],
-   desc = L["Options that alter the coordinate block"],
-   get = get,
-   set = set,
-   args = {
-      desc = {
-         order = 1,
-         type = "description",
-         name = L["TomTom provides you with a floating coordinate display that can be used to determine your current position.  These options can be used to enable or disable this display, or customize the block's display."],
-      },
-      enable = {
-         order = 2,
-         type = "toggle",
-         name = L["Enable coordinate block"],
-         desc = L["Enables a floating block that displays your current position in the current zone"],
-		 width = "double",
-         arg = "block.enable",
-      },
-	  lock = {
-		  order = 3,
-		  type = "toggle",
-		  name = L["Lock coordinate block"],
-		  desc = L["Locks the coordinate block so it can't be accidentally dragged to another location"],
-		  width = "double",
-		  arg = "block.lock",
-	  },
-	  accuracy = {
-		  order = 4,
-		  type = "range",
-		  name = "Coordinate Accuracy",
-		  desc = L["Coordinates can be displayed as simple XX, YY coordinate, or as more precise XX.XX, YY.YY.  This setting allows you to control that precision"],
-		  min = 0, max = 2, step = 1,
-		  arg = "block.accuracy",
-	  },
-	  display = {
-         order = 4,
-         type = "group",
-		 inline = true,
-         name = L["Display Settings"],
-		 args = {
-			 help = {
-				 type = "description",
-				 name = L["The display of the coordinate block can be customized by changing the options below."],
-				 order = 1,
-			 },
-			 bordercolor = {
-				 type = "color",
-				 name = L["Border color"],
-				 arg = "block.bordercolor",
-			 },
-			 bgcolor = {
-				 type = "color",
-				 name = L["Background color"],
-				 arg = "block.bgcolor",
-			 },
-			 height = {
-				 type = "range",
-				 name = L["Block height"],
-				 arg = "block.height",
-				 min = 5, max = 50, step = 1,
-			 },
-			 width = {
-				 type = "range",
-				 name = L["Block width"],
-				 arg = "block.width",
-				 min = 50, max = 250, step = 5,
-			 },
-			 fontsize = {
-				 type = "range",
-				 name = L["Font size"],
-				 arg = "block.fontsize",
-				 min = 1, max = 24, step = 1,
-			 },
-		 },
-	 },
-   },
-} -- End coordinate block settings
+	options.args.coordblock = {
+		type = "group",
+		name = L["Coordinate Block"],
+		desc = L["Options that alter the coordinate block"],
+		get = get,
+		set = set,
+		args = {
+			desc = {
+				order = 1,
+				type = "description",
+				name = L["TomTom provides you with a floating coordinate display that can be used to determine your current position.  These options can be used to enable or disable this display, or customize the block's display."],
+			},
+			enable = {
+				order = 2,
+				type = "toggle",
+				name = L["Enable coordinate block"],
+				desc = L["Enables a floating block that displays your current position in the current zone"],
+				width = "double",
+				arg = "block.enable",
+			},
+			lock = {
+				order = 3,
+				type = "toggle",
+				name = L["Lock coordinate block"],
+				desc = L["Locks the coordinate block so it can't be accidentally dragged to another location"],
+				width = "double",
+				arg = "block.lock",
+			},
+			accuracy = {
+				order = 4,
+				type = "range",
+				name = "Coordinate Accuracy",
+				desc = L["Coordinates can be displayed as simple XX, YY coordinate, or as more precise XX.XX, YY.YY.  This setting allows you to control that precision"],
+				min = 0, max = 2, step = 1,
+				arg = "block.accuracy",
+			},
+			display = {
+				order = 4,
+				type = "group",
+				inline = true,
+				name = L["Display Settings"],
+				args = {
+					help = {
+						type = "description",
+						name = L["The display of the coordinate block can be customized by changing the options below."],
+						order = 1,
+					},
+					bordercolor = {
+						type = "color",
+						name = L["Border color"],
+						arg = "block.bordercolor",
+					},
+					bgcolor = {
+						type = "color",
+						name = L["Background color"],
+						arg = "block.bgcolor",
+						hasAlpha = true,
+					},
+					height = {
+						type = "range",
+						name = L["Block height"],
+						arg = "block.height",
+						min = 5, max = 50, step = 1,
+					},
+					width = {
+						type = "range",
+						name = L["Block width"],
+						arg = "block.width",
+						min = 50, max = 250, step = 5,
+					},
+					fontsize = {
+						type = "range",
+						name = L["Font size"],
+						arg = "block.fontsize",
+						min = 1, max = 24, step = 1,
+					},
+				},
+			},
+		},
+	} -- End coordinate block settings

-options.args.crazytaxi = {
-   type = "group",
-   name = L["Waypoint Arrow"],
-   get = get,
-   set = set,
-   args = {
-      help = {
-         order = 1,
-         type = "description",
-         name = L["TomTom provides an arrow that can be placed anywhere on the screen.  Similar to the arrow in \"Crazy Taxi\" it will point you towards your next waypoint"],
-      },
-      enable = {
-         order = 2,
-         type = "toggle",
-         name = L["Enable floating waypoint arrow"],
-         width = "double",
-		 arg = "arrow.enable",
-      },
-	  lock = {
-		  order = 3,
-		  type = "toggle",
-		  name = L["Lock waypoint arrow"],
-		  desc = L["Locks the waypoint arrow, so it can't be moved accidentally"],
-		  arg = "arrow.lock",
-	  },
-	  arrival = {
-		  order = 4,
-		  type = "toggle",
-		  name = L["Show estimated time to arrival"],
-		  desc = L["Shows an estimate of how long it will take you to reach the waypoint at your current speed"],
-		  width = "double",
-		  arg = "arrow.showtta",
-	  },
-	  heredistance = {
-		  order = 5,
-		  type = "range",
-		  name = L["\"Arrival Distance\""],
-		  desc = L["This setting will control the distance at which the waypoint arrow switches to a downwards arrow, indicating you have arrived at your destination"],
-		  min = 0, max = 150, step = 5,
-		  arg = "arrow.arrival",
-	  },
-      color = {
-         type = "group",
-         name = L["Arrow colors"],
-		 inline = true,
-         args = {
-            help = {
-               order = 1,
-               type = "description",
-               name = L["The floating waypoint arrow can change color depending on whether or nor you are facing your destination.  By default it will display green when you are facing it directly, and red when you are facing away from it.  These colors can be changed in this section.  Setting these options to the same color will cause the arrow to not change color at all"],
-            },
-            colorstart = {
+	options.args.crazytaxi = {
+		type = "group",
+		name = L["Waypoint Arrow"],
+		get = get,
+		set = set,
+		args = {
+			help = {
+				order = 1,
+				type = "description",
+				name = L["TomTom provides an arrow that can be placed anywhere on the screen.  Similar to the arrow in \"Crazy Taxi\" it will point you towards your next waypoint"],
+			},
+			enable = {
 				order = 2,
-               type = "color",
-               name = L["Good color"],
-			   desc = L["The color to be displayed when you are moving in the direction of the active waypoint"],
-			   arg = "arrow.goodcolor",
-			   hasAlpha = false,
-            },
-			colormiddle = {
+				type = "toggle",
+				name = L["Enable floating waypoint arrow"],
+				width = "double",
+				arg = "arrow.enable",
+			},
+			lock = {
 				order = 3,
-				type = "color",
-				name = L["Middle color"],
-				desc = L["The color to be displayed when you are halfway between the direction of the active waypoint and the completely wrong direction"],
-				arg = "arrow.middlecolor",
-				hasAlpha = false,
+				type = "toggle",
+				name = L["Lock waypoint arrow"],
+				desc = L["Locks the waypoint arrow, so it can't be moved accidentally"],
+				arg = "arrow.lock",
 			},
-            colorend = {
+			arrival = {
 				order = 4,
-               type = "color",
-               name = L["Bad color"],
-			   desc = L["The color to be displayed when you are moving in the opposite direction of the active waypoint"],
-			   arg = "arrow.badcolor",
-			   hasAlpha = false,
-            },
-         },
-      },
-   },
-} -- End crazy taxi options
+				type = "toggle",
+				name = L["Show estimated time to arrival"],
+				desc = L["Shows an estimate of how long it will take you to reach the waypoint at your current speed"],
+				width = "double",
+				arg = "arrow.showtta",
+			},
+			heredistance = {
+				order = 5,
+				type = "range",
+				name = L["\"Arrival Distance\""],
+				desc = L["This setting will control the distance at which the waypoint arrow switches to a downwards arrow, indicating you have arrived at your destination"],
+				min = 0, max = 150, step = 5,
+				arg = "arrow.arrival",
+			},
+			color = {
+				type = "group",
+				name = L["Arrow colors"],
+				inline = true,
+				args = {
+					help = {
+						order = 1,
+						type = "description",
+						name = L["The floating waypoint arrow can change color depending on whether or nor you are facing your destination.  By default it will display green when you are facing it directly, and red when you are facing away from it.  These colors can be changed in this section.  Setting these options to the same color will cause the arrow to not change color at all"],
+					},
+					colorstart = {
+						order = 2,
+						type = "color",
+						name = L["Good color"],
+						desc = L["The color to be displayed when you are moving in the direction of the active waypoint"],
+						arg = "arrow.goodcolor",
+						hasAlpha = false,
+					},
+					colormiddle = {
+						order = 3,
+						type = "color",
+						name = L["Middle color"],
+						desc = L["The color to be displayed when you are halfway between the direction of the active waypoint and the completely wrong direction"],
+						arg = "arrow.middlecolor",
+						hasAlpha = false,
+					},
+					colorend = {
+						order = 4,
+						type = "color",
+						name = L["Bad color"],
+						desc = L["The color to be displayed when you are moving in the opposite direction of the active waypoint"],
+						arg = "arrow.badcolor",
+						hasAlpha = false,
+					},
+				},
+			},
+		},
+	} -- End crazy taxi options

-options.args.minimap = {
-   type = "group",
-   name = L["Minimap"],
-   get = get,
-   set = set,
-   args = {
-      help = {
-         order = 1,
-         type = "description",
-         name = L["TomTom can display multiple waypoint arrows on the minimap.  These options control the display of these waypoints"],
-      },
-      enable = {
-         order = 2,
-         type = "toggle",
-         name = L["Enable minimap waypoints"],
-         width = "double",
-		 arg = "minimap.enable",
-      },
-      otherzone = {
-         type = "toggle",
-         name = L["Display waypoints from other zones"],
-         desc = L["TomTom can hide waypoints in other zones, this setting toggles that functionality"],
-         width = "double",
-		 arg = "minimap.otherzone",
-      },
-      tooltip = {
-         type = "toggle",
-         name = L["Enable mouseover tooltips"],
-         desc = L["TomTom can display a tooltip containing information abouto waypoints, when they are moused over.  This setting toggles that functionality"],
-		 width = "double",
-		 arg = "minimap.tooltip",
-      },
-
-   },
-} -- End minimap options
+	options.args.minimap = {
+		type = "group",
+		name = L["Minimap"],
+		get = get,
+		set = set,
+		args = {
+			help = {
+				order = 1,
+				type = "description",
+				name = L["TomTom can display multiple waypoint arrows on the minimap.  These options control the display of these waypoints"],
+			},
+			enable = {
+				order = 2,
+				type = "toggle",
+				name = L["Enable minimap waypoints"],
+				width = "double",
+				arg = "minimap.enable",
+			},
+			otherzone = {
+				type = "toggle",
+				name = L["Display waypoints from other zones"],
+				desc = L["TomTom can hide waypoints in other zones, this setting toggles that functionality"],
+				width = "double",
+				arg = "minimap.otherzone",
+			},
+			tooltip = {
+				type = "toggle",
+				name = L["Enable mouseover tooltips"],
+				desc = L["TomTom can display a tooltip containing information abouto waypoints, when they are moused over.  This setting toggles that functionality"],
+				width = "double",
+				arg = "minimap.tooltip",
+			},

-options.args.worldmap = {
-	type = "group",
-	name = L["World Map"],
-	get = get,
-	set = set,
-	args = {
-		help = {
-			order = 1,
-			type = "description",
-			name = L["TomTom can display multiple waypoints on the world map.  These options control the display of these waypoints"],
 		},
-		enable = {
-			order = 2,
-			type = "toggle",
-			name = L["Enable world map waypoints"],
-			width = "double",
-			arg = "worldmap.enable",
-		},
-		otherzone = {
-			order = 3,
-			type = "toggle",
-			name = L["Display waypoints from other zones"],
-			desc = L["TomTom can hide waypoints in other zones, this setting toggles that functionality"],
-			width = "double",
-			arg = "worldmap.otherzone",
-		},
-		tooltip = {
-			order = 4,
-			type = "toggle",
-			name = L["Enable mouseover tooltips"],
-			desc = L["TomTom can display a tooltip containing information abouto waypoints, when they are moused over.  This setting toggles that functionality"],
-			width = "double",
-			arg = "worldmap.tooltip",
-		},
-		createclick = {
-			order = 5,
-			type = "toggle",
-			name = L["Allow control-right clicking on map to create new waypoint"],
-			width = "double",
-			arg = "worldmap.clickcreate",
-		},
-		player = {
-			order = 6,
-			type = "group",
-			inline = true,
-			name = L["Player Coordinates"],
-			args = {
-				enableplayer = {
-					order = 1,
-					type = "toggle",
-					name = L["Enable showing player coordinates"],
-					width = "double",
-					arg = "mapcoords.playerenable",
+	} -- End minimap options
+
+	options.args.worldmap = {
+		type = "group",
+		name = L["World Map"],
+		get = get,
+		set = set,
+		args = {
+			help = {
+				order = 1,
+				type = "description",
+				name = L["TomTom can display multiple waypoints on the world map.  These options control the display of these waypoints"],
+			},
+			enable = {
+				order = 2,
+				type = "toggle",
+				name = L["Enable world map waypoints"],
+				width = "double",
+				arg = "worldmap.enable",
+			},
+			otherzone = {
+				order = 3,
+				type = "toggle",
+				name = L["Display waypoints from other zones"],
+				desc = L["TomTom can hide waypoints in other zones, this setting toggles that functionality"],
+				width = "double",
+				arg = "worldmap.otherzone",
+			},
+			tooltip = {
+				order = 4,
+				type = "toggle",
+				name = L["Enable mouseover tooltips"],
+				desc = L["TomTom can display a tooltip containing information abouto waypoints, when they are moused over.  This setting toggles that functionality"],
+				width = "double",
+				arg = "worldmap.tooltip",
+			},
+			createclick = {
+				order = 5,
+				type = "toggle",
+				name = L["Allow control-right clicking on map to create new waypoint"],
+				width = "double",
+				arg = "worldmap.clickcreate",
+			},
+			player = {
+				order = 6,
+				type = "group",
+				inline = true,
+				name = L["Player Coordinates"],
+				args = {
+					enableplayer = {
+						order = 1,
+						type = "toggle",
+						name = L["Enable showing player coordinates"],
+						width = "double",
+						arg = "mapcoords.playerenable",
+					},
+					playeraccuracy = {
+						order = 4,
+						type = "range",
+						name = L["Player coordinate accuracy"],
+						desc = L["Coordinates can be displayed as simple XX, YY coordinate, or as more precise XX.XX, YY.YY.  This setting allows you to control that precision"],
+						min = 0, max = 2, step = 1,
+						arg = "mapcoords.playeraccuracy",
+					},
 				},
-				playeraccuracy = {
-					order = 4,
-					type = "range",
-					name = L["Player coordinate accuracy"],
-					desc = L["Coordinates can be displayed as simple XX, YY coordinate, or as more precise XX.XX, YY.YY.  This setting allows you to control that precision"],
-					min = 0, max = 2, step = 1,
-					arg = "mapcoords.playeraccuracy",
+			},
+			cursor = {
+				order = 7,
+				type = "group",
+				inline = true,
+				name = L["Cursor Coordinates"],
+				args = {
+					enablecursor = {
+						order = 3,
+						type = "toggle",
+						name = L["Enable showing cursor coordinates"],
+						width = "double",
+						arg = "mapcoords.cursorenable",
+					},
+
+					cursoraccuracy = {
+						order = 5,
+						type = "range",
+						name = L["Cursor coordinate accuracy"],
+						desc = L["Coordinates can be displayed as simple XX, YY coordinate, or as more precise XX.XX, YY.YY.  This setting allows you to control that precision"],
+						min = 0, max = 2, step = 1,
+						arg = "mapcoords.cursoraccuracy",
+					},
 				},
 			},
 		},
-		cursor = {
-			order = 7,
-			type = "group",
-			inline = true,
-			name = L["Cursor Coordinates"],
-			args = {
-				enablecursor = {
-					order = 3,
-					type = "toggle",
-					name = L["Enable showing cursor coordinates"],
-					width = "double",
-					arg = "mapcoords.cursorenable",
-				},
+	} -- End world map options

-				cursoraccuracy = {
-					order = 5,
-					type = "range",
-					name = L["Cursor coordinate accuracy"],
-					desc = L["Coordinates can be displayed as simple XX, YY coordinate, or as more precise XX.XX, YY.YY.  This setting allows you to control that precision"],
-					min = 0, max = 2, step = 1,
-					arg = "mapcoords.cursoraccuracy",
-				},
+	options.args.general = {
+		type = "group",
+		name = L["General Options"],
+		get = get,
+		set = set,
+		args = {
+			comm = {
+				type = "toggle",
+				order = 1,
+				name = L["Accept waypoints from guild and party members"],
+				width = "double",
+				arg = "comm.enable",
+			},
+			promptcomm = {
+				type = "toggle",
+				order = 2,
+				name = L["Prompt before accepting sent waypoints"],
+				width = "double",
+				arg = "comm.prompt",
+			},
+			persistence = {
+				type = "toggle",
+				order = 3,
+				name = L["Save waypoints in between sessions"],
+				width = "double",
+				arg = "persistence.savewaypoints",
+			},
+			cleardistance = {
+				type = "range",
+				order = 4,
+				name = L["Clear waypoint distance"],
+				desc = L["Waypoints can be automatically cleared when you reach them.  This slider allows you to customize the distance in yards that signals your \"arrival\" at the waypoint.  A setting of 0 turns off the auto-clearing feature\n\nChanging this setting only takes effect after reloading your interface."],
+				min = 0, max = 150, step = 1,
+				arg = "persistence.cleardistance",
 			},
 		},
-	},
-} -- End world map options
+	}

-options.args.general = {
-   type = "group",
-   name = L["General Options"],
-   get = get,
-   set = set,
-   args = {
-      comm = {
-         type = "toggle",
-		 order = 1,
-         name = L["Accept waypoints from guild and party members"],
-         width = "double",
-		 arg = "comm.enable",
-      },
-      promptcomm = {
-         type = "toggle",
-		 order = 2,
-         name = L["Prompt before accepting sent waypoints"],
-         width = "double",
-		 arg = "comm.prompt",
-      },
-      persistence = {
-         type = "toggle",
-		 order = 3,
-         name = L["Save waypoints in between sessions"],
-         width = "double",
-		 arg = "persistence.savewaypoints",
-      },
-	  cleardistance = {
-		  type = "range",
-		  order = 4,
-		  name = L["Clear waypoint distance"],
-		  desc = L["Waypoints can be automatically cleared when you reach them.  This slider allows you to customize the distance in yards that signals your \"arrival\" at the waypoint.  A setting of 0 turns off the auto-clearing feature\n\nChanging this setting only takes effect after reloading your interface."],
-		  min = 0, max = 150, step = 1,
-		  arg = "persistence.cleardistance",
-	  },
-   },
-}
+	options.args.profile = {
+		type = "group",
+		name = L["Profile options"],
+		args = {
+			desc = {
+				order = 1,
+				type = "description",
+				name = L["TomTom's saved variables are organized so you can have shared options across all your characters, while having different sets of waypoints for each.  These options sections allow you to change the saved variable configurations so you can set up per-character options, or even share waypoints between characters"],
+			},
+			options = LibStub("AceDBOptions-3.0"):GetOptionsTable(TomTom.db),
+			waypoints = LibStub("AceDBOptions-3.0"):GetOptionsTable(TomTom.waydb)
+		}
+	}
+
+	options.args.profile.args.options.name = L["Options profile"]
+	options.args.profile.args.options.desc = L["Saved profile for TomTom options"]
+	options.args.profile.args.options.order = 2
+	options.args.profile.args.waypoints.name = L["Waypoints profile"]
+	options.args.profile.args.waypoints.desc = L["Save profile for TomTom waypoints"]
+	options.args.profile.args.waypoints.order = 3
+
+	return options
+end

 local config = LibStub("AceConfig-3.0")
 local dialog = LibStub("AceConfigDialog-3.0")
@@ -371,8 +396,9 @@ local registered = false;
 SLASH_TOMTOM1 = "/tomtom"
 SlashCmdList["TOMTOM"] = function(msg)
 	local build = GetBuildInfo()
-
+
 	if not registered then
+		local options = createconfig()
 		if build == "0.4.0" then
 			config:RegisterOptionsTable("TomTom", {
 				name = L["TomTom"],
@@ -388,6 +414,17 @@ SlashCmdList["TOMTOM"] = function(msg)
 			dialog:AddToBlizOptions("TomTom", "TomTom")

 			-- Add the options in reverse order of how we want them to be shown
+			-- Profile Options
+			local p_options = options.args.profile.args.options
+			local w_options = options.args.profile.args.waypoints
+			options.args.profile.args.options = nil
+			options.args.profile.args.waypoints = nil
+			config:RegisterOptionsTable("TomTom-Profiles", options.args.profile)
+			config:RegisterOptionsTable("TomTom-Profiles-Options", p_options)
+			config:RegisterOptionsTable("TomTom-Profiles-Waypoints", p_waypoints)
+			dialog:AddToBlizOptions("TomTom-Profiles", options.args.profile.name, "TomTom")
+			dialog:AddToBlizOptions("TomTom-Profiles-Options", p_options.name, "TomTom-Profiles")
+			dialog:AddToBlizOptions("TomTom-Profiles-Waypoints", p_waypoints.name, "TomTom-Profiles")
 			-- World Map Options
 			config:RegisterOptionsTable("TomTom-Worldmap", options.args.worldmap)
 			dialog:AddToBlizOptions("TomTom-Worldmap", options.args.worldmap.name, "TomTom")
diff --git a/TomTom_Waypoints.lua b/TomTom_Waypoints.lua
index 0424f53..87a783b 100644
--- a/TomTom_Waypoints.lua
+++ b/TomTom_Waypoints.lua
@@ -61,7 +61,7 @@ local Minimap_OnEnter,Minimap_OnLeave,Minimap_OnUpdate,Minimap_OnClick,Minimap_O
 local Arrow_OnUpdate
 local World_OnEnter,World_OnLeave,World_OnClick,World_OnEvent

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

@@ -116,7 +116,10 @@ function TomTom:SetWaypoint(c, z, x, y, callbacks)
 	point.z = z
 	point.x = x
 	point.y = y
+	point.world = world
 	point.callbacks = callbacks
+	point.worldmap.callbacks = callbacks and callbacks.world
+	point.minimap.callbacks = callbacks and callbacks.minimap

 	-- Process the callbacks table to put distances in a consumable format
 	if callbacks and callbacks.distance then
@@ -136,7 +139,9 @@ function TomTom:SetWaypoint(c, z, x, y, callbacks)

 	-- Place the waypoint
 	Astrolabe:PlaceIconOnMinimap(point.minimap, c, z, x, y)
-	Astrolabe:PlaceIconOnWorldMap(WorldMapDetailFrame, point.worldmap, c, z, x, y)
+	if point.world then
+		Astrolabe:PlaceIconOnWorldMap(WorldMapDetailFrame, point.worldmap, c, z, x, y)
+	end

 	point.uid = getuid(point)
 	return point.uid
@@ -148,6 +153,11 @@ function TomTom:RemoveWaypoint(uid)
 	point.minimap:Hide()
 	point.worldmap:Hide()
 	table.insert(pool, point)
+
+	if point.callbacks and point.callbacks.remove then
+		point.callbacks.remove("remove", uid)
+	end
+
 	point.uid = nil
 end

@@ -172,15 +182,15 @@ do
 	end

 	function Minimap_OnClick(self, button)
-		local data = self.point.callbacks
+		local data = self.callbacks

-		if data.onclick then
+		if data and data.onclick then
 			data.onclick("onclick", self.point.uid, self, button)
 		end
 	end

 	function Minimap_OnEnter(self, motion)
-		local data = self.point.callbacks
+		local data = self.callbacks

 		if data and data.tooltip_show then
 			local uid = self.point.uid
@@ -189,6 +199,13 @@ do
 			tooltip_uid = uid
 			tooltip_callbacks = data

+			-- Parent to UIParent, unless it's hidden
+			if UIParent:IsVisible() then
+				tooltip:SetParent(UIParent)
+			else
+				tooltip:SetParent(self)
+			end
+
 			tooltip:SetOwner(self, "ANCHOR_BOTTOMLEFT")

 			data.tooltip_show("tooltip_show", tooltip, uid, dist)
@@ -318,19 +335,13 @@ do
 			end

 			local data = self.point
-			-- It seems that data.x and data.y are occasionally not valid
-			-- perhaps when the waypoint is removed.  Guard this for now
-			-- TODO: Fix permanently
-			if not data.x or not data.y then
-				self:Hide()
-				return
-			end
-
-			local x,y = Astrolabe:PlaceIconOnWorldMap(WorldMapDetailFrame, self, data.c, data.z, data.x, data.y)
-			if (x and y and (0 < x and x <= 1) and (0 < y and y <= 1)) then
-				self:Show()
-			else
-				self:Hide()
+			if data.world then
+				local x,y = Astrolabe:PlaceIconOnWorldMap(WorldMapDetailFrame, self, data.c, data.z, data.x, data.y)
+				if (x and y and (0 < x and x <= 1) and (0 < y and y <= 1)) then
+					self:Show()
+				else
+					self:Hide()
+				end
 			end
 		end
 	end