Пример #1
0
        public static bool IsValidPlacement(
            VoxelHandle Location,
            CraftItem CraftType,
            GameMaster Player,
            Body PreviewBody,
            String Verb,
            String PastParticple)
        {
            if (CraftType == null)
            {
                return(false);
            }

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

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

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

                    break;
                }

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

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

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

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

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

                bool intersectsWall = VoxelHelpers.EnumerateCoordinatesInBoundingBox
                                          (PreviewBody.GetRotatedBoundingBox().Expand(-0.1f)).Any(
                    v =>
                {
                    var tvh = new VoxelHandle(Player.World.ChunkManager.ChunkData, v);
                    return(tvh.IsValid && !tvh.IsEmpty);
                });

                if (intersectsWall && !CraftType.Prerequisites.Contains(CraftItem.CraftPrereq.NearWall))
                {
                    Player.World.ShowToolPopup("Can't " + Verb + " here: intersects wall.");
                    return(false);
                }
            }
            Player.World.ShowToolPopup("");
            return(true);
        }
Пример #2
0
        private bool ValidatePlanting(VoxelHandle voxel)
        {
            if (!voxel.Type.IsSoil)
            {
                World.UserInterface.ShowTooltip("Can only plant on soil!");
                return(false);
            }

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

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

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

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

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

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

            if (World.EnumerateZones().Any(z => z.GetBoundingBox().Expand(0.1f).Intersects(voxelBox)))
            {
                World.UserInterface.ShowTooltip("Can't plant inside zones.");
                return(false);
            }

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

            return(true);
        }
Пример #3
0
        /// <summary>
        /// This is the underlying Dig behavior that dwarves follow while digging.
        /// </summary>
        /// <param name="agent">The agent.</param>
        /// <param name="voxel">The voxel.</param>
        /// <param name="energyLoss">The energy loss the dwarf gets per block mined.</param>
        /// <returns>Success when the block is mined, fail if it fails to be mined, and running otherwise.</returns>
        public static IEnumerable <Act.Status> Dig(this Creature agent, string voxel, float energyLoss)
        {
            agent.Sprite.ResetAnimations(Creature.CharacterMode.Attacking);

            // Block since we're in a coroutine.
            while (true)
            {
                // Get the voxel stored in the agent's blackboard.
                Voxel blackBoardVoxel = agent.AI.Blackboard.GetData <Voxel>(voxel);

                // Somehow, there wasn't a voxel to mine.
                if (blackBoardVoxel == null)
                {
                    agent.DrawIndicator(IndicatorManager.StandardIndicators.Question);
                    yield return(Act.Status.Fail);

                    break;
                }

                Voxel vox = blackBoardVoxel;

                // If the voxel has already been destroyed, just ignore it and return.
                if (vox.Health <= 0.0f || !agent.Faction.IsDigDesignation(vox))
                {
                    agent.AI.AddXP(Math.Max((int)(VoxelLibrary.GetVoxelType(blackBoardVoxel.TypeName).StartingHealth / 4), 1));
                    agent.Stats.NumBlocksDestroyed++;
                    agent.CurrentCharacterMode = Creature.CharacterMode.Idle;
                    yield return(Act.Status.Success);

                    break;
                }

                // Look at the block and slow your velocity down.
                agent.Physics.Face(vox.Position + Vector3.One * 0.5f);
                agent.Physics.Velocity *= 0.9f;

                // Play the attack animations.
                agent.CurrentCharacterMode = Creature.CharacterMode.Attacking;
                agent.Sprite.ResetAnimations(agent.CurrentCharacterMode);
                agent.Sprite.PlayAnimations(agent.CurrentCharacterMode);

                // Wait until an attack was successful...
                foreach (var status in
                         agent.Attacks[0].Perform(agent,
                                                  agent.Physics.Position,
                                                  vox, DwarfTime.LastTime,
                                                  agent.Stats.BaseDigSpeed,
                                                  agent.Faction.Name))
                {
                    if (status == Act.Status.Running)
                    {
                        agent.Physics.Face(vox.Position + Vector3.One * 0.5f);
                        agent.Physics.Velocity *= 0.9f;

                        // Debug drawing.
                        if (agent.AI.DrawPath)
                        {
                            Drawer3D.DrawLine(vox.Position, agent.AI.Position, Color.Green, 0.25f);
                        }
                        yield return(Act.Status.Running);
                    }
                }

                // If the voxel has been destroyed by you, gather it.
                if (vox.Health <= 0.0f)
                {
                    List <Body> items = vox.Kill();

                    if (items != null)
                    {
                        foreach (Body item in items)
                        {
                            agent.Gather(item);
                        }
                    }
                }

                // Wait until the animation is done playing before continuing.
                while (!agent.Sprite.CurrentAnimation.IsDone() && agent.Sprite.CurrentAnimation.IsPlaying)
                {
                    agent.Physics.Face(vox.Position + Vector3.One * 0.5f);
                    agent.Physics.Velocity *= 0.9f;
                    yield return(Act.Status.Running);
                }

                // Pause the animation and wait for a recharge timer.
                agent.Sprite.PauseAnimations(agent.CurrentCharacterMode);


                // Wait for a recharge timer to trigger.
                agent.Attacks[0].RechargeTimer.Reset();
                while (!agent.Attacks[0].RechargeTimer.HasTriggered)
                {
                    agent.Attacks[0].RechargeTimer.Update(DwarfTime.LastTime);
                    agent.Physics.Face(vox.Position + Vector3.One * 0.5f);
                    agent.Physics.Velocity *= 0.9f;
                    yield return(Act.Status.Running);
                }

                agent.CurrentCharacterMode = Creature.CharacterMode.Idle;

                yield return(Act.Status.Running);
            }
        }
