Ejemplo n.º 1
0
        public virtual void HandleCollisions(bool queryNeighborHood, VoxelHandle[] neighborHood, ChunkManager chunks, float dt)
        {
            if (CollideMode == CollisionMode.None)
            {
                return;
            }

            int y = (int)Position.Y;

            if (CurrentVoxel.IsValid && !CurrentVoxel.IsEmpty)
            {
                var currentBox = CurrentVoxel.GetBoundingBox();
                if (currentBox.Contains(Position) == ContainmentType.Contains)
                {
                    ResolveTerrainCollisionGradientMethod();
                    OnTerrainCollision(CurrentVoxel);
                    return;
                }
            }

            if (queryNeighborHood)
            {
                int i = 0;
                foreach (var v in VoxelHelpers.EnumerateManhattanCube(CurrentVoxel.Coordinate).Select(c => new VoxelHandle(chunks, c)))
                {
                    neighborHood[i] = v;
                    i++;
                }
            }

            foreach (var v in neighborHood)
            {
                if (!v.IsValid || v.IsEmpty)
                {
                    continue;
                }

                if (CollideMode == CollisionMode.UpDown && (int)v.Coordinate.Y == y)
                {
                    continue;
                }

                if (CollideMode == CollisionMode.Sides && (int)v.Coordinate.Y != y)
                {
                    continue;
                }

                if (Collide(v.GetBoundingBox(), dt))
                {
                    OnTerrainCollision(v);
                }
            }
        }
Ejemplo n.º 2
0
        public Zone GetMostLikelyZone(VoxelHandle v)
        {
            foreach (var r in PersistentData.Zones.Where(r => r.ContainsVoxel(v)))
            {
                return(r);
            }

            BoundingBox larger = new BoundingBox(v.GetBoundingBox().Min - new Vector3(0.5f, 0.5f, 0.5f), v.GetBoundingBox().Max + new Vector3(0.5f, 0.5f, 0.5f));

            return((from room in PersistentData.BuildDesignations
                    from buildDesignation in room.VoxelOrders
                    where larger.Intersects(buildDesignation.Voxel.GetBoundingBox())
                    select buildDesignation.ToBuild).FirstOrDefault());
        }
Ejemplo n.º 3
0
        public static IEnumerable <GlobalVoxelCoordinate> BreadthFirstSearchNonBlocking(
            ChunkManager Data,
            GlobalVoxelCoordinate Start,
            float Radius,
            Func <GlobalVoxelCoordinate, bool> IsGoal)
        {
            var queue         = new Queue <GlobalVoxelCoordinate>();
            var visited       = new HashSet <GlobalVoxelCoordinate>();
            var radiusSquared = Radius * Radius;

            queue.Enqueue(Start);
            visited.Add(Start);

            while (queue.Count > 0)
            {
                var current = queue.Dequeue();

                if (IsGoal(current))
                {
                    yield return(current);

                    yield break;
                }

                var delta = current.ToVector3() - Start.ToVector3();
                if (delta.LengthSquared() < radiusSquared)
                {
                    foreach (var neighbor in VoxelHelpers.EnumerateManhattanNeighbors(current))
                    {
                        var v = new VoxelHandle(Data, neighbor);
                        if (!visited.Contains(neighbor) && v.IsValid && v.IsEmpty)
                        {
                            if (Debugger.Switches.DrawPaths)
                            {
                                Drawer3D.DrawBox(v.GetBoundingBox(), Color.Red, 0.1f, true);
                            }
                            visited.Add(neighbor);
                            queue.Enqueue(neighbor);
                        }
                    }
                }
                yield return(new GlobalVoxelCoordinate(-9999, -9999, -9999));
            }
        }
Ejemplo n.º 4
0
 public DestroyOnTimer(ComponentManager Manager, ChunkManager chunkManager, VoxelHandle Voxel) :
     base(Manager, "DestroyTimer", Matrix.CreateTranslation(Voxel.GetBoundingBox().Center()), new Vector3(0.5f, 0.5f, 0.5f), Vector3.Zero)
 {
     this.Voxel = Voxel;
 }
Ejemplo n.º 5
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)
                    {
                        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);
            }
        }
