예제 #1
0
        private static VertexColorInfo CalculateVertexLight(VoxelHandle Vox, VoxelVertex Vertex,
                                                            ChunkManager chunks)
        {
            int neighborsEmpty   = 0;
            int neighborsChecked = 0;

            var color = new VertexColorInfo();

            color.DynamicColor = 0;
            color.SunColor     = 0;

            foreach (var c in VoxelHelpers.EnumerateVertexNeighbors(Vox.Coordinate, Vertex))
            {
                var v = new VoxelHandle(chunks.ChunkData, c);
                if (!v.IsValid)
                {
                    continue;
                }

                color.SunColor += v.SunColor;
                if (!v.IsEmpty || !v.IsExplored)
                {
                    if (v.Type.EmitsLight)
                    {
                        color.DynamicColor = 255;
                    }
                    neighborsEmpty   += 1;
                    neighborsChecked += 1;
                }
                else
                {
                    neighborsChecked += 1;
                }
            }

            float proportionHit = (float)neighborsEmpty / (float)neighborsChecked;

            color.AmbientColor = (int)Math.Min((1.0f - proportionHit) * 255.0f, 255);
            color.SunColor     = (int)Math.Min((float)color.SunColor / (float)neighborsChecked, 255);

            return(color);
        }
예제 #2
0
        private Vector3 ProjectToSurface(Vector3 pos)
        {
            var vox = VoxelHelpers.FindFirstVisibleVoxelOnRay(World.ChunkManager,
                                                              new Vector3(pos.X, World.WorldSizeInVoxels.Y - 1, pos.Z),
                                                              new Vector3(pos.X, 0, pos.Z));

            if (!vox.IsValid)
            {
                return(pos);
            }

            var diffY = (vox.WorldPosition.Y + 0.5f) - pos.Y;

            if (Math.Abs(diffY) > 10)
            {
                diffY = Math.Sign(diffY) * 10;
            }

            return(new Vector3(pos.X, pos.Y + diffY, pos.Z));
        }
예제 #3
0
        public Flag(ComponentManager Manager, Vector3 position, CompanyInformation logo) :
            base(Manager, "Flag", Matrix.CreateTranslation(position), new Vector3(1.0f, 1.0f, 1.0f), Vector3.Zero)
        {
            this.Logo = logo;

            Tags.Add("Flag");

            var voxelUnder = VoxelHelpers.FindFirstVoxelBelow(new VoxelHandle(
                                                                  Manager.World.ChunkManager.ChunkData,
                                                                  GlobalVoxelCoordinate.FromVector3(position)));

            if (voxelUnder.IsValid)
            {
                AddChild(new VoxelListener(Manager, Manager.World.ChunkManager,
                                           voxelUnder));
            }

            CollisionType = CollisionManager.CollisionType.Static;
            CreateCosmeticChildren(Manager);
        }
예제 #4
0
        public virtual void OrientToWalls()
        {
            Orient(0);
            var curr = new VoxelHandle(Manager.World.ChunkManager.ChunkData,
                                       GlobalVoxelCoordinate.FromVector3(LocalTransform.Translation));

            if (curr.IsValid)
            {
                foreach (var n in VoxelHelpers.EnumerateManhattanNeighbors2D(curr.Coordinate))
                {
                    var v = new VoxelHandle(World.ChunkManager.ChunkData, n);
                    if (v.IsValid && !v.IsEmpty)
                    {
                        Vector3 diff = n.ToVector3() - curr.WorldPosition;
                        Orient((float)Math.Atan2(diff.X, diff.Z));
                        break;
                    }
                }
            }
        }
예제 #5
0
        public Bed(ComponentManager manager, Vector3 position) :
            base(manager, "Bed", Matrix.CreateTranslation(position), new Vector3(1.5f, 0.5f, 0.75f), new Vector3(-0.5f + 1.5f * 0.5f, -0.5f + 0.25f, -0.5f + 0.75f * 0.5f))
        {
            Tags.Add("Bed");
            CollisionType = CollisionManager.CollisionType.Static;

            var voxelUnder = VoxelHelpers.FindFirstVoxelBelow(new VoxelHandle(
                                                                  manager.World.ChunkManager.ChunkData,
                                                                  GlobalVoxelCoordinate.FromVector3(position)));

            if (voxelUnder.IsValid)
            {
                AddChild(new VoxelListener(manager, manager.World.ChunkManager,
                                           voxelUnder));
            }

            CreateCosmeticChildren(manager);

            OrientToWalls();
        }
예제 #6
0
        public override Feasibility IsFeasible(Creature agent)
        {
            if (!agent.Stats.IsTaskAllowed(Task.TaskCategory.Dig))
            {
                return(Feasibility.Infeasible);
            }

            if (!VoxelToKill.IsValid || VoxelToKill.IsEmpty || VoxelToKill.Health <= 0)
            {
                return(Feasibility.Infeasible);
            }

            if (agent.AI.Status.IsAsleep)
            {
                return(Feasibility.Infeasible);
            }

            return(agent.Faction.Designations.IsVoxelDesignation(VoxelToKill, DesignationType.Dig) &&
                   !VoxelHelpers.VoxelIsCompletelySurrounded(VoxelToKill) ? Feasibility.Feasible : Feasibility.Infeasible);
        }
예제 #7
0
        public void CheckForLavaAndWater(Body Body, DwarfTime gameTime, ChunkManager chunks)
        {
            foreach (var coordinate in VoxelHelpers.EnumerateCoordinatesInBoundingBox(Body.BoundingBox))
            {
                var voxel = new VoxelHandle(chunks.ChunkData, coordinate);
                if (!voxel.IsValid || voxel.LiquidLevel == 0)
                {
                    continue;
                }

                if (voxel.LiquidType == LiquidType.Lava)
                {
                    Heat += 100.0f;
                }
                else if (voxel.LiquidType == LiquidType.Water)
                {
                    Heat = Math.Max(0.0f, Heat - 100.0f);
                }
            }
        }
예제 #8
0
        public static bool BreadthFirstSearch(
            ChunkData Data,
            GlobalVoxelCoordinate Start,
            float Radius,
            Func <GlobalVoxelCoordinate, bool> IsGoal,
            out GlobalVoxelCoordinate Result)
        {
            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))
                {
                    Result = current;
                    return(true);
                }

                var delta = current.ToVector3() - Start.ToVector3();
                if (delta.LengthSquared() < radiusSquared)
                {
                    foreach (var neighbor in VoxelHelpers.EnumerateManhattanNeighbors(current))
                    {
                        if (!visited.Contains(neighbor))
                        {
                            visited.Add(neighbor);
                            queue.Enqueue(neighbor);
                        }
                    }
                }
            }

            Result = new GlobalVoxelCoordinate(0, 0, 0);
            return(false);
        }
