Public feed #532002

Nanowish/pet change model via ke

public text v1 · immutable
Raw Edit
·published 2007-06-03 00:57 UTC
rendered paste body
Index: DOLDatabase/DOLTables/DBNpcTemplate.cs
===================================================================
--- DOLDatabase/DOLTables/DBNpcTemplate.cs	(revision 663)
+++ 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 @@
 			}
 		}
 
+        /// <summary>
+        /// AvailableWeapons
+        /// </summary>
+        [DataElement(AllowDbNull = true)]
+        public string WeaponsAvailable
+        {
+            get { return m_weaponsAvailable; }
+            set
+            {
+                Dirty = true;
+                m_weaponsAvailable = value;
+            }
+        }
+
+        /// <summary>
+        /// RaceAvailable
+        /// </summary>
+        [DataElement(AllowDbNull = true)]
+        public string RaceAvailable
+        {
+            get {return m_raceAvailable;}
+            set
+            {
+                Dirty = true;
+                m_raceAvailable = value;
+            }
+        }
+
 		/// <summary>
 		/// Ghost
 		/// </summary>
Index: GameServer/gameobjects/GameNPC.cs
===================================================================
--- GameServer/gameobjects/GameNPC.cs	(revision 663)
+++ GameServer/gameobjects/GameNPC.cs	(working copy)
@@ -262,6 +262,26 @@
 			set { m_bodyType = value; }
 		}
 
+        private string m_raceAvailable;
+        /// <summary>
+        /// The NPC's race model
+        /// </summary>
+        public string RaceAvailable
+        {
+            get { return m_raceAvailable; }
+            set { m_raceAvailable = value; }
+        }
+
+        private string m_weaponsAvailable;
+        /// <summary>
+        /// The NPC's weapons pet
+        /// </summary>
+        public string WeaponsAvailable
+        {
+            get { return m_weaponsAvailable; }
+            set { m_weaponsAvailable = value; }
+        }
+
 		private int m_houseNumber;
 		/// <summary>
 		/// The NPC's current house
Index: GameServer/gameutils/INpcTemplate.cs
===================================================================
--- GameServer/gameutils/INpcTemplate.cs	(revision 663)
+++ GameServer/gameutils/INpcTemplate.cs	(working copy)
@@ -168,5 +168,15 @@
 		/// Gets the body type of the npc
 		/// </summary>
 		int BodyType { get;}
+
+        /// <summary>
+        /// Gets the race model pet
+        /// </summary>
+        string RaceAvailable { get;}
+
+        /// <summary>
+        /// Gets the weapon pet
+        /// </summary>
+        string WeaponsAvailable{ get;}
 	}
 }
\ No newline at end of file
Index: GameServer/gameutils/NpcTemplate.cs
===================================================================
--- GameServer/gameutils/NpcTemplate.cs	(revision 663)
+++ 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;
 
 		/// <summary>
 		/// 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/language/Language-EN.txt
===================================================================
--- GameServer/language/Language-EN.txt	(revision 663)
+++ GameServer/language/Language-EN.txt	(working copy)
@@ -642,6 +642,32 @@
 Scripts.Players.Duel.YouInGroup:			You are in a group.
 Scripts.Players.Duel.YouSurrender:			You surrender to {0}!
 
