コード例 #1
0
        private static void BuildVoxelTopFaceGeometry(
            RawPrimitive Into,
            VoxelChunk Chunk,
            Cache Cache,
            BoxPrimitive Primitive,
            VoxelHandle V,
            BoxPrimitive.BoxTextureCoords UVs,
            int i)
        {
            var face  = (BoxFace)i;
            var delta = FaceDeltas[i];

            var faceVoxel = new VoxelHandle(Chunk.Manager, V.Coordinate + GlobalVoxelOffset.FromVector3(delta));

            if (!IsFaceVisible(V, faceVoxel, face))
            {
                return;
            }

            var faceDescriptor = Primitive.GetFace(face);
            int exploredVerts  = 0;
            var vertexColors   = new VertexColorInfo[4];
            var vertexTint     = new Color[4];

            // Find all verticies to use for geometry later, and for the fringe
            var vertexPositions = new Vector3[4];

            for (int faceVertex = 0; faceVertex < faceDescriptor.VertexCount; faceVertex++)
            {
                var vertex      = Primitive.Vertices[faceDescriptor.VertexOffset + faceVertex];
                var voxelVertex = Primitive.Deltas[faceDescriptor.VertexOffset + faceVertex];

                var rampOffset = Vector3.Zero;
                if (V.IsExplored && V.Type.CanRamp && ShouldRamp(voxelVertex, V.RampType))
                {
                    rampOffset = new Vector3(0, -V.Type.RampSize, 0);
                }

                var worldPosition = V.WorldPosition + vertex.Position + rampOffset;
                //worldPosition += VertexNoise.GetNoiseVectorFromRepeatingTexture(worldPosition);

                vertexPositions[faceVertex] = worldPosition;
            }

            if (V.IsExplored)
            {
                exploredVerts = 4;
            }
            else
            {
                for (int faceVertex = 0; faceVertex < faceDescriptor.VertexCount; ++faceVertex)
                {
                    var  voxelVertex         = Primitive.Deltas[faceDescriptor.VertexOffset + faceVertex];
                    var  cacheKey            = GetCacheKey(V, voxelVertex);
                    bool anyNeighborExplored = true;

                    if (!Cache.ExploredCache.TryGetValue(cacheKey, out anyNeighborExplored))
                    {
                        anyNeighborExplored = VoxelHelpers.EnumerateVertexNeighbors2D(V.Coordinate, voxelVertex)
                                              .Select(c => new VoxelHandle(V.Chunk.Manager, c))
                                              .Any(n => n.IsValid && n.IsExplored);
                        Cache.ExploredCache.Add(cacheKey, anyNeighborExplored);
                    }


                    if (anyNeighborExplored)
                    {
                        exploredVerts += 1;
                    }
                }
            }

            for (int faceVertex = 0; faceVertex < faceDescriptor.VertexCount; ++faceVertex)
            {
                var voxelVertex = Primitive.Deltas[faceDescriptor.VertexOffset + faceVertex];
                var cacheKey    = GetCacheKey(V, voxelVertex);

                VertexColorInfo vertexColor;
                if (!Cache.LightCache.TryGetValue(cacheKey, out vertexColor))
                {
                    vertexColor = CalculateVertexLight(V, voxelVertex, Chunk.Manager);
                    Cache.LightCache.Add(cacheKey, vertexColor);
                }

                vertexColors[faceVertex] = vertexColor;

                vertexTint[faceVertex] = new Color(1.0f, 1.0f, 1.0f, 1.0f);
                if (exploredVerts != 4)
                {
                    bool anyNeighborExplored = true;
                    if (!Cache.ExploredCache.TryGetValue(cacheKey, out anyNeighborExplored))
                    {
                        throw new InvalidProgramException("Failed cache lookup");
                    }

                    if (!anyNeighborExplored)
                    {
                        vertexTint[faceVertex] = new Color(0.0f, 0.0f, 0.0f, 1.0f);
                    }
                }

                vertexTint[faceVertex] = new Color(vertexTint[faceVertex].ToVector4() * V.Type.Tint.ToVector4());
            }

            if (exploredVerts != 0)
            {
                var baseUVs = UVs.Uvs[11]; // EW

                var baseUVBounds = new Vector4(baseUVs.X + 0.001f, baseUVs.Y + 0.001f, baseUVs.X + (1.0f / 16.0f) - 0.001f, baseUVs.Y + (1.0f / 16.0f) - 0.001f);

                // Draw central top tile.
                AddTopFaceGeometry(Into,
                                   Cache.AmbientValues, Primitive,
                                   faceDescriptor,
                                   vertexPositions,
                                   vertexColors,
                                   vertexTint,
                                   Vector2.One,
                                   baseUVs, baseUVBounds);

                if (V.GrassType != 0)
                {
                    BuildGrassFringeGeometry(Into, Chunk, Cache, Primitive, V, vertexColors,
                                             vertexTint, vertexPositions, faceDescriptor, exploredVerts);
                }
            }
            else
            {
                if (!Debugger.Switches.HideSliceTop)
                {
                    var indexOffset = Into.VertexCount;

                    for (int faceVertex = 0; faceVertex < faceDescriptor.VertexCount; faceVertex++)
                    {
                        Into.AddVertex(new ExtendedVertex(
                                           vertexPositions[faceVertex] + VertexNoise.GetNoiseVectorFromRepeatingTexture(vertexPositions[faceVertex]),
                                           new Color(0, 0, 0, 255),
                                           new Color(0, 0, 0, 255),
                                           new Vector2(12.5f / 16.0f, 0.5f / 16.0f),
                                           new Vector4(12.0f / 16.0f, 0.0f, 13.0f / 16.0f, 1.0f / 16.0f)));
                    }

                    for (int idx = faceDescriptor.IndexOffset; idx < faceDescriptor.IndexCount +
                         faceDescriptor.IndexOffset; idx++)
                    {
                        ushort offset  = Primitive.Indexes[idx];
                        ushort offset0 = Primitive.Indexes[faceDescriptor.IndexOffset];
                        Into.AddIndex((short)(indexOffset + offset - offset0));
                    }
                }
            }
        }
コード例 #2
0
        // This will loop through the whole world and draw out all liquid primatives that are handed to the function.
        public static void InitializePrimativesFromChunk(VoxelChunk chunk, List <LiquidPrimitive> primitivesToInit)
        {
            LiquidPrimitive[] lps = new LiquidPrimitive[(int)LiquidType.Count];

            if (!AddCaches(primitivesToInit, ref lps))
            {
                return;
            }

            LiquidType      curLiqType   = LiquidType.None;
            LiquidPrimitive curPrimitive = null;

            ExtendedVertex[] curVertices = null;
            ushort[]         curIndexes  = null;
            int[]            maxVertices = new int[lps.Length];
            int[]            maxIndexes  = new int[lps.Length];

            int  maxVertex  = 0;
            int  maxIndex   = 0;
            int  totalFaces = 6;
            bool fogOfWar   = GameSettings.Default.FogofWar;

            for (int y = 0; y < Math.Min(chunk.Manager.World.Master.MaxViewingLevel + 1, VoxelConstants.ChunkSizeY); y++)
            {
                if (chunk.Data.LiquidPresent[y] == 0)
                {
                    continue;
                }

                for (int x = 0; x < VoxelConstants.ChunkSizeX; x++)
                {
                    for (int z = 0; z < VoxelConstants.ChunkSizeZ; z++)
                    {
                        var voxel = new VoxelHandle(chunk, new LocalVoxelCoordinate(x, y, z));
                        if (fogOfWar && !voxel.IsExplored)
                        {
                            continue;
                        }

                        if (voxel.LiquidLevel > 0)
                        {
                            var liqType = voxel.LiquidType;

                            // We need to see if we changed types and should change the data we are writing to.
                            if (liqType != curLiqType)
                            {
                                LiquidPrimitive newPrimitive = lps[(int)liqType];
                                // We weren't passed a LiquidPrimitive object to work with for this type so we'll skip it.
                                if (newPrimitive == null)
                                {
                                    continue;
                                }

                                maxVertices[(int)curLiqType] = maxVertex;
                                maxIndexes[(int)curLiqType]  = maxIndex;

                                curVertices = newPrimitive.Vertices;
                                curIndexes  = newPrimitive.Indexes;

                                curLiqType   = liqType;
                                curPrimitive = newPrimitive;
                                maxVertex    = maxVertices[(int)liqType];
                                maxIndex     = maxIndexes[(int)liqType];
                            }

                            int facesToDraw = 0;
                            for (int i = 0; i < totalFaces; i++)
                            {
                                BoxFace face = (BoxFace)i;
                                // We won't draw the bottom face.  This might be needed down the line if we add transparent tiles like glass.
                                if (face == BoxFace.Bottom)
                                {
                                    continue;
                                }

                                var delta = faceDeltas[(int)face];

                                // Pull the current neighbor DestinationVoxel based on the face it would be touching.

                                var vox = VoxelHelpers.GetNeighbor(voxel, delta);

                                if (vox.IsValid)
                                {
                                    if (face == BoxFace.Top)
                                    {
                                        if (!(vox.LiquidLevel == 0 || y == (int)chunk.Manager.World.Master.MaxViewingLevel))
                                        {
                                            cache.drawFace[(int)face] = false;
                                            continue;
                                        }
                                    }
                                    else
                                    {
                                        if (vox.LiquidLevel != 0 || !vox.IsEmpty)
                                        {
                                            cache.drawFace[(int)face] = false;
                                            continue;
                                        }
                                    }
                                }
                                else
                                {
                                    cache.drawFace[(int)face] = false;
                                    continue;
                                }

                                cache.drawFace[(int)face] = true;
                                facesToDraw++;
                            }

                            // There's no faces to draw on this voxel.  Let's go to the next one.
                            if (facesToDraw == 0)
                            {
                                continue;
                            }

                            // Now we check to see if we need to resize the current Vertex array.
                            int vertexSizeIncrease = facesToDraw * 4;
                            int indexSizeIncrease  = facesToDraw * 6;

                            lock (curPrimitive.VertexLock)
                            {
                                // Check vertex array size
                                if (curVertices == null)
                                {
                                    curVertices           = new ExtendedVertex[256];
                                    curPrimitive.Vertices = curVertices;
                                }
                                else if (curVertices.Length <= maxVertex + vertexSizeIncrease)
                                {
                                    ExtendedVertex[] newVerts = new ExtendedVertex[MathFunctions.NearestPowerOf2(maxVertex + vertexSizeIncrease)];

                                    curVertices.CopyTo(newVerts, 0);
                                    curVertices           = newVerts;
                                    curPrimitive.Vertices = curVertices;
                                }

                                // Check index array size
                                if (curIndexes == null)
                                {
                                    curIndexes           = new ushort[256];
                                    curPrimitive.Indexes = curIndexes;
                                }
                                else if (curIndexes.Length <= maxIndex + indexSizeIncrease)
                                {
                                    ushort[] newIdxs = new ushort[MathFunctions.NearestPowerOf2(maxIndex + indexSizeIncrease)];

                                    curIndexes.CopyTo(newIdxs, 0);
                                    curIndexes           = newIdxs;
                                    curPrimitive.Indexes = curIndexes;
                                }
                            }

                            // Now we have a list of all the faces that will need to be drawn.  Let's draw  them.
                            CreateWaterFaces(voxel, chunk, x, y, z, curVertices, curIndexes, maxVertex, maxIndex);

                            // Finally increase the size so we can move on.
                            maxVertex += vertexSizeIncrease;
                            maxIndex  += indexSizeIncrease;
                        }
                    }
                }
            }

            // The last thing we need to do is make sure we set the current primative's maxVertices to the right value.
            maxVertices[(int)curLiqType] = maxVertex;
            maxIndexes[(int)curLiqType]  = maxIndex;

            // Now actually force the VertexBuffer to be recreated in each primative we worked with.
            for (int i = 0; i < lps.Length; i++)
            {
                LiquidPrimitive updatedPrimative = lps[i];
                if (updatedPrimative == null)
                {
                    continue;
                }

                maxVertex = maxVertices[i];
                maxIndex  = maxIndexes[i];

                if (maxVertex > 0)
                {
                    try
                    {
                        lock (updatedPrimative.VertexLock)
                        {
                            updatedPrimative.VertexCount  = maxVertex;
                            updatedPrimative.IndexCount   = maxIndex;
                            updatedPrimative.VertexBuffer = null;
                            updatedPrimative.IndexBuffer  = null;
                        }
                    }
                    catch (System.Threading.AbandonedMutexException e)
                    {
                        Console.Error.WriteLine(e.Message);
                    }
                }
                else
                {
                    try
                    {
                        lock (updatedPrimative.VertexLock)
                        {
                            updatedPrimative.VertexBuffer = null;
                            updatedPrimative.Vertices     = null;
                            updatedPrimative.IndexBuffer  = null;
                            updatedPrimative.Indexes      = null;
                            updatedPrimative.VertexCount  = 0;
                            updatedPrimative.IndexCount   = 0;
                        }
                    }
                    catch (System.Threading.AbandonedMutexException e)
                    {
                        Console.Error.WriteLine(e.Message);
                    }
                }
                updatedPrimative.IsBuilding = false;
            }

            cache.inUse = false;
            cache       = null;
        }