예제 #9
0
        public Chair(ComponentManager manager, Vector3 position) :
            base(manager, "Chair", Matrix.Identity, new Vector3(1.0f, 1.0f, 1.0f), Vector3.Zero)
        {
            var matrix = Matrix.CreateRotationY((float)Math.PI * 0.5f);

            matrix.Translation = position - new Vector3(0, 0.22f, 0);
            LocalTransform     = matrix;

            Initialize(Manager);
            CreateCosmeticChildren(Manager);

            var voxelUnder = VoxelHelpers.FindFirstVoxelBelow(new VoxelHandle(
                                                                  manager.World.ChunkManager.ChunkData,
                                                                  GlobalVoxelCoordinate.FromVector3(position)));

            if (voxelUnder.IsValid)
            {
                AddChild(new VoxelListener(manager, manager.World.ChunkManager,
                                           voxelUnder));
            }
        }
예제 #10
0
        override public void Update(DwarfTime gameTime, ChunkManager chunks, Camera camera)
        {
            base.Update(gameTime, chunks, camera);

            if (!Active)
            {
                return;
            }

            SenseTimer.Update(gameTime);

            if (SenseTimer.HasTriggered)
            {
                Creatures.Clear();

                var myRoot = GetRoot();

                foreach (var body in Manager.World.EnumerateIntersectingObjects(BoundingBox, b => b.Active && !Object.ReferenceEquals(b, myRoot) && b.IsRoot()))
                {
                    if (body.GetComponent <Creature>().HasValue(out var minion))
                    {
                        float dist = (body.Position - GlobalTransform.Translation).LengthSquared();

                        if (dist > SenseRadius)
                        {
                            continue;
                        }

                        if (CheckLineOfSight && VoxelHelpers.DoesRayHitSolidVoxel(Manager.World.ChunkManager, Position, body.Position))
                        {
                            continue;
                        }

                        Creatures.Add(minion);
                    }
                }
            }

            Creatures.RemoveAll(ai => ai.IsDead);
        }
예제 #11
0
        public static bool VoxelIsCompletelySurrounded(VoxelHandle V)
        {
            if (V.Chunk == null)
            {
                return(false);
            }

            foreach (var neighborCoordinate in VoxelHelpers.EnumerateManhattanNeighbors(V.Coordinate))
            {
                var voxelHandle = new VoxelHandle(V.Chunk.Manager.ChunkData, neighborCoordinate);
                if (!voxelHandle.IsValid)
                {
                    return(false);
                }
                if (voxelHandle.IsEmpty)
                {
                    return(false);
                }
            }

            return(true);
        }
        public static bool VoxelIsSurroundedByWater(VoxelHandle V)
        {
            if (V.Chunk == null)
            {
                return(false);
            }

            foreach (var neighborCoordinate in VoxelHelpers.EnumerateManhattanNeighbors(V.Coordinate))
            {
                var voxelHandle = new VoxelHandle(V.Chunk.Manager, neighborCoordinate);
                if (!voxelHandle.IsValid)
                {
                    return(false);
                }
                if (voxelHandle.IsEmpty && voxelHandle.LiquidLevel < 4)
                {
                    return(false);
                }
            }

            return(true);
        }
예제 #13
0
        public AddDesignationResult AddVoxelDesignation(VoxelHandle Voxel, DesignationType Type, Object Tag, Task Task)
        {
            lock (designationLock)
            {
                var key = VoxelHelpers.GetVoxelQuickCompare(Voxel);

                List <VoxelDesignation> list = null;
                if (VoxelDesignations.ContainsKey(key))
                {
                    list = VoxelDesignations[key];
                }
                else
                {
                    list = new List <VoxelDesignation>();
                    VoxelDesignations.Add(key, list);
                }

                var existingEntry = list.FirstOrDefault(d => d.Type == Type);

                if (existingEntry != null)
                {
                    existingEntry.Tag = Tag;
                    return(AddDesignationResult.AlreadyExisted);
                }
                else
                {
                    list.Add(new VoxelDesignation
                    {
                        Voxel = Voxel,
                        Type  = Type,
                        Tag   = Tag,
                        Task  = Task
                    });
                    Voxel.Invalidate();
                    return(AddDesignationResult.Added);
                }
            }
        }
예제 #14
0
        public bool CollidesWithChunks(ChunkManager chunks, Vector3 pos, bool applyForce, bool allowInvisible, float size = 0.5f, float height = 2.0f)
        {
            var  box          = new BoundingBox(pos - new Vector3(size, height * 0.5f, size), pos + new Vector3(size, height * 0.5f, size));
            bool gotCollision = false;

            foreach (var v in VoxelHelpers.EnumerateCube(GlobalVoxelCoordinate.FromVector3(pos))
                     .Select(n => new VoxelHandle(chunks, n)))
            {
                if (!v.IsValid)
                {
                    continue;
                }
                if (v.IsEmpty)
                {
                    continue;
                }
                if (!allowInvisible && !v.IsVisible)
                {
                    continue;
                }

                var voxAABB = v.GetBoundingBox();
                if (box.Intersects(voxAABB))
                {
                    gotCollision = true;
                    if (applyForce)
                    {
                        Collide(v, box, voxAABB);
                    }
                    else
                    {
                        return(true);
                    }
                }
            }

            return(gotCollision);
        }
        public static bool DoesVoxelHaveVisibleSurface(WorldManager World, VoxelHandle V)
        {
            if (!V.IsValid)
            {
                return(false);
            }
            if (V.Coordinate.Y >= World.Renderer.PersistentSettings.MaxViewingLevel)
            {
                return(false);
            }
            if (V.IsEmpty)
            {
                return(false);
            }
            if (V.Coordinate.Y == World.Renderer.PersistentSettings.MaxViewingLevel - 1)
            {
                return(true);
            }
            if (V.Coordinate.Y == World.WorldSizeInVoxels.Y - 1)
            {
                return(true);
            }

            foreach (var neighborCoordinate in VoxelHelpers.EnumerateManhattanNeighbors(V.Coordinate))
            {
                var neighbor = new VoxelHandle(World.ChunkManager, neighborCoordinate);
                if (!neighbor.IsValid)
                {
                    return(true);
                }
                if (neighbor.IsEmpty && neighbor.IsExplored)
                {
                    return(true);
                }
            }

            return(false);
        }
예제 #16
0
        public static bool DoesVoxelHaveVisibleSurface(WorldManager World, VoxelHandle V)
        {
            if (!V.IsValid)
            {
                return(false);
            }
            if (V.Coordinate.Y >= World.Master.MaxViewingLevel)
            {
                return(false);
            }
            if (V.IsEmpty)
            {
                return(false);
            }
            if (V.Coordinate.Y == World.Master.MaxViewingLevel - 1)
            {
                return(true);
            }
            if (V.Coordinate.Y == VoxelConstants.ChunkSizeY - 1)
            {
                return(true);
            }

            foreach (var neighborCoordinate in VoxelHelpers.EnumerateManhattanNeighbors(V.Coordinate))
            {
                var neighbor = new VoxelHandle(World.ChunkManager.ChunkData, neighborCoordinate);
                if (!neighbor.IsValid)
                {
                    return(true);
                }
                if (neighbor.IsEmpty && neighbor.IsExplored)
                {
                    return(true);
                }
            }

            return(false);
        }
