Browse Source

Fixed AddControlEffect crash on lua_interface->LogError when target is null
Work on Issue #418 for item flags (not fully completed)
Item Flags Implemented:
- No Destroy
- No Zone
- Lore
- Lore Equip
- Stack Lore

Emagi 1 year ago
parent
commit
c799cdeb5a

+ 6 - 3
EQ2/source/WorldServer/Commands/Commands.cpp

@@ -4217,7 +4217,7 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
 				Item* item = master_item_list.GetItem(item_id);
 				if(item && item->generic_info.max_charges > 1)
 					quantity = item->generic_info.max_charges;
-				client->AddItem(item_id, quantity);
+				client->AddItem(item_id, quantity, AddItemType::BUY_FROM_BROKER);
 			}
 			break;
 		}
@@ -6620,11 +6620,14 @@ void Commands::Command_Inventory(Client* client, Seperator* sep, EQ2_RemoteComma
 
 			if(item)
 			{
-				if(item->details.item_locked)
-				{
+				if(item->details.item_locked) {
 					client->SimpleMessage(CHANNEL_COLOR_RED, "You cannot destroy the item in use.");
 					return;
 				}
+				else if(item->CheckFlag(NO_DESTROY)) {
+					client->SimpleMessage(CHANNEL_COLOR_RED, "You can't destroy this item.");
+					return;
+				}
 				if(item->GetItemScript() && lua_interface)
 					lua_interface->RunItemScript(item->GetItemScript(), "destroyed", item, client->GetPlayer());
 			

+ 112 - 1
EQ2/source/WorldServer/Items/Items.cpp

@@ -3373,7 +3373,6 @@ EQ2Packet* PlayerItemList::serialize(Player* player, int16 version){
 #endif
 		packet->setDataByName("equip_flag",0);
 		app = packet->serializeCountPacket(version, 1, orig_packet, xor_packet);
-		DumpPacket(app);
 		safe_delete(packet);
 	}
 	MPlayerItems.releasereadlock(__FUNCTION__, __LINE__);
@@ -3771,6 +3770,82 @@ void PlayerItemList::ResetPackets() {
 	packet_count = 0;
 }
 
+
+int32 PlayerItemList::CheckSlotConflict(Item* item, bool check_lore_only, bool lock, int16* lore_stack_count) {
+	bool is_lore = false;
+	bool is_stack_lore = false;
+	if(!(is_lore = item->CheckFlag(LORE)) && !(is_stack_lore = item->CheckFlag(STACK_LORE)) && check_lore_only) {
+		return 0;
+	}
+	
+	if(!check_lore_only && !is_lore && !is_stack_lore && !item->CheckFlag(LORE_EQUIP)) {
+		return 0;
+	}
+	
+	
+	int32 conflict = 0;
+	
+	if(lock)
+		MPlayerItems.readlock(__FUNCTION__, __LINE__);
+	
+	map<sint32, map<int8, map<int16, Item*>> >::iterator itr;
+	map<int16, Item*>::iterator slot_itr;
+	
+	for(itr = items.begin(); itr != items.end(); itr++){
+		for(slot_itr=itr->second[0].begin();slot_itr!=itr->second[0].end(); slot_itr++){
+			if(slot_itr->second && slot_itr->second->details.item_id == item->details.item_id){
+				if(lore_stack_count) {
+					*lore_stack_count += slot_itr->second->details.count;
+				}
+				if(!is_stack_lore && slot_itr->second->CheckFlag(LORE)) {
+					conflict = LORE;
+					break;
+				}
+				else if(is_stack_lore && (*lore_stack_count + item->details.count) > slot_itr->second->stack_count) {
+					conflict = STACK_LORE;
+					break;
+				}
+				else if(!check_lore_only && slot_itr->second->CheckFlag(LORE_EQUIP)) {
+					conflict = LORE_EQUIP;
+					break;
+				}
+			}
+		}
+			
+		if(conflict > 0)
+			break;
+		
+		for(slot_itr=itr->second[1].begin();slot_itr!=itr->second[1].end(); slot_itr++){
+			if(slot_itr->second && slot_itr->second->details.item_id == item->details.item_id){
+				if(lore_stack_count) {
+					*lore_stack_count += slot_itr->second->details.count;
+				}
+				if(!is_stack_lore && slot_itr->second->CheckFlag(LORE)) {
+					conflict = LORE;
+					break;
+				}
+				else if(is_stack_lore && (*lore_stack_count + item->details.count) > slot_itr->second->stack_count) {
+					conflict = STACK_LORE;
+					break;
+				}
+				else if(!check_lore_only && slot_itr->second->CheckFlag(LORE_EQUIP)) {
+					conflict = LORE_EQUIP;
+					break;
+				}
+			}
+		}
+		
+		if(conflict > 0)
+			break;
+	}
+
+	if(lock)
+		MPlayerItems.releasereadlock(__FUNCTION__, __LINE__);
+	
+	return conflict;
+}
+
+
 EquipmentItemList::EquipmentItemList(){
 	orig_packet = 0;
 	xor_packet = 0;
@@ -4118,6 +4193,42 @@ int8 EquipmentItemList::GetFreeSlot(Item* tmp, int8 slot_id){
 	return 255;
 }
 
+int32 EquipmentItemList::CheckSlotConflict(Item* item, bool check_lore_only, int16* lore_stack_count) {
+	bool is_lore = false;
+	bool is_stack_lore = false;
+	if(!(is_lore = item->CheckFlag(LORE)) && !(is_stack_lore = item->CheckFlag(STACK_LORE)) && check_lore_only) {
+		return 0;
+	}
+	
+	if(!check_lore_only && !is_lore && !is_stack_lore && !item->CheckFlag(LORE_EQUIP)) {
+		return 0;
+	}
+	
+	int32 conflict = 0;
+	MEquipmentItems.lock();
+	for(int8 i=0;i<NUM_SLOTS;i++){
+		if(items[i] && items[i]->details.item_id == item->details.item_id) {
+			if(lore_stack_count)
+				*lore_stack_count += items[i]->details.count;
+			if(!is_stack_lore && items[i]->CheckFlag(LORE)) {
+				conflict = LORE;
+				break;
+			}
+			else if(is_stack_lore && (*lore_stack_count + item->details.count) > items[i]->stack_count) {
+				conflict = STACK_LORE;
+				break;
+			}
+			else if(!check_lore_only && items[i]->CheckFlag(LORE_EQUIP)) {
+				conflict = LORE_EQUIP;
+				break;
+			}
+		}
+	}
+
+	MEquipmentItems.unlock();
+	return conflict;
+}
+
 int8 EquipmentItemList::GetSlotByItem(Item* item) {
 	int8 slot = 255;
 	for (int8 i = 0; i < NUM_SLOTS; i++) {

+ 5 - 0
EQ2/source/WorldServer/Items/Items.h

@@ -1088,6 +1088,8 @@ public:
 	
 	void	ResetPackets();
 
+	int32	CheckSlotConflict(Item* tmp, bool check_lore_only = false, bool lock_mutex = true, int16* lore_stack_count = 0);
+	
 	Mutex MPlayerItems;
 private:
 	void AddItemToPacket(PacketStruct* packet, Player* player, Item* item, int16 i, bool overflow = false);
@@ -1095,6 +1097,7 @@ private:
 	int16 packet_count;
 	vector<Item*> overflowItems;
 };
+
 class EquipmentItemList{
 public:
 	EquipmentItemList();
@@ -1118,6 +1121,8 @@ public:
 	bool	CheckEquipSlot(Item* tmp, int8 slot);
 	bool	CanItemBeEquippedInSlot(Item* tmp, int8 slot);
 	int8	GetFreeSlot(Item* tmp, int8 slot_id = 255);
+	int32	CheckSlotConflict(Item* tmp, bool check_lore_only = false, int16* lore_stack_count = 0);
+	
 	int8	GetSlotByItem(Item* item);
 	ItemStatsValues*	CalculateEquipmentBonuses(Entity* entity = 0);
 	EQ2Packet* serialize(int16 version, Player* player);

+ 57 - 123
EQ2/source/WorldServer/Items/ItemsDB.cpp

@@ -30,111 +30,6 @@
 
 extern World world;
 
-void WorldDatabase::LoadDataFromRow(MYSQL_ROW row, Item* item) 
-{
-// this is too much on top of already having the top level load item debug msg
-//	LogWrite(ITEM__DEBUG, 5, "Items", "\tSetting details for item ID: %u", strtoul(row[0], NULL, 0));
-	item->details.item_id = strtoul(row[0], NULL, 0);
-	int8 size = strlen(row[1]);
-
-	if(size > 63)
-		size = 63;
-
-	item->name = string(row[1]);
-	item->lowername = ToLower(item->name);
-	item->details.icon = atoi(row[2]);
-	item->details.count = atoi(row[3]);
-	item->details.tier = atoi(row[4]);
-	item->generic_info.weight = atoi(row[5]);
-
-	if(row[6] && strlen(row[6]))
-		item->description = string(row[6]);
-
-	item->generic_info.show_name = atoi(row[7]);
-
-	if(atoi(row[8]))
-		item->generic_info.item_flags += ATTUNEABLE;
-
-	if(atoi(row[9]))
-		item->generic_info.item_flags += ARTIFACT;
-
-	if(atoi(row[10]))
-		item->generic_info.item_flags += LORE;
-
-	if(atoi(row[11]))
-		item->generic_info.item_flags += TEMPORARY;
-
-	if(atoi(row[12]))
-		item->generic_info.item_flags += NO_TRADE;
-
-	if(atoi(row[13]))
-		item->generic_info.item_flags += NO_VALUE;
-
-	if(atoi(row[14]))
-		item->generic_info.item_flags += NO_ZONE;
-
-	if(atoi(row[15]))
-		item->generic_info.item_flags += NO_DESTROY;
-
-	if(atoi(row[16]))
-		item->generic_info.item_flags += CRAFTED;
-
-	if(atoi(row[17]))
-		item->generic_info.item_flags += GOOD_ONLY;
-
-	if(atoi(row[18]))
-		item->generic_info.item_flags += EVIL_ONLY;
-
-	if(atoul(row[19]) == 0)
-		item->generic_info.skill_req1 = 0xFFFFFFFF;
-	else
-		item->generic_info.skill_req1 = atoul(row[19]);
-
-	if(atoul(row[20]) == 0)
-		item->generic_info.skill_req2 = 0xFFFFFFFF;
-	else
-		item->generic_info.skill_req2 = atoul(row[20]);
-
-	item->generic_info.skill_min = atoi(row[21]);
-
-	if(atoul(row[23])>0)
-		item->SetSlots(atoul(row[23]));
-
-	item->sell_price = atoul(row[24]);
-	item->stack_count = atoi(row[25]);
-	item->generic_info.collectable = atoi(row[26]);
-	item->generic_info.offers_quest_id = atoul(row[27]);
-	item->generic_info.part_of_quest_id = atoul(row[28]);
-	item->details.recommended_level = atoi(row[29]);
-	item->details.item_locked = false;
-	item->generic_info.adventure_default_level = atoi(row[30]);
-	item->generic_info.max_charges = atoi(row[31]);
-	item->generic_info.display_charges = atoi(row[32]);
-	item->generic_info.tradeskill_default_level = atoi(row[33]);
-
-	#ifdef WIN32
-			item->generic_info.adventure_classes = _strtoui64(row[34], NULL, 10);
-			item->generic_info.tradeskill_classes = _strtoui64(row[35], NULL, 10);
-	#else
-			item->generic_info.adventure_classes = strtoull(row[34], 0, 10);
-			item->generic_info.tradeskill_classes = strtoull(row[35], 0, 10);
-	#endif
-
-	if(row[36] && strlen(row[36])){
-		item->SetItemScript(row[36]);
-		LogWrite(ITEM__DEBUG, 5, "LUA", "\tLoading LUA Item Script: '%s'", item->item_script.c_str());
-	}
-
-	if(item->generic_info.max_charges > 0)
-		item->details.count = item->generic_info.max_charges;
-
-	if(item->details.count == 0)
-		item->details.count = 1;
-
-	item->generic_info.usable = atoi(row[37]);
-	item->details.soe_id = atoi(row[39]);
-}
-
 // handle new database class til all functions are converted
 void WorldDatabase::LoadDataFromRow(DatabaseResult* result, Item* item) 
 {
@@ -167,7 +62,7 @@ void WorldDatabase::LoadDataFromRow(DatabaseResult* result, Item* item)
 
 	if( result->GetInt8Str("lore") == 1 )
 		item->generic_info.item_flags += LORE;
-
+	
 	if( result->GetInt8Str("temporary") == 1 )
 		item->generic_info.item_flags += TEMPORARY;
 
@@ -192,6 +87,9 @@ void WorldDatabase::LoadDataFromRow(DatabaseResult* result, Item* item)
 	if( result->GetInt8Str("evil_only") == 1 )
 		item->generic_info.item_flags += EVIL_ONLY;
 
+	if( result->GetInt8Str("stacklore") == 1 )
+		item->generic_info.item_flags += STACK_LORE;
+	
 	// add more Flags/Flags2 here
 
 	if (result->GetInt8Str("lore_equip") == 1)
@@ -1156,11 +1054,20 @@ void WorldDatabase::SaveItems(Client* client)
 	{
 		item = item_iter->second;
 
-		if(item && item->save_needed)
-		{
-			LogWrite(ITEM__DEBUG, 5, "Items", "SaveItems: Acct: %u, Char: %u, Item: %u, NOT-EQUIPPED", client->GetAccountID(), client->GetCharacterID(), item);
-			SaveItem(client->GetAccountID(), client->GetCharacterID(), item, "NOT-EQUIPPED");
-			item->save_needed = false;
+		if(item) {
+			if(item->needs_deletion || (client->IsZoning() && item->CheckFlag(NO_ZONE))) {
+				DeleteItem(client->GetCharacterID(), item, 0);
+				client->GetPlayer()->item_list.DestroyItem(item->details.index);
+				if(!client->IsZoning()) {
+					client->QueuePacket(client->GetPlayer()->SendInventoryUpdate(client->GetVersion()));
+				}
+			}
+			else if(item->save_needed)
+			{
+				LogWrite(ITEM__DEBUG, 5, "Items", "SaveItems: Acct: %u, Char: %u, Item: %u, NOT-EQUIPPED", client->GetAccountID(), client->GetCharacterID(), item);
+				SaveItem(client->GetAccountID(), client->GetCharacterID(), item, "NOT-EQUIPPED");
+				item->save_needed = false;
+			}
 		}
 	}
 	safe_delete(items);
@@ -1171,12 +1078,21 @@ void WorldDatabase::SaveItems(Client* client)
 	{
 		item = equipped_list->at(i);
 
-		if(item && item->save_needed)
+		if(item)
 		{
-			if(item->details.appearance_type)
-				SaveItem(client->GetAccountID(), client->GetCharacterID(), item, "APPEARANCE");
-			else
-				SaveItem(client->GetAccountID(), client->GetCharacterID(), item, "EQUIPPED");
+			if(item->needs_deletion || (client->IsZoning() && item->CheckFlag(NO_ZONE))) {
+				DeleteItem(client->GetCharacterID(), item, 0);
+				client->GetPlayer()->item_list.DestroyItem(item->details.index);
+				if(!client->IsZoning()) {
+					client->QueuePacket(client->GetPlayer()->SendInventoryUpdate(client->GetVersion()));
+				}
+			}
+			else if(item->save_needed) {
+				if(item->details.appearance_type)
+					SaveItem(client->GetAccountID(), client->GetCharacterID(), item, "APPEARANCE");
+				else
+					SaveItem(client->GetAccountID(), client->GetCharacterID(), item, "EQUIPPED");
+			}
 			item->save_needed = false;
 		}
 	}
@@ -1189,10 +1105,19 @@ void WorldDatabase::SaveItems(Client* client)
 	{
 		item = appearance_equipped_list->at(i);
 
-		if(item && item->save_needed)
+		if(item)
 		{
-			SaveItem(client->GetAccountID(), client->GetCharacterID(), item, "APPEARANCE");
-			item->save_needed = false;
+			if(item->needs_deletion || (client->IsZoning() && item->CheckFlag(NO_ZONE))) {
+				DeleteItem(client->GetCharacterID(), item, 0);
+				client->GetPlayer()->item_list.DestroyItem(item->details.index);
+				if(!client->IsZoning()) {
+					client->QueuePacket(client->GetPlayer()->SendInventoryUpdate(client->GetVersion()));
+				}
+			}
+			else if(item->save_needed) {
+				SaveItem(client->GetAccountID(), client->GetCharacterID(), item, "APPEARANCE");
+				item->save_needed = false;
+			}
 		}
 	}
 	safe_delete(appearance_equipped_list);
@@ -1201,10 +1126,19 @@ void WorldDatabase::SaveItems(Client* client)
 	for (int32 i = 0; i < overflow->size(); i++){
 		item = overflow->at(i);
 		if (item) {
-			sint16 slot = item->details.slot_id;
-			item->details.slot_id = i;
-			SaveItem(client->GetAccountID(), client->GetCharacterID(), item, "NOT-EQUIPPED");
-			item->details.slot_id = slot;
+			if(item->needs_deletion || (client->IsZoning() && item->CheckFlag(NO_ZONE))) {
+				DeleteItem(client->GetCharacterID(), item, 0);
+				client->GetPlayer()->item_list.DestroyItem(item->details.index);
+				if(!client->IsZoning()) {
+					client->QueuePacket(client->GetPlayer()->SendInventoryUpdate(client->GetVersion()));
+				}
+			}
+			else {
+				sint16 slot = item->details.slot_id;
+				item->details.slot_id = i;
+				SaveItem(client->GetAccountID(), client->GetCharacterID(), item, "NOT-EQUIPPED");
+				item->details.slot_id = slot;
+			}
 		}
 	}
 	safe_delete(overflow);

+ 1 - 381
EQ2/source/WorldServer/Items/Loot.cpp

@@ -36,387 +36,7 @@ extern ConfigReader configReader;
 extern MasterSkillList master_skill_list;
 extern RuleManager rule_manager;
 
-
-// JA: storing loot-related functions here til I find them all :/
-
-/*
-void Combat::AddLooter(Entity* victim, Entity* attacker){
-	MLooters.writelock(__FUNCTION__, __LINE__);
-	if(attacker->IsPlayer()){
-		PlayerGroup* group = ((Player*)attacker)->GetGroup();
-		if(group && group->members.size() > 0){
-			deque<GroupMemberInfo*>::iterator itr;
-			for(itr = group->members.begin(); itr != group->members.end(); itr++)
-				looters[victim].push_back((*itr)->client->GetPlayer());
-		}
-		else
-			looters[victim].push_back(attacker);
-	}
-	MLooters.releasewritelock(__FUNCTION__, __LINE__);
-}
-
-void Combat::ClearLooters(Entity* spawn){
-	MLooters.writelock(__FUNCTION__, __LINE__);
-	looters.erase(spawn);
-	MLooters.releasewritelock(__FUNCTION__, __LINE__);
-}
-
-bool Combat::CheckLootAllowed(Entity* dead, Entity* spawn){
-	if(!spawn || !dead || dead->GetHP() > 0)
-		return false;
-	bool ret = false;
-	MLooters.readlock(__FUNCTION__, __LINE__);
-	if(looters.count(dead) > 0){
-		vector<Entity*>::iterator itr;
-		for(itr = looters[dead].begin(); itr != looters[dead].end(); itr++){
-			if(*itr == spawn){
-				ret = true;
-				break;
-			}
-		}
-		
-	}
-	MLooters.releasereadlock(__FUNCTION__, __LINE__);
-	return ret;
-}
-
-
-
-bool Client::HandleLootItem(Entity* entity, Item* item){
-	if(!item){
-		SimpleMessage(CHANNEL_COLOR_YELLOW, "Unable to find item to loot!");
-		return false;
-	}
-	if(player->item_list.HasFreeSlot() || player->item_list.CanStack(item)){
-		if(player->item_list.AssignItemToFreeSlot(item)){
-			int8 type = CHANNEL_COLOR_LOOT;
-			if(GetVersion() >= 973 && GetVersion() <= 1000)
-				type = CHANNEL_COLOR_NEW_LOOT;
-			else if(GetVersion() >= 973)
-				type = CHANNEL_COLOR_NEWEST_LOOT;			
-			if(entity)
-				Message(type, "You loot \\aITEM %u 0:%s\\/a from the corpse of %s", item->details.item_id, item->name.c_str(), entity->GetName());
-			else
-				Message(type, "You found a \\aITEM %u 0:%s\\/a", item->details.item_id, item->name.c_str());
-			Guild* guild = player->GetGuild();
-			if (guild && item->details.tier >= ITEM_TAG_LEGENDARY) {
-				char adjective[32];
-				int8 type;
-				memset(adjective, 0, sizeof(adjective));
-				if (item->details.tier >= ITEM_TAG_MYTHICAL) {
-					strncpy(adjective, "Mythical", sizeof(adjective) - 1);
-					type = GUILD_EVENT_LOOTS_MYTHICAL_ITEM;
-				}
-				else if (item->details.tier >= ITEM_TAG_FABLED) {
-					strncpy(adjective, "Fabled", sizeof(adjective) - 1);
-					type = GUILD_EVENT_LOOTS_FABELED_ITEM;
-				}
-				else {
-					strncpy(adjective, "Legendary", sizeof(adjective) - 1);
-					type = GUILD_EVENT_LOOTS_LEGENDARY_ITEM;
-				}
-				guild->AddNewGuildEvent(type, "%s has looted the %s \\aITEM %u 0:%s\\/a", Timer::GetUnixTimeStamp(), true, player->GetName(), adjective, item->details.item_id, item->name.c_str());
-				guild->SendMessageToGuild(type, "%s has looted the %s \\aITEM %u 0:%s\\/a", player->GetName(), adjective, item->details.item_id, item->name.c_str());
-			}
-			CheckPlayerQuestsItemUpdate(item);
-			return true;
-		}
-		else
-			SimpleMessage(CHANNEL_COLOR_RED, "Could not find free slot to place item.");	
-	}
-	else
-		SimpleMessage(CHANNEL_COLOR_YELLOW, "Unable to loot item: Inventory is FULL.");
-	return false;
-}
-
-bool Client::HandleLootItem(Entity* entity, int32 item_id){
-	if(!entity)
-		return false;
-	return HandleLootItem(entity, entity->LootItem(item_id));
-}
-
-void Client::HandleLoot(EQApplicationPacket* app){
-	PacketStruct* packet = configReader.getStruct("WS_LootType", GetVersion());
-	if(packet){
-		packet->LoadPacketData(app->pBuffer, app->size);
-		int32 loot_id = packet->getType_int32_ByName("loot_id");
-		bool loot_all = (packet->getType_int8_ByName("loot_all") == 1);
-		safe_delete(packet);
-		int32 item_id = 0;
-		Item* item = 0;
-		Spawn* spawn = GetCurrentZone()->GetSpawnByID(loot_id);
-		if(player->HasPendingLootItems(loot_id)){
-			Item* master_item = 0;
-			if(loot_all){
-				vector<Item*>* items = player->GetPendingLootItems(loot_id);
-				if(items){
-					for(int32 i=0;loot_all && i<items->size();i++){
-						master_item = items->at(i);
-						if(master_item){
-							item = new Item(master_item);
-							if(item){
-								loot_all = HandleLootItem(0, item);
-								if(loot_all)
-									player->RemovePendingLootItem(loot_id, item->details.item_id);
-							}
-						}
-					}
-					safe_delete(items);
-				}
-			}
-			else{
-				packet = configReader.getStruct("WS_LootItem", GetVersion());
-				if(packet){
-					packet->LoadPacketData(app->pBuffer, app->size);
-					item_id = packet->getType_int32_ByName("item_id");
-					vector<Item*>* items = player->GetPendingLootItems(loot_id);
-					if(items){
-						for(int32 i=0;i<items->size();i++){
-							master_item = items->at(i);
-							if(master_item && master_item->details.item_id == item_id){
-								item = new Item(master_item);
-								if(item && HandleLootItem(0, item))
-									player->RemovePendingLootItem(loot_id, item->details.item_id);
-								break;
-							}
-						}
-						safe_delete(items);
-					}
-					safe_delete(packet);
-				}
-			}
-			EQ2Packet* outapp = player->SendInventoryUpdate(GetVersion());
-			if(outapp)
-				QueuePacket(outapp);
-			Loot(0, player->GetPendingLootItems(loot_id), (Entity*)spawn);
-		}
-		else{
-			if(spawn && spawn->IsEntity() && GetCurrentZone()->GetCombat()->CheckLootAllowed((Entity*)spawn, player)){
-				if(loot_all){
-					while(loot_all && ((item_id = ((Entity*)spawn)->GetLootItemID()) > 0)){
-						loot_all = HandleLootItem((Entity*)spawn, item_id);
-					}
-				}
-				else{
-					packet = configReader.getStruct("WS_LootItem", GetVersion());
-					if(packet){
-						packet->LoadPacketData(app->pBuffer, app->size);
-						item_id = packet->getType_int32_ByName("item_id");
-						HandleLootItem((Entity*)spawn, item_id);
-						safe_delete(packet);
-					}
-				}
-				EQ2Packet* outapp = player->SendInventoryUpdate(GetVersion());
-				if(outapp)
-					QueuePacket(outapp);
-				Loot((Entity*)spawn);
-				if(!((Entity*)spawn)->HasLoot()){
-					CloseLoot();
-					if(((Entity*)spawn)->IsNPC())
-						GetCurrentZone()->RemoveDeadSpawn(spawn);
-				}
-			}
-			else{
-				if(!spawn){
-					LogWrite(WORLD__ERROR, 0, "World", "Unknown id of %u when looting!", loot_id);
-					SimpleMessage(CHANNEL_COLOR_YELLOW, "Unable to find spawn to loot!");
-				}
-				else
-					SimpleMessage(CHANNEL_COLOR_YELLOW, "You are not unable to loot that at this time.");
-			}
-		}
-	}
-}
-
-
-void Client::SendPendingLoot(int32 total_coins, Entity* entity){
-	if(entity)
-		Loot(total_coins, player->GetPendingLootItems(entity->GetID()), entity);
-}
-
-void Client::CloseLoot(){
-	PacketStruct* packet = configReader.getStruct("WS_CloseWindow", GetVersion());
-	packet->setDataByName("window_id", 4);
-	EQ2Packet* outapp = packet->serialize();
-//	DumpPacket(outapp);
-	QueuePacket(outapp);
-	safe_delete(packet);
-}
-
-string Client::GetCoinMessage(int32 total_coins){
-	if(total_coins == 0)
-		return " 0 Copper";
-	char tmp[64] = {0};
-	string message = "";
-	int32 val = 0;
-	if(total_coins >= 1000000){
-		val = total_coins / 1000000;
-		total_coins -= 1000000 * val;
-		sprintf(tmp, " %u Platinum", val);
-		message.append(tmp);
-		memset(tmp, 0, 64);
-	}
-	if(total_coins >= 10000){
-		val = total_coins / 10000;
-		total_coins -= 10000 * val;
-		sprintf(tmp, " %u Gold", val);
-		message.append(tmp);
-		memset(tmp, 0, 64);
-	}
-	if(total_coins >= 100){
-		val = total_coins / 100;
-		total_coins -= 100 * val;
-		sprintf(tmp, " %u Silver", val);
-		message.append(tmp);
-		memset(tmp, 0, 64);
-	}
-	if(total_coins > 0){
-		sprintf(tmp, " %u Copper", (int32)total_coins);
-		message.append(tmp);
-	}
-	return message;
-}
-
-void Client::Loot(int32 total_coins, vector<Item*>* items, Entity* entity){
-	if(!entity){
-		CloseLoot();
-		return;
-	}
-	if(total_coins > 0){
-		player->AddCoins(total_coins);
-		//PlaySound("coin_cha_ching");
-		string message = "";
-		if(entity->GetHP() == 0){
-			message = "You loot ";
-			entity->SetLootCoins(0);
-		}
-		else
-			message = "You receive ";
-		message.append(GetCoinMessage(total_coins));
-		if(entity->GetHP() == 0)
-			message.append(" from the corpse of ").append(entity->GetName());
-		int8 type = CHANNEL_COLOR_LOOT;
-		if(GetVersion() >= 973)
-			type = CHANNEL_COLOR_NEW_LOOT;
-		SimpleMessage(type, message.c_str());
-	}
-	if(!items || items->size() == 0)
-		CloseLoot();
-	PacketStruct* packet = configReader.getStruct("WS_UpdateLoot", GetVersion());
-	if(packet){
-		vector<Item*>::iterator itr;
-		int32 packet_size = 0;
-		if(items && items->size() > 0){
-			packet->setDataByName("loot_count", items->size());
-			packet->setDataByName("display", 1);
-		}
-		packet->setDataByName("unknown2", 1);
-		packet->setDataByName("unknown3", 0x3C);
-		packet->setDataByName("loot_id", entity->GetID());
-		EQ2Packet* tmpPacket = packet->serialize();
-		packet_size += tmpPacket->size;
-		uchar* data = 0;
-		if(items && items->size() > 0){
-			data = new uchar[items->size()*1000 + packet_size];
-			memset(data, 0, items->size()*1000 + packet_size);
-		}
-		else{
-			data = new uchar[packet_size];
-			memset(data, 0, packet_size);
-		}
-		uchar* ptr = data;
-		memcpy(ptr, tmpPacket->pBuffer, tmpPacket->size);
-		ptr += tmpPacket->size;
-		safe_delete(tmpPacket);
-		Item* item = 0;
-		if(items && items->size() > 0){
-			for(itr = items->begin(); itr != items->end(); itr++){
-				item = *itr;
-				memcpy(ptr, &item->details.item_id, sizeof(int32));
-				ptr += sizeof(int32);
-				packet_size += sizeof(int32);
-
-				tmpPacket = item->serialize(GetVersion(), true, GetPlayer(), false, 1, 0, false, true);
-				if(GetVersion() >= 860){
-					memcpy(ptr, tmpPacket->pBuffer + 11, tmpPacket->size - 11);
-					ptr += tmpPacket->size - 11;
-					packet_size += tmpPacket->size - 11;
-				}
-				else{
-					memcpy(ptr, tmpPacket->pBuffer + 10, tmpPacket->size - 10);
-					ptr += tmpPacket->size - 10;
-					packet_size += tmpPacket->size - 10;
-				}
-				safe_delete(tmpPacket);
-			}
-		}
-		packet_size -= sizeof(int32);
-		memcpy(data, &packet_size, sizeof(int32));
-		packet_size += sizeof(int32);
-		EQ2Packet* outapp = new EQ2Packet(OP_ClientCmdMsg, data, packet_size);
-		//DumpPacket(outapp);
-		QueuePacket(outapp);
-		safe_delete_array(data);
-		safe_delete(packet);
-	}
-}
-
-void Client::Loot(Entity* entity){
-	if(GetCurrentZone()->GetCombat()->CheckLootAllowed(entity, GetPlayer())){
-		int32 total_coins = entity->GetLootCoins();
-		entity->LockLoot();
-		Loot(total_coins, entity->GetLootItems(), entity);
-		entity->UnlockLoot();
-	}
-	else
-		SimpleMessage(CHANNEL_COLOR_YELLOW, "You are not allowed to loot at this time.");
-}
-
-
-bool Player::HasPendingLootItems(int32 id){
-	return (pending_loot_items.count(id) > 0 && pending_loot_items[id].size() > 0);
-}
-
-bool Player::HasPendingLootItem(int32 id, int32 item_id){
-	return (pending_loot_items.count(id) > 0 && pending_loot_items[id].count(item_id) > 0);
-}
-vector<Item*>* Player::GetPendingLootItems(int32 id){
-	vector<Item*>* ret = 0;
-	if(pending_loot_items.count(id) > 0){
-		ret = new vector<Item*>();
-		map<int32, bool>::iterator itr;
-		for(itr = pending_loot_items[id].begin(); itr != pending_loot_items[id].end(); itr++){
-			if(master_item_list.GetItem(itr->first))
-				ret->push_back(master_item_list.GetItem(itr->first));
-		}
-	}
-	return ret;
-}
-
-void Player::RemovePendingLootItem(int32 id, int32 item_id){
-	if(pending_loot_items.count(id) > 0){
-		pending_loot_items[id].erase(item_id);
-		if(pending_loot_items[id].size() == 0)
-			pending_loot_items.erase(id);
-	}
-}
-
-void Player::RemovePendingLootItems(int32 id){
-	if(pending_loot_items.count(id) > 0)
-		pending_loot_items.erase(id);
-}
-
-void Player::AddPendingLootItems(int32 id, vector<Item*>* items){
-	if(items){
-		Item* item = 0;
-		for(int32 i=0;i<items->size();i++){
-			item = items->at(i);
-			if(item)
-				pending_loot_items[id][item->details.item_id] = true;
-		}
-	}
-}*/
-
+// If we want to transfer functions to this file then we should just do it, but for now we don't need all this commented code here
 
 NPC* Entity::DropChest() {
 	// Check to see if treasure chests are disabled in the rules

+ 2 - 2
EQ2/source/WorldServer/LuaFunctions.cpp

@@ -2616,7 +2616,7 @@ int EQ2Emu_lua_AddControlEffect(lua_State* state) {
 					lua_interface->LogError("%s: Unhandled control effect type of %u.", lua_interface->GetScriptName(state), type);
 			}
 			else
-				lua_interface->LogError("%s: Error applying control effect on non entity '%s'.", lua_interface->GetScriptName(state), target->GetName());
+				lua_interface->LogError("%s: Error applying control effect on non entity '%s'.", lua_interface->GetScriptName(state), (target != nullptr) ? target->GetName() : "NO_TARGET");
 		}
 		luaspell->MSpellTargets.releasereadlock(__FUNCTION__, __LINE__);
 	}
@@ -2685,7 +2685,7 @@ int EQ2Emu_lua_AddControlEffect(lua_State* state) {
 			lua_interface->LogError("%s: Unhandled control effect type of %u.", lua_interface->GetScriptName(state), type);
 	}
 	else
-		lua_interface->LogError("%s: Error applying control effect on non entity '%s'.", lua_interface->GetScriptName(state), spawn->GetName());
+		lua_interface->LogError("%s: Error applying control effect on non entity '%s'.", lua_interface->GetScriptName(state), (spawn != nullptr) ? spawn->GetName() : "NO_SPAWN");
 	return 0;
 }
 

+ 52 - 4
EQ2/source/WorldServer/Player.cpp

@@ -1575,7 +1575,7 @@ EQ2Packet* PlayerInfo::serialize(int16 version, int16 modifyPos, int32 modifyVal
 				int16 tmpsize = modifyPos + 128;
 				if (tmpsize > size)
 					tmpsize = size;
-				DumpPacket(ptr2, tmpsize - modifyPos);
+				//DumpPacket(ptr2, tmpsize - modifyPos);
 			}
 			size = Pack(tmp, changes, size, size, version, reverse);
 			//DumpPacket(tmp, size);
@@ -2126,6 +2126,7 @@ vector<EQ2Packet*> Player::EquipItem(int16 index, int16 version, int8 appearance
 		}
 		int8 slot = equipList->GetFreeSlot(item, slot_id);
 		bool canEquip = CanEquipItem(item);
+		int32 conflictSlot = 0;
 		
 		if(canEquip && !appearance_type && item->CheckFlag2(APPEARANCE_ONLY))
 		{
@@ -2133,6 +2134,27 @@ vector<EQ2Packet*> Player::EquipItem(int16 index, int16 version, int8 appearance
 			GetClient()->SimpleMessage(CHANNEL_COLOR_RED, "This item is for appearance slots only.");
 			return packets;
 		}
+		else if(canEquip && (conflictSlot = equipList->CheckSlotConflict(item)) > 0) {
+			bool abort = true;
+			switch(conflictSlot) {
+				case LORE:
+					GetClient()->SimpleMessage(CHANNEL_COLOR_RED, "Lore conflict, cannot equip this item.");
+					break;
+				case LORE_EQUIP:
+					GetClient()->SimpleMessage(CHANNEL_COLOR_RED, "You already have this item equipped, you cannot equip another.");
+					break;
+				case STACK_LORE:
+					GetClient()->SimpleMessage(CHANNEL_COLOR_RED, "Cannot equip as it exceeds lore stack.");
+					break;
+				default:
+					abort = false;
+					break;
+			}
+			if(abort) {
+				item_list.MPlayerItems.releasereadlock(__FUNCTION__, __LINE__);
+				return packets;
+			}
+		}
 		else if (canEquip && item->CheckFlag(ATTUNEABLE)) {
 			PacketStruct* packet = configReader.getStruct("WS_ChoiceWindow", version);
 			char text[255];
@@ -2239,9 +2261,36 @@ vector<EQ2Packet*> Player::EquipItem(int16 index, int16 version, int8 appearance
 
 	return packets;
 }
-bool Player::AddItem(Item* item) {
+bool Player::AddItem(Item* item, AddItemType type) {
+	int32 conflictItemList = 0, conflictequipmentList = 0, conflictAppearanceEquipmentList = 0;
+	int16 lore_stack_count = 0;
 	if (item && item->details.item_id > 0) {
-		if (item_list.AssignItemToFreeSlot(item)) {
+		if( ((conflictItemList = item_list.CheckSlotConflict(item, true, true, &lore_stack_count)) == LORE ||
+		   (conflictequipmentList = equipment_list.CheckSlotConflict(item, true, &lore_stack_count)) == LORE ||
+		   (conflictAppearanceEquipmentList = appearance_equipment_list.CheckSlotConflict(item, true, &lore_stack_count)) == LORE) && !item->CheckFlag(STACK_LORE)) {
+			   
+			switch(type)
+			{
+				case AddItemType::BUY_FROM_BROKER:
+				client->Message(CHANNEL_COLOR_CHAT_RELATIONSHIP, "You already own this item and cannot have another.");
+				break;
+				default:
+				client->Message(CHANNEL_COLOR_CHAT_RELATIONSHIP, "You cannot obtain %s due to lore conflict.", item->name.c_str());
+				break;			
+			}
+			return false;
+		}
+		else if(conflictItemList == STACK_LORE || conflictequipmentList == STACK_LORE || 
+				conflictAppearanceEquipmentList == STACK_LORE) {
+					switch(type)
+					{
+						default:
+						client->Message(CHANNEL_COLOR_CHAT_RELATIONSHIP, "You already have one stack of the LORE item: %s.", item->name.c_str());
+						break;			
+					}
+			return false;
+		}
+		else if (item_list.AssignItemToFreeSlot(item)) {
 			item->save_needed = true;
 			return true;
 		}
@@ -3835,7 +3884,6 @@ bool Player::SetSpawnSentState(Spawn* spawn, SpawnState state) {
 		}
 		else if(state == SpawnState::SPAWN_STATE_REMOVING && 
 			spawn_state_list.count(spawn->GetID()) == 0) {
-			spawn_state_list.erase(spawn->GetID());
 			SpawnQueueState* removal = new SpawnQueueState;
 			removal->index_id = index;
 			removal->spawn_state_timer = Timer(1000, true);

+ 7 - 1
EQ2/source/WorldServer/Player.h

@@ -410,6 +410,12 @@ private:
 	Mutex MFlagChanges;
 };
 
+enum AddItemType {
+	NOT_SET = 0,
+	BUY_FROM_BROKER = 1,
+	GM_COMMAND = 2
+};
+
 class Player : public Entity{
 public:
 	Player();
@@ -498,7 +504,7 @@ public:
 	Quest* SetStepComplete(int32 quest_id, int32 step);
 	Quest* AddStepProgress(int32 quest_id, int32 step, int32 progress);
 	int32  GetStepProgress(int32 quest_id, int32 step_id);
-	bool AddItem(Item* item);
+	bool AddItem(Item* item, AddItemType type = AddItemType::NOT_SET);
 	bool AddItemToBank(Item* item);
 	int16 GetSpellSlotMappingCount();
 	int16 GetSpellPacketCount();

+ 2 - 2
EQ2/source/WorldServer/Spawn.cpp

@@ -620,8 +620,8 @@ EQ2Packet* Spawn::spawn_serialize(Player* player, int16 version, int16 offset, i
 		}
 		cout << "setting offset: " << offset << " to: " << value << endl;
 	}
-	if (offset > 0)
-		DumpPacket(part2, part2_size);
+	//if (offset > 0)
+	//	DumpPacket(part2, part2_size);
 
 	uchar tmp[4000];
 	bool reverse = (version > 283);

+ 3 - 2
EQ2/source/WorldServer/Spawn.h

@@ -1283,6 +1283,9 @@ public:
 
 	void SetDeletedSpawn(bool val) { deleted_spawn = val; }
 	bool IsDeletedSpawn() { return deleted_spawn; }
+	
+	EquipmentItemList equipment_list;
+	EquipmentItemList appearance_equipment_list;
 protected:
 
 	bool	has_quests_required;
@@ -1316,8 +1319,6 @@ protected:
 	int32			pickup_unique_item_id;
 	map<int32, vector<int16>* > required_quests;
 	map<int32, LUAHistory*> required_history;
-	EquipmentItemList equipment_list;
-	EquipmentItemList appearance_equipment_list;
 
 	MutexList<SpawnProximity*> spawn_proximities;
 

+ 0 - 1
EQ2/source/WorldServer/WorldDatabase.h

@@ -291,7 +291,6 @@ public:
 	map<int32, vector<LevelArray*> >*	LoadSpellClasses();
 	void	LoadTransporters(ZoneServer* zone);
 	void	LoadTransportMaps(ZoneServer* zone);
-	void	LoadDataFromRow(MYSQL_ROW row, Item* item); // JA - eventually get rid of this function when all DB calls are converted
 	void	LoadDataFromRow(DatabaseResult *result, Item* item);
 	void	LoadCharacterItemList(int32 account_id, int32 char_id, Player* player, int16);
 	bool	loadCharacter(const char* name, int32 account_id, Client* client);

+ 27 - 14
EQ2/source/WorldServer/client.cpp

@@ -2091,8 +2091,7 @@ bool Client::HandlePacket(EQApplicationPacket* app) {
 	}
 	case OP_BuyPlayerHouseMsg: {
 		LogWrite(OPCODE__DEBUG, 1, "Opcode", "Opcode 0x%X (%i): OP_BuyPlayerHouseMsg", opcode, opcode);
-		DumpPacket(app);
-
+		
 		PacketStruct* packet = configReader.getStruct("WS_BuyHouse", GetVersion());
 		if (packet) {
 			packet->LoadPacketData(app->pBuffer, app->size);
@@ -2148,7 +2147,7 @@ bool Client::HandlePacket(EQApplicationPacket* app) {
 	}
 	case OP_EnterHouseMsg: {
 		LogWrite(OPCODE__DEBUG, 1, "Opcode", "Opcode 0x%X (%i): OP_EnterHouseMsg", opcode, opcode);
-		DumpPacket(app);
+		
 		PacketStruct* packet = configReader.getStruct("WS_EnterHouse", GetVersion());
 		if (packet) {
 			packet->LoadPacketData(app->pBuffer, app->size);
@@ -2169,7 +2168,7 @@ bool Client::HandlePacket(EQApplicationPacket* app) {
 	}
 	case OP_PayHouseUpkeepMsg: {
 		LogWrite(OPCODE__DEBUG, 1, "Opcode", "Opcode 0x%X (%i): OP_PayHouseUpkeepMsg", opcode, opcode);
-		DumpPacket(app);
+		
 		PacketStruct* packet = configReader.getStruct("WS_PayUpkeep", GetVersion());
 
 		if (packet) {
@@ -2303,7 +2302,6 @@ bool Client::HandlePacket(EQApplicationPacket* app) {
 				}
 			}
 		}
-		DumpPacket(app);
 		break;
 	}
 	case OP_QuestJournalWaypointMsg: {
@@ -2524,6 +2522,18 @@ bool Client::HandleLootItem(Spawn* entity, Item* item) {
 		SimpleMessage(CHANNEL_COLOR_YELLOW, "Unable to find item to loot!");
 		return false;
 	}
+	int32 conflictItemList = 0, conflictequipmentList = 0, conflictAppearanceEquipmentList = 0;
+	int16 lore_stack_count = 0;
+	if(((conflictItemList = player->item_list.CheckSlotConflict(item, true, true, &lore_stack_count)) == LORE ||
+	   (conflictequipmentList = player->equipment_list.CheckSlotConflict(item, true, &lore_stack_count)) == LORE ||
+	   (conflictAppearanceEquipmentList = player->appearance_equipment_list.CheckSlotConflict(item, true, &lore_stack_count)) == LORE) && !item->CheckFlag(STACK_LORE)) {
+		Message(CHANNEL_COLOR_RED, "You cannot loot %s due to lore conflict.", item->name.c_str());
+		return false;
+	}
+	else if(conflictItemList == STACK_LORE || conflictequipmentList == STACK_LORE || conflictAppearanceEquipmentList == STACK_LORE) {
+		Message(CHANNEL_COLOR_RED, "You cannot loot %s due to stack lore conflict.", item->name.c_str());
+		return false;
+	}
 	if (player->item_list.HasFreeSlot() || player->item_list.CanStack(item)) {
 		if (player->item_list.AssignItemToFreeSlot(item)) {
 			int8 type = CHANNEL_LOOT;
@@ -5032,7 +5042,6 @@ void Client::Loot(int32 total_coins, vector<Item*>* items, Spawn* entity) {
 			outapp = packet->serialize();
 		}
 		if (outapp) {
-			DumpPacket(outapp);
 			QueuePacket(outapp);
 		}
 		safe_delete_array(data);
@@ -6485,7 +6494,7 @@ void Client::SaveCombineSpawns(const char* name) {
 	combine_spawn = 0;
 }
 
-bool Client::AddItem(int32 item_id, int16 quantity) {
+bool Client::AddItem(int32 item_id, int16 quantity, AddItemType type) {
 	Item* master_item = master_item_list.GetItem(item_id);
 	Item* item = 0;
 	if (master_item)
@@ -6493,7 +6502,8 @@ bool Client::AddItem(int32 item_id, int16 quantity) {
 	if (item) {
 		if (quantity > 0)
 			item->details.count = quantity;
-		return AddItem(item);
+		
+		return AddItem(item, nullptr, type);
 	}
 	else
 		Message(CHANNEL_COLOR_RED, "Could not find item with id of: %i", item_id);
@@ -6501,7 +6511,7 @@ bool Client::AddItem(int32 item_id, int16 quantity) {
 	return false;
 }
 
-bool Client::AddItem(Item* item, bool* item_deleted) {
+bool Client::AddItem(Item* item, bool* item_deleted, AddItemType type) {
 	if (!item) {
 		return false;
 	}
@@ -6509,7 +6519,7 @@ bool Client::AddItem(Item* item, bool* item_deleted) {
 		if (GetVersion() <= 283 && item->details.num_slots > CLASSIC_EQ_MAX_BAG_SLOTS)
 			item->details.num_slots = CLASSIC_EQ_MAX_BAG_SLOTS;		
 	}
-	if (player->AddItem(item)) {
+	if (player->AddItem(item, type)) {
 		EQ2Packet* outapp = player->SendInventoryUpdate(GetVersion());
 		if (outapp) {
 			//DumpPacket(outapp);
@@ -6530,7 +6540,7 @@ bool Client::AddItem(Item* item, bool* item_deleted) {
 			lua_interface->RunItemScript(item->GetItemScript(), "obtained", item, player);
 	}
 	else {
-		SimpleMessage(CHANNEL_COLOR_RED, "Could not find free slot to place item.");
+		// likely lore conflict
 		safe_delete(item);
 
 		if(item_deleted)
@@ -6579,7 +6589,7 @@ bool Client::AddItemToBank(Item* item) {
 			lua_interface->RunItemScript(item->GetItemScript(), "obtained", item, player);
 	}
 	else {
-		SimpleMessage(CHANNEL_COLOR_RED, "Could not find free slot to place item.");
+		// likely lore conflict
 		safe_delete(item);
 		return false;
 	}
@@ -7928,7 +7938,6 @@ void Client::SendMailList() {
 			p->setDataByName("unknown3", 0x01F4);
 			p->setDataByName("unknown4", 0x01000000);
 			EQ2Packet* pack = p->serialize();
-			DumpPacket(pack->pBuffer, pack->size);
 			QueuePacket(pack);
 			safe_delete(p);
 		}
@@ -7987,7 +7996,6 @@ void Client::DisplayMailMessage(int32 mail_id) {
 				mail->already_read = true;
 				mail->save_needed = true;
 				EQ2Packet* pack = packet->serialize();
-				DumpPacket(pack);
 				QueuePacket(pack);
 				safe_delete(packet);
 				// trying to update this causes the window not to open
@@ -8112,6 +8120,11 @@ void Client::DeleteMail(int32 mail_id, bool from_database) {
 }
 bool Client::AddMailItem(Item* item)
 {
+	if(item && (item->CheckFlag(LORE) || item->CheckFlag(STACK_LORE))) {
+		Message(CHANNEL_COLOR_CHAT_RELATIONSHIP, "Lore items cannot be mailed.");
+		return false;
+	}
+	
 	bool ret = false;
 	if (GetMailTransaction()) {
 		MMailWindowMutex.lock();

+ 2 - 2
EQ2/source/WorldServer/client.h

@@ -197,8 +197,8 @@ public:
 	void	BankDeposit(int64 amount);
 	Spawn*	GetBanker();
 	void	SetBanker(Spawn* in_banker);
-	bool	AddItem(int32 item_id, int16 quantity = 0);
-	bool	AddItem(Item* item, bool* item_deleted = 0);
+	bool	AddItem(int32 item_id, int16 quantity = 0, AddItemType type = AddItemType::NOT_SET);
+	bool	AddItem(Item* item, bool* item_deleted = 0, AddItemType type = AddItemType::NOT_SET);
 	bool	AddItemToBank(int32 item_id, int16 quantity = 0);
 	bool	AddItemToBank(Item* item);
 	bool	RemoveItem(Item *item, int16 quantity, bool force_override_no_delete = false);

+ 1 - 1
EQ2/source/WorldServer/zoneserver.cpp

@@ -3400,7 +3400,7 @@ void ZoneServer::HandleChatMessage(Client* client, Spawn* from, const char* to,
 			if (channel_name)
 				packet->setMediumStringByName("channel_name", channel_name);
 			EQ2Packet* outapp = packet->serialize();
-			DumpPacket(outapp);
+			//DumpPacket(outapp);
 			client->QueuePacket(outapp);
 			safe_delete(packet);
 		}