+# Pet custom text
+# SpiritMaster #
+SummonSpellHandler.CustomPet.Spiritmaster.MasterMale:		master
+SummonSpellHandler.CustomPet.Spiritmaster.MasterFemale:		mistress
+SummonSpellHandler.CustomPet.Spiritmaster.SummonerMale:		summoner
+SummonSpellHandler.CustomPet.Spiritmaster.SummonerFemale:	summoner
+SummonSpellHandler.CustomPet.Spiritmaster.WeaponKey:		weapon
+SummonSpellHandler.CustomPet.Spiritmaster.InvocSay:			Hail, {0}. As my {1} and {0}, you may target me and say Niflheim to learn more about the abilities I possess.
+SummonSpellHandler.CustomPet.Spiritmaster.MainText:			As one of the lost spirits of Niflheim, I can assume the appareance of any warrior race. Command me to become a {0}. You may command me to wield the [{1}] of your choice.
+SummonSpellHandler.CustomPet.Spiritmaster.WeaponText:			What weapon do you command me to wield? A {0} ?
+# BoneDancer #
+SummonSpellHandler.CustomPet.Bonedancer.WeaponKey:			weapons
+SummonSpellHandler.CustomPet.Bonedancer.InvocKey:			Commander
+SummonSpellHandler.CustomPet.Bonedancer.InvocSay:			Hail, {0}. As my {1} and {0}, you may target me and say {2} to learn more about the abilities I possess.
+SummonSpellHandler.CustomPet.Bonedancer.MainText:			As one of Bogdar's commanders, I have many of the fossil [{0}] within his bone army. Which weapon shall I wield for you?
+SummonSpellHandler.CustomPet.Bonedancer.WeaponText:			I have mastered the {0} make your choice.
+# Enchanter #
+SummonSpellHandler.CustomPet.Enchanter.InvocKey:			Underhill
+SummonSpellHandler.CustomPet.Enchanter.InvocSay:			Greetings, Enchanter ! As my {0} {1}, you may target me and say {2} to learn more about the abilities I possess.
+SummonSpellHandler.CustomPet.Enchanter.MainText:			Greetings, friend. As one of the Underhill,c
+# Druid #
+SummonSpellHandler.CustomPet.Druid.InvocKey:				Nature
+SummonSpellHandler.CustomPet.Druid.InvocSay:				Greetings, {0} ! As your nature spirit, you may target me and say {1} to learn more about the abilities I possess.
+SummonSpellHandler.CustomPet.Druid.MainText:				As one of the nature spirit. I can appear to you in any forms: {0} based on your preference.
+
+
 # /Language
 Scripts.Players.Language.Current:			Your language is currently set to: {0}.
 Scripts.Players.Language.Set:				You change your server display language to {0}.
Index: GameServer/language/Language-FR.txt
===================================================================
--- GameServer/language/Language-FR.txt	(revision 663)
+++ GameServer/language/Language-FR.txt	(working copy)
@@ -567,6 +567,31 @@
 Scripts.Players.Duel.YouInGroup:			Vous êtes dans un groupe.
 Scripts.Players.Duel.YouSurrender:			Vous vous rendez à {0}!
 
+# Pet custom text
+SummonSpellHandler.CustomPet.Spiritmaster.MasterMale:			maître
+SummonSpellHandler.CustomPet.Spiritmaster.MasterFemale:			maîtresse
+SummonSpellHandler.CustomPet.Spiritmaster.SummonerMale:			invocateur
+SummonSpellHandler.CustomPet.Spiritmaster.SummonerFemale:		invocatrice
+SummonSpellHandler.CustomPet.Spiritmaster.WeaponKey:				arme
+SummonSpellHandler.CustomPet.Spiritmaster.InvocSay:				Hail, {0}. En tant que mon {1} et {0}, vous pouvez me cibler et dire Niflheim pour en savoir plus sur mes compétences.
+SummonSpellHandler.CustomPet.Spiritmaster.MainText:				Etant un des esprits perdus de Niflheim, je peux prendre l'apparence de n'importe quelle race de guerrier. Vous pouvez me commander d'être {0}. Et vous pouvez aussi me faire choisir l'[{1}] que vous préférez.
+SummonSpellHandler.CustomPet.Spiritmaster.WeaponText:			Quelle arme me commandez-vous de porter? Vous avez le choix entre: {0} ?
+# BoneDancer #
+SummonSpellHandler.CustomPet.Bonedancer.WeaponKey:			armes
+SummonSpellHandler.CustomPet.Bonedancer.InvocKey:			Commander
+SummonSpellHandler.CustomPet.Bonedancer.InvocSay:			Hail, {0}. En tant que mon {1} et {0}, vous pouvez me cibler et dire {2} pour en savoir plus sur mes compétences.
+SummonSpellHandler.CustomPet.Bonedancer.MainText:			Etant un des commandants de Bogdar, j'ai appris à maîtriser la maniement de plusieurs types d'[{0}] fossiles au sein de son armée squelette.
+SummonSpellHandler.CustomPet.Bonedancer.WeaponText:			Je manie parfaitement: {0} faites votre choix.
+# Enchanter #
+SummonSpellHandler.CustomPet.Enchanter.InvocKey:			Voile
+SummonSpellHandler.CustomPet.Enchanter.InvocSay:			Bonjour ! En tant que mon {0} {1}, vous pouvez me cibler et dire '{2}' pour en apprendre plus sur mes compétences.
+SummonSpellHandler.CustomPet.Enchanter.MainText:			Bonjour, Enchanteur ! Etant un habitant du Voile, j'ai la possibilité d'apparaître sous la forme d'un {0}, selon votre préférence.
+# Druid #
+SummonSpellHandler.CustomPet.Druid.InvocKey:				Nature
+SummonSpellHandler.CustomPet.Druid.InvocSay:				Salutations, {0} ! En ma qualité d'esprit naturel, vous pouvez me cibler et dire {1} pour en apprendre plus sur les compétences dont je dispose.
+SummonSpellHandler.CustomPet.Druid.MainText:				J'appartiens aux esprits naturels. Je peux vous apparaître sous la forme d'un grand nombre de formes: {0} selon votre préférence.
+
+
 # /Language
 Scripts.Players.Language.Set:				Vous changez la langue d'affichage du serveur en {0}.
 Scripts.Players.Language.Current:			La langue d'affichage est actuellement: {0}.