예제 #17
0
        public override void OnVoxelsSelected(List <VoxelHandle> voxels, InputManager.MouseButton button)
        {
            var parentTask = Player.TaskManager.EnumerateTasks().OfType <GuardZoneTask>().FirstOrDefault();

            if (parentTask == null)
            {
                parentTask = new GuardZoneTask();
                Player.TaskManager.AddTask(parentTask);
            }

            if (button == InputManager.MouseButton.Left)
            {
                foreach (var v in voxels.Where(v => v.IsValid && !v.IsEmpty))
                {
                    var key = VoxelHelpers.GetVoxelQuickCompare(v);
                    if (Player.Faction.GuardedVoxels.ContainsKey(key))
                    {
                        return;
                    }

                    Player.Faction.Designations.AddVoxelDesignation(v, DesignationType.Guard, null, new GuardZoneTask.DesignationProxyTask(parentTask, v));
                    Player.Faction.GuardedVoxels.Add(key, v);
                }

                OnConfirm(Faction.FilterMinionsWithCapability(Player.World.Master.SelectedMinions, Task.TaskCategory.Gather));
            }
            else
            {
                foreach (var v in voxels.Where(v => v.IsValid && !v.IsEmpty))
                {
                    var des = Player.Faction.Designations.GetVoxelDesignation(v, DesignationType.Guard);
                    if (des != null)
                    {
                        Player.TaskManager.CancelTask(des.Task);
                    }
                }
            }
        }
예제 #18
0
        public IEnumerable <VoxelHandle> Select(BoundingBox buffer, Vector3 start, Vector3 end)
        {
            switch (Brush)
            {
            case VoxelBrush.Box:
                return(VoxelHelpers.EnumerateCoordinatesInBoundingBox(buffer)
                       .Select(c => new VoxelHandle(Chunks.ChunkData, c))
                       .Where(v => v.IsValid));

            case VoxelBrush.Shell:
                return(EnumerateShell(buffer)
                       .Select(c => new VoxelHandle(Chunks.ChunkData, c))
                       .Where(v => v.IsValid));

            case VoxelBrush.Stairs:
                return(EnumerateStairVoxels(buffer, start, end, SelectionType == VoxelSelectionType.SelectFilled)
                       .Select(c => new VoxelHandle(Chunks.ChunkData, c))
                       .Where(v => v.IsValid));

            default:
                throw new InvalidOperationException("VoxelBrush has invalid value");
            }
        }
예제 #19
0
        private static BoxTransition ComputeTransitions(
            ChunkData Data,
            VoxelHandle V,
            VoxelType Type)
        {
            if (Type.Transitions == VoxelType.TransitionType.Horizontal)
            {
                var value = ComputeTransitionValueOnPlane(
                    VoxelHelpers.EnumerateManhattanNeighbors2D(V.Coordinate)
                    .Select(c => new VoxelHandle(Data, c)), Type);

                return(new BoxTransition()
                {
                    Top = (TransitionTexture)value
                });
            }
            else
            {
                var transitionFrontBack = ComputeTransitionValueOnPlane(
                    VoxelHelpers.EnumerateManhattanNeighbors2D(V.Coordinate, ChunkManager.SliceMode.Z)
                    .Select(c => new VoxelHandle(Data, c)),
                    Type);

                var transitionLeftRight = ComputeTransitionValueOnPlane(
                    VoxelHelpers.EnumerateManhattanNeighbors2D(V.Coordinate, ChunkManager.SliceMode.X)
                    .Select(c => new VoxelHandle(Data, c)),
                    Type);

                return(new BoxTransition()
                {
                    Front = (TransitionTexture)transitionFrontBack,
                    Back = (TransitionTexture)transitionFrontBack,
                    Left = (TransitionTexture)transitionLeftRight,
                    Right = (TransitionTexture)transitionLeftRight
                });
            }
        }
예제 #20
0
        public override MaybeNull <Act> CreateScript(Creature creature)
        {
            var above = VoxelHelpers.GetVoxelAbove(creature.Physics.CurrentVoxel);

            if ((above.IsValid && above.LiquidLevel > 0) || creature.AI.Movement.CanFly)
            {
                return(new Wrap(() => SwimUp(creature))
                {
                    Name = "Swim up"
                });
            }

            Act fallback = null;

            if (creature.World.EnumerateZones().Count() == 0)
            {
                fallback = new LongWanderAct(creature.AI)
                {
                    PathLength = 20, Radius = 30, Is2D = true, Name = "Randomly wander."
                }
            }
            ;
            else
            {
                fallback = new GoToZoneAct(creature.AI, Datastructures.SelectRandom(creature.World.EnumerateZones()));
            }

            return(new Select(new Sequence(new Wrap(() => FindLandEnum(creature))
            {
                Name = "Search for land."
            },
                                           new GoToNamedVoxelAct("Land", PlanAct.PlanType.Into, creature.AI)),
                              fallback)
            {
                Name = "Find Land"
            });
        }
예제 #21
0
// This is a more expensive terrain collision method that has fewer problems than the box-collision method.
        // It works by stepping the physics object along the gradient of the terrain field until it is out of collision.
        // It will only work if the object is on the edge of the terrain (i.e exactly one voxel in or less).
        public void ResolveTerrainCollisionGradientMethod()
        {
            Vector3 localGradient = Vector3.Zero;

            var p = Position;

            localGradient  = Position - CurrentVoxel.Center;
            localGradient += Velocity; // Prefer to push in the direction we're already going.
            foreach (var v in VoxelHelpers.EnumerateManhattanNeighbors(CurrentVoxel.Coordinate))
            {
                var handle = new VoxelHandle(World.ChunkManager, v);
                var sign   = (handle.IsValid && handle.IsEmpty) ? -1 : 1;
                localGradient += (p - handle.Center) * sign;
            }

            p += localGradient * 0.01f;
            Matrix m = LocalTransform;

            m.Translation  = p;
            LocalTransform = m;
            Velocity      += localGradient * 0.01f;
            PropogateTransforms();
            UpdateBoundingBox();
        }
