From 630812299fc5f53ab9fb9b033d907e800cb11dca Mon Sep 17 00:00:00 2001
From: Kitty Barnett <develop@catznip.com>
Date: Sat, 9 Jun 2018 19:06:00 +0200
Subject: [PATCH] Added @jump=n and @fly:[true|false]=force (with issuing
 object exemption)

--HG--
branch : RLVa
---
 indra/newview/llagent.cpp    | 18 ++++++++++++++----
 indra/newview/rlvactions.cpp | 15 +++++++++++++++
 indra/newview/rlvactions.h   | 12 ++++++++++++
 indra/newview/rlvdefines.h   |  1 +
 indra/newview/rlvhandler.cpp | 17 +++++++++++++++++
 indra/newview/rlvhelper.cpp  | 21 +++++++++++++++++++++
 6 files changed, 80 insertions(+), 4 deletions(-)

diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index 285dcb0096..7be7feab4c 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -672,6 +672,13 @@ void LLAgent::moveLeftNudge(S32 direction)
 //-----------------------------------------------------------------------------
 void LLAgent::moveUp(S32 direction)
 {
+// [RLVa:KB] - Checked: RLVa-2.2
+	if ( (!RlvActions::canJump()) && (direction > 0) && (!getFlying()) )
+	{
+		return;
+	}
+// [/Sl:KB]
+
 	mMoveTimer.reset();
 	LLFirstUse::notMoving(false);
 
@@ -735,8 +742,11 @@ void LLAgent::movePitch(F32 mag)
 // Does this parcel allow you to fly?
 BOOL LLAgent::canFly()
 {
-// [RLVa:KB] - Checked: 2010-03-02 (RLVa-1.2.0d) | Modified: RLVa-1.0.0c
-	if (gRlvHandler.hasBehaviour(RLV_BHVR_FLY)) return FALSE;
+// [RLVa:KB] - Checked: RLVa-1.0
+	if (!RlvActions::canFly())
+	{
+		return FALSE;
+	}
 // [/RLVa:KB]
 	if (isGodlike()) return TRUE;
 
@@ -786,8 +796,8 @@ void LLAgent::setFlying(BOOL fly)
 
 	if (fly)
 	{
-// [RLVa:KB] - Checked: 2010-03-02 (RLVa-1.2.0d) | Modified: RLVa-1.0.0c
-		if (gRlvHandler.hasBehaviour(RLV_BHVR_FLY))
+// [RLVa:KB] - Checked: RLVa-1.0
+		if (!RlvActions::canFly())
 		{
 			return;
 		}
diff --git a/indra/newview/rlvactions.cpp b/indra/newview/rlvactions.cpp
index 74207b96a7..355945dbc0 100644
--- a/indra/newview/rlvactions.cpp
+++ b/indra/newview/rlvactions.cpp
@@ -295,6 +295,21 @@ bool RlvActions::autoAcceptTeleportRequest(const LLUUID& idRequester)
 	return ((idRequester.notNull()) && (gRlvHandler.isException(RLV_BHVR_ACCEPTTPREQUEST, idRequester))) || (gRlvHandler.hasBehaviour(RLV_BHVR_ACCEPTTPREQUEST));
 }
 
+bool RlvActions::canFly()
+{
+	return (!gRlvHandler.getCurrentCommand()) ? !gRlvHandler.hasBehaviour(RLV_BHVR_FLY) : !gRlvHandler.hasBehaviourExcept(RLV_BHVR_FLY, gRlvHandler.getCurrentObject());
+}
+
+bool RlvActions::canFly(const LLUUID& idRlvObjExcept)
+{
+	return !gRlvHandler.hasBehaviourExcept(RLV_BHVR_FLY, idRlvObjExcept);
+}
+
+bool RlvActions::canJump()
+{
+	return !gRlvHandler.hasBehaviour(RLV_BHVR_JUMP);
+}
+
 // ============================================================================
 // Teleporting
 //
diff --git a/indra/newview/rlvactions.h b/indra/newview/rlvactions.h
index afafa726b8..90b1069f6b 100644
--- a/indra/newview/rlvactions.h
+++ b/indra/newview/rlvactions.h
@@ -176,6 +176,18 @@ public:
 	 */
 	static bool autoAcceptTeleportRequest(const LLUUID& idRequester);
 
+	/*
+	 * Returns true if the user can fly
+	 * (NOTE: the parameter-less overload takes the currently executing command into account)
+	 */
+	static bool canFly();
+	static bool canFly(const LLUUID& idRlvObjExcept);
+
+	/*
+	 * Returns true if the user can jump
+	 */
+	static bool canJump();
+
 	// ===========
 	// Teleporting
 	// ===========
diff --git a/indra/newview/rlvdefines.h b/indra/newview/rlvdefines.h
index 29cc03a913..056e0303de 100644
--- a/indra/newview/rlvdefines.h
+++ b/indra/newview/rlvdefines.h
@@ -163,6 +163,7 @@ enum ERlvBehaviour {
 	RLV_BHVR_TOUCHALL,				// "touchall"
 	RLV_BHVR_TOUCHME,				// "touchme"
 	RLV_BHVR_FLY,					// "fly"
+	RLV_BHVR_JUMP,                  // "jump"
 	RLV_BHVR_SETGROUP,				// "setgroup"
 	RLV_BHVR_UNSIT,					// "unsit"
 	RLV_BHVR_SIT,					// "sit"
diff --git a/indra/newview/rlvhandler.cpp b/indra/newview/rlvhandler.cpp
index d998375444..13a2f95138 100644
--- a/indra/newview/rlvhandler.cpp
+++ b/indra/newview/rlvhandler.cpp
@@ -2391,6 +2391,23 @@ ERlvCmdRet RlvForceHandler<RLV_BHVR_DETACHME>::onCommand(const RlvCommand& rlvCm
 	return RLV_RET_SUCCESS;
 }
 
+// Handles: @fly:[true|false]=force
+template<> template<>
+ERlvCmdRet RlvForceHandler<RLV_BHVR_FLY>::onCommand(const RlvCommand& rlvCmd)
+{
+	bool fForceFly = true;
+	if ( (rlvCmd.hasOption()) && (!RlvCommandOptionHelper::parseOption<bool>(rlvCmd.getOption(), fForceFly)) )
+		return RLV_RET_FAILED_OPTION;
+
+	if ( (fForceFly) && (!RlvActions::canFly(rlvCmd.getObjectID())) )
+		return RLV_RET_FAILED_LOCK;
+
+	if (fForceFly != (bool)gAgent.getFlying())
+		gAgent.setFlying(fForceFly);
+
+	return RLV_RET_SUCCESS;
+}
+
 // Handles: @remattach[:<folder|attachpt|attachgroup>]=force
 template<> template<>
 ERlvCmdRet RlvForceRemAttachHandler::onCommand(const RlvCommand& rlvCmd)
diff --git a/indra/newview/rlvhelper.cpp b/indra/newview/rlvhelper.cpp
index 8dbfc69215..144d0242a5 100644
--- a/indra/newview/rlvhelper.cpp
+++ b/indra/newview/rlvhelper.cpp
@@ -104,6 +104,7 @@ RlvBehaviourDictionary::RlvBehaviourDictionary()
 	addModifier(RLV_BHVR_FARTOUCH, RLV_MODIFIER_FARTOUCHDIST, new RlvBehaviourModifier("Fartouch Distance", RLV_MODIFIER_FARTOUCH_DEFAULT, true, new RlvBehaviourModifierCompMin));
 	addEntry(new RlvBehaviourGenericProcessor<RLV_OPTION_NONE>("fly", RLV_BHVR_FLY));
 	addEntry(new RlvBehaviourGenericProcessor<RLV_OPTION_NONE>("interact", RLV_BHVR_INTERACT, RlvBehaviourInfo::BHVR_EXTENDED));
+	addEntry(new RlvBehaviourGenericProcessor<RLV_OPTION_NONE>("jump", RLV_BHVR_JUMP));
 	addEntry(new RlvBehaviourInfo("notify",					RLV_BHVR_NOTIFY,				RLV_TYPE_ADDREM));
 	addEntry(new RlvBehaviourGenericProcessor<RLV_OPTION_NONE>("permissive", RLV_BHVR_PERMISSIVE));
 	addEntry(new RlvBehaviourGenericProcessor<RLV_OPTION_NONE_OR_EXCEPTION>("recvchat", RLV_BHVR_RECVCHAT, RlvBehaviourInfo::BHVR_STRICT));
@@ -255,6 +256,7 @@ RlvBehaviourDictionary::RlvBehaviourDictionary()
 	//
 	addEntry(new RlvBehaviourInfo("adjustheight",			RLV_BHVR_ADJUSTHEIGHT,			RLV_TYPE_FORCE));
 	addEntry(new RlvForceProcessor<RLV_BHVR_DETACHME>("detachme"));
+	addEntry(new RlvForceProcessor<RLV_BHVR_FLY>("fly"));
 	addEntry(new RlvForceProcessor<RLV_BHVR_SETCAM_FOCUS>("setcam_focus", RlvBehaviourInfo::BHVR_EXPERIMENTAL));
 	addEntry(new RlvForceProcessor<RLV_BHVR_SETCAM_EYEOFFSET, RlvForceCamEyeFocusOffsetHandler>("setcam_eyeoffset", RlvBehaviourInfo::BHVR_EXPERIMENTAL));
 	addEntry(new RlvForceProcessor<RLV_BHVR_SETCAM_FOCUSOFFSET, RlvForceCamEyeFocusOffsetHandler>("setcam_focusoffset", RlvBehaviourInfo::BHVR_EXPERIMENTAL));
@@ -699,6 +701,25 @@ bool RlvCommandOptionHelper::parseOption<int>(const std::string& strOption, int&
 	return true;
 }
 
+template<>
+bool RlvCommandOptionHelper::parseOption<bool>(const std::string& strOption, bool& fOption)
+{
+	try
+	{
+		// Try and parse it as a number first
+		int nOption = std::stoi(strOption);
+		fOption = (bool)nOption;
+		return (nOption == 0) || (nOption == 1);
+	}
+	catch (const std::invalid_argument&)
+	{
+		// Then try and parse it as true/false
+		std::istringstream ss(strOption);
+		ss >> std::boolalpha >> fOption;
+		return !ss.fail();
+	}
+}
+
 template<>
 bool RlvCommandOptionHelper::parseOption<float>(const std::string& strOption, float& nOption)
 {
-- 
GitLab