protected override void SendQuestWindow(GameNPC questNPC, GamePlayer player, DataQuest quest, bool offer) { GSTCPPacketOut pak = new GSTCPPacketOut(GetPacketCode(eServerPackets.Dialog)); ushort QuestID = quest.ClientQuestID; pak.WriteShort((offer) ? (byte)0x22 : (byte)0x21); // Dialog pak.WriteShort(QuestID); pak.WriteShort((ushort)questNPC.ObjectID); pak.WriteByte(0x00); // unknown pak.WriteByte(0x00); // unknown pak.WriteByte(0x00); // unknown pak.WriteByte(0x00); // unknown pak.WriteByte((offer) ? (byte)0x02 : (byte)0x01); // Accept/Decline or Finish/Not Yet pak.WriteByte(0x01); // Wrap pak.WritePascalString(quest.Name); String personalizedSummary = BehaviourUtils.GetPersonalizedMessage(quest.Description, player); if (personalizedSummary.Length > 255) { pak.WritePascalString(personalizedSummary.Substring(0, 255)); // Summary is max 255 bytes ! } else { pak.WritePascalString(personalizedSummary); } if (offer) { //String personalizedStory = BehaviourUtils.GetPersonalizedMessage(quest.Story, player); pak.WriteShort((ushort)quest.Story.Length); pak.WriteStringBytes(quest.Story); } else { pak.WriteShort((ushort)quest.FinishText.Length); pak.WriteStringBytes(quest.FinishText); } pak.WriteShort(QuestID); pak.WriteByte((byte)quest.StepTexts.Count); // #goals count foreach (string text in quest.StepTexts) { pak.WritePascalString(String.Format("{0}\r", text)); } pak.WriteInt((uint)(0)); pak.WriteByte((byte)0); pak.WriteByte((byte)quest.FinalRewards.Count); foreach (ItemTemplate reward in quest.FinalRewards) { WriteItemData(pak, GameInventoryItem.Create<ItemTemplate>(reward)); } pak.WriteByte((byte)quest.NumOptionalRewardsChoice); pak.WriteByte((byte)quest.OptionalRewards.Count); foreach (ItemTemplate reward in quest.OptionalRewards) { WriteItemData(pak, GameInventoryItem.Create<ItemTemplate>(reward)); } SendTCP(pak); }
/// <summary> /// A player has interacted with an object that has a DataQuest. /// Check to see if we can offer this quest to the player and display the text /// </summary> /// <param name="player"></param> /// <param name="obj"></param> protected virtual void CheckOfferQuest(GamePlayer player, GameObject obj) { // Can we offer this quest to the player? if (CheckQuestQualification(player)) { if (StartType == eStartType.InteractComplete) { // This quest finishes with the interaction CharacterXDataQuest charQuest = GetCharacterQuest(player, ID, true); if (charQuest.Count < MaxQuestCount) { if (ExecuteCustomQuestStep(player, 0, eStepCheckType.Finish)) { if (Description.Trim() != "") { SendMessage(player, Description, 0, eChatType.CT_System, eChatLoc.CL_PopupWindow); } if (m_finalRewards.Count > 0) { lock (player.Inventory) { if (player.Inventory.IsSlotsFree(m_finalRewards.Count, eInventorySlot.FirstBackpack, eInventorySlot.LastBackpack)) { foreach (ItemTemplate item in m_finalRewards) { if (item != null) { GiveItem((obj is GameLiving ? obj as GameLiving : null), player, item, false); } } } else { SendMessage(player, "Your inventory does not have enough space to finish this quest!", 0, eChatType.CT_System, eChatLoc.CL_PopupWindow); return; } } } if (m_rewardXPs.Count > 0 && m_rewardXPs[0] > 0) { player.GainExperience(GameLiving.eXPSource.Quest, m_rewardXPs[0]); } if (m_rewardMoneys.Count > 0 && m_rewardMoneys[0] > 0) { player.AddMoney(m_rewardMoneys[0], "You are awarded {0}!"); InventoryLogging.LogInventoryAction("(QUEST;" + Name + ")", player, eInventoryActionType.Quest, m_rewardMoneys[0]); } charQuest.Count++; GameServer.Database.SaveObject(charQuest); bool add = true; lock (player.QuestListFinished) { foreach (AbstractQuest q in player.QuestListFinished) { if (q is DataQuest && (q as DataQuest).ID == ID) { add = false; break; } } } if (add) { player.QuestListFinished.Add(this); } player.Out.SendQuestListUpdate(); player.Out.SendMessage(String.Format(LanguageMgr.GetTranslation(player.Client, "AbstractQuest.FinishQuest.Completed", Name)), eChatType.CT_ScreenCenter, eChatLoc.CL_SystemWindow); player.Out.SendMessage(String.Format(LanguageMgr.GetTranslation(player.Client, "AbstractQuest.FinishQuest.Completed", Name)), eChatType.CT_Important, eChatLoc.CL_SystemWindow); } } return; } if (StartType == eStartType.AutoStart) { CharacterXDataQuest charQuest = GetCharacterQuest(player, ID, true); DataQuest dq = new DataQuest(player, obj, DBDataQuest, charQuest); dq.Step = 1; player.AddQuest(dq); if (m_sourceTexts.Count > 0) { if (string.IsNullOrEmpty(m_sourceTexts[0]) == false) { SendMessage(player, m_sourceTexts[0], 0, eChatType.CT_System, eChatLoc.CL_PopupWindow); } } else { ChatUtil.SendDebugMessage(player, "Source Text missing on AutoStart quest."); } if (obj is GameNPC) { UpdateQuestIndicator(obj as GameNPC, player); } return; } // Send offer quest dialog if (StartType == eStartType.RewardQuest) { GameNPC offerNPC = obj as GameNPC; if (offerNPC != null) { // Note: If the offer is handled by the custom step then it should return false to prevent a double offer if (ExecuteCustomQuestStep(player, 0, eStepCheckType.Offer)) { player.Out.SendQuestOfferWindow(offerNPC, player, this); } } } else if (string.IsNullOrEmpty(Description) == false) { SendMessage(player, Description, 0, eChatType.CT_System, eChatLoc.CL_PopupWindow); } } }
public static void RewardQuestNotify(DOLEvent e, object sender, EventArgs args) { // Reward Quest accept if (e == GamePlayerEvent.AcceptQuest) { QuestEventArgs qargs = args as QuestEventArgs; if (qargs == null) return; GamePlayer player = qargs.Player; GameLiving giver = qargs.Source; foreach (DBDataQuest quest in GameObject.DataQuestCache) { if ((quest.ID + DATAQUEST_CLIENTOFFSET) == qargs.QuestID) { CharacterXDataQuest charQuest = GetCharacterQuest(player, quest.ID, true); DataQuest dq = new DataQuest(player, giver, quest, charQuest); dq.Step = 1; player.AddQuest(dq); if (giver is GameNPC) { eQuestIndicator indicator = eQuestIndicator.None; if ((giver as GameNPC).ShowQuestIndicator(player)) indicator = eQuestIndicator.Available; player.Out.SendNPCsQuestEffect(giver as GameNPC, indicator); } player.Out.SendSoundEffect(7, 0, 0, 0, 0, 0); break; } } return; } }
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); } }
public override void SendQuestRewardWindow(GameNPC questNPC, GamePlayer player, DataQuest quest) { SendQuestWindow(questNPC, player, quest, false); }
public override void SendQuestOfferWindow(GameNPC questNPC, GamePlayer player, DataQuest quest) { SendQuestWindow(questNPC, player, quest, true); }
public void HandlePacket(GameClient client, GSPacketIn packet) { if (client == null) return; uint extraID = 0; ushort objectType = packet.ReadShort(); 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; switch (objectType) { #region Inventory Item case 1: //Display Infos on inventory item case 10: // market search { if (objectType == 1) { invItem = client.Player.Inventory.GetItem((eInventorySlot)objectID); if (invItem == null) { if (client.Player.ActiveConMerchant != null) { GameConsignmentMerchant con = client.Player.ActiveConMerchant; invItem = con.ConInventory[objectID]; if (invItem == null) return; } else if (client.Player.ActiveVault != null) { GameVault vault = client.Player.ActiveVault; invItem = vault.GetVaultInventory(client.Player)[objectID]; if (invItem == null) return; } else { return; } } } else if (objectType == 10) { List<InventoryItem> list = client.Player.TempProperties.getProperty<object>(DOL.GS.PacketHandler.Client.v168.PlayerMarketSearchRequestHandler.EXPLORER_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, "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, "DetailDisplayHandler.HandlePacket.CannotTraded")); if (!invItem.IsDropable) objectInfo.Add(LanguageMgr.GetTranslation(client, "DetailDisplayHandler.HandlePacket.CannotSold")); if (invItem.IsIndestructible) objectInfo.Add(LanguageMgr.GetTranslation(client, "DetailDisplayHandler.HandlePacket.CannotDestroyed")); if (invItem.BonusLevel > 0) { objectInfo.Add(" "); objectInfo.Add(LanguageMgr.GetTranslation(client, "DetailDisplayHandler.HandlePacket.BonusLevel", invItem.BonusLevel)); } //Add admin info if (client.Account.PrivLevel > 1) { WriteTechnicalInfo(objectInfo, invItem); } break; #endregion Old Delve } #endregion #region Spell case 2: //spell { int lineID = objectID / 100; int spellID = objectID % 100; SpellLine spellLine = client.Player.GetSpellLines()[lineID] as SpellLine; if (spellLine == null) return; Spell spell = null; foreach (Spell spl in SkillBase.GetSpellList(spellLine.KeyName)) { if (spl.Level == spellID) { spell = spl; break; } } if (spell == null) return; caption = spell.Name; WriteSpellInfo(objectInfo, spell, spellLine, client); break; } case 3: //spell { IList skillList = client.Player.GetNonTrainableSkillList(); IList styles = client.Player.GetStyleList(); int index = objectID - skillList.Count - styles.Count - 100; List<SpellLine> spelllines = client.Player.GetSpellLines(); if (spelllines == null || index < 0) break; lock (client.Player.lockSpellLinesList) { Dictionary<string, KeyValuePair<Spell, SpellLine>> spelllist = client.Player.GetUsableSpells(spelllines, false); if (index >= spelllist.Count) { index -= spelllist.Count; } else { Dictionary<string, KeyValuePair<Spell, SpellLine>>.ValueCollection.Enumerator spellenum = spelllist.Values.GetEnumerator(); int i = 0; while (spellenum.MoveNext()) { if (i == index) { caption = spellenum.Current.Key.Name; WriteSpellInfo(objectInfo, spellenum.Current.Key, spellenum.Current.Value, client); break; } i++; } } } 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; int pagenumber = objectID / MerchantTradeItems.MAX_ITEM_IN_TRADEWINDOWS; int slotnumber = 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, "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<ItemTemplate>(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<ItemTemplate>(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, GameInventoryItem.Create<ItemTemplate>(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); } } } break; } #endregion #region Style case 6: //style { IList styleList = client.Player.GetStyleList(); IList skillList = client.Player.GetNonTrainableSkillList(); Style style = null; int styleID = objectID - skillList.Count - 100; if (styleID < 0 || styleID >= styleList.Count) break; style = styleList[styleID] as Style; if (style == null) break; 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, "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, invItem); } break; #endregion Old Delve } #endregion #region Ability case 8://abilities { int id = objectID - 100; IList skillList = client.Player.GetNonTrainableSkillList(); Ability abil = (Ability)skillList[id]; if (abil != null) { IList allabilitys = client.Player.GetAllAbilities(); foreach (Ability checkab in allabilitys) { if (checkab.Name == abil.Name) { if (checkab.DelveInfo.Count > 0) objectInfo.AddRange(checkab.DelveInfo); else objectInfo.Add("There is no special information."); } } } break; } #endregion #region Trainer case 9: //trainer window "info" button { IList specList = client.Player.GetSpecList(); Specialization spec; if (objectID < specList.Count) { spec = (Specialization)specList[objectID]; } 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.getClassRealmAbility(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; } List<Style> styles = SkillBase.GetStyleList(spec.KeyName, client.Player.CharacterClass.ID); IList playerSpells = client.Player.GetSpellLines(); SpellLine selectedSpellLine = null; lock (playerSpells.SyncRoot) { foreach (SpellLine line in playerSpells) { if (!line.IsBaseLine && line.Spec == spec.KeyName) { selectedSpellLine = line; break; } } } List<Spell> spells = new List<Spell>(); if (selectedSpellLine != null) spells = SkillBase.GetSpellList(selectedSpellLine.KeyName); caption = spec.Name; if (styles.Count <= 0 && playerSpells.Count <= 0) { objectInfo.Add("no info found for this spec"); break; } objectInfo.Add(LanguageMgr.GetTranslation(client, "DetailDisplayHandler.HandlePacket.LevName")); foreach (Style style in styles) { objectInfo.Add(style.Level + ": " + style.Name); } foreach (Spell spell in spells) { objectInfo.Add(spell.Level + ": " + spell.Name); } 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, "DetailDisplayHandler.HandlePacket.Item", client.Player.Name, GetShortItemInfo(invItem, client)); if (client.Player.Group == null) { client.Out.SendMessage(LanguageMgr.GetTranslation(client, "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, "DetailDisplayHandler.HandlePacket.GuildItem", client.Player.Name, GetShortItemInfo(invItem, client)); if (client.Player.Guild == null) { client.Out.SendMessage(LanguageMgr.GetTranslation(client, "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, "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, "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, "DetailDisplayHandler.HandlePacket.OnlyModerator"), eChatType.CT_System, eChatLoc.CL_SystemWindow); return; } string str = LanguageMgr.GetTranslation(client, "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 = SkillBase.GetStyleByID((int)objectID, client.Player.CharacterClass.ID); if (style == null) return; caption = style.Name; WriteStyleInfo(objectInfo, style, client); break; } //spells case 22: { Spell spell = SkillBase.GetSpellByID((int)objectID); if (spell == null) return; caption = spell.Name; WriteSpellInfo(objectInfo, spell, SkillBase.GetSpellLine(GlobalSpellsLines.Reserved_Spells), client); 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, "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, "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, "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, "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, "DetailDisplayHandler.HandlePacket.OnlyModerator"), eChatType.CT_System, eChatLoc.CL_SystemWindow); return; } string str = LanguageMgr.GetTranslation(client, "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 ChampionAbilities delve from trainer window default: { // Try and handle all Champion lines, including custom lines ChampSpec spec = ChampSpecMgr.GetAbilityFromIndex(objectType - 150, objectID / 256 + 1, objectID % 256 + 1); if (spec != null) { Spell spell = SkillBase.GetSpellByID(spec.SpellID); if (spell != null) { SpellLine spellLine = client.Player.GetChampionSpellLine(); if (spellLine != null) { caption = spell.Name; WriteSpellInfo(objectInfo, spell, spellLine, client); } else { objectInfo.Add("Champion spell line not found!"); } } } break; } #endregion } if (objectInfo.Count > 0) { client.Out.SendCustomTextWindow(caption, objectInfo); } else { 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); } }
public void RemoveDataQuest(DataQuest quest) { if (m_dataQuests.Contains(quest)) m_dataQuests.Remove(quest); }
public void SendQuestOfferWindow(GameNPC questNPC, GamePlayer player, DataQuest quest) { }
/// <summary> /// Search area for data quests. Z is not checked, user must specify radius and time in data quest /// </summary> /// <param name="dataQuest"></param> /// <param name="validStep"></param> /// <param name="text"></param> /// <param name="regionId"></param> /// <param name="x"></param> /// <param name="y"></param> /// <param name="radius"></param> /// <param name="searchSeconds"></param> public QuestSearchArea(DataQuest dataQuest, int validStep, string text, ushort regionId, int x, int y, int radius = DEFAULT_SEARCH_RADIUS, int searchSeconds = DEFAULT_SEARCH_SECONDS) : base(text, x, y, 0, radius) { CreateArea(dataQuest, validStep, searchSeconds, text, regionId); }
protected void CreateArea(DataQuest dataQuest, int validStep, int searchSeconds, string text, ushort regionId) { m_regionId = regionId; m_questType = typeof(DataQuest); m_dataQuest = dataQuest; m_validStep = validStep; m_searchSeconds = searchSeconds; m_popupText = text; DisplayMessage = false; if (WorldMgr.GetRegion(regionId) != null) { WorldMgr.GetRegion(regionId).AddArea(this); } else { string errorText = "Could not find region " + regionId + " when trying to create QuestSearchArea! "; dataQuest.LastErrorText += errorText; log.Error(errorText); } }
const ushort MAX_STORY_LENGTH = 1000; // Via trial and error, 1.108 client. // Often will cut off text around 990 but longer strings do not result in any errors. -Tolakram protected override void SendQuestWindow(GameNPC questNPC, GamePlayer player, DataQuest quest, bool offer) { using (GSTCPPacketOut pak = new GSTCPPacketOut(GetPacketCode(eServerPackets.Dialog))) { ushort QuestID = quest.ClientQuestID; pak.WriteShort((offer) ? (byte)0x22 : (byte)0x21); // Dialog pak.WriteShort(QuestID); pak.WriteShort((ushort)questNPC.ObjectID); pak.WriteByte(0x00); // unknown pak.WriteByte(0x00); // unknown pak.WriteByte(0x00); // unknown pak.WriteByte(0x00); // unknown pak.WriteByte((offer) ? (byte)0x02 : (byte)0x01); // Accept/Decline or Finish/Not Yet pak.WriteByte(0x01); // Wrap pak.WritePascalString(quest.Name); String personalizedSummary = BehaviourUtils.GetPersonalizedMessage(quest.Description, player); if (personalizedSummary.Length > 255) { pak.WritePascalString(personalizedSummary.Substring(0, 255)); // Summary is max 255 bytes or client will crash ! } else { pak.WritePascalString(personalizedSummary); } if (offer) { String personalizedStory = BehaviourUtils.GetPersonalizedMessage(quest.Story, player); if (personalizedStory.Length > MAX_STORY_LENGTH) { pak.WriteShort(MAX_STORY_LENGTH); pak.WriteStringBytes(personalizedStory.Substring(0, MAX_STORY_LENGTH)); } else { pak.WriteShort((ushort)personalizedStory.Length); pak.WriteStringBytes(personalizedStory); } } else { if (quest.FinishText.Length > MAX_STORY_LENGTH) { pak.WriteShort(MAX_STORY_LENGTH); pak.WriteStringBytes(quest.FinishText.Substring(0, MAX_STORY_LENGTH)); } else { pak.WriteShort((ushort)quest.FinishText.Length); pak.WriteStringBytes(quest.FinishText); } } pak.WriteShort(QuestID); pak.WriteByte((byte)quest.StepTexts.Count); // #goals count foreach (string text in quest.StepTexts) { string t = text; // Need to protect for any text length > 255. It does not crash client but corrupts RewardQuest display -Tolakram if (text.Length > 253) { t = text.Substring(0, 253); } pak.WritePascalString(String.Format("{0}\r", t)); } pak.WriteInt((uint)(0)); pak.WriteByte((byte)0); pak.WriteByte((byte)quest.FinalRewards.Count); foreach (ItemTemplate reward in quest.FinalRewards) { WriteItemData(pak, GameInventoryItem.Create(reward)); } pak.WriteByte((byte)quest.NumOptionalRewardsChoice); pak.WriteByte((byte)quest.OptionalRewards.Count); foreach (ItemTemplate reward in quest.OptionalRewards) { WriteItemData(pak, GameInventoryItem.Create(reward)); } SendTCP(pak); } }
/// <summary> /// Load any data driven quests for this object /// </summary> public void LoadDataQuests() { if (m_dataQuestCache == null) { FillDataQuestCache(); } m_dataQuests.Clear(); foreach (DBDataQuest quest in m_dataQuestCache) { if ((quest.StartRegionID == CurrentRegionID || quest.StartRegionID == 0) && quest.StartName == Name) { DataQuest dq = new DataQuest(quest); dq.StartObject = this; AddDataQuest(dq); } } }
public void SendQuestRewardWindow(GameNPC questNPC, GamePlayer player, DataQuest quest) { if (SendQuestRewardWindowDataMethod != null) SendQuestRewardWindowDataMethod(this, questNPC, player, quest); }
/// <summary> /// Check offered quests to see if whisper should be processed /// </summary> /// <param name="player"></param> /// <param name="living"></param> /// <param name="text"></param> protected virtual void CheckOfferedQuestWhisper(GamePlayer player, GameLiving living, string text) { //log.DebugFormat("Checking accept quest: '{0}' ID: {1} of type '{2}', key word '{3}', is qualified {4}", Name, ID, (eStartType)DBDataQuest.StartType, DBDataQuest.AcceptText, CheckQuestQualification(player)); if (CheckQuestQualification(player) && DBDataQuest.StartType == (byte)eStartType.Standard && DBDataQuest.AcceptText == text) { //log.DebugFormat("Adding quest {0} to player {1}", Name, player.Name); CharacterXDataQuest charQuest = GetCharacterQuest(player, ID, true); DataQuest dq = new DataQuest(player, living, DBDataQuest, charQuest); dq.Step = 1; player.AddQuest(dq); if (m_sourceTexts.Count > 0) { SendMessage(player, m_sourceTexts[0], 0, eChatType.CT_System, eChatLoc.CL_PopupWindow); } else { ChatUtil.SendDebugMessage(player, "Source Text missing on accept quest."); } if (living is GameNPC) { UpdateQuestIndicator(living as GameNPC, player); } } }
public void AddDataQuest(DataQuest quest) { if (m_dataQuests.Contains(quest) == false) m_dataQuests.Add(quest); }
public virtual void SendQuestRewardWindow(GameNPC questNPC, GamePlayer player, DataQuest quest) { }
/// <summary> /// Load any data driven quests for this object /// </summary> public void LoadDataQuests(GamePlayer player = null) { if (m_dataQuestCache == null) { FillDataQuestCache(); } m_dataQuests.Clear(); try { foreach (DBDataQuest quest in m_dataQuestCache[CurrentRegionID]) { if (quest.StartName == Name) { DataQuest dq = new DataQuest(quest, this); AddDataQuest(dq); // if a player forced the reload report any errors if (player != null && dq.LastErrorText != "") { ChatUtil.SendErrorMessage(player, dq.LastErrorText); } } } } catch { } try { foreach (DBDataQuest quest in m_dataQuestCache[0]) { if (quest.StartName == Name) { DataQuest dq = new DataQuest(quest, this); AddDataQuest(dq); // if a player forced the reload report any errors if (player != null && dq.LastErrorText != "") { ChatUtil.SendErrorMessage(player, dq.LastErrorText); } } } } catch { } }
protected virtual void SendQuestWindow(GameNPC questNPC, GamePlayer player, DataQuest quest, bool offer) { }