コード例 #3
0
ファイル: BuildVoxelOrder.cs プロジェクト: hhy5277/dwarfcorp
 public BuildVoxelOrder(BuildZoneOrder Order, Zone ToBuild, VoxelHandle Voxel)
 {
     this.Order   = Order;
     this.ToBuild = ToBuild;
     this.Voxel   = Voxel;
 }
コード例 #4
0
        private static void UpdateChunk(VoxelChunk chunk)
        {
            var addGrassToThese = new List <Tuple <VoxelHandle, byte> >();

            for (var y = 0; y < VoxelConstants.ChunkSizeY; ++y)
            {
                // Skip empty slices.
                if (chunk.Data.VoxelsPresentInSlice[y] == 0)
                {
                    continue;
                }

                for (var x = 0; x < VoxelConstants.ChunkSizeX; ++x)
                {
                    for (var z = 0; z < VoxelConstants.ChunkSizeZ; ++z)
                    {
                        var voxel = new VoxelHandle(chunk, new LocalVoxelCoordinate(x, y, z));

                        // Allow grass to decay
                        if (voxel.GrassType != 0)
                        {
                            var decal = GrassLibrary.GetGrassType(voxel.GrassType);

                            if (decal.NeedsSunlight && voxel.SunColor < 255)
                            {
                                voxel.GrassType = 0;
                            }
                            else if (decal.Decay)
                            {
                                voxel.GrassDecay -= 1;
                                if (voxel.GrassDecay == 0)
                                {
                                    var newDecal = GrassLibrary.GetGrassType(decal.BecomeWhenDecays);
                                    if (newDecal != null)
                                    {
                                        voxel.GrassType = newDecal.ID;
                                    }
                                    else
                                    {
                                        voxel.GrassType = 0;
                                    }
                                }
                            }
                        }
                        else if (voxel.Type.GrassSpreadsHere)
                        {
                            // Spread grass onto this tile - but only from the same biome.

                            var biome = Overworld.GetBiomeAt(voxel.Coordinate.ToVector3());

                            var grassyNeighbors = VoxelHelpers.EnumerateManhattanNeighbors2D(voxel.Coordinate)
                                                  .Select(c => new VoxelHandle(voxel.Chunk.Manager.ChunkData, c))
                                                  .Where(v => v.IsValid && v.GrassType != 0)
                                                  .Where(v => biome == Overworld.GetBiomeAt(v.Coordinate.ToVector3()))
                                                  .ToList();

                            if (grassyNeighbors.Count > 0)
                            {
                                if (MathFunctions.RandEvent(0.1f))
                                {
                                    addGrassToThese.Add(Tuple.Create(voxel, grassyNeighbors[MathFunctions.RandInt(0, grassyNeighbors.Count)].GrassType));
                                }
                            }
                        }
                    }
                }
            }

            foreach (var v in addGrassToThese)
            {
                var l         = v.Item1;
                var grassType = GrassLibrary.GetGrassType(v.Item2);
                if (grassType.NeedsSunlight && l.SunColor != 255)
                {
                    continue;
                }
                l.GrassType = v.Item2;
            }
        }
コード例 #5
0
ファイル: CreatureMovement.cs プロジェクト: hhy5277/dwarfcorp
        // Inverts GetMoveActions. So, returns the list of move actions whose target is the current voxel.
        // Very, very slow.
        public IEnumerable <MoveAction> GetInverseMoveActions(MoveState currentstate, List <GameComponent> teleportObjects)
        {
            if (Parent == null)
            {
                yield break;
            }

            if (Creature == null)
            {
                yield break;
            }

            var current = currentstate.Voxel;

            if (Can(MoveType.Teleport))
            {
                foreach (var obj in teleportObjects)
                {
                    if ((obj.Position - current.WorldPosition).LengthSquared() > 2)
                    {
                        continue;
                    }

                    for (int dx = -TeleportDistance; dx <= TeleportDistance; dx++)
                    {
                        for (int dz = -TeleportDistance; dz <= TeleportDistance; dz++)
                        {
                            for (int dy = -TeleportDistance; dy <= TeleportDistance; dy++)
                            {
                                if (dx * dx + dy * dy + dz * dz > TeleportDistanceSquared)
                                {
                                    continue;
                                }
                                VoxelHandle teleportNeighbor = new VoxelHandle(Parent.World.ChunkManager, current.Coordinate + new GlobalVoxelOffset(dx, dy, dz));
                                var         adjacent         = VoxelHelpers.GetNeighbor(teleportNeighbor, new GlobalVoxelOffset(0, -1, 0));
                                if (teleportNeighbor.IsValid && teleportNeighbor.IsEmpty && adjacent.IsValid && adjacent.IsEmpty)
                                {
                                    yield return(new MoveAction()
                                    {
                                        InteractObject = obj,
                                        Diff = new Vector3(dx, dx, dz),
                                        SourceVoxel = teleportNeighbor,
                                        DestinationState = currentstate,
                                        MoveType = MoveType.Teleport,
                                        CostMultiplier = 1.0f
                                    });
                                }
                            }
                        }
                    }
                }
            }

            var storage = new MoveActionTempStorage();

            foreach (var v in VoxelHelpers.EnumerateCube(current.Coordinate)
                     .Select(n => new VoxelHandle(current.Chunk.Manager, n))
                     .Where(h => h.IsValid))
            {
                foreach (var a in GetMoveActions(new MoveState()
                {
                    Voxel = v
                }, teleportObjects, storage).Where(a => a.DestinationState == currentstate))
                {
                    yield return(a);
                }

                if (!Can(MoveType.RideVehicle))
                {
                    continue;
                }

                // Now that dwarfs can ride vehicles, the inverse of the move actions becomes extremely complicated. We must now
                // iterate through all rails intersecting every neighbor and see if we can find a connection from that rail to this one.
                // Further, we must iterate through the entire rail network and enumerate all possible directions in and out of that rail.
                // Yay!

                // Actually - why not just not bother with rails when inverse pathing, since it should only be invoked when forward pathing fails anyway?
                // Also NOT hacking in inverse elevators!

                /*
                 * var bodies = new HashSet<GameComponent>();
                 * OctTree.EnumerateItems(v.GetBoundingBox(), bodies);
                 *
                 * var rails = bodies.OfType<Rail.RailEntity>().Where(r => r.Active);
                 * foreach (var rail in rails)
                 * {
                 *  if (rail.GetContainingVoxel() != v)
                 *      continue;
                 *
                 *  foreach (var neighborRail in rail.NeighborRails.Select(neighbor => Creature.Manager.FindComponent(neighbor.NeighborID) as Rail.RailEntity))
                 *  {
                 *      var actions = GetMoveActions(new MoveState()
                 *      {
                 *          Voxel = v,
                 *          VehicleType = VehicleTypes.Rail,
                 *          Rail = rail,
                 *          PrevRail = neighborRail
                 *      }, OctTree, teleportObjects, storage);
                 *      foreach (var a in actions.Where(a => a.DestinationState == currentstate))
                 *      {
                 *          yield return a;
                 *      }
                 *  }
                 *
                 *  foreach (var a in GetMoveActions(new MoveState() { Voxel = v, VehicleType = VehicleTypes.Rail, Rail = rail, PrevRail = null }, OctTree, teleportObjects, storage).Where(a => a.DestinationState == currentstate))
                 *      yield return a;
                 * }
                 */
            }
        }
コード例 #6
0
ファイル: PlanAct.cs プロジェクト: polytronicgr/dwarfcorp
 public void SetTarget(VoxelHandle target)
 {
     Agent.Blackboard.SetData(TargetName, target);
 }
コード例 #7
0
        private static void UpdateChunk(VoxelChunk chunk)
        {
            var addGrassToThese = new List <Tuple <VoxelHandle, byte> >();

            for (var y = 0; y < VoxelConstants.ChunkSizeY; ++y)
            {
                // Skip empty slices.
                if (chunk.Data.VoxelsPresentInSlice[y] == 0)
                {
                    continue;
                }

                for (var x = 0; x < VoxelConstants.ChunkSizeX; ++x)
                {
                    for (var z = 0; z < VoxelConstants.ChunkSizeZ; ++z)
                    {
                        var voxel = VoxelHandle.UnsafeCreateLocalHandle(chunk, new LocalVoxelCoordinate(x, y, z));

                        // Allow grass to decay
                        if (voxel.GrassType != 0)
                        {
                            var grass = Library.GetGrassType(voxel.GrassType);

                            if (grass.NeedsSunlight && !voxel.Sunlight)
                            {
                                voxel.GrassType = 0;
                            }
                            else if (grass.Decay)
                            {
                                if (voxel.GrassDecay == 0)
                                {
                                    var newDecal = Library.GetGrassType(grass.BecomeWhenDecays);
                                    if (newDecal != null)
                                    {
                                        voxel.GrassType = newDecal.ID;
                                    }
                                    else
                                    {
                                        voxel.GrassType = 0;
                                    }
                                }
                                else
                                {
                                    voxel.GrassDecay -= 1;
                                }
                            }
                        }
//#if false
                        else if (voxel.Type.GrassSpreadsHere)
                        {
                            // Spread grass onto this tile - but only from the same biome.

                            // Don't spread if there's an entity here.
                            var entityPresent = chunk.Manager.World.EnumerateIntersectingObjects(
                                new BoundingBox(voxel.WorldPosition + new Vector3(0.1f, 1.1f, 0.1f), voxel.WorldPosition + new Vector3(0.9f, 1.9f, 0.9f)),
                                CollisionType.Static).Any();
                            if (entityPresent)
                            {
                                continue;
                            }

                            var biome = chunk.Manager.World.Overworld.Map.GetBiomeAt(voxel.Coordinate.ToVector3(), chunk.Manager.World.Overworld.InstanceSettings.Origin);

                            var grassyNeighbors = VoxelHelpers.EnumerateManhattanNeighbors2D(voxel.Coordinate)
                                                  .Select(c => new VoxelHandle(voxel.Chunk.Manager, c))
                                                  .Where(v => v.IsValid && v.GrassType != 0)
                                                  .Where(v => Library.GetGrassType(v.GrassType).Spreads)
                                                  .Where(v => biome == chunk.Manager.World.Overworld.Map.GetBiomeAt(v.Coordinate.ToVector3(), chunk.Manager.World.Overworld.InstanceSettings.Origin))
                                                  .ToList();

                            if (grassyNeighbors.Count > 0)
                            {
                                if (MathFunctions.RandEvent(0.1f))
                                {
                                    addGrassToThese.Add(Tuple.Create(voxel, grassyNeighbors[MathFunctions.RandInt(0, grassyNeighbors.Count)].GrassType));
                                }
                            }
                        }
//#endif
                    }
                }
            }

            foreach (var v in addGrassToThese)
            {
                var l         = v.Item1;
                var grassType = Library.GetGrassType(v.Item2);
                if (grassType.NeedsSunlight && !l.Sunlight)
                {
                    continue;
                }
                l.GrassType = v.Item2;
            }
        }