예제 #22
0
        public override void Update(DwarfTime gameTime, ChunkManager chunks, Camera camera)
        {
            UpdateTimer.Update(gameTime);
            if (UpdateTimer.HasTriggered)
            {
                Body p = (Body)Parent;

                var voxelBelow = new VoxelHandle(chunks.ChunkData,
                                                 GlobalVoxelCoordinate.FromVector3(p.GlobalTransform.Translation
                                                                                   + Vector3.Down * 0.25f));

                if (voxelBelow.IsValid)
                {
                    var shadowTarget = VoxelHelpers.FindFirstVoxelBelow(voxelBelow);

                    if (shadowTarget.IsValid)
                    {
                        var     h   = shadowTarget.Coordinate.Y + 1;
                        Vector3 pos = p.GlobalTransform.Translation;
                        pos.Y = h;
                        float  scaleFactor = GlobalScale / (Math.Max((p.GlobalTransform.Translation.Y - h) * 0.25f, 1));
                        Matrix newTrans    = OriginalTransform;
                        newTrans            *= Matrix.CreateScale(scaleFactor);
                        newTrans.Translation = (pos - p.GlobalTransform.Translation) + new Vector3(0.0f, 0.1f, 0.0f);
                        Tint = new Color(Tint.R, Tint.G, Tint.B, (int)(scaleFactor * 255));
                        Matrix globalRotation = p.GlobalTransform;
                        globalRotation.Translation = Vector3.Zero;
                        LocalTransform             = newTrans * Matrix.Invert(globalRotation);
                    }
                }
                UpdateTimer.HasTriggered = false;
            }


            base.Update(gameTime, chunks, camera);
        }
예제 #23
0
        public List <Body> GenerateRandomSpawn(int numCreatures, Vector3 position)
        {
            if (Race.CreatureTypes.Count == 0)
            {
                return(new List <Body>());
            }

            List <Body> toReturn = new List <Body>();

            for (int i = 0; i < numCreatures; i++)
            {
                string  creature = Race.CreatureTypes[MathFunctions.Random.Next(Race.CreatureTypes.Count)];
                Vector3 offset   = MathFunctions.RandVector3Cube() * 2;

                var voxelUnder = VoxelHelpers.FindFirstVoxelBelowIncludeWater(new VoxelHandle(
                                                                                  World.ChunkManager.ChunkData, GlobalVoxelCoordinate.FromVector3(position + offset)));
                if (voxelUnder.IsValid)
                {
                    var body = EntityFactory.CreateEntity <Body>(creature, voxelUnder.WorldPosition + new Vector3(0.5f, 1, 0.5f));
                    var ai   = body.EnumerateAll().OfType <CreatureAI>().FirstOrDefault();

                    if (ai != null)
                    {
                        ai.Faction.Minions.Remove(ai);

                        Minions.Add(ai);
                        ai.Faction         = this;
                        ai.Creature.Allies = Name;
                    }

                    toReturn.Add(body);
                }
            }

            return(toReturn);
        }
예제 #24
0
        public List <GameComponent> GenerateRandomSpawn(int numCreatures, Vector3 position)
        {
            var r = new List <GameComponent>();

            if (Race.HasValue(out var race))
            {
                if (race.CreatureTypes.Count == 0)
                {
                    return(r);
                }

                for (int i = 0; i < numCreatures; i++)
                {
                    var creature = race.CreatureTypes.SelectRandom();
                    var offset   = MathFunctions.RandVector3Cube() * 2;

                    var voxelUnder = VoxelHelpers.FindFirstVoxelBelowIncludingWater(World.ChunkManager.CreateVoxelHandle(GlobalVoxelCoordinate.FromVector3(position + offset)));
                    if (voxelUnder.IsValid)
                    {
                        var body = EntityFactory.CreateEntity <GameComponent>(creature, voxelUnder.WorldPosition + new Vector3(0.5f, 1, 0.5f));
                        var ai   = body.EnumerateAll().OfType <CreatureAI>().FirstOrDefault();

                        if (ai != null)
                        {
                            ai.Faction.Minions.Remove(ai);
                            Minions.Add(ai);
                            ai.Creature.Faction = this;
                        }

                        r.Add(body);
                    }
                }
            }

            return(r);
        }
예제 #25
0
        private void HandleMouseButton(ButtonState ButtonState, VoxelHandle underMouse, bool newVoxel, bool altPressed, ref bool ButtonPressed, InputManager.MouseButton Button)
        {
            // If the left mouse button is pressed, update the slection buffer.
            if (ButtonPressed)
            {
                // On release, select voxels.
                if (ButtonState == ButtonState.Released)
                {
                    ReleaseSound.Play(World.Renderer.CursorLightPos);
                    ButtonPressed = false;

                    if (SelectionBuffer.Count > 0)
                    {
                        var t = new List <VoxelHandle>(SelectionBuffer);
                        SelectionBuffer.Clear();
                        Selected.Invoke(t, Button);
                    }

                    BoxYOffset        = 0;
                    PrevBoxYOffsetInt = 0;
                }
                // Otherwise, update the selection buffer
                else
                {
                    if (SelectionBuffer.Count == 0)
                    {
                        FirstVoxel = underMouse;
                        SelectionBuffer.Add(underMouse);
                    }
                    else
                    {
                        SelectionBuffer.Clear();
                        SelectionBuffer.Add(FirstVoxel);
                        SelectionBuffer.Add(underMouse);
                        BoundingBox buffer = GetSelectionBox();

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

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

                        if (!altPressed && Brush.CullUnseenVoxels && SelectionType == VoxelSelectionType.SelectFilled)
                        {
                            SelectionBuffer.RemoveAll(v =>
                            {
                                if (v.Equals(underMouse))
                                {
                                    return(false);
                                }
                                if (World.PersistentData.Designations.IsVoxelDesignation(v, DesignationType.Put))
                                {
                                    return(false);                                                                              // Treat put designations as solid.
                                }
                                return(!VoxelHelpers.DoesVoxelHaveVisibleSurface(World, v));
                            });
                        }

                        if (newVoxel)
                        {
                            DragSound.Play(World.Renderer.CursorLightPos, SelectionBuffer.Count / 20.0f);
                            Dragged.Invoke(SelectionBuffer, Button);
                        }
                    }
                }
            }
            // If the mouse was not previously pressed, but is now pressed, then notify us of that.
            else if (ButtonState == ButtonState.Pressed)
            {
                ClickSound.Play(World.Renderer.CursorLightPos);;
                ButtonPressed     = true;
                BoxYOffset        = 0;
                PrevBoxYOffsetInt = 0;
            }
        }
