示例#1
0
        /// <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);
 }