From 36afcdf55b8f974b6d913afdf60d756f4c4bf70c Mon Sep 17 00:00:00 2001
From: Kitty Barnett <develop@catznip.com>
Date: Tue, 6 Apr 2021 19:23:25 +0200
Subject: [PATCH] Refactor @sit=force to support @sitground=force as a synonym 
  * Permission check changed from hasBehaviour to hasBehaviourExcept
 (consistency with @sit and @unsit)   * Added stand up/ground sit behaviour to
 mimick RLV behaviour

---
 indra/newview/rlvactions.cpp |  6 ++++++
 indra/newview/rlvactions.h   |  1 +
 indra/newview/rlvdefines.h   |  1 +
 indra/newview/rlvhandler.cpp | 33 +++++++++++++++++++++++++++++----
 indra/newview/rlvhandler.h   |  1 +
 indra/newview/rlvhelper.cpp  |  1 +
 6 files changed, 39 insertions(+), 4 deletions(-)

diff --git a/indra/newview/rlvactions.cpp b/indra/newview/rlvactions.cpp
index 0a2c8b5b587..ee8ca58e821 100644
--- a/indra/newview/rlvactions.cpp
+++ b/indra/newview/rlvactions.cpp
@@ -464,6 +464,12 @@ bool RlvActions::canGroundSit()
 	return (!hasBehaviour(RLV_BHVR_SIT)) && (canStand());
 }
 
