예제 #1
0
        public override void Die()
        {
            if (World == null)
            {
                return;                // WUT
            }
            if (Stats == null)
            {
                return;                // SERIOUSLY WTF??
            }
            World.RemoveFromSpeciesTracking(Stats.Species);

            NoiseMaker.MakeNoise("Die", Physics.Position, true);

            if (AI.Stats.Money > 0)
            {
                EntityFactory.CreateEntity <CoinPile>("Coins Resource", AI.Position, Blackboard.Create("Money", AI.Stats.Money));
            }

            if (Stats.Species.HasMeat)
            {
                String type = Stats.CurrentClass.Name + " " + "Meat";

                if (!Library.DoesResourceTypeExist(type))
                {
                    var r = Library.CreateResourceType(Library.GetResourceType(Stats.Species.BaseMeatResource));
                    r.Name      = type;
                    r.ShortName = type;
                    Library.AddResourceType(r);
                }

                Inventory.AddResource(new ResourceAmount(type, 1));
            }

            if (Stats.Species.HasBones)
            {
                String type = Stats.CurrentClass.Name + " Bone";

                if (!Library.DoesResourceTypeExist(type))
                {
                    var r = Library.CreateResourceType(Library.GetResourceType("Bone"));
                    r.Name      = type;
                    r.ShortName = type;
                    Library.AddResourceType(r);
                }

                Inventory.AddResource(new ResourceAmount(type, 1));
            }

            base.Die();
        }
예제 #2
0
        /// <summary>
        /// Kills the creature and releases its resources.
        /// </summary>
        public override void Die()
        {
            // This is just a silly hack to make sure that creatures
            // carrying resources to a trade depot release their resources
            // when they die.

            CreateMeatAndBones();
            NoiseMaker.MakeNoise("Die", Physics.Position, true);

            if (AI.Status.Money > 0)
            {
                EntityFactory.CreateEntity <CoinPile>("Coins Resource", AI.Position, Blackboard.Create("Money", AI.Status.Money));
            }

            base.Die();
        }
예제 #3
0
        public static IEnumerable <Body> CreateResourcePiles(IEnumerable <ResourceAmount> resources, BoundingBox box)
        {
            const int maxPileSize = 64;

            foreach (ResourceAmount resource in resources)
            {
                for (int numRemaining = resource.NumResources; numRemaining > 0; numRemaining -= maxPileSize)
                {
                    const int maxIters = 10;

                    for (int i = 0; i < maxIters; i++)
                    {
                        Vector3 pos   = MathFunctions.RandVector3Box(box);
                        var     voxel = new VoxelHandle(World.ChunkManager.ChunkData,
                                                        GlobalVoxelCoordinate.FromVector3(pos));
                        if ((!voxel.IsValid) || !voxel.IsEmpty)
                        {
                            continue;
                        }

                        Physics body = EntityFactory.CreateEntity <Physics>(resource.ResourceType + " Resource",
                                                                            pos, Blackboard.Create <int>("num", Math.Min(numRemaining, maxPileSize))) as Physics;


                        if (body != null)
                        {
                            body.Velocity = MathFunctions.RandVector3Cube();
                            body.Velocity.Normalize();
                            body.Velocity  *= 5.0f;
                            body.IsSleeping = false;
                            yield return(body);
                        }
                        break;
                    }
                }
            }
        }
