Index: DOLDatabase/DOLTables/DBNpcTemplate.cs =================================================================== --- DOLDatabase/DOLTables/DBNpcTemplate.cs (revision 665) +++ DOLDatabase/DOLTables/DBNpcTemplate.cs (working copy) @@ -44,6 +44,8 @@ private string m_level = "0"; private short m_maxSpeed = 50; private string m_equipmentTemplateID = ""; + private string m_raceAvailable = ""; + private string m_weaponsAvailable = ""; private bool m_ghost; private byte m_meleeDamageType = 1; private byte m_parryChance; @@ -210,6 +212,34 @@ } } + /// + /// AvailableWeapons + /// + [DataElement(AllowDbNull = true)] + public string WeaponsAvailable + { + get { return m_weaponsAvailable; } + set + { + Dirty = true; + m_weaponsAvailable = value; + } + } + + /// + /// RaceAvailable + /// + [DataElement(AllowDbNull = true)] + public string RaceAvailable + { + get {return m_raceAvailable;} + set + { + Dirty = true; + m_raceAvailable = value; + } + } + /// /// Ghost /// Index: GameServer/gameobjects/GameNPC.cs =================================================================== --- GameServer/gameobjects/GameNPC.cs (revision 665) +++ GameServer/gameobjects/GameNPC.cs (working copy) @@ -262,6 +262,26 @@ set { m_bodyType = value; } } + private string m_raceAvailable; + /// + /// The NPC's race model + /// + public string RaceAvailable + { + get { return m_raceAvailable; } + set { m_raceAvailable = value; } + } + + private string m_weaponsAvailable; + /// + /// The NPC's weapons pet + /// + public string WeaponsAvailable + { + get { return m_weaponsAvailable; } + set { m_weaponsAvailable = value; } + } + private int m_houseNumber; /// /// The NPC's current house Index: GameServer/gameutils/INpcTemplate.cs =================================================================== --- GameServer/gameutils/INpcTemplate.cs (revision 665) +++ GameServer/gameutils/INpcTemplate.cs (working copy) @@ -168,5 +168,15 @@ /// Gets the body type of the npc /// int BodyType { get;} + + /// + /// Gets the race model pet + /// + string RaceAvailable { get;} + + /// + /// Gets the weapon pet + /// + string WeaponsAvailable{ get;} } } \ No newline at end of file Index: GameServer/gameutils/NpcTemplate.cs =================================================================== --- GameServer/gameutils/NpcTemplate.cs (revision 665) +++ GameServer/gameutils/NpcTemplate.cs (working copy) @@ -68,6 +68,8 @@ protected byte m_aggroLevel; protected int m_aggroRange; protected int m_bodyType; + protected string m_raceAvailable; + protected string m_weaponsAvailable; /// /// Constructs a new NpcTemplate @@ -162,6 +164,8 @@ m_aggroLevel = data.AggroLevel; m_aggroRange = data.AggroRange; m_bodyType = data.BodyType; + m_raceAvailable = data.RaceAvailable; + m_weaponsAvailable = data.WeaponsAvailable; } public NpcTemplate(GameNPC mob) @@ -196,6 +200,8 @@ m_aggroRange = brain.AggroRange; } m_bodyType = mob.BodyType; + m_raceAvailable = mob.RaceAvailable; + m_weaponsAvailable = mob.WeaponsAvailable; } public NpcTemplate() @@ -422,6 +428,18 @@ set { m_bodyType = value; } } + public string RaceAvailable + { + get { return m_raceAvailable; } + set { m_raceAvailable = value; } + } + + public string WeaponsAvailable + { + get { return m_weaponsAvailable; } + set { m_weaponsAvailable = value; } + } + public virtual void SaveIntoDatabase() { DBNpcTemplate tmp = tmp = (DBNpcTemplate)GameServer.Database.FindObjectByKey(typeof(DBNpcTemplate), TemplateId); Index: GameServer/spells/SummonSpellHandler.cs =================================================================== --- GameServer/spells/SummonSpellHandler.cs (revision 665) +++ GameServer/spells/SummonSpellHandler.cs (working copy) @@ -24,9 +24,12 @@ using DOL.Events; using DOL.GS; using DOL.GS.Effects; +using DOL.Database; +using DOL.Language; using DOL.GS.PacketHandler; using DOL.GS.SkillHandler; using log4net; +using System.Text.RegularExpressions; namespace DOL.GS.Spells { @@ -74,6 +77,34 @@ return base.CheckBeginCast(selectedTarget); } + /// + /// Return the pet text based on gender. + /// + /// key text + public string GetGender(string type){ + string gender = string.Empty; + GamePlayer player = Caster as GamePlayer; + GameClient client = player.Client; + + if (type == "master"){ + if (((GamePlayer)Caster).PlayerCharacter.Gender == (int)0){ + gender = LanguageMgr.GetTranslation(client, "SummonSpellHandler.CustomPet.Spiritmaster.MasterMale"); + } + if (((GamePlayer)Caster).PlayerCharacter.Gender == (int)1){ + gender = LanguageMgr.GetTranslation(client, "SummonSpellHandler.CustomPet.Spiritmaster.MasterFemale"); + } + } + if (type == "summoner"){ + if (((GamePlayer)Caster).PlayerCharacter.Gender == (int)0){ + gender = LanguageMgr.GetTranslation(client, "SummonSpellHandler.CustomPet.Spiritmaster.SummonerMale"); + } + if (((GamePlayer)Caster).PlayerCharacter.Gender == (int)1){ + gender = LanguageMgr.GetTranslation(client, "SummonSpellHandler.CustomPet.Spiritmaster.SummonerFemale"); + } + } + return gender; + } + /// /// Apply effect on target or do spell action if non duration spell /// @@ -125,8 +156,9 @@ else { target.GetSpotFromHeading(64, out x, out y); - + ControlledNpc controlledBrain = new ControlledNpc(player); + GameClient client = player.Client; GameNPC summoned = new GameNPC(template); summoned.SetOwnBrain(controlledBrain); @@ -145,10 +177,351 @@ GameEventMgr.AddHandler(player, GamePlayerEvent.CommandNpcRelease, new DOLEventHandler(OnNpcReleaseCommand)); player.SetControlledNpc(controlledBrain); effect.Start(summoned); - } - } + + #region [Custom pet model's and weapon's Handlers] Nanowish + if (player.CharacterClass.ID == (int)eCharacterClass.Spiritmaster) + { + summoned.Say(LanguageMgr.GetTranslation(client, "SummonSpellHandler.CustomPet.Spiritmaster.InvocSay", GetGender("master"), GetGender("summoner"))); + } + if (player.CharacterClass.ID == (int)eCharacterClass.Bonedancer) + { + summoned.Say(LanguageMgr.GetTranslation(client, "SummonSpellHandler.CustomPet.Bonedancer.InvocSay", GetGender("master"), GetGender("summoner"),LanguageMgr.GetTranslation(client, "SummonSpellHandler.CustomPet.Bonedancer.InvocKey"))); + } + if (player.CharacterClass.ID == (int)eCharacterClass.Enchanter) + { + summoned.Say(LanguageMgr.GetTranslation(client, "SummonSpellHandler.CustomPet.Enchanter.InvocSay", GetGender("master"), GetGender("summoner"), LanguageMgr.GetTranslation(client, "SummonSpellHandler.CustomPet.Enchanter.InvocKey"))); + } + if (player.CharacterClass.ID == (int)eCharacterClass.Druid) + { + summoned.Say(LanguageMgr.GetTranslation(client, "SummonSpellHandler.CustomPet.Druid.InvocSay", player.Name, LanguageMgr.GetTranslation(client, "SummonSpellHandler.CustomPet.Druid.InvocKey"))); + } + GameEventMgr.AddHandler(summoned, GameLivingEvent.WhisperReceive, new DOLEventHandler(WhisperReceiveCallback)); + GameEventMgr.AddHandler(summoned, GameLivingEvent.SayReceive, new DOLEventHandler(SayReceiveCallback)); + #endregion + } + } + #region [Custom pet model's and weapon's management] Nanowish + + /// + /// Add and Switch weapon method + /// + /// add custom weapon + /// add weapon in slot get with GetSlot(ItemTemplate, int, string) method + public void SetWeapon(ItemTemplate weapon, eInventorySlot slot) + { + GamePlayer player = Caster as GamePlayer; + IControlledBrain pet = player.ControlledNpc; + pet.Body.Inventory.RemoveItem(pet.Body.Inventory.GetItem(eInventorySlot.RightHandWeapon)); + pet.Body.Inventory.RemoveItem(pet.Body.Inventory.GetItem(eInventorySlot.LeftHandWeapon)); + pet.Body.Inventory.RemoveItem(pet.Body.Inventory.GetItem(eInventorySlot.TwoHandWeapon)); + pet.Body.Inventory.AddTemplate(weapon, 1, slot, slot); + if (slot == eInventorySlot.RightHandWeapon || slot == eInventorySlot.LeftHandWeapon) + { + pet.Body.SwitchWeapon(GameLiving.eActiveWeaponSlot.Standard); + } + if (slot == eInventorySlot.TwoHandWeapon) + { + pet.Body.SwitchWeapon(GameLiving.eActiveWeaponSlot.TwoHanded); + } + } + + /// + /// get slot of pet weapon. + /// + /// pet weapon + /// return int of weapon.Hand method + /// pet weapon model say with key word + public eInventorySlot GetSlot(ItemTemplate weapon, int slot, string modelId) + { + eInventorySlot defaultSlot = eInventorySlot.RightHandWeapon; + weapon = (ItemTemplate)GameServer.Database.FindObjectByKey(typeof(ItemTemplate), modelId); + + if (slot == 0) defaultSlot = eInventorySlot.RightHandWeapon; + if (slot == 1) defaultSlot = eInventorySlot.TwoHandWeapon; + if (slot == 2) defaultSlot = eInventorySlot.LeftHandWeapon; + return defaultSlot; + } + + /// + /// return the model's Id of the field RaceAvailable. + /// + /// get model's Id with model's name + public ushort PetRaceModelId(string saytext) + { + GamePlayer player = Caster as GamePlayer; + INpcTemplate template = NpcTemplateMgr.GetTemplate(Spell.LifeDrainReturn); + IList m_listmodel = new ArrayList(); + ushort modelId = 0; + foreach (string str in template.RaceAvailable.Split(';')) + { + string[] modelList = str.Split(':'); + modelId = Convert.ToUInt16(modelList[1]); + + if (modelList.Length == 0) continue; + m_listmodel.Add(modelList); + + //Get if race string exist and return model id, ex: troll:666, 666 is returned. + if (modelList[0].Contains(saytext)) + { + return modelId; + } + } + return modelId; + } + + /// + /// return the model's Id of the field RaceAvailable. + /// + /// get model's Id with model's name + public string PetWeaponsModelId(string saytext) + { + GamePlayer player = Caster as GamePlayer; + INpcTemplate template = NpcTemplateMgr.GetTemplate(Spell.LifeDrainReturn); + IList m_listmodel = new ArrayList(); + string modelId = string.Empty; + foreach (string str in template.WeaponsAvailable.Split(';')) + { + string[] modelList = str.Split(':'); + modelId = modelList[1]; + + if (modelList.Length == 0) continue; + m_listmodel.Add(modelList); + + //Get if race string exist and return model id, ex: troll:666, 666 is returned. + if (modelList[0].Contains(saytext)) + { + return modelId; + } + } + return modelId; + } + + /// + /// race option: return the model's Name of the field RaceAvailable. + /// weapon option: return the model's Name of the field WeaponsAvailable. + /// + /// search in field + public string PetModelName(string option) + { + INpcTemplate template = NpcTemplateMgr.GetTemplate(Spell.LifeDrainReturn); + GamePlayer player = Caster as GamePlayer; + IControlledBrain pet = player.ControlledNpc; + IList m_listmodel = new ArrayList(); + string modelName = string.Empty; + + if (option.Equals("race")) + { + foreach (string str in template.RaceAvailable.Split(';')) + { + string[] modelList = str.Split(':'); + if (modelList.Length == 0) continue; + m_listmodel.Add(modelList); + modelName += String.Format("[{0}], ", modelList[0]); + } + } + if (option.Equals("weapon")) + { + foreach (string str in template.WeaponsAvailable.Split(';')) + { + string[] modelList = str.Split(':'); + if (modelList.Length == 0) continue; + m_listmodel.Add(modelList); + modelName += String.Format("[{0}], ", modelList[0]); + } + } + + return modelName; + } + + /// + /// Get if the key word say to pet, with Regex IgnoreCase, match with text option. + /// + /// key word + /// text match with key word + public bool GetSayKeys(SayReceiveEventArgs sArgs ,string text) + { + if (Regex.Match(sArgs.Text, text, RegexOptions.IgnoreCase).Success) + return true; + return false; + } + + /// + /// Get if the key word whispered to pet, with Regex IgnoreCase, match with text option. + /// + /// key word + /// text match with key word + public bool GetWhispKeys(WhisperReceiveEventArgs wArgs, string text) + { + if (Regex.Match(wArgs.Text, text, RegexOptions.IgnoreCase).Success) + return true; + return false; + } + + public void SayReceiveCallback(DOLEvent ev, object sender, EventArgs args) + { + GamePlayer player = ((SourceEventArgs)args).Source as GamePlayer; + IControlledBrain pet = player.ControlledNpc; + GameClient client = player.Client; + + if (player == null) + return; + + if (pet == null) + return; + + if (ev == GameLivingEvent.SayReceive) + { + SayReceiveEventArgs sArgs = (SayReceiveEventArgs)args; + if (player.CharacterClass.ID == (int)eCharacterClass.Spiritmaster) + { + if (GetSayKeys(sArgs, "niflheim")) + { + if (PetModelName("race").Length > 4) + { + pet.Body.SayTo(player, LanguageMgr.GetTranslation(client, "SummonSpellHandler.CustomPet.Spiritmaster.MainText", PetModelName("race"), LanguageMgr.GetTranslation(client, "SummonSpellHandler.CustomPet.Spiritmaster.WeaponKey"))); + } + } + } + if (player.CharacterClass.ID == (int)eCharacterClass.Enchanter) + { + if (GetSayKeys(sArgs, LanguageMgr.GetTranslation(client, "SummonSpellHandler.CustomPet.Enchanter.InvocKey"))) + { + if (PetModelName("race").Length > 4) + { + pet.Body.SayTo(player, LanguageMgr.GetTranslation(client, "SummonSpellHandler.CustomPet.Enchanter.MainText", PetModelName("race"))); + } + } + } + if (player.CharacterClass.ID == (int)eCharacterClass.Druid) + { + if (GetSayKeys(sArgs, LanguageMgr.GetTranslation(client, "SummonSpellHandler.CustomPet.Druid.InvocKey"))) + { + if (PetModelName("race").Length > 4) + { + pet.Body.SayTo(player, LanguageMgr.GetTranslation(client, "SummonSpellHandler.CustomPet.Druid.MainText", PetModelName("race"))); + } + } + } + if (player.CharacterClass.ID == (int)eCharacterClass.Bonedancer) + { + if (GetSayKeys(sArgs, LanguageMgr.GetTranslation(client, "SummonSpellHandler.CustomPet.Bonedancer.InvocKey"))) + { + if (PetModelName("weapon").Length > 4) + { + pet.Body.SayTo(player, LanguageMgr.GetTranslation(client, "SummonSpellHandler.CustomPet.Bonedancer.MainText", LanguageMgr.GetTranslation(client, "SummonSpellHandler.CustomPet.Bonedancer.WeaponKey"))); + } + } + } + else {return;} + } + } + + public void WhisperReceiveCallback(DOLEvent ev, object sender, EventArgs args) + { + + INpcTemplate template = NpcTemplateMgr.GetTemplate(Spell.LifeDrainReturn); + GamePlayer player = ((SourceEventArgs)args).Source as GamePlayer; + GameClient client = player.Client; + + if (player == null) + return; + + IControlledBrain pet = player.ControlledNpc; + if (pet == null) + return; + + if (ev == GameLivingEvent.WhisperReceive) + { + // Get class, get text whisp text and say pet text. + WhisperReceiveEventArgs wArgs = (WhisperReceiveEventArgs)args; + if (player.CharacterClass.ID == (int)eCharacterClass.Spiritmaster + || player.CharacterClass.ID == (int)eCharacterClass.Enchanter + || player.CharacterClass.ID == (int)eCharacterClass.Druid) + { + if (PetModelName("race").Length > 4) + { + if (GetWhispKeys(wArgs, "niflheim") && player.CharacterClass.ID == (int)eCharacterClass.Spiritmaster) + { + pet.Body.SayTo(player, LanguageMgr.GetTranslation(client, "SummonSpellHandler.CustomPet.Spiritmaster.MainText", PetModelName("race"), LanguageMgr.GetTranslation(client, "SummonSpellHandler.CustomPet.Spiritmaster.WeaponKey"))); + } + if (GetWhispKeys(wArgs, LanguageMgr.GetTranslation(client, "SummonSpellHandler.CustomPet.Enchanter.InvocKey")) && player.CharacterClass.ID == (int)eCharacterClass.Enchanter) + { + pet.Body.SayTo(player, LanguageMgr.GetTranslation(client, "SummonSpellHandler.CustomPet.Enchanter.MainText", PetModelName("race"))); + } + if (GetWhispKeys(wArgs, LanguageMgr.GetTranslation(client, "SummonSpellHandler.CustomPet.Druid.InvocKey")) && player.CharacterClass.ID == (int)eCharacterClass.Druid) + { + pet.Body.SayTo(player, LanguageMgr.GetTranslation(client, "SummonSpellHandler.CustomPet.Druid.MainText", PetModelName("race"))); + } + } + // if the text is not voile, underhill, niflheim or nature the pet model is changed + if (PetModelName("race").Contains(wArgs.Text) + && !GetWhispKeys(wArgs, "niflheim") + && !GetWhispKeys(wArgs, LanguageMgr.GetTranslation(client, "SummonSpellHandler.CustomPet.Enchanter.InvocKey")) + && !GetWhispKeys(wArgs, LanguageMgr.GetTranslation(client, "SummonSpellHandler.CustomPet.Enchanter.InvocKey")) + && !GetWhispKeys(wArgs, LanguageMgr.GetTranslation(client, "SummonSpellHandler.CustomPet.Druid.InvocKey")) + //don't change weapon when change model. + && (!GetWhispKeys(wArgs, LanguageMgr.GetTranslation(client, "SummonSpellHandler.CustomPet.Spiritmaster.WeaponKey")) + || !GetWhispKeys(wArgs, LanguageMgr.GetTranslation(client, "SummonSpellHandler.CustomPet.Bonedancer.WeaponKey")))) + { + try + { + pet.Body.Model = PetRaceModelId(wArgs.Text); + } + catch (Exception) + { + player.Out.SendMessage("!!! Model Race Error!!! Please contact the server admin.", eChatType.CT_Important, eChatLoc.CL_SystemWindow); + if (log.IsErrorEnabled) + log.Error("!!!Model Race Error!!! " + player.Name + "try to use invalid pet race, please check your DB"); + } + } + } + + //get class, get keys and say pet weapon text + if (player.CharacterClass.ID == (int)eCharacterClass.Spiritmaster + || player.CharacterClass.ID == (int)eCharacterClass.Bonedancer) + { + if (PetModelName("weapon").Length > 4) + { + if (GetWhispKeys(wArgs, LanguageMgr.GetTranslation(client, "SummonSpellHandler.CustomPet.Spiritmaster.WeaponKey")) + || GetWhispKeys(wArgs, LanguageMgr.GetTranslation(client, "SummonSpellHandler.CustomPet.Bonedancer.WeaponKey"))) + { + if (player.CharacterClass.ID == (int)eCharacterClass.Spiritmaster) + { + pet.Body.SayTo(player, LanguageMgr.GetTranslation(client, "SummonSpellHandler.CustomPet.Spiritmaster.WeaponText", PetModelName("weapon"))); + } + + if (player.CharacterClass.ID == (int)eCharacterClass.Bonedancer) + { + pet.Body.SayTo(player, LanguageMgr.GetTranslation(client, "SummonSpellHandler.CustomPet.Bonedancer.WeaponText", PetModelName("weapon"))); + } + } + } + try + { + // if the text is not weapons, weapon, arme or arme the pet weapon is changed + if ((!GetWhispKeys(wArgs, LanguageMgr.GetTranslation(client, "SummonSpellHandler.CustomPet.Spiritmaster.WeaponKey")) + || !GetWhispKeys(wArgs, LanguageMgr.GetTranslation(client, "SummonSpellHandler.CustomPet.Bonedancer.WeaponKey"))) + && PetModelName("weapon").Contains(wArgs.Text)) + { + ItemTemplate weapon = (ItemTemplate)GameServer.Database.FindObjectByKey(typeof(ItemTemplate), PetWeaponsModelId(wArgs.Text)); + SetWeapon(weapon, GetSlot(weapon, weapon.Hand, PetWeaponsModelId(wArgs.Text))); + } + else { return; } + } + catch (Exception) + { + player.Out.SendMessage("!!!Weapon Error!!! Please contact the server admin.", eChatType.CT_Important, eChatLoc.CL_SystemWindow); + if (log.IsErrorEnabled) + log.Error("!!!Weapon Error!!! " + player.Name + " try to use invalid pet weapon, please check your DB"); + } + } + + } + + } + #endregion - /// + /// /// When an applied effect expires. /// Duration spells only. /// @@ -183,6 +556,8 @@ player.SetControlledNpc(null); GameEventMgr.RemoveHandler(player, GamePlayerEvent.CommandNpcRelease, new DOLEventHandler(OnNpcReleaseCommand)); + GameEventMgr.RemoveHandler(npc.Body, GameLivingEvent.WhisperReceive, new DOLEventHandler(WhisperReceiveCallback)); + GameEventMgr.RemoveHandler(npc.Body, GameLivingEvent.SayReceive, new DOLEventHandler(SayReceiveCallback)); GameSpellEffect effect = FindEffectOnTarget(npc.Body, this); if (effect != null) @@ -187,6 +562,7 @@ GameSpellEffect effect = FindEffectOnTarget(npc.Body, this); if (effect != null) effect.Cancel(false); + } ///