diff --git a/indra/newview/llfloaterhoverheight.cpp b/indra/newview/llfloaterhoverheight.cpp
index f25d491910807abaf2ff9e486bde83cfdd3b7c1d..bcdab6b3a01f335a10cd43472bdf0be60edbdcae 100755
--- a/indra/newview/llfloaterhoverheight.cpp
+++ b/indra/newview/llfloaterhoverheight.cpp
@@ -36,68 +36,58 @@
 #include "llviewerregion.h"
 #include "llvoavatarself.h"
 
-class LLHoverHeightResponder: public LLHTTPClient::Responder
+LLFloaterHoverHeight::LLFloaterHoverHeight(const LLSD& key) : LLFloater(key)
 {
-public:
-	LLHoverHeightResponder(): LLHTTPClient::Responder() {}
+}
 
-private:
-	void httpFailure()
-	{
-		LL_WARNS() << dumpResponse() << LL_ENDL;
-	}
+void LLFloaterHoverHeight::syncFromPreferenceSetting(void *user_data)
+{
+	LLVector3 offset = gSavedSettings.getVector3("AvatarPosFinalOffset");
+	F32 value = offset[2];
 
-	void httpSuccess()
+	LLFloaterHoverHeight *self = static_cast<LLFloaterHoverHeight*>(user_data);
+	LLSliderCtrl* sldrCtrl = self->getChild<LLSliderCtrl>("HoverHeightSlider");
+	sldrCtrl->setValue(value,FALSE);
+	if (isAgentAvatarValid())
 	{
-		LL_INFOS() << dumpResponse() << LL_ENDL;
+		gAgentAvatarp->sendHoverHeight();
 	}
-};
-
-LLFloaterHoverHeight::LLFloaterHoverHeight(const LLSD& key) : LLFloater(key)
-{
 }
 
 BOOL LLFloaterHoverHeight::postBuild()
 {
-
-	LLVector3 offset = gSavedSettings.getVector3("AvatarPosFinalOffset");
-	F32 value = offset[2];
-
 	LLSliderCtrl* sldrCtrl = getChild<LLSliderCtrl>("HoverHeightSlider");
-	sldrCtrl->setValue(value,FALSE);
 	sldrCtrl->setSliderMouseUpCallback(boost::bind(&LLFloaterHoverHeight::onFinalCommit,this));
 	sldrCtrl->setSliderEditorCommitCallback(boost::bind(&LLFloaterHoverHeight::onFinalCommit,this));
 	childSetCommitCallback("HoverHeightSlider", &LLFloaterHoverHeight::onSliderMoved, NULL);
 
+	// Initialize slider from pref setting.
+	syncFromPreferenceSetting(this);
+	// Update slider on future pref changes.
+	gSavedSettings.getControl("AvatarPosFinalOffset")->getCommitSignal()->connect(boost::bind(&syncFromPreferenceSetting, this));
+
 	return TRUE;
 }
 
 // static
 void LLFloaterHoverHeight::onSliderMoved(LLUICtrl* ctrl, void* userData)
 {
+	LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
+	F32 value = sldrCtrl->getValueF32();
+	LLVector3 offset = gSavedSettings.getVector3("AvatarPosFinalOffset");
+	offset[2] = value;
+	gAgentAvatarp->mHoverOffset = offset;
 }
 
-// Do extra send-to-the-server work when slider drag completes, or new
+// Do send-to-the-server work when slider drag completes, or new
 // value entered as text.
 void LLFloaterHoverHeight::onFinalCommit()
-{
-	LL_INFOS() << "FINAL FINAL!!!" << LL_ENDL;
-	sendHoverHeightUpdate();
-}
-
-void LLFloaterHoverHeight::sendHoverHeightUpdate()
 {
 	LLSliderCtrl* sldrCtrl = getChild<LLSliderCtrl>("HoverHeightSlider");
 	F32 value = sldrCtrl->getValueF32();
+	LLVector3 offset = gSavedSettings.getVector3("AvatarPosFinalOffset");
+	offset[2] = value;
+	gSavedSettings.setVector3("AvatarPosFinalOffset",offset);
+}
 
-	std::string url = gAgent.getRegion()->getCapability("AgentPreferences");
 
-	if (!url.empty())
-	{
-		LLSD update = LLSD::emptyMap();
-		update["hover_height"] = value;
-
-		LL_INFOS() << "updating hover height to " << value << LL_ENDL;
-		LLHTTPClient::post(url, update, new LLHoverHeightResponder);
-	}
-}
diff --git a/indra/newview/llfloaterhoverheight.h b/indra/newview/llfloaterhoverheight.h
index b81f293ae58d21c9bfb00be31c3d22f59b099afa..586871374f821d6ee752d5915575894f8487f360 100755
--- a/indra/newview/llfloaterhoverheight.h
+++ b/indra/newview/llfloaterhoverheight.h
@@ -39,7 +39,7 @@ class LLFloaterHoverHeight: public LLFloater
 
 	void onFinalCommit();
 
-	void sendHoverHeightUpdate();
+	static void syncFromPreferenceSetting(void *user_data);
 };
 
 #endif
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 9da7717b74c163bc7ea762310976647715d7d12e..d5f9268a640040a7291363a76228f4e46bca1e4c 100755
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -2210,6 +2210,8 @@ bool idle_startup()
 		llassert(LLPathfindingManager::getInstance() != NULL);
 		LLPathfindingManager::getInstance()->initSystem();
 
