public static bool BuildNewEntities(out int spawnZonesCount)
        {
            spawnZonesCount = 0;

            foreach (Facet facet in World.Facets)
            {
                foreach (Land land in facet.Lands)
                {
                    foreach (Map map in land.Maps)
                    {
                        foreach (ZPlane zPlane in map.ZPlanes.Values)
                        {
                            try
                            {
                                if (zPlane.zAutonomy != null && zPlane.zAutonomy.entities != null && zPlane.zAutonomy.entities.Length > 0)
                                {
                                    // name(class|class2),name,name,name(class|class|class)
                                    string[] critters = zPlane.zAutonomy.entities.Split(",".ToCharArray());

                                    List <Tuple <string, EntityLists.Entity, string> > creatureDescProfessionTuples = new List <Tuple <string, EntityLists.Entity, string> >();

                                    #region Create list of Tuples with EntityLists.Entity and profession or profession synonym string.
                                    foreach (string s in critters)
                                    {
                                        EntityLists.Entity cr = EntityLists.Entity.Alligator;

                                        string desc = "";

                                        // adjective(s) for descriptive, and other purposes
                                        if (s.StartsWith("["))
                                        {
                                            desc = s.Substring(s.IndexOf("[") + 1, s.IndexOf("]") - s.IndexOf("[") - 1);
                                        }

                                        string critterType = "";

                                        if (s.Contains("(")) // various professions
                                        {
                                            if (s.StartsWith("["))
                                            {
                                                critterType = s.Substring(s.IndexOf("]") + 1, s.IndexOf("(") - s.IndexOf("]") - 1);
                                            }
                                            else
                                            {
                                                critterType = s.Substring(0, s.IndexOf("("));
                                            }

                                            if (!Enum.TryParse(critterType, true, out cr))
                                            {
                                                Utils.Log("Error parsing CreatureLists.Creature (" + critterType + ") from zPlane: " + zPlane.ToString(), Utils.LogType.SystemWarning);
                                                continue;
                                            }

                                            string[] classesList = s.Substring(s.IndexOf("(") + 1, s.IndexOf(")") - s.IndexOf("(") - 1).Split("|".ToCharArray());

                                            foreach (string cl in classesList)
                                            {
                                                Tuple <string, EntityLists.Entity, string> tuple = Tuple.Create(desc, cr, cl);

                                                if (!creatureDescProfessionTuples.Contains(tuple))
                                                {
                                                    creatureDescProfessionTuples.Add(tuple);
                                                }
                                            }
                                        }
                                        else
                                        {
                                            if (s.StartsWith("["))
                                            {
                                                critterType = s.Substring(s.IndexOf("]") + 1, s.Length - s.IndexOf("]") - 1);
                                            }
                                            else
                                            {
                                                critterType = s;
                                            }

                                            if (!Enum.TryParse(critterType, true, out cr))
                                            {
                                                Utils.Log("Error parsing CreatureLists.Creature ( " + critterType + " ) from zPlane: " + zPlane.ToString(), Utils.LogType.SystemWarning);
                                                continue;
                                            }

                                            Tuple <string, EntityLists.Entity, string> tuple = Tuple.Create(desc, cr, "Fighter");

                                            if (!creatureDescProfessionTuples.Contains(tuple))
                                            {
                                                creatureDescProfessionTuples.Add(tuple);
                                            }
                                        }
                                    }
                                    #endregion

                                    NPC        npc       = null;
                                    List <int> NPCIDList = new List <int>();
                                    List <int> WaterDwellingNPCIDList = new List <int>();
                                    Dictionary <int, Tuple <int, int> > SpawnGroupAmounts      = new Dictionary <int, Tuple <int, int> >();
                                    Dictionary <int, Tuple <int, int> > WaterSpawnGroupAmounts = new Dictionary <int, Tuple <int, int> >();

                                    foreach (Tuple <string, EntityLists.Entity, string> tuple in creatureDescProfessionTuples)
                                    {
                                        npc = null;

                                        #region Check if an entity/profession, in the same level range, has already been built. If so, choose it for the SpawnZone.
                                        foreach (Tuple <EntityLists.Entity, string, int> createdNPC in AutoCreatedNPCDictionary.Keys)
                                        {
                                            // if an Entity/profession pair has already been created, check level and use if within range.
                                            if (createdNPC.Item1 == tuple.Item2 && createdNPC.Item2 == tuple.Item3 && AutoCreatedNPCDictionary[createdNPC].shortDesc.Contains(tuple.Item1))
                                            {
                                                if (AutoCreatedNPCDictionary[createdNPC].Level >= zPlane.zAutonomy.minimumSuggestedLevel &&
                                                    AutoCreatedNPCDictionary[createdNPC].Level <= zPlane.zAutonomy.maximumSuggestedLevel)
                                                {
                                                    npc = AutoCreatedNPCDictionary[createdNPC].CloneNPC();
                                                    break;
                                                }
                                            }
                                        }
                                        #endregion

                                        if (npc == null)
                                        {
                                            if (EntityLists.IsMerchant(tuple.Item2))
                                            {
                                                npc = new Merchant();

                                                if (EntityLists.TRAINER_SPELLS.Contains(tuple.Item2))
                                                {
                                                    (npc as Merchant).trainerType = Merchant.TrainerType.Spell;
                                                }
                                                else if (EntityLists.TRAINER_ANIMAL.Contains(tuple.Item2))
                                                {
                                                    (npc as Merchant).trainerType = Merchant.TrainerType.Animal;
                                                }

                                                if (EntityLists.MENTOR.Contains(tuple.Item2))
                                                {
                                                    (npc as Merchant).interactiveType = Merchant.InteractiveType.Mentor;
                                                }

                                                if (!EntityLists.MOBILE.Contains(tuple.Item2))
                                                {
                                                    npc.IsMobile = false;
                                                }
                                            }
                                            else
                                            {
                                                npc = new NPC();
                                            }

                                            EntityBuilder builder = new EntityBuilder();

                                            if (!builder.BuildEntity(tuple.Item1, tuple.Item2, npc, zPlane, tuple.Item3))
                                            {
                                                // Log an issue with building a new entity, move on to next.
                                                Utils.Log("Failed to build entity: " + tuple.Item1.ToString() + ", " + tuple.Item2.ToString() + " ZPlane: " + zPlane.ToString(), Utils.LogType.SystemWarning);
                                                continue;
                                            }
                                            else
                                            {
                                                // Built a new entity (NPC), add it to the dictionary.
                                                AutoCreatedNPCDictionary.Add(Tuple.Create(tuple.Item2, tuple.Item3, npc.npcID), npc);
                                            }
                                        }

                                        if (npc != null)
                                        {
                                            if (!NPCIDList.Contains(npc.npcID))
                                            {
                                                if (!npc.IsWaterDweller)
                                                {
                                                    NPCIDList.Add(npc.npcID);
                                                }
                                                else
                                                {
                                                    WaterDwellingNPCIDList.Add(npc.npcID);
                                                }

                                                // Currently limiting social groups of spell warming professions to humans only.
                                                // Let's say other humanoid casters don't work well together as there is too much of a power struggle.
                                                // Maybe in the future there will be exceptions to this rule.
                                                if (EntityLists.SOCIAL.Contains(tuple.Item2) && ((npc.IsSpellWarmingProfession && EntityLists.HUMAN.Contains(tuple.Item2)) || !npc.IsSpellWarmingProfession) &&
                                                    !SpawnGroupAmounts.ContainsKey(npc.npcID))
                                                {
                                                    int low  = 2;
                                                    int high = 4;

                                                    // Animals typically have more members in a group.
                                                    if (EntityLists.ANIMAL.Contains(tuple.Item2))
                                                    {
                                                        high += Rules.Dice.Next(0, Rules.RollD(1, 2));
                                                    }

                                                    // Humanoids and humans have a chance to be alone.
                                                    if (EntityLists.IsHumanOrHumanoid(npc) && Rules.RollD(1, 100) < 15)
                                                    {
                                                        low  = 1;
                                                        high = 2;
                                                    }

                                                    if (!npc.IsWaterDweller)
                                                    {
                                                        SpawnGroupAmounts.Add(npc.npcID, Tuple.Create(low, high));
                                                    }
                                                    else
                                                    {
                                                        WaterSpawnGroupAmounts.Add(npc.npcID, Tuple.Create(low, high));
                                                    }
                                                }
                                            }
                                            else
                                            {
                                                Utils.Log("NPC ID already exists in SpawnZone NPCIDList in BuildNewEntities(). NPC: " + npc.GetLogString() + " ZPlane: " + zPlane.ToString(), Utils.LogType.SystemWarning);
                                            }
                                        }
                                    }

                                    if (NPCIDList.Count > 0)
                                    {
                                        SpawnZone szl = new SpawnZone(facet, NPCIDList[0], NPCIDList, SpawnGroupAmounts, land.LandID, map.MapID, zPlane.zCord, false);
                                        facet.Add(szl);
                                        if (!SpawnZone.Spawns.ContainsKey(szl.ZoneID))
                                        {
                                            SpawnZone.Spawns.Add(szl.ZoneID, szl);
                                        }
                                        spawnZonesCount++;
                                    }
                                    else if (WaterDwellingNPCIDList.Count > 0)
                                    {
                                        SpawnZone szl = new SpawnZone(facet, WaterDwellingNPCIDList[0], NPCIDList, SpawnGroupAmounts, land.LandID, map.MapID, zPlane.zCord, true);
                                        facet.Add(szl);
                                        if (!SpawnZone.Spawns.ContainsKey(szl.ZoneID))
                                        {
                                            SpawnZone.Spawns.Add(szl.ZoneID, szl);
                                        }
                                        spawnZonesCount++;
                                    }
                                }

                                if (zPlane.zAutonomy != null && zPlane.zAutonomy.uniqueEntities.Count > 0)
                                {
                                    EntityBuilder builder = new EntityBuilder();

                                    foreach (ZUniqueEntity zUnique in zPlane.zAutonomy.uniqueEntities)
                                    {
                                        NPC npc;

                                        if (EntityLists.IsMerchant(zUnique.entity))
                                        {
                                            npc = new Merchant();

                                            if (EntityLists.TRAINER_SPELLS.Contains(zUnique.entity))
                                            {
                                                (npc as Merchant).trainerType = Merchant.TrainerType.Spell;
                                            }
                                            else if (EntityLists.TRAINER_ANIMAL.Contains(zUnique.entity))
                                            {
                                                (npc as Merchant).trainerType = Merchant.TrainerType.Animal;
                                            }

                                            if (EntityLists.MENTOR.Contains(zUnique.entity))
                                            {
                                                (npc as Merchant).interactiveType = Merchant.InteractiveType.Mentor;
                                            }

                                            if (!EntityLists.MOBILE.Contains(zUnique.entity))
                                            {
                                                npc.IsMobile = false;
                                            }
                                        }
                                        else
                                        {
                                            npc = new NPC();
                                        }

                                        npc.lairCritter = zUnique.hasLair;
                                        npc.lairCells   = zUnique.lairCells;

                                        if (!builder.BuildEntity(zUnique.description, zUnique.entity, npc, zPlane, zUnique.profession))
                                        {
                                            // Log an issue with building a new unique entity, move on to next.
                                            Utils.Log("Failed to build unique entity: " + zUnique.description + ", " + zUnique.entity + " ZPlane: " + zPlane.ToString(), Utils.LogType.SystemWarning);
                                            continue;
                                        }
                                        else
                                        {
                                            // Built a new unique entity (NPC), add it to the dictionary.
                                            AutoCreatedNPCDictionary.Add(Tuple.Create(zUnique.entity, zUnique.profession, npc.npcID), npc);
                                        }

                                        // add spawn zone
                                        SpawnZone szl = new SpawnZone(facet, zUnique, npc, land.LandID, map.MapID, zPlane.zCord, npc.IsWaterDweller);
                                        facet.Add(szl);
                                        if (!SpawnZone.Spawns.ContainsKey(szl.ZoneID))
                                        {
                                            SpawnZone.Spawns.Add(szl.ZoneID, szl);
                                        }
                                        spawnZonesCount++;
                                    }
                                }
                            }
                            catch (Exception e)
                            {
                                Utils.Log("EntityCreationManager.BuildNewEntities issue with map:" + map.Name + " zPlane:" + zPlane.name + ". Check autonomous tags and info.", Utils.LogType.ExceptionDetail);
                                Utils.LogException(e);
                            }
                        }
                    }
                }
            }

            return(true);
        }