예제 #4
0
        public static void GenerateCaveVegetation(VoxelChunk chunk, int x, int y, int z, int caveHeight, BiomeData biome, Vector3 vec, WorldManager world, Perlin NoiseGenerator)
        {
            var vUnder   = new VoxelHandle(chunk, new LocalVoxelCoordinate(x, y - 1, z));
            var wayUnder = new VoxelHandle(chunk, new LocalVoxelCoordinate(x, y - caveHeight, z));

            wayUnder.RawSetType(VoxelLibrary.GetVoxelType(biome.SoilLayer.VoxelType));

            var grassType = GrassLibrary.GetGrassType(biome.GrassDecal);

            if (grassType != null)
            {
                wayUnder.RawSetGrass(grassType.ID);
            }

            foreach (VegetationData veg in biome.Vegetation)
            {
                if (!MathFunctions.RandEvent(veg.SpawnProbability))
                {
                    continue;
                }

                if (NoiseGenerator.Noise(vec.X / veg.ClumpSize, veg.NoiseOffset, vec.Y / veg.ClumpSize) < veg.ClumpThreshold)
                {
                    continue;
                }

                if (!vUnder.IsEmpty && vUnder.Type.Name == biome.SoilLayer.VoxelType)
                {
                    vUnder.RawSetType(VoxelLibrary.GetVoxelType(biome.SoilLayer.VoxelType));
                    vUnder.RawSetGrass(0);
                    float treeSize = MathFunctions.Rand() * veg.SizeVariance + veg.MeanSize;

                    WorldManager.DoLazy(() =>
                    {
                        if (!GameSettings.Default.FogofWar)
                        {
                            GameComponent entity = EntityFactory.CreateEntity <GameComponent>(veg.Name,
                                                                                              vUnder.WorldPosition + new Vector3(0.5f, 1.0f, 0.5f),
                                                                                              Blackboard.Create("Scale", treeSize));
                        }
                        else
                        {
                            world.ComponentManager.RootComponent.AddChild(new ExploredListener(
                                                                              world.ComponentManager, vUnder)
                            {
                                EntityToSpawn  = veg.Name,
                                SpawnLocation  = vUnder.WorldPosition + new Vector3(0.5f, 1.0f, 0.5f),
                                BlackboardData = Blackboard.Create("Scale", treeSize)
                            });
                        }
                    });
                }
            }

            float spawnLikelihood = (world.InitialEmbark.Difficulty + 0.1f);

            foreach (FaunaData animal in biome.Fauna)
            {
                if (y <= 0 || !(MathFunctions.Random.NextDouble() < animal.SpawnProbability * spawnLikelihood))
                {
                    continue;
                }

                FaunaData animal1 = animal;
                WorldManager.DoLazy(() =>
                {
                    if (!GameSettings.Default.FogofWar)
                    {
                        var entity = EntityFactory.CreateEntity <GameComponent>(animal1.Name,
                                                                                wayUnder.WorldPosition + Vector3.Up * 1.5f);
                    }
                    else
                    {
                        world.ComponentManager.RootComponent.AddChild(new ExploredListener
                                                                          (world.ComponentManager, new VoxelHandle(chunk, wayUnder.Coordinate.GetLocalVoxelCoordinate()))
                        {
                            EntityToSpawn = animal1.Name,
                            SpawnLocation = wayUnder.WorldPosition + Vector3.Up * 1.5f
                        });
                    }
                });
                break;
            }
        }
예제 #5
0
        public void GenerateSurfaceLife(Dictionary <string, Dictionary <string, int> > creatureCounts, VoxelChunk Chunk, float maxHeight)
        {
            //int waterHeight = (int)(VoxelConstants.ChunkSizeY * NormalizeHeight(SeaLevel + 1.0f / VoxelConstants.ChunkSizeY, maxHeight));
            for (var x = 0; x < VoxelConstants.ChunkSizeX; ++x)
            {
                for (var z = 0; z < VoxelConstants.ChunkSizeZ; ++z)
                {
                    var biomeData = Overworld.GetBiomeAt(new Vector3(x + Chunk.Origin.X, 0, z + Chunk.Origin.Z), Chunk.Manager.World.WorldScale, Chunk.Manager.World.WorldOrigin);
                    var topVoxel  = VoxelHelpers.FindFirstVoxelBelow(new VoxelHandle(
                                                                         Chunk, new LocalVoxelCoordinate(x, VoxelConstants.ChunkSizeY - 1, z)));

                    if (!topVoxel.IsValid ||
                        topVoxel.Coordinate.Y == 0 ||
                        topVoxel.Coordinate.Y >= 60)    // Lift to some kind of generator settings?
                    {
                        continue;
                    }
                    var above = VoxelHelpers.GetVoxelAbove(topVoxel);
                    if (above.IsValid && above.LiquidLevel != 0)
                    {
                        continue;
                    }
                    foreach (var animal in biomeData.Fauna)
                    {
                        if (MathFunctions.RandEvent(animal.SpawnProbability))
                        {
                            if (!creatureCounts.ContainsKey(biomeData.Name))
                            {
                                creatureCounts[biomeData.Name] = new Dictionary <string, int>();
                            }
                            var dict = creatureCounts[biomeData.Name];
                            if (!dict.ContainsKey(animal.Name))
                            {
                                dict[animal.Name] = 0;
                            }
                            if (dict[animal.Name] < animal.MaxPopulation)
                            {
                                EntityFactory.CreateEntity <Body>(animal.Name,
                                                                  topVoxel.WorldPosition + Vector3.Up * 1.5f);
                            }
                            break;
                        }
                    }

                    if (topVoxel.Type.Name != biomeData.SoilLayer.VoxelType)
                    {
                        continue;
                    }

                    foreach (VegetationData veg in biomeData.Vegetation)
                    {
                        if (topVoxel.GrassType == 0)
                        {
                            continue;
                        }

                        if (MathFunctions.RandEvent(veg.SpawnProbability) &&
                            NoiseGenerator.Noise(topVoxel.Coordinate.X / veg.ClumpSize,
                                                 veg.NoiseOffset, topVoxel.Coordinate.Z / veg.ClumpSize) >= veg.ClumpThreshold)
                        {
                            topVoxel.RawSetType(VoxelLibrary.GetVoxelType(biomeData.SoilLayer.VoxelType));

                            var treeSize = MathFunctions.Rand() * veg.SizeVariance + veg.MeanSize;
                            var tree     = EntityFactory.CreateEntity <Plant>(veg.Name,
                                                                              topVoxel.WorldPosition + new Vector3(0.5f, 1.0f, 0.5f),
                                                                              Blackboard.Create("Scale", treeSize));

                            break;
                        }
                    }
                }
            }
        }