Пример #4
0
        public override IEnumerable <Status> Run()
        {
            while (true)
            {
                Creature.AI.Blackboard.Erase(PathName);
                Agent.Blackboard.SetData <bool>("NoPath", false);
                PlanAct planAct = new PlanAct(Creature.AI, PathName, VoxelName, PlanType)
                {
                    Radius = Radius, MaxTimeouts = MaxTimeouts
                };
                planAct.Initialize();

                bool planSucceeded = false;
                while (true)
                {
                    Act.Status planStatus = planAct.Tick();

                    if (planStatus == Status.Fail)
                    {
                        yield return(Act.Status.Running);

                        break;
                    }

                    else if (planStatus == Status.Running)
                    {
                        yield return(Act.Status.Running);
                    }

                    else if (planStatus == Status.Success)
                    {
                        planSucceeded = true;
                        break;
                    }
                    yield return(Act.Status.Running);
                }

                if (!planSucceeded && planAct.LastResult == AStarPlanner.PlanResultCode.MaxExpansionsReached)
                {
                    yield return(Act.Status.Running);

                    Creature.CurrentCharacterMode = CharacterMode.Idle;
                    Creature.Physics.Velocity     = Vector3.Zero;
                    Timer planTimeout = new Timer(MathFunctions.Rand(30.0f, 120.0f), false, Timer.TimerMode.Real);
                    List <VoxelHandle> exploredVoxels = new List <VoxelHandle>();
                    Color debugColor = new Color(MathFunctions.RandVector3Cube() + Vector3.One * 0.5f);
                    float debugScale = MathFunctions.Rand() * 0.5f + 0.5f;
                    while (!planTimeout.HasTriggered)
                    {
                        // In this case, try to follow a greedy path toward the entity instead of just failing.
                        var greedyPath = planAct.ComputeGreedyFallback(20, exploredVoxels);
                        var goal       = planAct.GetGoal();
                        Creature.AI.Blackboard.SetData("GreedyPath", greedyPath);
                        var greedyPathFollow = new FollowPathAct(Creature.AI, "GreedyPath")
                        {
                            BlendEnd   = true,
                            BlendStart = false
                        };
                        greedyPathFollow.Initialize();

                        foreach (var currStatus in greedyPathFollow.Run())
                        {
                            if (Debugger.Switches.DrawPaths)
                            {
                                foreach (var voxel in exploredVoxels)
                                {
                                    Drawer3D.DrawBox(voxel.GetBoundingBox().Expand(-debugScale), debugColor, 0.05f, false);
                                }
                            }
                            if (!exploredVoxels.Contains(Agent.Physics.CurrentVoxel))
                            {
                                exploredVoxels.Add(Agent.Physics.CurrentVoxel);
                            }
                            if (Debugger.Switches.DrawPaths)
                            {
                                Drawer3D.DrawLine(Agent.Position, goal.GetVoxel().WorldPosition, debugColor, 0.1f);
                            }
                            if (goal.IsInGoalRegion(Agent.Physics.CurrentVoxel))
                            {
                                yield return(Act.Status.Success);

                                yield break;
                            }
                            yield return(Act.Status.Running);
                        }
                        planTimeout.Update(DwarfTime.LastTime);
                    }
                    continue;
                }
                else if (!planSucceeded)
                {
                    Agent.Blackboard.SetData <bool>("NoPath", true);
                    yield return(Act.Status.Fail);

                    yield break;
                }
                yield return(Act.Status.Success);

                yield break;
            }
        }
