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); } }