Ejemplo n.º 6
0
        public override void Update(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, Tint);
            }


            bool particlePhysics = GameSettings.Default.ParticlePhysics;

            foreach (Particle p in Particles)
            {
                float vel = p.Velocity.LengthSquared();
                if (!Data.Sleeps || vel > 0.2f)
                {
                    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);
                    }
                    p.Velocity        += Data.ConstantAccel * (float)gameTime.ElapsedGameTime.TotalSeconds;
                    p.Velocity        *= Data.LinearDamping;
                    p.AngularVelocity *= Data.AngularDamping;
                }
                else if (Data.Sleeps && vel < 0.2f)
                {
                    p.Velocity = Vector3.Zero;
                }


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

                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 && v.IsEmpty)
                    {
                        p.Tint = new Color(v.SunColor, 255, 0);
                    }
                }

                if (Data.CollidesWorld && particlePhysics && vel > 0.2f)
                {
                    BoundingBox b = new BoundingBox(p.Position - Vector3.One * p.Scale * 0.5f, p.Position + Vector3.One * p.Scale * 0.5f);
                    if (v.IsValid && !v.IsEmpty)
                    {
                        Physics.Contact contact = new Physics.Contact();
                        if (Physics.TestStaticAABBAABB(b, v.GetBoundingBox(), 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 (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 (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(p);
                    p.InstanceData.Color      = p.Tint;
                }
            }

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


            foreach (var sprites in Sprites)
            {
                sprites.Update(gameTime, camera, chunks.Graphics, chunks.ChunkData.MaxViewingLevel);
            }
            if (Particles.Count > 0)
            {
                base.Update(gameTime, chunks, camera);
            }
        }
Ejemplo n.º 7
0
        public override IEnumerable <Status> Run()
        {
            foreach (var res in Agent.Blackboard.GetData <List <Resource> >(ResourceBlackboardName))
            {
                if (!Creature.Inventory.Contains(res))
                {
                    yield return(Status.Fail);
                }
            }

            foreach (var status in Creature.HitAndWait(1.0f, true, () => Location.Coordinate.ToVector3() + Vector3.One * 0.5f))
            {
                if (status == Status.Running)
                {
                    yield return(status);
                }
            }

            foreach (var res in Agent.Blackboard.GetData <List <Resource> >(ResourceBlackboardName))
            {
                var grabbed = Creature.Inventory.RemoveAndCreate(res, Inventory.RestockType.Any);

                if (grabbed == null)
                {
                    yield return(Status.Fail);

                    yield break;
                }
                else
                {
                    // If the creature intersects the box, find a voxel adjacent to it that is free, and jump there to avoid getting crushed.
                    if (Creature.Physics.BoundingBox.Intersects(Location.GetBoundingBox()))
                    {
                        var neighbors = VoxelHelpers.EnumerateAllNeighbors(Location.Coordinate)
                                        .Select(c => new VoxelHandle(Agent.World.ChunkManager, c));

                        var closest     = VoxelHandle.InvalidHandle;
                        var closestDist = float.MaxValue;
                        foreach (var voxel in neighbors)
                        {
                            if (!voxel.IsValid)
                            {
                                continue;
                            }

                            float dist = (voxel.WorldPosition - Creature.Physics.Position).LengthSquared();
                            if (dist < closestDist && voxel.IsEmpty)
                            {
                                closestDist = dist;
                                closest     = voxel;
                            }
                        }

                        if (closest.IsValid)
                        {
                            TossMotion teleport = new TossMotion(0.5f, 1.0f, Creature.Physics.GlobalTransform, closest.WorldPosition + Vector3.One * 0.5f);
                            Creature.Physics.AnimationQueue.Add(teleport);
                        }
                    }

                    // Todo: Shitbox - what happens if the player saves while this animation is in progress?? How is the OnComplete restored?
                    var motion = new TossMotion(1.0f, 2.0f, grabbed.LocalTransform, Location.Coordinate.ToVector3() + new Vector3(0.5f, 0.5f, 0.5f));
                    if (grabbed.GetRoot().GetComponent <Physics>().HasValue(out var grabbedPhysics))
                    {
                        grabbedPhysics.CollideMode = Physics.CollisionMode.None;
                    }
                    grabbed.AnimationQueue.Add(motion);

                    motion.OnComplete += () => grabbed.Die();
                }

                if (Library.GetVoxelType(VoxelType).HasValue(out var vType))
                {
                    PlaceVoxel(Location, vType, Creature.Manager.World);
                }

                Creature.Stats.NumBlocksPlaced++;
                Creature.AI.AddXP(1);

                yield return(Status.Success);

                yield break;
            }
        }
Ejemplo n.º 8
0
        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);
            }
        }
Ejemplo n.º 9
0
        public override IEnumerable <Status> Run()
        {
            if (!Creature.Faction.Designations.IsVoxelDesignation(Location, DesignationType.Put))
            {
                yield return(Status.Success);

                yield break;
            }

            if (!Creature.Inventory.HasResource(Resource))
            {
                yield return(Status.Fail);
            }

            foreach (var status in Creature.HitAndWait(1.0f, true, () => Location.Coordinate.ToVector3() + Vector3.One * 0.5f))
            {
                if (!Creature.Faction.Designations.IsVoxelDesignation(Location, DesignationType.Put))
                {
                    yield return(Status.Success);

                    yield break;
                }
                if (status == Status.Running)
                {
                    yield return(status);
                }
            }

            var grabbed = Creature.Inventory.RemoveAndCreate(Resource,
                                                             Inventory.RestockType.Any).FirstOrDefault();

            if (grabbed == null)
            {
                yield return(Status.Fail);

                yield break;
            }
            else
            {
                if (Creature.Faction.Designations.IsVoxelDesignation(Location, DesignationType.Put))
                {
                    // If the creature intersects the box, find a voxel adjacent to it that is free, and jump there to avoid getting crushed.
                    if (Creature.Physics.BoundingBox.Intersects(Location.GetBoundingBox()))
                    {
                        var neighbors = VoxelHelpers.EnumerateAllNeighbors(Location.Coordinate)
                                        .Select(c => new VoxelHandle(Agent.Chunks.ChunkData, c));

                        var   closest     = VoxelHandle.InvalidHandle;
                        float closestDist = float.MaxValue;
                        foreach (var voxel in neighbors)
                        {
                            if (!voxel.IsValid)
                            {
                                continue;
                            }

                            float dist = (voxel.WorldPosition - Creature.Physics.Position).LengthSquared();
                            if (dist < closestDist && voxel.IsEmpty)
                            {
                                closestDist = dist;
                                closest     = voxel;
                            }
                        }

                        if (closest.IsValid)
                        {
                            TossMotion teleport = new TossMotion(0.5f, 1.0f, Creature.Physics.GlobalTransform, closest.WorldPosition + Vector3.One * 0.5f);
                            Creature.Physics.AnimationQueue.Add(teleport);
                        }
                    }
                    TossMotion motion = new TossMotion(1.0f, 2.0f, grabbed.LocalTransform, Location.Coordinate.ToVector3() + new Vector3(0.5f, 0.5f, 0.5f));
                    grabbed.GetRoot().GetComponent <Physics>().CollideMode = Physics.CollisionMode.None;
                    grabbed.AnimationQueue.Add(motion);


                    var put = Creature.Faction.Designations.GetVoxelDesignation(Location, DesignationType.Put) as short?;
                    if (!put.HasValue)
                    {
                        yield return(Status.Fail);

                        yield break;
                    }
                    var putType = VoxelLibrary.GetVoxelType(put.Value);

                    motion.OnComplete += () =>
                    {
                        grabbed.Die();
                        PlaceVoxel(Location, putType, Creature.Manager.World);

                        Creature.Faction.Designations.RemoveVoxelDesignation(Location, DesignationType.Put);
                        Creature.Stats.NumBlocksPlaced++;
                        Creature.AI.AddXP(1);
                    };

                    yield return(Status.Success);

                    yield break;
                }
                else
                {
                    Creature.Inventory.Pickup(grabbed, Inventory.RestockType.RestockResource);
                    grabbed.Die();

                    yield return(Status.Success);
                }
            }
        }