コード例 #8
0
        private void DiscreteUpdate(ChunkManager ChunkManager, VoxelChunk chunk)
        {
            for (var y = 0; y < VoxelConstants.ChunkSizeY; ++y)
            {
                // Apply 'liquid present' tracking in voxel data to skip entire slices.
                if (chunk.Data.LiquidPresent[y] == 0)
                {
                    continue;
                }

                var layerOrder = SlicePermutations[MathFunctions.RandInt(0, SlicePermutations.Length)];

                for (var i = 0; i < layerOrder.Length; ++i)
                {
                    var x            = layerOrder[i] % VoxelConstants.ChunkSizeX;
                    var z            = (layerOrder[i] >> VoxelConstants.XDivShift) % VoxelConstants.ChunkSizeZ;
                    var currentVoxel = VoxelHandle.UnsafeCreateLocalHandle(chunk, new LocalVoxelCoordinate(x, y, z));

                    if (currentVoxel.TypeID != 0)
                    {
                        continue;
                    }

                    if (currentVoxel.LiquidType == LiquidType.None || currentVoxel.LiquidLevel < 1)
                    {
                        continue;
                    }

                    // Evaporate.
                    if (currentVoxel.LiquidLevel <= EvaporationLevel && MathFunctions.RandEvent(0.01f))
                    {
                        if (currentVoxel.LiquidType == LiquidType.Lava && Library.GetVoxelType("Stone").HasValue(out VoxelType stone))
                        {
                            currentVoxel.Type = stone;
                        }

                        NeedsMinimapUpdate = true;
                        currentVoxel.QuickSetLiquid(LiquidType.None, 0);
                        continue;
                    }

                    var voxBelow = ChunkManager.CreateVoxelHandle(new GlobalVoxelCoordinate(currentVoxel.Coordinate.X, currentVoxel.Coordinate.Y - 1, currentVoxel.Coordinate.Z));

                    if (voxBelow.IsValid && voxBelow.IsEmpty)
                    {
                        // Fall into the voxel below.

                        // Special case: No liquid below, just drop down.
                        if (voxBelow.LiquidType == LiquidType.None)
                        {
                            NeedsMinimapUpdate = true;
                            CreateSplash(currentVoxel.Coordinate.ToVector3(), currentVoxel.LiquidType);
                            voxBelow.QuickSetLiquid(currentVoxel.LiquidType, currentVoxel.LiquidLevel);
                            currentVoxel.QuickSetLiquid(LiquidType.None, 0);
                            continue;
                        }

                        var belowType      = voxBelow.LiquidType;
                        var aboveType      = currentVoxel.LiquidType;
                        var spaceLeftBelow = maxWaterLevel - voxBelow.LiquidLevel;

                        if (spaceLeftBelow >= currentVoxel.LiquidLevel)
                        {
                            NeedsMinimapUpdate = true;
                            CreateSplash(currentVoxel.Coordinate.ToVector3(), aboveType);
                            voxBelow.LiquidLevel += currentVoxel.LiquidLevel;
                            currentVoxel.QuickSetLiquid(LiquidType.None, 0);
                            HandleLiquidInteraction(voxBelow, aboveType, belowType);
                            continue;
                        }

                        if (spaceLeftBelow > 0)
                        {
                            NeedsMinimapUpdate = true;
                            CreateSplash(currentVoxel.Coordinate.ToVector3(), aboveType);
                            currentVoxel.LiquidLevel = (byte)(currentVoxel.LiquidLevel - maxWaterLevel + voxBelow.LiquidLevel);
                            voxBelow.LiquidLevel     = maxWaterLevel;
                            HandleLiquidInteraction(voxBelow, aboveType, belowType);
                            continue;
                        }
                    }
                    else if (voxBelow.IsValid && currentVoxel.LiquidType == LiquidType.Lava && !voxBelow.IsEmpty && voxBelow.GrassType > 0)
                    {
                        voxBelow.GrassType = 0;
                    }

                    if (currentVoxel.LiquidLevel <= 1)
                    {
                        continue;
                    }

                    // Nothing left to do but spread.

                    RollArray(NeighborPermutations[MathFunctions.RandInt(0, NeighborPermutations.Length)], NeighborScratch, MathFunctions.RandInt(0, 4));

                    for (var n = 0; n < NeighborScratch.Length; ++n)
                    {
                        var neighborOffset = VoxelHelpers.ManhattanNeighbors2D[NeighborScratch[n]];
                        var neighborVoxel  = new VoxelHandle(Chunks, currentVoxel.Coordinate + neighborOffset);

                        if (neighborVoxel.IsValid && neighborVoxel.IsEmpty)
                        {
                            if (neighborVoxel.LiquidLevel < currentVoxel.LiquidLevel)
                            {
                                NeedsMinimapUpdate = true;
                                var amountToMove = (int)(currentVoxel.LiquidLevel * GetSpreadRate(currentVoxel.LiquidType));
                                if (neighborVoxel.LiquidLevel + amountToMove > maxWaterLevel)
                                {
                                    amountToMove = maxWaterLevel - neighborVoxel.LiquidLevel;
                                }

                                if (amountToMove > 2)
                                {
                                    CreateSplash(neighborVoxel.Coordinate.ToVector3(), currentVoxel.LiquidType);
                                }

                                var newWater = currentVoxel.LiquidLevel - amountToMove;

                                var sourceType = currentVoxel.LiquidType;
                                var destType   = neighborVoxel.LiquidType;
                                currentVoxel.QuickSetLiquid(newWater == 0 ? LiquidType.None : sourceType, (byte)newWater);
                                neighborVoxel.QuickSetLiquid(destType == LiquidType.None ? sourceType : destType, (byte)(neighborVoxel.LiquidLevel + amountToMove));
                                HandleLiquidInteraction(neighborVoxel, sourceType, destType);
                                break;
                            }
                        }
                    }
                }
            }
        }
コード例 #9
0
        public void GenerateCaves(VoxelChunk chunk, WorldManager world)
        {
            Vector3   origin = chunk.Origin;
            BiomeData biome  = BiomeLibrary.GetBiome("Cave");

            for (int x = 0; x < VoxelConstants.ChunkSizeX; x++)
            {
                for (int z = 0; z < VoxelConstants.ChunkSizeZ; z++)
                {
                    var topVoxel = VoxelHelpers.FindFirstVoxelBelow(new VoxelHandle(
                                                                        chunk, new LocalVoxelCoordinate(x, VoxelConstants.ChunkSizeY - 1, z)));

                    for (int i = 0; i < CaveLevels.Count; i++)
                    {
                        int y = CaveLevels[i];
                        if (y <= 0 || y >= topVoxel.Coordinate.Y)
                        {
                            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))
                        {
                            continue;
                        }

                        bool invalidCave = false;
                        for (int dy = 0; dy < caveHeight; dy++)
                        {
                            if (y - dy <= 0)
                            {
                                continue;
                            }

                            var voxel = new VoxelHandle(chunk, new LocalVoxelCoordinate(x, y - dy, z));

                            foreach (var coord in VoxelHelpers.EnumerateAllNeighbors(voxel.Coordinate))
                            {
                                VoxelHandle v = new VoxelHandle(Manager.ChunkData, coord);
                                if (v.IsValid && (v.WaterCell.WaterLevel > 0 || v.SunColor > 0))
                                {
                                    invalidCave = true;
                                    break;
                                }
                            }

                            if (!invalidCave)
                            {
                                voxel.RawSetType(VoxelLibrary.emptyType);
                            }
                            else
                            {
                                break;
                            }
                        }

                        if (!invalidCave && caveNoise > CaveSize * 1.8f && y - caveHeight > 0)
                        {
                            GenerateCaveVegetation(chunk, x, y, z, caveHeight, biome, vec, world, NoiseGenerator);
                            GenerateCaveFauna(chunk, world, biome, y - caveHeight, x, z);
                        }
                    }
                }
            }

            /*
             * // Second pass sets the caves to empty as needed
             * for (int x = 0; x < VoxelConstants.ChunkSizeX; x++)
             * {
             *  for (int y = 0; y < VoxelConstants.ChunkSizeY; y++)
             *  {
             *      for (int z = 0; z < VoxelConstants.ChunkSizeZ; z++)
             *      {
             *          VoxelHandle handle = new VoxelHandle(chunk, new LocalVoxelCoordinate(x, y, z));
             *          if (handle.Type == magicCube)
             *          {
             *              handle.RawSetType(VoxelLibrary.emptyType);
             *          }
             *      }
             *  }
             * }
             */
        }
コード例 #10
0
 public BuildVoxelOrder GetBuildDesignation(VoxelHandle v)
 {
     return(BuildDesignations.SelectMany(room => room.VoxelOrders).FirstOrDefault(buildDesignation => buildDesignation.Voxel == v));
 }
コード例 #11
0
 public bool IsInStockpile(VoxelHandle v)
 {
     return(Stockpiles.Any(s => s.ContainsVoxel(v)));
 }
コード例 #12
0
 public bool IsBuildDesignation(VoxelHandle v)
 {
     return(BuildDesignations.SelectMany(room => room.VoxelOrders).Any(buildDesignation => buildDesignation.Voxel == v));
 }
コード例 #13
0
 public bool IsInRoom(VoxelHandle v)
 {
     return(DesignatedRooms.Any(r => r.ContainsVoxel(v)) || Faction.IsInStockpile(v));
 }
コード例 #14
0
        private static void BuildGrassFringeGeometry(
            RawPrimitive Into,
            VoxelChunk Chunk,
            Cache Cache,
            BoxPrimitive Primitive,
            VoxelHandle V,
            VertexColorInfo[] VertexColors,
            Color[] VertexTint,
            Vector3[] VertexPositions,
            BoxPrimitive.FaceDescriptor Face,
            int ExploredVerts)
        {
            if (V.GrassType == 0)
            {
                return;
            }

            var decalType = Library.GetGrassType(V.GrassType);

            AddGrassGeometry(Into, Cache.AmbientValues, Primitive, V, Face, ExploredVerts, VertexPositions, VertexColors, VertexTint, decalType);

            // Draw fringe
            if (decalType.FringeTransitionUVs == null)
            {
                return;
            }

            for (var s = 0; s < 4; ++s)
            {
                var neighborCoord = V.Coordinate + VoxelHelpers.ManhattanNeighbors2D[s];
                var neighbor      = new VoxelHandle(Chunk.Manager, neighborCoord);

                if (!neighbor.IsValid)
                {
                    continue;
                }

                var aboveNeighbor = new VoxelHandle(Chunk.Manager, neighborCoord + new GlobalVoxelOffset(0, 1, 0));

                if (!aboveNeighbor.IsValid || aboveNeighbor.IsEmpty)
                {
                    // Draw horizontal fringe.
                    if (!neighbor.IsEmpty)
                    {
                        if (neighbor.GrassType != 0 &&
                            Library.GetGrassType(neighbor.GrassType).FringePrecedence >= decalType.FringePrecedence)
                        {
                            continue;
                        }
                    }

                    // Twizzle vertex positions.
                    var newPositions = new Vector3[4];
                    newPositions[FringeIndicies[s, 0]] = VertexPositions[FringeIndicies[s, 4]];
                    newPositions[FringeIndicies[s, 1]] = VertexPositions[FringeIndicies[s, 4]]
                                                         + (VoxelHelpers.ManhattanNeighbors2D[s].AsVector3() * 0.5f);
                    newPositions[FringeIndicies[s, 2]] = VertexPositions[FringeIndicies[s, 5]]
                                                         + (VoxelHelpers.ManhattanNeighbors2D[s].AsVector3() * 0.5f);
                    newPositions[FringeIndicies[s, 3]] = VertexPositions[FringeIndicies[s, 5]];

                    var newColors = new VertexColorInfo[4];
                    newColors[FringeIndicies[s, 0]] = VertexColors[FringeIndicies[s, 4]];
                    newColors[FringeIndicies[s, 1]] = VertexColors[FringeIndicies[s, 4]];
                    newColors[FringeIndicies[s, 2]] = VertexColors[FringeIndicies[s, 5]];
                    newColors[FringeIndicies[s, 3]] = VertexColors[FringeIndicies[s, 5]];

                    var slopeTweak = new Vector3(0.0f, 0.0f, 0.0f);
                    if (neighbor.IsEmpty)
                    {
                        slopeTweak.Y = -0.5f;
                    }
                    else
                    {
                        slopeTweak.Y = 0.125f;
                    }

                    newPositions[FringeIndicies[s, 1]] += slopeTweak;
                    newPositions[FringeIndicies[s, 2]] += slopeTweak;

                    var newTints = new Color[4];
                    newTints[FringeIndicies[s, 0]] = VertexTint[FringeIndicies[s, 4]];
                    newTints[FringeIndicies[s, 1]] = VertexTint[FringeIndicies[s, 4]];
                    newTints[FringeIndicies[s, 2]] = VertexTint[FringeIndicies[s, 5]];
                    newTints[FringeIndicies[s, 3]] = VertexTint[FringeIndicies[s, 5]];

                    AddTopFaceGeometry(Into,
                                       Cache.AmbientValues, Primitive,
                                       Face,
                                       newPositions,
                                       newColors,
                                       newTints,
                                       SideFringeUVScales[s],
                                       decalType.FringeTransitionUVs[s].UV,
                                       decalType.FringeTransitionUVs[s].Bounds);
                }
                else
                {
                    // Draw vertical fringe!

                    var newPositions = new Vector3[4];
                    newPositions[FringeIndicies[s, 0]] = VertexPositions[FringeIndicies[s, 4]];
                    newPositions[FringeIndicies[s, 1]] = VertexPositions[FringeIndicies[s, 4]]
                                                         + new Vector3(0.0f, 0.5f, 0.0f)
                                                         + (VoxelHelpers.ManhattanNeighbors2D[s].AsVector3() * -0.05f);
                    newPositions[FringeIndicies[s, 2]] = VertexPositions[FringeIndicies[s, 5]]
                                                         + new Vector3(0.0f, 0.5f, 0.0f)
                                                         + (VoxelHelpers.ManhattanNeighbors2D[s].AsVector3() * -0.05f);
                    newPositions[FringeIndicies[s, 3]] = VertexPositions[FringeIndicies[s, 5]];

                    var newColors = new VertexColorInfo[4];
                    newColors[FringeIndicies[s, 0]] = VertexColors[FringeIndicies[s, 4]];
                    newColors[FringeIndicies[s, 1]] = VertexColors[FringeIndicies[s, 4]];
                    newColors[FringeIndicies[s, 2]] = VertexColors[FringeIndicies[s, 5]];
                    newColors[FringeIndicies[s, 3]] = VertexColors[FringeIndicies[s, 5]];

                    var newTints = new Color[4];
                    newTints[FringeIndicies[s, 0]] = VertexTint[FringeIndicies[s, 4]];
                    newTints[FringeIndicies[s, 1]] = VertexTint[FringeIndicies[s, 4]];
                    newTints[FringeIndicies[s, 2]] = VertexTint[FringeIndicies[s, 5]];
                    newTints[FringeIndicies[s, 3]] = VertexTint[FringeIndicies[s, 5]];

                    AddTopFaceGeometry(Into,
                                       Cache.AmbientValues, Primitive,
                                       Face,
                                       newPositions,
                                       newColors,
                                       newTints,
                                       SideFringeUVScales[s],
                                       decalType.FringeTransitionUVs[s].UV,
                                       decalType.FringeTransitionUVs[s].Bounds);
                }
            }

            for (var s = 0; s < 4; ++s)
            {
                var neighborCoord = V.Coordinate + VoxelHelpers.DiagonalNeighbors2D[s];
                var handle        = new VoxelHandle(Chunk.Manager, neighborCoord);

                if (handle.IsValid)
                {
                    if (!handle.IsEmpty)
                    {
                        if (handle.GrassType != 0 &&
                            Library.GetGrassType(handle.GrassType).FringePrecedence >= decalType.FringePrecedence)
                        {
                            continue;
                        }
                    }

                    var manhattanA = new VoxelHandle(Chunk.Manager, V.Coordinate + VoxelHelpers.ManhattanNeighbors2D[s]);
                    if (!manhattanA.IsValid || (manhattanA.GrassType == V.GrassType))
                    {
                        continue;
                    }

                    manhattanA = new VoxelHandle(Chunk.Manager, V.Coordinate + VoxelHelpers.ManhattanNeighbors2D[FringeIndicies[4 + s, 5]]);
                    if (!manhattanA.IsValid || (manhattanA.GrassType == V.GrassType))
                    {
                        continue;
                    }

                    // Twizzle vertex positions.
                    var newPositions = new Vector3[4];
                    var pivot        = VertexPositions[FringeIndicies[4 + s, 4]];
                    var nDelta       = VoxelHelpers.DiagonalNeighbors2D[s].AsVector3();

                    newPositions[FringeIndicies[4 + s, 0]] = pivot;
                    newPositions[FringeIndicies[4 + s, 1]] = pivot + new Vector3(nDelta.X * 0.5f, 0, 0);
                    newPositions[FringeIndicies[4 + s, 2]] = pivot + new Vector3(nDelta.X * 0.5f, 0, nDelta.Z * 0.5f);
                    newPositions[FringeIndicies[4 + s, 3]] = pivot + new Vector3(0, 0, nDelta.Z * 0.5f);

                    var slopeTweak = new Vector3(0.0f, 0.0f, 0.0f);
                    if (handle.IsEmpty)
                    {
                        slopeTweak.Y = -0.5f;
                    }
                    else
                    {
                        slopeTweak.Y = 0.125f;
                    }

                    newPositions[FringeIndicies[4 + s, 1]] += slopeTweak;
                    newPositions[FringeIndicies[4 + s, 2]] += slopeTweak;
                    newPositions[FringeIndicies[4 + s, 3]] += slopeTweak;

                    var newColors = new VertexColorInfo[4];
                    newColors[FringeIndicies[4 + s, 0]] = VertexColors[FringeIndicies[4 + s, 4]];
                    newColors[FringeIndicies[4 + s, 1]] = VertexColors[FringeIndicies[4 + s, 4]];
                    newColors[FringeIndicies[4 + s, 2]] = VertexColors[FringeIndicies[4 + s, 4]];
                    newColors[FringeIndicies[4 + s, 3]] = VertexColors[FringeIndicies[4 + s, 4]];

                    var newTints = new Color[4];
                    newTints[FringeIndicies[4 + s, 0]] = VertexTint[FringeIndicies[4 + s, 4]];
                    newTints[FringeIndicies[4 + s, 1]] = VertexTint[FringeIndicies[4 + s, 4]];
                    newTints[FringeIndicies[4 + s, 2]] = VertexTint[FringeIndicies[4 + s, 4]];
                    newTints[FringeIndicies[4 + s, 3]] = VertexTint[FringeIndicies[4 + s, 4]];

                    AddTopFaceGeometry(Into,
                                       Cache.AmbientValues, Primitive,
                                       Face,
                                       newPositions,
                                       newColors,
                                       newTints,
                                       new Vector2(0.5f, 0.5f),
                                       decalType.FringeTransitionUVs[4 + s].UV,
                                       decalType.FringeTransitionUVs[4 + s].Bounds);
                }
            }
        }