Пример #5
0
        public override IEnumerable <Status> Run()
        {
            Path     = null;
            Timeouts = 0;
            PlannerTimer.Reset(PlannerTimer.TargetTimeSeconds);
            var     lastId  = -1;
            Vector3 goalPos = Vector3.Zero;

            Agent.Blackboard.SetData <bool>("NoPath", false);
            while (true)
            {
                if (Path != null)
                {
                    yield return(Status.Success);

                    break;
                }

                if (Timeouts > MaxTimeouts)
                {
                    Agent.Blackboard.SetData <bool>("NoPath", true);
                    yield return(Status.Fail);

                    break;
                }
                if (WaitingOnResponse && Debugger.Switches.DrawPaths)
                {
                    Drawer3D.DrawLine(Creature.AI.Position, goalPos, Color.Blue, 0.25f);
                }
                PlannerTimer.Update(DwarfTime.LastTime);

                ChunkManager chunks = Creature.Manager.World.ChunkManager;
                if (PlannerTimer.HasTriggered || Timeouts == 0)
                {
                    if (!Target.IsValid && Type != PlanType.Edge)
                    {
                        Creature.DrawIndicator(IndicatorManager.StandardIndicators.Question);
                        Agent.Blackboard.SetData <bool>("NoPath", true);
                        yield return(Status.Fail);

                        break;
                    }

                    var voxUnder = VoxelHelpers.GetValidVoxelNear(chunks, Agent.Position);

                    if (!voxUnder.IsValid)
                    {
                        if (Debugger.Switches.DrawPaths)
                        {
                            Creature.World.MakeWorldPopup(String.Format("Invalid request"), Creature.Physics, -10, 1);
                        }
                        Creature.DrawIndicator(IndicatorManager.StandardIndicators.Question);
                        Agent.Blackboard.SetData <bool>("NoPath", true);
                        yield return(Status.Fail);

                        break;
                    }

                    Path = null;
                    AstarPlanRequest aspr = new AstarPlanRequest
                    {
                        Subscriber      = Agent.PlanSubscriber,
                        Start           = voxUnder,
                        MaxExpansions   = MaxExpansions,
                        Sender          = Agent,
                        HeuristicWeight = Weights[Timeouts]
                    };

                    lastId          = aspr.ID;
                    aspr.GoalRegion = GetGoal();
                    goalPos         = GetGoal().GetVoxel().GetBoundingBox().Center();
                    Agent.PlanSubscriber.Clear();
                    if (!Agent.PlanSubscriber.SendRequest(aspr, aspr.ID))
                    {
                        yield return(Status.Fail);

                        yield break;
                    }
                    PlannerTimer.Reset(PlannerTimer.TargetTimeSeconds);
                    WaitingOnResponse = true;
                    yield return(Status.Running);


                    Timeouts++;
                }
                else
                {
                    if (Target.IsValid && Creature.AI.DrawAIPlan)
                    {
                        Drawer3D.DrawLine(Creature.AI.Position, Target.WorldPosition, Color.Blue, 0.25f);
                    }
                    Status statusResult = Status.Running;

                    while (Agent.PlanSubscriber.Responses.Count > 0)
                    {
                        AStarPlanResponse response;
                        if (!Agent.PlanSubscriber.Responses.TryDequeue(out response))
                        {
                            yield return(Status.Running);

                            continue;
                        }
                        LastResult = response.Result;

                        if (response.Success && response.Request.ID == lastId)
                        {
                            Path = response.Path;
                            WaitingOnResponse = false;

                            statusResult = Status.Success;
                        }
                        else if (response.Request.ID != lastId)
                        {
                            bool obeysGoal = response.Success && (GetGoal().IsInGoalRegion(response.Path.Last().DestinationVoxel));
                            if (Debugger.Switches.DrawPaths)
                            {
                                if (obeysGoal)
                                {
                                    Creature.World.MakeWorldPopup(String.Format("Using Old Path", response.Result), Creature.Physics, -10, 1);
                                }
                                else
                                {
                                    Creature.World.MakeWorldPopup(String.Format("Old Path Dropped", response.Result), Creature.Physics, -10, 1);
                                }
                            }

                            if (obeysGoal)
                            {
                                Path = response.Path;
                                WaitingOnResponse = false;
                                statusResult      = Status.Success;
                            }
                            else
                            {
                                continue;
                            }
                        }
                        else if (response.Result == AStarPlanner.PlanResultCode.Invalid || response.Result == AStarPlanner.PlanResultCode.NoSolution ||
                                 response.Result == AStarPlanner.PlanResultCode.Cancelled || response.Result == AStarPlanner.PlanResultCode.Invalid)
                        {
                            if (Debugger.Switches.DrawPaths)
                            {
                                Creature.World.MakeWorldPopup(String.Format("Path: {0}", response.Result), Creature.Physics, -10, 1);
                            }
                            Creature.DrawIndicator(IndicatorManager.StandardIndicators.Question);
                            Agent.Blackboard.SetData <bool>("NoPath", true);
                            statusResult = Status.Fail;
                            yield return(Status.Fail);
                        }
                        else if (Timeouts <= MaxTimeouts)
                        {
                            Timeouts++;
                            yield return(Status.Running);
                        }
                        else
                        {
                            if (Debugger.Switches.DrawPaths)
                            {
                                Creature.World.MakeWorldPopup(String.Format("Max timeouts reached", response.Result), Creature.Physics, -10, 1);
                            }
                            Creature.DrawIndicator(IndicatorManager.StandardIndicators.Question);
                            Agent.Blackboard.SetData <bool>("NoPath", true);
                            statusResult = Status.Fail;
                        }
                    }
                    yield return(statusResult);
                }
            }
        }