예제 #26
0
        public IEnumerable <Status> PerformStep(MoveAction Step)
        {
            var actionSpeed = GetAgentSpeed(Step.MoveType);

            switch (Step.MoveType)
            {
                #region Ride Elevator
            case MoveType.RideElevator:

                CleanupMinecart();
                var shafts = Step.DestinationState.Tag as Elevators.ElevatorMoveState;
                if (shafts == null || shafts.Entrance == null || shafts.Entrance.IsDead || shafts.Exit == null || shafts.Exit.IsDead)
                {
                    yield return(Status.Fail);
                }

                var shaft = shafts.Entrance.Shaft;
                if (shaft == null || shaft.Invalid)
                {
                    yield return(Status.Fail);
                }

                if (!shaft.EnqueuDwarf(Agent, shafts))
                {
                    yield return(Status.Fail);
                }

                while (!shaft.ReadyToBoard(Agent))
                {
                    if (DeltaTime > 30.0f)
                    {
                        yield return(Status.Fail);    // We waited too long.
                    }
                    if (shaft.Invalid)
                    {
                        yield return(Status.Fail);
                    }

                    SetCharacterMode(CharacterMode.Idle);

                    if (Debugger.Switches.DebugElevators)
                    {
                        Drawer3D.DrawBox(shafts.Entrance.GetBoundingBox(), Color.Red, 0.1f, false);
                        Drawer3D.DrawBox(shafts.Exit.GetBoundingBox(), Color.Red, 0.1f, false);
                        Drawer3D.DrawBox(Step.DestinationVoxel.GetBoundingBox(), Color.Red, 0.1f, false);
                    }

                    yield return(Status.Running);
                }

                DeltaTime = 0;
                foreach (var bit in Translate(Agent.Position, GetPathPoint(shafts.Entrance.GetContainingVoxel()), actionSpeed))
                {
                    if (shaft.Invalid)
                    {
                        yield return(Status.Fail);
                    }

                    shaft.WaitForMe(Agent);

                    SetCharacterMode(CharacterMode.Walking);

                    if (Debugger.Switches.DebugElevators)
                    {
                        Drawer3D.DrawBox(shafts.Entrance.GetBoundingBox(), Color.Green, 0.1f, false);
                        Drawer3D.DrawBox(shafts.Exit.GetBoundingBox(), Color.Green, 0.1f, false);
                        Drawer3D.DrawBox(Step.DestinationVoxel.GetBoundingBox(), Color.Green, 0.1f, false);
                    }
                    yield return(Status.Running);
                }

                shaft.StartMotion(Agent);

                var grav = Creature.Physics.Gravity;
                //Creature.Physics.Gravity = Vector3.Zero;
                while (!shaft.AtDestination(Agent))
                {
                    if (shaft.Invalid)
                    {
                        yield return(Status.Fail);
                    }

                    SetCharacterMode(CharacterMode.Idle);

                    if (Debugger.Switches.DebugElevators)
                    {
                        Drawer3D.DrawBox(shafts.Entrance.GetBoundingBox(), Color.Red, 0.1f, false);
                        Drawer3D.DrawBox(shafts.Exit.GetBoundingBox(), Color.Red, 0.1f, false);
                        Drawer3D.DrawBox(Step.DestinationVoxel.GetBoundingBox(), Color.Red, 0.1f, false);
                    }

                    yield return(Status.Running);
                }

                DeltaTime = 0;
                foreach (var bit in Translate(Agent.Physics.LocalPosition, GetPathPoint(Step.DestinationVoxel), actionSpeed))
                {
                    if (shaft.Invalid)
                    {
                        yield return(Status.Fail);
                    }

                    shaft.WaitForMe(Agent);

                    SetCharacterMode(CharacterMode.Walking);

                    if (Debugger.Switches.DebugElevators)
                    {
                        Drawer3D.DrawBox(shafts.Entrance.GetBoundingBox(), Color.Green, 0.1f, false);
                        Drawer3D.DrawBox(shafts.Exit.GetBoundingBox(), Color.Green, 0.1f, false);
                        Drawer3D.DrawBox(Step.DestinationVoxel.GetBoundingBox(), Color.Green, 0.1f, false);
                    }

                    yield return(Status.Running);
                }
                Creature.Physics.Gravity = grav;

                shaft.Done(Agent);

                break;

                #endregion
            case MoveType.EnterVehicle:

                Creature.NoiseMaker.MakeNoise("Jump", Agent.Position, false);

                foreach (var bit in Jump(GetPathPoint(Step.SourceVoxel), GetPathPoint(Step.DestinationVoxel), Step.DestinationVoxel.Center - Step.SourceVoxel.Center, actionSpeed, 1.5f))
                {
                    SetCharacterMode(Creature.Physics.Velocity.Y > 0 ? CharacterMode.Jumping : CharacterMode.Falling);
                    yield return(Status.Running);
                }

                DeltaTime = 0.0f;
                SetupMinecart();

                break;

            case MoveType.ExitVehicle:

                CleanupMinecart();
                SetAgentTranslation(GetPathPoint(Step.DestinationVoxel));
                break;

            case MoveType.RideVehicle:

                SetupMinecart();
                var rail = Step.SourceState.Rail;
                if (rail == null)
                {
                    yield return(Status.Fail);
                }

                var rideTime = 1.0f / actionSpeed;
                while (DeltaTime < rideTime)
                {
                    var pos = rail.InterpolateSpline(DeltaTime / rideTime, Step.SourceVoxel.WorldPosition, Step.DestinationVoxel.WorldPosition);

                    var transform = Agent.Physics.LocalTransform;
                    transform.Translation        = pos + Vector3.Up * 0.5f;
                    Agent.Physics.LocalTransform = transform;
                    Agent.Physics.Velocity       = GetPathPoint(Step.DestinationVoxel) - GetPathPoint(Step.SourceVoxel);

                    SetCharacterMode(CharacterMode.Minecart);

                    transform.Translation = pos + Vector3.Up * -0.1f;

                    if (Minecart != null)
                    {
                        Minecart.LocalTransform = transform;
                    }

                    yield return(Status.Running);
                }

                DeltaTime -= rideTime;

                break;

            case MoveType.Walk:

                // Todo: Fail if distance is too great.

                CleanupMinecart();

                foreach (var bit in Translate(Agent.Position, GetPathPoint(Step.DestinationVoxel), actionSpeed))
                {
                    SetCharacterMode(CharacterMode.Walking);
                    yield return(Status.Running);
                }
                break;

            case MoveType.Swim:

                CleanupMinecart();

                foreach (var bit in Translate(Agent.Position, GetPathPoint(Step.DestinationVoxel), actionSpeed))
                {
                    Creature.NoiseMaker.MakeNoise("Swim", Agent.Position, true);
                    SetCharacterMode(CharacterMode.Swimming);
                    yield return(Status.Running);
                }

                break;

            case MoveType.Jump:
            {
                CleanupMinecart();
                Creature.NoiseMaker.MakeNoise("Jump", Agent.Position, false);

                var dest  = GetPathPoint(Step.DestinationVoxel);
                var above = VoxelHelpers.GetVoxelAbove(Step.SourceVoxel);
                if (above.IsValid && !above.IsEmpty)
                {
                    yield return(Status.Fail);
                }

                foreach (var bit in Jump(Agent.Position, dest, dest - Agent.Position, actionSpeed / 2.0f, 0.0f))
                {
                    Creature.Physics.CollisionType = CollisionType.None;
                    Creature.OverrideCharacterMode = false;
                    SetCharacterMode(Creature.Physics.Velocity.Y > 0 ? CharacterMode.Jumping : CharacterMode.Falling);
                    yield return(Status.Running);
                }

                SetAgentTranslation(dest);

                break;
            }

            case MoveType.HighJump:
            {
                CleanupMinecart();
                Creature.NoiseMaker.MakeNoise("Jump", Agent.Position, false);

                var dest  = GetPathPoint(Step.DestinationVoxel);
                var above = VoxelHelpers.GetVoxelAbove(Step.SourceVoxel);
                if (above.IsValid && !above.IsEmpty)
                {
                    yield return(Status.Fail);
                }

                foreach (var bit in Jump(Agent.Position, dest, dest - Agent.Position, actionSpeed / 2.0f, 1.5f))
                {
                    Creature.Physics.CollisionType = CollisionType.None;
                    Creature.OverrideCharacterMode = false;
                    SetCharacterMode(Creature.Physics.Velocity.Y > 0 ? CharacterMode.Jumping : CharacterMode.Falling);
                    yield return(Status.Running);
                }

                SetAgentTranslation(dest);

                break;
            }

            case MoveType.Fall:

                CleanupMinecart();

                foreach (var bit in Translate(Agent.Position, GetPathPoint(Step.DestinationVoxel), actionSpeed))
                {
                    SetCharacterMode(CharacterMode.Falling);
                    yield return(Status.Running);
                }

                break;

            case MoveType.Climb:

                CleanupMinecart();

                DeltaTime = 0.0f;
                foreach (var bit in Translate(GetPathPoint(Step.SourceVoxel), GetPathPoint(Step.DestinationVoxel), actionSpeed))
                {
                    if (Step.InteractObject == null || Step.InteractObject.IsDead)
                    {
                        yield return(Status.Fail);
                    }

                    if (DeltaTime - LastNoiseTime > 1.0f)
                    {
                        Creature.NoiseMaker.MakeNoise("Climb", Agent.Position, false);
                        LastNoiseTime = DeltaTime;
                    }

                    SetCharacterMode(CharacterMode.Climbing);
                    yield return(Status.Running);
                }

                break;

            case MoveType.ClimbWalls:

                CleanupMinecart();

                DeltaTime = 0.0f;
                foreach (var bit in Translate(GetPathPoint(Step.SourceVoxel), GetPathPoint(Step.DestinationVoxel), actionSpeed))
                {
                    if (DeltaTime - LastNoiseTime > 1.0f)
                    {
                        Creature.NoiseMaker.MakeNoise("Climb", Agent.Position, false);
                        LastNoiseTime = DeltaTime;
                    }

                    SetCharacterMode(CharacterMode.Climbing);

                    if (Step.ActionVoxel.IsValid)
                    {
                        var voxelVector = new Vector3(Step.ActionVoxel.Coordinate.X + 0.5f, Agent.Physics.Position.Y, Step.ActionVoxel.Coordinate.Z + 0.5f);
                        Agent.Physics.Velocity = Vector3.Normalize(voxelVector - Agent.Physics.Position) * actionSpeed;
                    }

                    yield return(Status.Running);
                }

                break;

            case MoveType.Fly:

                CleanupMinecart();

                DeltaTime = 0.0f;
                foreach (var bit in Translate(GetPathPoint(Step.SourceVoxel), GetPathPoint(Step.DestinationVoxel), actionSpeed))
                {
                    if ((int)(DeltaTime * 100) % 2 == 0)
                    {
                        Creature.NoiseMaker.MakeNoise("Flap", Agent.Position, false);
                    }
                    SetCharacterMode(CharacterMode.Flying);

                    yield return(Status.Running);
                }

                break;

            case MoveType.Dig:

                CleanupMinecart();

                var destroy = new DigAct(Creature.AI, new KillVoxelTask(Step.DestinationVoxel))
                {
                    CheckOwnership = false
                };
                destroy.Initialize();
                foreach (var status in destroy.Run())
                {
                    if (status == Act.Status.Fail)
                    {
                        yield return(Act.Status.Fail);
                    }
                    yield return(Act.Status.Running);
                }
                yield return(Act.Status.Fail);    // Abort the path so that they stop digging if a path has opened.

                break;

            case MoveType.DestroyObject:

                CleanupMinecart();

                var melee = new AttackAct(Creature.AI, (GameComponent)Step.InteractObject);
                melee.Initialize();
                foreach (var status in melee.Run())
                {
                    if (status == Act.Status.Fail)
                    {
                        yield return(Act.Status.Fail);
                    }
                    yield return(Act.Status.Running);
                }
                yield return(Act.Status.Fail);    // Abort the path so that they stop destroying things if a path has opened.

                break;

            case MoveType.Teleport:

                CleanupMinecart();

                if (Step.InteractObject == null || Step.InteractObject.IsDead)
                {
                    yield return(Status.Fail);
                }

                if (Step.InteractObject.GetComponent <MagicalObject>().HasValue(out var teleporter))
                {
                    teleporter.CurrentCharges--;
                }

                SoundManager.PlaySound(ContentPaths.Audio.Oscar.sfx_ic_dwarf_magic_research, Agent.Position, true, 1.0f);
                Agent.World.ParticleManager.Trigger("green_flame", (Step.InteractObject as GameComponent).Position, Color.White, 1);
                //Agent.GetRoot().SetFlagRecursive(GameComponent.Flag.Visible, false);

                {
                    var source = GetPathPoint(Step.SourceVoxel);
                    var dest   = GetPathPoint(Step.DestinationVoxel);
                    var delta  = dest - source;
                    var steps  = delta.Length() * 2.0f;
                    delta.Normalize();
                    delta *= 0.5f;

                    for (var i = 0; i <= steps; ++i)
                    {
                        Agent.World.ParticleManager.Trigger("star_particle", source, Color.White, 1);
                        source += delta;
                    }
                }

                //foreach (var bit in Translate(GetPathPoint(Step.SourceVoxel), GetPathPoint(Step.DestinationVoxel), actionSpeed))
                //{
                //    Agent.World.ParticleManager.Trigger("star_particle", Agent.Position, Color.White, 1);
                //    yield return Status.Running;
                //}

                SetAgentTranslation(GetPathPoint(Step.DestinationVoxel));
                //Agent.GetRoot().SetFlagRecursive(GameComponent.Flag.Visible, true);
                yield return(Status.Running);

                break;
            }
        }