コード例 #15
0
        public void Update(DwarfTime gameTime, ChunkManager chunks, Camera camera)
        {
            var body = Parent as Body;

            System.Diagnostics.Debug.Assert(body != null);

            Vector3 targetVelocity = TargetPosition - body.GlobalTransform.Translation;

            if (targetVelocity.LengthSquared() > 0.0001f)
            {
                targetVelocity.Normalize();
                targetVelocity *= MaxVelocity;
            }

            Matrix m = body.LocalTransform;

            m.Translation      += targetVelocity * (float)gameTime.ElapsedGameTime.TotalSeconds;
            body.LocalTransform = m;

            body.HasMoved = true;

            switch (State)
            {
            case BalloonState.DeliveringGoods:
            {
                var voxel = new VoxelHandle(chunks.ChunkData,
                                            GlobalVoxelCoordinate.FromVector3(body.GlobalTransform.Translation));

                if (voxel.IsValid)
                {
                    var surfaceVoxel = VoxelHelpers.FindFirstVoxelBelow(voxel);
                    var height       = surfaceVoxel.Coordinate.Y + 1;

                    TargetPosition = new Vector3(body.GlobalTransform.Translation.X, height + 5, body.GlobalTransform.Translation.Z);

                    Vector3 diff = body.GlobalTransform.Translation - TargetPosition;

                    if (diff.LengthSquared() < 2)
                    {
                        State = BalloonState.Waiting;
                    }
                }
                else
                {
                    State = BalloonState.Leaving;
                }
            }
            break;

            case BalloonState.Leaving:
                TargetPosition = Vector3.UnitY * 100 + body.GlobalTransform.Translation;

                if (body.GlobalTransform.Translation.Y > 65)
                {
                    Die();
                }

                break;

            case BalloonState.Waiting:
                TargetPosition = body.GlobalTransform.Translation;

                if (!shipmentGiven)
                {
                    shipmentGiven = true;
                }
                else
                {
                    State = BalloonState.Leaving;
                }


                break;
            }
        }
コード例 #16
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));

            wayUnder.RawSetGrass(GrassLibrary.GetGrassType(biome.GrassDecal).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;

                    EntityFactory.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, world.ChunkManager, vUnder)
                            {
                                EntityToSpawn  = veg.Name,
                                SpawnLocation  = vUnder.WorldPosition + new Vector3(0.5f, 1.0f, 0.5f),
                                BlackboardData = Blackboard.Create("Scale", treeSize)
                            });
                        }
                    });
                }
            }

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

                FaunaData animal1 = animal;
                EntityFactory.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,
                                                                          world.ChunkManager, new VoxelHandle(chunk, wayUnder.Coordinate.GetLocalVoxelCoordinate()))
                        {
                            EntityToSpawn = animal1.Name,
                            SpawnLocation = wayUnder.WorldPosition + Vector3.Up * 1.5f
                        });
                    }
                });
                break;
            }
        }
コード例 #17
0
        public void Update(ParticleManager manager, DwarfTime gameTime, ChunkManager chunks, Camera camera)
        {
            ParticleEmitter._camera = camera;

            List <Particle> toRemove = new List <Particle>();

            TriggerTimer.Update(gameTime);
            if (TriggerTimer.HasTriggered && Data.ParticlesPerFrame > 0)
            {
                Trigger(Data.ParticlesPerFrame, Vector3.Zero, new Color(255, 255, 0));
            }


            bool particlePhysics = GameSettings.Default.ParticlePhysics;

            foreach (Particle p in Particles)
            {
                float vel = p.Velocity.LengthSquared();
                if (Data.EmitsLight && p.Scale > 0.1f)
                {
                    DynamicLight.TempLights.Add(new DynamicLight(10.0f, 255.0f, false)
                    {
                        Position = p.Position
                    });
                }
                p.Position += p.Velocity * (float)gameTime.ElapsedGameTime.TotalSeconds;

                if (Data.RotatesWithVelocity)
                {
                    Vector3 cameraVel   = camera.Project(p.Velocity + camera.Position);
                    float   projectionX = cameraVel.X;
                    float   projectionY = cameraVel.Y;

                    p.Angle = (float)Math.Atan2(projectionY, projectionX);
                }
                else
                {
                    p.Angle += (float)(p.AngularVelocity * gameTime.ElapsedGameTime.TotalSeconds);
                }
                if (!Data.Sleeps || vel > 0.01f)
                {
                    p.Velocity += Data.ConstantAccel * (float)gameTime.ElapsedGameTime.TotalSeconds;
                }
                p.Velocity        *= Data.LinearDamping;
                p.AngularVelocity *= Data.AngularDamping;


                if (!Data.UseManualControl)
                {
                    p.LifeRemaining -= Data.ParticleDecay * (float)gameTime.ElapsedGameTime.TotalSeconds;
                }
                else if (p.TimeAlive > 60)
                {
                    p.LifeRemaining = 0;
                }

                p.Scale += Data.GrowthSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds;

                p.Scale = Math.Max(p.Scale, 0.0f);

                var v = new VoxelHandle(chunks.ChunkData,
                                        GlobalVoxelCoordinate.FromVector3(p.Position));

                if (Data.HasLighting)
                {
                    if (v.IsValid)
                    {
                        p.LightRamp = new Color(v.Sunlight ? 255 : 0, 255, 0);
                    }
                }
                else
                {
                    p.LightRamp = new Color(255, 255, 0);
                }

                if (Data.CollidesWorld && particlePhysics && vel > 0.2f)
                {
                    if (v.IsValid && !v.IsEmpty)
                    {
                        BoundingBox     b       = new BoundingBox(p.Position - Vector3.One * p.Scale * 0.5f, p.Position + Vector3.One * p.Scale * 0.5f);
                        BoundingBox     vBox    = v.GetBoundingBox();
                        Physics.Contact contact = new Physics.Contact();
                        if (Physics.TestStaticAABBAABB(b, vBox, ref contact))
                        {
                            p.Position += contact.NEnter * contact.Penetration;
                            Vector3 newVelocity = Vector3.Reflect(p.Velocity, -contact.NEnter);
                            p.Velocity         = newVelocity * Data.Damping;
                            p.AngularVelocity *= 0.5f;
                            if (Data.Sleeps)
                            {
                                p.Velocity        = Vector3.Zero;
                                p.AngularVelocity = 0.0f;
                                vel = 0.0f;
                            }
                            if (!String.IsNullOrEmpty(Data.SpatterType))
                            {
                                var above = VoxelHelpers.GetVoxelAbove(v);
                                if (!above.IsValid || above.IsEmpty)
                                {
                                    float x = MathFunctions.Clamp(p.Position.X, vBox.Min.X + 0.1f, vBox.Max.X - 0.1f);
                                    float z = MathFunctions.Clamp(p.Position.Z, vBox.Min.Z + 0.1f, vBox.Max.Z - 0.1f);
                                    manager.Create(Data.SpatterType,
                                                   VertexNoise.Warp(new Vector3(x, v.RampType == RampType.None ? v.WorldPosition.Y + 1.02f : v.WorldPosition.Y + 0.6f, z)), Vector3.Zero, Color.White, Vector3.Up);
                                }
                                else
                                {
                                    manager.Create(Data.SpatterType, p.Position - contact.NEnter * contact.Penetration * 0.95f, Vector3.Zero, Color.White, contact.NEnter);
                                }
                                p.LifeRemaining = -1.0f;
                            }
                        }
                    }
                }

                if (p.LifeRemaining < 0)
                {
                    if (p.InstanceData != null)
                    {
                        p.InstanceData.ShouldDraw = false;
                        p.InstanceData.Transform  = Matrix.CreateTranslation(camera.Position + new Vector3(-1000, -1000, -1000));
                        Sprites[p.Frame].Remove(p.InstanceData);
                    }

                    toRemove.Add(p);
                }

                else if (p.InstanceData != null)
                {
                    p.TimeAlive += (float)gameTime.ElapsedGameTime.TotalSeconds + MathFunctions.Rand() * 0.01f;
                    int prevFrame = p.Frame;
                    int newFrame  = AnimPlayer.GetFrame(p.TimeAlive);
                    if (vel < 0.2f && Data.Sleeps)
                    {
                        newFrame = prevFrame;
                    }
                    if (newFrame != prevFrame)
                    {
                        p.Frame = newFrame;
                        if (Sprites.Count > 0)
                        {
                            Sprites[prevFrame].Remove(p.InstanceData);
                            Sprites[newFrame].Add(p.InstanceData);
                        }
                        if (/*!Data.Animation.Loops && */ p.Frame == Data.Animation.Frames.Count - 1)
                        {
                            p.LifeRemaining *= 0.1f;
                        }
                    }
                    p.InstanceData.ShouldDraw = true;
                    p.InstanceData.Transform  = MatrixFromParticle(Data, p);
                    p.InstanceData.LightRamp  = p.LightRamp;
                }
            }

            foreach (Particle p in toRemove)
            {
                Particles.Remove(p);
            }


            foreach (var sprites in Sprites)
            {
                sprites.Update(gameTime, camera, GameState.Game.GraphicsDevice, chunks.World.Master.MaxViewingLevel);
            }
        }
