Example #1
0
        public IEnumerable <Body> EnumerateIntersectingObjects(BoundingBox box, CollisionType queryType)
        {
            PerformanceMonitor.PushFrame("CollisionManager.EnumerateIntersectingObjects");
            var hash = new HashSet <Body>();

            OctTree.EnumerateItems(box, hash, t => (t.CollisionType & queryType) == t.CollisionType);
            PerformanceMonitor.PopFrame();
            return(hash);
        }
Example #2
0
        public void RenderInstances(
            GraphicsDevice Device,
            Shader Effect,
            Camera Camera,
            InstanceRenderer.RenderMode Mode)
        {
            int uniqueInstances = 0;

            RenderPass += 1;
            var frustrum = Camera.GetFrustrum();

            foreach (var item in OctTree.EnumerateItems(frustrum))
            {
                if (!item.Visible)
                {
                    continue;
                }

                if (item.RenderPass < RenderPass)
                {
                    uniqueInstances += 1;
                    Renderer.RenderInstance(item, Device, Effect, Camera, Mode);
                }
                item.RenderPass = RenderPass;
            }

            Renderer.Flush(Device, Effect, Camera, Mode);
            GamePerformance.Instance.TrackValueType("Instances Drawn", uniqueInstances);
        }
Example #3
0
        // Inverts GetMoveActions. So, returns the list of move actions whose target is the current voxel.
        // Very, very slow.
        public IEnumerable <MoveAction> GetInverseMoveActions(MoveState currentstate, OctTreeNode OctTree)
        {
            if (Parent == null)
            {
                yield break;
            }

            var creature = Creature;

            if (creature == null)
            {
                yield break;
            }
            var current = currentstate.Voxel;

            if (Can(MoveType.Teleport))
            {
                var teleportObjects = Parent.Faction.OwnedObjects.Where(obj => obj.Active && obj.Tags.Contains("Teleporter"));
                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.ChunkData, current.Coordinate + new GlobalVoxelOffset(dx, dy, dz));

                                if (teleportNeighbor.IsValid && teleportNeighbor.IsEmpty && !VoxelHelpers.GetNeighbor(teleportNeighbor, new GlobalVoxelOffset(0, -1, 0)).IsEmpty)
                                {
                                    yield return(new MoveAction()
                                    {
                                        InteractObject = obj,
                                        Diff = new Vector3(dx, dx, dz),
                                        SourceVoxel = teleportNeighbor,
                                        DestinationState = currentstate,
                                        MoveType = MoveType.Teleport
                                    });
                                }
                            }
                        }
                    }
                }
            }
            foreach (var v in VoxelHelpers.EnumerateCube(current.Coordinate)
                     .Select(n => new VoxelHandle(current.Chunk.Manager.ChunkData, n))
                     .Where(h => h.IsValid && h.IsEmpty))
            {
                foreach (var a in GetMoveActions(new MoveState()
                {
                    Voxel = v
                }, OctTree).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!
                var bodies = new HashSet <Body>();
                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;
                    }

                    /*
                     * if (!DwarfGame.IsMainThread)
                     * {
                     *  for (int i = 0; i < 1; i++)
                     *  {
                     *      Drawer3D.DrawBox(rail.GetBoundingBox(), Color.Purple, 0.1f, false);
                     *      System.Threading.Thread.Sleep(1);
                     *  }
                     * }
                     */
                    foreach (var neighborRail in rail.NeighborRails.Select(neighbor => creature.Manager.FindComponent(neighbor.NeighborID) as Rail.RailEntity))
                    {
                        var actions = GetMoveActions(new MoveState()
                        {
                            Voxel = v, VehicleState = new VehicleState()
                            {
                                Rail = rail, PrevRail = neighborRail
                            }
                        }, OctTree);
                        foreach (var a in actions.Where(a => a.DestinationState == currentstate))
                        {
                            yield return(a);

                            /*
                             * if (!DwarfGame.IsMainThread && a.MoveType == MoveType.RideVehicle)
                             * {
                             *  for (int i = 0; i < 10; i++)
                             *  {
                             *      Drawer3D.DrawBox(rail.GetBoundingBox(), Color.Red, 0.1f, false);
                             *      System.Threading.Thread.Sleep(1);
                             *  }
                             * }
                             */
                        }
                    }

                    foreach (var a in GetMoveActions(new MoveState()
                    {
                        Voxel = v, VehicleState = new VehicleState()
                        {
                            Rail = rail, PrevRail = null
                        }
                    }, OctTree).Where(a => a.DestinationState == currentstate))
                    {
                        yield return(a);
                    }
                }
            }
        }
