diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index edd4632a5d037ebb6b30992244e344dbfb8318b5..b9995022d409805c84ed63cd56bca8e8973d04cb 100644
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -1927,7 +1927,7 @@ void LLAppearanceMgr::updateCOF(LLInventoryModel::item_array_t& body_items_new,
 								LLInventoryModel::item_array_t& wear_items_new, 
 								LLInventoryModel::item_array_t& obj_items_new,
 								LLInventoryModel::item_array_t& gest_items_new,
-								bool append /*=false*/, const LLUUID& idOutfit /*=LLUUID::null*/)
+								bool append /*=false*/, const LLUUID& idOutfit /*=LLUUID::null*/, LLPointer<LLInventoryCallback> link_waiter /*= NULL*/)
 // [/RLVa:KB]
 {
 //	LLViewerInventoryCategory *pcat = gInventory.getCategory(category);
@@ -2056,7 +2056,11 @@ void LLAppearanceMgr::updateCOF(LLInventoryModel::item_array_t& body_items_new,
 
 	// Will link all the above items.
 	// link_waiter enforce flags are false because we've already fixed everything up in updateCOF().
-	LLPointer<LLInventoryCallback> link_waiter = new LLUpdateAppearanceOnDestroy(false,false);
+//	LLPointer<LLInventoryCallback> link_waiter = new LLUpdateAppearanceOnDestroy(false,false);
+// [RLVa:KB] Checked: 2015-05-05 (RLVa-1.4.12)
+	if (!link_waiter)
+		link_waiter = new LLUpdateAppearanceOnDestroy(false, false);
+// [/RLVa:KB]
 	LLSD contents = LLSD::emptyArray();
 
 	for (LLInventoryModel::item_array_t::const_iterator it = all_items.begin();
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index f87ea549a75c14a05a132cfa76e55177fbc02d44..9c168c38eec08d6c11d1d5e66d699f2447ee418f 100644
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -59,7 +59,7 @@ class LLAppearanceMgr: public LLSingleton<LLAppearanceMgr>
 // [RLVa:KB] - Checked: 2010-03-05 (RLVa-1.2.0a) | Added: RLVa-1.2.0a
 	void updateCOF(LLInventoryModel::item_array_t& body_items_new, LLInventoryModel::item_array_t& wear_items_new,
 				   LLInventoryModel::item_array_t& obj_items_new, LLInventoryModel::item_array_t& gest_items_new,
-				   bool append = false, const LLUUID& idOutfit = LLUUID::null);
+				   bool append = false, const LLUUID& idOutfit = LLUUID::null, LLPointer<LLInventoryCallback> link_waiter = NULL);
 // [/RLVa:KB]
 	void wearInventoryCategory(LLInventoryCategory* category, bool copy, bool append);
 	void wearInventoryCategoryOnAvatar(LLInventoryCategory* category, bool append);
diff --git a/indra/newview/rlvhelper.cpp b/indra/newview/rlvhelper.cpp
index 92d363c49cc3ca2c1479ee990618c85644911f84..c36a5f0fc345433cfc8d22d12f6a1f956c180f9e 100644
--- a/indra/newview/rlvhelper.cpp
+++ b/indra/newview/rlvhelper.cpp
@@ -888,7 +888,35 @@ void RlvForceWear::remWearable(const LLViewerWearable* pWearable)
 		m_remWearables.push_back(pWearable);
 }
 
-// Checked: 2010-09-18 (RLVa-1.2.1)
+// Checked: 2015-05-05 (RLVa-1.4.12)
+void RlvForceWear::updatePendingAttachments()
+{
+	if (RlvForceWear::instanceExists())
+	{
+		RlvForceWear* pThis = RlvForceWear::getInstance();
+		for (const pendingattachments_map_t::value_type& itAttach : pThis->m_pendingAttachments)
+			LLAttachmentsMgr::instance().addAttachment(itAttach.first, itAttach.second & ~ATTACHMENT_ADD, itAttach.second & ATTACHMENT_ADD);
+		pThis->m_pendingAttachments.clear();
+	}
+}
+
+// Checked: 2015-05-05 (RLVa-1.4.12)
+void RlvForceWear::addPendingAttachment(const LLUUID& idItem, U8 idxPoint)
+{
+	auto itAttach = m_pendingAttachments.find(idItem);
+	if (m_pendingAttachments.end() == itAttach)
+		m_pendingAttachments.insert(std::make_pair(idItem, idxPoint));
+	else
+		itAttach->second = idxPoint;
+}
+
+// Checked: 2015-05-05 (RLVa-1.4.12)
+void RlvForceWear::remPendingAttachment(const LLUUID& idItem)
+{
+	m_pendingAttachments.erase(idItem);
+}
+
+// Checked: 2015-05-05 (RLVa-1.4.12)
 void RlvForceWear::done()
 {
 	// Sanity check - don't go through all the motions below only to find out there's nothing to actually do
@@ -898,41 +926,35 @@ void RlvForceWear::done()
 		return;
 	}
 
-	LLAppearanceMgr* pAppearanceMgr = LLAppearanceMgr::getInstance();
-	
 	//
 	// Process removals
 	//
 
+	uuid_vec_t remItems;
+
 	// Wearables
 	if (m_remWearables.size())
 	{
-		for (std::list<const LLViewerWearable*>::const_iterator itWearable = m_remWearables.begin(); itWearable != m_remWearables.end(); ++itWearable)
-			pAppearanceMgr->removeItemFromAvatar((*itWearable)->getItemID());
+		for (const LLViewerWearable* pWearable : m_remWearables)
+			remItems.push_back(pWearable->getItemID());
 		m_remWearables.clear();
 	}
 
 	// Gestures
 	if (m_remGestures.size())
 	{
-		// NOTE: LLGestureMgr::deactivateGesture() will call LLAppearanceMgr::removeCOFItemLinks() for us
-		for (S32 idxItem = 0, cntItem = m_remGestures.size(); idxItem < cntItem; idxItem++)
-			LLGestureMgr::instance().deactivateGesture(m_remGestures.at(idxItem)->getUUID());
+		// NOTE: LLGestureMgr::deactivateGesture() will call LLAppearanceMgr::removeCOFItemLinks() for us and supply its own callback
+		for (const LLViewerInventoryItem* pItem : m_remGestures)
+			LLGestureMgr::instance().deactivateGesture(pItem->getUUID());
 		m_remGestures.clear();
 	}
 
 	// Attachments
 	if (m_remAttachments.size())
 	{
-		// Don't bother with COF if all we're doing is detaching some attachments (keeps people from rebaking on every @remattach=force)
 		LLAgentWearables::userRemoveMultipleAttachments(m_remAttachments);
-
-		for (std::vector<LLViewerObject*>::const_iterator itAttachObj = m_remAttachments.begin(); 
-				itAttachObj != m_remAttachments.end(); ++itAttachObj)
-		{
-			pAppearanceMgr->removeCOFItemLinks((*itAttachObj)->getAttachmentItemID());
-		}
-
+		for (const LLViewerObject* pAttachObj : m_remAttachments)
+			remItems.push_back(pAttachObj->getAttachmentItemID());
 		m_remAttachments.clear();
 	}
 
@@ -942,50 +964,51 @@ void RlvForceWear::done()
 
 	// Wearables need to be split into AT_BODYPART and AT_CLOTHING for COF
 	LLInventoryModel::item_array_t addBodyParts, addClothing;
-	for (addwearables_map_t::const_iterator itAddWearables = m_addWearables.begin(); itAddWearables != m_addWearables.end(); ++itAddWearables)
+	for (addwearables_map_t::const_iterator itAddWearables = m_addWearables.cbegin(); itAddWearables != m_addWearables.cend(); ++itAddWearables)
 	{
-		const LLInventoryModel::item_array_t& wearItems = itAddWearables->second;
-		for (S32 idxItem = 0, cntItem = wearItems.size(); idxItem < cntItem; idxItem++)
+		// NOTE: LLAppearanceMgr will filter our duplicates so no need for us to check here
+		for (LLViewerInventoryItem* pItem : itAddWearables->second)
 		{
-			LLViewerInventoryItem* pItem = wearItems.at(idxItem);
-			if (!pAppearanceMgr->isLinkInCOF(pItem->getUUID()))		// It's important to examine COF here and *not* gAgentWearables
-			{
-				if (LLAssetType::AT_BODYPART == pItem->getType())
-					addBodyParts.push_back(pItem);
-				else
-					addClothing.push_back(pItem);
-			}
+			if (LLAssetType::AT_BODYPART == pItem->getType())
+				addBodyParts.push_back(pItem);
+			else
+				addClothing.push_back(pItem);
 		}
 	}
 	m_addWearables.clear();
 
 	// Until LL provides a way for updateCOF to selectively attach add/replace we have to deal with attachments ourselves
-	for (addattachments_map_t::const_iterator itAddAttachments = m_addAttachments.begin(); 
-			itAddAttachments != m_addAttachments.end(); ++itAddAttachments)
+	for (addattachments_map_t::const_iterator itAddAttachments = m_addAttachments.cbegin(); itAddAttachments != m_addAttachments.cend(); ++itAddAttachments)
 	{
-		const LLInventoryModel::item_array_t& wearItems = itAddAttachments->second;
-		for (S32 idxItem = 0, cntItem = wearItems.size(); idxItem < cntItem; idxItem++)
-		{
-			const LLUUID& idItem = wearItems.at(idxItem)->getLinkedUUID();
-			if (gAgentAvatarp->attachmentWasRequested(idItem))
-				continue;
-			gAgentAvatarp->addAttachmentRequest(idItem);
-
-			LLAttachmentsMgr::instance().addAttachment(idItem, itAddAttachments->first & ~ATTACHMENT_ADD, itAddAttachments->first & ATTACHMENT_ADD);
-		}
+		for (const LLViewerInventoryItem* pItem : itAddAttachments->second)
+			addPendingAttachment(pItem->getLinkedUUID(), itAddAttachments->first);
 	}
 	m_addAttachments.clear();
 
-	// If there are additions we need to call LLAppearanceManager::updateCOF(), otherwise LLAppearanceManager::updateAppearanceFromCOF()
+	//
+	// Tie it all together
+	//
+
+	//          |    Wearables    |   Attachments    |   Gestures      |
+	//          |======================================================|
+	// Add    : | LLAppearanceMgr | <custom>         | LLAppearanceMgr |
+	// Remove : | LLAppearanceMgr | LLAppearanceMgr  | LLGestureMgr    |
+	LLPointer<LLInventoryCallback> cb = new LLUpdateAppearanceOnDestroy(false, false, boost::bind(RlvForceWear::updatePendingAttachments));
+
+	if (!remItems.empty())
+	{
+		LLAppearanceMgr::instance().removeItemsFromAvatar(remItems, cb, true);
+	}
+
 	if ( (!addBodyParts.empty()) || (!addClothing.empty()) || (!m_addGestures.empty()) )
 	{
 		LLInventoryModel::item_array_t addAttachments;
-		pAppearanceMgr->updateCOF(addBodyParts, addClothing, addAttachments, m_addGestures, true);
+		LLAppearanceMgr::instance().updateCOF(addBodyParts, addClothing, addAttachments, m_addGestures, true, LLUUID::null, cb);
 
 		m_addGestures.clear();
 	}
 
-	// Since RlvForceWear is a singleton now we want to be sure there aren't any leftovers
+	// Make sure there are no leftovers for the next cycle
 	RLV_ASSERT( (m_remWearables.empty()) && (m_remAttachments.empty()) && (m_remGestures.empty()) );
 	RLV_ASSERT( (m_addWearables.empty()) && (m_addAttachments.empty()) && (m_addGestures.empty()) );
 }
