/// <summary> /// Create a number of herds of particular types of animal. This could be limited to just one animal per herd depending on the type of animal /// </summary> /// <param name="biome">The biome the animal lives in. If it is null, it'll be ignored</param> /// <param name="domesticated">Whether the animal is domesticated or not. If null, it'll be ignored</param> /// <param name="tag">If contains a tag, will ignore all other values and generate one having the right tag</param> /// <param name="herds">The total amount of herds to be created</param> /// <returns>A list of arrays. Each element of the list represents a different herd. Each element of the array represents an animal within that herd</returns> public static List<List<Actor>> CreateAnimalHerds(GlobalBiome? biome, bool? domesticated, string tag, int herds) { var dictionary = DatabaseHandling.GetDatabase(Archetype.ANIMALS); //Pick the right one var animalData = dictionary.Values.Select(d => new AnimalData(d.ToArray())); IEnumerable<AnimalData> candidates = null; if (String.IsNullOrEmpty(tag)) { if (domesticated != null && domesticated == true) { candidates = animalData.Where(a => a.Domesticated.Equals(domesticated.Value)); } else { candidates = animalData.Where(a => (biome == null || a.BiomeList.Contains(biome.ToString()))); } ; } else { candidates = animalData.Where(a => a.Tags.ToUpper().Split(',').Contains(tag.ToUpper())); } var candidatesList = candidates.ToArray(); List<List<Actor>> retHerds = new List<List<Actor>>(); for (int i = 0; i < herds; i++) { //Let's generate a bunch of herds var chosen = candidatesList[GameState.Random.Next(candidatesList.Length)]; //Let's generate a herd of those List<Actor> herd = new List<Actor>(); int herdContents = GameState.Random.Next(chosen.PackSizeMin, chosen.PackSizeMax); for (int j = 0; j < herdContents; j++) { herd.Add(AnimalGeneration.GenerateAnimal(chosen)); } retHerds.Add(herd); } return retHerds; }
/// <summary> /// Generates a map with a particular biome /// </summary> /// <param name="herdAmount">The total amount of herds to generate</param> /// <param name="BanditAmount">The total amount of bandits to generate.</param> /// <param name="actors"></param> /// <returns></returns> public static MapBlock[,] GenerateMap(GlobalBiome biome, int herdAmount, int banditAmount, out Actor[] actors, out MapCoordinate startPoint) { MapBlock[,] map = new MapBlock[MAP_EDGE, MAP_EDGE]; Random random = new Random(); ItemFactory.ItemFactory factory = new ItemFactory.ItemFactory(); int tileID = 0; factory.CreateItem(Archetype.TILES, details[biome].BaseTileTag, out tileID); //Create a new map which is edge X edge in dimensions and made of the base tile for (int x = 0; x < MAP_EDGE; x++) { for (int y = 0; y < MAP_EDGE; y++) { MapBlock block = new MapBlock(); map[x, y] = block; block.Tile = factory.CreateItem("tile", tileID); block.Tile.Coordinate = new MapCoordinate(x, y, 0, MapType.LOCAL); } } #region Leave Town Item //Now select all the border tiles and put in a "Exit here" border for (int x = 0; x < map.GetLength(0); x++) { MapCoordinate coo = new MapCoordinate(x, 0, 0, MapType.LOCAL); LeaveTownItem lti = new LeaveTownItem(); lti.Coordinate = coo; lti.Description = "continue on your journey"; lti.Name = "Leave Area"; lti.Coordinate = coo; map[x, 0].ForcePutItemOnBlock(lti); coo = new MapCoordinate(x, map.GetLength(1) - 1, 0, MapType.LOCAL); lti = new LeaveTownItem(); lti.Coordinate = coo; lti.Description = "continue on your journey"; lti.Name = "Leave Area"; lti.Coordinate = coo; map[x, map.GetLength(1) - 1].ForcePutItemOnBlock(lti); } for (int y = 0; y < map.GetLength(1); y++) { MapCoordinate coo = new MapCoordinate(0, y, 0, MapType.LOCAL); LeaveTownItem lti = new LeaveTownItem(); lti.Coordinate = coo; lti.Description = "continue on your journey"; lti.Name = "Leave Area"; lti.Coordinate = coo; map[0, y].ForcePutItemOnBlock(lti); coo = new MapCoordinate(map.GetLength(0) - 1, y, 0, MapType.LOCAL); lti = new LeaveTownItem(); lti.Coordinate = coo; lti.Description = "continue on your journey"; lti.Name = "Leave Area"; lti.Coordinate = coo; map[map.GetLength(0) - 1, y].ForcePutItemOnBlock(lti); } #endregion #region Desert Oasis if (biome == GlobalBiome.ARID_DESERT) { //Let's create a pool of water towards one of the corners. int randomNumber = random.Next(2); int rXCoord = 0; if (randomNumber == 1) { //Lower rXCoord = random.Next(0, MAP_EDGE / 3); } else { rXCoord = random.Next(2 * MAP_EDGE / 3, MAP_EDGE); } randomNumber = random.Next(2); int rYCoord = 0; if (randomNumber == 1) { //Lower rYCoord = random.Next(0, MAP_EDGE / 3); } else { rYCoord = random.Next(2 * MAP_EDGE / 3, MAP_EDGE); } //The pool will have a radius of 3 MapCoordinate coo = new MapCoordinate(rXCoord, rYCoord, 0, MapType.LOCAL); //Go through the blocks with a radius of 3 var oasisBlocks = map.Cast<MapBlock>().ToArray().Where(b => Math.Abs(b.Tile.Coordinate - coo) <= 3).ToArray(); int waterTile = -1; factory.CreateItem(Archetype.TILES, "water", out waterTile); foreach (var block in oasisBlocks) { var coord = block.Tile.Coordinate; block.Tile = factory.CreateItem("tile", waterTile); block.Tile.Coordinate = coord; } var aroundOasis = map.Cast<MapBlock>().ToArray().Where(b => Math.Abs(b.Tile.Coordinate - coo) <= 4 && Math.Abs(b.Tile.Coordinate - coo) > 3).ToArray(); int dummy; int grassTile = 0; factory.CreateItem(Archetype.TILES, "grass", out grassTile); foreach (var block in aroundOasis) { var coord = block.Tile.Coordinate; block.Tile = factory.CreateItem("tile", grassTile); block.Tile.Coordinate = coord; } //Put in some trees around the pool for (int i = 0; i < 3; i++) { MapItem tree = factory.CreateItem(Archetype.MUNDANEITEMS, "jungle tree", out dummy); var block = aroundOasis[random.Next(aroundOasis.Length)]; if (block.MayContainItems) { //Drop it block.ForcePutItemOnBlock(tree); } } } #endregion #region Wetland Splotches if (biome == GlobalBiome.WETLAND) { int waterTile = -1; factory.CreateItem(Archetype.TILES, "water", out waterTile); for (int i=0; i < 7; i++) { MapBlock rBlock = map[random.Next(map.GetLength(0)), random.Next(map.GetLength(1))]; Rectangle safeRect = new Rectangle( MAP_EDGE/2 - 5,MAP_EDGE/2 -5,10,10); if (safeRect.Contains(rBlock.Tile.Coordinate.X,rBlock.Tile.Coordinate.Y)) { continue; //Not here! } int size = random.Next(1, 3); //Get all the tiles around the block for a particular size var pool = map.Cast<MapBlock>().ToArray().Where(b => Math.Abs(b.Tile.Coordinate - rBlock.Tile.Coordinate) <= size).ToArray(); foreach(var block in pool) { MapCoordinate coo = block.Tile.Coordinate; block.Tile = factory.CreateItem("tiles", waterTile); block.Tile.Coordinate = coo; } } } #endregion for (int i = 0; i < details[biome].TreeCount; i++) { int treeID = 0; MapItem item = null; item = factory.CreateItem(Archetype.MUNDANEITEMS, details[biome].TreeTag, out treeID); //try 50 times to put it somewhere int tries = 0; while (tries < 50) { MapBlock randomBlock = map[random.Next(map.GetLength(0)), random.Next(map.GetLength(1))]; if (randomBlock.MayContainItems) { randomBlock.ForcePutItemOnBlock(item); break; } tries++; } } List<Actor> actorList = new List<Actor>(); //There, now that's done, lets generate some animals if (herdAmount + banditAmount > 0) { var herds = ActorGeneration.CreateAnimalHerds(biome, false, null, herdAmount); var bandits = CampGenerator.CreateBandits(banditAmount); var actorGroups = herds.Union(bandits); //Each actor group will be placed in a random 3 radius circle foreach (var actorGroup in actorGroups) { MapBlock randomBlock = map[random.Next(map.GetLength(0)), random.Next(map.GetLength(1))]; Rectangle wanderRect = new Rectangle(randomBlock.Tile.Coordinate.X - 2, randomBlock.Tile.Coordinate.Y - 2, 4, 4); //Put the actor groups somewhere around that block var blocks = map.Cast<MapBlock>().ToArray().Where(b => Math.Abs(b.Tile.Coordinate - randomBlock.Tile.Coordinate) < 4).ToArray(); //Pick a number of random blocks foreach (var newActor in actorGroup) { int tries = 0; while (tries < 50) { var actorBlock = blocks[random.Next(blocks.Length)]; if (actorBlock.MayContainItems) { //Put it there newActor.MapCharacter.Coordinate = actorBlock.Tile.Coordinate; actorBlock.ForcePutItemOnBlock(newActor.MapCharacter); //Make them wander newActor.MissionStack.Push(new WanderMission() { LoiterPercentage = 50, WanderPoint = actorBlock.Tile.Coordinate, WanderRectangle = wanderRect }); actorList.Add(newActor); break; } tries++; } } } } //Drop the player in the thick of it MapBlock center = map[map.GetLength(0) / 2, map.GetLength(1) / 2]; center.RemoveTopItem(); //Remove it if someone else wanted it startPoint = center.Tile.Coordinate; actors = actorList.ToArray(); return map; }
/// <summary> /// Parses the maplet. The optional biome is for use on herds /// </summary> /// <param name="xml"></param> /// <param name="biome"></param> /// <returns></returns> public Maplet ParseMaplet(XElement xml,GlobalBiome? biome = null) { //Read the first node - its going to be a maplet XElement element = xml; if (element.Name != "Maplet") { throw new Exception("The expected node was not a maplet"); } Maplet maplet = new Maplet(); //Get the attributes foreach (XAttribute attr in element.Attributes()) { string value = attr.Value; switch (attr.Name.LocalName) { case "MapletName": maplet.MapletName = value; break; case "SizeX": maplet.SizeX = Int32.Parse(value); break; case "SizeY": maplet.SizeY = Int32.Parse(value); break; case "SizeRange": maplet.SizeRange = Int32.Parse(value); break; case "Walled": maplet.Walled = Boolean.Parse(value); break; case "WindowProbability": maplet.WindowProbability = Int32.Parse(value); break; case "Tiled": maplet.Tiled = Boolean.Parse(value); break; case "TileID": maplet.TileID = Int32.Parse(value); break; case "TileTag": maplet.TileTag = value; break; } } maplet.MapletContents = new List<MapletContents>(); XElement mapletContents =element.Elements().First(); //Now we go through all the children foreach (XElement contents in mapletContents.Elements()) { //It's always going to be a MapletContents - so we can pre-populate the data MapletContents content = null; //So, what's the type of it? switch (contents.Name.LocalName) { case "MapletContentsItem": content = new MapletContentsItem(); break; case "MapletContentsItemTag": content = new MapletContentsItemTag(); break; case "MapletContentsMaplet": content = new MapletContentsMaplet(); break; case "MapletActor": content = new MapletActor(); break; case "MapletHerd": content = new MapletHerd() { LocalBiome = biome.HasValue ? biome.Value : GlobalBiome.ARID_DESERT }; break; case "MapletActorWanderArea": content = new MapletActorWanderArea(); break; case "MapletPatrolPoint": content = new MapletPatrolPoint(); break; case "MapletFootpathNode": content = new MapletFootpathNode(); break; case "MapletContentsItemSpecial": content = new MapletContentsItemSpecial(); break; } //Get the attributes foreach (XAttribute attr in contents.Attributes()) { string value = attr.Value; switch (attr.Name.LocalName) { case "ProbabilityPercentage": content.ProbabilityPercentage = Int32.Parse(value); break; case "MaxAmount": content.MaxAmount = Int32.Parse(value); break; case "Position": content.Position = (PositionAffinity) Enum.Parse(typeof(PositionAffinity), value, true); break; case "Padding": content.Padding = Int32.Parse(value); break; case "AllowItemsOnTop": content.AllowItemsOnTop = Boolean.Parse(value); break; case "x": content.x = Int32.Parse(value); break; case "y": content.y = Int32.Parse(value); break; case "ItemCategory": ((MapletContentsItem)content).ItemCategory = value; break; case "ItemID": ((MapletContentsItem)content).ItemID = Int32.Parse(value); break; case "Category": ((MapletContentsItemTag)content).Category = value; break; case "Tag": ((MapletContentsItemTag)content).Tag = value; break; case "FirstFit": ((MapletContentsMaplet)content).FirstFit = bool.Parse(value); break; case "EnemyID": ((MapletActor)content).EnemyID = Int32.Parse(value); break; case "EnemyType": ((MapletActor)content).EnemyType = value; break; case "EnemyTag": ((MapletActor)content).EnemyTag = value; break; case "UseLocalType": ((MapletActor)content).UseLocalType = bool.Parse(value); break; case "EnemyMission": ((MapletActor)content).EnemyMission = (ActorMissionType)Enum.Parse(typeof(ActorMissionType), value.ToUpper()); break; case "VendorType": ((MapletActor)content).VendorType = (VendorType)Enum.Parse(typeof(VendorType), value.ToUpper()); break; case "VendorLevel": ((MapletActor)content).VendorLevel = Int32.Parse(value.ToString()); break; case "BiomeName": ((MapletHerd)content).BiomeName = value.ToString(); break; case "Domesticated": ((MapletHerd)content).Domesticated = bool.Parse(value); break; case "UseLocalBiome": ((MapletHerd)content).UseLocalBiome = bool.Parse(value); break; case "Owners": content.OwnerFactions = value.ToString(); break; case "Profession": if (content.GetType() == typeof(MapletActorWanderArea)) { ((MapletActorWanderArea)content).Profession = (ActorProfession)Enum.Parse(typeof(ActorProfession), value.ToUpper()); } else if (content.GetType() == typeof(MapletPatrolPoint)) { ((MapletPatrolPoint)content).Profession = (ActorProfession)Enum.Parse(typeof(ActorProfession), value.ToUpper()); } break; case "MaximumAmount": content.MaxAmount = Int32.Parse(value); break; case "PatrolName": ((MapletPatrolPoint)content).PatrolName = value; break; case "PointRadius": ((MapletPatrolPoint)content).PointRadius = Int32.Parse(value); break; case "IsPrimary": ((MapletFootpathNode)content).IsPrimary = Boolean.Parse(value); break; case "HerdTag": ((MapletHerd)content).HerdTag = value; break; case "Type": ((MapletContentsItemSpecial)content).Type = value; break; case "Arguments": ((MapletContentsItemSpecial)content).Type = value; break; } } maplet.MapletContents.Add(content); //Now if its a MapletContentsMaplet, it'll contain an element which is the maplet if (typeof(MapletContentsMaplet).Equals(content.GetType())) { if (contents.Elements().First().Name.LocalName.Equals(MAPLETTAG)) { //This is a maplet tag - we load it from the file instead ((MapletContentsMaplet)content).Maplet = ParseMaplet(MapletDatabaseHandler.GetMapletByTag(contents.Elements().First().Attribute("Tag").Value)); } else { ((MapletContentsMaplet)content).Maplet = ParseMaplet(contents.Elements().First()); } } } return maplet; }
/// <summary> /// Loads a Random encounter at a particular biome /// </summary> /// <param name="biome"></param> private void LoadRandomEncounter(GlobalBiome biome) { Actor[] actors = null; MapCoordinate startPoint = null; List<PointOfInterest> pointsOfInterest = null; var gennedCamp = WildernessGenerator.GenerateMap(biome, GameState.Random.Next(1, 5), GameState.Random.Next(0, 2), out actors, out startPoint); GameState.LocalMap = new LocalMap(gennedCamp.GetLength(0), gennedCamp.GetLength(1), 1, 0); GameState.LocalMap.Actors = new List<Actor>(); List<MapBlock> collapsedMap = new List<MapBlock>(); foreach (MapBlock block in gennedCamp) { collapsedMap.Add(block); } GameState.LocalMap.AddToLocalMap(collapsedMap.ToArray()); GameState.PlayerCharacter.MapCharacter.Coordinate = startPoint; MapBlock playerBlock = GameState.LocalMap.GetBlockAtCoordinate(startPoint); playerBlock.PutItemOnBlock(GameState.PlayerCharacter.MapCharacter); GameState.LocalMap.Actors.AddRange(actors); GameState.LocalMap.Actors.Add(GameState.PlayerCharacter); GameState.LocalMap.PointsOfInterest = pointsOfInterest; }
public Maplet ParseMapletFromTag(string tag,GlobalBiome? biome = null) { return ParseMaplet(MapletDatabaseHandler.GetMapletByTag(tag),biome); }