Loading...   

  • Created By Uleat On: 04:52 PM October 02, 2014
  • Link

 common/Item.cpp        | 149 +++++++++++++++++++++++++++++++
 common/Item.h          |  20 +++++
 common/shareddb.cpp    | 108 ++++++++++++----------
 common/shareddb.h      |   4 +-
 world/worlddb.cpp      |  58 ++++++------
 zone/bot.cpp           | 236 +++++++++++++++++++++++++------------------------
 zone/bot.h             |   3 +
 zone/client.cpp        | 125 ++++++++++----------------
 zone/client.h          |   4 +-
 zone/client_packet.cpp |  12 ++-
 zone/command.cpp       |   2 +
 zone/corpse.cpp        |  45 +++++-----
 zone/corpse.h          |   2 +
 zone/inventory.cpp     | 101 +++++++++++++--------
 zone/merc.cpp          |   6 ++
 zone/mob.cpp           |  94 +++++++++++---------
 zone/mob.h             |   6 +-
 zone/npc.cpp           |  49 +++++-----
 zone/npc.h             |   4 +-
 19 files changed, 630 insertions(+), 398 deletions(-)

diff --git a/common/Item.cpp b/common/Item.cpp
index 82e3b51..e7d2681 100644
--- a/common/Item.cpp
+++ b/common/Item.cpp
@@ -56,6 +56,7 @@ static inline int32 GetNextItemInstSerialNumber() {
 ItemInst::ItemInst(const Item_Struct* item, int16 charges) {
 	m_use_type = ItemInstNormal;
 	m_item = item;
+	m_ornament = nullptr;
 	m_charges = charges;
 	m_price = 0;
 	m_instnodrop = false;
@@ -78,6 +79,7 @@ ItemInst::ItemInst(const Item_Struct* item, int16 charges) {
 ItemInst::ItemInst(SharedDatabase *db, uint32 item_id, int16 charges) {
 	m_use_type = ItemInstNormal;
 	m_item = db->GetItem(item_id);
+	m_ornament = nullptr;
 	m_charges = charges;
 	m_price = 0;
 	m_merchantslot = 0;
@@ -157,6 +159,7 @@ ItemInst::ItemInst(const ItemInst& copy)
 {
 	m_use_type=copy.m_use_type;
 	m_item=copy.m_item;
+	m_ornament=copy.m_ornament;
 	m_charges=copy.m_charges;
 	m_price=copy.m_price;
 	m_color=copy.m_color;
@@ -295,6 +298,152 @@ int8 ItemInst::AvailableAugmentSlot(int32 augtype) const
 	return (i<5) ? i : -1;
 }
 
+bool ItemInst::TransformItem(SharedDatabase *db, uint32 ornament_id) {
+	if((m_item == nullptr) || (m_item->ItemClass != ItemClassCommon))
+		return false;
+
+	if((ornament_id == 0) || (m_ornament != nullptr) || (db == nullptr))
+		return false;
+
+	if((m_ornament = db->GetItem(ornament_id)) == nullptr)
+		return false;
+
+	if(m_ornament->BagType != BagTypeTransformationmold) {
+		m_ornament = nullptr;
+		return false;
+	}
+
+	return true;
+}
+
+bool ItemInst::TransformItem(const Item_Struct* ornament) {
+	if((m_item == nullptr) || (m_item->ItemClass != ItemClassCommon))
+		return false;
+
+	if((ornament == nullptr) || (m_ornament != nullptr))
+		return false;
+
+	if(ornament->BagType != BagTypeTransformationmold)
+		return false;
+
+	m_ornament = ornament;
+	return true;
+}
+
+const Item_Struct* ItemInst::DetransformItem() {
+	if((m_item == nullptr) || (m_item->ItemClass != ItemClassCommon)) {
+		m_ornament = nullptr;
+		return nullptr;
+	}
+
+	const Item_Struct* ornament = m_ornament;
+	m_ornament = nullptr;
+
+	return ornament;
+}
+
+const Item_Struct* ItemInst::GetVisibleItem() const {
+	if(m_item == nullptr)
+		return nullptr;
+
+	if(m_ornament != nullptr)
+		return m_ornament;
+
+	for(uint8 augiter = 0; augiter < MAX_AUGMENT_SLOTS; ++augiter) {
+		ItemInst* auginst = GetAugment(augiter);
+
+		if(auginst && (auginst->GetItem()->AugType & ((uint32)1 << 19)))
+			return auginst->GetItem();
+	}
+
+	return m_item;
+}
+
+uint32 ItemInst::GetVisibleItemID() const {
+	if(m_item == nullptr)
+		return 0;
+
+	return GetVisibleItem()->ID;
+}
+
+uint32 ItemInst::GetVisibleMaterial(bool weapon) const {
+	if(m_item == nullptr)
+		return 0;
+
+	const Item_Struct* item = GetVisibleItem();
+
+	if(weapon) {
+		uint32 material = (uint32)atoul(&item->IDFile[2]);
+
+		if((material == 0) || (material == 63)) { // 63 is 'small bag' - we should send the base IDFile||material instead
+			material = (uint32)atoul(&m_item->IDFile[2]);
+
+			if((material == 0) || (material == 63))
+				return m_item->Material;
+			else
+				return material;
+		}
+		else {
+			return material;
+		}
+	}
+	else {
+		// if armor graphics ever use 'idfile' we'll need to update this
+		return item->Material;
+	}
+}
+
+uint32 ItemInst::GetVisibleColor(bool weapon) const {
+	if(m_item == nullptr)
+		return 0;
+
+	const Item_Struct* item = GetVisibleItem();
+
+	if(weapon) {
+		uint32 material = (uint32)atoul(&item->IDFile[2]);
+
+		if((material == 0) || (material == 63)) {
+			material = (uint32)atoul(&m_item->IDFile[2]);
+
+			if((material == 0) || (material == 63))
+				return 0;
+			else
+				return m_item->Color;
+		}
+		else {
+			return item->Color;
+		}
+	}
+	else {
+		if(m_color && (m_color != item->Color) && (m_color != m_item->Color))
+			return m_color;
+		else
+			return item->Color;
+	}
+}
+
+uint32 ItemInst::IsVisibleEliteMaterial(bool weapon) const {
+	if(m_item == nullptr)
+		return 0;
+
+	const Item_Struct* item = GetVisibleItem();
+
+	if(weapon) {
+		// if weapons use this, just dump the if-else check and 'return item->EliteMaterial;'
+		return 0;
+	}
+	else {
+		return item->EliteMaterial;
+	}
+}
+
+/*
+bool ItemInst::IsVisibleHeroicMaterial() const {
+	// not implemented
+	// (find the commit that added this code to get an idea of what needs to be updated)
+}
+*/
+
 bool ItemInst::AvailableWearSlot(uint32 aug_wear_slots) const
 {
 	if (m_item->ItemClass != ItemClassCommon || !m_item)
diff --git a/common/Item.h b/common/Item.h
index d62d92b..c806e9e 100644
--- a/common/Item.h
+++ b/common/Item.h
@@ -268,6 +268,7 @@ public:
 	ItemInst(ItemInstTypes use_type) {
 		m_use_type = use_type;
 		m_item = nullptr;
+		m_ornament = nullptr;
 		m_charges = 0;
 		m_price = 0;
 		m_instnodrop = false;
@@ -298,6 +299,24 @@ public:
 	bool IsEquipable(int16 slot_id) const;
 
 	//
+	// Ornaments (bag-type)
+	//
+	bool IsOrnamented() const { return (m_ornament != nullptr); }
+	const Item_Struct* GetOrnament() const { return m_ornament; }
+	const uint32 GetOrnamentID() const { return(m_ornament ? m_ornament->ID : 0); }
+	bool TransformItem(SharedDatabase* db, uint32 ornament_id);
+	bool TransformItem(const Item_Struct* ornament);
+	const Item_Struct* DetransformItem();
+
+	// Visible Item
+	const Item_Struct* GetVisibleItem() const;
+	uint32 GetVisibleItemID() const;
+	uint32 GetVisibleMaterial(bool weapon = false) const;
+	uint32 GetVisibleColor(bool weapon = false) const;
+	uint32 IsVisibleEliteMaterial(bool weapon = false) const;
+	bool IsVisibleHeroicMaterial() const { return false; } // not implemented (I think that I read augtype 21 = heroic)
+
+	//
 	// Augements
 	//
 	inline bool IsAugmentable() const { return m_item->AugSlotType[0]!=0 || m_item->AugSlotType[1]!=0 || m_item->AugSlotType[2]!=0 || m_item->AugSlotType[3]!=0 || m_item->AugSlotType[4]!=0; }
@@ -426,6 +445,7 @@ protected:
 
 	ItemInstTypes		m_use_type;	// Usage type for item
 	const Item_Struct*	m_item;		// Ptr to item data
+	const Item_Struct*	m_ornament;	// Ptr to bag-type ornament data
 	int16				m_charges;	// # of charges for chargeable items
 	uint32				m_price;	// Bazaar /trader price
 	uint32				m_color;
diff --git a/common/shareddb.cpp b/common/shareddb.cpp
index a49cec4..e9be78c 100644
--- a/common/shareddb.cpp
+++ b/common/shareddb.cpp
@@ -51,7 +51,7 @@ bool SharedDatabase::SetHideMe(uint32 account_id, uint8 hideme)
 	char *query = 0;
 
 	if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE account SET hideme = %i where id = %i", hideme, account_id), errbuf)) {
-		std::cerr << "Error in SetGMSpeed query '" << query << "' " << errbuf << std::endl;
+		std::cerr << "Error in SetHideMe query '" << query << "' " << errbuf << std::endl;
 		safe_delete_array(query);
 		return false;
 	}
@@ -204,6 +204,7 @@ bool SharedDatabase::SaveInventory(uint32 char_id, const ItemInst* inst, int16 s
 	char errbuf[MYSQL_ERRMSG_SIZE];
 	char* query = 0;
 	bool ret = false;
+	uint32 ornament_id = 0;
 	uint32 augslot[5] = { 0, 0, 0, 0, 0 };
 
 	//never save tribute slots:
@@ -211,6 +212,8 @@ bool SharedDatabase::SaveInventory(uint32 char_id, const ItemInst* inst, int16 s
 		return(true);
 
 	if (inst && inst->IsType(ItemClassCommon)) {
+		ornament_id = inst->GetOrnamentID();
+
 		for(int i=0;i<5;i++) {
 			ItemInst *auginst=inst->GetItem(i);
 			augslot[i]=(auginst && auginst->GetItem()) ? auginst->GetItem()->ID : 0;
@@ -247,12 +250,12 @@ bool SharedDatabase::SaveInventory(uint32 char_id, const ItemInst* inst, int16 s
 
 			uint32 len_query = MakeAnyLenString(&query,
 				"REPLACE INTO sharedbank "
-				"	(acctid,slotid,itemid,charges,custom_data,"
+				"	(acctid,slotid,itemid,charges,custom_data,ornamentid,"
 				"	augslot1,augslot2,augslot3,augslot4,augslot5)"
-				" VALUES(%lu,%lu,%lu,%lu,'%s',"
+				" VALUES(%lu,%lu,%lu,%lu,'%s',%lu,"
 				"	%lu,%lu,%lu,%lu,%lu)",
 				(unsigned long)account_id, (unsigned long)slot_id, (unsigned long)inst->GetItem()->ID, (unsigned long)charges,
-				inst->GetCustomDataString().c_str(),
+				inst->GetCustomDataString().c_str(), (unsigned long)ornament_id,
 				(unsigned long)augslot[0],(unsigned long)augslot[1],(unsigned long)augslot[2],(unsigned long)augslot[3],(unsigned long)augslot[4]);
 
 
@@ -284,12 +287,12 @@ bool SharedDatabase::SaveInventory(uint32 char_id, const ItemInst* inst, int16 s
 			// Update/Insert item
 			uint32 len_query = MakeAnyLenString(&query,
 				"REPLACE INTO inventory "
-				"	(charid,slotid,itemid,charges,instnodrop,custom_data,color,"
+				"	(charid,slotid,itemid,charges,instnodrop,custom_data,color,ornamentid,"
 				"	augslot1,augslot2,augslot3,augslot4,augslot5)"
-				" VALUES(%lu,%lu,%lu,%lu,%lu,'%s',%lu,"
+				" VALUES(%lu,%lu,%lu,%lu,%lu,'%s',%lu,%lu,"
 				"	%lu,%lu,%lu,%lu,%lu)",
 				(unsigned long)char_id, (unsigned long)slot_id, (unsigned long)inst->GetItem()->ID, (unsigned long)charges,
-				(unsigned long)(inst->IsInstNoDrop() ? 1:0),inst->GetCustomDataString().c_str(),(unsigned long)inst->GetColor(),
+				(unsigned long)(inst->IsInstNoDrop() ? 1:0),inst->GetCustomDataString().c_str(),(unsigned long)inst->GetColor(),(unsigned long)ornament_id,
 				(unsigned long)augslot[0],(unsigned long)augslot[1],(unsigned long)augslot[2],(unsigned long)augslot[3],(unsigned long)augslot[4] );
 
 			ret = RunQuery(query, len_query, errbuf);
@@ -416,26 +419,27 @@ bool SharedDatabase::GetSharedBank(uint32 id, Inventory* inv, bool is_charid) {
 
 	if (is_charid) {
 		len_query = MakeAnyLenString(&query,
-			"SELECT sb.slotid,sb.itemid,sb.charges,sb.augslot1,sb.augslot2,sb.augslot3,sb.augslot4,sb.augslot5,sb.custom_data from sharedbank sb "
+			"SELECT sb.slotid,sb.itemid,sb.charges,sb.ornamentid,sb.augslot1,sb.augslot2,sb.augslot3,sb.augslot4,sb.augslot5,sb.custom_data from sharedbank sb "
 			"INNER JOIN character_ ch ON ch.account_id=sb.acctid "
 			"WHERE ch.id=%i", id);
 	}
 	else {
 		len_query = MakeAnyLenString(&query,
-			"SELECT slotid,itemid,charges,augslot1,augslot2,augslot3,augslot4,augslot5,custom_data from sharedbank WHERE acctid=%i", id);
+			"SELECT slotid,itemid,charges,ornamentid,augslot1,augslot2,augslot3,augslot4,augslot5,custom_data from sharedbank WHERE acctid=%i", id);
 	}
 
 	if (RunQuery(query, len_query, errbuf, &result)) {
 		while ((row = mysql_fetch_row(result))) {
-			int16 slot_id	= (int16)atoi(row[0]);
-			uint32 item_id	= (uint32)atoi(row[1]);
-			int8 charges	= (int8)atoi(row[2]);
+			int16 slot_id		= (int16)atoi(row[0]);
+			uint32 item_id		= (uint32)atoul(row[1]);
+			int8 charges		= (int8)atoi(row[2]);
+			uint32 ornament_id	= (uint32)atoul(row[3]);
 			uint32 aug[5];
-			aug[0]	= (uint32)atoi(row[3]);
-			aug[1]	= (uint32)atoi(row[4]);
-			aug[2]	= (uint32)atoi(row[5]);
-			aug[3]	= (uint32)atoi(row[6]);
-			aug[4]	= (uint32)atoi(row[7]);
+			aug[0]	= (uint32)atoul(row[4]);
+			aug[1]	= (uint32)atoul(row[5]);
+			aug[2]	= (uint32)atoul(row[6]);
+			aug[3]	= (uint32)atoul(row[7]);
+			aug[4]	= (uint32)atoul(row[8]);
 			const Item_Struct* item = GetItem(item_id);
 
 			if (item) {
@@ -443,14 +447,16 @@ bool SharedDatabase::GetSharedBank(uint32 id, Inventory* inv, bool is_charid) {
 
 				ItemInst* inst = CreateBaseItem(item, charges);
 				if (item->ItemClass == ItemClassCommon) {
+					if(ornament_id)
+						inst->TransformItem(this, ornament_id);
 					for(int i=0;i<5;i++) {
 						if (aug[i]) {
 							inst->PutAugment(this, i, aug[i]);
 						}
 					}
 				}
-				if(row[8]) {
-					std::string data_str(row[8]);
+				if(row[9]) {
+					std::string data_str(row[9]);
 					std::string id;
 					std::string value;
 					bool use_id = true;
@@ -516,21 +522,22 @@ bool SharedDatabase::GetInventory(uint32 char_id, Inventory* inv) {
 	bool ret = false;
 
 	// Retrieve character inventory
-	if (RunQuery(query, MakeAnyLenString(&query, "SELECT slotid,itemid,charges,color,augslot1,augslot2,augslot3,augslot4,augslot5,"
+	if (RunQuery(query, MakeAnyLenString(&query, "SELECT slotid,itemid,charges,color,ornamentid,augslot1,augslot2,augslot3,augslot4,augslot5,"
 		"instnodrop,custom_data FROM inventory WHERE charid=%i ORDER BY slotid", char_id), errbuf, &result)) {
 
 		while ((row = mysql_fetch_row(result))) {
-			int16 slot_id	= atoi(row[0]);
-			uint32 item_id	= atoi(row[1]);
-			uint16 charges	= atoi(row[2]);
-			uint32 color		= atoul(row[3]);
+			int16 slot_id		= atoi(row[0]);
+			uint32 item_id		= (uint32)atoul(row[1]);
+			uint16 charges		= atoi(row[2]);
+			uint32 color		= (uint32)atoul(row[3]);
+			uint32 ornament_id	= (uint32)atoul(row[4]);
 			uint32 aug[5];
-			aug[0]	= (uint32)atoul(row[4]);
-			aug[1]	= (uint32)atoul(row[5]);
-			aug[2]	= (uint32)atoul(row[6]);
-			aug[3]	= (uint32)atoul(row[7]);
-			aug[4]	= (uint32)atoul(row[8]);
-			bool instnodrop	= (row[9] && (uint16)atoi(row[9])) ? true : false;
+			aug[0]	= (uint32)atoul(row[5]);
+			aug[1]	= (uint32)atoul(row[6]);
+			aug[2]	= (uint32)atoul(row[7]);
+			aug[3]	= (uint32)atoul(row[8]);
+			aug[4]	= (uint32)atoul(row[9]);
+			bool instnodrop	= (row[10] && (uint16)atoi(row[10])) ? true : false;
 
 			const Item_Struct* item = GetItem(item_id);
 
@@ -539,8 +546,8 @@ bool SharedDatabase::GetInventory(uint32 char_id, Inventory* inv) {
 
 				ItemInst* inst = CreateBaseItem(item, charges);
 
-				if(row[10]) {
-					std::string data_str(row[10]);
+				if(row[11]) {
+					std::string data_str(row[11]);
 					std::string id;
 					std::string value;
 					bool use_id = true;
@@ -575,6 +582,8 @@ bool SharedDatabase::GetInventory(uint32 char_id, Inventory* inv) {
 					inst->SetCharges(charges);
 
 				if (item->ItemClass == ItemClassCommon) {
+					if(ornament_id)
+						inst->TransformItem(this, ornament_id);
 					for(int i=0;i<5;i++) {
 						if (aug[i]) {
 							inst->PutAugment(this, i, aug[i]);
@@ -624,22 +633,23 @@ bool SharedDatabase::GetInventory(uint32 account_id, char* name, Inventory* inv)
 	bool ret = false;
 
 	// Retrieve character inventory
-	if (RunQuery(query, MakeAnyLenString(&query, "SELECT slotid,itemid,charges,color,augslot1,augslot2,augslot3,augslot4,augslot5,"
+	if (RunQuery(query, MakeAnyLenString(&query, "SELECT slotid,itemid,charges,color,ornamentid,augslot1,augslot2,augslot3,augslot4,augslot5,"
 		"instnodrop,custom_data FROM inventory INNER JOIN character_ ch ON ch.id=charid WHERE ch.name='%s' AND ch.account_id=%i ORDER BY slotid",
 		name, account_id), errbuf, &result))
 	{
 		while ((row = mysql_fetch_row(result))) {
-			int16 slot_id	= atoi(row[0]);
-			uint32 item_id	= atoi(row[1]);
-			int8 charges	= atoi(row[2]);
-			uint32 color		= atoul(row[3]);
+			int16 slot_id		= atoi(row[0]);
+			uint32 item_id		= (uint32)atoul(row[1]);
+			int8 charges		= atoi(row[2]);
+			uint32 color		= (uint32)atoul(row[3]);
+			uint32 ornament_id	= (uint32)atoul(row[4]);
 			uint32 aug[5];
-			aug[0]	= (uint32)atoi(row[4]);
-			aug[1]	= (uint32)atoi(row[5]);
-			aug[2]	= (uint32)atoi(row[6]);
-			aug[3]	= (uint32)atoi(row[7]);
-			aug[4]	= (uint32)atoi(row[8]);
-			bool instnodrop	= (row[9] && (uint16)atoi(row[9])) ? true : false;
+			aug[0]	= (uint32)atoul(row[5]);
+			aug[1]	= (uint32)atoul(row[6]);
+			aug[2]	= (uint32)atoul(row[7]);
+			aug[3]	= (uint32)atoul(row[8]);
+			aug[4]	= (uint32)atoul(row[9]);
+			bool instnodrop	= (row[10] && (uint16)atoi(row[10])) ? true : false;
 			const Item_Struct* item = GetItem(item_id);
 			int16 put_slot_id = SLOT_INVALID;
 			if(!item)
@@ -648,8 +658,8 @@ bool SharedDatabase::GetInventory(uint32 account_id, char* name, Inventory* inv)
 			ItemInst* inst = CreateBaseItem(item, charges);
 			inst->SetInstNoDrop(instnodrop);
 
-			if(row[10]) {
-				std::string data_str(row[10]);
+			if(row[11]) {
+				std::string data_str(row[11]);
 				std::string id;
 				std::string value;
 				bool use_id = true;
@@ -679,6 +689,8 @@ bool SharedDatabase::GetInventory(uint32 account_id, char* name, Inventory* inv)
 			inst->SetCharges(charges);
 
 			if (item->ItemClass == ItemClassCommon) {
+				if(ornament_id)
+					inst->TransformItem(this, ornament_id);
 				for(int i=0;i<5;i++) {
 					if (aug[i]) {
 						inst->PutAugment(this, i, aug[i]);
@@ -1297,7 +1309,7 @@ uint32 SharedDatabase::SetPlayerProfile_MQ(char** query, uint32 account_id, uint
 
 
 // Create appropriate ItemInst class
-ItemInst* SharedDatabase::CreateItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5)
+ItemInst* SharedDatabase::CreateItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, uint32 orn)
 {
 	const Item_Struct* item = nullptr;
 	ItemInst* inst = nullptr;
@@ -1309,6 +1321,7 @@ ItemInst* SharedDatabase::CreateItem(uint32 item_id, int16 charges, uint32 aug1,
 		inst->PutAugment(this, 2, aug3);
 		inst->PutAugment(this, 3, aug4);
 		inst->PutAugment(this, 4, aug5);
+		inst->TransformItem(this, orn);
 	}
 
 	return inst;
@@ -1316,7 +1329,7 @@ ItemInst* SharedDatabase::CreateItem(uint32 item_id, int16 charges, uint32 aug1,
 
 
 // Create appropriate ItemInst class
-ItemInst* SharedDatabase::CreateItem(const Item_Struct* item, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5)
+ItemInst* SharedDatabase::CreateItem(const Item_Struct* item, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, uint32 orn)
 {
 	ItemInst* inst = nullptr;
 	if (item) {
@@ -1326,6 +1339,7 @@ ItemInst* SharedDatabase::CreateItem(const Item_Struct* item, int16 charges, uin
 		inst->PutAugment(this, 2, aug3);
 		inst->PutAugment(this, 3, aug4);
 		inst->PutAugment(this, 4, aug5);
+		inst->TransformItem(this, orn);
 	}
 
 	return inst;
diff --git a/common/shareddb.h b/common/shareddb.h
index 05c3db6..bf72e1d 100644
--- a/common/shareddb.h
+++ b/common/shareddb.h
@@ -71,8 +71,8 @@ public:
 	/*
 	* Item Methods
 	*/
-	ItemInst* CreateItem(uint32 item_id, int16 charges=0, uint32 aug1=0, uint32 aug2=0, uint32 aug3=0, uint32 aug4=0, uint32 aug5=0);
-	ItemInst* CreateItem(const Item_Struct* item, int16 charges=0, uint32 aug1=0, uint32 aug2=0, uint32 aug3=0, uint32 aug4=0, uint32 aug5=0);
+	ItemInst* CreateItem(uint32 item_id, int16 charges=0, uint32 aug1=0, uint32 aug2=0, uint32 aug3=0, uint32 aug4=0, uint32 aug5=0, uint32 orn=0);
+	ItemInst* CreateItem(const Item_Struct* item, int16 charges=0, uint32 aug1=0, uint32 aug2=0, uint32 aug3=0, uint32 aug4=0, uint32 aug5=0, uint32 orn=0);
 	ItemInst* CreateBaseItem(const Item_Struct* item, int16 charges=0);
 
 	/*
diff --git a/world/worlddb.cpp b/world/worlddb.cpp
index ab8f609..0c3fe91 100644
--- a/world/worlddb.cpp
+++ b/world/worlddb.cpp
@@ -178,36 +178,44 @@ void WorldDatabase::GetCharSelectInfo(uint32 account_id, CharacterSelect_Struct*
 				// NOTE: items don't have a color, players MAY have a tint, if the
 				// use_tint part is set. otherwise use the regular color
 				inv = new Inventory;
-				if(GetInventory(account_id, cs->name[char_num], inv))
-				{
-					for (uint8 material = 0; material <= 8; material++)
-					{
-						uint32 color;
-						ItemInst *item = inv->GetItem(Inventory::CalcSlotFromMaterial(material));
-						if(item == 0)
-							continue;
-
-						cs->equip[char_num][material] = item->GetItem()->Material;
 
-						if(pp->item_tint[material].rgb.use_tint)	// they have a tint (LoY dye)
-							color = pp->item_tint[material].color;
-						else	// no tint, use regular item color
-							color = item->GetItem()->Color;
+				if(GetInventory(account_id, cs->name[char_num], inv)) {
+					ItemInst* inst = nullptr;
 
-						cs->cs_colors[char_num][material].color = color;
+					for(uint8 matiter = MaterialHead; matiter < _MaterialCount; ++matiter) {
+						if(matiter == MaterialWrist)
+							continue;
 
-						// the weapons are kept elsewhere
-						if ((material==MaterialPrimary) || (material==MaterialSecondary))
-						{
-							if(strlen(item->GetItem()->IDFile) > 2) {
-								uint32 idfile=atoi(&item->GetItem()->IDFile[2]);
-								if (material==MaterialPrimary)
-									cs->primary[char_num]=idfile;
-								else
-									cs->secondary[char_num]=idfile;
-							}
+						if(inst = inv->GetItem(Inventory::CalcSlotFromMaterial(matiter))) {
+							cs->equip[char_num][matiter] = inst->GetVisibleMaterial();
+						
+							if(pp->item_tint[matiter].rgb.use_tint)
+								cs->cs_colors[char_num][matiter].color = pp->item_tint[matiter].color;
+							else
+								cs->cs_colors[char_num][matiter].color = inst->GetVisibleColor();
 						}
 					}
+
+					// not sure why both 'cs->equip' and 'cs->primary/secondary' are set..but, it's easy to do
+					if(inst = inv->GetItem(SLOT_PRIMARY)) {
+						cs->primary[char_num] = inst->GetVisibleMaterial(true);
+						cs->cs_colors[char_num][MaterialPrimary].color = inst->GetVisibleColor(true);
+					}
+
+					if(inst = inv->GetItem(SLOT_SECONDARY)) {
+						cs->secondary[char_num] = inst->GetVisibleMaterial(true);
+						cs->cs_colors[char_num][MaterialSecondary].color = inst->GetVisibleColor(true);
+					}
+
+					// this check gives SLOT_BRACER01 priority, if it is present
+					if((inst = inv->GetItem(SLOT_BRACER01)) || (inst = inv->GetItem(SLOT_BRACER02))) {
+						cs->equip[char_num][MaterialWrist] = inst->GetVisibleMaterial();
+
+						if(pp->item_tint[MaterialWrist].rgb.use_tint)
+							cs->cs_colors[char_num][MaterialWrist].color = pp->item_tint[MaterialWrist].color;
+						else
+							cs->cs_colors[char_num][MaterialWrist].color = inst->GetVisibleColor();
+ 					}
 				}
 				else
 				{
diff --git a/zone/bot.cpp b/zone/bot.cpp
index 1526bed..242c995 100644
--- a/zone/bot.cpp
+++ b/zone/bot.cpp
@@ -4347,10 +4347,12 @@ void Bot::Spawn(Client* botCharacterOwner, std::string* errorMessage) {
 void Bot::SetBotItemInSlot(uint32 slotID, uint32 itemID, const ItemInst* inst, std::string *errorMessage) {
 	char errbuf[MYSQL_ERRMSG_SIZE];
 	char *query = 0;
+	uint32 ornament_id = 0;
 	uint32 augslot[5] = { 0, 0, 0, 0, 0 };
 
 	if(this->GetBotID() > 0 && slotID >= 0 && itemID > 0) {
 		if (inst && inst->IsType(ItemClassCommon)) {
+			ornament_id = inst->GetOrnamentID();
 			for(int i=0; i<5; ++i) {
 				ItemInst* auginst = inst->GetItem(i);
 				augslot[i] = (auginst && auginst->GetItem()) ? auginst->GetItem()->ID : 0;
@@ -4358,11 +4360,11 @@ void Bot::SetBotItemInSlot(uint32 slotID, uint32 itemID, const ItemInst* inst, s
 		}
 		if(!database.RunQuery(query, MakeAnyLenString(&query,
 			"REPLACE INTO botinventory "
-			"	(botid,slotid,itemid,charges,instnodrop,color,"
+			"	(botid,slotid,itemid,charges,instnodrop,color,ornamentid,"
 			"	augslot1,augslot2,augslot3,augslot4,augslot5)"
-			" VALUES(%lu,%lu,%lu,%lu,%lu,%lu,"
+			" VALUES(%lu,%lu,%lu,%lu,%lu,%lu,%lu,"
 			"	%lu,%lu,%lu,%lu,%lu)",
-			(unsigned long)this->GetBotID(), (unsigned long)slotID, (unsigned long)itemID, (unsigned long)inst->GetCharges(), (unsigned long)(inst->IsInstNoDrop() ? 1:0),(unsigned long)inst->GetColor(),
+			(unsigned long)this->GetBotID(), (unsigned long)slotID, (unsigned long)itemID, (unsigned long)inst->GetCharges(), (unsigned long)(inst->IsInstNoDrop() ? 1:0),(unsigned long)inst->GetColor(),(unsigned long)ornament_id,
 			(unsigned long)augslot[0],(unsigned long)augslot[1],(unsigned long)augslot[2],(unsigned long)augslot[3],(unsigned long)augslot[4]), errbuf)) {
 				*errorMessage = std::string(errbuf);
 		}
@@ -4394,21 +4396,22 @@ void Bot::GetBotItems(std::string* errorMessage, Inventory &inv) {
 		MYSQL_RES* DatasetResult;
 		MYSQL_ROW DataRow;
 
-		if(database.RunQuery(query, MakeAnyLenString(&query, "SELECT slotid,itemid,charges,color,augslot1,augslot2,augslot3,augslot4,augslot5,instnodrop FROM botinventory WHERE botid=%i order by slotid", this->GetBotID()), errbuf, &DatasetResult)) {
+		if(database.RunQuery(query, MakeAnyLenString(&query, "SELECT slotid,itemid,charges,color,ornamentid,augslot1,augslot2,augslot3,augslot4,augslot5,instnodrop FROM botinventory WHERE botid=%i order by slotid", this->GetBotID()), errbuf, &DatasetResult)) {
 			while(DataRow = mysql_fetch_row(DatasetResult)) {
-				int16 slot_id	= atoi(DataRow[0]);
-				uint32 item_id	= atoi(DataRow[1]);
-				uint16 charges	= atoi(DataRow[2]);
-				uint32 color	= atoul(DataRow[3]);
+				int16 slot_id		= atoi(DataRow[0]);
+				uint32 item_id		= (uint32)atoul(DataRow[1]);
+				uint16 charges		= atoi(DataRow[2]);
+				uint32 color		= (uint32)atoul(DataRow[3]);
+				uint32 ornament_id	= (uint32)atoul(DataRow[4]);
 				uint32 aug[5];
-				aug[0] = (uint32)atoul(DataRow[4]);
-				aug[1] = (uint32)atoul(DataRow[5]);
-				aug[2] = (uint32)atoul(DataRow[6]);
-				aug[3] = (uint32)atoul(DataRow[7]);
-				aug[4] = (uint32)atoul(DataRow[8]);
-				bool instnodrop	= (DataRow[9] && (uint16)atoi(DataRow[9])) ? true : false;
-
-				ItemInst* inst = database.CreateItem(item_id, charges, aug[0], aug[1], aug[2], aug[3], aug[4]);
+				aug[0] = (uint32)atoul(DataRow[5]);
+				aug[1] = (uint32)atoul(DataRow[6]);
+				aug[2] = (uint32)atoul(DataRow[7]);
+				aug[3] = (uint32)atoul(DataRow[8]);
+				aug[4] = (uint32)atoul(DataRow[9]);
+				bool instnodrop	= (DataRow[10] && (uint16)atoi(DataRow[10])) ? true : false;
+
+				ItemInst* inst = database.CreateItem(item_id, charges, aug[0], aug[1], aug[2], aug[3], aug[4], ornament_id);
 				if(inst) {
 					int16 put_slot_id = SLOT_INVALID;
 					if(instnodrop || ((slot_id >= 0) && (slot_id <= 21) && inst->GetItem()->Attuneable))
@@ -4588,102 +4591,24 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) {
 		ns->spawn.helm = 0xFF;
 		ns->spawn.equip_chest2 = 0xFF;
 
-		const Item_Struct* item = 0;
-		const ItemInst* inst = 0;
-
 		uint32 spawnedbotid = 0;
 		spawnedbotid = this->GetBotID();
 
-		inst = GetBotItem(SLOT_HANDS);
-		if(inst) {
-			item = inst->GetItem();
-			if(item) {
-				ns->spawn.equipment[MaterialHands]	= item->Material;
-				ns->spawn.colors[MaterialHands].color = GetEquipmentColor(MaterialHands);
-			}
-		}
-
-		inst = GetBotItem(SLOT_HEAD);
-		if(inst) {
-			item = inst->GetItem();
-			if(item) {
-				ns->spawn.equipment[MaterialHead] = item->Material;
-				ns->spawn.colors[MaterialHead].color = GetEquipmentColor(MaterialHead);
-			}
-		}
+		const ItemInst* inst = nullptr;
 
-		inst = GetBotItem(SLOT_ARMS);
-		if(inst) {
-			item = inst->GetItem();
-			if(item) {
-				ns->spawn.equipment[MaterialArms] = item->Material;
-				ns->spawn.colors[MaterialArms].color = GetEquipmentColor(MaterialArms);
-			}
-		}
-
-		inst = GetBotItem(SLOT_BRACER01);
-		if(inst) {
-			item = inst->GetItem();
-			if(item) {
-				ns->spawn.equipment[MaterialWrist] = item->Material;
-				ns->spawn.colors[MaterialWrist].color	= GetEquipmentColor(MaterialWrist);
-			}
-		}
-
-		inst = GetBotItem(SLOT_BRACER02);
-		if(inst) {
-			item = inst->GetItem();
-			if(item) {
-				ns->spawn.equipment[MaterialWrist] = item->Material;
-				ns->spawn.colors[MaterialWrist].color	= GetEquipmentColor(MaterialWrist);
-			}
-		}
-
-		inst = GetBotItem(SLOT_CHEST);
-		if(inst) {
-			item = inst->GetItem();
-			if(item) {
-				ns->spawn.equipment[MaterialChest]	= item->Material;
-				ns->spawn.colors[MaterialChest].color = GetEquipmentColor(MaterialChest);
-			}
-		}
-
-		inst = GetBotItem(SLOT_LEGS);
-		if(inst) {
-			item = inst->GetItem();
-			if(item) {
-				ns->spawn.equipment[MaterialLegs] = item->Material;
-				ns->spawn.colors[MaterialLegs].color = GetEquipmentColor(MaterialLegs);
-			}
-		}
-
-		inst = GetBotItem(SLOT_FEET);
-		if(inst) {
-			item = inst->GetItem();
-			if(item) {
-				ns->spawn.equipment[MaterialFeet] = item->Material;
-				ns->spawn.colors[MaterialFeet].color = GetEquipmentColor(MaterialFeet);
-			}
-		}
+		for(uint8 matiter = MaterialHead; matiter < _MaterialCount; ++matiter) {
+			if(matiter == MaterialWrist)
+				continue;
 
-		inst = GetBotItem(SLOT_PRIMARY);
-		if(inst) {
-			item = inst->GetItem();
-			if(item) {
-				if(strlen(item->IDFile) > 2)
-					ns->spawn.equipment[MaterialPrimary] = atoi(&item->IDFile[2]);
-					ns->spawn.colors[MaterialPrimary].color = GetEquipmentColor(MaterialPrimary);
+			if(inst = m_inv.GetItem(m_inv.CalcSlotFromMaterial(matiter))) {
+				ns->spawn.equipment[matiter] = inst->GetVisibleMaterial((matiter == MaterialPrimary) || (matiter == MaterialSecondary));
+				ns->spawn.colors[matiter].color = inst->GetVisibleColor((matiter == MaterialPrimary) || (matiter == MaterialSecondary));
 			}
 		}
 
-		inst = GetBotItem(SLOT_SECONDARY);
-		if(inst) {
-			item = inst->GetItem();
-			if(item) {
-				if(strlen(item->IDFile) > 2)
-					ns->spawn.equipment[MaterialSecondary] = atoi(&item->IDFile[2]);
-					ns->spawn.colors[MaterialSecondary].color = GetEquipmentColor(MaterialSecondary);
-			}
+		if((inst = m_inv[SLOT_BRACER01]) || (inst = m_inv[SLOT_BRACER02])) {
+			ns->spawn.equipment[MaterialWrist] = inst->GetVisibleMaterial();
+			ns->spawn.colors[MaterialWrist].color = inst->GetVisibleColor();
 		}
 	}
 }
@@ -6045,6 +5970,8 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli
 				std::string TempErrorMessage;
 				const Item_Struct* mWeaponItem = inst->GetItem();
 				bool failedLoreCheck = false;
+				if(CheckLoreConflict(inst->GetOrnament()))
+					failedLoreCheck = true;
 				for(int m=0; m<MAX_AUGMENT_SLOTS; ++m) {
 					ItemInst *itm = inst->GetAugment(m);
 					if(itm)
@@ -16469,6 +16396,19 @@ uint8 Bot::GetNumberNeedingHealedInGroup(uint8 hpr, bool includePets) {
 	return needHealed;
 }
 
+uint32 Bot::GetEquipment(uint8 material_slot) const {
+	if(material_slot < _MaterialCount) {
+		int16 slot = Inventory::CalcSlotFromMaterial(material_slot);
+
+		const ItemInst* inst = m_inv.GetItem(slot);
+
+		if(inst)
+			return inst->GetID();
+ 	}
+
+ 	return 0;
+}
+
 uint32 Bot::GetEquipmentColor(uint8 material_slot) const
 {
 	//Bot tints
@@ -16476,23 +16416,85 @@ uint32 Bot::GetEquipmentColor(uint8 material_slot) const
 	uint32 returncolor = 0;
 	uint32 botid = this->GetBotID();
 
-	//Translate code slot # to DB slot #
-	slotid = Inventory::CalcSlotFromMaterial(material_slot);
+	if(material_slot < _MaterialCount) {
+		//Translate code slot # to DB slot #
+		slotid = Inventory::CalcSlotFromMaterial(material_slot);
 
-	//read from db
-	char* Query = 0;
-	MYSQL_RES* DatasetResult;
-	MYSQL_ROW DataRow;
+		if(material_slot > MaterialFeet) {
+			ItemInst* inst = m_inv.GetItem(slotid);
 
-	if(database.RunQuery(Query, MakeAnyLenString(&Query, "SELECT color FROM botinventory WHERE BotID = %u AND SlotID = %u", botid, slotid), 0, &DatasetResult)) {
-		if(mysql_num_rows(DatasetResult) == 1) {
-			DataRow = mysql_fetch_row(DatasetResult);
-			if(DataRow)
-				returncolor = atoul(DataRow[0]);
+			if(inst && inst->GetItem())
+				return inst->GetItem()->Color;
+		}
+		else {
+			//read from db
+			char* Query = 0;
+			MYSQL_RES* DatasetResult;
+			MYSQL_ROW DataRow;
+
+			if(database.RunQuery(Query, MakeAnyLenString(&Query, "SELECT color FROM botinventory WHERE BotID = %u AND SlotID = %u", botid, slotid), 0, &DatasetResult)) {
+				if(mysql_num_rows(DatasetResult) == 1) {
+					DataRow = mysql_fetch_row(DatasetResult);
+					if(DataRow)
+						returncolor = atoul(DataRow[0]);
+				}
+				mysql_free_result(DatasetResult);
+				safe_delete_array(Query);
+			}
 		}
-		mysql_free_result(DatasetResult);
-		safe_delete_array(Query);
 	}
+
+	return returncolor;
+}
+
+uint32 Bot::GetVisibleEquipment(uint8 material_slot) const {
+	if(material_slot < _MaterialCount) {
+		int16 slot = Inventory::CalcSlotFromMaterial(material_slot);
+
+		const ItemInst* inst = m_inv.GetItem(slot);
+
+		if(inst)
+			return inst->GetVisibleItemID();
+ 	}
+
+ 	return 0;
+}
+
+uint32 Bot::GetVisibleEquipmentColor(uint8 material_slot) const
+{
+	//Bot tints
+	uint32 slotid = 0;
+	uint32 returncolor = 0;
+	uint32 botid = this->GetBotID();
+
+	if(material_slot < _MaterialCount) {
+		//Translate code slot # to DB slot #
+		slotid = Inventory::CalcSlotFromMaterial(material_slot);
+
+		if(material_slot > MaterialFeet) {
+			ItemInst* inst = m_inv.GetItem(slotid);
+
+			if(inst && inst->GetItem())
+				return inst->GetVisibleColor(true);
+		}
+		else {
+			//read from db
+			char* Query = 0;
+			MYSQL_RES* DatasetResult;
+			MYSQL_ROW DataRow;
+
+			if(database.RunQuery(Query, MakeAnyLenString(&Query, "SELECT color FROM botinventory WHERE BotID = %u AND SlotID = %u", botid, slotid), 0, &DatasetResult)) {
+				if(mysql_num_rows(DatasetResult) == 1) {
+					DataRow = mysql_fetch_row(DatasetResult);
+					if(DataRow)
+						returncolor = atoul(DataRow[0]);
+				}
+				mysql_free_result(DatasetResult);
+				safe_delete_array(Query);
+			}
+		}
+	}
+
 	return returncolor;
 }
 
diff --git a/zone/bot.h b/zone/bot.h
index 485d373..6cf0c85 100644
--- a/zone/bot.h
+++ b/zone/bot.h
@@ -331,7 +331,10 @@ public:
 	void BotTradeAddItem(uint32 id, const ItemInst* inst, int16 charges, uint32 equipableSlots, uint16 lootSlot, std::string* errorMessage, bool addToDb = true);
 	void EquipBot(std::string* errorMessage);
 	bool CheckLoreConflict(const Item_Struct* item);
+	uint32 GetEquipment(uint8 material_slot) const;
 	uint32 GetEquipmentColor(uint8 material_slot) const;
+	uint32 GetVisibleEquipment(uint8 material_slot) const;
+	uint32 GetVisibleEquipmentColor(uint8 material_slot) const;
 
 	// Static Class Methods
 	static void SaveBotGroup(Group* botGroup, std::string botGroupName, std::string* errorMessage);
diff --git a/zone/client.cpp b/zone/client.cpp
index 827a3f3..d6b25d2 100644
--- a/zone/client.cpp
+++ b/zone/client.cpp
@@ -1864,57 +1864,21 @@ void Client::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho)
 
 	// pp also hold this info; should we pull from there or inventory?
 	// (update: i think pp should do it, as this holds LoY dye - plus, this is ugly code with Inventory!)
-	const Item_Struct* item = nullptr;
 	const ItemInst* inst = nullptr;
-	if ((inst = m_inv[SLOT_HANDS]) && inst->IsType(ItemClassCommon)) {
-		item = inst->GetItem();
-		ns->spawn.equipment[MaterialHands]	= item->Material;
-		ns->spawn.colors[MaterialHands].color	= GetEquipmentColor(MaterialHands);
-	}
-	if ((inst = m_inv[SLOT_HEAD]) && inst->IsType(ItemClassCommon)) {
-		item = inst->GetItem();
-		ns->spawn.equipment[MaterialHead]	= item->Material;
-		ns->spawn.colors[MaterialHead].color	= GetEquipmentColor(MaterialHead);
-	}
-	if ((inst = m_inv[SLOT_ARMS]) && inst->IsType(ItemClassCommon)) {
-		item = inst->GetItem();
-		ns->spawn.equipment[MaterialArms]	= item->Material;
-		ns->spawn.colors[MaterialArms].color	= GetEquipmentColor(MaterialArms);
-	}
-	if ((inst = m_inv[SLOT_BRACER01]) && inst->IsType(ItemClassCommon)) {
-		item = inst->GetItem();
-		ns->spawn.equipment[MaterialWrist]= item->Material;
-		ns->spawn.colors[MaterialWrist].color	= GetEquipmentColor(MaterialWrist);
-	}
-	if ((inst = m_inv[SLOT_BRACER02]) && inst->IsType(ItemClassCommon)) {
-		item = inst->GetItem();
-		ns->spawn.equipment[MaterialWrist]= item->Material;
-		ns->spawn.colors[MaterialWrist].color	= GetEquipmentColor(MaterialWrist);
-	}
-	if ((inst = m_inv[SLOT_CHEST]) && inst->IsType(ItemClassCommon)) {
-		item = inst->GetItem();
-		ns->spawn.equipment[MaterialChest]	= item->Material;
-		ns->spawn.colors[MaterialChest].color	= GetEquipmentColor(MaterialChest);
-	}
-	if ((inst = m_inv[SLOT_LEGS]) && inst->IsType(ItemClassCommon)) {
-		item = inst->GetItem();
-		ns->spawn.equipment[MaterialLegs]	= item->Material;
-		ns->spawn.colors[MaterialLegs].color	= GetEquipmentColor(MaterialLegs);
-	}
-	if ((inst = m_inv[SLOT_FEET]) && inst->IsType(ItemClassCommon)) {
-		item = inst->GetItem();
-		ns->spawn.equipment[MaterialFeet]	= item->Material;
-		ns->spawn.colors[MaterialFeet].color	= GetEquipmentColor(MaterialFeet);
-	}
-	if ((inst = m_inv[SLOT_PRIMARY]) && inst->IsType(ItemClassCommon)) {
-		item = inst->GetItem();
-		if (strlen(item->IDFile) > 2)
-			ns->spawn.equipment[MaterialPrimary] = atoi(&item->IDFile[2]);
-	}
-	if ((inst = m_inv[SLOT_SECONDARY]) && inst->IsType(ItemClassCommon)) {
-		item = inst->GetItem();
-		if (strlen(item->IDFile) > 2)
-			ns->spawn.equipment[MaterialSecondary] = atoi(&item->IDFile[2]);
+
+	for(uint8 matiter = MaterialHead; matiter < _MaterialCount; ++matiter) {
+		if(matiter == MaterialWrist)
+			continue;
+
+		if(inst = m_inv.GetItem(m_inv.CalcSlotFromMaterial(matiter))) { // removed the ItemClassCommon check
+			ns->spawn.equipment[matiter] = inst->GetVisibleMaterial((matiter == MaterialPrimary) || (matiter == MaterialSecondary));
+			ns->spawn.colors[matiter].color = inst->GetVisibleColor((matiter == MaterialPrimary) || (matiter == MaterialSecondary));
+		}
+	}
+
+	if((inst = m_inv[SLOT_BRACER01]) || (inst = m_inv[SLOT_BRACER02])) {
+		ns->spawn.equipment[MaterialWrist] = inst->GetVisibleMaterial();
+		ns->spawn.colors[MaterialWrist].color = inst->GetVisibleColor();
 	}
 
 	//these two may be related to ns->spawn.texture
@@ -2774,29 +2738,36 @@ bool Client::BindWound(Mob* bindmob, bool start, bool fail){
 	return true;
 }
 
-void Client::SetMaterial(int16 in_slot, uint32 item_id){
+void Client::SetMaterial(int16 in_slot, uint32 item_id) {
 	const Item_Struct* item = database.GetItem(item_id);
-	if (item && (item->ItemClass==ItemClassCommon)) {
-		if (in_slot==SLOT_HEAD)
-			m_pp.item_material[MaterialHead]		= item->Material;
-		else if (in_slot==SLOT_CHEST)
-			m_pp.item_material[MaterialChest]		= item->Material;
-		else if (in_slot==SLOT_ARMS)
-			m_pp.item_material[MaterialArms]		= item->Material;
-		else if (in_slot==SLOT_BRACER01)
-			m_pp.item_material[MaterialWrist]		= item->Material;
-		else if (in_slot==SLOT_BRACER02)
-			m_pp.item_material[MaterialWrist]		= item->Material;
-		else if (in_slot==SLOT_HANDS)
-			m_pp.item_material[MaterialHands]		= item->Material;
-		else if (in_slot==SLOT_LEGS)
-			m_pp.item_material[MaterialLegs]		= item->Material;
-		else if (in_slot==SLOT_FEET)
-			m_pp.item_material[MaterialFeet]		= item->Material;
-		else if (in_slot==SLOT_PRIMARY)
-			m_pp.item_material[MaterialPrimary]	= atoi(item->IDFile+2);
-		else if (in_slot==SLOT_SECONDARY)
-			m_pp.item_material[MaterialSecondary]	= atoi(item->IDFile+2);
+
+	if(item && (item->ItemClass == ItemClassCommon)) {
+		uint8 matslot = Inventory::CalcSlotFromMaterial(in_slot);
+		uint32 material = 0; // this is probably cheaper than scoping 'case MaterialSecondary:' and initializing there
+
+		switch(matslot) {
+		case MaterialHead:
+		case MaterialChest:
+		case MaterialArms:
+		case MaterialWrist:
+		case MaterialHands:
+		case MaterialLegs:
+		case MaterialFeet:
+			m_pp.item_material[matslot] = item->Material;
+			break;
+		case MaterialPrimary:
+		case MaterialSecondary:
+			material = (uint32)atoul(&item->IDFile[2]);
+			if((material == 0) || (material == 63))
+				// this really needs to match or call ItemInst::GetVisibleMaterial()...
+				// it would be better to pass an ItemInst here..but, that's not possible in all cases...
+				m_pp.item_material[matslot] = item->Material;
+			else
+				m_pp.item_material[matslot] = material;
+			break;
+		default:
+			break;
+		}
 	}
 }
 
@@ -6265,8 +6236,8 @@ void Client::Doppelganger(uint16 spell_id, Mob *target, const char *name_overrid
 	made_npc->PR = GetPR();
 	made_npc->Corrup = GetCorrup();
 	// looks
-	made_npc->texture = GetEquipmentMaterial(1);
-	made_npc->helmtexture = GetEquipmentMaterial(0);
+	made_npc->texture = GetVisibleEquipmentMaterial(1);
+	made_npc->helmtexture = GetVisibleEquipmentMaterial(0);
 	made_npc->haircolor = GetHairColor();
 	made_npc->beardcolor = GetBeardColor();
 	made_npc->eyecolor1 = GetEyeColor1();
@@ -6277,10 +6248,10 @@ void Client::Doppelganger(uint16 spell_id, Mob *target, const char *name_overrid
 	made_npc->drakkin_heritage = GetDrakkinHeritage();
 	made_npc->drakkin_tattoo = GetDrakkinTattoo();
 	made_npc->drakkin_details = GetDrakkinDetails();
-	made_npc->d_meele_texture1 = GetEquipmentMaterial(7);
-	made_npc->d_meele_texture2 = GetEquipmentMaterial(8);
+	made_npc->d_meele_texture1 = GetVisibleEquipmentMaterial(7);
+	made_npc->d_meele_texture2 = GetVisibleEquipmentMaterial(8);
 	for (int i = 0; i < _MaterialCount; i++)	{
-		made_npc->armor_tint[i] = GetEquipmentColor(i);
+		made_npc->armor_tint[i] = GetVisibleEquipmentColor(i);
 	}
 	made_npc->loottable_id = 0;
 
diff --git a/zone/client.h b/zone/client.h
index 76b2c67..4a65c2a 100644
--- a/zone/client.h
+++ b/zone/client.h
@@ -715,6 +715,8 @@ public:
 #endif
 	uint32 GetEquipment(uint8 material_slot) const;	// returns item id
 	uint32 GetEquipmentColor(uint8 material_slot) const;
+	uint32 GetVisibleEquipment(uint8 material_slot) const;	// returns visible item id
+	uint32 GetVisibleEquipmentColor(uint8 material_slot) const;
 
 	inline bool AutoSplitEnabled() { return m_pp.autosplit != 0; }
 
@@ -795,7 +797,7 @@ public:
 	void	QSSwapItemAuditor(MoveItem_Struct* move_in, bool postaction_call = false);
 	void	PutLootInInventory(int16 slot_id, const ItemInst &inst, ServerLootItem_Struct** bag_item_data = 0);
 	bool	AutoPutLootInInventory(ItemInst& inst, bool try_worn = false, bool try_cursor = true, ServerLootItem_Struct** bag_item_data = 0);
-	bool	SummonItem(uint32 item_id, int16 charges = -1, uint32 aug1=0, uint32 aug2=0, uint32 aug3=0, uint32 aug4=0, uint32 aug5=0, bool attuned=false, uint16 to_slot=SLOT_CURSOR);
+	bool	SummonItem(uint32 item_id, int16 charges = -1, uint32 aug1=0, uint32 aug2=0, uint32 aug3=0, uint32 aug4=0, uint32 aug5=0, bool attuned=false, uint16 to_slot=SLOT_CURSOR, uint32 orn=0);
 	void	SetStats(uint8 type,int16 set_val);
 	void	IncStats(uint8 type,int16 increase_val);
 	void	DropItem(int16 slot_id);
diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp
index cde2b14..a0ec049 100644
--- a/zone/client_packet.cpp
+++ b/zone/client_packet.cpp
@@ -3521,6 +3521,11 @@ void Client::Handle_OP_ChannelMessage(const EQApplicationPacket *app)
 
 void Client::Handle_OP_WearChange(const EQApplicationPacket *app)
 {
+	// This is a temporary modification until the new client ornamentation/augmentation packets are fully developed
+	// We are now ignoring wear change messages for everything but MaterialHead
+	// (Original behavior was to re-broadcast everything..but, I believe that only Head, Primary and Secondary
+	// were the only slots ever sent by the client. Otherwise, we have some duplicate/wasted broadcast time...)
+
 	if (app->size != sizeof(WearChange_Struct)) {
 		std::cout << "Wrong size: OP_WearChange, size=" << app->size << ", expected " << sizeof(WearChange_Struct) << std::endl;
 		return;
@@ -3530,8 +3535,11 @@ void Client::Handle_OP_WearChange(const EQApplicationPacket *app)
 	if(wc->spawn_id != GetID())
 		return;
 
-	// we could maybe ignore this and just send our own from moveitem
-	entity_list.QueueClients(this, app, true);
+	//if(wc->wear_slot_id == MaterialHead) {
+		// we could maybe ignore this and just send our own from moveitem
+		entity_list.QueueClients(this, app, true);
+	//}
+
 	return;
 }
 
diff --git a/zone/command.cpp b/zone/command.cpp
index 8c2192c..46863b6 100644
--- a/zone/command.cpp
+++ b/zone/command.cpp
@@ -6084,6 +6084,8 @@ void command_summonitem(Client *c, const Seperator *sep)
 			c->SummonItem(itemid, atoi(sep->arg[2]), atoi(sep->arg[3]), atoi(sep->arg[4]), atoi(sep->arg[5]), atoi(sep->arg[6]) );
 		else if (sep->argnum==7)
 			c->SummonItem(itemid, atoi(sep->arg[2]), atoi(sep->arg[3]), atoi(sep->arg[4]), atoi(sep->arg[5]), atoi(sep->arg[6]), atoi(sep->arg[7]) );
+		else if (sep->argnum==8)
+			c->SummonItem(itemid, atoi(sep->arg[2]), atoi(sep->arg[3]), atoi(sep->arg[4]), atoi(sep->arg[5]), atoi(sep->arg[6]), atoi(sep->arg[7]), false, 30, atoi(sep->arg[8]) );
 		else {
 			c->SummonItem(itemid);
 		}
diff --git a/zone/corpse.cpp b/zone/corpse.cpp
index 992649c..a969321 100644
--- a/zone/corpse.cpp
+++ b/zone/corpse.cpp
@@ -1977,39 +1977,42 @@ bool ZoneDatabase::DeletePlayerCorpse(uint32 dbid) {
 
 // these functions operate with a material slot, which is from 0 to 8
 uint32 Corpse::GetEquipment(uint8 material_slot) const {
-	int invslot;
+	if(material_slot < _MaterialCount) {
+		int16 inv_slot = Inventory::CalcSlotFromMaterial(material_slot);
 
-	if(material_slot > 8)
-	{
-		return 0;
+		if(inv_slot != SLOT_INVALID)
+			return GetWornItem(inv_slot);
 	}
 
-	invslot = Inventory::CalcSlotFromMaterial(material_slot);
-	if(invslot == -1)
-		return 0;
-
-	return GetWornItem(invslot);
+	return 0;
 }
 
 uint32 Corpse::GetEquipmentColor(uint8 material_slot) const {
-	const Item_Struct *item;
-
-	if(material_slot > 8)
-	{
-		return 0;
-	}
+	if(material_slot < _MaterialCount) {
+		const Item_Struct* item = database.GetItem(GetEquipment(material_slot));
 
-	item = database.GetItem(GetEquipment(material_slot));
-	if(item != 0)
-	{
-		return item_tint[material_slot].rgb.use_tint ?
-			item_tint[material_slot].color :
-			item->Color;
+		if(item != nullptr) {
+			if(material_slot > MaterialFeet)
+				return item->Color;
+			else
+				return item_tint[material_slot].rgb.use_tint ? item_tint[material_slot].color : item->Color;
+		}
 	}
 
 	return 0;
 }
 
+// These two will need to be reworked once augments and ornamentations are saved to the corpse
+uint32 Corpse::GetVisibleEquipment(uint8 material_slot) const {
+	// TODO: ...
+	return GetEquipment(material_slot);
+}
+
+uint32 Corpse::GetVisibleEquipmentColor(uint8 material_slot) const {
+	// TODO: ...
+	return GetEquipmentColor(material_slot);
+}
+
 void Corpse::AddLooter(Mob* who)
 {
 	for (int i=0; i<MAX_LOOTERS; i++)
diff --git a/zone/corpse.h b/zone/corpse.h
index b9999e7..f8eef60 100644
--- a/zone/corpse.h
+++ b/zone/corpse.h
@@ -109,6 +109,8 @@ public:
 	char		orgname[64];
 	uint32 GetEquipment(uint8 material_slot) const;	// returns item id
 	uint32 GetEquipmentColor(uint8 material_slot) const;
+	uint32 GetVisibleEquipment(uint8 material_slot) const;	// returns visible item id
+	uint32 GetVisibleEquipmentColor(uint8 material_slot) const;
 	inline int GetRezzExp() { return rezzexp; }
 
 protected:
diff --git a/zone/inventory.cpp b/zone/inventory.cpp
index 5292dd1..59cea1f 100644
--- a/zone/inventory.cpp
+++ b/zone/inventory.cpp
@@ -200,8 +200,9 @@ bool Client::CheckLoreConflict(const Item_Struct* item) {
 	return (m_inv.HasItemByLoreGroup(item->LoreGroup, ~invWhereSharedBank) != SLOT_INVALID);
 }
 
-bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, bool attuned, uint16 to_slot) {
+bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, bool attuned, uint16 to_slot, uint32 orn) {
 	// TODO: update calling methods and script apis to handle a failure return
+	// TODO: add bag-type ornament code/restrictions
 
 	const Item_Struct* item = database.GetItem(item_id);
 
@@ -547,6 +548,9 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2,
 		return false;
 	}
 
+	// add bag-style ornamentation
+	inst->TransformItem(&database, orn);
+
 	// add any validated augments
 	for(int iter = 0; iter < MAX_AUGMENT_SLOTS; ++iter) {
 		if(augments[iter])
@@ -1614,7 +1618,8 @@ bool Client::SwapItem(MoveItem_Struct* move_in) {
 					}
 				}
 			}
-			SetMaterial(dst_slot_id,src_inst->GetItem()->ID);
+			//SetMaterial(dst_slot_id,src_inst->GetItem()->ID);
+			SetMaterial(dst_slot_id, src_inst->GetVisibleItemID());
 		}
 		if(!m_inv.SwapItem(src_slot_id, dst_slot_id)) { return false; }
 		mlog(INVENTORY__SLOTS, "Moving entire item from slot %d to slot %d", src_slot_id, dst_slot_id);
@@ -1640,10 +1645,13 @@ bool Client::SwapItem(MoveItem_Struct* move_in) {
 		}
 	}
 
-	int matslot = SlotConvert2(dst_slot_id);
-	if (dst_slot_id<22 && matslot != 0) {
+	//int matslot = SlotConvert2(dst_slot_id);
+	uint8 matslot = Inventory::CalcMaterialFromSlot(dst_slot_id);
+
+	// this is a really hack'ish way of doing this... this whole system needs to be re-written :P
+	// this emulates the original condition..not updating the helm model.
+	if((uint16)dst_slot_id < 22 && ((matslot != _MaterialInvalid) && (matslot != 0)))
 		SendWearChange(matslot);
-	}
 
 	// Step 7: Save change to the database
 	if (src_slot_id==SLOT_CURSOR){
@@ -2167,30 +2175,17 @@ void Client::MoveSlotNotAllowed(bool client_update) {
 }
 
 // these functions operate with a material slot, which is from 0 to 8
-uint32 Client::GetEquipment(uint8 material_slot) const
-{
-	int invslot;
-	const ItemInst *item;
+uint32 Client::GetEquipment(uint8 material_slot) const {
+	if(material_slot < _MaterialCount) {
+		int16 slot = Inventory::CalcSlotFromMaterial(material_slot);
 
-	if(material_slot > 8)
-	{
-		return 0;
-	}
-
-	invslot = Inventory::CalcSlotFromMaterial(material_slot);
-	if(invslot == -1)
-	{
-		return 0;
-	}
+		const ItemInst* inst = m_inv.GetItem(slot);
 
-	item = m_inv.GetItem(invslot);
+		if(inst)
+			return inst->GetID();
+ 	}
 
-	if(item && item->GetItem())
-	{
-		return item->GetItem()->ID;
-	}
-
-	return 0;
+ 	return 0;
 }
 
 /*
@@ -2208,21 +2203,51 @@ int32 Client::GetEquipmentMaterial(uint8 material_slot)
 }
 */
 
-uint32 Client::GetEquipmentColor(uint8 material_slot) const
-{
-	const Item_Struct *item;
+uint32 Client::GetEquipmentColor(uint8 material_slot) const {
+	if(material_slot < _MaterialCount) {
+		int16 slot = Inventory::CalcSlotFromMaterial(material_slot);
 
-	if(material_slot > 8)
-	{
-		return 0;
+		const ItemInst* inst = m_inv.GetItem(slot);
+
+		if(inst) {
+			if(material_slot > MaterialFeet) {
+				if(inst->GetItem())
+					return inst->GetItem()->Color;
+			}
+			else {
+				return m_pp.item_tint[material_slot].rgb.use_tint ? m_pp.item_tint[material_slot].color : inst->GetColor();
+			}
+		}
 	}
 
-	item = database.GetItem(GetEquipment(material_slot));
-	if(item != 0)
-	{
-		return m_pp.item_tint[material_slot].rgb.use_tint ?
-			m_pp.item_tint[material_slot].color :
-			item->Color;
+	return 0;
+}
+
+uint32 Client::GetVisibleEquipment(uint8 material_slot) const {
+	if(material_slot < _MaterialCount) {
+		int16 slot = Inventory::CalcSlotFromMaterial(material_slot);
+
+		const ItemInst* inst = m_inv.GetItem(slot);
+
+		if(inst)
+			return inst->GetVisibleItemID();
+ 	}
+
+ 	return 0;
+}
+
+uint32 Client::GetVisibleEquipmentColor(uint8 material_slot) const {
+	if(material_slot < _MaterialCount) {
+		int16 slot = Inventory::CalcSlotFromMaterial(material_slot);
+
+		const ItemInst* inst = m_inv.GetItem(slot);
+
+		if(inst) {
+			if(material_slot > MaterialFeet)
+				return inst->GetVisibleColor(true);
+			else
+				return m_pp.item_tint[material_slot].rgb.use_tint ? m_pp.item_tint[material_slot].color : inst->GetVisibleColor();
+		}
 	}
 
 	return 0;
diff --git a/zone/merc.cpp b/zone/merc.cpp
index c8c8da6..ad3adb6 100644
--- a/zone/merc.cpp
+++ b/zone/merc.cpp
@@ -1253,6 +1253,12 @@ void Merc::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) {
 		ns->spawn.size = 0;
 		ns->spawn.NPC = 1;					// 0=player,1=npc,2=pc corpse,3=npc corpse
 		ns->spawn.IsMercenary = 1;
+
+		// Based on info from post-RoF live client, we will definitely need 4 slots..
+		// (..probably Primary, Secondary, Chest and Helm)
+		//
+		// (will have to examine this class to see if they can/will use ornaments/augments -U)
+
 		/*const Item_Struct* item = 0;
 		const ItemInst* inst = 0;
 
diff --git a/zone/mob.cpp b/zone/mob.cpp
index 8748671..5732acd 100644
--- a/zone/mob.cpp
+++ b/zone/mob.cpp
@@ -938,14 +938,14 @@ void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho)
 
 	for(i = 0; i < _MaterialCount; i++)
 	{
-		ns->spawn.equipment[i] = GetEquipmentMaterial(i);
+		ns->spawn.equipment[i] = GetVisibleEquipmentMaterial(i);
 		if (armor_tint[i])
 		{
 			ns->spawn.colors[i].color = armor_tint[i];
 		}
 		else
 		{
-			ns->spawn.colors[i].color = GetEquipmentColor(i);
+			ns->spawn.colors[i].color = GetVisibleEquipmentColor(i);
 		}
 	}
 
@@ -2489,14 +2489,20 @@ uint32 Mob::RandomTimer(int min,int max) {
 	return r;
 }
 
-uint32 NPC::GetEquipment(uint8 material_slot) const
-{
-	if(material_slot > 8)
-		return 0;
-	int invslot = Inventory::CalcSlotFromMaterial(material_slot);
-	if (invslot == -1)
-		return 0;
-	return equipment[invslot];
+uint32 NPC::GetEquipment(uint8 material_slot) const {
+	if(material_slot < _MaterialCount) {
+		int16 slot = Inventory::CalcSlotFromMaterial(material_slot);
+		
+		if((uint16)slot < 22)
+			return equipment[slot];
+	}
+
+	return 0;
+}
+
+uint32 NPC::GetVisibleEquipment(uint8 material_slot) const {
+	// TODO: ...
+	return GetEquipment(material_slot);
 }
 
 void Mob::SendWearChange(uint8 material_slot)
@@ -2505,9 +2511,9 @@ void Mob::SendWearChange(uint8 material_slot)
 	WearChange_Struct* wc = (WearChange_Struct*)outapp->pBuffer;
 
 	wc->spawn_id = GetID();
-	wc->material = GetEquipmentMaterial(material_slot);
-	wc->elite_material = IsEliteMaterialItem(material_slot);
-	wc->color.color = GetEquipmentColor(material_slot);
+	wc->material = GetVisibleEquipmentMaterial(material_slot);
+	wc->elite_material = IsVisibleEliteMaterialItem(material_slot);
+	wc->color.color = GetVisibleEquipmentColor(material_slot);
 	wc->wear_slot_id = material_slot;
 
 	entity_list.QueueClients(this, outapp);
@@ -2522,7 +2528,7 @@ void Mob::SendTextureWC(uint8 slot, uint16 texture, uint32 hero_forge_model, uin
 	wc->spawn_id = this->GetID();
 	wc->material = texture;
 	if (this->IsClient())
-		wc->color.color = GetEquipmentColor(slot);
+		wc->color.color = GetVisibleEquipmentColor(slot);
 	else
 		wc->color.color = this->GetArmorTint(slot);
 	wc->wear_slot_id = slot;
@@ -2550,7 +2556,7 @@ void Mob::SetSlotTint(uint8 material_slot, uint8 red_tint, uint8 green_tint, uin
 	WearChange_Struct* wc = (WearChange_Struct*)outapp->pBuffer;
 
 	wc->spawn_id = this->GetID();
-	wc->material = GetEquipmentMaterial(material_slot);
+	wc->material = GetVisibleEquipmentMaterial(material_slot);
 	wc->color.color = color;
 	wc->wear_slot_id = material_slot;
 
@@ -2574,26 +2580,19 @@ void Mob::WearChange(uint8 material_slot, uint16 texture, uint32 color)
 	safe_delete(outapp);
 }
 
-int32 Mob::GetEquipmentMaterial(uint8 material_slot) const
-{
-	const Item_Struct *item;
+uint32 Mob::GetEquipmentMaterial(uint8 material_slot) const {
+	const Item_Struct* item = database.GetItem(GetEquipment(material_slot));
 
-	item = database.GetItem(GetEquipment(material_slot));
-	if(item != 0)
-	{
-		if	// for primary and secondary we need the model, not the material
-		(
-			material_slot == MaterialPrimary ||
-			material_slot == MaterialSecondary
-		)
-		{
+	if(item != nullptr) {
+		// for primary and secondary we need the model, not the material
+		if((material_slot == MaterialPrimary) || (material_slot == MaterialSecondary)) {
 			if(strlen(item->IDFile) > 2)
 				return atoi(&item->IDFile[2]);
-			else	//may as well try this, since were going to 0 anyways
+			// may as well try this, since were going to 0 anyways
+			else	
 				return item->Material;
 		}
-		else
-		{
+		else {
 			return item->Material;
 		}
 	}
@@ -2601,32 +2600,39 @@ int32 Mob::GetEquipmentMaterial(uint8 material_slot) const
 	return 0;
 }
 
-uint32 Mob::GetEquipmentColor(uint8 material_slot) const
-{
-	const Item_Struct *item;
+uint32 Mob::GetEquipmentColor(uint8 material_slot) const {
+	const Item_Struct* item = database.GetItem(GetEquipment(material_slot));
 
-	item = database.GetItem(GetEquipment(material_slot));
-	if(item != 0)
-	{
+	if(item != nullptr)
 		return item->Color;
-	}
 
 	return 0;
 }
 
-uint32 Mob::IsEliteMaterialItem(uint8 material_slot) const
-{
-	const Item_Struct *item;
+uint32 Mob::IsEliteMaterialItem(uint8 material_slot) const {
+	const Item_Struct* item = database.GetItem(GetEquipment(material_slot));
 
-	item = database.GetItem(GetEquipment(material_slot));
-	if(item != 0)
-	{
+	if(item != nullptr)
 		return item->EliteMaterial;
-	}
 
 	return 0;
 }
 
+uint32 Mob::GetVisibleEquipmentMaterial(uint8 material_slot) const {
+	// TODO: ...
+	return GetEquipmentMaterial(material_slot);
+}
+
+uint32 Mob::GetVisibleEquipmentColor(uint8 material_slot) const {
+	// TODO: ...
+	return GetEquipmentColor(material_slot);
+}
+
+uint32 Mob::IsVisibleEliteMaterialItem(uint8 material_slot) const {
+	// TODO: ...
+	return IsEliteMaterialItem(material_slot);
+}
+
 // works just like a printf
 void Mob::Say(const char *format, ...)
 {
diff --git a/zone/mob.h b/zone/mob.h
index 4ee5da5..c5687ea 100644
--- a/zone/mob.h
+++ b/zone/mob.h
@@ -282,9 +282,13 @@ public:
 	inline void ShieldEquiped(bool val) { has_shieldequiped = val; }
 	virtual uint16 GetSkill(SkillUseTypes skill_num) const { return 0; }
 	virtual uint32 GetEquipment(uint8 material_slot) const { return(0); }
-	virtual int32 GetEquipmentMaterial(uint8 material_slot) const;
+	virtual uint32 GetEquipmentMaterial(uint8 material_slot) const;
 	virtual uint32 GetEquipmentColor(uint8 material_slot) const;
 	virtual uint32 IsEliteMaterialItem(uint8 material_slot) const;
+	virtual uint32 GetVisibleEquipment(uint8 material_slot) const { return(0); }
+	virtual uint32 GetVisibleEquipmentMaterial(uint8 material_slot) const;
+	virtual uint32 GetVisibleEquipmentColor(uint8 material_slot) const;
+	virtual uint32 IsVisibleEliteMaterialItem(uint8 material_slot) const;
 	bool AffectedBySpellExcludingSlot(int slot, int effect);
 	virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill) = 0;
 	virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill,
diff --git a/zone/npc.cpp b/zone/npc.cpp
index f83d1d3..f56194f 100644
--- a/zone/npc.cpp
+++ b/zone/npc.cpp
@@ -1194,32 +1194,37 @@ uint32 ZoneDatabase::NPCSpawnDB(uint8 command, const char* zone, uint32 zone_ver
 	return false;
 }
 
-int32 NPC::GetEquipmentMaterial(uint8 material_slot) const
-{
-	if (material_slot >= _MaterialCount)
-		return 0;
+uint32 NPC::GetEquipmentMaterial(uint8 material_slot) const {
+	if(material_slot < _MaterialCount) {
+		int16 inv_slot = Inventory::CalcSlotFromMaterial(material_slot);
 
-	int inv_slot = Inventory::CalcSlotFromMaterial(material_slot);
-	if (inv_slot == -1)
-		return 0;
-	if(equipment[inv_slot] == 0) {
-		switch(material_slot) {
-		case MaterialHead:
-			return helmtexture;
-		case MaterialChest:
-			return texture;
-		case MaterialPrimary:
-			return d_meele_texture1;
-		case MaterialSecondary:
-			return d_meele_texture2;
-		default:
-			//they have nothing in the slot, and its not a special slot... they get nothing.
-			return(0);
+		if(inv_slot != SLOT_INVALID) {
+			if(equipment[inv_slot] != 0) {
+				return Mob::GetEquipmentMaterial(material_slot);
+			}
+			else {
+				switch(material_slot) {
+				case MaterialHead:
+					return helmtexture;
+				case MaterialChest:
+					return texture;
+				case MaterialPrimary:
+					return d_meele_texture1;
+				case MaterialSecondary:
+					return d_meele_texture2;
+				default:
+					break;
+				}
+			}
 		}
 	}
+	
+	return 0;
+}
 
-	//they have some loot item in this slot, pass it up to the default handler
-	return(Mob::GetEquipmentMaterial(material_slot));
+uint32 NPC::GetVisibleEquipmentMaterial(uint8 material_slot) const {
+	// TODO: ...
+	return GetEquipmentMaterial(material_slot);
 }
 
 uint32 NPC::GetMaxDamage(uint8 tlevel)
diff --git a/zone/npc.h b/zone/npc.h
index e887717..708d9d6 100644
--- a/zone/npc.h
+++ b/zone/npc.h
@@ -262,7 +262,9 @@ public:
 	void				GetClosestWaypoint(std::list<wplist> &wp_list, int count, float m_x, float m_y, float m_z);
 
 	uint32				GetEquipment(uint8 material_slot) const;	// returns item id
-	int32				GetEquipmentMaterial(uint8 material_slot) const;
+	uint32				GetEquipmentMaterial(uint8 material_slot) const;
+	uint32				GetVisibleEquipment(uint8 material_slot) const;	// returns visible item id
+	uint32				GetVisibleEquipmentMaterial(uint8 material_slot) const;
 
 	void				NextGuardPosition();
 	void				SaveGuardSpot(bool iClearGuardSpot = false);

Raw Paste Data