diff --git a/.hgtags b/.hgtags
index 6db0a64173d7a30414aadc3a235e0c22040d361d..e73ba6a156718c42b95157658f5d2235453ca170 100755
--- a/.hgtags
+++ b/.hgtags
@@ -498,3 +498,4 @@ bc61801f614022c920cb5c3df1d7d67a9561ce1f 3.7.22-release
 3be800e1afad9615442159e388d6d137be7b951e 3.7.23-release
 d3d0101e980ec95043e0af9b7903045d3bc447e4 3.7.24-release
 9978a8c3a2ffce4a5e1c186256581c2ac139c9dc 3.7.25-release
+000e9dda4162cbf0a83ba88558b19473654a09a9 3.7.26-release
diff --git a/indra/llcharacter/llcharacter.h b/indra/llcharacter/llcharacter.h
index d4e3b763865d211f036e38fa166237ab794e2ca6..1a3e3076634416ef83f902169949461d05542d38 100755
--- a/indra/llcharacter/llcharacter.h
+++ b/indra/llcharacter/llcharacter.h
@@ -261,6 +261,9 @@ class LLCharacter
 	static std::vector< LLCharacter* > sInstances;
 	static BOOL sAllowInstancesChange ; //debug use
 
+	virtual void	setHoverOffset(const LLVector3& hover_offset, bool send_update=true) { mHoverOffset = hover_offset; }
+	const LLVector3& getHoverOffset() const { return mHoverOffset; }
+
 protected:
 	LLMotionController	mMotionController;
 
@@ -273,7 +276,6 @@ class LLCharacter
 	U32					mSkeletonSerialNum;
 	LLAnimPauseRequest	mPauseRequest;
 
-
 private:
 	// visual parameter stuff
 	typedef std::map<S32, LLVisualParam *> 		visual_param_index_map_t;
@@ -284,6 +286,8 @@ class LLCharacter
 	visual_param_name_map_t  					mVisualParamNameMap;
 
 	static LLStringTable sVisualParamNames;	
+
+	LLVector3 mHoverOffset;
 };
 
 #endif // LL_LLCHARACTER_H
diff --git a/indra/llcharacter/lljoint.cpp b/indra/llcharacter/lljoint.cpp
index 5bee4da7c04c2e2f730317e01090fde9a58bebf6..8fa08a2a6ce0ea7314e94973661c376164ec1eec 100755
--- a/indra/llcharacter/lljoint.cpp
+++ b/indra/llcharacter/lljoint.cpp
@@ -290,7 +290,7 @@ const LLVector3& LLJoint::getPosition()
 
 bool do_debug_joint(const std::string& name)
 {
-	return true;
+	return false;
 }
 
 //--------------------------------------------------------------------
diff --git a/indra/llmessage/message_prehash.cpp b/indra/llmessage/message_prehash.cpp
index 39cfb6019e5af4cfdaf2b88e8e3a55a4401571e4..a62b9c322704fffb15bdff35910ce7eb08bba4b5 100755
--- a/indra/llmessage/message_prehash.cpp
+++ b/indra/llmessage/message_prehash.cpp
@@ -1383,3 +1383,5 @@ char const* const _PREHASH_GroupAVSounds = LLMessageStringTable::getInstance()->
 char const* const _PREHASH_AppearanceData = LLMessageStringTable::getInstance()->getString("AppearanceData");
 char const* const _PREHASH_AppearanceVersion = LLMessageStringTable::getInstance()->getString("AppearanceVersion");
 char const* const _PREHASH_CofVersion = LLMessageStringTable::getInstance()->getString("CofVersion");
+char const* const _PREHASH_AppearanceHover = LLMessageStringTable::getInstance()->getString("AppearanceHover");
+char const* const _PREHASH_HoverHeight = LLMessageStringTable::getInstance()->getString("HoverHeight");
diff --git a/indra/llmessage/message_prehash.h b/indra/llmessage/message_prehash.h
index 573e10dc0bc2dc630d5a1153693e79e2434ece7b..573c8e466f5ab3b92f0ed12615c5621a7bdbf4b9 100755
--- a/indra/llmessage/message_prehash.h
+++ b/indra/llmessage/message_prehash.h
@@ -1383,4 +1383,6 @@ extern char const* const _PREHASH_GroupAVSounds;
 extern char const* const _PREHASH_AppearanceData;
 extern char const* const _PREHASH_AppearanceVersion;
 extern char const* const _PREHASH_CofVersion;
+extern char const* const _PREHASH_AppearanceHover;
+extern char const* const _PREHASH_HoverHeight;
 #endif
diff --git a/indra/llui/llsliderctrl.cpp b/indra/llui/llsliderctrl.cpp
index 62c5ecb8f125a15d5d3776aae0dcecdcbf0ebfd7..2da39fa54b5fc417e97b2652abf43b7569e5541c 100755
--- a/indra/llui/llsliderctrl.cpp
+++ b/indra/llui/llsliderctrl.cpp
@@ -58,7 +58,8 @@ LLSliderCtrl::LLSliderCtrl(const LLSliderCtrl::Params& p)
 	mPrecision(p.decimal_digits),
 	mTextEnabledColor(p.text_color()),
 	mTextDisabledColor(p.text_disabled_color()),
-	mLabelWidth(p.label_width)
+	mLabelWidth(p.label_width),
+	mEditorCommitSignal(NULL)
 {
 	S32 top = getRect().getHeight();
 	S32 bottom = 0;
@@ -196,6 +197,11 @@ LLSliderCtrl::LLSliderCtrl(const LLSliderCtrl::Params& p)
 	updateText();
 }
 