コード例 #18
0
        public VoxelChunk GenerateChunk(Vector3 origin, WorldManager World)
        {
            float      waterHeight = SeaLevel + 1.0f / VoxelConstants.ChunkSizeY;
            VoxelChunk c           = new VoxelChunk(Manager, origin, GlobalVoxelCoordinate.FromVector3(origin).GetGlobalChunkCoordinate());

            for (int x = 0; x < VoxelConstants.ChunkSizeX; x++)
            {
                for (int z = 0; z < VoxelConstants.ChunkSizeZ; z++)
                {
                    Vector2 v = new Vector2(x + origin.X, z + origin.Z) / WorldScale;

                    var biome = Overworld.Map[(int)MathFunctions.Clamp(v.X, 0, Overworld.Map.GetLength(0) - 1), (int)MathFunctions.Clamp(v.Y, 0, Overworld.Map.GetLength(1) - 1)].Biome;

                    BiomeData biomeData = BiomeLibrary.Biomes[biome];

                    Vector2 pos         = new Vector2(x + origin.X, z + origin.Z) / WorldScale;
                    float   hNorm       = Overworld.LinearInterpolate(pos, Overworld.Map, Overworld.ScalarFieldType.Height);
                    float   h           = MathFunctions.Clamp(hNorm * VoxelConstants.ChunkSizeY, 0.0f, VoxelConstants.ChunkSizeY - 2);
                    int     stoneHeight = (int)(MathFunctions.Clamp((int)(h - (biomeData.SoilLayer.Depth + (Math.Sin(v.X) + Math.Cos(v.Y)))), 1, h));

                    int currentSubsurfaceLayer = 0;
                    int depthWithinSubsurface  = 0;
                    for (int y = VoxelConstants.ChunkSizeY - 1; y >= 0; y--)
                    {
                        var voxel = new VoxelHandle(c, new LocalVoxelCoordinate(x, y, z));

                        if (y == 0)
                        {
                            voxel.RawSetType(VoxelLibrary.GetVoxelType("Bedrock"));
                            voxel.Health = 255; // ?
                            continue;
                        }

                        if (y <= stoneHeight && stoneHeight > 1)
                        {
                            voxel.RawSetType(VoxelLibrary.GetVoxelType(biomeData.SubsurfaceLayers[currentSubsurfaceLayer].VoxelType));
                            depthWithinSubsurface++;
                            if (depthWithinSubsurface > biomeData.SubsurfaceLayers[currentSubsurfaceLayer].Depth)
                            {
                                depthWithinSubsurface = 0;
                                currentSubsurfaceLayer++;
                                if (currentSubsurfaceLayer > biomeData.SubsurfaceLayers.Count - 1)
                                {
                                    currentSubsurfaceLayer = biomeData.SubsurfaceLayers.Count - 1;
                                }
                            }
                        }

                        else if ((y == (int)h || y == stoneHeight) && hNorm > waterHeight)
                        {
                            if (biomeData.ClumpGrass &&
                                NoiseGenerator.Noise(pos.X / biomeData.ClumpSize, 0, pos.Y / biomeData.ClumpSize) >
                                biomeData.ClumpTreshold)
                            {
                                voxel.RawSetType(VoxelLibrary.GetVoxelType(biomeData.SoilLayer.VoxelType));
                                if (!String.IsNullOrEmpty(biomeData.GrassDecal))
                                {
                                    var decal = GrassLibrary.GetGrassType(biomeData.GrassDecal);
                                    voxel.RawSetGrass(decal.ID);
                                }
                            }
                            else if (!biomeData.ClumpGrass)
                            {
                                voxel.RawSetType(VoxelLibrary.GetVoxelType(biomeData.SoilLayer.VoxelType));
                                if (!String.IsNullOrEmpty(biomeData.GrassDecal))
                                {
                                    var decal = GrassLibrary.GetGrassType(biomeData.GrassDecal);
                                    voxel.RawSetGrass(decal.ID);
                                }
                            }
                            else
                            {
                                voxel.RawSetType(VoxelLibrary.GetVoxelType(biomeData.SoilLayer.VoxelType));
                            }
                        }
                        else if (y > h && y > 0)
                        {
                            voxel.RawSetType(VoxelLibrary.emptyType);
                        }
                        else if (hNorm <= waterHeight)
                        {
                            voxel.RawSetType(VoxelLibrary.GetVoxelType(biomeData.ShoreVoxel));
                        }
                        else
                        {
                            voxel.RawSetType(VoxelLibrary.GetVoxelType(biomeData.SoilLayer.VoxelType));
                        }
                    }
                }
            }

            GenerateWater(c);
            GenerateLava(c);

            UpdateSunlight(c, 255);
            return(c);
        }
コード例 #19
0
ファイル: PlantTool.cs プロジェクト: chengjingfeng/dwarfcorp
        private bool ValidatePlanting(VoxelHandle voxel)
        {
            if (!voxel.Type.IsSoil)
            {
                World.UserInterface.ShowTooltip("Can only plant on soil!");
                return(false);
            }

            if (Library.GetResourceType(PlantType).Tags.Contains(Resource.ResourceTags.AboveGroundPlant))
            {
                if (voxel.Sunlight == false)
                {
                    World.UserInterface.ShowTooltip("Can only plant " + PlantType + " above ground.");
                    return(false);
                }
            }
            else if (Library.GetResourceType(PlantType).Tags.Contains(Resource.ResourceTags.BelowGroundPlant))
            {
                if (voxel.Sunlight)
                {
                    World.UserInterface.ShowTooltip("Can only plant " + PlantType + " below ground.");
                    return(false);
                }
            }

            if (World.PersistentData.Designations.GetVoxelDesignation(voxel, DesignationType.Plant).HasValue(out var designation))
            {
                World.UserInterface.ShowTooltip("You're already planting here.");
                return(false);
            }

            var boundingBox = new BoundingBox(voxel.Coordinate.ToVector3() + new Vector3(0.2f, 0.2f, 0.2f), voxel.Coordinate.ToVector3() + new Vector3(0.8f, 0.8f, 0.8f));
            var entities    = World.EnumerateIntersectingObjects(boundingBox, CollisionType.Static).OfType <IVoxelListener>();

            if (entities.Any())
            {
                if (Debugger.Switches.DrawToolDebugInfo)
                {
                    Drawer3D.DrawBox(boundingBox, Color.Red, 0.03f, false);
                    foreach (var entity in entities)
                    {
                        Drawer3D.DrawBox((entity as GameComponent).GetBoundingBox(), Color.Yellow, 0.03f, false);
                    }
                }

                World.UserInterface.ShowTooltip("There's something in the way.");
                return(false);
            }

            var voxelBox = voxel.GetBoundingBox().Expand(-0.2f);

            if (World.EnumerateZones().Where(room => room.Intersects(voxelBox)).Any())
            {
                World.UserInterface.ShowTooltip("Can't plant inside zones.");
                return(false);
            }

            World.UserInterface.ShowTooltip("Click to plant.");

            return(true);
        }
コード例 #20
0
        public void Update()
        {
            MouseState    mouse    = Mouse.GetState();
            KeyboardState keyboard = Keyboard.GetState();

            var underMouse = GetVoxelUnderMouse();
            // Keep track of whether a new voxel has been selected.
            bool newVoxel = underMouse.IsValid && underMouse != VoxelUnderMouse;

            if (!underMouse.IsValid)
            {
                return;
            }

            VoxelUnderMouse = underMouse;

            // Update the cursor light.
            World.CursorLightPos = underMouse.WorldPosition + new Vector3(0.5f, 0.5f, 0.5f);

            // Get the type of the voxel and display it to the player.
            if (Enabled && !underMouse.IsEmpty && underMouse.IsExplored)
            {
                string info = underMouse.Type.Name;

                // If it belongs to a room, display that information.
                if (World.PlayerFaction.RoomBuilder.IsInRoom(underMouse))
                {
                    Room room = World.PlayerFaction.RoomBuilder.GetMostLikelyRoom(underMouse);

                    if (room != null)
                    {
                        info += " (" + room.ID + ")";
                    }
                }
                World.ShowInfo(info);
            }

            // Do nothing if not enabled.
            if (!Enabled)
            {
                return;
            }

            bool altPressed = false;

            // If the left or right ALT keys are pressed, we can adjust the height of the selection
            // for building pits and tall walls using the mouse wheel.
            if (keyboard.IsKeyDown(Keys.LeftAlt) || keyboard.IsKeyDown(Keys.RightAlt))
            {
                var change = mouse.ScrollWheelValue - LastMouseWheel;
                BoxYOffset += (change) * 0.01f;
                int offset = (int)BoxYOffset;
                if (offset != PrevBoxYOffsetInt)
                {
                    DragSound.Play(World.CursorLightPos);
                    newVoxel = true;
                }
                PrevBoxYOffsetInt = offset;
                altPressed        = true;
            }
            else
            {
                PrevBoxYOffsetInt = 0;
            }
            LastMouseWheel = mouse.ScrollWheelValue;

            // Draw a box around the current voxel under the mouse.
            if (underMouse.IsValid && DrawVoxel)
            {
                BoundingBox box = underMouse.GetBoundingBox().Expand(0.05f);
                Drawer3D.DrawBox(box, CurrentColor, CurrentWidth, true);
            }

            // If the left mouse button is pressed, update the slection buffer.
            if (isLeftPressed)
            {
                // On release, select voxels.
                if (mouse.LeftButton == ButtonState.Released)
                {
                    ReleaseSound.Play(World.CursorLightPos);
                    isLeftPressed = false;
                    LeftReleasedCallback();
                    BoxYOffset        = 0;
                    PrevBoxYOffsetInt = 0;
                }
                // Otherwise, update the selection buffer
                else
                {
                    if (SelectionBuffer.Count == 0)
                    {
                        FirstVoxel = underMouse;
                        SelectionBuffer.Add(underMouse);
                    }
                    else
                    {
                        SelectionBuffer.Clear();
                        SelectionBuffer.Add(FirstVoxel);
                        SelectionBuffer.Add(underMouse);
                        BoundingBox buffer = GetSelectionBox();

                        // Update the selection box to account for offsets from mouse wheel.
                        if (BoxYOffset > 0)
                        {
                            buffer.Max.Y += (int)BoxYOffset;
                        }
                        else if (BoxYOffset < 0)
                        {
                            buffer.Min.Y += (int)BoxYOffset;
                        }

                        SelectionBuffer = Select(buffer, FirstVoxel.WorldPosition, underMouse.WorldPosition).ToList();

                        if (!altPressed && Brush != VoxelBrush.Stairs)
                        {
                            if (SelectionType == VoxelSelectionType.SelectFilled)
                            {
                                SelectionBuffer.RemoveAll(v =>
                                {
                                    if (v.Equals(underMouse))
                                    {
                                        return(false);
                                    }
                                    return(!VoxelHelpers.DoesVoxelHaveVisibleSurface(World, v));
                                });
                            }
                        }

                        if (newVoxel)
                        {
                            DragSound.Play(World.CursorLightPos, SelectionBuffer.Count / 20.0f);
                            Dragged.Invoke(SelectionBuffer, InputManager.MouseButton.Left);
                        }
                    }
                }
            }
            // If the mouse was not previously pressed, but is now pressed, then notify us of that.
            else if (mouse.LeftButton == ButtonState.Pressed)
            {
                ClickSound.Play(World.CursorLightPos);;
                isLeftPressed     = true;
                BoxYOffset        = 0;
                PrevBoxYOffsetInt = 0;
            }

            // Case where the right mouse button is pressed (mirrors left mouse button)
            // TODO(Break this into a function)
            if (isRightPressed)
            {
                if (mouse.RightButton == ButtonState.Released)
                {
                    ReleaseSound.Play(World.CursorLightPos);
                    isRightPressed = false;
                    RightReleasedCallback();
                    BoxYOffset        = 0;
                    PrevBoxYOffsetInt = 0;
                }
                else
                {
                    if (SelectionBuffer.Count == 0)
                    {
                        SelectionBuffer.Add(underMouse);
                        FirstVoxel = underMouse;
                    }
                    else
                    {
                        SelectionBuffer.Clear();
                        SelectionBuffer.Add(FirstVoxel);
                        SelectionBuffer.Add(underMouse);
                        BoundingBox buffer = GetSelectionBox();
                        if (BoxYOffset > 0)
                        {
                            buffer.Max.Y += (int)BoxYOffset;
                        }
                        else if (BoxYOffset < 0)
                        {
                            buffer.Min.Y += (int)BoxYOffset;
                        }

                        SelectionBuffer = VoxelHelpers.EnumerateCoordinatesInBoundingBox(buffer)
                                          .Select(c => new VoxelHandle(Chunks.ChunkData, c))
                                          .Where(v => v.IsValid)
                                          .ToList();

                        if (newVoxel)
                        {
                            DragSound.Play(World.CursorLightPos, SelectionBuffer.Count / 20.0f);
                            Dragged.Invoke(SelectionBuffer, InputManager.MouseButton.Right);
                        }
                    }
                }
            }
            else if (mouse.RightButton == ButtonState.Pressed)
            {
                ClickSound.Play(World.CursorLightPos);
                RightPressedCallback();
                BoxYOffset     = 0;
                isRightPressed = true;
            }
        }