예제 #6
0
        public void GenerateVegetation(VoxelChunk chunk, ComponentManager components, ContentManager content, GraphicsDevice graphics)
        {
            int   waterHeight = (int)(SeaLevel * chunk.SizeY);
            bool  updated     = false;
            Voxel v           = chunk.MakeVoxel(0, 0, 0);
            Voxel vUnder      = chunk.MakeVoxel(0, 0, 0);

            for (int x = 0; x < chunk.SizeX; x++)
            {
                for (int z = 0; z < chunk.SizeZ; z++)
                {
                    Vector2         vec       = new Vector2(x + chunk.Origin.X, z + chunk.Origin.Z) / PlayState.WorldScale;
                    Overworld.Biome biome     = Overworld.Map[(int)MathFunctions.Clamp(vec.X, 0, Overworld.Map.GetLength(0) - 1), (int)MathFunctions.Clamp(vec.Y, 0, Overworld.Map.GetLength(1) - 1)].Biome;
                    BiomeData       biomeData = BiomeLibrary.Biomes[biome];

                    int y = chunk.GetFilledVoxelGridHeightAt(x, chunk.SizeY - 1, z);

                    if (!chunk.IsCellValid(x, (int)(y - chunk.Origin.Y), z))
                    {
                        continue;
                    }

                    v.GridPosition = new Vector3(x, y, z);

                    if (!v.IsEmpty || chunk.Data.Water[v.Index].WaterLevel != 0 || y <= waterHeight)
                    {
                        continue;
                    }

                    foreach (VegetationData veg in biomeData.Vegetation)
                    {
                        if (y <= 0)
                        {
                            continue;
                        }

                        if (!MathFunctions.RandEvent(veg.SpawnProbability))
                        {
                            continue;
                        }

                        if (NoiseGenerator.Noise(vec.X / veg.ClumpSize, veg.NoiseOffset, vec.Y / veg.ClumpSize) < veg.ClumpThreshold)
                        {
                            continue;
                        }

                        int yh = chunk.GetFilledVoxelGridHeightAt(x, y, z);

                        if (yh > 0)
                        {
                            vUnder.GridPosition = new Vector3(x, yh - 1, z);
                            if (!vUnder.IsEmpty && vUnder.TypeName == biomeData.GrassVoxel)
                            {
                                vUnder.Type = VoxelLibrary.GetVoxelType(biomeData.SoilVoxel);
                                updated     = true;
                                float offset = veg.VerticalOffset;
                                if (vUnder.RampType != RampType.None)
                                {
                                    offset -= 0.25f;
                                }
                                float treeSize = MathFunctions.Rand() * veg.SizeVariance + veg.MeanSize;
                                EntityFactory.CreateEntity <Body>(veg.Name, chunk.Origin + new Vector3(x, y, z) + new Vector3(0, treeSize * offset, 0), Blackboard.Create("Scale", treeSize));
                            }
                        }

                        break;
                    }
                }
            }

            if (updated)
            {
                chunk.ShouldRebuild = true;
            }
        }