示例#2
0
        public bool OnCast(Character caster, string args)
        {
            // There is no power level to this spell. Only one demon may be controlled, and if the caster has
            // any pets the spell will flail. The demon will be very powerful, this it's why it is a skill 17 spell.

            // First gather a list of unnamed demons.

            if (caster.Pets != null && caster.Pets.Count > 0 && (caster is PC) && (caster as PC).ImpLevel < Globals.eImpLevel.DEVJR)
            {
                caster.WriteToDisplay("Summoning a demon requires your full concentration.");
                return(false);
            }

            List <EntityLists.Entity> availableDemons = new List <EntityLists.Entity>();

            foreach (EntityLists.Entity entity in EntityLists.DEMONS)
            {
                if (!EntityLists.NAMED_DEMONS.Contains(entity))
                {
                    availableDemons.Add(entity);
                }
            }

            NPC demon = NPC.LoadNPC(Item.ID_SUMMONEDMOB, caster.FacetID, caster.LandID, caster.MapID, caster.X, caster.Y, caster.Z, -1);

            EntityLists.Entity chosenDemon = availableDemons[Rules.Dice.Next(availableDemons.Count)];

            EntityBuilder builder = new EntityBuilder();

            demon.Level  = caster.Level + Rules.RollD(3, 4);
            demon.entity = chosenDemon;
            List <Character.ClassType> allowedProfessions = new List <Character.ClassType>
            {
                Character.ClassType.Fighter,
                Character.ClassType.Ravager,
                //Character.ClassType.Sorcerer,
                //Character.ClassType.Thaumaturge,
                Character.ClassType.Thief,
                Character.ClassType.Wizard,
            };

            demon.BaseProfession = allowedProfessions[Rules.Dice.Next(0, allowedProfessions.Count - 1)];

            builder.SetOnTheFlyVariables(demon);
            EntityBuilder.SetVisualKey(demon.entity, demon);
            builder.SetName(demon, demon.BaseProfession.ToString().ToLower());
            builder.SetDescriptions("summoned", demon, caster.Map.ZPlanes[caster.Z], demon.BaseProfession.ToString().ToLower());
            EntityBuilder.SetGender(demon, caster.Map.ZPlanes[caster.Z]);
            EntityBuilder.SetVisualKey(demon.entity, demon);

            if (demon.IsSpellUser)
            {
                NPC.CreateGenericSpellList(demon);
                GameSpell.FillSpellLists(demon);
            }

            if (EntityLists.IsHumanOrHumanoid(demon))
            {
                demon.wearing.Clear();

                List <int> armorToWear = Autonomy.ItemBuilding.ArmorSets.ArmorSet.ArmorSetDictionary[Autonomy.ItemBuilding.ArmorSets.ArmorSet.FULL_STEEL].GetArmorList(demon);

                foreach (int id in armorToWear)
                {
                    Item armor = Item.CopyItemFromDictionary(id);
                    armor.special += " " + Item.EXTRAPLANAR;
                    demon.WearItem(armor);
                }
            }

            if (EntityLists.IsHumanOrHumanoid(demon) || EntityLists.ANIMALS_WIELDING_WEAPONS.Contains(demon.entity))
            {
                List <int> weaponsList = Autonomy.ItemBuilding.LootManager.GetBasicWeaponsFromArmory(demon, true);
                if (weaponsList.Count > 0)
                {
                    demon.EquipRightHand(Item.CopyItemFromDictionary(weaponsList[Rules.Dice.Next(weaponsList.Count - 1)]));
                }
                weaponsList = Autonomy.ItemBuilding.LootManager.GetBasicWeaponsFromArmory(demon, false);
                if (weaponsList.Count > 0)
                {
                    demon.EquipLeftHand(Item.CopyItemFromDictionary(weaponsList[Rules.Dice.Next(weaponsList.Count - 1)]));
                }

                if (demon.RightHand != null)
                {
                    demon.RightHand.special += " " + Item.EXTRAPLANAR;
                }
                if (demon.LeftHand != null)
                {
                    demon.LeftHand.special += " " + Item.EXTRAPLANAR;
                }
            }

            demon.castMode = NPC.CastMode.Limited;

            demon.Hits    = demon.HitsFull;
            demon.Mana    = demon.ManaFull;
            demon.Stamina = demon.StaminaFull;

            demon.Alignment = Globals.eAlignment.ChaoticEvil;
            demon.race      = "Hell";

            //demon.aiType = NPC.AIType.EmptySlot;
            demon.Age     = 0;
            demon.special = "despawn";
            int fiveMinutes = Utils.TimeSpanToRounds(new TimeSpan(0, 5, 0));

            // 5 minutes plus 1 minute per magic skill level
            demon.RoundsRemaining = fiveMinutes + Skills.GetSkillLevel(caster.magic) * Utils.TimeSpanToRounds(new TimeSpan(0, 1, 0));
            demon.species         = Globals.eSpecies.Demon; // this may need to be changed for AI to work properly
            demon.Alignment       = caster.Alignment;
            demon.canCommand      = true;
            demon.IsMobile        = true;
            demon.IsSummoned      = true;
            demon.IsUndead        = EntityLists.UNDEAD.Contains(demon.entity);

            demon.FollowID = caster.UniqueID;

            demon.PetOwner = caster;
            caster.Pets.Add(demon);

            if (demon.CurrentCell != caster.CurrentCell)
            {
                demon.CurrentCell = caster.CurrentCell;
            }

            demon.EmitSound(demon.idleSound);

            demon.AddToWorld();

            return(true);
        }