コード例 #21
0
ファイル: WorldManager.cs プロジェクト: jeason1997/dwarfcorp
        public bool IsCameraUnderwater()
        {
            var handle = new VoxelHandle(ChunkManager.ChunkData, GlobalVoxelCoordinate.FromVector3(Camera.Position));

            return(handle.IsValid && handle.WaterCell.WaterLevel > 0);
        }
コード例 #22
0
ファイル: BuildRailTool.cs プロジェクト: jeason1997/dwarfcorp
        private void Place(VoxelHandle Location)
        {
            var assignments = new List <Task>();

            for (var i = 0; i < PreviewBodies.Count; ++i)
            {
                var body              = PreviewBodies[i];
                var piece             = Pattern.Pieces[i];
                var actualPosition    = new VoxelHandle(Location.Chunk.Manager.ChunkData, Location.Coordinate + new GlobalVoxelOffset(piece.Offset.X, 0, piece.Offset.Y));
                var addNewDesignation = true;

                foreach (var entity in Player.World.CollisionManager.EnumerateIntersectingObjects(actualPosition.GetBoundingBox().Expand(-0.2f), CollisionManager.CollisionType.Static))
                {
                    if (!addNewDesignation)
                    {
                        break;
                    }
                    if (Object.ReferenceEquals(entity, body))
                    {
                        continue;
                    }

                    var possibleCombination = FindPossibleCombination(piece, entity);
                    if (possibleCombination != null)
                    {
                        var combinedPiece = new Rail.JunctionPiece
                        {
                            RailPiece   = possibleCombination.Result,
                            Orientation = Rail.OrientationHelper.Rotate((entity as RailPiece).Piece.Orientation, (int)possibleCombination.ResultRelativeOrientation),
                        };

                        var existingDesignation = Player.Faction.Designations.EnumerateEntityDesignations(DesignationType.Craft).FirstOrDefault(d => Object.ReferenceEquals(d.Body, entity));
                        if (existingDesignation != null)
                        {
                            (entity as RailPiece).UpdatePiece(combinedPiece, actualPosition);
                            (existingDesignation.Tag as CraftDesignation).Progress = 0.0f;
                            body.Delete();
                            addNewDesignation = false;
                        }
                        else
                        {
                            (entity as RailPiece).Die();
                            body.UpdatePiece(combinedPiece, actualPosition);
                        }
                    }
                }

                if (addNewDesignation)
                {
                    var startPos = body.Position + new Vector3(0.0f, -0.3f, 0.0f);
                    var endPos   = body.Position;

                    var designation = new CraftDesignation
                    {
                        Entity              = body,
                        WorkPile            = new WorkPile(Player.World.ComponentManager, startPos),
                        OverrideOrientation = false,
                        Valid                = true,
                        ItemType             = RailCraftItem,
                        SelectedResources    = SelectedResources,
                        Location             = new VoxelHandle(Player.World.ChunkManager.ChunkData, GlobalVoxelCoordinate.FromVector3(body.Position)),
                        HasResources         = false,
                        ResourcesReservedFor = null,
                        Orientation          = 0.0f,
                        Progress             = 0.0f,
                    };

                    Player.World.ComponentManager.RootComponent.AddChild(designation.WorkPile);
                    designation.WorkPile.AnimationQueue.Add(new EaseMotion(1.1f, Matrix.CreateTranslation(startPos), endPos));
                    Player.World.ParticleManager.Trigger("puff", endPos, Color.White, 10);
                    Player.Faction.Designations.AddEntityDesignation(body, DesignationType.Craft, designation);
                    assignments.Add(new CraftItemTask(designation));
                }
            }

            if (assignments.Count > 0)
            {
                Player.World.Master.TaskManager.AddTasks(assignments);
            }
        }
コード例 #23
0
ファイル: CreatureMovement.cs プロジェクト: hhy5277/dwarfcorp
        private IEnumerable <MoveAction> EnumerateSuccessors(
            MoveState state,
            VoxelHandle voxel,
            MoveActionTempStorage Storage,
            bool inWater,
            bool standingOnGround,
            bool topCovered,
            bool hasNeighbors)
        {
            bool isClimbing = false;

            if (state.VehicleType == VehicleTypes.Rail)
            {
                if (Can(MoveType.ExitVehicle)) // Possibly redundant... If they can ride they should be able to exit right?
                {
                    yield return(new MoveAction()
                    {
                        SourceState = state,
                        DestinationState = new MoveState()
                        {
                            VehicleType = VehicleTypes.None,
                            Voxel = state.Voxel
                        },
                        MoveType = MoveType.ExitVehicle,
                        Diff = new Vector3(1, 1, 1),
                        CostMultiplier = 1.0f
                    });
                }

                if (Can(MoveType.RideVehicle))
                {
                    foreach (var neighbor in Rail.RailHelper.EnumerateForwardNetworkConnections(state.PrevRail, state.Rail))
                    {
                        var neighborRail = Creature.Manager.FindComponent(neighbor) as Rail.RailEntity;
                        if (neighborRail == null || !neighborRail.Active)
                        {
                            continue;
                        }

                        yield return(new MoveAction()
                        {
                            SourceState = state,
                            DestinationState = new MoveState()
                            {
                                Voxel = neighborRail.GetContainingVoxel(),
                                Rail = neighborRail,
                                PrevRail = state.Rail,
                                VehicleType = VehicleTypes.Rail
                            },
                            MoveType = MoveType.RideVehicle,
                            CostMultiplier = 1.0f
                        });
                    }
                }

                yield break; // Nothing can be done without exiting the rails first.
            }

            if (CanClimb || Can(MoveType.RideVehicle))
            {
                //Climbing ladders and riding rails.

                var bodies = Storage.NeighborObjects.Where(o => o.GetBoundingBox().Intersects(voxel.GetBoundingBox()));

                // if the creature can climb objects and a ladder is in this voxel,
                // then add a climb action.
                if (CanClimb)
                {
                    var ladder = bodies.FirstOrDefault(component => component.Tags.Contains("Climbable"));

                    if (ladder != null)
                    {
                        yield return(new MoveAction
                        {
                            SourceState = state,
                            Diff = new Vector3(1, 2, 1),
                            MoveType = MoveType.Climb,
                            InteractObject = ladder,
                            CostMultiplier = 1.0f,
                            DestinationVoxel = Storage.Neighborhood[1, 2, 1]
                        });

                        if (!standingOnGround)
                        {
                            yield return(new MoveAction
                            {
                                SourceState = state,
                                Diff = new Vector3(1, 0, 1),
                                MoveType = MoveType.Climb,
                                InteractObject = ladder,
                                CostMultiplier = 1.0f,
                                DestinationVoxel = Storage.Neighborhood[1, 2, 1]
                            });
                        }
                        standingOnGround = true;
                    }
                }

                if (Can(MoveType.RideVehicle))
                {
                    var rails = bodies.OfType <Rail.RailEntity>().Where(r => r.Active);

                    if (rails.Count() > 0 && Can(MoveType.RideVehicle))
                    {
                        {
                            foreach (var rail in rails)
                            {
                                if (rail.GetContainingVoxel() != state.Voxel)
                                {
                                    continue;
                                }


                                yield return(new MoveAction()
                                {
                                    SourceState = state,
                                    DestinationState = new MoveState()
                                    {
                                        VehicleType = VehicleTypes.Rail,
                                        Rail = rail,
                                        Voxel = rail.GetContainingVoxel()
                                    },
                                    MoveType = MoveType.EnterVehicle,
                                    Diff = new Vector3(1, 1, 1),
                                    CostMultiplier = 1.0f
                                });
                            }
                        }
                    }

                    var elevators = bodies.OfType <Elevators.ElevatorShaft>().Where(r => r.Active && System.Math.Abs(r.Position.Y - voxel.Center.Y) < 0.5f);

                    foreach (var elevator in elevators)
                    {
                        foreach (var elevatorExit in Elevators.Helper.EnumerateExits(elevator.Shaft))
                        {
                            if (object.ReferenceEquals(elevator, elevatorExit.ShaftSegment))
                            {
                                continue;                                                              // Ignore exits from the segment we are entering at.
                            }
                            yield return(new MoveAction()
                            {
                                SourceState = state,
                                DestinationState = new MoveState()
                                {
                                    Voxel = elevatorExit.OntoVoxel,
                                    VehicleType = VehicleTypes.None,
                                    Tag = new Elevators.ElevatorMoveState
                                    {
                                        Entrance = elevator,
                                        Exit = elevatorExit.ShaftSegment
                                    }
                                },
                                MoveType = MoveType.RideElevator,
                                CostMultiplier = elevator.GetQueueSize() + 1.0f
                            });
                        }
                    }
                }
            }

            // If the creature can fly and is not underwater, it can fly
            // to any adjacent empty cell.
            if (CanFly && !inWater)
            {
                for (int dx = 0; dx <= 2; dx++)
                {
                    for (int dz = 0; dz <= 2; dz++)
                    {
                        for (int dy = 0; dy <= 2; dy++)
                        {
                            if (dx == 1 && dz == 1 && dy == 1)
                            {
                                continue;
                            }

                            if (Storage.Neighborhood[dx, dy, dz].IsValid && Storage.Neighborhood[dx, dy, dz].IsEmpty)
                            {
                                yield return(new MoveAction
                                {
                                    SourceState = state,
                                    Diff = new Vector3(dx, dy, dz),
                                    MoveType = MoveType.Fly,
                                    CostMultiplier = 1.0f,
                                    DestinationVoxel = Storage.Neighborhood[dx, dy, dz]
                                });
                            }
                        }
                    }
                }
            }

            // If the creature is not in water and is not standing on ground,
            // it can fall one voxel downward in free space.
            if (!inWater && !standingOnGround)
            {
                yield return(new MoveAction
                {
                    SourceState = state,
                    Diff = new Vector3(1, 0, 1),
                    MoveType = MoveType.Fall,
                    CostMultiplier = 1.0f,
                    DestinationVoxel = Storage.Neighborhood[1, 0, 1]
                });
            }

            // If the creature can climb walls and is not blocked by a voxl above.
            if (CanClimbWalls && !topCovered)
            {
                // This monstrosity is unrolling an inner loop so that we don't have to allocate an array or
                // enumerators.
                var wall = VoxelHandle.InvalidHandle;
                var n211 = Storage.Neighborhood[2, 1, 1];
                if (n211.IsValid && !n211.IsEmpty)
                {
                    wall = n211;
                }
                else
                {
                    var n011 = Storage.Neighborhood[0, 1, 1];
                    if (n011.IsValid && !n011.IsEmpty)
                    {
                        wall = n011;
                    }
                    else
                    {
                        var n112 = Storage.Neighborhood[1, 1, 2];
                        if (n112.IsValid && !n112.IsEmpty)
                        {
                            wall = n112;
                        }
                        else
                        {
                            var n110 = Storage.Neighborhood[1, 1, 0];
                            if (n110.IsValid && !n110.IsEmpty)
                            {
                                wall = n110;
                            }
                        }
                    }
                }

                if (wall.IsValid)
                {
                    isClimbing = true;
                    yield return(new MoveAction
                    {
                        SourceState = state,
                        Diff = new Vector3(1, 2, 1),
                        MoveType = MoveType.ClimbWalls,
                        ActionVoxel = wall,
                        CostMultiplier = 1.0f,
                        DestinationVoxel = Storage.Neighborhood[1, 2, 1]
                    });

                    if (!standingOnGround)
                    {
                        yield return(new MoveAction
                        {
                            SourceState = state,
                            Diff = new Vector3(1, 0, 1),
                            MoveType = MoveType.ClimbWalls,
                            ActionVoxel = wall,
                            CostMultiplier = 1.0f,
                            DestinationVoxel = Storage.Neighborhood[1, 0, 1]
                        });
                    }
                }
            }

            // If the creature either can walk or is in water, add the
            // eight-connected free neighbors around the voxel.
            if ((CanWalk && standingOnGround) || (CanSwim && inWater))
            {
                // If the creature is in water, it can swim. Otherwise, it will walk.
                var moveType = inWater ? MoveType.Swim : MoveType.Walk;
                if (Storage.Neighborhood[0, 1, 1].IsValid && Storage.Neighborhood[0, 1, 1].IsEmpty)
                {
                    // +- x
                    yield return(new MoveAction
                    {
                        SourceState = state,
                        DestinationVoxel = Storage.Neighborhood[0, 1, 1],
                        Diff = new Vector3(0, 1, 1),
                        MoveType = moveType,
                        CostMultiplier = 1.0f
                    });
                }

                if (Storage.Neighborhood[2, 1, 1].IsValid && Storage.Neighborhood[2, 1, 1].IsEmpty)
                {
                    yield return(new MoveAction
                    {
                        SourceState = state,
                        Diff = new Vector3(2, 1, 1),
                        MoveType = moveType,
                        CostMultiplier = 1.0f,
                        DestinationVoxel = Storage.Neighborhood[2, 1, 1]
                    });
                }

                if (Storage.Neighborhood[1, 1, 0].IsValid && Storage.Neighborhood[1, 1, 0].IsEmpty)
                {
                    // +- z
                    yield return(new MoveAction
                    {
                        SourceState = state,
                        Diff = new Vector3(1, 1, 0),
                        MoveType = moveType,
                        CostMultiplier = 1.0f,
                        DestinationVoxel = Storage.Neighborhood[1, 1, 0]
                    });
                }

                if (Storage.Neighborhood[1, 1, 2].IsValid && Storage.Neighborhood[1, 1, 2].IsEmpty)
                {
                    yield return(new MoveAction
                    {
                        SourceState = state,
                        Diff = new Vector3(1, 1, 2),
                        MoveType = moveType,
                        CostMultiplier = 1.0f,
                        DestinationVoxel = Storage.Neighborhood[1, 1, 2]
                    });
                }

                // Only bother worrying about 8-connected movement if there are
                // no full neighbors around the voxel.
                if (!hasNeighbors)
                {
                    if (Storage.Neighborhood[2, 1, 2].IsValid && Storage.Neighborhood[2, 1, 2].IsEmpty)
                    {
                        // +x + z
                        yield return(new MoveAction
                        {
                            SourceState = state,
                            Diff = new Vector3(2, 1, 2),
                            MoveType = moveType,
                            CostMultiplier = 1.0f,
                            DestinationVoxel = Storage.Neighborhood[2, 1, 2]
                        });
                    }

                    if (Storage.Neighborhood[2, 1, 0].IsValid && Storage.Neighborhood[2, 1, 0].IsEmpty)
                    {
                        yield return(new MoveAction
                        {
                            SourceState = state,
                            Diff = new Vector3(2, 1, 0),
                            MoveType = moveType,
                            CostMultiplier = 1.0f,
                            DestinationVoxel = Storage.Neighborhood[2, 1, 0]
                        });
                    }

                    if (Storage.Neighborhood[0, 1, 2].IsValid && Storage.Neighborhood[0, 1, 2].IsEmpty)
                    {
                        // -x -z
                        yield return(new MoveAction
                        {
                            SourceState = state,
                            Diff = new Vector3(0, 1, 2),
                            MoveType = moveType,
                            CostMultiplier = 1.0f,
                            DestinationVoxel = Storage.Neighborhood[0, 1, 2]
                        });
                    }

                    if (Storage.Neighborhood[0, 1, 0].IsValid && Storage.Neighborhood[0, 1, 0].IsEmpty)
                    {
                        yield return(new MoveAction
                        {
                            SourceState = state,
                            Diff = new Vector3(0, 1, 0),
                            MoveType = moveType,
                            CostMultiplier = 1.0f,
                            DestinationVoxel = Storage.Neighborhood[0, 1, 0]
                        });
                    }
                }
            }

            // If the creature's head is free, and it is standing on ground,
            // or if it is in water, or if it is climbing, it can also jump
            // to voxels that are 1 cell away and 1 cell up.
            if (!topCovered && (standingOnGround || (CanSwim && inWater) || isClimbing))
            {
                for (int dx = 0; dx <= 2; dx++)
                {
                    for (int dz = 0; dz <= 2; dz++)
                    {
                        if (dx == 1 && dz == 1)
                        {
                            continue;
                        }

                        if (Storage.Neighborhood[dx, 1, dz].IsValid && !Storage.Neighborhood[dx, 1, dz].IsEmpty)
                        {
                            yield return(new MoveAction
                            {
                                SourceState = state,
                                Diff = new Vector3(dx, 2, dz),
                                MoveType = MoveType.Jump,
                                DestinationVoxel = Storage.Neighborhood[dx, 2, dz],
                                CostMultiplier = 1.0f
                            });
                        }
                    }
                }
            }

            /*
             * if (CanDig)
             * {
             *  // This loop is unrolled for speed. It gets the manhattan neighbors and tells the creature that it can mine
             *  // the surrounding rock to get through.
             *  VoxelHandle neighbor = Storage.Neighborhood[0, 1, 1];
             *  if (neighbor.IsValid && !neighbor.IsEmpty && (!IsDwarf || !neighbor.IsPlayerBuilt))
             *  {
             *      yield return (new MoveAction
             *      {
             *          SourceState = state,
             *          Diff = new Vector3(0, 1, 1),
             *          MoveType = MoveType.Dig,
             *          DestinationVoxel = neighbor,
             *          CostMultiplier = 1.0f
             *      });
             *  }
             *
             *  neighbor = Storage.Neighborhood[2, 1, 1];
             *  if (neighbor.IsValid && !neighbor.IsEmpty && (!IsDwarf || !neighbor.IsPlayerBuilt))
             *  {
             *      yield return (new MoveAction
             *      {
             *          SourceState = state,
             *          Diff = new Vector3(2, 1, 1),
             *          MoveType = MoveType.Dig,
             *          DestinationVoxel = neighbor,
             *          CostMultiplier = 1.0f
             *      });
             *  }
             *
             *  neighbor = Storage.Neighborhood[1, 1, 2];
             *  if (neighbor.IsValid && !neighbor.IsEmpty && (!IsDwarf || !neighbor.IsPlayerBuilt))
             *  {
             *      yield return (new MoveAction
             *      {
             *          SourceState = state,
             *          Diff = new Vector3(1, 1, 2),
             *          MoveType = MoveType.Dig,
             *          DestinationVoxel = neighbor,
             *          CostMultiplier = 1.0f
             *      });
             *  }
             *
             *  neighbor = Storage.Neighborhood[1, 1, 0];
             *  if (neighbor.IsValid && !neighbor.IsEmpty && (!IsDwarf || !neighbor.IsPlayerBuilt))
             *  {
             *      yield return (new MoveAction
             *      {
             *          SourceState = state,
             *          Diff = new Vector3(1, 1, 0),
             *          MoveType = MoveType.Dig,
             *          DestinationVoxel = neighbor,
             *          CostMultiplier = 1.0f
             *      });
             *  }
             *
             *  neighbor = Storage.Neighborhood[1, 2, 1];
             *  if (neighbor.IsValid && !neighbor.IsEmpty && (!IsDwarf || !neighbor.IsPlayerBuilt))
             *  {
             *      yield return (new MoveAction
             *      {
             *          SourceState = state,
             *          Diff = new Vector3(1, 2, 1),
             *          MoveType = MoveType.Dig,
             *          DestinationVoxel = neighbor,
             *          CostMultiplier = 1.0f
             *      });
             *  }
             *
             *  neighbor = Storage.Neighborhood[1, 0, 1];
             *  if (neighbor.IsValid && !neighbor.IsEmpty && (!IsDwarf || !neighbor.IsPlayerBuilt))
             *  {
             *      yield return (new MoveAction
             *      {
             *          SourceState = state,
             *          Diff = new Vector3(1, 0, 1),
             *          MoveType = MoveType.Dig,
             *          DestinationVoxel = neighbor,
             *          CostMultiplier = 1.0f
             *      });
             *  }
             * }
             */
        }