diff --git a/indra/newview/rlvhelper.h b/indra/newview/rlvhelper.h
index b97e4a8cb671407b4d248e6844f81f035098de1d..2d935f80e84469b8bc4a1513d2191d802903322b 100644
--- a/indra/newview/rlvhelper.h
+++ b/indra/newview/rlvhelper.h
@@ -276,6 +276,15 @@ class RlvForceWear : public LLSingleton<RlvForceWear>
 		return std::find(m_remWearables.begin(), m_remWearables.end(), pWearable) != m_remWearables.end();
 	}
 
+	/*
+	 * Pending attachments
+	 */
+public:
+	static void updatePendingAttachments();
+protected:
+	void addPendingAttachment(const LLUUID& idItem, U8 idxPoint);
+	void remPendingAttachment(const LLUUID& idItem);
+
 protected:
 	typedef std::pair<LLWearableType::EType, LLInventoryModel::item_array_t> addwearable_pair_t;
 	typedef std::map<LLWearableType::EType, LLInventoryModel::item_array_t> addwearables_map_t;
@@ -288,6 +297,9 @@ class RlvForceWear : public LLSingleton<RlvForceWear>
 	std::list<const LLViewerWearable*> m_remWearables;
 	LLInventoryModel::item_array_t   m_remGestures;
 
+	typedef std::map<LLUUID, U8> pendingattachments_map_t;
+	pendingattachments_map_t         m_pendingAttachments;
+
 private:
 	friend class LLSingleton<RlvForceWear>;
 };