public Always(Act.Status status) { AlwaysStatus = status; }
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; } }
public IEnumerable <Status> TrackMovingTarget() { while (true) { // This is to support the case of going from one entity to another. if (_entity != null) { Entity = _entity; } Creature.AI.Blackboard.Erase("EntityVoxel"); Act.Status status = SetTargetVoxelFromEntityAct.SetTarget("EntityVoxel", EntityName, Creature); GameComponent entity = Agent.Blackboard.GetData <GameComponent>(EntityName); if (entity == null || entity.IsDead) { yield return(Status.Success); yield break; } if (status != Status.Success) { yield return(Act.Status.Running); } List <MoveAction> existingPath = Creature.AI.Blackboard.GetData <List <MoveAction> >("PathToEntity"); Creature.AI.Blackboard.Erase("PathToEntity"); PlanWithGreedyFallbackAct planAct = new PlanWithGreedyFallbackAct() { Agent = Creature.AI, PathName = "PathToEntity", VoxelName = "EntityVoxel", PlanType = PlanType, Radius = Radius, MaxTimeouts = 1 }; planAct.Initialize(); bool planSucceeded = false; while (true) { Act.Status planStatus = planAct.Tick(); LastTickedChild = planAct; 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; } } if (!planSucceeded) { Agent.SetTaskFailureReason("Failed to reach entity. Path planning failed."); yield return(Act.Status.Fail); yield break; } FollowPathAct followPath = new FollowPathAct(Creature.AI, "PathToEntity") { //BlendEnd = true, //BlendStart = existingPath == null }; followPath.Initialize(); while (true) { if (PlanType == PlanAct.PlanType.Radius && (Creature.Physics.Position - entity.Position).Length() < Radius) { yield return(Act.Status.Success); } Act.Status pathStatus = followPath.Tick(); LastTickedChild = followPath; if (pathStatus == Status.Fail) { break; } else if (pathStatus == Status.Running) { yield return(Act.Status.Running); List <MoveAction> path = Agent.Blackboard.GetData <List <MoveAction> >("PathToEntity"); if (path == null || path.Count == 0) { Agent.SetTaskFailureReason("Failed to find path to entity."); yield return(Act.Status.Fail); yield break; } var under = VoxelHelpers.FindFirstVoxelBelowIncludingWater(new VoxelHandle(entity.World.ChunkManager, GlobalVoxelCoordinate.FromVector3(entity.Position))); bool targetMoved = under == VoxelHandle.InvalidHandle || (path.Last().DestinationVoxel.WorldPosition - under.WorldPosition).Length() > Math.Max(Radius, 2) * 2; if (MovingTarget && (path.Count > 0 && targetMoved)) { break; } if (MovingTarget && (Creature.Physics.Position - entity.Position).Length() < 2) { yield return(Status.Success); yield break; } continue; } else if (pathStatus == Status.Success) { yield return(Act.Status.Success); yield break; } } yield return(Act.Status.Running); } }
public override void Update(DwarfTime gameTime, ChunkManager chunks, Camera camera) { IdleTimer.Update(gameTime); SpeakTimer.Update(gameTime); OrderEnemyAttack(); DeleteBadTasks(); PreEmptTasks(); if (Status.Energy.IsUnhappy() && PlayState.Time.IsNight()) { Task toReturn = new SatisfyTirednessTask(); toReturn.SetupScript(Creature); if (!Tasks.Contains(toReturn)) { Tasks.Add(toReturn); } } if (Status.Hunger.IsUnhappy() && Faction.CountResourcesWithTag(Resource.ResourceTags.Food) > 0) { Task toReturn = new SatisfyHungerTask(); toReturn.SetupScript(Creature); if (!Tasks.Contains(toReturn)) { Tasks.Add(toReturn); } } if (CurrentTask != null && CurrentAct != null) { Act.Status status = CurrentAct.Tick(); bool retried = false; if (status == Act.Status.Fail) { if (CurrentTask.ShouldRetry(Creature)) { if (!Tasks.Contains(CurrentTask)) { CurrentTask.Priority = Task.PriorityType.Eventually; Tasks.Add(CurrentTask); CurrentTask.SetupScript(Creature); retried = true; } } } if (status != Act.Status.Running && !retried) { CurrentTask = null; } } else { bool tantrum = false; if (Status.Happiness.IsUnhappy()) { tantrum = MathFunctions.Rand(0, 1) < 0.25f; } Task goal = GetEasiestTask(Tasks); if (goal != null) { if (tantrum) { Creature.DrawIndicator(IndicatorManager.StandardIndicators.Sad); if (Creature.Allies == "Dwarf") { PlayState.AnnouncementManager.Announce(Stats.FullName + " (" + Stats.CurrentLevel.Name + ")" + " refuses to work!", "Our employee is unhappy, and would rather not work!", ZoomToMe); } CurrentTask = null; } else { IdleTimer.Reset(IdleTimer.TargetTimeSeconds); goal.SetupScript(Creature); CurrentTask = goal; Tasks.Remove(goal); } } else { CurrentTask = ActOnIdle(); } } PlannerTimer.Update(gameTime); UpdateThoughts(); UpdateXP(); base.Update(gameTime, chunks, camera); }
public IEnumerable <Status> TrackMovingTarget() { int maxFailures = 10; int currentFailures = 0; while (true) { Creature.AI.Blackboard.Erase("EntityVoxel"); Act.Status status = SetTargetVoxelFromEntityAct.SetTarget("EntityVoxel", EntityName, Creature); Body entity = Agent.Blackboard.GetData <Body>(EntityName); if (entity == null || entity.IsDead) { yield return(Status.Success); yield break; } if (status != Status.Success) { yield return(Act.Status.Running); } Creature.AI.Blackboard.Erase("PathToEntity"); PlanAct planAct = new PlanAct(Creature.AI, "PathToEntity", "EntityVoxel", PlanType) { Radius = Radius }; 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; } } if (!planSucceeded) { currentFailures++; yield return(Act.Status.Running); Creature.CurrentCharacterMode = Creature.CharacterMode.Idle; Creature.Physics.Velocity = Vector3.Zero; if (currentFailures > maxFailures) { yield return(Act.Status.Fail); yield break; } continue; } FollowPathAct followPath = new FollowPathAct(Creature.AI, "PathToEntity"); followPath.Initialize(); while (true) { if (PlanType == PlanAct.PlanType.Radius && (Creature.Physics.Position - entity.Position).Length() < Radius) { yield return(Act.Status.Success); } Act.Status pathStatus = followPath.Tick(); if (pathStatus == Status.Fail) { break; } else if (pathStatus == Status.Running) { yield return(Act.Status.Running); List <Creature.MoveAction> path = Agent.Blackboard.GetData <List <Creature.MoveAction> >("PathToEntity"); if (path.Count > 0 && (path.Last().Voxel.Position - entity.LocalTransform.Translation).Length() > 4) { break; } if (MovingTarget && (Creature.Physics.Position - entity.Position).Length() < 2) { yield return(Status.Success); yield break; } continue; } else if (pathStatus == Status.Success) { yield return(Act.Status.Success); yield break; } } yield return(Act.Status.Running); } }
public IEnumerable <Status> TrackMovingTarget() { while (true) { // This is to support the case of going from one entity to another. if (_entity != null) { Entity = _entity; } Creature.AI.Blackboard.Erase("EntityVoxel"); Act.Status status = SetTargetVoxelFromEntityAct.SetTarget("EntityVoxel", EntityName, Creature); Body entity = Agent.Blackboard.GetData <Body>(EntityName); if (entity == null || entity.IsDead) { yield return(Status.Success); yield break; } if (status != Status.Success) { yield return(Act.Status.Running); } List <MoveAction> existingPath = Creature.AI.Blackboard.GetData <List <MoveAction> >("PathToEntity"); Creature.AI.Blackboard.Erase("PathToEntity"); PlanWithGreedyFallbackAct planAct = new PlanWithGreedyFallbackAct() { Agent = Creature.AI, PathName = "PathToEntity", VoxelName = "EntityVoxel", PlanType = PlanType, Radius = Radius, MaxTimeouts = 1 }; planAct.Initialize(); bool planSucceeded = false; while (true) { Act.Status planStatus = planAct.Tick(); LastTickedChild = planAct; 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; } } if (!planSucceeded) { Agent.SetMessage("Failed to reach entity. Path planning failed."); yield return(Act.Status.Fail); yield break; } FollowPathAct followPath = new FollowPathAct(Creature.AI, "PathToEntity") { BlendEnd = true, BlendStart = existingPath == null }; followPath.Initialize(); while (true) { if (PlanType == PlanAct.PlanType.Radius && (Creature.Physics.Position - entity.Position).Length() < Radius) { yield return(Act.Status.Success); } Act.Status pathStatus = followPath.Tick(); LastTickedChild = followPath; if (pathStatus == Status.Fail) { break; } else if (pathStatus == Status.Running) { yield return(Act.Status.Running); List <MoveAction> path = Agent.Blackboard.GetData <List <MoveAction> >("PathToEntity"); if (path == null || path.Count == 0) { Agent.SetMessage("Failed to find path to entity."); yield return(Act.Status.Fail); yield break; } bool targetMoved = (path.Last().DestinationVoxel.WorldPosition - entity.LocalTransform.Translation).Length() > Math.Max(Radius, 2) * 2; if (MovingTarget && (path.Count > 0 && targetMoved)) { break; } if (MovingTarget && (Creature.Physics.Position - entity.Position).Length() < 2) { yield return(Status.Success); yield break; } continue; } else if (pathStatus == Status.Success) { yield return(Act.Status.Success); yield break; } } yield return(Act.Status.Running); } }
public IEnumerable <Status> TrackMovingTarget() { while (true) { Creature.AI.Blackboard.Erase("EntityVoxel"); Act.Status status = SetTargetVoxelFromEntityAct.SetTarget("EntityVoxel", EntityName, Creature); Body entity = Agent.Blackboard.GetData <Body>(EntityName); if (entity == null || entity.IsDead) { yield return(Status.Success); yield break; } if (status != Status.Success) { yield return(Act.Status.Running); } Creature.AI.Blackboard.Erase("PathToEntity"); PlanAct planAct = new PlanAct(Creature.AI, "PathToEntity", "EntityVoxel", PlanAct.PlanType.Adjacent); 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; } } if (!planSucceeded) { yield return(Act.Status.Running); continue; } FollowPathAnimationAct followPath = new FollowPathAnimationAct(Creature.AI, "PathToEntity"); followPath.Initialize(); while (true) { Act.Status pathStatus = followPath.Tick(); if (pathStatus == Status.Fail) { break; } else if (pathStatus == Status.Running) { yield return(Act.Status.Running); List <Creature.MoveAction> path = Agent.Blackboard.GetData <List <Creature.MoveAction> >("PathToEntity"); if (path.Count > 0 && (path.Last().Voxel.Position - entity.LocalTransform.Translation).Length() > 4) { break; } if (MovingTarget && (Creature.Physics.Position - entity.Position).Length() < 2) { yield return(Status.Success); yield break; } continue; } else if (pathStatus == Status.Success) { yield return(Act.Status.Success); yield break; } } yield return(Act.Status.Running); } }