예제 #7
0
        public void VoxelsSelected(List <VoxelHandle> refs, InputManager.MouseButton button)
        {
            if (!IsEnabled)
            {
                return;
            }
            switch (button)
            {
            case (InputManager.MouseButton.Left):
            {
                List <Task> assignments = new List <Task>();
                // Creating multiples doesn't work anyway - kill it.
                foreach (var r in refs)
                {
                    if (IsDesignation(r) || !r.IsValid || !r.IsEmpty)
                    {
                        continue;
                    }
                    else
                    {
                        Vector3 pos = r.WorldPosition + new Vector3(0.5f, 0.0f, 0.5f) + CurrentCraftType.SpawnOffset;

                        Vector3 startPos = pos + new Vector3(0.0f, -0.1f, 0.0f);
                        Vector3 endPos   = pos;
                        // TODO: Why are we creating a new designation?
                        CraftDesignation newDesignation = new CraftDesignation()
                        {
                            ItemType            = CurrentCraftType,
                            Location            = r,
                            Orientation         = CurrentDesignation.Orientation,
                            OverrideOrientation = CurrentDesignation.OverrideOrientation,
                            Valid             = true,
                            Entity            = CurrentCraftBody,
                            SelectedResources = SelectedResources
                        };

                        if (IsValid(newDesignation))
                        {
                            AddDesignation(newDesignation, CurrentCraftType.SpawnOffset);
                            assignments.Add(new CraftItemTask(newDesignation));

                            // Todo: Maybe don't support create huge numbers of entities at once?
                            CurrentCraftBody = EntityFactory.CreateEntity <Body>(CurrentCraftType.Name, r.WorldPosition,
                                                                                 Blackboard.Create <List <ResourceAmount> >("Resources", SelectedResources));
                            EntityFactory.GhostEntity(CurrentCraftBody, Color.White);

                            newDesignation.WorkPile = new WorkPile(World.ComponentManager, startPos);
                            World.ComponentManager.RootComponent.AddChild(newDesignation.WorkPile);
                            newDesignation.WorkPile.AnimationQueue.Add(new EaseMotion(1.1f, Matrix.CreateTranslation(startPos), endPos));
                            World.ParticleManager.Trigger("puff", pos, Color.White, 10);
                        }
                    }
                }

                if (assignments.Count > 0)
                {
                    World.Master.TaskManager.AddTasks(assignments);
                }

                break;
            }

            case (InputManager.MouseButton.Right):
            {
                foreach (var r in refs)
                {
                    if (!IsDesignation(r))
                    {
                        continue;
                    }
                    RemoveDesignation(r);
                }
                break;
            }
            }
        }
예제 #8
0
        public void Update(DwarfTime gameTime, GameMaster player)
        {
            if (!IsEnabled)
            {
                if (CurrentCraftBody != null)
                {
                    CurrentCraftBody.Delete();
                    CurrentCraftBody = null;
                }

                return;
            }

            if (Faction == null)
            {
                Faction = player.Faction;
            }

            if (CurrentCraftType != null && CurrentCraftBody == null)
            {
                CurrentCraftBody = EntityFactory.CreateEntity <Body>(CurrentCraftType.Name,
                                                                     player.VoxSelector.VoxelUnderMouse.WorldPosition,
                                                                     Blackboard.Create <List <ResourceAmount> >("Resources", SelectedResources));
                EntityFactory.GhostEntity(CurrentCraftBody, Color.White);

                CurrentDesignation = new CraftDesignation()
                {
                    ItemType = CurrentCraftType,
                    Location = VoxelHandle.InvalidHandle,
                    Valid    = true
                };

                OverrideOrientation = false;
                CurrentCraftBody.SetTintRecursive(Color.Green);
            }

            if (CurrentCraftBody == null || !player.VoxSelector.VoxelUnderMouse.IsValid)
            {
                return;
            }

            CurrentCraftBody.LocalPosition = player.VoxSelector.VoxelUnderMouse.WorldPosition + new Vector3(0.5f, 0.0f, 0.5f) + CurrentCraftType.SpawnOffset;

            CurrentCraftBody.GlobalTransform = CurrentCraftBody.LocalTransform;
            CurrentCraftBody.UpdateTransform();
            CurrentCraftBody.PropogateTransforms();
            if (OverrideOrientation)
            {
                CurrentCraftBody.Orient(CurrentOrientation);
            }
            else
            {
                CurrentCraftBody.OrientToWalls();
            }

            HandleOrientation();

            if (CurrentDesignation != null)
            {
                if (CurrentDesignation.Location.Equals(player.VoxSelector.VoxelUnderMouse))
                {
                    return;
                }

                CurrentDesignation.Location = player.VoxSelector.VoxelUnderMouse;

                World.ShowTooltip("Click to build. Press R/T to rotate.");
                CurrentCraftBody.SetTintRecursive(IsValid(CurrentDesignation) ? Color.Green : Color.Red);
            }
        }
