public IEnumerable <Act.Status> WrangleAnimal(CreatureAI agent, CreatureAI creature)
 {
     creature.PositionConstraint = new BoundingBox(agent.Position - new Vector3(1.0f, 0.5f, 1.0f),
                                                   agent.Position + new Vector3(1.0f, 0.5f, 1.0f));
     Drawer3D.DrawLine(creature.Position, agent.Position, Color.Black, 0.05f);
     yield return(Act.Status.Success);
 }
示例#2
0
 public virtual void Render(DwarfTime gameTime, ChunkManager chunks, Camera camera, SpriteBatch spriteBatch, GraphicsDevice graphicsDevice, Shader effect, bool renderingForWater)
 {
     if (Debugger.Switches.DrawBoundingBoxes)
     {
         Drawer3D.DrawBox(BoundingBox, Color.Blue, 0.02f, false);
         Drawer3D.DrawLine(GlobalTransform.Translation, GlobalTransform.Translation + Vector3.UnitX, Color.Red, 0.02f);
         Drawer3D.DrawLine(GlobalTransform.Translation, GlobalTransform.Translation + Vector3.UnitY, Color.Blue, 0.02f);
         Drawer3D.DrawLine(GlobalTransform.Translation, GlobalTransform.Translation + Vector3.UnitZ, Color.Green, 0.02f);
     }
 }
示例#3
0
 private void DrawDebugPath()
 {
     if (Debugger.Switches.DrawPaths)
     {
         for (var i = 0; i < Path.Count; ++i)
         {
             if (Path[i].MoveType == MoveType.Jump)
             {
                 Drawer3D.DrawLine(GetPathPoint(Path[i].SourceVoxel), GetPathPoint(Path[i].DestinationVoxel), Color.Red, 0.1f);
             }
             else
             {
                 Drawer3D.DrawLine(GetPathPoint(Path[i].SourceVoxel), GetPathPoint(Path[i].DestinationVoxel), Color.Blue, 0.1f);
             }
         }
     }
 }
示例#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.FindValidVoxelNear(chunks, Agent.Position);

                    if (!voxUnder.IsValid)
                    {
                        if (Debugger.Switches.DrawPaths)
                        {
                            Creature.World.UserInterface.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
                {
                    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 && response.Path != null && response.Path.Count > 0)
                        {
                            var goal = GetGoal();

                            bool obeysGoal = goal == null ? false : (response.Success && (goal.IsInGoalRegion(response.Path.Last().DestinationVoxel)));

                            if (Debugger.Switches.DrawPaths)
                            {
                                if (obeysGoal)
                                {
                                    Creature.World.UserInterface.MakeWorldPopup(String.Format("Using Old Path", response.Result), Creature.Physics, -10, 1);
                                }
                                else
                                {
                                    Creature.World.UserInterface.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.UserInterface.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.UserInterface.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
        public override IEnumerable <Status> Run()
        {
            Path     = null;
            Timeouts = 0;
            PlannerTimer.Reset(PlannerTimer.TargetTimeSeconds);
            Voxel voxUnder = new Voxel();

            while (true)
            {
                if (Path != null)
                {
                    yield return(Status.Success);

                    break;
                }

                if (Timeouts > MaxTimeouts)
                {
                    yield return(Status.Fail);

                    break;
                }

                PlannerTimer.Update(DwarfTime.LastTime);

                ChunkManager chunks = PlayState.ChunkManager;
                if (PlannerTimer.HasTriggered || Timeouts == 0)
                {
                    if (!chunks.ChunkData.GetVoxel(Agent.Position, ref voxUnder))
                    {
                        Creature.DrawIndicator(IndicatorManager.StandardIndicators.Question);
                        yield return(Status.Fail);

                        break;
                    }


                    if (Target == null && Type != PlanType.Edge)
                    {
                        Creature.DrawIndicator(IndicatorManager.StandardIndicators.Question);
                        yield return(Status.Fail);

                        break;
                    }

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

                        switch (Type)
                        {
                        case PlanType.Radius:
                            aspr.GoalRegion = new SphereGoalRegion(Target, Radius);
                            break;

                        case PlanType.Into:
                            aspr.GoalRegion = new VoxelGoalRegion(Target);
                            break;

                        case PlanType.Adjacent:
                            aspr.GoalRegion = new AdjacentVoxelGoalRegion2D(Target);
                            break;

                        case PlanType.Edge:
                            aspr.GoalRegion = new EdgeGoalRegion();
                            break;
                        }

                        PlanSubscriber.SendRequest(aspr);
                        PlannerTimer.Reset(PlannerTimer.TargetTimeSeconds);
                        WaitingOnResponse = true;
                        yield return(Status.Running);
                    }
                    else
                    {
                        Path = null;
                        Creature.DrawIndicator(IndicatorManager.StandardIndicators.Question);
                        yield return(Status.Fail);

                        break;
                    }

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

                    while (PlanSubscriber.Responses.Count > 0)
                    {
                        AStarPlanResponse response;
                        PlanSubscriber.Responses.TryDequeue(out response);

                        if (response.Success)
                        {
                            Path = response.Path;

                            if (Type == PlanType.Adjacent && Path.Count > 0)
                            {
                                Path.RemoveAt(Path.Count - 1);
                            }
                            WaitingOnResponse = false;

                            statusResult = Status.Success;
                        }
                        else
                        {
                            Creature.DrawIndicator(IndicatorManager.StandardIndicators.Question);
                            statusResult = Status.Fail;
                        }
                    }
                    yield return(statusResult);
                }
            }
        }
示例#7
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.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);
                        }
                    }
                    agent.AI.AddXP(Math.Max((int)(VoxelLibrary.GetVoxelType(blackBoardVoxel.TypeName).StartingHealth / 4), 1));
                    agent.Stats.NumBlocksDestroyed++;
                }

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