Ejemplo n.º 10
0
 public ExploredListener(ComponentManager Manager, VoxelHandle Voxel) :
     base(Manager, "ExplorationSpawner", Matrix.CreateTranslation(Voxel.GetBoundingBox().Center()), new Vector3(0.5f, 0.5f, 0.5f), Vector3.Zero)
 {
     this.Voxel         = Voxel;
     this.CollisionType = CollisionType.Static;
 }
Ejemplo n.º 11
0
        public void CheckSurroundings(GameComponent Body, DwarfTime gameTime, ChunkManager chunks)
        {
            if (Heat > Flashpoint)
            {
                var insideBodies = World.EnumerateIntersectingObjects(Body.GetBoundingBox());

                foreach (var body in insideBodies.Where(b => b != Parent && b.Active && b.Parent == Manager.RootComponent))
                {
                    var flames = body.GetComponent <Flammable>();
                    if (flames != null)
                    {
                        flames.Heat += 100;
                    }
                }
                SoundManager.PlaySound(ContentPaths.Audio.fire, Body.Position, true);
            }

            float expansion = Heat > Flashpoint ? 1.0f : 0.0f;

            foreach (var coordinate in VoxelHelpers.EnumerateCoordinatesInBoundingBox(Body.BoundingBox.Expand(expansion)))
            {
                var voxel = new VoxelHandle(chunks, coordinate);
                if (!voxel.IsValid)
                {
                    continue;
                }

                if (Heat > Flashpoint && MathFunctions.RandEvent(0.5f))
                {
                    if (voxel.Type.IsFlammable)
                    {
                        if (MathFunctions.RandEvent(0.1f))
                        {
                            var existingItems = World.EnumerateIntersectingObjects(voxel.GetBoundingBox().Expand(-0.1f));


                            if (!existingItems.Any(e => e is Fire))
                            {
                                EntityFactory.CreateEntity <Fire>("Fire", voxel.GetBoundingBox().Center());
                            }
                            SoundManager.PlaySound(ContentPaths.Audio.Oscar.sfx_env_lava_spread, voxel.GetBoundingBox().Center(), true, 1.0f);
                            VoxelHelpers.KillVoxel(World, voxel);
                        }
                    }

                    if (voxel.GrassType != 0x0)
                    {
                        if (MathFunctions.RandEvent(0.1f))
                        {
                            var box = voxel.GetBoundingBox().Expand(-0.1f);
                            box.Min += Vector3.One; // Todo: Why shifting one on every axis?
                            box.Max += Vector3.One;
                            if (!World.EnumerateIntersectingObjects(box).Any(e => e is Fire))
                            {
                                EntityFactory.CreateEntity <Fire>("Fire", box.Center());
                            }
                        }

                        if (MathFunctions.RandEvent(0.5f))
                        {
                            SoundManager.PlaySound(ContentPaths.Audio.Oscar.sfx_env_lava_spread, voxel.GetBoundingBox().Center(), true, 1.0f);
                            voxel.GrassType = 0x0;
                        }
                    }
                }

                if (voxel.LiquidLevel <= 0)
                {
                    continue;
                }
                if (voxel.LiquidType == LiquidType.Lava)
                {
                    Heat += 100.0f;
                }
                else if (voxel.LiquidType == LiquidType.Water)
                {
                    Heat = Heat * 0.25f;
                }
            }
        }
Ejemplo n.º 12
0
        private bool ValidatePlanting(VoxelHandle voxel)
        {
            if (!voxel.Type.IsSoil)
            {
                Player.World.ShowTooltip("Can only plant on soil!");
                return(false);
            }

            if (ResourceLibrary.Resources[PlantType].Tags.Contains(Resource.ResourceTags.AboveGroundPlant))
            {
                if (voxel.Sunlight == false)
                {
                    Player.World.ShowTooltip("Can only plant " + PlantType + " above ground.");
                    return(false);
                }
            }
            else if (ResourceLibrary.Resources[PlantType].Tags.Contains(Resource.ResourceTags.BelowGroundPlant))
            {
                if (voxel.Sunlight)
                {
                    Player.World.ShowTooltip("Can only plant " + PlantType + " below ground.");
                    return(false);
                }
            }

            var designation = Player.Faction.Designations.GetVoxelDesignation(voxel, DesignationType.Plant);

            if (designation != null)
            {
                Player.World.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    = Player.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 Body).GetBoundingBox(), Color.Yellow, 0.03f, false);
                    }
                }

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

            // We have to shrink the bounding box used because for some reason zones overflow their bounds a little during their collision check.
            if (Player.Faction.GetIntersectingRooms(voxel.GetBoundingBox().Expand(-0.2f)).Count > 0)
            {
                Player.World.ShowTooltip("Can't plant inside zones.");
                return(false);
            }

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

            return(true);
        }
