public void HandlePacket(GameClient client, GSPacketIn packet)
		{
			if (client == null || client.Player == null) 
				return;

			ushort objectType = packet.ReadShort();

			uint extraID = 0;
			if (client.Version >= GameClient.eClientVersion.Version186)
			{
				extraID = packet.ReadInt();
			}

			ushort objectID = packet.ReadShort();

			string caption = "";
			var objectInfo = new List<string>();

			/*
			Type    Description         Id
			1       Inventory item      Slot (ie. 0xC for 2 handed weapon)
			2       Spell               spell level + spell line ID * 100 (starting from 0)
			3       ???
			4       Merchant item       Slot (divide by 30 to get page)
			5       Buff/effect         The buff id (each buff has a unique id)
			6       Style               style list index = ID-100-abilities count
			7       Trade window        position in trade window (starting form 0)
			8       Ability             100+position in players abilities list (?)
			9       Trainers skill      position in trainers window list
			10		Market Search		slot?
			19		Reward Quest
			 */

			ChatUtil.SendDebugMessage(client, string.Format("Delve objectType={0}, objectID={1}, extraID={2}", objectType, objectID, extraID));

			ItemTemplate item = null;
			InventoryItem invItem = null;

			var snapSkills = client.Player.GetAllUsableSkills();
			var snapLists = client.Player.GetAllUsableListSpells();
			// find the first non-specialization index.
			int indexAtSpecOid = Math.Max(0, snapSkills.FindIndex(it => (it.Item1 is Specialization) == false)) + (objectID - 100);
			
			switch (objectType)
			{
					#region Inventory Item
				case 1: //Display Infos on inventory item
				case 10: // market search
					{
						if (objectType == 1)
						{
							IGameInventoryObject invObject = client.Player.TargetObject as IGameInventoryObject;

							// first try any active inventory object
							if (invItem == null)
							{
								if (client.Player.ActiveInventoryObject != null)
								{
									invObject = client.Player.ActiveInventoryObject;

									if (invObject != null && invObject.GetClientInventory(client.Player) != null)
									{
										invObject.GetClientInventory(client.Player).TryGetValue(objectID, out invItem);
									}
								}
							}

							// finally try direct inventory access
							if (invItem == null)
							{
								invItem = client.Player.Inventory.GetItem((eInventorySlot)objectID);
							}

							// Failed to get any inventory
							if (invItem == null)
								return;

						}
						else if (objectType == 10)
						{
							List<InventoryItem> list = client.Player.TempProperties.getProperty<object>(MarketExplorer.EXPLORER_ITEM_LIST, null) as List<InventoryItem>;
							if (list == null)
							{
								list = client.Player.TempProperties.getProperty<object>("TempSearchKey", null) as List<InventoryItem>;
								if (list == null)
									return;
							}

							if (objectID >= list.Count)
								return;

							invItem = list[objectID];

							if (invItem == null)
								return;
						}

						// Aredhel: Start of a more sophisticated item delve system.
						// The idea is to have every item inherit from an item base class,
						// this base class will provide a method
						//
						// public virtual void Delve(List<String>, GamePlayer player)
						//
						// which can be overridden in derived classes to provide additional
						// information. Same goes for spells, just add the spell delve
						// in the Delve() hierarchy. This will on one hand make this class
						// much more concise (1800 lines at the time of this writing) and
						// on the other hand the whole delve system much more flexible, for
						// example when adding new item types (artifacts, for example) you
						// provide *only* an overridden Delve() method, use the base
						// Delve() and you're done, spells, charges and everything else.

						// Let the player class create the appropriate item to delve
						caption = invItem.Name;

						if (client.Player.DelveItem<InventoryItem>(invItem, objectInfo))
							break;

						#region Old Delve

						if (invItem is InventoryArtifact)
						{
							List<String> delve = new List<String>();
							(invItem as InventoryArtifact).Delve(delve, client.Player);

							foreach (string line in delve)
								objectInfo.Add(line);

							break;
						}

						//**********************************
						//show crafter name
						//**********************************
						if (invItem.IsCrafted)
						{
							objectInfo.Add(LanguageMgr.GetTranslation(client.Account.Language, "DetailDisplayHandler.HandlePacket.CrafterName", invItem.Creator));
							objectInfo.Add(" ");
						}
						else if (invItem.Description != null && invItem.Description != "")
						{
							objectInfo.Add(invItem.Description);
							objectInfo.Add(" ");
						}

						if ((invItem.Object_Type >= (int)eObjectType.GenericWeapon) && (invItem.Object_Type <= (int)eObjectType._LastWeapon) ||
						    invItem.Object_Type == (int)eObjectType.Instrument)
						{
							WriteUsableClasses(objectInfo, invItem, client);
							WriteMagicalBonuses(objectInfo, invItem, client, false);
							WriteClassicWeaponInfos(objectInfo, invItem, client);
						}

						if (invItem.Object_Type >= (int)eObjectType.Cloth && invItem.Object_Type <= (int)eObjectType.Scale)
						{
							WriteUsableClasses(objectInfo, invItem, client);
							WriteMagicalBonuses(objectInfo, invItem, client, false);
							WriteClassicArmorInfos(objectInfo, invItem, client);
						}

						if (invItem.Object_Type == (int)eObjectType.Shield)
						{
							WriteUsableClasses(objectInfo, invItem, client);
							WriteMagicalBonuses(objectInfo, invItem, client, false);
							WriteClassicShieldInfos(objectInfo, invItem, client);
						}

						if (invItem.Object_Type == (int)eObjectType.Magical || invItem.Object_Type == (int)eObjectType.AlchemyTincture || invItem.Object_Type == (int)eObjectType.SpellcraftGem)
						{
							WriteMagicalBonuses(objectInfo, invItem, client, false);
						}

						//***********************************
						//shows info for Poison Potions
						//***********************************
						if (invItem.Object_Type == (int)eObjectType.Poison)
						{
							WritePoisonInfo(objectInfo, invItem, client);
						}

						if (invItem.Object_Type == (int)eObjectType.Magical && invItem.Item_Type == (int)eInventorySlot.FirstBackpack) // potion
						{
							WritePotionInfo(objectInfo, invItem, client);
						}
						else if (invItem.CanUseEvery > 0)
						{
							// Items with a reuse timer (aka cooldown).
							objectInfo.Add(" ");

							int minutes = invItem.CanUseEvery / 60;
							int seconds = invItem.CanUseEvery % 60;

							if (minutes == 0)
							{
								objectInfo.Add(String.Format("Can use item every: {0} sec", seconds));
							}
							else
							{
								objectInfo.Add(String.Format("Can use item every: {0}:{1:00} min", minutes, seconds));
							}

							// objectInfo.Add(String.Format("Can use item every: {0:00}:{1:00}", minutes, seconds));

							int cooldown = invItem.CanUseAgainIn;

							if (cooldown > 0)
							{
								minutes = cooldown / 60;
								seconds = cooldown % 60;

								if (minutes == 0)
								{
									objectInfo.Add(String.Format("Can use again in: {0} sec", seconds));
								}
								else
								{
									objectInfo.Add(String.Format("Can use again in: {0}:{1:00} min", minutes, seconds));
								}

								// objectInfo.Add(String.Format("Can use again in: {0:00}:{1:00}", minutes, seconds));
							}
						}

						if (!invItem.IsDropable || !invItem.IsPickable || invItem.IsIndestructible)
							objectInfo.Add(" ");

						if (!invItem.IsPickable)
							objectInfo.Add(LanguageMgr.GetTranslation(client.Account.Language, "DetailDisplayHandler.HandlePacket.CannotTraded"));

						if (!invItem.IsDropable)
							objectInfo.Add(LanguageMgr.GetTranslation(client.Account.Language, "DetailDisplayHandler.HandlePacket.CannotSold"));

						if (invItem.IsIndestructible)
							objectInfo.Add(LanguageMgr.GetTranslation(client.Account.Language, "DetailDisplayHandler.HandlePacket.CannotDestroyed"));


						if (invItem.BonusLevel > 0)
						{
							objectInfo.Add(" ");
							objectInfo.Add(LanguageMgr.GetTranslation(client.Account.Language, "DetailDisplayHandler.HandlePacket.BonusLevel", invItem.BonusLevel));

						}

						//Add admin info
						if (client.Account.PrivLevel > 1)
						{
							WriteTechnicalInfo(objectInfo, client, invItem);
						}

						break;

						#endregion Old Delve
					}
					#endregion
					#region Spell
				case 2: //spell List
					{
						int lineID = objectID / 100;
						int spellID = objectID % 100;

						Skill sk = null;
						SpellLine sl = null;
						
						// is spelline in index ?
						if (lineID < snapLists.Count)
						{
							int index = snapLists[lineID].Item2.FindIndex(s => s is Spell ? 
							                                                   s.Level == spellID 
							                                                   : (s is Styles.Style ? ((Styles.Style)s).SpecLevelRequirement == spellID
							                                                      : (s is Ability ? ((Ability)s).SpecLevelRequirement == spellID : false)));
							
							if (index > -1)
							{
								sk = snapLists[lineID].Item2[index];
							}
							
							sl = snapLists[lineID].Item1;
						}
						
						if (sk is Spell && sl != null)
						{
							caption = sk.Name;
							WriteSpellInfo(objectInfo, (Spell)sk, sl, client);
						}
						else if (sk is Styles.Style)
						{
							caption = sk.Name;
							WriteStyleInfo(objectInfo, (Style)sk, client);
						}
						else if (sk is Ability)
						{
							caption = sk.Name;
							Ability abil = (Ability)sk;
							
							if (abil.DelveInfo.Count > 0)
								objectInfo.AddRange(abil.DelveInfo);
							else
								objectInfo.Add("There is no special information.");
						}
		
						break;
					}
				case 3: //spell Hybrid
					{	
						
	
						SpellLine spellLine = null;
						Spell spell = null;
	
						// are we in list ?
						if (indexAtSpecOid < snapSkills.Count)
						{
							spell = (Spell)snapSkills[indexAtSpecOid].Item1;
							spellLine = (SpellLine)snapSkills[indexAtSpecOid].Item2;
						}
						
						if (spell == null || spellLine == null)
							return;
	
						caption = spell.Name;
						WriteSpellInfo(objectInfo, spell, spellLine, client);	
						break;
					}
					#endregion
					#region Merchant / RewardQuest
				case 4: //Display Infos on Merchant objects
				case 19: //Display Info quest reward
					{
						if (objectType == 4)
						{
							GameMerchant merchant = null;
							if (client.Player.TargetObject != null && client.Player.TargetObject is GameMerchant)
								merchant = (GameMerchant)client.Player.TargetObject;
							if (merchant == null)
								return;

							byte pagenumber = (byte)(objectID / MerchantTradeItems.MAX_ITEM_IN_TRADEWINDOWS);
							short slotnumber = (short)(objectID % MerchantTradeItems.MAX_ITEM_IN_TRADEWINDOWS);

							item = merchant.TradeItems.GetItem(pagenumber, (eMerchantWindowSlot)slotnumber);
						}
						else if (objectType == 19)
						{
							ushort questID = (ushort)((extraID << 12) | (ushort)(objectID >> 4));
							int index = objectID & 0x0F;

							GameLiving questGiver = null;
							if (client.Player.TargetObject != null && client.Player.TargetObject is GameLiving)
								questGiver = (GameLiving)client.Player.TargetObject;

							ChatUtil.SendDebugMessage(client, "Quest ID: " + questID);

							if (questID == 0)
								return; // questID == 0, wrong ID ?
							
							if (questID <= DataQuest.DATAQUEST_CLIENTOFFSET)
							{
								AbstractQuest q = client.Player.IsDoingQuest(QuestMgr.GetQuestTypeForID(questID));

								if (q == null)
								{
									// player not doing quest, most likely on offer screen
									if (questGiver != null)
									{
										try
										{
											q = (AbstractQuest)Activator.CreateInstance(QuestMgr.GetQuestTypeForID(questID), new object[] { client.Player, 1 });
										}
										catch
										{
											// we tried!
										}
									}

									if (q == null)
									{
										ChatUtil.SendDebugMessage(client, "Can't find or create quest!");
										return;
									}
								}

								if (!(q is RewardQuest))
									return; // this is not new quest

								List<ItemTemplate> rewards = null;
								if (index < 8)
									rewards = (q as RewardQuest).Rewards.BasicItems;
								else
								{
									rewards = (q as RewardQuest).Rewards.OptionalItems;
									index -= 8;
								}
								if (rewards != null && index >= 0 && index < rewards.Count)
								{
									item = rewards[index];
								}
							}
							else // Data quest support, check for RewardQuest type
							{
								DataQuest dq = null;

								foreach (DBDataQuest d in GameObject.DataQuestCache)
								{
									if (d.ID == questID - DataQuest.DATAQUEST_CLIENTOFFSET)
									{
										dq = new DataQuest(d);
										break;
									}
								}

								if (dq != null && dq.StartType == DataQuest.eStartType.RewardQuest)
								{
									List<ItemTemplate> rewards = null;
									if (index < 8)
										rewards = dq.FinalRewards;
									else
									{
										rewards = dq.OptionalRewards;
										index -= 8;
									}
									if (rewards != null && index >= 0 && index < rewards.Count)
									{
										item = rewards[index];
									}
								}
							}

						}


						if (item == null)
							return;

						caption = item.Name;

						if (client.Player.DelveItem<ItemTemplate>(item, objectInfo))
							break;

						#region Old Delve

						// fallback to old delve

						if (item.Item_Type == (int)eInventorySlot.Horse)
						{
							WriteHorseInfo(objectInfo, item, client, "");
						}

						if ((item.Item_Type == (int)eInventorySlot.HorseBarding || item.Item_Type == (int)eInventorySlot.HorseArmor) && item.Level > 0)
						{
							objectInfo.Add(" ");//empty line
							objectInfo.Add(" ");//empty line
							objectInfo.Add(LanguageMgr.GetTranslation(client.Account.Language, "DetailDisplayHandler.HandlePacket.ChampionLevel", item.Level));
						}

						if ((item.Object_Type >= (int)eObjectType.GenericWeapon) && (item.Object_Type <= (int)eObjectType.MaulerStaff) ||
						    item.Object_Type == (int)eObjectType.Instrument)
						{
							WriteUsableClasses(objectInfo, item, client);
							WriteMagicalBonuses(objectInfo, item, client, false);
							WriteClassicWeaponInfos(objectInfo, GameInventoryItem.Create(item), client);
						}

						if (item.Object_Type >= (int)eObjectType.Cloth && item.Object_Type <= (int)eObjectType.Scale)
						{
							WriteUsableClasses(objectInfo, item, client);
							WriteMagicalBonuses(objectInfo, item, client, false);
							WriteClassicArmorInfos(objectInfo, GameInventoryItem.Create(item), client);
						}

						if (item.Object_Type == (int)eObjectType.Shield)
						{
							WriteUsableClasses(objectInfo, item, client);
							WriteMagicalBonuses(objectInfo, item, client, false);
							WriteClassicShieldInfos(objectInfo, item, client);
						}

						if ((item.Item_Type != (int)eInventorySlot.Horse && item.Object_Type == (int)eObjectType.Magical) || item.Object_Type == (int)eObjectType.AlchemyTincture || item.Object_Type == (int)eObjectType.SpellcraftGem)
						{
							WriteMagicalBonuses(objectInfo, item, client, false);
						}

						if (item.Object_Type == (int)eObjectType.Poison)
						{
							WritePoisonInfo(objectInfo, item, client);
						}

						if (item.Object_Type == (int)eObjectType.Magical && item.Item_Type == 40) // potion
							WritePotionInfo(objectInfo, item, client);

						//Add admin info
						if (client.Account.PrivLevel > 1)
						{
							WriteTechnicalInfo(objectInfo, client, GameInventoryItem.Create(item), item.MaxDurability, item.MaxCondition);
						}
						break;

						#endregion Old Delve
					}
					#endregion
					#region Effect
				case 5: //icons on top (buffs/dots)
					{
						IGameEffect foundEffect = null;
						lock (client.Player.EffectList)
						{
							foreach (IGameEffect effect in client.Player.EffectList)
							{
								if (effect.InternalID == objectID)
								{
									foundEffect = effect;
									break;
								}
							}
						}

						if (foundEffect == null) break;

						caption = foundEffect.Name;
						objectInfo.AddRange(foundEffect.DelveInfo);

						if (client.Account.PrivLevel > 1 && foundEffect is GameSpellEffect)
						{
							if ((foundEffect as GameSpellEffect).Spell != null)
							{
								if (client.Account.PrivLevel > 1)
								{
									objectInfo.Add(" ");
									objectInfo.Add("----------Technical informations----------");
									objectInfo.Add("Line: " + ((foundEffect as GameSpellEffect).SpellHandler == null ? "unknown" : (foundEffect as GameSpellEffect).SpellHandler.SpellLine.Name));
									objectInfo.Add("SpellID: " + (foundEffect as GameSpellEffect).Spell.ID);
									objectInfo.Add("Type: " + (foundEffect as GameSpellEffect).Spell.SpellType);
									objectInfo.Add("ClientEffect: " + (foundEffect as GameSpellEffect).Spell.ClientEffect);
									objectInfo.Add("Icon: " + (foundEffect as GameSpellEffect).Spell.Icon);
									if ((foundEffect as GameSpellEffect).SpellHandler != null)
										objectInfo.Add("HasPositiveEffect: " + (foundEffect as GameSpellEffect).SpellHandler.HasPositiveEffect);
									objectInfo.Add("Disabled: " + (foundEffect as GameSpellEffect).IsDisabled);
								}
							}
						}


						break;
					}
					#endregion
					#region Style
				case 6: //style
					{
						Style style = null;
						// are we in list ?
						if (indexAtSpecOid < snapSkills.Count)
						{
							style = (Style)snapSkills[indexAtSpecOid].Item1;
						}
						
						if (style == null)
							return;

						caption = style.Name;

						WriteStyleInfo(objectInfo, style, client);
						break;
					}
					#endregion
					#region Trade Window
				case 7: //trade windows
					{
						ITradeWindow playerTradeWindow = client.Player.TradeWindow;
						if (playerTradeWindow == null)
							return;

						if (playerTradeWindow.PartnerTradeItems != null && objectID < playerTradeWindow.PartnerItemsCount)
							invItem = (InventoryItem)playerTradeWindow.PartnerTradeItems[objectID];

						if (invItem == null)
							return;

						// Let the player class create the appropriate item to delve
						caption = invItem.Name;

						if (client.Player.DelveItem<InventoryItem>(invItem, objectInfo))
							break;

						#region Old Delve
						// fallback to old delve

						if (invItem.Item_Type == (int)eInventorySlot.Horse)
						{
							WriteHorseInfo(objectInfo, invItem, client, "");
						}

						if ((invItem.Item_Type == (int)eInventorySlot.HorseBarding || invItem.Item_Type == (int)eInventorySlot.HorseArmor) && invItem.Level > 0)
						{
							objectInfo.Add(" ");//empty line
							objectInfo.Add(" ");//empty line
							objectInfo.Add(LanguageMgr.GetTranslation(client.Account.Language, "DetailDisplayHandler.HandlePacket.ChampionLevel", invItem.Level));
						}
						if ((invItem.Object_Type >= (int)eObjectType.GenericWeapon) && (invItem.Object_Type <= (int)eObjectType.MaulerStaff) ||
						    invItem.Object_Type == (int)eObjectType.Instrument)
						{
							WriteUsableClasses(objectInfo, invItem, client);
							WriteMagicalBonuses(objectInfo, invItem, client, false);
							WriteClassicWeaponInfos(objectInfo, invItem, client);
						}

						if (invItem.Object_Type >= (int)eObjectType.Cloth && invItem.Object_Type <= (int)eObjectType.Scale)
						{
							WriteUsableClasses(objectInfo, invItem, client);
							WriteMagicalBonuses(objectInfo, invItem, client, false);
							WriteClassicArmorInfos(objectInfo, invItem, client);
						}

						if (invItem.Object_Type == (int)eObjectType.Shield)
						{
							WriteUsableClasses(objectInfo, invItem, client);
							WriteMagicalBonuses(objectInfo, invItem, client, false);
							WriteClassicShieldInfos(objectInfo, invItem, client);
						}

						if ((invItem.Item_Type != (int)eInventorySlot.Horse && invItem.Object_Type == (int)eObjectType.Magical) || invItem.Object_Type == (int)eObjectType.AlchemyTincture || invItem.Object_Type == (int)eObjectType.SpellcraftGem)
						{
							WriteMagicalBonuses(objectInfo, invItem, client, false);
						}

						if (invItem.Object_Type == (int)eObjectType.Poison)
						{
							WritePoisonInfo(objectInfo, invItem, client);
						}

						if (invItem.Object_Type == (int)eObjectType.Magical && invItem.Item_Type == 40) // potion
							WritePotionInfo(objectInfo, invItem, client);

						//Add admin info
						if (client.Account.PrivLevel > 1)
						{
							WriteTechnicalInfo(objectInfo, client, invItem);
						}

						break;

						#endregion Old Delve
					}
					#endregion
					#region Ability
				case 8://abilities
					{
						Ability abil = null;
						// are we in list ?
						if (indexAtSpecOid < snapSkills.Count)
						{
							abil = (Ability)snapSkills[indexAtSpecOid].Item1;
						}
						
						if (abil == null)
							return;
						
						caption = abil.Name;
						
						if (abil.DelveInfo.Count > 0)
							objectInfo.AddRange(abil.DelveInfo);
						else
							objectInfo.Add("There is no special information.");
						break;
					}
					#endregion
					#region Trainer
				case 9: //trainer window "info" button
					{
						Specialization spec = client.Player.GetSpecList().Where(e => e.Trainable).ElementAtOrDefault(objectID);
						
						if (spec != null)
							caption = spec.Name;
						
						if (client.TrainerSkillCache != null && objectID < client.TrainerSkillCache.Count)
						{
							objectInfo.Add(LanguageMgr.GetTranslation(client.Account.Language, "DetailDisplayHandler.HandlePacket.LevName"));
							foreach (Skill sk in client.TrainerSkillCache[objectID].Item2.Select(e => e.Item3))
							{
								if (sk is Ability)
									objectInfo.Add(string.Format("{0}: {1}", ((Ability)sk).SpecLevelRequirement, sk.Name));
								else if (sk is Style)
									objectInfo.Add(string.Format("{0}: {1}", ((Style)sk).SpecLevelRequirement, sk.Name));
								else
									objectInfo.Add(string.Format("{0}: {1}", sk.Level, sk.Name));
							}
						}
						else
						{
							//delve on realm abilities [by Suncheck]
							if (objectID >= 50)
							{
								int clientclassID = client.Player.CharacterClass.ID;
								int sub = 50;
								List<RealmAbility> ra_list = SkillBase.GetClassRealmAbilities(clientclassID);
								Ability ra5abil = SkillBase.GetClassRR5Ability(clientclassID);
								RealmAbility ab = ra_list[objectID - sub];
								if (ra5abil != null) //check if player have rr
								{
									if (client.Player.RealmPoints < 513500) //player have not rr5 abilty
										sub--;
								}
								for (int i = 0; i <= (objectID - sub); i++) //get all ra's at full level
								{
									RealmAbility raabil = ra_list[i];
									RealmAbility playerra = (RealmAbility)client.Player.GetAbility(raabil.KeyName);
									if (playerra != null)
										if (playerra.Level >= playerra.MaxLevel)
											sub--;
								}
								ab = ra_list[objectID - sub];
								if (ab != null)
								{
									caption = ab.Name;
									objectInfo.AddRange(ab.DelveInfo);
									break;
								}
							}
							caption = "Specialization not found";
							objectInfo.Add("that specialization is not found, id=" + objectID);
							break;
						}
						break;
					}
					#endregion
					#region Group
				case 12: // Item info to Group Chat
					{
						invItem = client.Player.Inventory.GetItem((eInventorySlot)objectID);
						if (invItem == null) return;
						string str = LanguageMgr.GetTranslation(client.Account.Language, "DetailDisplayHandler.HandlePacket.Item", client.Player.Name, GetShortItemInfo(invItem, client));
						if (client.Player.Group == null)
						{
							client.Out.SendMessage(LanguageMgr.GetTranslation(client.Account.Language, "DetailDisplayHandler.HandlePacket.NoGroup"), eChatType.CT_System, eChatLoc.CL_SystemWindow);
							return;
						}
						client.Player.Group.SendMessageToGroupMembers(str, eChatType.CT_Group, eChatLoc.CL_ChatWindow);
						return;
					}
					#endregion
					#region Guild
				case 13: // Item info to Guild Chat
					{
						invItem = client.Player.Inventory.GetItem((eInventorySlot)objectID);
						if (invItem == null) return;
						string str = LanguageMgr.GetTranslation(client.Account.Language, "DetailDisplayHandler.HandlePacket.GuildItem", client.Player.Name, GetShortItemInfo(invItem, client));
						if (client.Player.Guild == null)
						{
							client.Out.SendMessage(LanguageMgr.GetTranslation(client.Account.Language, "DetailDisplayHandler.HandlePacket.DontBelongGuild"), eChatType.CT_System, eChatLoc.CL_SystemWindow);
							return;
						}
						if (!client.Player.Guild.HasRank(client.Player, Guild.eRank.GcSpeak))
						{
							client.Out.SendMessage(LanguageMgr.GetTranslation(client.Account.Language, "DetailDisplayHandler.HandlePacket.NoPermissionToSpeak"), eChatType.CT_System, eChatLoc.CL_SystemWindow);
							return;
						}
						foreach (GamePlayer ply in client.Player.Guild.GetListOfOnlineMembers())
						{
							if (!client.Player.Guild.HasRank(ply, Guild.eRank.GcHear)) continue;
							ply.Out.SendMessage(str, eChatType.CT_Guild, eChatLoc.CL_ChatWindow);
						}
						return;
					}
					#endregion
					#region ChatGroup
				case 15: // Item info to Chat group
					{
						invItem = client.Player.Inventory.GetItem((eInventorySlot)objectID);
						if (invItem == null) return;

						ChatGroup mychatgroup = (ChatGroup)client.Player.TempProperties.getProperty<object>(ChatGroup.CHATGROUP_PROPERTY, null);
						if (mychatgroup == null)
						{
							client.Player.Out.SendMessage(LanguageMgr.GetTranslation(client.Account.Language, "DetailDisplayHandler.HandlePacket.MustBeInChatGroup"), eChatType.CT_System, eChatLoc.CL_SystemWindow);
							return;
						}
						if (mychatgroup.Listen == true && (((bool)mychatgroup.Members[client.Player]) == false))
						{
							client.Player.Out.SendMessage(LanguageMgr.GetTranslation(client.Account.Language, "DetailDisplayHandler.HandlePacket.OnlyModerator"), eChatType.CT_System, eChatLoc.CL_SystemWindow);
							return;
						}
						string str = LanguageMgr.GetTranslation(client.Account.Language, "DetailDisplayHandler.HandlePacket.ChatItem", client.Player.Name, GetShortItemInfo(invItem, client));
						foreach (GamePlayer ply in mychatgroup.Members.Keys)
						{
							ply.Out.SendMessage(str, eChatType.CT_Chat, eChatLoc.CL_ChatWindow);
						}
						return;
					}
					#endregion
					#region Trainer Window
					//styles
				case 20:
					{
						Style style = null;
						if (client.TrainerSkillCache != null)
						{
							// Search Id
							Skill sk = client.TrainerSkillCache.SelectMany(el => el.Item2).Where(e => e.Item2 == objectID && e.Item3.SkillType == eSkillPage.Styles).FirstOrDefault().Item3;
							if (sk is Style)
								style = (Style)sk;
						}
						
						if (style == null) return;

						caption = style.Name;
						WriteStyleInfo(objectInfo, style, client);
						break;
					}
					//spells
				case 22:
					//songs
				case 21:
					// Ability
				case 23:
					{
						Skill sk = null;
						if (client.TrainerSkillCache != null)
						{
							// Search Id
							sk = client.TrainerSkillCache.SelectMany(el => el.Item2).Where(e => ((objectType == 23 && e.Item2 == objectID && e.Item1 == 5) || (e.Item2 == objectID && e.Item1 != 5))).OrderBy(e => e.Item1).FirstOrDefault().Item3;
						}
						
						if (sk == null) return;
						
						if (sk is Spell)
						{
							Spell spell = (Spell)sk;
							caption = spell.Name;

							WriteSpellInfo(objectInfo, spell, SkillBase.GetSpellLine(GlobalSpellsLines.Reserved_Spells), client);
						}
						else if (sk is Ability)
						{
							Ability abil = (Ability)sk;
							caption = abil.Name;
						
							if (abil.DelveInfo.Count > 0)
								objectInfo.AddRange(abil.DelveInfo);
							else
								objectInfo.Add("There is no special information.");
						}
						
						break;
					}
					#endregion
					#region Repair
				case 100://repair
					{
						invItem = client.Player.Inventory.GetItem((eInventorySlot)objectID);
						if (invItem != null)
						{
							client.Player.RepairItem(invItem);
						}
						else
						{
							client.Out.SendMessage(LanguageMgr.GetTranslation(client.Account.Language, "DetailDisplayHandler.HandlePacket.VeryStrange"), eChatType.CT_System, eChatLoc.CL_SystemWindow);
						}
						return;
					}
					#endregion
					#region Self Craft
				case 101://selfcraft
					{
						invItem = client.Player.Inventory.GetItem((eInventorySlot)objectID);
						if (invItem != null)
						{
							client.Player.OpenSelfCraft(invItem);
						}
						else
						{
							client.Out.SendMessage(LanguageMgr.GetTranslation(client.Account.Language, "DetailDisplayHandler.HandlePacket.VeryStrange"), eChatType.CT_System, eChatLoc.CL_SystemWindow);
						}
						return;
					}
					#endregion
					#region Salvage
				case 102://salvage
					{
						invItem = client.Player.Inventory.GetItem((eInventorySlot)objectID);
						if (invItem != null)
						{
							client.Player.SalvageItem(invItem);
						}
						else
						{
							client.Out.SendMessage(LanguageMgr.GetTranslation(client.Account.Language, "DetailDisplayHandler.HandlePacket.VeryStrange"), eChatType.CT_System, eChatLoc.CL_SystemWindow);
						}
						return;
					}
					#endregion
					#region BattleGroup
				case 103: // Item info to battle group
					{
						invItem = client.Player.Inventory.GetItem((eInventorySlot)objectID);
						if (invItem == null) return;

						BattleGroup mybattlegroup = (BattleGroup)client.Player.TempProperties.getProperty<object>(BattleGroup.BATTLEGROUP_PROPERTY, null);
						if (mybattlegroup == null)
						{
							client.Player.Out.SendMessage(LanguageMgr.GetTranslation(client.Account.Language, "DetailDisplayHandler.HandlePacket.MustBeInBattleGroup"), eChatType.CT_System, eChatLoc.CL_SystemWindow);
							return;
						}
						if (mybattlegroup.Listen == true && (((bool)mybattlegroup.Members[client.Player]) == false))
						{
							client.Player.Out.SendMessage(LanguageMgr.GetTranslation(client.Account.Language, "DetailDisplayHandler.HandlePacket.OnlyModerator"), eChatType.CT_System, eChatLoc.CL_SystemWindow);
							return;
						}
						string str = LanguageMgr.GetTranslation(client.Account.Language, "DetailDisplayHandler.HandlePacket.ChatItem", client.Player.Name, GetShortItemInfo(invItem, client));
						foreach (GamePlayer ply in mybattlegroup.Members.Keys)
						{
							ply.Out.SendMessage(str, eChatType.CT_Chat, eChatLoc.CL_ChatWindow);
						}
						return;
					}
					#endregion
				#region v1.110+
				case 24://SpellsNew
					if (client.CanSendTooltip(24, objectID))
				        client.Out.SendDelveInfo(DelveSpell(client, objectID));
			        			        
					break;
				case 25://StylesNew
					if (client.CanSendTooltip(25, objectID))
	                    client.Out.SendDelveInfo(DelveStyle(client, objectID));
                    break;
				case 26://SongsNew
                    if (client.CanSendTooltip(26, objectID))
						client.Out.SendDelveInfo(DelveSong(client, objectID));
						client.Out.SendDelveInfo(DelveSpell(client, objectID));
					break;
				case 27://RANew
					if (client.CanSendTooltip(27, objectID))
	                   client.Out.SendDelveInfo(DelveRealmAbility(client, objectID));
                    break;
				case 28://AbilityNew
                    if (client.CanSendTooltip(28, objectID))
				        client.Out.SendDelveInfo(DelveAbility(client, objectID));
			        break;
				#endregion
				#region ChampionAbilities delve from trainer window
				default:
					{
						// Try retieving champion lines
						int clSpecID = objectType - 150;
						int clLineIndex = objectID >> 8;
						int clSkillIndex = objectID & 0x00FF;

						// Get Player CL Spec
						var clspec = client.Player.GetSpecList().Where(sp => sp is LiveChampionsSpecialization).Cast<LiveChampionsSpecialization>().FirstOrDefault();
						
						// check if the tree can be used
						List<Tuple<MiniLineSpecialization, List<Tuple<Skill, byte>>>> tree = null;
						if (clspec != null)
						{
							tree = clspec.GetTrainerTreeDisplay(client.Player, clspec.RetrieveTypeForIndex(clSpecID));
						}
						
						// Try and handle all Champion lines, including custom lines
						if (tree != null)
						{
							try
							{
								Skill skill = tree[clLineIndex].Item2[clSkillIndex].Item1;
								if (skill != null)
								{
									if (skill is Spell)
									{
										SpellLine spellLine = clspec.GetSpellLinesForLiving(client.Player).FirstOrDefault();
										if (spellLine != null)
										{
											caption = skill.Name;
											WriteSpellInfo(objectInfo, (Spell)skill, spellLine, client);
										}
										else
										{
											objectInfo.Add("Champion spell line not found!");
										}
									}
									else if (skill is Style)
									{
										caption = skill.Name;
										WriteStyleInfo(objectInfo, (Style)skill, client);
									}
								}
							}
							catch
							{
							}
						}

						break;
					}
					#endregion
			}

			if (objectInfo.Count > 0)
			{
				client.Out.SendCustomTextWindow(caption, objectInfo);
			}
			else if ((objectType < 24 || objectType > 28) && objectType < 150) // only warn for non v1.110+ objects
			{
				log.WarnFormat("DetailDisplayHandler no info for objectID {0} of type {1}. Item: {2}, client: {3}", objectID, objectType, (item == null ? (invItem == null ? "null" : invItem.Id_nb) : item.Id_nb), client);
			}
		}