+LLSliderCtrl::~LLSliderCtrl()
+{
+	delete mEditorCommitSignal;
+}
+
 // static
 void LLSliderCtrl::onEditorGainFocus( LLFocusableElement* caller, void *userdata )
 {
@@ -308,6 +314,8 @@ void LLSliderCtrl::onEditorCommit( LLUICtrl* ctrl, const LLSD& userdata )
 	if( success )
 	{
 		self->onCommit();
+		if (self->mEditorCommitSignal)
+			(*(self->mEditorCommitSignal))(self, self->getValueF32());
 	}
 	else
 	{
@@ -421,6 +429,11 @@ boost::signals2::connection LLSliderCtrl::setSliderMouseUpCallback( const commit
 	return mSlider->setMouseUpCallback( cb );
 }
 
+boost::signals2::connection LLSliderCtrl::setSliderEditorCommitCallback( const commit_signal_t::slot_type& cb )   
+{ 
+	if (!mEditorCommitSignal) mEditorCommitSignal = new commit_signal_t();
+	return mEditorCommitSignal->connect(cb); 
+}
 void LLSliderCtrl::onTabInto()
 {
 	if( mEditor )
diff --git a/indra/llui/llsliderctrl.h b/indra/llui/llsliderctrl.h
index 5153e33f49f11178fb4d4e507a219dbf294bc9d5..67cca9ef04efc701fbde13bcd692d0f8330938dd 100755
--- a/indra/llui/llsliderctrl.h
+++ b/indra/llui/llsliderctrl.h
@@ -81,7 +81,7 @@ class LLSliderCtrl : public LLF32UICtrl
 	LLSliderCtrl(const Params&);
 	friend class LLUICtrlFactory;
 public:
-	virtual ~LLSliderCtrl() {} // Children all cleaned up by default view destructor.
+	virtual ~LLSliderCtrl();
 
 	/*virtual*/ F32	getValueF32() const { return mSlider->getValueF32(); }
 	void			setValue(F32 v, BOOL from_event = FALSE);
@@ -112,6 +112,7 @@ class LLSliderCtrl : public LLF32UICtrl
 
 	boost::signals2::connection setSliderMouseDownCallback(	const commit_signal_t::slot_type& cb );
 	boost::signals2::connection setSliderMouseUpCallback( const commit_signal_t::slot_type& cb );
+	boost::signals2::connection setSliderEditorCommitCallback( const commit_signal_t::slot_type& cb );
 
 	/*virtual*/ void	onTabInto();
 
@@ -150,6 +151,8 @@ class LLSliderCtrl : public LLF32UICtrl
 
 	LLUIColor	mTextEnabledColor;
 	LLUIColor	mTextDisabledColor;
+
+	commit_signal_t*	mEditorCommitSignal;
 };
 
 #endif  // LL_LLSLIDERCTRL_H
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 154f3b572613d77673b2e1b1d0894173e61f1698..318e3c8688cc9b93af3ef2d548810910326f94cc 100755
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -245,6 +245,7 @@ set(viewer_SOURCE_FILES
     llfloaterhandler.cpp
     llfloaterhardwaresettings.cpp
     llfloaterhelpbrowser.cpp
+    llfloaterhoverheight.cpp
     llfloaterhud.cpp
     llfloaterimagepreview.cpp
     llfloaterimsessiontab.cpp
@@ -850,6 +851,7 @@ set(viewer_HEADER_FILES
     llfloaterhandler.h
     llfloaterhardwaresettings.h
     llfloaterhelpbrowser.h
+    llfloaterhoverheight.h
     llfloaterhud.h
     llfloaterimagepreview.h
     llfloaterimnearbychat.h
diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt
index e5403775b2455aa19f1c143120f8f15c411c312b..0bbe2c1160c93377ec7d03bc072b1ba0baf8998b 100644
--- a/indra/newview/VIEWER_VERSION.txt
+++ b/indra/newview/VIEWER_VERSION.txt
@@ -1 +1 @@
-3.7.26
+3.7.27
diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml
index 15cb5bc0ebd8f47778ca03807261ccc44c50d1eb..de3732f339c6d84cf6ad7bf84c3e246d366de09e 100755
--- a/indra/newview/app_settings/logcontrol.xml
+++ b/indra/newview/app_settings/logcontrol.xml
@@ -43,6 +43,7 @@
 					<key>tags</key>
 						<array>
 						<!-- sample entry for debugging specific items	
+						     <string>Avatar</string>
 						     <string>Inventory</string>
 						     <string>SceneLoadTiming</string>
 						     <string>Avatar</string>
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 9f3fc26c907c6f7634114f6fd460cbf6ac928b2d..2eb780ec5d711c73256cadba18b8310b67731e78 100755
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -665,6 +665,21 @@
       <key>Value</key>
       <integer>2</integer>
     </map>
+    <key>AvatarPosFinalOffset</key>
+    <map>
+      <key>Comment</key>
+      <string>After-everything-else fixup for avatar position.</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>Vector3</string>
+      <key>Value</key>
+      <array>
+        <real>0.0</real>
+        <real>0.0</real>
+        <real>0.0</real>
+      </array>
+    </map>
     <key>AvatarPickerURL</key>
     <map>
       <key>Comment</key>
diff --git a/indra/newview/app_settings/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml
index fc6f1f6395f7f0cbbdec0d4bf70c2c02967acf22..d119504017d6ae6a1dbb1a9c1f9fbcf6904492c6 100755
--- a/indra/newview/app_settings/settings_per_account.xml
+++ b/indra/newview/app_settings/settings_per_account.xml
@@ -1,5 +1,16 @@
 <llsd>
     <map>
+    <key>AvatarHoverOffsetZ</key>
+    <map>
+      <key>Comment</key>
+      <string>After-everything-else fixup for avatar Z position.</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>F32</string>
+      <key>Value</key>
+        <real>0.0</real>
+    </map>
     <key>DoNotDisturbResponseChanged</key>
         <map>
         <key>Comment</key>
diff --git a/indra/newview/llfloaterhoverheight.cpp b/indra/newview/llfloaterhoverheight.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..8908626de6a737aa7cd46ef32ed00f51b76a42ac
--- /dev/null
+++ b/indra/newview/llfloaterhoverheight.cpp
@@ -0,0 +1,157 @@
+/** 
+* @file llfloaterhoverheight.cpp
+* @brief Controller for self avatar hover height
+* @author vir@lindenlab.com
+*
+* $LicenseInfo:firstyear=2014&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2014, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+* $/LicenseInfo$
+*/
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llfloaterhoverheight.h"
+#include "llsliderctrl.h"
+#include "llviewercontrol.h"
+#include "llsdserialize.h"
+#include "llhttpclient.h"
+#include "llagent.h"
+#include "llviewerregion.h"
+#include "llvoavatarself.h"
+
+LLFloaterHoverHeight::LLFloaterHoverHeight(const LLSD& key) : LLFloater(key)
+{
+}
+
+void LLFloaterHoverHeight::syncFromPreferenceSetting(void *user_data)
+{
+	F32 value = gSavedPerAccountSettings.getF32("AvatarHoverOffsetZ");
+
+	LLFloaterHoverHeight *self = static_cast<LLFloaterHoverHeight*>(user_data);
+	LLSliderCtrl* sldrCtrl = self->getChild<LLSliderCtrl>("HoverHeightSlider");
+	sldrCtrl->setValue(value,FALSE);
+
+	if (isAgentAvatarValid())
+	{
+		LLVector3 offset(0.0, 0.0, llclamp(value,MIN_HOVER_Z,MAX_HOVER_Z));
+		LL_INFOS("Avatar") << "setting hover from preference setting " << offset[2] << LL_ENDL;
+		gAgentAvatarp->setHoverOffset(offset);
+		//gAgentAvatarp->sendHoverHeight();
+	}
+}
+
+BOOL LLFloaterHoverHeight::postBuild()
+{
+	LLSliderCtrl* sldrCtrl = getChild<LLSliderCtrl>("HoverHeightSlider");
+	sldrCtrl->setMinValue(MIN_HOVER_Z);
+	sldrCtrl->setMaxValue(MAX_HOVER_Z);
+	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.
+	if (gSavedPerAccountSettings.getControl("AvatarHoverOffsetZ"))
+	{
+		gSavedPerAccountSettings.getControl("AvatarHoverOffsetZ")->getCommitSignal()->connect(boost::bind(&syncFromPreferenceSetting, this));
+	}
+	else
+	{
+		LL_WARNS() << "Control not found for AvatarHoverOffsetZ" << LL_ENDL;
+	}
+
+	updateEditEnabled();
+
+	if (!mRegionChangedSlot.connected())
+	{
+		mRegionChangedSlot = gAgent.addRegionChangedCallback(boost::bind(&LLFloaterHoverHeight::onRegionChanged,this));
+	}
+	// Set up based on initial region.
+	onRegionChanged();
+
+	return TRUE;
+}
+
+void LLFloaterHoverHeight::onClose(bool app_quitting)
+{
+	if (mRegionChangedSlot.connected())
+	{
+		mRegionChangedSlot.disconnect();
+	}
+}
+
+// static
+void LLFloaterHoverHeight::onSliderMoved(LLUICtrl* ctrl, void* userData)
+{
+	LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
+	F32 value = sldrCtrl->getValueF32();
+	LLVector3 offset(0.0, 0.0, llclamp(value,MIN_HOVER_Z,MAX_HOVER_Z));
+	LL_INFOS("Avatar") << "setting hover from slider moved" << offset[2] << LL_ENDL;
+	gAgentAvatarp->setHoverOffset(offset, false);
+}
+
+// Do send-to-the-server work when slider drag completes, or new
+// value entered as text.
+void LLFloaterHoverHeight::onFinalCommit()
+{
+	LLSliderCtrl* sldrCtrl = getChild<LLSliderCtrl>("HoverHeightSlider");
+	F32 value = sldrCtrl->getValueF32();
+	gSavedPerAccountSettings.setF32("AvatarHoverOffsetZ",value);
+
+	LLVector3 offset(0.0, 0.0, llclamp(value,MIN_HOVER_Z,MAX_HOVER_Z));
+	LL_INFOS("Avatar") << "setting hover from slider final commit " << offset[2] << LL_ENDL;
+	gAgentAvatarp->setHoverOffset(offset, true); // will send update this time.
+}
+
+void LLFloaterHoverHeight::onRegionChanged()
+{
+	LLViewerRegion *region = gAgent.getRegion();
+	if (region && region->simulatorFeaturesReceived())
+	{
+		updateEditEnabled();
+	}
+	else if (region)
+	{
+		region->setSimulatorFeaturesReceivedCallback(boost::bind(&LLFloaterHoverHeight::onSimulatorFeaturesReceived,this,_1));
+	}
+}
+
+void LLFloaterHoverHeight::onSimulatorFeaturesReceived(const LLUUID &region_id)
+{
+	LLViewerRegion *region = gAgent.getRegion();
+	if (region && (region->getRegionID()==region_id))
+	{
+		updateEditEnabled();
+	}
+}
+
+void LLFloaterHoverHeight::updateEditEnabled()
+{
+	bool enabled = gAgent.getRegion() && gAgent.getRegion()->avatarHoverHeightEnabled();
+	LLSliderCtrl* sldrCtrl = getChild<LLSliderCtrl>("HoverHeightSlider");
+	sldrCtrl->setEnabled(enabled);
+	if (enabled)
+	{
+		syncFromPreferenceSetting(this);
+	}
+}
+
+
diff --git a/indra/newview/llfloaterhoverheight.h b/indra/newview/llfloaterhoverheight.h
new file mode 100755
index 0000000000000000000000000000000000000000..ee065bc184a18c7d9749bea8959b0909a07d2e17
--- /dev/null
+++ b/indra/newview/llfloaterhoverheight.h
@@ -0,0 +1,52 @@
+/** 
+* @file   llfloaterhoverheight.h
+* @brief  Controller for self avatar hover height.
+* @author vir@lindenlab.com
+*
+* $LicenseInfo:firstyear=2014&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2014, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+* $/LicenseInfo$
+*/
+#ifndef LL_LLFLOATERHOVERHEIGHT_H
+#define LL_LLFLOATERHOVERHEIGHT_H
+
+#include "llfloater.h"
+
+class LLFloaterHoverHeight: public LLFloater
+{
+public:
+	LLFloaterHoverHeight(const LLSD& key);
+	BOOL postBuild();
+
+	static void onSliderMoved(LLUICtrl* ctrl, void* userData);
+
+	void onFinalCommit();
+
+	static void syncFromPreferenceSetting(void *user_data);
+
+	void onRegionChanged();
+	void onSimulatorFeaturesReceived(const LLUUID &region_id);
+	void updateEditEnabled();
+
+	/*virtual*/ void onClose(bool app_quitting);
+	boost::signals2::connection mRegionChangedSlot;
+};
+
+#endif
diff --git a/indra/newview/llfloaterperms.cpp b/indra/newview/llfloaterperms.cpp
index 0880a5f35af5dc2a3693d13b821092c8f7e3975f..849aa7cd14cd3cc9ef35f2ee1fd8ea4a5eda9dab 100755
--- a/indra/newview/llfloaterperms.cpp
+++ b/indra/newview/llfloaterperms.cpp
@@ -35,6 +35,8 @@
 #include "llagent.h"
 #include "llviewerregion.h"
 #include "llnotificationsutil.h"
+#include "llsdserialize.h"
+#include "llvoavatar.h"
 
 LLFloaterPerms::LLFloaterPerms(const LLSD& seed)
 : LLFloater(seed)
@@ -171,8 +173,9 @@ class LLFloaterPermsResponder : public LLHTTPClient::Responder
 private:
 	static	std::string sPreviousReason;
 
-	void error(U32 status, const std::string& reason)
+	void httpFailure()
 	{
+		const std::string& reason = getReason();
 		// Do not display the same error more than once in a row
 		if (reason != sPreviousReason)
 		{
@@ -182,8 +185,12 @@ class LLFloaterPermsResponder : public LLHTTPClient::Responder
 			LLNotificationsUtil::add("DefaultObjectPermissions", args);
 		}
 	}
-	void result(const LLSD& content)
+
+	void httpSuccess()
 	{
+		//const LLSD& content = getContent();
+		//dump_sequential_xml("perms_responder_result.xml", content);
+
 		// Since we have had a successful POST call be sure to display the next error message
 		// even if it is the same as a previous one.
 		sPreviousReason = "";
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 319d220b5106d7e9b463e9e1abd7cd06d3a5d223..42fc3001877d6456f9c527403bbedce6550e7fbb 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/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index e19fe9ca754ca5859de3890077962894ad67d403..fc18b20758f80e981a62ab93382378533e198c86 100755
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -70,6 +70,7 @@
 #include "llfloatergroups.h"
 #include "llfloaterhardwaresettings.h"
 #include "llfloaterhelpbrowser.h"
+#include "llfloaterhoverheight.h"
 #include "llfloaterhud.h"
 #include "llfloaterimagepreview.h"
 #include "llfloaterimsession.h"
@@ -221,7 +222,8 @@ void LLViewerFloaterReg::registerFloaters()
 	LLFloaterReg::add("god_tools", "floater_god_tools.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterGodTools>);
 	LLFloaterReg::add("group_picker", "floater_choose_group.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterGroupPicker>);
 
-	LLFloaterReg::add("help_browser", "floater_help_browser.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHelpBrowser>);	
+	LLFloaterReg::add("help_browser", "floater_help_browser.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHelpBrowser>);
+	LLFloaterReg::add("edit_hover_height", "floater_edit_hover_height.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHoverHeight>);
 	LLFloaterReg::add("hud", "floater_hud.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHUD>);
 
 	LLFloaterReg::add("impanel", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterIMSession>);
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index b77d3ca1be2706ec14b3b3b1389e328420f29381..3b0adcf7f4cdb4af4c8ed31ad5de94d1504e3092 100755
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -3890,6 +3890,14 @@ class LLEnableEditShape : public view_listener_t
 	}
 };
 
+class LLEnableHoverHeight : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		return gAgent.getRegion() && gAgent.getRegion()->avatarHoverHeightEnabled();
+	}
+};
+
 class LLEnableEditPhysics : public view_listener_t
 {
 	bool handleEvent(const LLSD& userdata)
@@ -6087,6 +6095,11 @@ void handle_edit_shape()
 	LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "edit_shape"));
 }
 
+void handle_hover_height()
+{
+	LLFloaterReg::showInstance("edit_hover_height");
+}
+
 void handle_edit_physics()
 {
 	LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "edit_physics"));
@@ -8583,10 +8596,12 @@ void initialize_menus()
 	view_listener_t::addMenu(new LLEditEnableTakeOff(), "Edit.EnableTakeOff");
 	view_listener_t::addMenu(new LLEditEnableCustomizeAvatar(), "Edit.EnableCustomizeAvatar");
 	view_listener_t::addMenu(new LLEnableEditShape(), "Edit.EnableEditShape");
+	view_listener_t::addMenu(new LLEnableHoverHeight(), "Edit.EnableHoverHeight");
 	view_listener_t::addMenu(new LLEnableEditPhysics(), "Edit.EnableEditPhysics");
 	commit.add("CustomizeAvatar", boost::bind(&handle_customize_avatar));
 	commit.add("EditOutfit", boost::bind(&handle_edit_outfit));
 	commit.add("EditShape", boost::bind(&handle_edit_shape));
+	commit.add("HoverHeight", boost::bind(&handle_hover_height));
 	commit.add("EditPhysics", boost::bind(&handle_edit_physics));
 
 	// View menu
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index 7d82ecf565cc3bc488c747b9426694783cbe1755..7ebe12cc074c82d69fa6e2b1e5a1d6b059c25a6c 100755
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -425,6 +425,7 @@ LLViewerRegion::LLViewerRegion(const U64 &handle,
 	mCacheDirty(FALSE),
 	mReleaseNotesRequested(FALSE),
 	mCapabilitiesReceived(false),
+	mSimulatorFeaturesReceived(false),
 	mBitsReceived(0.f),
 	mPacketsReceived(0.f),
 	mDead(FALSE),
@@ -2039,6 +2040,26 @@ void LLViewerRegion::getInfo(LLSD& info)
 	info["Region"]["Handle"]["y"] = (LLSD::Integer)y;
 }
 
+boost::signals2::connection LLViewerRegion::setSimulatorFeaturesReceivedCallback(const caps_received_signal_t::slot_type& cb)
+{
+	return mSimulatorFeaturesReceivedSignal.connect(cb);
+}
+
+void LLViewerRegion::setSimulatorFeaturesReceived(bool received)
+{
+	mSimulatorFeaturesReceived = received;
+	if (received)
+	{
+		mSimulatorFeaturesReceivedSignal(getRegionID());
+		mSimulatorFeaturesReceivedSignal.disconnect_all_slots();
+	}
+}
+
+bool LLViewerRegion::simulatorFeaturesReceived() const
+{
+	return mSimulatorFeaturesReceived;
+}
+
 void LLViewerRegion::getSimulatorFeatures(LLSD& sim_features) const
 {
 	sim_features = mSimulatorFeatures;
@@ -2052,6 +2073,9 @@ void LLViewerRegion::setSimulatorFeatures(const LLSD& sim_features)
 	LLSDSerialize::toPrettyXML(sim_features, str);
 	LL_INFOS() << str.str() << LL_ENDL;
 	mSimulatorFeatures = sim_features;
+
+	setSimulatorFeaturesReceived(true);
+	
 }
 
 //this is called when the parent is not cacheable.
@@ -3100,6 +3124,12 @@ bool LLViewerRegion::dynamicPathfindingEnabled() const
 	return ( mSimulatorFeatures.has("DynamicPathfindingEnabled") &&
 			 mSimulatorFeatures["DynamicPathfindingEnabled"].asBoolean());
 }
+
+bool LLViewerRegion::avatarHoverHeightEnabled() const
+{
+	return ( mSimulatorFeatures.has("AvatarHoverHeightEnabled") &&
+			 mSimulatorFeatures["AvatarHoverHeightEnabled"].asBoolean());
+}
 /* Static Functions */
 
 void log_capabilities(const CapabilityMap &capmap)
diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h
index d01e7469368820cc7a673d7fa2aa196bbc45b82f..c14fa5aee805c62bf9322237b428a49de8711a97 100755
--- a/indra/newview/llviewerregion.h
+++ b/indra/newview/llviewerregion.h
@@ -309,12 +309,19 @@ class LLViewerRegion: public LLCapabilityProvider // implements this interface
 	bool meshRezEnabled() const;
 	bool meshUploadEnabled() const;
 
+	// has region received its simulator features list? Requires an additional query after caps received.
+	void setSimulatorFeaturesReceived(bool);
+	bool simulatorFeaturesReceived() const;
+	boost::signals2::connection setSimulatorFeaturesReceivedCallback(const caps_received_signal_t::slot_type& cb);
+	
 	void getSimulatorFeatures(LLSD& info) const;	
 	void setSimulatorFeatures(const LLSD& info);
 
 	
 	bool dynamicPathfindingEnabled() const;
 
+	bool avatarHoverHeightEnabled() const;
+
 	typedef enum
 	{
 		CACHE_MISS_TYPE_FULL = 0,
@@ -512,6 +519,7 @@ class LLViewerRegion: public LLCapabilityProvider // implements this interface
 	BOOL                                    mCacheDirty;
 	BOOL	mAlive;					// can become false if circuit disconnects
 	BOOL	mCapabilitiesReceived;
+	BOOL	mSimulatorFeaturesReceived;
 	BOOL    mReleaseNotesRequested;
 	BOOL    mDead;  //if true, this region is in the process of deleting.
 	BOOL    mPaused; //pause processing the objects in the region
@@ -532,11 +540,13 @@ class LLViewerRegion: public LLCapabilityProvider // implements this interface
 	CacheMissItem::cache_miss_list_t   mCacheMissList;
 	
 	caps_received_signal_t mCapabilitiesReceivedSignal;		
+	caps_received_signal_t mSimulatorFeaturesReceivedSignal;		
+
 	LLSD mSimulatorFeatures;
 
 	// the materials capability throttle
 	LLFrameTimer mMaterialsCapThrottleTimer;
-LLFrameTimer	mRenderInfoRequestTimer;
+	LLFrameTimer mRenderInfoRequestTimer;
 };
 
 inline BOOL LLViewerRegion::getRegionProtocol(U64 protocol) const
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 7292af99a43e01dbbee366b6c5e2c62ca25ffa7e..75b81cdeedd55cd41e09731523efddc2bd207984 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -111,6 +111,9 @@ extern F32 ANIM_SPEED_MAX;
 extern F32 ANIM_SPEED_MIN;
 extern U32 JOINT_COUNT_REQUIRED_FOR_FULLRIG;
 
+const F32 MAX_HOVER_Z = 2.0;
+const F32 MIN_HOVER_Z = -2.0;
+
 // #define OUTPUT_BREAST_DATA
 
 using namespace LLAvatarAppearanceDefines;
@@ -252,6 +255,8 @@ struct LLAppearanceMessageContents
 	//U32 appearance_flags = 0;
 	std::vector<F32> mParamWeights;
 	std::vector<LLVisualParam*> mParams;
+	LLVector3 mHoverOffset;
+	bool mHoverOffsetWasSet;
 };
 
 struct LLVOAvatarChildJoint : public LLInitParam::ChoiceBlock<LLVOAvatarChildJoint>
@@ -721,7 +726,8 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
 	mCachedInMuteList(false)
 {
 	//VTResume();  // VTune
-	
+	setHoverOffset(LLVector3(0.0, 0.0, 0.0));
+
 	// mVoiceVisualizer is created by the hud effects manager and uses the HUD Effects pipeline
 	const BOOL needsSendToSim = false; // currently, this HUD effect doesn't need to pack and unpack data to do its job
 	mVoiceVisualizer = ( LLVoiceVisualizer *)LLHUDManager::getInstance()->createViewerEffect( LLHUDObject::LL_HUD_EFFECT_VOICE_VISUALIZER, needsSendToSim );
@@ -774,6 +780,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
 	mRuthTimer.reset();
 	mRuthDebugTimer.reset();
 	mDebugExistenceTimer.reset();
+	mLastAppearanceMessageTimer.reset();
 
     if(LLSceneMonitor::getInstance()->isEnabled())
 	{
@@ -1957,6 +1964,11 @@ U32 LLVOAvatar::processUpdateMessage(LLMessageSystem *mesgsys,
 	// Do base class updates...
 	U32 retval = LLViewerObject::processUpdateMessage(mesgsys, user_data, block_num, update_type, dp);
 
+	//LLTEContents tec;
+	//S32 te_retval = parseTEMessage(mesgsys, _PREHASH_ObjectData, block_num, tec);
+
+	LL_DEBUGS("Avatar") << avString() << update_type << LL_ENDL; 
+
 	// Print out arrival information once we have name of avatar.
 		if (has_name && getNVPair("FirstName"))
 		{
@@ -3185,12 +3197,8 @@ bool LLVOAvatar::isInMuteList()
 	return muted;
 }
 
-//------------------------------------------------------------------------
-// updateCharacter()
-// called on both your avatar and other avatars
-//------------------------------------------------------------------------
-BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
-{	
+void LLVOAvatar::updateDebugText()
+{
 	// clear debug text
 	mDebugText.clear();
 
@@ -3227,6 +3235,22 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
 			debug_line += llformat(" - cof rcv:%d", last_received_cof_version);
 		}
 		debug_line += llformat(" bsz-z: %f avofs-z: %f", mBodySize[2], mAvatarOffset[2]);
+		bool hover_enabled = getRegion() && getRegion()->avatarHoverHeightEnabled();
+		debug_line += hover_enabled ? " H" : " h";
+		const LLVector3& hover_offset = getHoverOffset();
+		if (hover_offset[2] != 0.0)
+		{
+			debug_line += llformat(" hov_z: %f", hover_offset[2]);
+			debug_line += llformat(" %s", (mIsSitting ? "S" : "T"));
+			debug_line += llformat("%s", (isMotionActive(ANIM_AGENT_SIT_GROUND_CONSTRAINED) ? "G" : "-"));
+		}
+		F32 elapsed = mLastAppearanceMessageTimer.getElapsedTimeF32();
+		static const char *elapsed_chars = "Xx*...";
+		U32 bucket = U32(elapsed*2);
+		if (bucket < strlen(elapsed_chars))
+		{
+			debug_line += llformat(" %c", elapsed_chars[bucket]);
+		}
 		addDebugText(debug_line);
 	}
 	if (gSavedSettings.getBOOL("DebugAvatarCompositeBaked"))
@@ -3234,7 +3258,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
 		if (!mBakedTextureDebugText.empty())
 			addDebugText(mBakedTextureDebugText);
 	}
-				 
+
 	if (LLVOAvatar::sShowAnimationDebug)
 	{
 		for (LLMotionController::motion_list_t::iterator iter = mMotionController.getActiveMotions().begin();
@@ -3263,6 +3287,27 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
 		}
 	}
 
+	if (!mDebugText.size() && mText.notNull())
+	{
+		mText->markDead();
+		mText = NULL;
+	}
+	else if (mDebugText.size())
+	{
+		setDebugText(mDebugText);
+	}
+	mDebugText.clear();
+
+}
+
+//------------------------------------------------------------------------
+// updateCharacter()
+// called on both your avatar and other avatars
+//------------------------------------------------------------------------
+BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
+{	
+	updateDebugText();
+	
 	if (!mIsBuilt)
 	{
 		return FALSE;
@@ -3371,9 +3416,15 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
 	LLVector3 xyVel = getVelocity();
 	xyVel.mV[VZ] = 0.0f;
 	speed = xyVel.length();
-
+	// remembering the value here prevents a display glitch if the
+	// animation gets toggled during this update.
+	bool was_sit_ground_constrained = isMotionActive(ANIM_AGENT_SIT_GROUND_CONSTRAINED);
+	
 	if (!(mIsSitting && getParent()))
 	{
+		// This case includes all configurations except sitting on an
+		// object, so does include ground sit.
+
 		//--------------------------------------------------------------------
 		// get timing info
 		// handle initial condition case
@@ -3427,9 +3478,14 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
 		// correct for the fact that the pelvis is not necessarily the center 
 		// of the agent's physical representation
 		root_pos.mdV[VZ] -= (0.5f * mBodySize.mV[VZ]) - mPelvisToFoot;
+		if (!mIsSitting && !was_sit_ground_constrained)
+		{
+			root_pos += LLVector3d(getHoverOffset());
+		}
 		
 		LLVector3 newPosition = gAgent.getPosAgentFromGlobal(root_pos);
 
+
 		if (newPosition != mRoot->getXform()->getWorldPosition())
 		{		
 			mRoot->touch();
@@ -3594,7 +3650,9 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
 	}
 	else if (mDrawable.notNull())
 	{
-		mRoot->setPosition(mDrawable->getPosition());
+		LLVector3 pos = mDrawable->getPosition();
+		pos += getHoverOffset() * mDrawable->getRotation();
+		mRoot->setPosition(pos);
 		mRoot->setRotation(mDrawable->getRotation());
 	}
 	
@@ -3613,7 +3671,21 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
 	{
 		updateMotions(LLCharacter::NORMAL_UPDATE);
 	}
-	
+
+	// Special handling for sitting on ground.
+	if (!getParent() && (mIsSitting || was_sit_ground_constrained))
+	{
+		
+		F32 off_z = LLVector3d(getHoverOffset()).mdV[VZ];
+		if (off_z != 0.0)
+		{
+			LLVector3 pos = mRoot->getWorldPosition();
+			pos.mV[VZ] += off_z;
+			mRoot->touch();
+			mRoot->setWorldPosition(pos);
+		}
+	}
+
 	// update head position
 	updateHeadOffset();
 
@@ -3697,17 +3769,6 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
 
 	mRoot->updateWorldMatrixChildren();
 
-	if (!mDebugText.size() && mText.notNull())
-	{
-		mText->markDead();
-		mText = NULL;
-	}
-	else if (mDebugText.size())
-	{
-		setDebugText(mDebugText);
-	}
-	mDebugText.clear();
-
 	//mesh vertices need to be reskinned
 	mNeedsSkin = TRUE;
 	return TRUE;
@@ -7145,6 +7206,17 @@ void LLVOAvatar::parseAppearanceMessage(LLMessageSystem* mesgsys, LLAppearanceMe
 		// For future use:
 		//mesgsys->getU32Fast(_PREHASH_AppearanceData, _PREHASH_Flags, appearance_flags, 0);
 	}
+
+	// Parse the AppearanceData field, if any.
+	contents.mHoverOffsetWasSet = false;
+	if (mesgsys->has(_PREHASH_AppearanceHover))
+	{
+		LLVector3 hover;
+		mesgsys->getVector3Fast(_PREHASH_AppearanceHover, _PREHASH_HoverHeight, hover);
+		LL_DEBUGS("Avatar") << avString() << " hover received " << hover.mV[ VX ] << "," << hover.mV[ VY ] << "," << hover.mV[ VZ ] << LL_ENDL;
+		contents.mHoverOffset = hover;
+		contents.mHoverOffsetWasSet = true;
+	}
 	
 	// Parse visual params, if any.
 	S32 num_blocks = mesgsys->getNumberOfBlocksFast(_PREHASH_VisualParam);
@@ -7262,6 +7334,8 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 		return;
 	}
 
+	mLastAppearanceMessageTimer.reset();
+
 	ESex old_sex = getSex();
 
 	LLAppearanceMessageContents contents;
@@ -7446,6 +7520,22 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 		}
 	}
 
+	if (contents.mHoverOffsetWasSet && !isSelf())
+	{
+		// Got an update for some other avatar
+		// Ignore updates for self, because we have a more authoritative value in the preferences.
+		setHoverOffset(contents.mHoverOffset);
+		LL_INFOS("Avatar") << avString() << "setting hover from message" << contents.mHoverOffset[2] << LL_ENDL;
+	}
+
+	if (!contents.mHoverOffsetWasSet && !isSelf())
+	{
+		// If we don't get a value at all, we are presumably in a
+		// region that does not support hover height.
+		LL_WARNS() << avString() << "zeroing hover because not defined in appearance message" << LL_ENDL;
+		setHoverOffset(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/llvoavatar.h b/indra/newview/llvoavatar.h
index 7034f8349f2e8a1d562df96f26c118c18be9865e..1c3f4f2aa71272bc32c7d796d692e02aff1d0c04 100755
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -214,7 +214,6 @@ class LLVOAvatar :
 	/*virtual*/ LLVector3		getPosAgentFromGlobal(const LLVector3d &position);
 	virtual void				updateVisualParams();
 
-
 /**                    Inherited
  **                                                                            **
  *******************************************************************************/
@@ -234,6 +233,7 @@ class LLVOAvatar :
 	// Updates
 	//--------------------------------------------------------------------
 public:
+	void			updateDebugText();
 	virtual BOOL 	updateCharacter(LLAgent &agent);
 	void 			idleUpdateVoiceVisualizer(bool voice_enabled);
 	void 			idleUpdateMisc(bool detailed_update);
@@ -992,6 +992,7 @@ class LLVOAvatar :
 protected:
 	LLFrameTimer	mRuthDebugTimer; // For tracking how long it takes for av to rez
 	LLFrameTimer	mDebugExistenceTimer; // Debugging for how long the avatar has been in memory.
+	LLFrameTimer	mLastAppearanceMessageTimer; // Time since last appearance message received.
 
 	//--------------------------------------------------------------------
 	// COF monitoring
@@ -1024,6 +1025,9 @@ class LLVOAvatar :
 extern const F32 SELF_ADDITIONAL_PRI;
 extern const S32 MAX_TEXTURE_VIRTUAL_SIZE_RESET_INTERVAL;
 
+extern const F32 MAX_HOVER_Z;
+extern const F32 MIN_HOVER_Z;
+
 std::string get_sequential_numbered_file_name(const std::string& prefix,
 											  const std::string& suffix);
 void dump_sequential_xml(const std::string outprefix, const LLSD& content);
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index 3f3cd25f956695f7f8ded1d97c5b8b1fd38369a0..ae7a233876beaed665db35f33d16f8cea60277c3 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
 //-----------------------------------------------------------------------------
@@ -159,7 +178,10 @@ LLVOAvatarSelf::LLVOAvatarSelf(const LLUUID& id,
 	mScreenp(NULL),
 	mLastRegionHandle(0),
 	mRegionCrossingCount(0),
-	mInitialBakesLoaded(false)
+	mInitialBakesLoaded(false),
+	// Value outside legal range, so will always be a mismatch the
+	// first time through.
+	mLastHoverOffsetSent(LLVector3(0.0f, 0.0f, -999.0f))
 {
 	mMotionController.mIsSelf = TRUE;
 
@@ -220,11 +242,40 @@ void LLVOAvatarSelf::initInstance()
 		return;
 	}
 
+	setHoverIfRegionEnabled();
+
 	//doPeriodically(output_self_av_texture_diagnostics, 30.0);
 	doPeriodically(update_avatar_rez_metrics, 5.0);
 	doPeriodically(boost::bind(&LLVOAvatarSelf::checkStuckAppearance, this), 30.0);
 }
 
+void LLVOAvatarSelf::setHoverIfRegionEnabled()
+{
+	if (getRegion() && getRegion()->simulatorFeaturesReceived())
+	{
+		if (getRegion()->avatarHoverHeightEnabled())
+		{
+			F32 hover_z = gSavedPerAccountSettings.getF32("AvatarHoverOffsetZ");
+			setHoverOffset(LLVector3(0.0, 0.0, llclamp(hover_z,MIN_HOVER_Z,MAX_HOVER_Z)));
+			LL_INFOS("Avatar") << avString() << " set hover height from debug setting " << hover_z << LL_ENDL;
+		}
+		else 
+		{
+			setHoverOffset(LLVector3(0.0, 0.0, 0.0));
+			LL_INFOS("Avatar") << avString() << " zeroing hover height, region does not support" << LL_ENDL;
+		}
+	}
+	else
+	{
+		LL_INFOS("Avatar") << avString() << " region or simulator features not known, no change on hover" << LL_ENDL;
+		if (getRegion())
+		{
+			getRegion()->setSimulatorFeaturesReceivedCallback(boost::bind(&LLVOAvatarSelf::onSimulatorFeaturesReceived,this,_1));
+		}
+
+	}
+}
+
 bool LLVOAvatarSelf::checkStuckAppearance()
 {
 	const F32 CONDITIONAL_UNSTICK_INTERVAL = 300.0;
@@ -835,6 +886,12 @@ void LLVOAvatarSelf::removeMissingBakedTextures()
 	}
 }
 
+void LLVOAvatarSelf::onSimulatorFeaturesReceived(const LLUUID& region_id)
+{
+	LL_INFOS("Avatar") << "simulator features received, setting hover based on region props" << LL_ENDL;
+	setHoverIfRegionEnabled();
+}
+
 //virtual
 void LLVOAvatarSelf::updateRegion(LLViewerRegion *regionp)
 {
@@ -853,6 +910,17 @@ void LLVOAvatarSelf::updateRegion(LLViewerRegion *regionp)
 		//LL_INFOS() << "pos_from_old_region is " << global_pos_from_old_region
 		//	<< " while pos_from_new_region is " << pos_from_new_region
 		//	<< LL_ENDL;
+
+		// Update hover height, or schedule callback, based on whether
+		// it's supported in this region.
+		if (regionp->simulatorFeaturesReceived())
+		{
+			setHoverIfRegionEnabled();
+		}
+		else
+		{
+			regionp->setSimulatorFeaturesReceivedCallback(boost::bind(&LLVOAvatarSelf::onSimulatorFeaturesReceived,this,_1));
+		}
 	}
 
 	if (!regionp || (regionp->getHandle() != mLastRegionHandle))
@@ -2709,6 +2777,39 @@ 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();
+		const LLVector3& hover_offset = getHoverOffset();
+		update["hover_height"] = hover_offset[2];
+
+		LL_DEBUGS("Avatar") << avString() << "sending hover height value " << hover_offset[2] << LL_ENDL;
+		LLHTTPClient::post(url, update, new LLHoverHeightResponder);
+
+		mLastHoverOffsetSent = hover_offset;
+	}
+}
+
+void LLVOAvatarSelf::setHoverOffset(const LLVector3& hover_offset, bool send_update)
+{
+	if (getHoverOffset() != hover_offset)
+	{
+		LL_INFOS("Avatar") << avString() << " setting hover due to change " << hover_offset[2] << LL_ENDL;
+		LLVOAvatar::setHoverOffset(hover_offset, send_update);
+	}
+	if (send_update && (hover_offset != mLastHoverOffsetSent))
+	{
+		LL_INFOS("Avatar") << avString() << " sending hover due to change " << hover_offset[2] << LL_ENDL;
+		sendHoverHeight();
+	}
+}
 
 //------------------------------------------------------------------------
 // needsRenderBeam()
diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h
index 5f36872575cf63fe1d5e2ea90561b0d1f9142ab3..b8e9bbb77a42dd4dacd9bc674ee89fab9d1f26d9 100755
--- a/indra/newview/llvoavatarself.h
+++ b/indra/newview/llvoavatarself.h
@@ -75,6 +75,9 @@ class LLVOAvatarSelf :
 	// LLViewerObject interface and related
 	//--------------------------------------------------------------------
 public:
+	boost::signals2::connection                   mRegionChangedSlot;
+
+	void					onSimulatorFeaturesReceived(const LLUUID& region_id);
 	/*virtual*/ void 		updateRegion(LLViewerRegion *regionp);
 	/*virtual*/ void   	 	idleUpdate(LLAgent &agent, const F64 &time);
 
@@ -328,6 +331,14 @@ class LLVOAvatarSelf :
 public:
 	bool			sendAppearanceMessage(LLMessageSystem *mesgsys) const;
 
+	// -- care and feeding of hover height.
+	void 			setHoverIfRegionEnabled();
+	void			sendHoverHeight() const;
+	/*virtual*/ void setHoverOffset(const LLVector3& hover_offset, bool send_update=true);
+
+private:
+	mutable LLVector3 mLastHoverOffsetSent;
+
 /**                    Appearance
  **                                                                            **
  *******************************************************************************/
diff --git a/indra/newview/skins/default/xui/en/floater_edit_hover_height.xml b/indra/newview/skins/default/xui/en/floater_edit_hover_height.xml
new file mode 100755
index 0000000000000000000000000000000000000000..8ec6735a015ee246b15a8ddda1fecec14f7bcc32
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_edit_hover_height.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ positioning="cascading"
+ ignore_ui_scale="false"
+ legacy_header_height="225"
+ can_minimize="true"
+ can_close="true"
+ can_resize="true"
+ min_height="65"
+ min_width="515"
+ height="65"
+ layout="topleft"
+ name="HoverHeight"
+ single_instance="true"
+ help_topic="hover_height"
+ save_rect="true"
+ save_visibility="true"
+ title="SET HOVER HEIGHT"
+ width="515">
+      <slider
+     enabled="false"
+     control_name="HoverHeightSlider"
+     decimal_digits="3"
+     follows="top|left"
+     height="15"
+     increment="0.001"
+     initial_value="0.0"
+     label="Height"
+     label_width="60"
+     left="10"
+     width="501"
+     layout="topleft"
+     name="HoverHeightSlider"
+     top="35"
+     can_edit_text="true"
+     >
+    </slider>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/menu_attachment_self.xml b/indra/newview/skins/default/xui/en/menu_attachment_self.xml
index bcbc8d5b86c7df1ba7d93c0e69ee85e92b55769e..c6ae844d676dc6385f8181134975fd69f924cce0 100755
--- a/indra/newview/skins/default/xui/en/menu_attachment_self.xml
+++ b/indra/newview/skins/default/xui/en/menu_attachment_self.xml
@@ -91,6 +91,14 @@ name="Edit Outfit">
     <menu_item_call.on_enable
      function="Edit.EnableEditShape" />
   </menu_item_call>
+  <menu_item_call label="Hover Height"
+     layout="topleft"
+     name="Hover Height">
+     <menu_item_call.on_click
+      function="HoverHeight" />
+     <menu_item_call.on_enable
+      function="Edit.EnableHoverHeight" />
+  </menu_item_call>
   <menu_item_call
     label="My Friends"
     layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/menu_avatar_self.xml b/indra/newview/skins/default/xui/en/menu_avatar_self.xml
index ca0c9bd5e4947d8235235fc6b7c65364df09edae..d3b0b07f700f461fc7c55619de2443b61a9bcfb9 100755
--- a/indra/newview/skins/default/xui/en/menu_avatar_self.xml
+++ b/indra/newview/skins/default/xui/en/menu_avatar_self.xml
@@ -229,6 +229,14 @@
        <menu_item_call.on_enable
         function="Edit.EnableEditShape" />
    </menu_item_call>
+   <menu_item_call label="Hover Height"
+     layout="topleft"
+     name="Hover Height">
+     <menu_item_call.on_click
+      function="HoverHeight" />
+     <menu_item_call.on_enable
+      function="Edit.EnableHoverHeight" />
+   </menu_item_call>
    <menu_item_call
      label="My Friends"
      layout="topleft"
diff --git a/scripts/messages/message_template.msg b/scripts/messages/message_template.msg
index 6702de9b4a7a98eea4dbb7d2ddea0b8c1a6574e7..3cec4ada1c3dd9c1dcbd178fe09a753673eca05b 100755
--- a/scripts/messages/message_template.msg
+++ b/scripts/messages/message_template.msg
@@ -3594,6 +3594,10 @@ version 2.0
 		{	CofVersion			S32	}
 		{	Flags				U32	}
 	}
+	{
+		AppearanceHover		Variable
+		{	HoverHeight	LLVector3	}
+	}
 }
 
 // AvatarSitResponse - response to a request to sit on an object
diff --git a/scripts/messages/message_template.msg.sha1 b/scripts/messages/message_template.msg.sha1
index 7a31177f118ecd39a32866c51b3664e62e8affe6..e699efb03c588f0713f4121b73f674581468ef36 100755
--- a/scripts/messages/message_template.msg.sha1
+++ b/scripts/messages/message_template.msg.sha1
@@ -1 +1 @@
-4dbf88396c3188ad4c54c4f847a7d8817793668d
\ No newline at end of file
+2286adc795b1b06eb86fdda431a71a6f0874b4f1
\ No newline at end of file