예제 #9
0
        public void GenerateCaves(VoxelChunk chunk)
        {
            Vector3      origin     = chunk.Origin;
            int          chunkSizeX = chunk.SizeX;
            int          chunkSizeY = chunk.SizeY;
            int          chunkSizeZ = chunk.SizeZ;
            BiomeData    biome      = BiomeLibrary.Biomes[Overworld.Biome.Cave];
            List <Voxel> neighbors  = new List <Voxel>();
            Voxel        vUnder     = chunk.MakeVoxel(0, 0, 0);

            for (int x = 0; x < chunkSizeX; x++)
            {
                for (int z = 0; z < chunkSizeZ; z++)
                {
                    int h = chunk.GetFilledVoxelGridHeightAt(x, chunk.SizeY - 1, z);
                    for (int i = 0; i < CaveLevels.Count; i++)
                    {
                        int y = CaveLevels[i];
                        if (y <= 0 || y >= h - 1)
                        {
                            continue;
                        }
                        Vector3 vec       = new Vector3(x, y, z) + chunk.Origin;
                        double  caveNoise = CaveNoise.GetValue((x + origin.X) * CaveNoiseScale * CaveFrequencies[i],
                                                               (y + origin.Y) * CaveNoiseScale * 3.0f, (z + origin.Z) * CaveNoiseScale * CaveFrequencies[i]);

                        double heightnoise = NoiseGenerator.Noise((x + origin.X) * NoiseScale * CaveFrequencies[i],
                                                                  (y + origin.Y) * NoiseScale * 3.0f, (z + origin.Z) * NoiseScale * CaveFrequencies[i]);

                        int caveHeight = Math.Min(Math.Max((int)(heightnoise * 5), 1), 3);

                        if (caveNoise > CaveSize)
                        {
                            bool waterFound = false;
                            for (int dy = 0; dy < caveHeight; dy++)
                            {
                                int index = chunk.Data.IndexAt(x, y - dy, z);
                                chunk.GetNeighborsManhattan(x, y - dy, z, neighbors);

                                if (neighbors.Any(v => v.WaterLevel > 0))
                                {
                                    waterFound = true;
                                }

                                if (waterFound)
                                {
                                    break;
                                }

                                chunk.Data.Types[index] = 0;
                            }

                            if (!waterFound && caveNoise > CaveSize * 1.8f && y - caveHeight > 0)
                            {
                                int indexunder = chunk.Data.IndexAt(x, y - caveHeight, z);
                                chunk.Data.Types[indexunder]      = (byte)VoxelLibrary.GetVoxelType(biome.GrassVoxel).ID;
                                chunk.Data.Health[indexunder]     = (byte)VoxelLibrary.GetVoxelType(biome.GrassVoxel).StartingHealth;
                                chunk.Data.IsExplored[indexunder] = false;
                                foreach (VegetationData veg in biome.Vegetation)
                                {
                                    if (!MathFunctions.RandEvent(veg.SpawnProbability))
                                    {
                                        continue;
                                    }

                                    if (NoiseGenerator.Noise(vec.X / veg.ClumpSize, veg.NoiseOffset, vec.Y / veg.ClumpSize) < veg.ClumpThreshold)
                                    {
                                        continue;
                                    }


                                    vUnder.GridPosition = new Vector3(x, y - 1, z);
                                    if (!vUnder.IsEmpty && vUnder.TypeName == biome.GrassVoxel)
                                    {
                                        vUnder.Type = VoxelLibrary.GetVoxelType(biome.SoilVoxel);
                                        float offset = veg.VerticalOffset;
                                        if (vUnder.RampType != RampType.None)
                                        {
                                            offset -= 0.25f;
                                        }
                                        float         treeSize = MathFunctions.Rand() * veg.SizeVariance + veg.MeanSize;
                                        GameComponent entity   = EntityFactory.CreateEntity <GameComponent>(veg.Name, chunk.Origin + new Vector3(x, y, z) + new Vector3(0, treeSize * offset, 0), Blackboard.Create("Scale", treeSize));
                                        entity.GetRootComponent().SetActiveRecursive(false);
                                        entity.GetRootComponent().SetVisibleRecursive(false);
                                        if (GameSettings.Default.FogofWar)
                                        {
                                            ExploredListener listener = new ExploredListener(
                                                PlayState.ComponentManager, entity, PlayState.ChunkManager, vUnder);
                                        }
                                    }
                                }
                            }

                            foreach (FaunaData animal in biome.Fauna)
                            {
                                if (y <= 0 || !(PlayState.Random.NextDouble() < animal.SpawnProbability))
                                {
                                    continue;
                                }


                                var entity = EntityFactory.CreateEntity <GameComponent>(animal.Name, chunk.Origin + new Vector3(x, y, z) + Vector3.Up * 1.0f);
                                entity.GetRootComponent().SetActiveRecursive(false);
                                entity.GetRootComponent().SetVisibleRecursive(false);

                                if (GameSettings.Default.FogofWar)
                                {
                                    ExploredListener listener = new ExploredListener(PlayState.ComponentManager, entity,
                                                                                     PlayState.ChunkManager, chunk.MakeVoxel(x, y, z));
                                }
                                break;
                            }
                        }
                    }
                }
            }
        }