コード例 #24
0
ファイル: EnemySensor.cs プロジェクト: sodomon2/dwarfcorp
        public void Sense()
        {
            if (Name == "turret-sensor")
            {
                var x = 5;
            }

            if (!Active)
            {
                return;
            }

            if (Creature != null)
            {
                Allies = Creature.Faction;
            }

            // Don't sense enemies if we're inside the ground??
            var currentVoxel = new VoxelHandle(World.ChunkManager, GlobalVoxelCoordinate.FromVector3(Position));

            if (!(currentVoxel.IsValid && currentVoxel.IsEmpty))
            {
                return;
            }

            var sensed = new List <CreatureAI>();

            var myRoot = GetRoot();

            foreach (var body in Manager.World.EnumerateIntersectingObjects(BoundingBox, b => !Object.ReferenceEquals(b, myRoot) && b.IsRoot()))
            {
                if (body.GetComponent <Flammable>().HasValue(out var flames) && flames.IsOnFire)
                {
                    if (GetRoot().GetComponent <CreatureAI>().HasValue(out var myAI))
                    {
                        var task = new FleeEntityTask(body, 5)
                        {
                            Priority        = TaskPriority.Urgent,
                            AutoRetry       = false,
                            ReassignOnDeath = false
                        };

                        if (!myAI.HasTaskWithName(task))
                        {
                            myAI.AssignTask(task);
                        }

                        continue;
                    }
                }

                if (body.GetComponent <CreatureAI>().HasValue(out var minion))
                {
                    if (!minion.Active)
                    {
                        continue;
                    }

                    if (!DetectCloaked && minion.Creature.IsCloaked)
                    {
                        continue;
                    }

                    else if (DetectCloaked && minion.Creature.IsCloaked)
                    {
                        minion.Creature.IsCloaked = false;
                    }

                    if (World.Overworld.GetPolitics(Allies.ParentFaction, minion.Faction.ParentFaction).GetCurrentRelationship() != Relationship.Hateful)
                    {
                        continue;
                    }

                    if (!VoxelHelpers.DoesRayHitSolidVoxel(Manager.World.ChunkManager, Position, minion.Position))
                    {
                        sensed.Add(minion);
                    }
                }
            }

            if (sensed != null && sensed.Count > 0 && OnEnemySensed != null)
            {
                OnEnemySensed.Invoke(sensed);
            }
        }
コード例 #25
0
 public void SetVoxel(VoxelHandle voxel)
 {
     Agent.Blackboard.SetData(VoxelName, voxel);
 }
コード例 #26
0
ファイル: Stockpile.cs プロジェクト: sodomon2/dwarfcorp
        private List <VoxelHandle> SpiralVoxels()
        {
            // Process voxels into a neat grid.
            if (Voxels.Count == 0)
            {
                throw new InvalidOperationException();
            }

            var bounds    = this.GetBoundingBox();
            var voxelGrid = new VoxelHandle[(int)(bounds.Max.X - bounds.Min.X), (int)(bounds.Max.Z - bounds.Min.Z)];

            foreach (var voxel in Voxels)
            {
                voxelGrid[(int)(voxel.Coordinate.X - bounds.Min.X), (int)(voxel.Coordinate.Z - bounds.Min.Z)] = voxel;
            }

            // if any invalid voxels in grid, go ahead and abort.
            foreach (var voxel in voxelGrid)
            {
                if (!voxel.IsValid)
                {
                    return(Voxels);
                }
            }

            // Find center voxel. Actually want to round UP - or - spiral in positive direction?
            var center_c  = GlobalVoxelCoordinate.FromVector3(bounds.Center());
            var current_v = Voxels.FirstOrDefault(v => v.Coordinate == center_c);

            if (!current_v.IsValid)
            {
                return(Voxels);
            }

            var direction = Direction.East;

            var results = new List <VoxelHandle>();

            results.Add(current_v);

            // Starting at center, spiral around, starting to the right.

            while (true)
            {
                var next_voxel = Voxels.FirstOrDefault(v => v.Coordinate == current_v.Coordinate + GetDirectionOffset(direction));
                if (next_voxel.IsValid)
                {
                    results.Add(next_voxel);
                    current_v = next_voxel;

                    var possible_turn  = TurnRight(direction);
                    var possible_ahead = Voxels.FirstOrDefault(v => v.Coordinate == current_v.Coordinate + GetDirectionOffset(possible_turn));
                    if (possible_ahead.IsValid && !results.Any(v => v.Coordinate == possible_ahead.Coordinate))
                    {
                        direction = possible_turn;
                    }
                }
                else
                {
                    break;
                }
            }

            // Recover any voxels we missed.
            foreach (var voxel in Voxels)
            {
                if (!results.Any(v => v.Coordinate == voxel.Coordinate))
                {
                    results.Add(voxel);
                }
            }

            return(results);

            // For each voxel - step one in the current direction and return.
            //      If we've hit an edge - try and turn.
            //      If the next direction is unvisited - turn
        }