예제 #27
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);
                }
            }
        }
예제 #28
0
        public override void OnVoxelsSelected(List <VoxelHandle> refs, InputManager.MouseButton button)
        {
            if (Command.Contains("Build/"))
            {
                if (Library.CreateZone(Command.Substring(6), World).HasValue(out var zone))
                {
                    World.AddZone(zone);
                    zone.CompleteRoomImmediately(refs);
                }
            }
            if (Command.Contains("Spawn/"))
            {
                string type = Command.Substring(6);
                foreach (var vox in refs.Where(vox => vox.IsValid))
                {
                    if (vox.IsEmpty)
                    {
                        var offset = Vector3.Zero;

                        if (Library.GetCraftable(type).HasValue(out var craftItem))
                        {
                            offset = craftItem.SpawnOffset;
                        }

                        var body = EntityFactory.CreateEntity <GameComponent>(type, vox.WorldPosition + new Vector3(0.5f, 0.0f, 0.5f) + offset);
                        if (body != null)
                        {
                            body.PropogateTransforms();

                            if (craftItem != null)
                            {
                                if (craftItem.AddToOwnedPool)
                                {
                                    World.PlayerFaction.OwnedObjects.Add(body);
                                }

                                if (craftItem.Deconstructable)
                                {
                                    body.Tags.Add("Deconstructable"); // Todo: Should not need to set tag every time item is created. Inherint?
                                }
                            }
                        }
                    }
                }
            }
            else if (Command.Contains("Resource/"))
            {
                string type = Command.Substring("Resource/".Length);
                foreach (var vox in refs.Where(vox => vox.IsValid))
                {
                    var body = World.ComponentManager.RootComponent.AddChild(new ResourceEntity(World.ComponentManager, new Resource(type), vox.WorldPosition + new Vector3(0.5f, 0.5f, 0.5f)));
                    body.PropogateTransforms();
                }
            }
            else if (Command.Contains("Rail/"))
            {
                string type     = Command.Substring("Rail/".Length);
                var    junction = new Rail.JunctionPiece
                {
                    RailPiece   = type,
                    Orientation = Rail.PieceOrientation.North,
                    Offset      = Point.Zero
                };

                foreach (var vox in refs.Where(vox => vox.IsValid))
                {
                    if (vox.IsEmpty)
                    {
                        var entity = new Rail.RailEntity(World.ComponentManager, vox, junction);
                        World.ComponentManager.RootComponent.AddChild(entity);
                    }
                }
            }
            else if (Command.Contains("Grass/"))
            {
                var type = Library.GetGrassType(Command.Substring(6));
                if (type != null)
                {
                    foreach (var vox in refs.Where(v => v.IsValid))
                    {
                        var v = vox;
                        if (!vox.IsEmpty)
                        {
                            v.GrassType  = type.ID;
                            v.GrassDecay = type.InitialDecayValue;
                        }
                    }
                }
            }
            else if (Command.Contains("Decal/"))
            {
                var type = Library.GetDecalType(Command.Substring(6));
                if (type != null)
                {
                    foreach (var vox in refs.Where(v => v.IsValid))
                    {
                        var v = vox;
                        if (!vox.IsEmpty)
                        {
                            v.DecalType = type.ID;
                        }
                    }
                }
            }
            else if (Command.Contains("Disease"))
            {
                foreach (var creature in World.EnumerateIntersectingObjects(VoxelHelpers.GetVoxelBoundingBox(refs), CollisionType.Both).OfType <Creature>())
                {
                    creature.Stats.AcquireDisease(DiseaseLibrary.GetRandomDisease());
                }
            }
            else
            {
                foreach (var vox in refs.Where(vox => vox.IsValid))
                {
                    if (Command.Contains("Place/"))
                    {
                        string type = Command.Substring(6);
                        var    v    = vox;
                        if (Library.GetVoxelType(type).HasValue(out VoxelType vType))
                        {
                            v.Type = vType;
                        }
                        v.QuickSetLiquid(LiquidType.None, 0);

                        if (type == "Magic")
                        {
                            World.ComponentManager.RootComponent.AddChild(
                                new DestroyOnTimer(World.ComponentManager, World.ChunkManager, vox)
                            {
                                DestroyTimer = new Timer(5.0f + MathFunctions.Rand(-0.5f, 0.5f), true)
                            });
                        }
                    }
                    else
                    {
                        switch (Command)
                        {
                        case "Delete Block":
                        {
                            var v = vox;
                            World.OnVoxelDestroyed(vox);
                            v.Type = Library.EmptyVoxelType;
                            v.QuickSetLiquid(LiquidType.None, 0);
                        }
                        break;

                        case "Nuke Column":
                        {
                            for (var y = 1; y < World.WorldSizeInVoxels.Y; ++y)
                            {
                                var v = World.ChunkManager.CreateVoxelHandle(new GlobalVoxelCoordinate(vox.Coordinate.X, y, vox.Coordinate.Z));
                                v.Type = Library.EmptyVoxelType;
                                v.QuickSetLiquid(LiquidType.None, 0);
                            }
                        }
                        break;

                        case "Kill Block":
                            foreach (var selected in refs)
                            {
                                if (!selected.IsEmpty)
                                {
                                    VoxelHelpers.KillVoxel(World, selected);
                                }
                            }
                            break;

                        case "Fill Water":
                        {
                            if (vox.IsEmpty)
                            {
                                var v = vox;
                                v.QuickSetLiquid(LiquidType.Water, WaterManager.maxWaterLevel);
                            }
                        }
                        break;

                        case "Fill Lava":
                        {
                            if (vox.IsEmpty)
                            {
                                var v = vox;
                                v.QuickSetLiquid(LiquidType.Lava, WaterManager.maxWaterLevel);
                            }
                        }
                        break;

                        case "Fire":
                        {
                            foreach (var flam2 in World.EnumerateIntersectingObjects(vox.GetBoundingBox(), CollisionType.Both).OfType <Flammable>())
                            {
                                flam2.Heat = flam2.Flashpoint + 1;
                            }
                        }
                        break;

                        default:
                            break;
                        }
                    }
                }
            }
        }