Ejemplo n.º 13
0
        /// <summary> gets the list of actions that the creature can take from a given voxel. </summary>
        public IEnumerable <MoveAction> GetMoveActions(VoxelHandle voxel)
        {
            if (!voxel.IsValid || !voxel.IsEmpty)
            {
                yield break;
            }

            CollisionManager objectHash = Creature.Manager.World.CollisionManager;

            var  neighborHood     = GetNeighborhood(voxel);
            bool inWater          = (neighborHood[1, 1, 1].IsValid && neighborHood[1, 1, 1].WaterCell.WaterLevel > 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 isClimbing       = false;

            var successors = new List <MoveAction>();

            if (CanClimb)
            {
                //Climbing ladders.
                var bodies = objectHash.EnumerateIntersectingObjects(voxel.GetBoundingBox(), CollisionManager.CollisionType.Static).OfType <GameComponent>();

                var ladder = bodies.FirstOrDefault(component => component.Tags.Contains("Climbable"));

                // if the creature can climb objects and a ladder is in this voxel,
                // then add a climb action.
                if (ladder != null)
                {
                    successors.Add(new MoveAction
                    {
                        Diff           = new Vector3(1, 2, 1),
                        MoveType       = MoveType.Climb,
                        InteractObject = ladder
                    });

                    isClimbing = true;

                    if (!standingOnGround)
                    {
                        successors.Add(new MoveAction
                        {
                            Diff           = new Vector3(1, 0, 1),
                            MoveType       = MoveType.Climb,
                            InteractObject = ladder
                        });
                    }

                    standingOnGround = true;
                }
            }

            // If the creature can climb walls and is not blocked by a voxl above.
            if (CanClimbWalls && !topCovered)
            {
                var walls = new VoxelHandle[]
                {
                    neighborHood[2, 1, 1], neighborHood[0, 1, 1], neighborHood[1, 1, 2],
                    neighborHood[1, 1, 0]
                };

                var wall = VoxelHandle.InvalidHandle;
                foreach (var w in walls)
                {
                    if (w.IsValid && !w.IsEmpty)
                    {
                        wall = w;
                    }
                }

                if (wall.IsValid)
                {
                    isClimbing = true;
                    successors.Add(new MoveAction
                    {
                        Diff        = new Vector3(1, 2, 1),
                        MoveType    = MoveType.ClimbWalls,
                        ActionVoxel = wall
                    });

                    if (!standingOnGround)
                    {
                        successors.Add(new MoveAction
                        {
                            Diff        = new Vector3(1, 0, 1),
                            MoveType    = MoveType.ClimbWalls,
                            ActionVoxel = wall
                        });
                    }
                }
            }

            // 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 (!neighborHood[0, 1, 1].IsValid || neighborHood[0, 1, 1].IsEmpty)
                {
                    // +- x
                    successors.Add(new MoveAction
                    {
                        Diff     = new Vector3(0, 1, 1),
                        MoveType = moveType
                    });
                }

                if (!neighborHood[2, 1, 1].IsValid || neighborHood[2, 1, 1].IsEmpty)
                {
                    successors.Add(new MoveAction
                    {
                        Diff     = new Vector3(2, 1, 1),
                        MoveType = moveType
                    });
                }

                if (!neighborHood[1, 1, 0].IsValid || neighborHood[1, 1, 0].IsEmpty)
                {
                    // +- z
                    successors.Add(new MoveAction
                    {
                        Diff     = new Vector3(1, 1, 0),
                        MoveType = moveType
                    });
                }

                if (!neighborHood[1, 1, 2].IsValid || neighborHood[1, 1, 2].IsEmpty)
                {
                    successors.Add(new MoveAction
                    {
                        Diff     = new Vector3(1, 1, 2),
                        MoveType = moveType
                    });
                }

                // Only bother worrying about 8-connected movement if there are
                // no full neighbors around the voxel.
                if (!hasNeighbors)
                {
                    if (!neighborHood[2, 1, 2].IsValid || neighborHood[2, 1, 2].IsEmpty)
                    {
                        // +x + z
                        successors.Add(new MoveAction
                        {
                            Diff     = new Vector3(2, 1, 2),
                            MoveType = moveType
                        });
                    }

                    if (!neighborHood[2, 1, 0].IsValid || neighborHood[2, 1, 0].IsEmpty)
                    {
                        successors.Add(new MoveAction
                        {
                            Diff     = new Vector3(2, 1, 0),
                            MoveType = moveType
                        });
                    }

                    if (!neighborHood[0, 1, 2].IsValid || neighborHood[0, 1, 2].IsEmpty)
                    {
                        // -x -z
                        successors.Add(new MoveAction
                        {
                            Diff     = new Vector3(0, 1, 2),
                            MoveType = moveType
                        });
                    }

                    if (!neighborHood[0, 1, 0].IsValid || neighborHood[0, 1, 0].IsEmpty)
                    {
                        successors.Add(new MoveAction
                        {
                            Diff     = new Vector3(0, 1, 0),
                            MoveType = moveType
                        });
                    }
                }
            }

            // 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 (neighborHood[dx, 1, dz].IsValid && !neighborHood[dx, 1, dz].IsEmpty)
                        {
                            successors.Add(new MoveAction
                            {
                                Diff     = new Vector3(dx, 2, dz),
                                MoveType = MoveType.Jump
                            });
                        }
                    }
                }
            }


            // 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)
            {
                successors.Add(new MoveAction
                {
                    Diff     = new Vector3(1, 0, 1),
                    MoveType = MoveType.Fall
                });
            }

            // 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 (!neighborHood[dx, 1, dz].IsValid || neighborHood[dx, 1, dz].IsEmpty)
                            {
                                successors.Add(new MoveAction
                                {
                                    Diff     = new Vector3(dx, dy, dz),
                                    MoveType = MoveType.Fly
                                });
                            }
                        }
                    }
                }
            }

            // Now, validate each move action that the creature might take.
            foreach (MoveAction v in successors)
            {
                var n = neighborHood[(int)v.Diff.X, (int)v.Diff.Y, (int)v.Diff.Z];
                if (n.IsValid && (n.IsEmpty || n.WaterCell.WaterLevel > 0))
                {
                    // Do one final check to see if there is an object blocking the motion.
                    bool blockedByObject   = false;
                    var  objectsAtNeighbor = Creature.Manager.World.CollisionManager.EnumerateIntersectingObjects(
                        n.GetBoundingBox(), CollisionManager.CollisionType.Static);

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

                    foreach (var body in objectsAtNeighbor.OfType <GameComponent>())
                    {
                        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.Loving)
                            {
                                if (Can(MoveType.DestroyObject))
                                {
                                    yield return(new MoveAction
                                    {
                                        Diff = v.Diff,
                                        MoveType = MoveType.DestroyObject,
                                        InteractObject = door,
                                        DestinationVoxel = n,
                                        SourceVoxel = voxel
                                    });
                                }
                                blockedByObject = true;
                            }
                        }
                    }

                    // If no object blocked us, we can move freely as normal.
                    if (!blockedByObject)
                    {
                        MoveAction newAction = v;
                        newAction.SourceVoxel      = voxel;
                        newAction.DestinationVoxel = n;
                        yield return(newAction);
                    }
                }
            }
        }