Пример #6
0
        override public void Update(DwarfTime gameTime, ChunkManager chunks, Camera camera)
        {
            base.Update(gameTime, chunks, camera);

            Storm.InitializeStatics();
            BoundingBox box = chunks.Bounds;

            box.Expand(10.0f);

            if (GlobalTransform.Translation.X < box.Min.X ||
                GlobalTransform.Translation.X > box.Max.X ||
                GlobalTransform.Translation.Z < box.Min.Z ||
                GlobalTransform.Translation.Z > box.Max.Z)
            {
                Die();
            }


            bool generateRainDrop = MathFunctions.RandEvent(Raininess * 0.75f);

            if (generateRainDrop)
            {
                for (int i = 0; i < MaxRainDrops; i++)
                {
                    if (!RainDrops[i].IsAlive)
                    {
                        RainDrops[i].IsAlive = true;
                        if (RainDrops[i].Particle != null)
                        {
                            RainDrops[i].Particle.LifeRemaining = 60.0f;
                            RainDrops[i].Particle.TimeAlive     = 0.0f;
                        }
                        RainDrops[i].Pos = MathFunctions.RandVector3Box(BoundingBox.Expand(5));
                        RainDrops[i].Pos = new Vector3(RainDrops[i].Pos.X, BoundingBox.Min.Y - 1, RainDrops[i].Pos.Z);
                        RainDrops[i].Vel = Vector3.Down * Storm.Properties[TypeofStorm].RainSpeed + Velocity;
                        break;
                    }
                }
            }

            bool generateLightning = LightningChance > 0.0f && MathFunctions.RandEvent((float)(LightningChance * 0.001f));

            if (generateLightning)
            {
                var below = VoxelHelpers.FindFirstVoxelBelowIncludingWater(new VoxelHandle(World.ChunkManager, GlobalVoxelCoordinate.FromVector3(new Vector3(Position.X, Math.Min(World.WorldSizeInVoxels.Y - 1, Position.Y), Position.Z))));
                if (below.IsValid && !below.IsEmpty)
                {
                    var above = VoxelHelpers.GetVoxelAbove(below);
                    if (above.IsValid)
                    {
                        EntityFactory.CreateEntity <Fire>("Fire", above.GetBoundingBox().Center());
                        List <Vector3> lightningStrikes = new List <Vector3>();
                        List <Color>   colors           = new List <Color>();
                        var            c = above.GetBoundingBox().Center();
                        for (float t = 0; t < 1.0f; t += 0.25f)
                        {
                            var p = c * t + Position * (1.0f - t);
                            lightningStrikes.Add(p + MathFunctions.RandVector3Box(-5, 5, 0, 0.1f, -5, 5));
                            colors.Add(Color.White);
                        }
                        lightningStrikes.Add(c);
                        colors.Add(Color.White);
                        Drawer3D.DrawLineList(lightningStrikes, colors, 0.3f);
                        SoundManager.PlaySound(ContentPaths.Audio.Oscar.sfx_gui_rain_storm_alert, MathFunctions.Rand(0.001f, 0.05f), MathFunctions.Rand(0.5f, 1.0f));
                        SoundManager.PlaySound(ContentPaths.Audio.Oscar.sfx_trap_destroyed, c, false, 1.0f, MathFunctions.Rand(-0.5f, 0.5f));
                        World.ParticleManager.Trigger("explode", c, Color.White, 10);
                    }
                }
            }

            Storm.StormProperties stormProperties = Storm.Properties[TypeofStorm];
            var rainEmitter = World.ParticleManager.Effects[stormProperties.RainEffect];
            var hitEmitter  = World.ParticleManager.Effects[stormProperties.HitEffect];

            for (int i = 0; i < MaxRainDrops; i++)
            {
                if (!RainDrops[i].IsAlive)
                {
                    continue;
                }

                RainDrops[i].Pos += RainDrops[i].Vel * DwarfTime.Dt;

                if (stormProperties.RainRandom > 0)
                {
                    RainDrops[i].Vel.X += MathFunctions.Rand(-1, 1) * stormProperties.RainRandom * DwarfTime.Dt;
                    RainDrops[i].Vel.Z += MathFunctions.Rand(-1, 1) * stormProperties.RainRandom * DwarfTime.Dt;
                }

                if (RainDrops[i].Pos.Y < 0)
                {
                    RainDrops[i].IsAlive = false;
                }

                if (!RainDrops[i].IsAlive && RainDrops[i].Particle != null)
                {
                    RainDrops[i].Particle.LifeRemaining = -1;
                }
                else if (RainDrops[i].IsAlive && RainDrops[i].Particle == null)
                {
                    RainDrops[i].Particle = rainEmitter.Emitters[0].CreateParticle(RainDrops[i].Pos,
                                                                                   RainDrops[i].Vel, Color.White);
                }
                else if (RainDrops[i].IsAlive && RainDrops[i].Particle != null)
                {
                    RainDrops[i].Particle.Position = RainDrops[i].Pos;
                    RainDrops[i].Particle.Velocity = RainDrops[i].Vel;
                }

                var test = new VoxelHandle(chunks, GlobalVoxelCoordinate.FromVector3(RainDrops[i].Pos));
                if (!test.IsValid || (test.IsEmpty && test.LiquidLevel == 0))
                {
                    continue;
                }

                RainDrops[i].IsAlive = false;

                var hitBodies = World.EnumerateIntersectingObjects(new BoundingBox(RainDrops[i].Pos - Vector3.One, RainDrops[i].Pos + Vector3.One));

                foreach (var body in hitBodies)
                {
                    if (body.Parent != Manager.RootComponent)
                    {
                        continue;
                    }

                    var flames = body.GetRoot().GetComponent <Flammable>();
                    if (flames != null)
                    {
                        flames.Heat *= 0.25f;
                    }

                    var seeds = body.GetRoot().GetComponent <Seedling>();
                    if (seeds != null)
                    {
                        if (TypeofStorm == StormType.RainStorm)
                        {
                            seeds.GrowthTime += MathFunctions.Rand(1.0f, 12.0f);
                        }
                        else if (MathFunctions.RandEvent(0.01f))
                        {
                            seeds.GetRoot().Die();
                        }
                    }
                }
                hitEmitter.Trigger(1, RainDrops[i].Pos + Vector3.UnitY * 0.5f, Color.White);

                //if (!MathFunctions.RandEvent(0.1f)) continue;

                var above = test.IsEmpty ? test : VoxelHelpers.GetVoxelAbove(test);

                if (!above.IsValid || !above.IsEmpty)
                {
                    continue;
                }
                if (TypeofStorm == StormType.RainStorm &&
                    (above.LiquidLevel < WaterManager.maxWaterLevel && (above.LiquidType == LiquidType.Water)))
                {
                    above.LiquidLevel = (byte)Math.Min(WaterManager.maxWaterLevel, above.LiquidLevel + WaterManager.rainFallAmount);
                    above.LiquidType  = stormProperties.LiquidToCreate;
                }
                else if (TypeofStorm == StormType.SnowStorm && above.IsEmpty && above.LiquidLevel == 0)
                {
                    if (test.GrassType == 0)
                    {
                        test.GrassType  = Library.GetGrassType("snow").ID;
                        test.GrassDecay = Library.GetGrassType("snow").InitialDecayValue;
                    }
                    else
                    {
                        var existingGrass = Library.GetGrassType((byte)test.GrassType);
                        if (!String.IsNullOrEmpty(existingGrass.BecomeWhenSnowedOn))
                        {
                            var newGrass = Library.GetGrassType(existingGrass.BecomeWhenSnowedOn);
                            test.GrassType  = newGrass.ID;
                            test.GrassDecay = newGrass.InitialDecayValue;
                        }
                    }
                }
            }

            Matrix tf = LocalTransform;

            tf.Translation += Velocity * DwarfTime.Dt;
            LocalTransform  = tf;
        }