예제 #10
0
        public override void Destroy()
        {
            BoundingBox box         = GetBoundingBox();
            const int   maxPileSize = 64;

            foreach (ResourceAmount resource in Resources)
            {
                for (int numRemaining = resource.NumResources; numRemaining > 0; numRemaining -= maxPileSize)
                {
                    Physics body = EntityFactory.CreateEntity <Physics>(resource.ResourceType + " Resource",
                                                                        Vector3.Up + MathFunctions.RandVector3Box(box), Blackboard.Create <int>("num", Math.Min(numRemaining, maxPileSize))) as Physics;

                    if (body != null)
                    {
                        body.Velocity = MathFunctions.RandVector3Cube();
                    }
                }
            }

            if (Faction != null)
            {
                Faction.Stockpiles.Remove(this);
            }
            base.Destroy();
        }
예제 #11
0
        public void GenerateSurfaceLife(VoxelChunk Chunk)
        {
            var waterHeight = (int)(SeaLevel * VoxelConstants.ChunkSizeY);

            for (var x = 0; x < VoxelConstants.ChunkSizeX; ++x)
            {
                for (var z = 0; z < VoxelConstants.ChunkSizeZ; ++z)
                {
                    var biomeData = GetBiomeAt(new Vector2(x + Chunk.Origin.X, z + Chunk.Origin.Z));
                    var topVoxel  = VoxelHelpers.FindFirstVoxelBelow(new VoxelHandle(
                                                                         Chunk, new LocalVoxelCoordinate(x, VoxelConstants.ChunkSizeY - 1, z)));

                    if (!topVoxel.IsValid ||
                        topVoxel.Coordinate.Y == 0 ||
                        topVoxel.Coordinate.Y >= 60)    // Lift to some kind of generator settings?
                    {
                        continue;
                    }
                    var above = VoxelHelpers.GetVoxelAbove(topVoxel);
                    if (above.IsValid && above.WaterCell.WaterLevel != 0)
                    {
                        continue;
                    }
                    foreach (var animal in biomeData.Fauna)
                    {
                        if (MathFunctions.RandEvent(animal.SpawnProbability))
                        {
                            EntityFactory.CreateEntity <Body>(animal.Name,
                                                              topVoxel.WorldPosition + Vector3.Up * 1.5f);

                            break;
                        }
                    }

                    if (topVoxel.Type.Name != biomeData.SoilLayer.VoxelType)
                    {
                        continue;
                    }

                    foreach (VegetationData veg in biomeData.Vegetation)
                    {
                        if (topVoxel.GrassType == 0)
                        {
                            continue;
                        }

                        if (MathFunctions.RandEvent(veg.SpawnProbability) &&
                            NoiseGenerator.Noise(topVoxel.Coordinate.X / veg.ClumpSize,
                                                 veg.NoiseOffset, topVoxel.Coordinate.Z / veg.ClumpSize) >= veg.ClumpThreshold)
                        {
                            topVoxel.RawSetType(VoxelLibrary.GetVoxelType(biomeData.SoilLayer.VoxelType));

                            var treeSize = MathFunctions.Rand() * veg.SizeVariance + veg.MeanSize;
                            var tree     = EntityFactory.CreateEntity <Plant>(veg.Name,
                                                                              topVoxel.WorldPosition + new Vector3(0.5f, 1.0f, 0.5f),
                                                                              Blackboard.Create("Scale", treeSize));

                            break;
                        }
                    }
                }
            }
        }