\ No newline at end of file
Index: GameServer/spells/SummonSpellHandler.cs
===================================================================
--- GameServer/spells/SummonSpellHandler.cs	(revision 663)
+++ 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);
 		}
 
+        /// <summary>
+        /// Return the pet text based on gender.
+        /// </summary>
+        /// <param name="type">key text</param>
+		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;
+		}
+		
 		/// <summary>
 		/// Apply effect on target or do spell action if non duration spell
 		/// </summary>
@@ -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
+
+        /// <summary>
+        /// Add and Switch weapon method
+        /// </summary>
+        /// <param name="weapon">add custom weapon</param>
+        /// <param name="slot">add weapon in slot get with GetSlot(ItemTemplate, int, string) method</param>
+        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);
+            }
+        }
+
+        /// <summary>
+        /// get slot of pet weapon.
+        /// </summary>
+        /// <param name="weapon">pet weapon</param>
+        /// <param name="slot">return int of weapon.Hand method</param>
+        /// <param name="modelId">pet weapon model say with key word</param>
+        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;
+        }
+
+        /// <summary>
+        /// return the model's Id of the field RaceAvailable.
+        /// </summary>
+        /// <param name="saytext">get model's Id with model's name</param>
+        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]);
 
-		/// <summary>
+                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;
+        }
+
+        /// <summary>
+        /// return the model's Id of the field RaceAvailable.
+        /// </summary>
+        /// <param name="saytext">get model's Id with model's name</param>
+        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;
+        }
+
+        /// <summary>
+        /// race option: return the model's Name of the field RaceAvailable.
+        /// weapon option: return the model's Name of the field WeaponsAvailable.
+        /// </summary>
+        /// <param name="option">search in field</param>
+        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;
+        }
+
+        /// <summary>
+        /// Get if the key word say to pet, with Regex IgnoreCase, match with text option.
+        /// </summary>
+        /// <param name="sArgs">key word</param>
+        /// <param name="text">text match with key word</param>
+        public bool GetSayKeys(SayReceiveEventArgs sArgs ,string text)
+        {
+            if (Regex.Match(sArgs.Text, text, RegexOptions.IgnoreCase).Success)
+                return true;
+            return false;
+        }
+
+        /// <summary>
+        /// Get if the key word whispered to pet, with Regex IgnoreCase, match with text option.
+        /// </summary>
+        /// <param name="wArgs">key word</param>
+        /// <param name="text">text match with key word</param>
+        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
+
+        /// <summary>
 		/// When an applied effect expires.
 		/// Duration spells only.
 		/// </summary>
@@ -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);
+			
 		}
 
 		/// <summary>