Пример #7
0
        /// <summary>
        /// Called when a frame is to be drawn to the screen
        /// </summary>
        /// <param name="gameTime">The current time</param>
        public void Render(DwarfTime gameTime)
        {
            if (!ShowingWorld)
            {
                return;
            }

            var frustum     = Camera.GetDrawFrustum();
            var renderables = EnumerateIntersectingObjects(frustum)
                              .Where(r => r.IsVisible && !ChunkManager.IsAboveCullPlane(r.GetBoundingBox()));

            // Controls the sky fog
            float x = (1.0f - Sky.TimeOfDay);

            x = x * x;
            DefaultShader.FogColor       = new Color(0.32f * x, 0.58f * x, 0.9f * x);
            DefaultShader.LightPositions = LightPositions;

            CompositeLibrary.Render(GraphicsDevice);
            CompositeLibrary.Update();

            GraphicsDevice.DepthStencilState = DepthStencilState.Default;
            GraphicsDevice.BlendState        = BlendState.Opaque;

            // Computes the water height.
            float wHeight = WaterRenderer.GetVisibleWaterHeight(ChunkManager, Camera, GraphicsDevice.Viewport,
                                                                lastWaterHeight);

            lastWaterHeight = wHeight;

            // Draw reflection/refraction images
            WaterRenderer.DrawReflectionMap(renderables, gameTime, this, wHeight - 0.1f,
                                            GetReflectedCameraMatrix(wHeight),
                                            DefaultShader, GraphicsDevice);


            #region Draw Selection Buffer.

            if (SelectionBuffer == null)
            {
                SelectionBuffer = new SelectionBuffer(8, GraphicsDevice);
            }

            GraphicsDevice.RasterizerState   = RasterizerState.CullNone;
            GraphicsDevice.DepthStencilState = DepthStencilState.Default;
            GraphicsDevice.BlendState        = BlendState.Opaque;

            Plane slicePlane = WaterRenderer.CreatePlane(SlicePlane, new Vector3(0, -1, 0), Camera.ViewMatrix, false);

            if (SelectionBuffer.Begin(GraphicsDevice))
            {
                // Draw the whole world, and make sure to handle slicing
                DefaultShader.ClipPlane       = new Vector4(slicePlane.Normal, slicePlane.D);
                DefaultShader.ClippingEnabled = true;
                DefaultShader.View            = Camera.ViewMatrix;
                DefaultShader.Projection      = Camera.ProjectionMatrix;
                DefaultShader.World           = Matrix.Identity;

                //GamePerformance.Instance.StartTrackPerformance("Render - Selection Buffer - Chunks");
                ChunkRenderer.RenderSelectionBuffer(DefaultShader, GraphicsDevice, Camera.ViewMatrix);
                //GamePerformance.Instance.StopTrackPerformance("Render - Selection Buffer - Chunks");

                //GamePerformance.Instance.StartTrackPerformance("Render - Selection Buffer - Components");
                ComponentRenderer.RenderSelectionBuffer(renderables, gameTime, ChunkManager, Camera,
                                                        DwarfGame.SpriteBatch, GraphicsDevice, DefaultShader);
                //GamePerformance.Instance.StopTrackPerformance("Render - Selection Buffer - Components");

                //GamePerformance.Instance.StartTrackPerformance("Render - Selection Buffer - Instances");
                InstanceRenderer.Flush(GraphicsDevice, DefaultShader, Camera,
                                       InstanceRenderMode.SelectionBuffer);
                //GamePerformance.Instance.StopTrackPerformance("Render - Selection Buffer - Instances");

                SelectionBuffer.End(GraphicsDevice);
            }


            #endregion



            // Start drawing the bloom effect
            if (GameSettings.Default.EnableGlow)
            {
                bloom.BeginDraw();
            }

            // Draw the sky
            GraphicsDevice.Clear(DefaultShader.FogColor);
            DrawSky(gameTime, Camera.ViewMatrix, 1.0f, DefaultShader.FogColor);

            // Defines the current slice for the GPU
            float level = ChunkManager.World.Master.MaxViewingLevel + 0.25f;
            if (level > VoxelConstants.ChunkSizeY)
            {
                level = 1000;
            }

            SlicePlane = level;

            DefaultShader.WindDirection = Weather.CurrentWind;
            DefaultShader.WindForce     = 0.0005f * (1.0f + (float)Math.Sin(Time.GetTotalSeconds() * 0.001f));
            // Draw the whole world, and make sure to handle slicing
            DefaultShader.ClipPlane       = new Vector4(slicePlane.Normal, slicePlane.D);
            DefaultShader.ClippingEnabled = true;
            //Blue ghost effect above the current slice.
            DefaultShader.GhostClippingEnabled = true;
            Draw3DThings(gameTime, DefaultShader, Camera.ViewMatrix);

            // Now we want to draw the water on top of everything else
            DefaultShader.ClippingEnabled      = true;
            DefaultShader.GhostClippingEnabled = false;

            //ComponentManager.CollisionManager.DebugDraw();

            DefaultShader.View                 = Camera.ViewMatrix;
            DefaultShader.Projection           = Camera.ProjectionMatrix;
            DefaultShader.GhostClippingEnabled = true;
            // Now draw all of the entities in the game
            DefaultShader.ClipPlane       = new Vector4(slicePlane.Normal, slicePlane.D);
            DefaultShader.ClippingEnabled = true;

            if (Debugger.Switches.DrawOcttree)
            {
                foreach (var box in OctTree.EnumerateBounds(frustum))
                {
                    Drawer3D.DrawBox(box.Item2, Color.Yellow, 1.0f / (float)(box.Item1 + 1), false);
                }
            }

            // Render simple geometry (boxes, etc.)
            Drawer3D.Render(GraphicsDevice, DefaultShader, Camera, DesignationDrawer, PlayerFaction.Designations, this);

            DefaultShader.EnableShadows = false;

            DefaultShader.View = Camera.ViewMatrix;

            ComponentRenderer.Render(renderables, gameTime, ChunkManager,
                                     Camera,
                                     DwarfGame.SpriteBatch, GraphicsDevice, DefaultShader,
                                     ComponentRenderer.WaterRenderType.None, lastWaterHeight);
            InstanceRenderer.Flush(GraphicsDevice, DefaultShader, Camera, InstanceRenderMode.Normal);

            if (Master.CurrentToolMode == GameMaster.ToolMode.BuildZone ||
                Master.CurrentToolMode == GameMaster.ToolMode.BuildWall ||
                Master.CurrentToolMode == GameMaster.ToolMode.BuildObject)
            {
                DefaultShader.View       = Camera.ViewMatrix;
                DefaultShader.Projection = Camera.ProjectionMatrix;
                DefaultShader.SetTexturedTechnique();
                GraphicsDevice.BlendState = BlendState.NonPremultiplied;
            }

            WaterRenderer.DrawWater(
                GraphicsDevice,
                (float)gameTime.TotalGameTime.TotalSeconds,
                DefaultShader,
                Camera.ViewMatrix,
                GetReflectedCameraMatrix(wHeight),
                Camera.ProjectionMatrix,
                new Vector3(0.1f, 0.0f, 0.1f),
                Camera,
                ChunkManager);
            ParticleManager.Render(this, GraphicsDevice);
            DefaultShader.ClippingEnabled = false;

            if (GameSettings.Default.EnableGlow)
            {
                bloom.DrawTarget = UseFXAA ? fxaa.RenderTarget : null;

                if (UseFXAA)
                {
                    fxaa.Begin(DwarfTime.LastTime);
                }
                bloom.Draw(gameTime.ToRealTime());
                if (UseFXAA)
                {
                    fxaa.End(DwarfTime.LastTime);
                }
            }
            else if (UseFXAA)
            {
                fxaa.End(DwarfTime.LastTime);
            }

            RasterizerState rasterizerState = new RasterizerState()
            {
                ScissorTestEnable = true
            };


            if (Debugger.Switches.DrawSelectionBuffer)
            {
                SelectionBuffer.DebugDraw(GraphicsDevice.Viewport.Bounds);
            }

            try
            {
                DwarfGame.SafeSpriteBatchBegin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, Drawer2D.PointMagLinearMin,
                                               null, rasterizerState, null, Matrix.Identity);
                //DwarfGame.SpriteBatch.Draw(Shadows.ShadowTexture, Vector2.Zero, Color.White);
                if (IsCameraUnderwater())
                {
                    Drawer2D.FillRect(DwarfGame.SpriteBatch, GraphicsDevice.Viewport.Bounds, new Color(10, 40, 60, 200));
                }

                Drawer2D.Render(DwarfGame.SpriteBatch, Camera, GraphicsDevice.Viewport);

                IndicatorManager.Render(gameTime);
            }
            finally
            {
                DwarfGame.SpriteBatch.End();
            }

            if (Debugger.Switches.DrawComposites)
            {
                Vector2 offset = Vector2.Zero;
                foreach (var composite in CompositeLibrary.Composites)
                {
                    offset = composite.Value.DebugDraw(DwarfGame.SpriteBatch, (int)offset.X, (int)offset.Y);
                }
            }


            Master.Render(Game, gameTime, GraphicsDevice);

            DwarfGame.SpriteBatch.GraphicsDevice.ScissorRectangle =
                DwarfGame.SpriteBatch.GraphicsDevice.Viewport.Bounds;


            GraphicsDevice.DepthStencilState = DepthStencilState.Default;
            GraphicsDevice.BlendState        = BlendState.Opaque;

            lock (ScreenshotLock)
            {
                foreach (Screenshot shot in Screenshots)
                {
                    TakeScreenshot(shot.FileName, shot.Resolution);
                }

                Screenshots.Clear();
            }
        }