コード例 #27
0
        private static void CreateWaterFaces(
            VoxelHandle voxel,
            VoxelChunk chunk,
            int x, int y, int z,
            ExtendedVertex[] vertices,
            ushort[] Indexes,
            int startVertex,
            int startIndex)
        {
            // Reset the appropriate parts of the cache.
            cache.Reset();

            // These are reused for every face.
            var   origin           = voxel.WorldPosition;
            float centerWaterlevel = voxel.LiquidLevel;

            float[] foaminess = new float[4];

            for (int i = 0; i < cache.drawFace.Length; i++)
            {
                if (!cache.drawFace[i])
                {
                    continue;
                }
                BoxFace face = (BoxFace)i;

                var faceDescriptor = primitive.GetFace(face);
                int indexOffset    = startVertex;

                for (int vertOffset = 0; vertOffset < faceDescriptor.VertexCount; vertOffset++)
                {
                    VoxelVertex currentVertex = primitive.Deltas[faceDescriptor.VertexOffset + vertOffset];

                    // These will be filled out before being used   lh  .
                    //float foaminess1;
                    foaminess[vertOffset] = 0.0f;
                    bool shoreLine = false;

                    Vector3 pos        = Vector3.Zero;
                    Vector3 rampOffset = Vector3.Zero;
                    var     uv         = primitive.UVs.Uvs[vertOffset + faceDescriptor.VertexOffset];
                    // We are going to have to reuse some vertices when drawing a single so we'll store the position/foaminess
                    // for quick lookup when we find one of those reused ones.
                    // When drawing multiple faces the Vertex overlap gets bigger, which is a bonus.
                    if (!cache.vertexCalculated[(int)currentVertex])
                    {
                        float count             = 1.0f;
                        float emptyNeighbors    = 0.0f;
                        float averageWaterLevel = centerWaterlevel;

                        var vertexSucc = VoxelHelpers.VertexNeighbors[(int)currentVertex];

                        // Run through the successors and count up the water in each voxel.
                        for (int v = 0; v < vertexSucc.Length; v++)
                        {
                            var neighborVoxel = new VoxelHandle(chunk.Manager.ChunkData,
                                                                voxel.Coordinate + vertexSucc[v]);
                            // Only continue if it's a valid (non-null) voxel.
                            if (!neighborVoxel.IsValid)
                            {
                                continue;
                            }

                            // Now actually do the math.
                            count++;
                            if (neighborVoxel.LiquidLevel < 1)
                            {
                                emptyNeighbors++;
                            }
                            if (neighborVoxel.LiquidType == LiquidType.None && !neighborVoxel.IsEmpty)
                            {
                                shoreLine = true;
                            }
                        }

                        foaminess[vertOffset] = emptyNeighbors / count;

                        if (foaminess[vertOffset] <= 0.5f)
                        {
                            foaminess[vertOffset] = 0.0f;
                        }
                        // Check if it should ramp.
                        else if (!shoreLine)
                        {
                            //rampOffset.Y = -0.4f;
                        }

                        pos = primitive.Vertices[vertOffset + faceDescriptor.VertexOffset].Position;
                        if ((currentVertex & VoxelVertex.Top) == VoxelVertex.Top)
                        {
                            pos.Y -= 0.6f;// Minimum ramp position

                            var neighbors = VoxelHelpers.EnumerateVertexNeighbors2D(voxel.Coordinate, currentVertex)
                                            .Select(c => new VoxelHandle(chunk.Manager.ChunkData, c))
                                            .Where(h => h.IsValid)
                                            .Select(h => (float)h.LiquidLevel / 8.0f);

                            if (neighbors.Count() > 0)
                            {
                                pos.Y *= neighbors.Average();
                            }
                        }
                        else
                        {
                            uv.Y -= 0.6f;
                        }

                        pos += VertexNoise.GetNoiseVectorFromRepeatingTexture(voxel.WorldPosition +
                                                                              primitive.Vertices[vertOffset + faceDescriptor.VertexOffset].Position);
                        pos += origin + rampOffset;

                        // Store the vertex information for future use when we need it again on this or another face.
                        cache.vertexCalculated[(int)currentVertex] = true;
                        cache.vertexFoaminess[(int)currentVertex]  = foaminess[vertOffset];
                        cache.vertexPositions[(int)currentVertex]  = pos;
                    }
                    else
                    {
                        // We've already calculated this one.  Time for a cheap grab from the lookup.
                        foaminess[vertOffset] = cache.vertexFoaminess[(int)currentVertex];
                        pos = cache.vertexPositions[(int)currentVertex];
                    }

                    vertices[startVertex].Set(pos,
                                              new Color(foaminess[vertOffset], 0.0f, 1.0f, 1.0f),
                                              Color.White,
                                              uv,
                                              new Vector4(0, 0, 1, 1));

                    startVertex++;
                }

                bool flippedQuad = foaminess[1] + foaminess[3] >
                                   foaminess[0] + foaminess[2];

                for (int idx = faceDescriptor.IndexOffset; idx < faceDescriptor.IndexCount + faceDescriptor.IndexOffset; idx++)
                {
                    ushort offset  = flippedQuad ? primitive.FlippedIndexes[idx] : primitive.Indexes[idx];
                    ushort offset0 = flippedQuad ? primitive.FlippedIndexes[faceDescriptor.IndexOffset] : primitive.Indexes[faceDescriptor.IndexOffset];

                    Indexes[startIndex] = (ushort)(indexOffset + offset - offset0);
                    startIndex++;
                }
            }
            // End cache.drawFace loop
        }
コード例 #28
0
ファイル: Stockpile.cs プロジェクト: sodomon2/dwarfcorp
 public override void AddVoxel(VoxelHandle Voxel)
 {
     base.AddVoxel(Voxel);
     RecalculateMaxResources();
     Voxels = SpiralVoxels();
 }
コード例 #29
0
        public static bool IsValidPlacement(
            VoxelHandle Location,
            CraftItem CraftType,
            WorldManager World,
            GameComponent PreviewBody,
            String Verb,
            String PastParticple)
        {
            if (CraftType == null)
            {
                return(false);
            }

            if (!String.IsNullOrEmpty(CraftType.CraftLocation) &&
                World.PlayerFaction.FindNearestItemWithTags(CraftType.CraftLocation, Location.WorldPosition, false, null) == null)
            {
                World.UserInterface.ShowTooltip("Can't " + Verb + ", need " + CraftType.CraftLocation);
                return(false);
            }

            foreach (var req in CraftType.Prerequisites)
            {
                switch (req)
                {
                case CraftItem.CraftPrereq.NearWall:
                {
                    var neighborFound = VoxelHelpers.EnumerateManhattanNeighbors2D(Location.Coordinate)
                                        .Select(c => new VoxelHandle(World.ChunkManager, c))
                                        .Any(v => v.IsValid && !v.IsEmpty);

                    if (!neighborFound)
                    {
                        World.UserInterface.ShowTooltip("Must be " + PastParticple + " next to wall!");
                        return(false);
                    }

                    break;
                }

                case CraftItem.CraftPrereq.OnGround:
                {
                    var below = VoxelHelpers.GetNeighbor(Location, new GlobalVoxelOffset(0, -1, 0));

                    if (!below.IsValid || below.IsEmpty)
                    {
                        World.UserInterface.ShowTooltip("Must be " + PastParticple + " on solid ground!");
                        return(false);
                    }
                    break;
                }
                }
            }

            if (PreviewBody != null)
            {
                // Just check for any intersecting body in octtree.

                var previewBox = PreviewBody.GetRotatedBoundingBox();
                var sensorBox  = previewBox;
                var sensor     = PreviewBody.GetComponent <GenericVoxelListener>();
                if (sensor != null)
                {
                    sensorBox = sensor.GetRotatedBoundingBox();
                }
                if (Debugger.Switches.DrawToolDebugInfo)
                {
                    Drawer3D.DrawBox(sensorBox, Color.Yellow, 0.1f, false);
                }

                foreach (var intersectingObject in World.EnumerateIntersectingObjects(sensorBox, CollisionType.Static))
                {
                    if (Object.ReferenceEquals(intersectingObject, sensor))
                    {
                        continue;
                    }
                    var objectRoot = intersectingObject.GetRoot() as GameComponent;
                    if (objectRoot is WorkPile)
                    {
                        continue;
                    }
                    if (objectRoot == PreviewBody)
                    {
                        continue;
                    }
                    if (objectRoot != null && objectRoot.GetRotatedBoundingBox().Intersects(previewBox))
                    {
                        World.UserInterface.ShowTooltip("Can't " + Verb + " here: intersects " + objectRoot.Name);
                        return(false);
                    }
                }

                bool intersectsWall = VoxelHelpers.EnumerateCoordinatesInBoundingBox
                                          (PreviewBody.GetRotatedBoundingBox().Expand(-0.1f)).Any(
                    v =>
                {
                    var tvh = new VoxelHandle(World.ChunkManager, v);
                    return(tvh.IsValid && !tvh.IsEmpty);
                });
                var  current    = new VoxelHandle(World.ChunkManager, GlobalVoxelCoordinate.FromVector3(PreviewBody.Position));
                bool underwater = current.IsValid && current.LiquidType != LiquidType.None;
                if (underwater)
                {
                    World.UserInterface.ShowTooltip("Can't " + Verb + " here: underwater or in lava.");
                    return(false);
                }
                if (intersectsWall && !CraftType.Prerequisites.Contains(CraftItem.CraftPrereq.NearWall))
                {
                    World.UserInterface.ShowTooltip("Can't " + Verb + " here: intersects wall.");
                    return(false);
                }
            }
            World.UserInterface.ShowTooltip("");
            return(true);
        }
コード例 #30
0
        private static void BuildVoxelFaceGeometry(
            RawPrimitive Into,
            VoxelChunk Chunk,
            Cache Cache,
            BoxPrimitive Primitive,
            VoxelHandle V,
            Color Tint,
            BoxPrimitive.BoxTextureCoords UVs,
            Matrix VertexTransform,
            int i,
            bool ApplyLighting)
        {
            var face  = (BoxFace)i;
            var delta = FaceDeltas[i];

            var faceVoxel = new VoxelHandle(Chunk.Manager, V.Coordinate + GlobalVoxelOffset.FromVector3(delta));

            if (!IsFaceVisible(V, faceVoxel, face))
            {
                return;
            }

            var faceDescriptor = Primitive.GetFace(face);
            var indexOffset    = Into.VertexCount;

            for (int faceVertex = 0; faceVertex < faceDescriptor.VertexCount; faceVertex++)
            {
                var vertex      = Primitive.Vertices[faceDescriptor.VertexOffset + faceVertex];
                var voxelVertex = Primitive.Deltas[faceDescriptor.VertexOffset + faceVertex];
                var vertexColor = new VertexColorInfo
                {
                    SunColor     = 255,
                    AmbientColor = 255,
                    DynamicColor = 255,
                };

                if (ApplyLighting)
                {
                    var cacheKey = GetCacheKey(V, voxelVertex);

                    if (!Cache.LightCache.TryGetValue(cacheKey, out vertexColor))
                    {
                        vertexColor = CalculateVertexLight(V, voxelVertex, Chunk.Manager);
                        Cache.LightCache.Add(cacheKey, vertexColor);
                    }

                    Cache.AmbientValues[faceVertex] = vertexColor.AmbientColor;
                }

                var rampOffset = Vector3.Zero;
                if (V.IsExplored && V.Type.CanRamp && ShouldRamp(voxelVertex, V.RampType))
                {
                    rampOffset = new Vector3(0, -V.Type.RampSize, 0);
                }

                var baseWorldPosition = V.WorldPosition + vertex.Position + rampOffset;
                var noise             = VertexNoise.GetNoiseVectorFromRepeatingTexture(baseWorldPosition);
                var localPosition     = Vector3.Transform(vertex.Position + rampOffset + noise, VertexTransform);

                Into.AddVertex(new ExtendedVertex(
                                   V.WorldPosition + localPosition,
                                   vertexColor.AsColor(),
                                   Tint,
                                   UVs.Uvs[faceDescriptor.VertexOffset + faceVertex],
                                   UVs.Bounds[faceDescriptor.IndexOffset / 6]));
            }

            bool flippedQuad = ApplyLighting && (Cache.AmbientValues[0] + Cache.AmbientValues[2] >
                                                 Cache.AmbientValues[1] + Cache.AmbientValues[3]);

            for (int idx = faceDescriptor.IndexOffset; idx < faceDescriptor.IndexCount +
                 faceDescriptor.IndexOffset; idx++)
            {
                ushort offset  = flippedQuad ? Primitive.FlippedIndexes[idx] : Primitive.Indexes[idx];
                ushort offset0 = flippedQuad ? Primitive.FlippedIndexes[faceDescriptor.IndexOffset] : Primitive.Indexes[faceDescriptor.IndexOffset];
                Into.AddIndex((short)(indexOffset + offset - offset0));
            }
        }