Example #4
0
        /// <summary> gets the list of actions that the creature can take from a given voxel. </summary>
        public IEnumerable <MoveAction> GetMoveActions(MoveState state, OctTreeNode OctTree)
        {
            if (Parent == null)
            {
                yield break;
            }

            var voxel = state.Voxel;

            if (!voxel.IsValid || !voxel.IsEmpty)
            {
                yield break;
            }
            var creature = Creature;

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

            var  neighborHood     = GetNeighborhood(voxel.Chunk.Manager.ChunkData, voxel);
            bool inWater          = (neighborHood[1, 1, 1].IsValid && neighborHood[1, 1, 1].LiquidLevel > WaterManager.inWaterThreshold);
            bool standingOnGround = (neighborHood[1, 0, 1].IsValid && !neighborHood[1, 0, 1].IsEmpty);
            bool topCovered       = (neighborHood[1, 2, 1].IsValid && !neighborHood[1, 2, 1].IsEmpty);
            bool hasNeighbors     = HasNeighbors(neighborHood);
            bool isRiding         = state.VehicleState.IsRidingVehicle;

            var neighborHoodBounds = new BoundingBox(neighborHood[0, 0, 0].GetBoundingBox().Min, neighborHood[2, 2, 2].GetBoundingBox().Max);
            var neighborObjects    = new HashSet <Body>();

            OctTree.EnumerateItems(neighborHoodBounds, neighborObjects);
            var successors = EnumerateSuccessors(state, voxel, neighborHood, inWater, standingOnGround, topCovered, hasNeighbors, isRiding, neighborObjects);

            if (Can(MoveType.Teleport))
            {
                var teleportObjects = Parent.Faction.OwnedObjects.Where(obj => obj.Active && obj.Tags.Contains("Teleporter"));
                foreach (var obj in teleportObjects)
                {
                    if ((obj.Position - state.Voxel.WorldPosition).LengthSquared() < TeleportDistanceSquared)
                    {
                        yield return(new MoveAction()
                        {
                            InteractObject = obj,
                            MoveType = MoveType.Teleport,
                            SourceVoxel = voxel,
                            DestinationState = new MoveState()
                            {
                                Voxel = new VoxelHandle(voxel.Chunk.Manager.ChunkData, GlobalVoxelCoordinate.FromVector3(obj.Position))
                            }
                        });
                    }
                }
            }
            // Now, validate each move action that the creature might take.
            foreach (MoveAction v in successors)
            {
                var n = v.DestinationVoxel.IsValid ? v.DestinationVoxel : neighborHood[(int)v.Diff.X, (int)v.Diff.Y, (int)v.Diff.Z];
                if (n.IsValid && (isRiding || n.IsEmpty || n.LiquidLevel > 0))
                {
                    // Do one final check to see if there is an object blocking the motion.
                    bool blockedByObject = false;
                    if (!isRiding)
                    {
                        var objectsAtNeighbor = neighborObjects.Where(o => o.GetBoundingBox().Intersects(n.GetBoundingBox()));

                        // If there is an object blocking the motion, determine if it can be passed through.

                        foreach (var body in objectsAtNeighbor)
                        {
                            var door = body as Door;
                            // ** Doors are in the octtree, pretty sure this was always pointless -- var door = body.GetRoot().EnumerateAll().OfType<Door>().FirstOrDefault();
                            // If there is an enemy door blocking movement, we can destroy it to get through.
                            if (door != null)
                            {
                                if (
                                    creature.World.Diplomacy.GetPolitics(door.TeamFaction, creature.Faction)
                                    .GetCurrentRelationship() ==
                                    Relationship.Hateful)
                                {
                                    if (Can(MoveType.DestroyObject))
                                    {
                                        yield return(new MoveAction
                                        {
                                            Diff = v.Diff,
                                            MoveType = MoveType.DestroyObject,
                                            InteractObject = door,
                                            DestinationVoxel = n,
                                            SourceState = state
                                        });
                                    }
                                    blockedByObject = true;
                                }
                            }
                        }
                    }

                    // If no object blocked us, we can move freely as normal.
                    if (!blockedByObject && n.LiquidType != LiquidType.Lava)
                    {
                        MoveAction newAction = v;
                        newAction.SourceState      = state;
                        newAction.DestinationVoxel = n;
                        yield return(newAction);
                    }
                }
            }
        }
Example #5
0
        // Inverts GetMoveActions. So, returns the list of move actions whose target is the current voxel.
        // Very, very slow.
        public IEnumerable <MoveAction> GetInverseMoveActions(MoveState currentstate, OctTreeNode OctTree, List <Body> 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.ChunkData, current.Coordinate + new GlobalVoxelOffset(dx, dy, dz));

                                if (teleportNeighbor.IsValid && teleportNeighbor.IsEmpty && !VoxelHelpers.GetNeighbor(teleportNeighbor, new GlobalVoxelOffset(0, -1, 0)).IsEmpty)
                                {
                                    yield return(new MoveAction()
                                    {
                                        InteractObject = obj,
                                        Diff = new Vector3(dx, dx, dz),
                                        SourceVoxel = teleportNeighbor,
                                        DestinationState = currentstate,
                                        MoveType = MoveType.Teleport
                                    });
                                }
                            }
                        }
                    }
                }
            }

            var storage = new MoveActionTempStorage();

            foreach (var v in VoxelHelpers.EnumerateCube(current.Coordinate)
                     .Select(n => new VoxelHandle(current.Chunk.Manager.ChunkData, n))
                     .Where(h => h.IsValid))
            {
                foreach (var a in GetMoveActions(new MoveState()
                {
                    Voxel = v
                }, OctTree, 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?
                var bodies = new HashSet <Body>();
                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, VehicleState = new VehicleState()
                            {
                                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, VehicleState = new VehicleState()
                        {
                            Rail = rail, PrevRail = null
                        }
                    }, OctTree, teleportObjects, storage).Where(a => a.DestinationState == currentstate))
                    {
                        yield return(a);
                    }
                }
            }
        }