diff --git a/indra/newview/rlvcommon.h b/indra/newview/rlvcommon.h
index 7b7ca22b0b7e8dafad416b5a812e68d12f8460ae..1c55c685d0eece0d63a8e2bb822b4f145c879213 100644
--- a/indra/newview/rlvcommon.h
+++ b/indra/newview/rlvcommon.h
@@ -56,6 +56,7 @@ class RlvObject;
 
 struct RlvException;
 typedef boost::variant<std::string, LLUUID, S32, ERlvBehaviour> RlvExceptionOption;
+typedef boost::variant<int, float> RlvBehaviourModifierValue;
 
 class RlvGCTimer;
 
diff --git a/indra/newview/rlvdefines.h b/indra/newview/rlvdefines.h
index 3358a4f6ecd2d210a6af90e930c323942c748c5b..7b21e8bb519347747fca4ffff83a2cc59a767738 100644
--- a/indra/newview/rlvdefines.h
+++ b/indra/newview/rlvdefines.h
@@ -194,11 +194,19 @@ enum ERlvBehaviour {
 	RLV_BHVR_UNKNOWN
 };
 
-enum RlvBehaviourOptionType
+enum ERlvBehaviourModifier
 {
-	RLV_OPTION_NONE,
-	RLV_OPTION_EXCEPTION,
-	RLV_OPTION_NONE_OR_EXCEPTION
+	RLV_MODIFIER_COUNT,
+	RLV_MODIFIER_UNKNOWN
+};
+
+enum ERlvBehaviourOptionType
+{
+	RLV_OPTION_NONE,				// Behaviour takes no parameters
+	RLV_OPTION_EXCEPTION,			// Behaviour requires an exception as a parameter
+	RLV_OPTION_NONE_OR_EXCEPTION,	// Behaviour takes either no parameters or an exception
+	RLV_OPTION_MODIFIER,			// Behaviour requires a modifier as a parameter
+	RLV_OPTION_NONE_OR_MODIFIER		// Behaviour takes either no parameters or a modifier
 };
 
 enum ERlvParamType {
diff --git a/indra/newview/rlvhandler.cpp b/indra/newview/rlvhandler.cpp
index c748a4de27b1601000b05cbd651e69d27836eeb3..368f3115954853f9d1f3cb486f9d6b893b836749 100644
--- a/indra/newview/rlvhandler.cpp
+++ b/indra/newview/rlvhandler.cpp
@@ -121,7 +121,7 @@ RlvHandler::RlvHandler() : m_fCanCancelTp(true), m_posSitSource(), m_pGCTimer(NU
 {
 	gAgent.addListener(this, "new group");
 
-	// Array auto-initialization to 0 is non-standard? (Compiler warning in VC-8.0)
+	// Array auto-initialization to 0 is still not supported in VS2013
 	memset(m_Behaviours, 0, sizeof(S16) * RLV_BHVR_COUNT);
 }
 
@@ -1362,6 +1362,45 @@ ERlvCmdRet RlvBehaviourGenericHandler<RLV_OPTION_NONE_OR_EXCEPTION>::onCommand(c
 	return RlvBehaviourGenericHandler<RLV_OPTION_NONE>::onCommand(rlvCmd, fRefCount);
 }
 
+// Handles: @bhvr:<modifier>=n|y
+ERlvCmdRet RlvBehaviourGenericHandler<RLV_OPTION_MODIFIER>::onCommand(const RlvCommand& rlvCmd, bool& fRefCount)
+{
+	// There should be an option and it should specify a valid modifier (RlvBehaviourModifier performs the appropriate type checks)
+	RlvBehaviourModifier* pBhvrModifier = RlvBehaviourDictionary::instance().getModifierFromBehaviour(rlvCmd.getBehaviourType());
+	RlvBehaviourModifierValue modValue;
+	if ( (!rlvCmd.hasOption()) || (!pBhvrModifier) || (!pBhvrModifier->convertOptionValue(rlvCmd.getOption(), modValue)) )
+		return RLV_RET_FAILED_OPTION;
+
+	if (RLV_TYPE_ADD == rlvCmd.getParamType())
+		pBhvrModifier->addValue(modValue, rlvCmd.getObjectID());
+	else
+		pBhvrModifier->removeValue(modValue, rlvCmd.getObjectID());
+
+	fRefCount = true;
+	return RLV_RET_SUCCESS;
+}
+
+// Handles: @bhvr[:<modifier>]=n|y
+ERlvCmdRet RlvBehaviourGenericHandler<RLV_OPTION_NONE_OR_MODIFIER>::onCommand(const RlvCommand& rlvCmd, bool& fRefCount)
+{
+	// If there is an option then it should specify a valid modifier (and reference count)
+	if (rlvCmd.hasOption())
+		return RlvBehaviourGenericHandler<RLV_OPTION_MODIFIER>::onCommand(rlvCmd, fRefCount);
+
+	// Add the default option on an empty modifier if needed
+	RlvBehaviourModifier* pBhvrModifier = RlvBehaviourDictionary::instance().getModifierFromBehaviour(rlvCmd.getBehaviourType());
+	if ( (pBhvrModifier) && (pBhvrModifier->getAddDefault()) )
+	{
+		if (RLV_TYPE_ADD == rlvCmd.getParamType())
+			pBhvrModifier->addValue(pBhvrModifier->getDefaultValue(), rlvCmd.getObjectID());
+		else
+			pBhvrModifier->removeValue(pBhvrModifier->getDefaultValue(), rlvCmd.getObjectID());
+	}
+
+	fRefCount = true;
+	return RLV_RET_SUCCESS;
+}
+
 // Handles: @addattach[:<attachpt>]=n|y and @remattach[:<attachpt>]=n|y
 template<> template<>
 ERlvCmdRet RlvBehaviourAddRemAttachHandler::onCommand(const RlvCommand& rlvCmd, bool& fRefCount)
diff --git a/indra/newview/rlvhelper.cpp b/indra/newview/rlvhelper.cpp
index f87485c56fb06daea593b70111514fefdf4f708c..7e78b05ec24e5b81d30579b0acc045a77c4c5e3e 100644
--- a/indra/newview/rlvhelper.cpp
+++ b/indra/newview/rlvhelper.cpp
@@ -32,8 +32,51 @@
 // RlvBehaviourDictionary
 //
 
+static RlvBehaviourModifier_CompMin s_RlvBehaviourModifier_CompMin;
+static RlvBehaviourModifier_CompMax s_RlvBehaviourModifier_CompMax;
+
+/*
+ * Processing of RLVa commands used to be a big switch/case loop with one function for each command type(addrem, reply
+ * and force). This is slowly being replaced with templated command handling which might be more confusing intially
+ * (also due to my poor naming schemes) but is actually far simpler and less error-prone than the old way.
+ *
+ * In the general case you just add a definition for the command below and then write the function body in rlvhandler.cpp
+ * and you're done! Told you this was easy.
+ *
+ * Reply command
+ * =============
+ * Definition: RlvReplyProcessor<RLV_BHVR_COMMANDNAME>("commandname"[, <options>]));
+ * Implement : ERlvCmdRet RlvReplyHandler<RLV_BHVR_COMMANDNAME>::onCommand(const RlvCommand& rlvCmd, std::string& strReply)
+ *
+ * Force command
+ * =============
+ * Definition: new RlvForceProcessor<RLV_BHVR_COMMANDNAME>("commandname"[, <options>]));
+ * Implement : ERlvCmdRet RlvForceProcessor<RLV_BHVR_COMMANDNAME>::onCommand(const RlvCommand& rlvCmd)
+ *
+ * Behaviours
+ * ==========
+ * Behaviours come in many forms but the added complexity is only in the variety of choices. The implementation is as
+ * easy as reply or force commands.
+ *
+ * For simple behaviours that only require recordkeeping and don't run code when set/unset (see ERlvBehaviourOptionType):
+ *   Definition: RlvBehaviourGenericProcessor<RLV_OPTION_TYPE>("commandname", RLV_BHVR_COMMANDNAME)
+ *   Implement : nothing! (it automagically works)
+ * For simple behaviours that only require recordkeeping and only run code when they toggle:
+ *   Definition: RlvBehaviourToggleProcessor<RLV_BHVR_COMMANDNAME, RLV_OPTION_TYPE>("commandname"))
+ *   Implement : void RlvBehaviourToggleHandler<RLV_BHVR_COMMANDNAME>::onCommandToggle(ERlvBehaviour eBhvr, bool fHasBhvr)
+ * For behaviours that require manual processing:
+ *   Definition: RlvBehaviourProcessor<RLV_BHVR_COMMANDNAME>("commandname"))
+ *   Implement : ERlvCmdRet RlvBehaviourHandler<RLV_BHVR_COMMANDNAME>::onCommand(const RlvCommand& rlvCmd, bool& fRefCount)
+ * For behaviours that run code when their modifier changes:
+ *   Definition: addModifier(RLV_BHVR_COMMANDNAME, RLV_MODIFIER_COMMANDNAME, new RlvBehaviourModifierHandler<RLV_MODIFIER_COMMANDNAME>(<default>, <auto-add>, <comparator>));
+ *   Implement : void RlvBehaviourModifierHandler::onValueChanged()
+ *
+ */
 RlvBehaviourDictionary::RlvBehaviourDictionary()
 {
+	// Array auto-initialization to 0 is still not supported in VS2013
+	memset(m_BehaviourModifiers, 0, sizeof(RlvBehaviourModifier*) * RLV_MODIFIER_COUNT);
+
 	//
 	// Restrictions
 	//
@@ -221,6 +264,12 @@ RlvBehaviourDictionary::~RlvBehaviourDictionary()
 	for (const RlvBehaviourInfo* pBhvrInfo : m_BhvrInfoList)
 		delete pBhvrInfo;
 	m_BhvrInfoList.clear();
+
+	for (int idxBhvrMod = 0; idxBhvrMod < RLV_MODIFIER_COUNT; idxBhvrMod++)
+	{
+		delete m_BehaviourModifiers[idxBhvrMod];
+		m_BehaviourModifiers[idxBhvrMod] = nullptr;
+	}
 }
 
 void RlvBehaviourDictionary::addEntry(const RlvBehaviourInfo* pEntry)
@@ -243,6 +292,15 @@ void RlvBehaviourDictionary::addEntry(const RlvBehaviourInfo* pEntry)
 	m_BhvrInfoList.push_back(pEntry);
 }
 
+void RlvBehaviourDictionary::addModifier(ERlvBehaviour eBhvr, ERlvBehaviourModifier eModifier, RlvBehaviourModifier* pModifierEntry)
+{
+	if (eModifier < RLV_MODIFIER_COUNT)
+	{
+		m_BehaviourModifiers[eModifier] = pModifierEntry;
+		m_Bhvr2ModifierMap.insert(std::make_pair(eBhvr, eModifier));
+	}
+}
+
 const RlvBehaviourInfo* RlvBehaviourDictionary::getBehaviourInfo(const std::string& strBhvr, ERlvParamType eParamType, bool* pfStrict) const
 {
 	bool fStrict = boost::algorithm::ends_with(strBhvr, "_sec");
@@ -289,6 +347,13 @@ bool RlvBehaviourDictionary::getHasStrict(ERlvBehaviour eBhvr) const
 	return false;
 }
 
+RlvBehaviourModifier* RlvBehaviourDictionary::getModifierFromBehaviour(ERlvBehaviour eBhvr) const
+{
+	rlv_bhvr2mod_map_t::const_iterator itMod = m_Bhvr2ModifierMap.find(eBhvr);
+	ERlvBehaviourModifier eBhvrMod = (m_Bhvr2ModifierMap.end() != itMod) ? itMod->second : RLV_MODIFIER_UNKNOWN;
+	return (eBhvrMod < RLV_MODIFIER_UNKNOWN) ? m_BehaviourModifiers[eBhvrMod] : nullptr;
+}
+
 void RlvBehaviourDictionary::toggleBehaviourFlag(const std::string& strBhvr, ERlvParamType eParamType, RlvBehaviourInfo::EBehaviourFlags eBhvrFlag, bool fEnable)
 {
 	rlv_string2info_map_t::const_iterator itBhvr = m_String2InfoMap.find(std::make_pair(strBhvr, (eParamType & RLV_TYPE_ADDREM) ? RLV_TYPE_ADDREM : eParamType));
@@ -298,6 +363,74 @@ void RlvBehaviourDictionary::toggleBehaviourFlag(const std::string& strBhvr, ERl
 	}
 }
 
+// ============================================================================
+// RlvBehaviourModifier
+//
+
+RlvBehaviourModifier::RlvBehaviourModifier(const RlvBehaviourModifierValue& defaultValue, bool fAddDefaultOnEmpty, RlvBehaviourModifier_Comp* pValueComparator)
+	: m_DefaultValue(defaultValue), m_fAddDefaultOnEmpty(fAddDefaultOnEmpty), m_pValueComparator(pValueComparator)
+{
+}
+
+bool RlvBehaviourModifier::addValue(const RlvBehaviourModifierValue& modValue, const LLUUID& idObject)
+{
+	if (modValue.which() == m_DefaultValue.which())
+	{
+		m_Values.insert((m_pValueComparator) ? std::lower_bound(m_Values.begin(), m_Values.end(), std::make_pair(modValue, idObject), boost::bind(&RlvBehaviourModifier_Comp::operator(), m_pValueComparator, _1, _2)) : m_Values.end(), std::make_pair(modValue, idObject));
+		onValueChange();
+		m_ChangeSignal(getValue());
+		return true;
+	}
+	return false;
+}
+
+void RlvBehaviourModifier::removeValue(const RlvBehaviourModifierValue& modValue, const LLUUID& idObject)
+{
+	if ( (modValue.which() == m_DefaultValue.which()) )
+	{
+		auto itValue = std::find(m_Values.begin(), m_Values.end(), std::make_pair(modValue, idObject));
+		if (m_Values.end() != itValue)
+		{
+			m_Values.erase(itValue);
+			onValueChange();
+			m_ChangeSignal(getValue());
+		}
+	}
+}
+
+void RlvBehaviourModifier::setPrimaryObject(const LLUUID& idPrimaryObject)
+{
+	if (m_pValueComparator)
+	{
+		m_pValueComparator->m_idPrimaryObject = idPrimaryObject;
+		m_Values.sort(boost::bind(&RlvBehaviourModifier_Comp::operator(), m_pValueComparator, _1, _2));
+		onValueChange();
+		m_ChangeSignal(getValue());
+	}
+}
+
+bool RlvBehaviourModifier::convertOptionValue(const std::string& optionValue, RlvBehaviourModifierValue& modValue) const
+{
+	try
+	{
+		if (typeid(float) == m_DefaultValue.type())
+		{
+			modValue = std::stof(optionValue.c_str());
+			return true;
+		}
+		else if (typeid(int) == m_DefaultValue.type())
+		{
+			modValue = std::stoi(optionValue.c_str());
+			return true;
+		}
+		return false;
+	}
+	catch (const std::invalid_argument&)
+	{
+		return false;
+	}
+}
+
 // ============================================================================
 // RlvCommmand
 //
diff --git a/indra/newview/rlvhelper.h b/indra/newview/rlvhelper.h
index 00feabc1b4f5d16071ad5832788ec14a30aea404..cfe64a48f5283b1400c2ff0f54a15daa15ee4a7f 100644
--- a/indra/newview/rlvhelper.h
+++ b/indra/newview/rlvhelper.h
@@ -142,14 +142,14 @@ template<ERlvBehaviour eBhvr, typename handlerImpl = RlvCommandHandler<RLV_TYPE_
 template<ERlvBehaviour eBhvr, typename handlerImpl = RlvCommandHandler<RLV_TYPE_REPLY, eBhvr>> using RlvReplyProcessor = RlvCommandProcessor<RLV_TYPE_REPLY, eBhvr, handlerImpl>;
 
 // Provides pre-defined generic implementations of basic behaviours (template voodoo - see original commit for something that still made sense)
-template<RlvBehaviourOptionType optionType> struct RlvBehaviourGenericHandler { static ERlvCmdRet onCommand(const RlvCommand& rlvCmd, bool& fRefCount); };
-template<RlvBehaviourOptionType optionType> using RlvBehaviourGenericProcessor = RlvBehaviourProcessor<RLV_BHVR_UNKNOWN, RlvBehaviourGenericHandler<optionType>>;
+template<ERlvBehaviourOptionType optionType> struct RlvBehaviourGenericHandler { static ERlvCmdRet onCommand(const RlvCommand& rlvCmd, bool& fRefCount); };
+template<ERlvBehaviourOptionType optionType> using RlvBehaviourGenericProcessor = RlvBehaviourProcessor<RLV_BHVR_UNKNOWN, RlvBehaviourGenericHandler<optionType>>;
 
 // ============================================================================
 // RlvBehaviourProcessor and related classes - Handles add/rem comamnds aka "restrictions)
 //
 
-template <ERlvBehaviour eBhvr, RlvBehaviourOptionType optionType, typename toggleHandlerImpl = RlvBehaviourToggleHandler<eBhvr>>
+template <ERlvBehaviour eBhvr, ERlvBehaviourOptionType optionType, typename toggleHandlerImpl = RlvBehaviourToggleHandler<eBhvr>>
 class RlvBehaviourToggleProcessor : public RlvBehaviourInfo
 {
 public:
@@ -157,6 +157,152 @@ public:
 	ERlvCmdRet processCommand(const RlvCommand& rlvCmd) const override { return RlvCommandHandlerBaseImpl<RLV_TYPE_ADDREM>::processCommand(rlvCmd, &RlvBehaviourGenericHandler<optionType>::onCommand, &toggleHandlerImpl::onCommandToggle); }
 };
 
+// ============================================================================
+// RlvBehaviourModifier - stores behaviour modifiers in an - optionally - sorted list and returns the first element (or default value if there are no modifiers)
+//
+
+typedef std::pair<RlvBehaviourModifierValue, LLUUID> RlvBehaviourModifierValueTuple;
+
+struct RlvBehaviourModifier_Comp
+{
+	virtual ~RlvBehaviourModifier_Comp() {}
+	virtual bool operator()(const RlvBehaviourModifierValueTuple& lhs, const RlvBehaviourModifierValueTuple& rhs)
+	{
+		// Values that match the primary object take precedence (otherwise maintain relative ordering)
+		if ( (rhs.second == m_idPrimaryObject) && (lhs.second != m_idPrimaryObject) )
+			return false;
+		return true;
+	}
+
+	LLUUID m_idPrimaryObject;
+};
+struct RlvBehaviourModifier_CompMin : public RlvBehaviourModifier_Comp
+{
+	bool operator()(const RlvBehaviourModifierValueTuple& lhs, const RlvBehaviourModifierValueTuple& rhs) override
+	{
+		if ( (m_idPrimaryObject.isNull()) || ((lhs.second == m_idPrimaryObject) && (rhs.second == m_idPrimaryObject)) )
+			return lhs.first < rhs.first;
+		return RlvBehaviourModifier_Comp::operator()(lhs, rhs);
+	}
+};
+struct RlvBehaviourModifier_CompMax : public RlvBehaviourModifier_Comp
+{
+	bool operator()(const RlvBehaviourModifierValueTuple& lhs, const RlvBehaviourModifierValueTuple& rhs) override
+	{
+		if ( (m_idPrimaryObject.isNull()) || ((lhs.second == m_idPrimaryObject) && (rhs.second == m_idPrimaryObject)) )
+			return rhs.first < lhs.first;
+		return RlvBehaviourModifier_Comp::operator()(lhs, rhs);
+	}
+};
+
+class RlvBehaviourModifier
+{
+public:
+	RlvBehaviourModifier(const RlvBehaviourModifierValue& defaultValue, bool fAddDefaultOnEmpty, RlvBehaviourModifier_Comp* pValueComparator);
+	virtual ~RlvBehaviourModifier() {}
+
+	/*
+	 * Member functions
+	 */
+protected:
+	virtual void onValueChange() const {}
+public:
+	bool addValue(const RlvBehaviourModifierValue& modValue, const LLUUID& idObject);
+	bool convertOptionValue(const std::string& optionValue, RlvBehaviourModifierValue& modValue) const;
+	bool getAddDefault() const { return m_fAddDefaultOnEmpty; }
+	const RlvBehaviourModifierValue& getDefaultValue() const { return m_DefaultValue; }
+	const RlvBehaviourModifierValue& getValue() const { return (!m_Values.empty()) ? m_Values.front().first : m_DefaultValue; }
+	template<typename T> const T&    getValue() const { return boost::get<T>(getValue()); }
+	void removeValue(const RlvBehaviourModifierValue& modValue, const LLUUID& idObject);
+	void setPrimaryObject(const LLUUID& idPrimaryObject);
+
+	typedef boost::signals2::signal<void(const RlvBehaviourModifierValue& newValue)> change_signal_t;
+	change_signal_t& getSignal() { return m_ChangeSignal; }
+
+	/*
+	 * Member variables
+	 */
+protected:
+	RlvBehaviourModifierValue            m_DefaultValue;
+	bool                                 m_fAddDefaultOnEmpty;
+	std::list<RlvBehaviourModifierValueTuple> m_Values;
+	change_signal_t                      m_ChangeSignal;
+	RlvBehaviourModifier_Comp*           m_pValueComparator;
+};
+
+template<ERlvBehaviourModifier eBhvrMod>
+class RlvBehaviourModifierHandler : public RlvBehaviourModifier
+{
+public:
+	//using RlvBehaviourModifier::RlvBehaviourModifier; // Needs VS2015 and up
+	RlvBehaviourModifierHandler(const RlvBehaviourModifierValue& defaultValue, bool fAddDefaultOnEmpty, RlvBehaviourModifier_Comp* pValueComparator)
+		: RlvBehaviourModifier(defaultValue, fAddDefaultOnEmpty, pValueComparator) {}
+protected:
+	void onValueChange() const override;
+};
+
+// Inspired by LLControlCache<T>
+template<typename T>
+class RlvBehaviourModifierCache : public LLRefCount, public LLInstanceTracker<RlvBehaviourModifierCache<T>, ERlvBehaviourModifier>
+{
+public:
+	RlvBehaviourModifierCache(ERlvBehaviourModifier eModifier)
+		: LLInstanceTracker<RlvBehaviourModifierCache<T>, ERlvBehaviourModifier>(eModifier)
+	{
+		RlvBehaviourModifier* pBhvrModifier = (eModifier < RLV_MODIFIER_COUNT) ? RlvBehaviourDictionary::instance().getModifier(eModifier) : nullptr;
+		if (pBhvrModifier)
+		{
+			mConnection = pBhvrModifier->getSignal().connect(boost::bind(&RlvBehaviourModifierCache<T>::handleValueChange, this, _1));
+			mCachedValue = pBhvrModifier->getValue<T>();
+		}
+		else
+		{
+			mCachedValue = {};
+		}
+	}
+	~RlvBehaviourModifierCache() {}
+
+	/*
+	 * Member functions
+	 */
+public:
+	const T& getValue() const { return mCachedValue; }
+protected:
+	void handleValueChange(const RlvBehaviourModifierValue& newValue) { mCachedValue = boost::get<T>(newValue); }
+
+	/*
+	 * Member variables
+	 */
+protected:
+	T mCachedValue;
+	boost::signals2::scoped_connection mConnection;
+};
+
+// Inspired by LLCachedControl<T>
+template <typename T>
+class RlvCachedBehaviourModifier
+{
+public:
+	RlvCachedBehaviourModifier(ERlvBehaviourModifier eModifier)
+	{
+		if ((mCachedModifierPtr = RlvBehaviourModifierCache<T>::getInstance(eModifier)) == nullptr)
+			mCachedModifierPtr = new RlvBehaviourModifierCache<T>(eModifier);
+	}
+
+	/*
+	 * Operators
+	 */
+public:
+	operator const T&() const { return mCachedModifierPtr->getValue(); }
+	const T& operator()() { return mCachedModifierPtr->getValue(); }
+
+	/*
+	 * Member variables
+	 */
+protected:
+	LLPointer<RlvBehaviourModifierCache<T>> mCachedModifierPtr;
+};
+
 // ============================================================================
 // RlvBehaviourDictionary and related classes
 //
@@ -169,6 +315,7 @@ protected:
 	~RlvBehaviourDictionary();
 public:
 	void addEntry(const RlvBehaviourInfo* pEntry);
+	void addModifier(ERlvBehaviour eBhvr, ERlvBehaviourModifier eModifier, RlvBehaviourModifier* pModifierEntry);
 
 	/*
 	 * General helper functions
@@ -178,7 +325,8 @@ public:
 	const RlvBehaviourInfo*	getBehaviourInfo(const std::string& strBhvr, ERlvParamType eParamType, bool* pfStrict = NULL) const;
 	bool                    getCommands(const std::string& strMatch, ERlvParamType eParamType, std::list<std::string>& cmdList) const;
 	bool                    getHasStrict(ERlvBehaviour eBhvr) const;
-	const std::string&      getStringFromBehaviour(ERlvBehaviour eBhvr, ERlvParamType eParamType, bool fStrict = false) const;
+	RlvBehaviourModifier*   getModifier(ERlvBehaviourModifier eBhvrMod) const { return (eBhvrMod < RLV_MODIFIER_COUNT) ? m_BehaviourModifiers[eBhvrMod] : nullptr; }
+	RlvBehaviourModifier*   getModifierFromBehaviour(ERlvBehaviour eBhvr) const;
 	void                    toggleBehaviourFlag(const std::string& strBhvr, ERlvParamType eParamType, RlvBehaviourInfo::EBehaviourFlags eBvhrFlag, bool fEnable);
 
 	/*
@@ -188,10 +336,13 @@ protected:
 	typedef std::list<const RlvBehaviourInfo*> rlv_bhvrinfo_list_t;
 	typedef std::map<std::pair<std::string, ERlvParamType>, const RlvBehaviourInfo*> rlv_string2info_map_t;
 	typedef std::multimap<ERlvBehaviour, const RlvBehaviourInfo*> rlv_bhvr2info_map_t;
+	typedef std::map<ERlvBehaviour, ERlvBehaviourModifier> rlv_bhvr2mod_map_t;
 
 	rlv_bhvrinfo_list_t   m_BhvrInfoList;
 	rlv_string2info_map_t m_String2InfoMap;
 	rlv_bhvr2info_map_t	  m_Bhvr2InfoMap;
+	rlv_bhvr2mod_map_t    m_Bhvr2ModifierMap;
+	RlvBehaviourModifier* m_BehaviourModifiers[RLV_MODIFIER_COUNT];
 };
 
 // ============================================================================