예제 #29
0
        override public void Update(DwarfTime gameTime, ChunkManager chunks, Camera camera)
        {
            base.Update(gameTime, chunks, camera);

            if (!Active)
            {
                return;
            }

            Creature.NoiseMaker.BasePitch = Stats.VoicePitch;

            // Non-dwarves are always at full energy.
            Stats.Energy.CurrentValue = 100.0f;

            AutoGatherTimer.Update(gameTime);

            if (AutoGatherTimer.HasTriggered)
            {
                if (!String.IsNullOrEmpty(Faction.Race.BecomeWhenEvil) && MathFunctions.RandEvent(0.01f))
                {
                    Faction.Minions.Remove(this);
                    Faction = World.Factions.Factions[Faction.Race.BecomeWhenEvil];
                    Faction.AddMinion(this);
                }
                else if (!String.IsNullOrEmpty(Faction.Race.BecomeWhenNotEvil) && MathFunctions.RandEvent(0.01f))
                {
                    Faction.Minions.Remove(this);
                    Faction = World.Factions.Factions[Faction.Race.BecomeWhenNotEvil];
                    Faction.AddMinion(this);
                }

                foreach (var body in World.EnumerateIntersectingObjects(Physics.BoundingBox.Expand(3.0f)).OfType <ResourceEntity>().Where(r => r.Active && r.AnimationQueue.Count == 0))
                {
                    var resource = Library.GetResourceType(body.Resource.Type);
                    if (resource.Tags.Contains(Resource.ResourceTags.Edible))
                    {
                        if ((Faction.Race.EatsMeat && resource.Tags.Contains(Resource.ResourceTags.AnimalProduct)) ||
                            (Faction.Race.EatsPlants && !resource.Tags.Contains(Resource.ResourceTags.AnimalProduct)))
                        {
                            Creature.GatherImmediately(body);
                            AssignTask(new ActWrapperTask(new EatFoodAct(this, false)));
                        }
                    }
                }

                OrderEnemyAttack();
            }

            DeleteBadTasks();
            PreEmptTasks();
            HandleReproduction();

            // Try to find food if we are hungry. Wait - doesn't this rob the player?
            if (Stats.Hunger.IsDissatisfied() && World.CountResourcesWithTag(Resource.ResourceTags.Edible) > 0)
            {
                Task toReturn = new SatisfyHungerTask();
                if (Stats.Hunger.IsCritical())
                {
                    toReturn.Priority = TaskPriority.Urgent;
                }
                if (!Tasks.Contains(toReturn) && CurrentTask != toReturn)
                {
                    AssignTask(toReturn);
                }
            }

            if (CurrentTask == null) // We need something to do.
            {
                var goal = GetEasiestTask(Tasks);

                if (goal != null)
                {
                    ChangeTask(goal);
                }
                else
                {
                    var newTask = ActOnIdle();
                    if (newTask != null)
                    {
                        ChangeTask(newTask);
                    }
                }
            }
            else
            {
                if (CurrentAct == null) // Should be impossible to have a current task and no current act.
                {
                    // Try and recover the correct act.
                    // <blecki> I always run with a breakpoint set here... just in case.
                    ChangeAct(CurrentTask.CreateScript(Creature));

                    // This is a bad situation!
                    if (CurrentAct == null)
                    {
                        ChangeTask(null);
                    }
                }

                if (CurrentAct != null)
                {
                    var  status  = CurrentAct.Tick();
                    bool retried = false;
                    if (CurrentAct != null && CurrentTask != null)
                    {
                        if (status == Act.Status.Fail)
                        {
                            LastFailedAct = CurrentAct.Name;

                            if (!FailedTasks.Any(task => task.TaskFailure.Equals(CurrentTask)))
                            {
                                FailedTasks.Add(new FailedTask()
                                {
                                    TaskFailure = CurrentTask, FailedTime = World.Time.CurrentDate
                                });
                            }

                            if (CurrentTask.ShouldRetry(Creature))
                            {
                                if (!Tasks.Contains(CurrentTask))
                                {
                                    ReassignCurrentTask();
                                    retried = true;
                                }
                            }
                        }
                    }

                    if (CurrentTask != null && CurrentTask.IsComplete(World))
                    {
                        ChangeTask(null);
                    }
                    else if (status != Act.Status.Running && !retried)
                    {
                        ChangeTask(null);
                    }
                }
            }

            // With a small probability, the creature will drown if its under water.
            if (MathFunctions.RandEvent(GameSettings.Default.DrownChance))
            {
                var  above       = VoxelHelpers.GetVoxelAbove(Physics.CurrentVoxel);
                var  below       = VoxelHelpers.GetVoxelBelow(Physics.CurrentVoxel);
                bool shouldDrown = (above.IsValid && (!above.IsEmpty || above.LiquidLevel > 0));
                if ((Physics.IsInLiquid || (!Movement.CanSwim && (below.IsValid && (below.LiquidLevel > 5)))) &&
                    (!Movement.CanSwim || shouldDrown))
                {
                    Creature.Damage(Movement.CanSwim ? 1.0f : 30.0f, Health.DamageType.Normal);
                }
            }

            if (PositionConstraint.Contains(Physics.LocalPosition) == ContainmentType.Disjoint)
            {
                Physics.LocalPosition = MathFunctions.Clamp(Physics.Position, PositionConstraint);
                Physics.PropogateTransforms();
            }
        }
