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