Ejemplo n.º 14
0
        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);
                }
            }

            var designation = World.PersistentData.Designations.GetVoxelDesignation(voxel, DesignationType.Plant);

            if (designation != null)
            {
                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);
        }
Ejemplo n.º 15
0
        private IEnumerable <MoveAction> EnumerateSuccessors(MoveState state, VoxelHandle voxel, VoxelHandle[,,] neighborHood, bool inWater, bool standingOnGround, bool topCovered, bool hasNeighbors, bool isRiding, HashSet <Body> neighborObjects)
        {
            bool isClimbing = false;

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

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

                if (!isRiding)
                {
                    var ladder = bodies.FirstOrDefault(component => component.Tags.Contains("Climbable"));

                    // if the creature can climb objects and a ladder is in this voxel,
                    // then add a climb action.
                    if (ladder != null && CanClimb)
                    {
                        yield return(new MoveAction
                        {
                            Diff = new Vector3(1, 2, 1),
                            MoveType = MoveType.Climb,
                            InteractObject = ladder
                        });

                        if (!standingOnGround)
                        {
                            yield return(new MoveAction
                            {
                                Diff = new Vector3(1, 0, 1),
                                MoveType = MoveType.Climb,
                                InteractObject = ladder
                            });
                        }
                        standingOnGround = true;
                    }
                }

                if (!isRiding)
                {
                    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()
                                    {
                                        VehicleState = new VehicleState()
                                        {
                                            Rail = rail
                                        },
                                        Voxel = rail.GetContainingVoxel()
                                    },
                                    MoveType = MoveType.EnterVehicle,
                                    Diff = new Vector3(1, 1, 1)
                                });
                            }
                        }
                    }
                }

                if (Can(MoveType.ExitVehicle) && isRiding)
                {
                    yield return(new MoveAction()
                    {
                        SourceState = state,
                        DestinationState = new MoveState()
                        {
                            VehicleState = new VehicleState(),
                            Voxel = state.Voxel
                        },
                        MoveType = MoveType.ExitVehicle,
                        Diff = new Vector3(1, 1, 1)
                    });
                }

                if (Can(MoveType.RideVehicle) && isRiding)
                {
                    foreach (var neighbor in Rail.RailHelper.EnumerateForwardNetworkConnections(state.VehicleState.PrevRail, state.VehicleState.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(),
                                VehicleState = new VehicleState()
                                {
                                    Rail = neighborRail,
                                    PrevRail = state.VehicleState.Rail
                                }
                            },
                            MoveType = MoveType.RideVehicle,
                        });
                    }
                }
            }

            // If the creature can climb walls and is not blocked by a voxl above.
            if (!isRiding && 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 = neighborHood[2, 1, 1];
                if (n211.IsValid && !n211.IsEmpty)
                {
                    wall = n211;
                }
                else
                {
                    var n011 = neighborHood[0, 1, 1];
                    if (n011.IsValid && !n011.IsEmpty)
                    {
                        wall = n011;
                    }
                    else
                    {
                        var n112 = neighborHood[1, 1, 2];
                        if (n112.IsValid && !n112.IsEmpty)
                        {
                            wall = n112;
                        }
                        else
                        {
                            var n110 = neighborHood[1, 1, 0];
                            if (n110.IsValid && !n110.IsEmpty)
                            {
                                wall = n110;
                            }
                        }
                    }
                }

                if (wall.IsValid)
                {
                    isClimbing = true;
                    yield return(new MoveAction
                    {
                        Diff = new Vector3(1, 2, 1),
                        MoveType = MoveType.ClimbWalls,
                        ActionVoxel = wall
                    });

                    if (!standingOnGround)
                    {
                        yield return(new MoveAction
                        {
                            Diff = new Vector3(1, 0, 1),
                            MoveType = MoveType.ClimbWalls,
                            ActionVoxel = wall
                        });
                    }
                }
            }

            // If the creature either can walk or is in water, add the
            // eight-connected free neighbors around the voxel.
            if (!isRiding && ((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 (!neighborHood[0, 1, 1].IsValid || neighborHood[0, 1, 1].IsEmpty)
                {
                    // +- x
                    yield return(new MoveAction
                    {
                        Diff = new Vector3(0, 1, 1),
                        MoveType = moveType
                    });
                }

                if (!neighborHood[2, 1, 1].IsValid || neighborHood[2, 1, 1].IsEmpty)
                {
                    yield return(new MoveAction
                    {
                        Diff = new Vector3(2, 1, 1),
                        MoveType = moveType
                    });
                }

                if (!neighborHood[1, 1, 0].IsValid || neighborHood[1, 1, 0].IsEmpty)
                {
                    // +- z
                    yield return(new MoveAction
                    {
                        Diff = new Vector3(1, 1, 0),
                        MoveType = moveType
                    });
                }

                if (!neighborHood[1, 1, 2].IsValid || neighborHood[1, 1, 2].IsEmpty)
                {
                    yield return(new MoveAction
                    {
                        Diff = new Vector3(1, 1, 2),
                        MoveType = moveType
                    });
                }

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

                    if (!neighborHood[2, 1, 0].IsValid || neighborHood[2, 1, 0].IsEmpty)
                    {
                        yield return(new MoveAction
                        {
                            Diff = new Vector3(2, 1, 0),
                            MoveType = moveType
                        });
                    }

                    if (!neighborHood[0, 1, 2].IsValid || neighborHood[0, 1, 2].IsEmpty)
                    {
                        // -x -z
                        yield return(new MoveAction
                        {
                            Diff = new Vector3(0, 1, 2),
                            MoveType = moveType
                        });
                    }

                    if (!neighborHood[0, 1, 0].IsValid || neighborHood[0, 1, 0].IsEmpty)
                    {
                        yield return(new MoveAction
                        {
                            Diff = new Vector3(0, 1, 0),
                            MoveType = moveType
                        });
                    }
                }
            }

            // 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 (!isRiding && (!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 (neighborHood[dx, 1, dz].IsValid && !neighborHood[dx, 1, dz].IsEmpty)
                        {
                            yield return(new MoveAction
                            {
                                Diff = new Vector3(dx, 2, dz),
                                MoveType = MoveType.Jump
                            });
                        }
                    }
                }
            }


            // If the creature is not in water and is not standing on ground,
            // it can fall one voxel downward in free space.
            if (!isRiding && !inWater && !standingOnGround)
            {
                yield return(new MoveAction
                {
                    Diff = new Vector3(1, 0, 1),
                    MoveType = MoveType.Fall
                });
            }

            // If the creature can fly and is not underwater, it can fly
            // to any adjacent empty cell.
            if (!isRiding && 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 (!neighborHood[dx, 1, dz].IsValid || neighborHood[dx, 1, dz].IsEmpty)
                            {
                                yield return(new MoveAction
                                {
                                    Diff = new Vector3(dx, dy, dz),
                                    MoveType = MoveType.Fly
                                });
                            }
                        }
                    }
                }
            }
        }