예제 #30
0
        // Inverts GetMoveActions. So, returns the list of move actions whose target is the current voxel.
        // Very, very slow.
        public IEnumerable <MoveAction> GetInverseMoveActions(MoveState currentstate, OctTreeNode OctTree)
        {
            if (Parent == null)
            {
                yield break;
            }

            var creature = Creature;

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

            if (Can(MoveType.Teleport))
            {
                var teleportObjects = Parent.Faction.OwnedObjects.Where(obj => obj.Active && obj.Tags.Contains("Teleporter"));
                foreach (var obj in teleportObjects)
                {
                    if ((obj.Position - current.WorldPosition).LengthSquared() > 2)
                    {
                        continue;
                    }

                    for (int dx = -TeleportDistance; dx <= TeleportDistance; dx++)
                    {
                        for (int dz = -TeleportDistance; dz <= TeleportDistance; dz++)
                        {
                            for (int dy = -TeleportDistance; dy <= TeleportDistance; dy++)
                            {
                                if (dx * dx + dy * dy + dz * dz > TeleportDistanceSquared)
                                {
                                    continue;
                                }
                                VoxelHandle teleportNeighbor = new VoxelHandle(Parent.World.ChunkManager.ChunkData, current.Coordinate + new GlobalVoxelOffset(dx, dy, dz));

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

                if (!Can(MoveType.RideVehicle))
                {
                    continue;
                }
                // Now that dwarfs can ride vehicles, the inverse of the move actions becomes extremely complicated. We must now
                // iterate through all rails intersecting every neighbor and see if we can find a connection from that rail to this one.
                // Further, we must iterate through the entire rail network and enumerate all possible directions in and out of that rail.
                // Yay!
                var bodies = new HashSet <Body>();
                OctTree.EnumerateItems(v.GetBoundingBox(), bodies);
                var rails = bodies.OfType <Rail.RailEntity>().Where(r => r.Active);
                foreach (var rail in rails)
                {
                    if (rail.GetContainingVoxel() != v)
                    {
                        continue;
                    }

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

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

                    foreach (var a in GetMoveActions(new MoveState()
                    {
                        Voxel = v, VehicleState = new VehicleState()
                        {
                            Rail = rail, PrevRail = null
                        }
                    }, OctTree).Where(a => a.DestinationState == currentstate))
                    {
                        yield return(a);
                    }
                }
            }
        }