+bool RlvActions::canGroundSit(const LLUUID& idRlvObjExcept)
+{
+	// See canGroundSit() but disregard any restrictions held by the issuing object
+	return (!gRlvHandler.hasBehaviourExcept(RLV_BHVR_SIT, idRlvObjExcept)) && (canStand(idRlvObjExcept));
+}
+
 bool RlvActions::canSit(const LLViewerObject* pObj, const LLVector3& posOffset /*=LLVector3::zero*/)
 {
 	// User can sit on the specified object if:
diff --git a/indra/newview/rlvactions.h b/indra/newview/rlvactions.h
index 889da1e6458..69d499280c0 100644
--- a/indra/newview/rlvactions.h
+++ b/indra/newview/rlvactions.h
@@ -254,6 +254,7 @@ class RlvActions
 	 * Returns true if the user can sit on the ground
 	 */
 	static bool canGroundSit();
+	static bool canGroundSit(const LLUUID& idRlvObjExcept);
 
 	/*
 	 * Returns true if the user can interact with the specified object (with an optional relative offset)
diff --git a/indra/newview/rlvdefines.h b/indra/newview/rlvdefines.h
index 13631811d23..a9b55b55232 100644
--- a/indra/newview/rlvdefines.h
+++ b/indra/newview/rlvdefines.h
@@ -176,6 +176,7 @@ enum ERlvBehaviour {
 	RLV_BHVR_SETGROUP,				// "setgroup"
 	RLV_BHVR_UNSIT,					// "unsit"
 	RLV_BHVR_SIT,					// "sit"
+	RLV_BHVR_SITGROUND,
 	RLV_BHVR_SITTP,					// "sittp"
 	RLV_BHVR_STANDTP,				// "standtp"
 	RLV_BHVR_SETDEBUG,				// "setdebug"
diff --git a/indra/newview/rlvhandler.cpp b/indra/newview/rlvhandler.cpp
index d2117cbeaf0..ba136231fb9 100644
--- a/indra/newview/rlvhandler.cpp
+++ b/indra/newview/rlvhandler.cpp
@@ -902,6 +902,12 @@ void RlvHandler::onSitOrStand(bool fSitting)
 		doOnIdleOneTime(boost::bind(RlvUtil::forceTp, m_posSitSource));
 		m_posSitSource.setZero();
 	}
+	else if ( (!fSitting) && (m_fPendingGroundSit) )
+	{
+		m_fPendingGroundSit = false;
+		gAgent.setControlFlags(AGENT_CONTROL_SIT_ON_GROUND);
+		send_agent_update(TRUE, TRUE);
+	}
 }
 
 // Checked: 2010-03-11 (RLVa-1.2.0a) | Modified: RLVa-1.2.0a
@@ -3142,6 +3148,28 @@ ERlvCmdRet RlvForceHandler<RLV_BHVR_SETGROUP>::onCommand(const RlvCommand& rlvCm
 	return (fValid) ? RLV_RET_SUCCESS : RLV_RET_FAILED_OPTION;
 }
 
+// Handles: @sitground=force
+template<> template<>
+ERlvCmdRet RlvForceHandler<RLV_BHVR_SITGROUND>::onCommand(const RlvCommand& rlvCmd)
+{
+	if ( (!RlvActions::canGroundSit(rlvCmd.getObjectID())) || (!isAgentAvatarValid()) )
+		return RLV_RET_FAILED_LOCK;
+
+	if (!gAgentAvatarp->isSitting())
+	{
+		gRlvHandler.m_fPendingGroundSit = false;
+		gAgent.setControlFlags(AGENT_CONTROL_SIT_ON_GROUND);
+	}
+	else if (gAgentAvatarp->getParent())
+	{
+		gRlvHandler.m_fPendingGroundSit = true;
+		gAgent.setControlFlags(AGENT_CONTROL_STAND_UP);
+	}
+	send_agent_update(TRUE, TRUE);
+
+	return RLV_RET_SUCCESS;
+}
+
 // Handles: @sit:<uuid>=force
 template<> template<>
 ERlvCmdRet RlvForceHandler<RLV_BHVR_SIT>::onCommand(const RlvCommand& rlvCmd)
@@ -3153,10 +3181,7 @@ ERlvCmdRet RlvForceHandler<RLV_BHVR_SIT>::onCommand(const RlvCommand& rlvCmd)
 	LLViewerObject* pObj = NULL;
 	if (idTarget.isNull())
 	{
-		if ( (!RlvActions::canGroundSit()) || ((isAgentAvatarValid()) && (gAgentAvatarp->isSitting())) )
-			return RLV_RET_FAILED_LOCK;
-		gAgent.sitDown();
-		send_agent_update(TRUE, TRUE);
+		return RlvForceHandler<RLV_BHVR_SITGROUND>::onCommand(rlvCmd);
 	}
 	else if ( ((pObj = gObjectList.findObject(idTarget)) != NULL) && (LL_PCODE_VOLUME == pObj->getPCode()))
 	{
diff --git a/indra/newview/rlvhandler.h b/indra/newview/rlvhandler.h
index 01da4b6269b..e36782c52af 100644
--- a/indra/newview/rlvhandler.h
+++ b/indra/newview/rlvhandler.h
@@ -266,6 +266,7 @@ class RlvHandler : public LLOldEvents::LLSimpleListener, public LLParticularGrou
 
 	bool                                    m_fCanCancelTp;					// @accepttp=n and @tpto=force
 	mutable LLVector3d                      m_posSitSource;					// @standtp=n (mutable because onForceXXX handles are all declared as const)
+	mutable bool                            m_fPendingGroundSit = false;	// @sitground=force
 	mutable LLUUID                          m_idAgentGroup;					// @setgroup=n
 	std::pair<LLUUID, std::string>          m_PendingGroupChange;			// @setgroup=force
 	std::pair<LLTimer, LLUUID>              m_GroupChangeExpiration;        // @setgroup=force
diff --git a/indra/newview/rlvhelper.cpp b/indra/newview/rlvhelper.cpp
index dcef3f98274..207ca5cebd4 100644
--- a/indra/newview/rlvhelper.cpp
+++ b/indra/newview/rlvhelper.cpp
@@ -287,6 +287,7 @@ RlvBehaviourDictionary::RlvBehaviourDictionary()
 	addEntry(new RlvForceProcessor<RLV_BHVR_SETCAM_MODE>("setcam_mode", RlvBehaviourInfo::BHVR_EXPERIMENTAL));
 	addEntry(new RlvForceProcessor<RLV_BHVR_SETGROUP>("setgroup"));
 	addEntry(new RlvForceProcessor<RLV_BHVR_SIT>("sit"));
+	addEntry(new RlvForceProcessor<RLV_BHVR_SITGROUND>("sitground"));
 	addEntry(new RlvForceProcessor<RLV_BHVR_TPTO>("tpto"));
 	addEntry(new RlvBehaviourInfo("unsit",					RLV_BHVR_UNSIT,					RLV_TYPE_FORCE));
 
-- 
GitLab