Ejemplo n.º 16
0
 private GameComponent GetBodyAt(VoxelHandle voxel, WorldManager World, string tag)
 {
     return(World.EnumerateIntersectingObjects(voxel.GetBoundingBox(),
                                               CollisionType.Static).OfType <GameComponent>().FirstOrDefault(component => component.Tags.Contains(tag)));
 }
Ejemplo n.º 17
0
        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 && Storage.Neighborhood[1, 0, 1].IsValid)
            {
                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;
                if (Storage.Neighborhood[2, 1, 1].IsValid && !Storage.Neighborhood[2, 1, 1].IsEmpty)
                {
                    wall = Storage.Neighborhood[2, 1, 1];
                }
                else if (Storage.Neighborhood[0, 1, 1].IsValid && !Storage.Neighborhood[0, 1, 1].IsEmpty)
                {
                    wall = Storage.Neighborhood[0, 1, 1];
                }
                else if (Storage.Neighborhood[1, 1, 2].IsValid && !Storage.Neighborhood[1, 1, 2].IsEmpty)
                {
                    wall = Storage.Neighborhood[1, 1, 2];
                }
                else if (Storage.Neighborhood[1, 1, 0].IsValid && !Storage.Neighborhood[1, 1, 0].IsEmpty)
                {
                    wall = Storage.Neighborhood[1, 1, 0];
                }

                if (wall.IsValid)
                {
                    isClimbing = true;

                    if (Storage.Neighborhood[1, 2, 1].IsValid)
                    {
                        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 && Storage.Neighborhood[1, 0, 1].IsValid)
                    {
                        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)
                        {
                            // Check to see if there is headspace for a higher jump.

                            //var highAbove = state.Voxel.Chunk.Manager.CreateVoxelHandle(Storage.Neighborhood[dx, 1, dz].Coordinate + new GlobalVoxelOffset(0, 2, 0));
                            //if (highAbove.IsValid && highAbove.IsEmpty)
                            //    yield return new MoveAction
                            //    {
                            //        SourceState = state,
                            //        Diff = new Vector3(dx, 2, dz),
                            //        MoveType = MoveType.HighJump,
                            //        DestinationVoxel = Storage.Neighborhood[dx, 2, dz],
                            //        CostMultiplier = 1.0f
                            //    };
                            //else
                            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
             *      });
             *  }
             * }
             */
        }
