460 lines
20 KiB
C++
460 lines
20 KiB
C++
/**
|
|
*
|
|
* Copyright (c) 2009-2010, Kitty Barnett
|
|
*
|
|
* The source code in this file is provided to you under the terms of the
|
|
* GNU General Public License, version 2.0, but WITHOUT ANY WARRANTY;
|
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
|
* PARTICULAR PURPOSE. Terms of the GPL can be found in doc/GPL-license.txt
|
|
* in this distribution, or online at http://www.gnu.org/licenses/gpl-2.0.txt
|
|
*
|
|
* By copying, modifying or distributing this software, you acknowledge that
|
|
* you have read and understood your obligations described above, and agree to
|
|
* abide by those obligations.
|
|
*
|
|
*/
|
|
|
|
#ifndef RLV_LOCKS_H
|
|
#define RLV_LOCKS_H
|
|
|
|
#include "rlvdefines.h"
|
|
#include "rlvcommon.h"
|
|
|
|
// ============================================================================
|
|
// RlvAttachPtLookup class declaration
|
|
//
|
|
|
|
#include "llagent.h"
|
|
#include "llagentwearables.h"
|
|
#include "llviewerjointattachment.h"
|
|
#include "llviewerobject.h"
|
|
#include "llvoavatar.h"
|
|
#include "lleventtimer.h"
|
|
|
|
#include "rlvdefines.h"
|
|
|
|
class RlvAttachPtLookup
|
|
{
|
|
public:
|
|
static LLViewerJointAttachment* getAttachPoint(const std::string& strText);
|
|
static LLViewerJointAttachment* getAttachPoint(const LLInventoryItem* pItem);
|
|
|
|
static S32 getAttachPointIndex(std::string strText);
|
|
static S32 getAttachPointIndex(const LLViewerObject* pObj);
|
|
static S32 getAttachPointIndex(const LLViewerJointAttachment* pObj);
|
|
static S32 getAttachPointIndex(const LLInventoryCategory* pFolder);
|
|
static S32 getAttachPointIndex(const LLInventoryItem* pItem, bool fFollowLinks = true);
|
|
|
|
static bool hasAttachPointName(const LLInventoryItem* pItem) { return (0 != getAttachPointIndex(pItem)); }
|
|
private:
|
|
static S32 getAttachPointIndexLegacy(const LLInventoryCategory* pFolder);
|
|
|
|
public:
|
|
static void initLookupTable();
|
|
private:
|
|
static std::map<std::string, S32> m_AttachPtLookupMap;
|
|
};
|
|
|
|
// ============================================================================
|
|
// RlvAttachmentLocks class declaration
|
|
//
|
|
|
|
// TODO-RLVa: [RLVa-1.2.1] Once everything is working for SL-2.0 thin out the member functions since a few of them are duplicates/unneeded
|
|
class RlvAttachmentLocks
|
|
{
|
|
public:
|
|
RlvAttachmentLocks() : m_fHasLockedHUD(false) {}
|
|
|
|
public:
|
|
// Adds an RLV_LOCK_REMOVE lock (held by idRlvObj) for the attachment
|
|
void addAttachmentLock(const LLUUID& idAttachObj, const LLUUID& idRlvObj);
|
|
// Adds an eLock type lock (held by idRlvObj) for the attachment point
|
|
void addAttachmentPointLock(S32 idxAttachPt, const LLUUID& idRlvObj, ERlvLockMask eLock);
|
|
|
|
// Returns TRUE if there is at least 1 non-detachable attachment currently attached to the attachment point
|
|
bool hasLockedAttachment(const LLViewerJointAttachment* pAttachPt) const;
|
|
// Returns TRUE if there is at least 1 eLock type locked attachment point (RLV_LOCK_ANY = RLV_LOCK_ADD *or* RLV_LOCK_REMOVE)
|
|
// - RLV_LOCK_REMOVE: specific attachment locked *or* any attachment point locked (regardless of whether it currently has attachments)
|
|
bool hasLockedAttachmentPoint(ERlvLockMask eLock) const;
|
|
// Returns TRUE if there is at least 1 non-detachable HUD attachment
|
|
bool hasLockedHUD() const { return m_fHasLockedHUD; }
|
|
|
|
// Returns TRUE if the attachment is RLV_LOCK_REMOVE locked
|
|
bool isLockedAttachment(const LLViewerObject* pObj) const;
|
|
// Returns TRUE if the attachment point is RLV_LOCK_REMOVE locked by anything other than idRlvObj
|
|
bool isLockedAttachmentExcept(const LLViewerObject* pObj, const LLUUID& idRlvObj) const;
|
|
// Returns TRUE if the attachment point is eLock type locked (RLV_LOCK_ANY = RLV_LOCK_ADD *or* RLV_LOCK_REMOVE)
|
|
bool isLockedAttachmentPoint(S32 idxAttachPt, ERlvLockMask eLock) const;
|
|
bool isLockedAttachmentPoint(const LLViewerJointAttachment* pAttachPt, ERlvLockMask eLock) const;
|
|
|
|
// Removes an RLV_LOCK_REMOVE lock (held by idRlvObj) for the attachment
|
|
void removeAttachmentLock(const LLUUID& idAttachObj, const LLUUID& idRlvObj);
|
|
// Removes an eLock type lock (held by idRlvObj) for the attachment point
|
|
void removeAttachmentPointLock(S32 idxAttachPt, const LLUUID& idRlvObj, ERlvLockMask eLock);
|
|
|
|
// Refreshes locked HUD attachment state
|
|
void updateLockedHUD();
|
|
// Iterates over all current attachment and attachment point locks and verifies their status (returns TRUE if verification succeeded)
|
|
bool verifyAttachmentLocks();
|
|
|
|
protected:
|
|
// Returns TRUE if the attachment point is eLock type locked by anything other than idRlvObj
|
|
bool isLockedAttachmentPointExcept(S32 idxAttachPt, ERlvLockMask eLock, const LLUUID& idRlvObj) const;
|
|
|
|
/*
|
|
* canAttach/canDetach trivial helper functions (note that a more approriate name might be userCanAttach/userCanDetach)
|
|
*/
|
|
public:
|
|
// Returns TRUE if the inventory item can be attached by the user (and optionally provides the attachment point - which may be NULL)
|
|
ERlvWearMask canAttach(const LLInventoryItem* pItem, LLViewerJointAttachment** ppAttachPtOut = NULL) const;
|
|
// Returns TRUE if the attachment point can be attached to by the user
|
|
ERlvWearMask canAttach(const LLViewerJointAttachment* pAttachPt) const;
|
|
|
|
// Returns TRUE if the inventory item can be detached by the user
|
|
bool canDetach(const LLInventoryItem* pItem) const;
|
|
// Returns TRUE if the attachment point has at least one attachment that can be detached by the user
|
|
bool canDetach(const LLViewerJointAttachment* pAttachPt, bool fDetachAll = false) const;
|
|
|
|
/*
|
|
* Member variables
|
|
*/
|
|
public:
|
|
typedef std::multimap<LLUUID, LLUUID> rlv_attachobjlock_map_t;
|
|
typedef std::multimap<S32, LLUUID> rlv_attachptlock_map_t;
|
|
// Accessors for RlvFloaterLocks
|
|
const rlv_attachptlock_map_t& getAttachPtLocks(ERlvLockMask eLock) { return (RLV_LOCK_ADD == eLock) ? m_AttachPtAdd : m_AttachPtRem; }
|
|
const rlv_attachobjlock_map_t& getAttachObjLocks() { return m_AttachObjRem; }
|
|
private:
|
|
rlv_attachptlock_map_t m_AttachPtAdd; // Map of attachment points that can't be attached to (idxAttachPt -> idObj)
|
|
rlv_attachptlock_map_t m_AttachPtRem; // Map of attachment points whose attachments can't be detached (idxAttachPt -> idObj)
|
|
rlv_attachobjlock_map_t m_AttachObjRem; // Map of attachments that can't be detached (idAttachObj -> idObj)
|
|
|
|
bool m_fHasLockedHUD;
|
|
};
|
|
|
|
extern RlvAttachmentLocks gRlvAttachmentLocks;
|
|
|
|
// ============================================================================
|
|
// RlvAttachmentLockWatchdog - Self contained class that automagically takes care of enforcing attachment locks (ie reattach-on-detach)
|
|
//
|
|
|
|
// TODO-RLVa: [RLVa-1.2.1] This class really looks rather cluttered so look into cleaning it up/simplifying it a bit
|
|
class RlvAttachmentLockWatchdog : public LLSingleton<RlvAttachmentLockWatchdog>
|
|
{
|
|
friend class LLSingleton<RlvAttachmentLockWatchdog>;
|
|
protected:
|
|
RlvAttachmentLockWatchdog() : m_pTimer(NULL) {}
|
|
~RlvAttachmentLockWatchdog() { delete m_pTimer; }
|
|
|
|
/*
|
|
* Member functions
|
|
*/
|
|
protected:
|
|
// NOTE: detach does *not* respect attachment locks so use with care
|
|
void detach(const LLViewerObject* pAttachObj);
|
|
void detach(S32 idxAttachPt, const LLViewerObject* pAttachObjExcept = NULL);
|
|
|
|
void startTimer() { if (!m_pTimer) m_pTimer = new RlvAttachmentLockWatchdogTimer(this); }
|
|
|
|
/*
|
|
* Event handlers
|
|
*/
|
|
public:
|
|
void onAttach(const LLViewerObject* pAttachObj, const LLViewerJointAttachment* pAttachPt);
|
|
void onDetach(const LLViewerObject* pAttachObj, const LLViewerJointAttachment* pAttachPt);
|
|
void onSavedAssetIntoInventory(const LLUUID& idItem);
|
|
BOOL onTimer();
|
|
void onWearAttachment(const LLInventoryItem* pItem, ERlvWearMask eWearAction);
|
|
void onWearAttachment(const LLUUID& idItem, ERlvWearMask eWearAction);
|
|
|
|
/*
|
|
* Member variables
|
|
*/
|
|
protected:
|
|
typedef std::list<LLUUID> rlv_detach_map_t;
|
|
rlv_detach_map_t m_PendingDetach;
|
|
|
|
struct RlvReattachInfo
|
|
{
|
|
RlvReattachInfo(const LLUUID& itemid) : idItem(itemid), fAssetSaved(false), tsAttach(0)
|
|
{ tsDetach = LLFrameTimer::getElapsedSeconds(); }
|
|
|
|
LLUUID idItem;
|
|
bool fAssetSaved;
|
|
F64 tsDetach;
|
|
F64 tsAttach;
|
|
protected:
|
|
RlvReattachInfo();
|
|
};
|
|
typedef std::multimap<S32, RlvReattachInfo> rlv_attach_map_t;
|
|
rlv_attach_map_t m_PendingAttach;
|
|
|
|
struct RlvWearInfo
|
|
{
|
|
RlvWearInfo(const LLUUID& itemid, ERlvWearMask wearaction) : idItem(itemid), eWearAction(wearaction)
|
|
{ tsWear = LLFrameTimer::getElapsedSeconds(); }
|
|
|
|
bool isAddLockedAttachPt(S32 idxAttachPt) const;
|
|
void dumpInstance() const;
|
|
|
|
LLUUID idItem;
|
|
ERlvWearMask eWearAction;
|
|
F64 tsWear;
|
|
std::map<S32, uuid_vec_t> attachPts;
|
|
protected:
|
|
RlvWearInfo();
|
|
};
|
|
typedef std::map<LLUUID, RlvWearInfo> rlv_wear_map_t;
|
|
rlv_wear_map_t m_PendingWear;
|
|
|
|
class RlvAttachmentLockWatchdogTimer : public LLEventTimer
|
|
{
|
|
public:
|
|
RlvAttachmentLockWatchdogTimer(RlvAttachmentLockWatchdog* pWatchdog) : LLEventTimer(10), m_pWatchdog(pWatchdog) {}
|
|
virtual ~RlvAttachmentLockWatchdogTimer() { m_pWatchdog->m_pTimer = NULL; }
|
|
virtual BOOL tick() { return m_pWatchdog->onTimer(); }
|
|
RlvAttachmentLockWatchdog* m_pWatchdog;
|
|
} *m_pTimer;
|
|
};
|
|
|
|
// ============================================================================
|
|
// RlvWearableLocks class declaration - modelled on RlvAttachmentLocks (attach pt = wearable type - attachment = wearable)
|
|
//
|
|
|
|
class RlvWearableLocks
|
|
{
|
|
public:
|
|
// Adds an eLock type lock (held by idRlvObj) for the wearable type
|
|
void addWearableTypeLock(EWearableType eType, const LLUUID& idRlvObj, ERlvLockMask eLock);
|
|
|
|
// Returns TRUE if there is at least 1 non-removable wearable currently worn on this wearable type
|
|
bool hasLockedWearable(EWearableType eType) const;
|
|
// Returns TRUE if there is at least 1 eLock type locked wearable type (RLV_LOCK_ANY = RLV_LOCK_ADD *or* RLV_LOCK_REMOVE)
|
|
// - RLV_LOCK_REMOVE: specific wearable locked *or* any wearable type locked (regardless of whether it currently has wearables)
|
|
bool hasLockedWearableType(ERlvLockMask eLock) const;
|
|
|
|
// Removes an eLock type lock (held by idRlvObj) for the wearable type
|
|
void removeWearableTypeLock(EWearableType eType, const LLUUID& idRlvObj, ERlvLockMask eLock);
|
|
|
|
// Returns TRUE if the wearable is RLV_LOCK_REMOVE locked
|
|
bool isLockedWearable(const LLWearable* pWearable) const;
|
|
// Returns TRUE if the wearable is RLV_LOCK_REMOVE locked by anything other than idRlvObj
|
|
bool isLockedWearableExcept(const LLWearable* pWearable, const LLUUID& idRlvObj) const;
|
|
|
|
// NOTE: isLockedWearableType doesn't check if a worn wearable is a specific wearable lock so don't let these be called by the outside
|
|
protected:
|
|
// Returns TRUE if the wearable type is eLock type locked
|
|
bool isLockedWearableType(EWearableType eType, ERlvLockMask eLock) const;
|
|
// Returns TRUE if the wearable type is eLock type locked by anything other than idRlvObj
|
|
bool isLockedWearableTypeExcept(EWearableType eType, ERlvLockMask eLock, const LLUUID& idRlvObj) const;
|
|
|
|
/*
|
|
* canWear/canRemove trivial helper functions (note that a more approriate name might be userCanWear/userCanRemove)
|
|
*/
|
|
public:
|
|
// Returns whether the inventory item can be worn by the user
|
|
ERlvWearMask canWear(const LLViewerInventoryItem* pItem) const;
|
|
// Returns whether the wearable type can be worn to by the user
|
|
ERlvWearMask canWear(EWearableType eType) const;
|
|
|
|
// Returns TRUE if the inventory item can be removed by the user
|
|
bool canRemove(const LLInventoryItem* pItem) const;
|
|
// Returns TRUE if the wearable type has at least one wearable that can be removed by the user
|
|
bool canRemove(EWearableType eType) const;
|
|
|
|
/*
|
|
* Member variables
|
|
*/
|
|
public:
|
|
typedef std::multimap<EWearableType, LLUUID> rlv_wearabletypelock_map_t;
|
|
// Accessors for RlvFloaterLocks
|
|
const rlv_wearabletypelock_map_t& getWearableTypeLocks(ERlvLockMask eLock) { return (RLV_LOCK_ADD == eLock) ? m_WearableTypeAdd : m_WearableTypeRem; }
|
|
protected:
|
|
rlv_wearabletypelock_map_t m_WearableTypeAdd;
|
|
rlv_wearabletypelock_map_t m_WearableTypeRem;
|
|
};
|
|
|
|
extern RlvWearableLocks gRlvWearableLocks;
|
|
|
|
// ============================================================================
|
|
// RlvAttachPtLookup inlined member functions
|
|
//
|
|
|
|
// Checked: 2010-03-03 (RLVa-1.1.3a) | Modified: RLVa-0.2.0d
|
|
inline LLViewerJointAttachment* RlvAttachPtLookup::getAttachPoint(const std::string& strText)
|
|
{
|
|
return (gAgent.getAvatarObject()) ? get_if_there(gAgent.getAvatarObject()->mAttachmentPoints, getAttachPointIndex(strText), (LLViewerJointAttachment*)NULL) : NULL;
|
|
}
|
|
|
|
// Checked: 2010-03-03 (RLVa-1.1.3a) | Modified: RLVa-1.0.1b
|
|
inline LLViewerJointAttachment* RlvAttachPtLookup::getAttachPoint(const LLInventoryItem* pItem)
|
|
{
|
|
return (gAgent.getAvatarObject()) ? get_if_there(gAgent.getAvatarObject()->mAttachmentPoints, getAttachPointIndex(pItem), (LLViewerJointAttachment*)NULL) : NULL;
|
|
}
|
|
|
|
// Checked: 2010-03-03 (RLVa-1.2.0a) | Modified: RLVa-1.2.0a
|
|
inline S32 RlvAttachPtLookup::getAttachPointIndex(std::string strText)
|
|
{
|
|
LLStringUtil::toLower(strText);
|
|
RLV_ASSERT(m_AttachPtLookupMap.size() > 0);
|
|
std::map<std::string, S32>::const_iterator itAttachPt = m_AttachPtLookupMap.find(strText);
|
|
return (itAttachPt != m_AttachPtLookupMap.end()) ? itAttachPt->second : 0;
|
|
}
|
|
|
|
// Checked: 2010-03-03 (RLVa-1.2.0a) | Modified: RLVa-0.2.0d
|
|
inline S32 RlvAttachPtLookup::getAttachPointIndex(const LLViewerObject* pObj)
|
|
{
|
|
return (pObj) ? ATTACHMENT_ID_FROM_STATE(pObj->getState()) : 0;
|
|
}
|
|
|
|
// ============================================================================
|
|
// RlvAttachmentLocks inlined member functions
|
|
//
|
|
|
|
// Checked: 2010-08-07 (RLVa-1.2.0i) | Modified: RLVa-1.2.0i
|
|
inline ERlvWearMask RlvAttachmentLocks::canAttach(const LLInventoryItem* pItem, LLViewerJointAttachment** ppAttachPtOut /*=NULL*/) const
|
|
{
|
|
// The specified item can be attached if:
|
|
// - it doesn't specify an attachment point
|
|
// - the attachment point it specifies can be attached to
|
|
LLViewerJointAttachment* pAttachPt = RlvAttachPtLookup::getAttachPoint(pItem);
|
|
if (ppAttachPtOut)
|
|
*ppAttachPtOut = pAttachPt;
|
|
return (!pAttachPt) ? RLV_WEAR : canAttach(pAttachPt);
|
|
}
|
|
|
|
// Checked: 2010-08-07 (RLVa-1.2.0i) | Modified: RLVa-1.2.0i
|
|
inline ERlvWearMask RlvAttachmentLocks::canAttach(const LLViewerJointAttachment* pAttachPt) const
|
|
{
|
|
// Non-attachable attachment point => RLV_WEAR_LOCKED
|
|
// One or more locked attachment(s) => RLV_WEAR_ADD
|
|
// Unlocked attachment(s) => RLV_WEAR_ADD | RLV_WEAR_REPLACE
|
|
// Empty attachment point => RLV_WEAR_ADD | RLV_WEAR_REPLACE
|
|
RLV_ASSERT(pAttachPt); // TODO-RLVa: [RLVa-1.2.1] Maybe it's better to just return something similar like above?
|
|
return
|
|
(ERlvWearMask)(((pAttachPt) && (!isLockedAttachmentPoint(pAttachPt, RLV_LOCK_ADD)))
|
|
? ((canDetach(pAttachPt, true)) ? RLV_WEAR_REPLACE : 0) | RLV_WEAR_ADD
|
|
: RLV_WEAR_LOCKED);
|
|
}
|
|
|
|
// Checked: 2010-02-28 (RLVa-1.2.0a) | Added: RLVa-1.0.5a
|
|
inline bool RlvAttachmentLocks::canDetach(const LLInventoryItem* pItem) const
|
|
{
|
|
const LLViewerObject* pAttachObj =
|
|
((pItem) && (gAgent.getAvatarObject())) ? gAgent.getAvatarObject()->getWornAttachment(pItem->getLinkedUUID()) : NULL;
|
|
return (pAttachObj) && (!isLockedAttachment(pAttachObj));
|
|
}
|
|
|
|
// Checked: 2010-02-28 (RLVa-1.2.0a) | Modified: RLVa-1.2.0a
|
|
inline bool RlvAttachmentLocks::hasLockedAttachmentPoint(ERlvLockMask eLock) const
|
|
{
|
|
// Remove locks are more common so check those first
|
|
return
|
|
( (eLock & RLV_LOCK_REMOVE) && ((!m_AttachPtRem.empty()) || (!m_AttachObjRem.empty())) ) ||
|
|
( (eLock & RLV_LOCK_ADD) && (!m_AttachPtAdd.empty()) );
|
|
}
|
|
|
|
// Checked: 2010-02-28 (RLVa-1.2.0a) | Modified: RLVa-1.2.0a
|
|
inline bool RlvAttachmentLocks::isLockedAttachment(const LLViewerObject* pObj) const
|
|
{
|
|
// If pObj is valid then it should always specify a root since we store root UUIDs in m_AttachObjRem
|
|
RLV_ASSERT( (!pObj) || (pObj == pObj->getRootEdit()) );
|
|
|
|
// Object is locked if:
|
|
// - it's specifically marked as non-detachable (ie @detach=n)
|
|
// - it's attached to an attachment point that is RLV_LOCK_REMOVE locked (ie @remattach:<attachpt>=n)
|
|
return
|
|
(pObj) && (pObj->isAttachment()) &&
|
|
( (m_AttachObjRem.find(pObj->getID()) != m_AttachObjRem.end()) ||
|
|
(isLockedAttachmentPoint(RlvAttachPtLookup::getAttachPointIndex(pObj), RLV_LOCK_REMOVE)) );
|
|
}
|
|
|
|
// Checked: 2010-02-28 (RLVa-1.2.0a) | Added: RLVa-1.0.5a
|
|
inline bool RlvAttachmentLocks::isLockedAttachmentPoint(S32 idxAttachPt, ERlvLockMask eLock) const
|
|
{
|
|
return
|
|
( (eLock & RLV_LOCK_REMOVE) && (m_AttachPtRem.find(idxAttachPt) != m_AttachPtRem.end()) ) ||
|
|
( (eLock & RLV_LOCK_ADD) && (m_AttachPtAdd.find(idxAttachPt) != m_AttachPtAdd.end()) );
|
|
}
|
|
|
|
// Checked: 2010-02-28 (RLVa-1.2.0a) | Modified: RLVa-1.2.0a
|
|
inline bool RlvAttachmentLocks::isLockedAttachmentPoint(const LLViewerJointAttachment* pAttachPt, ERlvLockMask eLock) const
|
|
{
|
|
return (pAttachPt) && (isLockedAttachmentPoint(RlvAttachPtLookup::getAttachPointIndex(pAttachPt), eLock));
|
|
}
|
|
|
|
// ============================================================================
|
|
// RlvAttachmentLockWatchdog inlined member functions
|
|
//
|
|
|
|
// Checked: 2010-08-07 (RLVa-1.2.0i) | Added: RLVa-1.2.0i
|
|
inline void RlvAttachmentLockWatchdog::onWearAttachment(const LLInventoryItem* pItem, ERlvWearMask eWearAction)
|
|
{
|
|
onWearAttachment(pItem->getLinkedUUID(), eWearAction);
|
|
}
|
|
|
|
// ============================================================================
|
|
// RlvWearableLocks inlined member functions
|
|
//
|
|
|
|
// Checked: 2010-03-19 (RLVa-1.1.3b) | Added: RLVa-1.2.0a
|
|
inline bool RlvWearableLocks::canRemove(const LLInventoryItem* pItem) const
|
|
{
|
|
// The specified item can be removed if its wearable can be removed
|
|
RLV_ASSERT( (pItem) && (LLInventoryType::IT_WEARABLE == pItem->getInventoryType()) );
|
|
const LLWearable* pWearable = (pItem) ? gAgentWearables.getWearableFromItemID(pItem->getLinkedUUID()) : NULL;
|
|
return (pWearable) && (!isLockedWearable(pWearable));
|
|
}
|
|
|
|
// Checked: 2010-05-14 (RLVa-1.2.0g) | Modified: RLVa-1.2.0g
|
|
inline ERlvWearMask RlvWearableLocks::canWear(const LLViewerInventoryItem* pItem) const
|
|
{
|
|
// The specified item can be worn if the wearable type it specifies can be worn on
|
|
RLV_ASSERT( (pItem) && (LLInventoryType::IT_WEARABLE == pItem->getInventoryType()) );
|
|
return (pItem) ? canWear(pItem->getWearableType()) : RLV_WEAR_LOCKED;
|
|
}
|
|
|
|
// Checked: 2010-05-14 (RLVa-1.2.0g) | Modified: RLVa-1.2.0g
|
|
inline ERlvWearMask RlvWearableLocks::canWear(EWearableType eType) const
|
|
{
|
|
// The specified wearable type can be worn on if:
|
|
// - the wearable type itself isn't RLV_LOCK_ADD locked => RLV_WEAR_ADD
|
|
// (and there are less than the maximum amount currently worn)
|
|
// - it doesn't have any non-removable wearables => RLV_WEAR_REPLACE | RLV_WEAR_ADD = RLV_WEAR
|
|
// TODO-RLVa: [RLVa-1.2.1] We don't have the ability to lock a specific wearable yet so rewrite this when we do
|
|
return (!isLockedWearableType(eType, RLV_LOCK_ADD))
|
|
? ((!hasLockedWearable(eType)) ? RLV_WEAR_REPLACE : RLV_WEAR_LOCKED)
|
|
: RLV_WEAR_LOCKED;
|
|
}
|
|
|
|
// Checked: 2010-03-18 (RLVa-1.2.0c) | Modified: RLVa-1.2.0a
|
|
inline bool RlvWearableLocks::hasLockedWearableType(ERlvLockMask eLock) const
|
|
{
|
|
// Remove locks are more common so check those first
|
|
// TODO-RLVa: [RLVa-1.2.1] We don't have the ability to lock a specific wearable yet so rewrite this when we do
|
|
return ( (eLock & RLV_LOCK_REMOVE) && (!m_WearableTypeRem.empty()) ) || ( (eLock & RLV_LOCK_ADD) && (!m_WearableTypeAdd.empty()) );
|
|
}
|
|
|
|
// Checked: 2010-03-19 (RLVa-1.2.0c) | Added: RLVa-1.2.0a
|
|
inline bool RlvWearableLocks::isLockedWearable(const LLWearable* pWearable) const
|
|
{
|
|
// Wearable is locked if:
|
|
// - it's specifically marked as non-removable
|
|
// - it's worn on a wearable type that is RLV_LOCK_REMOVE locked
|
|
// TODO-RLVa: [RLVa-1.2.1] We don't have the ability to lock a specific wearable yet so rewrite this when we do
|
|
RLV_ASSERT(pWearable);
|
|
return (pWearable) && (isLockedWearableType(pWearable->getType(), RLV_LOCK_REMOVE));
|
|
}
|
|
|
|
// Checked: 2010-03-19 (RLVa-1.2.0c) | Added: RLVa-1.2.0a
|
|
inline bool RlvWearableLocks::isLockedWearableType(EWearableType eType, ERlvLockMask eLock) const
|
|
{
|
|
return
|
|
( (eLock & RLV_LOCK_REMOVE) && (m_WearableTypeRem.find(eType) != m_WearableTypeRem.end()) ) ||
|
|
( (eLock & RLV_LOCK_ADD) && (m_WearableTypeAdd.find(eType) != m_WearableTypeAdd.end()) );
|
|
}
|
|
|
|
// ============================================================================
|
|
|
|
#endif // RLV_LOCKS_H
|