+		gAgentAvatarp->sendHoverHeight();
+
 		return TRUE;
 	}
 
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index d150ace455ee19d02fca2c04cab678b431aec805..118ed10eb2acad830a3c96e4aa2d0115b7125034 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -3219,6 +3219,10 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
 		{
 			debug_line += llformat(" - cof rcv:%d", last_received_cof_version);
 		}
+		if (mHoverOffset[2] != 0.0)
+		{
+			debug_line += llformat(" hov_z: %f", mHoverOffset[2]);
+		}
 		addDebugText(debug_line);
 	}
 	if (gSavedSettings.getBOOL("DebugAvatarCompositeBaked"))
@@ -3589,7 +3593,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
 	else if (mDrawable.notNull())
 	{
 		LLVector3 pos = mDrawable->getPosition();
-		pos += mHoverOffset;
+		pos += mHoverOffset * mDrawable->getRotation();
 		mRoot->setPosition(pos);
 		mRoot->setRotation(mDrawable->getRotation());
 	}
@@ -7327,11 +7331,22 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 		}
 	}
 
-	if (contents.mHoverOffsetWasSet)
+	if (contents.mHoverOffsetWasSet && !isSelf())
 	{
+		// Got an update for some other avatar.
+		// (Ignore updates for self because they may be out of date.)
 		mHoverOffset = contents.mHoverOffset;
 	}
 
+	if (!contents.mHoverOffsetWasSet)
+	{
+		// If we don't get a value at all, we are presumably in a
+		// region that does not support hover height.
+// FIXME RESTORE AFTER TESTING
+		LL_WARNS() << "zeroing hover because not defined in appearance message" << LL_ENDL;
+		mHoverOffset = LLVector3(0.0, 0.0, 0.0);
+	}
+
 	setCompositeUpdatesEnabled( TRUE );
 
 	// If all of the avatars are completely baked, release the global image caches to conserve memory.
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index f4c6472f7a8cf313f99ace8e9226e5a681c881ad..a5379f24ba6573605548d8012bb70e374f203848 100755
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -127,6 +127,25 @@ struct LocalTextureData
 	LLTextureEntry *mTexEntry;
 };
 
+// TODO - this class doesn't really do anything, could just use a base
+// class responder if nothing else gets added.
+class LLHoverHeightResponder: public LLHTTPClient::Responder
+{
+public:
+	LLHoverHeightResponder(): LLHTTPClient::Responder() {}
+
+private:
+	void httpFailure()
+	{
+		LL_WARNS() << dumpResponse() << LL_ENDL;
+	}
+
+	void httpSuccess()
+	{
+		LL_INFOS() << dumpResponse() << LL_ENDL;
+	}
+};
+
 //-----------------------------------------------------------------------------
 // Callback data
 //-----------------------------------------------------------------------------
@@ -163,8 +182,6 @@ LLVOAvatarSelf::LLVOAvatarSelf(const LLUUID& id,
 {
 	mMotionController.mIsSelf = TRUE;
 
-	mHoverOffset = gSavedSettings.getVector3("AvatarPosFinalOffset");
-
 	LL_DEBUGS() << "Marking avatar as self " << id << LL_ENDL;
 }
 
@@ -222,6 +239,8 @@ void LLVOAvatarSelf::initInstance()
 		return;
 	}
 
+	mHoverOffset = gSavedSettings.getVector3("AvatarPosFinalOffset");
+
 	//doPeriodically(output_self_av_texture_diagnostics, 30.0);
 	doPeriodically(update_avatar_rez_metrics, 5.0);
 	doPeriodically(boost::bind(&LLVOAvatarSelf::checkStuckAppearance, this), 30.0);
@@ -2687,6 +2706,22 @@ bool LLVOAvatarSelf::sendAppearanceMessage(LLMessageSystem *mesgsys) const
 	return success;
 }
 
+//------------------------------------------------------------------------
+// sendHoverHeight()
+//------------------------------------------------------------------------
+void LLVOAvatarSelf::sendHoverHeight() const
+{
+	std::string url = gAgent.getRegion()->getCapability("AgentPreferences");
+
+	if (!url.empty())
+	{
+		LLSD update = LLSD::emptyMap();
+		update["hover_height"] = mHoverOffset[2];
+
+		LL_DEBUGS("Avatar") << "sending hover height value " << mHoverOffset[2] << LL_ENDL;
+		LLHTTPClient::post(url, update, new LLHoverHeightResponder);
+	}
+}
 
 //------------------------------------------------------------------------
 // needsRenderBeam()
diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h
index e03de9fa0bfc9794c0e5cf3409063663275832cc..7b932abd44c8704d2060186380a3ad1b66f53743 100755
--- a/indra/newview/llvoavatarself.h
+++ b/indra/newview/llvoavatarself.h
@@ -328,6 +328,8 @@ class LLVOAvatarSelf :
 public:
 	bool			sendAppearanceMessage(LLMessageSystem *mesgsys) const;
 
+	void			sendHoverHeight() const;
+
 /**                    Appearance
  **                                                                            **
  *******************************************************************************/