Ejemplo n.º 18
0
        public void WalkUpdate(DwarfTime time, ChunkManager chunks)
        {
            {
                var mouseState = Mouse.GetState();
                if (!GameState.Game.GraphicsDevice.Viewport.Bounds.Contains(mouseState.X, mouseState.Y))
                {
                    return;
                }
            }
            // Don't attempt any camera control if the user is trying to type intoa focus item.
            if (World.UserInterface.Gui.FocusItem != null && !World.UserInterface.Gui.FocusItem.IsAnyParentTransparent() && !World.UserInterface.Gui.FocusItem.IsAnyParentHidden())
            {
                return;
            }

            if (GameSettings.Default.FogofWar)
            {
                var currentCoordinate = GlobalVoxelCoordinate.FromVector3(Position);
                if (currentCoordinate != _prevVoxelCoord)
                {
                    VoxelHelpers.RadiusReveal(chunks, new VoxelHandle(chunks, currentCoordinate), 10);
                    _prevVoxelCoord = currentCoordinate;
                }
            }

            float   diffPhi   = 0;
            float   diffTheta = 0;
            Vector3 forward   = (Target - Position);

            forward.Normalize();
            Vector3 right = Vector3.Cross(forward, UpVector);
            Vector3 up    = Vector3.Cross(right, forward);

            right.Normalize();
            up.Normalize();
            MouseState    mouse  = Mouse.GetState();
            KeyboardState keys   = Keyboard.GetState();
            var           bounds = new BoundingBox(World.ChunkManager.Bounds.Min, World.ChunkManager.Bounds.Max + Vector3.UnitY * 20);

            ZoomTargets.Clear();

            Target = MathFunctions.Clamp(Target, bounds);

            float diffX, diffY = 0;
            float dt = (float)time.ElapsedRealTime.TotalSeconds;

            SnapToBounds(new BoundingBox(World.ChunkManager.Bounds.Min, World.ChunkManager.Bounds.Max + Vector3.UnitY * 20));

            bool switchState = false;

            bool isAnyRotationKeyActive = keys.IsKeyDown(ControlSettings.Mappings.CameraMode) ||
                                          keys.IsKeyDown(Keys.RightShift) || Mouse.GetState().MiddleButton == ButtonState.Pressed;

            if (isAnyRotationKeyActive && !shiftPressed)
            {
                shiftPressed      = true;
                mouseOnRotate     = GameState.Game.GraphicsDevice.Viewport.Bounds.Center;
                mousePrerotate    = new Point(mouse.X, mouse.Y);
                switchState       = true;
                mouseActiveInWalk = !mouseActiveInWalk;
            }
            else if (!isAnyRotationKeyActive && shiftPressed)
            {
                shiftPressed = false;
            }

            if (shiftPressed)
            {
                Mouse.SetPosition(mousePrerotate.X, mousePrerotate.Y);
                KeyManager.TrueMousePos = new Point(mousePrerotate.X, mousePrerotate.Y);
            }
            else
            {
                KeyManager.TrueMousePos = new Point(mouse.X, mouse.Y);
            }

            if (KeyManager.RotationEnabled(this))
            {
                World.UserInterface.Gui.MouseVisible = false;
                Mouse.SetPosition(mouseOnRotate.X, mouseOnRotate.Y);

                if (!switchState)
                {
                    diffX = mouse.X - mouseOnRotate.X;
                    diffY = mouse.Y - mouseOnRotate.Y;
                }
                else
                {
                    diffX = 0;
                    diffY = 0;
                }

                if (!isLeftPressed && mouse.LeftButton == ButtonState.Pressed)
                {
                    isLeftPressed = true;
                }
                else if (mouse.LeftButton == ButtonState.Released)
                {
                    isLeftPressed = false;
                }

                if (!isRightPressed && mouse.RightButton == ButtonState.Pressed)
                {
                    isRightPressed = true;
                }
                else if (mouse.RightButton == ButtonState.Released)
                {
                    isRightPressed = false;
                }



                if (!isRightPressed)
                {
                    float filterDiffX = (float)(diffX * dt);
                    float filterDiffY = (float)(diffY * dt);

                    diffTheta = (filterDiffX);
                    diffPhi   = -(filterDiffY);
                }
                KeyManager.TrueMousePos = mousePrerotate;
            }
            else
            {
                World.UserInterface.Gui.MouseVisible = true;
            }

            Vector3 velocityToSet = Vector3.Zero;

            if (EnableControl)
            {
                if (keys.IsKeyDown(ControlSettings.Mappings.Forward) || keys.IsKeyDown(Keys.Up))
                {
                    Vector3 mov = forward;
                    mov.Normalize();
                    velocityToSet += mov * CameraMoveSpeed;
                }
                else if (keys.IsKeyDown(ControlSettings.Mappings.Back) || keys.IsKeyDown(Keys.Down))
                {
                    Vector3 mov = forward;
                    mov.Normalize();
                    velocityToSet += -mov * CameraMoveSpeed;
                }

                if (keys.IsKeyDown(ControlSettings.Mappings.Left) || keys.IsKeyDown(Keys.Left))
                {
                    Vector3 mov = right;
                    mov.Normalize();
                    velocityToSet += -mov * CameraMoveSpeed;
                }
                else if (keys.IsKeyDown(ControlSettings.Mappings.Right) || keys.IsKeyDown(Keys.Right))
                {
                    Vector3 mov = right;
                    mov.Normalize();
                    velocityToSet += mov * CameraMoveSpeed;
                }
            }

            if (keys.IsKeyDown(ControlSettings.Mappings.Fly))
            {
                flyKeyPressed = true;
            }
            else
            {
                if (flyKeyPressed)
                {
                    flying = !flying;
                }
                flyKeyPressed = false;
            }

            if (velocityToSet.LengthSquared() > 0)
            {
                if (!flying)
                {
                    float y = Velocity.Y;
                    Velocity = Velocity * 0.5f + 0.5f * velocityToSet;
                    Velocity = new Vector3(Velocity.X, y, Velocity.Z);
                }
                else
                {
                    Velocity = Velocity * 0.5f + 0.5f * velocityToSet;
                }
            }


            LastWheel = mouse.ScrollWheelValue;
            float ymult = flying ? 0.9f : 1.0f;

            Velocity = new Vector3(Velocity.X * 0.9f, Velocity.Y * ymult, Velocity.Z * 0.9f);

            float subSteps      = 10.0f;
            float subStepLength = 1.0f / subSteps;

            crouched = false;
            for (int i = 0; i < subSteps; i++)
            {
                VoxelHandle currentVoxel = new VoxelHandle(World.ChunkManager, GlobalVoxelCoordinate.FromVector3(Position));

                var below = VoxelHelpers.GetNeighbor(currentVoxel, new GlobalVoxelOffset(0, -1, 0));
                var above = VoxelHelpers.GetNeighbor(currentVoxel, new GlobalVoxelOffset(0, 1, 0));
                if (above.IsValid && !above.IsEmpty)
                {
                    crouched = true;
                }

                if (!flying)
                {
                    if (!below.IsValid || below.IsEmpty)
                    {
                        Velocity += dt * Gravity * subStepLength;
                    }
                    else if (keys.IsKeyDown(ControlSettings.Mappings.Jump))
                    {
                        Velocity += -dt * Gravity * subStepLength * 4;
                    }

                    if (currentVoxel.IsValid && currentVoxel.LiquidLevel > 0)
                    {
                        Velocity += -dt * Gravity * subStepLength * 0.999f;

                        if (keys.IsKeyDown(ControlSettings.Mappings.Jump))
                        {
                            Velocity += -dt * Gravity * subStepLength * 0.5f;
                        }
                        Velocity *= 0.99f;
                    }
                }

                if (!CollidesWithChunks(World.ChunkManager, Position, true, true, 0.4f, 0.9f))
                {
                    MoveTarget(Velocity * dt * subStepLength);
                    PushVelocity = Vector3.Zero;
                }
                else
                {
                    MoveTarget(Velocity * dt * subStepLength);
                }
            }
            VoxelHandle voxelAfterMove = new VoxelHandle(World.ChunkManager, GlobalVoxelCoordinate.FromVector3(Position));

            if (voxelAfterMove.IsValid && !voxelAfterMove.IsEmpty)
            {
                float distCenter = (voxelAfterMove.GetBoundingBox().Center() - Position).Length();
                if (distCenter < 0.5f)
                {
                    float       closest      = float.MaxValue;
                    VoxelHandle closestVoxel = VoxelHandle.InvalidHandle;
                    foreach (var voxel in VoxelHelpers.EnumerateAllNeighbors(voxelAfterMove.Coordinate).Select(c => new VoxelHandle(World.ChunkManager, c)).Where(v => v.IsEmpty))
                    {
                        float d = (voxel.GetBoundingBox().Center() - Position).Length();
                        if (d < closest)
                        {
                            closest      = d;
                            closestVoxel = voxel;
                        }
                    }

                    if (closestVoxel.IsValid)
                    {
                        var newPosition = closestVoxel.GetBoundingBox().Center();
                        var diff        = (newPosition - Position);
                        MoveTarget(diff);
                    }
                }
            }

            Target += right * diffTheta * 0.1f;
            var newTarget  = up * diffPhi * 0.1f + Target;
            var newForward = (Target - Position);

            if (Math.Abs(Vector3.Dot(newForward, UpVector)) < 0.99f)
            {
                Target = newTarget;
            }
            var diffTarget = Target - Position;

            diffTarget.Normalize();
            Target = Position + diffTarget * 1.0f;


            UpdateBasisVectors();

            UpdateViewMatrix();
        }