示例#3
0
        public bool OnCast(Character caster, string args)
        {
            #region Determine number of pets. Return false if at or above MAX_PETS.
            if (!caster.IsImmortal)
            {
                int petCount = 0;

                foreach (NPC pet in caster.Pets)
                {
                    if (pet.QuestList.Count == 0)
                    {
                        petCount++;
                    }
                }

                if (petCount >= GameSpell.MAX_PETS)
                {
                    caster.WriteToDisplay("You do not possess the mental fortitude to summon an ally.");
                    return(false);
                }
            }
            #endregion

            args = args.Replace(ReferenceSpell.Command, "");
            args = args.Trim();
            string[] sArgs = args.Split(" ".ToCharArray());

            #region Determine Power
            int magicSkillLevel = Skills.GetSkillLevel(caster.magic);
            int power           = magicSkillLevel;

            if (sArgs.Length > 0)
            {
                try
                {
                    power = Convert.ToInt32(sArgs[0]);

                    if (power > magicSkillLevel && !caster.IsImmortal)
                    {
                        power = magicSkillLevel;
                    }
                }
                catch (Exception)
                {
                    power = magicSkillLevel;
                }
            }

            if (power < 1)
            {
                power = caster.Level;
            }
            #endregion

            Entity entity = Entity.Fighter;

            Enum.TryParse(caster.BaseProfession.ToString(), true, out entity);

            EntityBuilder builder = new EntityBuilder();

            string profession = entity.ToString().ToLower();

            if (!EntityLists.IsHuman(caster) || Rules.RollD(1, 100) < 50)
            {
                string entityLowerCase = caster.entity.ToString().ToLower();
                if (entityLowerCase.StartsWith("drow"))
                {
                    entity = Entity.Drow;
                    // Drow.Master summons drow thieves, Drow.Matriarch summons drow priestesses unless uncomment below lines
                    //List<string> availableProfessions = new List<string>() {"anathema", "cleric", "ravager", "rogue", "sorcerer" };
                    //profession = availableProfessions[Rules.Dice.Next(0, availableProfessions.Count - 1)];
                }
                else if (EntityLists.ELVES.Contains(caster.entity))
                {
                    List <Entity> allyEntities = new List <Entity>()
                    {
                        Entity.Grey_Elf,
                        Entity.High_Elf,
                        Entity.Wood_Elf
                    };
                }
                else
                {
                    List <Entity> allyEntities = new List <Entity>()
                    {
                        Entity.Gnome, Entity.Goblin,
                        Entity.Kobold,
                        Entity.Orc,
                        Entity.Tengu,
                    };

                    entity = allyEntities[Rules.Dice.Next(0, allyEntities.Count - 1)];
                }

                //profession = EntityBuilder.THIEF_SYNONYMS[Rules.Dice.Next(0, EntityBuilder.THIEF_SYNONYMS.Length - 1)];
            }

            NPC ally = builder.BuildEntity("allied", entity, caster.Map.ZPlanes[caster.Z], profession);

            // Set level.
            ally.Level = Math.Max(caster.Level, magicSkillLevel) + Rules.Dice.Next(-1, 1); // magic skill should be set to higher skill if using impcast
            if (ally.Level <= 0)
            {
                ally.Level = 1;
            }

            builder.SetOnTheFlyVariables(ally);
            ally.Alignment = caster.Alignment;
            builder.SetName(ally, profession);
            builder.SetDescriptions("allied", ally, caster.Map.ZPlanes[caster.Z], ally.BaseProfession.ToString().ToLower());
            EntityBuilder.SetGender(ally, caster.Map.ZPlanes[caster.Z]);
            EntityBuilder.SetVisualKey(ally.entity, ally);
            if (ally.spellDictionary.Count > 0)
            {
                ally.magic = Skills.GetSkillForLevel(ally.Level + Rules.Dice.Next(-1, 1));
            }
            GameSpell.FillSpellLists(ally);

            if (EntityLists.IsHumanOrHumanoid(ally))
            {
                List <int> armorToWear;

                if (power <= 13)
                {
                    armorToWear = Autonomy.ItemBuilding.ArmorSets.ArmorSet.ArmorSetDictionary[Autonomy.ItemBuilding.ArmorSets.ArmorSet.FULL_STUDDED_LEATHER].GetArmorList(ally);
                }
                else if (power < 16)
                {
                    armorToWear = Autonomy.ItemBuilding.ArmorSets.ArmorSet.ArmorSetDictionary[Autonomy.ItemBuilding.ArmorSets.ArmorSet.FULL_CHAINMAIL].GetArmorList(ally);
                }
                else
                {
                    armorToWear = Autonomy.ItemBuilding.ArmorSets.ArmorSet.ArmorSetDictionary[Autonomy.ItemBuilding.ArmorSets.ArmorSet.FULL_BANDED_MAIL].GetArmorList(ally);
                }

                foreach (int id in armorToWear)
                {
                    Item armor = Item.CopyItemFromDictionary(id);
                    // It's basic armor sets only. Label them as ethereal. (They will go back with the phantasm to their home plane. Given items drop.)
                    armor.special += " " + Item.EXTRAPLANAR;
                    ally.WearItem(armor);
                }
            }

            if (EntityLists.IsHumanOrHumanoid(ally) || EntityLists.ANIMALS_WIELDING_WEAPONS.Contains(ally.entity))
            {
                List <int> weaponsList = Autonomy.ItemBuilding.LootManager.GetBasicWeaponsFromArmory(ally, true);
                if (weaponsList.Count > 0)
                {
                    ally.EquipRightHand(Item.CopyItemFromDictionary(weaponsList[Rules.Dice.Next(weaponsList.Count - 1)]));
                }
                weaponsList = Autonomy.ItemBuilding.LootManager.GetBasicWeaponsFromArmory(ally, false);
                if (weaponsList.Count > 0)
                {
                    ally.EquipLeftHand(Item.CopyItemFromDictionary(weaponsList[Rules.Dice.Next(weaponsList.Count - 1)]));
                }

                if (ally.RightHand != null)
                {
                    ally.RightHand.special += " " + Item.EXTRAPLANAR;
                }
                if (ally.LeftHand != null)
                {
                    ally.LeftHand.special += " " + Item.EXTRAPLANAR;
                }
            }

            ally.Hits    = ally.HitsFull;
            ally.Mana    = ally.ManaFull;
            ally.Stamina = ally.StaminaFull;

            ally.Age     = GameWorld.World.AgeCycles[Rules.Dice.Next(0, GameWorld.World.AgeCycles.Count - 1)];
            ally.special = "despawn summonthief";

            int oneMinute = Utils.TimeSpanToRounds(new TimeSpan(0, 1, 0));
            // 10 minutes + 2 minutes for every skill level past 3
            ally.RoundsRemaining = (oneMinute * 5) + ((power - ReferenceSpell.RequiredLevel) * oneMinute);
            //ally.species = Globals.eSpecies.Magical; // this may need to be changed for AI to work properly

            ally.canCommand = true;
            ally.IsMobile   = true;
            ally.IsSummoned = true;
            ally.IsUndead   = false;

            ally.FollowID = caster.UniqueID;

            ally.PetOwner = caster;
            caster.Pets.Add(ally);

            if (ally.CurrentCell != caster.CurrentCell)
            {
                ally.CurrentCell = caster.CurrentCell;
            }

            ReferenceSpell.SendGenericCastMessage(caster, null, true);

            ally.EmitSound(ally.idleSound);
            caster.WriteToDisplay((ally.longDesc.StartsWith("evil") ? "An " : "A ") + ally.longDesc + " answers your call for assistance.");
            caster.SendToAllInSight(caster.GetNameForActionResult() + " summons an ally.");
            if (caster is NPC)
            {
                ally.MostHated = (caster as NPC).MostHated;
            }
            ally.AddToWorld();
            return(true);
        }