Пример #8
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:

                if (!Step.DestinationVoxel.IsEmpty)
                {
                    yield return(Status.Fail);
                }

                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();

                if (!Step.DestinationVoxel.IsEmpty)
                {
                    yield return(Status.Fail);
                }

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

            case MoveType.RideVehicle:

                if (!Step.DestinationVoxel.IsEmpty)
                {
                    yield return(Status.Fail);
                }

                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:

                CleanupMinecart();
                // Todo: Fail if distance is too great.

                if (!Step.DestinationVoxel.IsEmpty)
                {
                    yield return(Status.Fail);
                }

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

            case MoveType.Swim:

                CleanupMinecart();

                if (!Step.DestinationVoxel.IsEmpty)
                {
                    yield return(Status.Fail);
                }

                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();

                if (!Step.DestinationVoxel.IsEmpty)
                {
                    yield return(Status.Fail);
                }

                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();

                if (!Step.DestinationVoxel.IsEmpty)
                {
                    yield return(Status.Fail);
                }

                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();

                if (!Step.DestinationVoxel.IsEmpty)
                {
                    yield return(Status.Fail);
                }

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

                break;

            case MoveType.Climb:

                CleanupMinecart();

                if (!Step.DestinationVoxel.IsEmpty)
                {
                    yield return(Status.Fail);
                }

                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();

                if (!Step.DestinationVoxel.IsEmpty)
                {
                    yield return(Status.Fail);
                }

                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();

                if (!Step.DestinationVoxel.IsEmpty)
                {
                    yield return(Status.Fail);
                }

                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();

                if (Step.DestinationVoxel.IsEmpty)     // Reverse of other states!
                {
                    yield return(Status.Fail);
                }

                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();

                if (!Step.DestinationVoxel.IsEmpty)
                {
                    yield return(Status.Fail);
                }

                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.DestinationVoxel.IsEmpty)
                {
                    yield return(Status.Fail);
                }

                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;
            }
        }