Ejemplo n.º 19
0
        private bool CanPlace(VoxelHandle Location, Rail.JunctionPiece Piece, RailPiece PreviewEntity)
        {
            var actualPosition = new VoxelHandle(Location.Chunk.Manager.ChunkData, Location.Coordinate + new GlobalVoxelOffset(Piece.Offset.X, 0, Piece.Offset.Y));

            if (!actualPosition.IsValid)
            {
                return(false);
            }
            if (!actualPosition.IsEmpty)
            {
                return(false);
            }

            if (actualPosition.Coordinate.Y == 0)
            {
                return(false);                                  // ???
            }
            var local      = actualPosition.Coordinate.GetLocalVoxelCoordinate();
            var voxelUnder = new VoxelHandle(actualPosition.Chunk, new LocalVoxelCoordinate(local.X, local.Y - 1, local.Z));

            if (voxelUnder.IsEmpty)
            {
                return(false);
            }

            foreach (var entity in  Player.World.CollisionManager.EnumerateIntersectingObjects(actualPosition.GetBoundingBox().Expand(-0.2f), CollisionManager.CollisionType.Static))
            {
                if (Object.ReferenceEquals(entity, PreviewEntity))
                {
                    continue;
                }
                if (entity is NewVoxelListener)
                {
                    continue;
                }

                if (FindPossibleCombination(Piece, entity) != null)
                {
                    return(true);
                }

                if (GamePerformance.DebugVisualizationEnabled)
                {
                    Drawer3D.DrawBox(entity.GetBoundingBox(), Color.Yellow, 0.1f, false);
                }

                return(false);
            }

            return(true);
        }