public void PerformCurrentAction() { Creature.MoveAction action = Path.First(); float t = 0; int currentIndex = 0; if (!GetCurrentAction(ref action, ref t, ref currentIndex)) { return; } int nextID = currentIndex + 1; bool hasNextAction = false; Vector3 half = Vector3.One * 0.5f; Vector3 nextPosition = Vector3.Zero; Vector3 currPosition = action.Voxel.Position + half; currPosition += RandomPositionOffsets[currentIndex]; if (nextID < Path.Count) { hasNextAction = true; nextPosition = Path[nextID].Voxel.Position; nextPosition += RandomPositionOffsets[nextID] + half; } Matrix transform = Agent.Physics.LocalTransform; Vector3 diff = (nextPosition - currPosition); switch (action.MoveType) { case Creature.MoveType.Walk: Creature.OverrideCharacterMode = false; if (hasNextAction) { transform.Translation = diff * t + currPosition; Agent.Physics.Velocity = diff; } else { transform.Translation = currPosition; } break; case Creature.MoveType.Swim: Creature.OverrideCharacterMode = false; if (hasNextAction) { transform.Translation = diff * t + currPosition; Agent.Physics.Velocity = diff; } else { transform.Translation = currPosition; } break; case Creature.MoveType.Jump: Creature.OverrideCharacterMode = false; if (hasNextAction) { float z = Easing.Ballistic(t, 1.0f, 1.0f); Vector3 start = currPosition; Vector3 end = nextPosition; Vector3 dx = (end - start) * t + start; dx.Y = start.Y * (1 - t) + end.Y * (t) + z; transform.Translation = dx; Agent.Physics.Velocity = new Vector3(diff.X, (dx.Y - Agent.Physics.Position.Y), diff.Z); } else { transform.Translation = currPosition; } break; case Creature.MoveType.Fall: Creature.OverrideCharacterMode = false; if (hasNextAction) { transform.Translation = diff * t + currPosition; Agent.Physics.Velocity = diff; } else { transform.Translation = currPosition; } break; case Creature.MoveType.Climb: Creature.OverrideCharacterMode = true; Creature.CurrentCharacterMode = Creature.CharacterMode.Walking; if (hasNextAction) { transform.Translation = diff * t + currPosition; Agent.Physics.Velocity = diff; } else { transform.Translation = currPosition; } break; } Agent.Physics.LocalTransform = transform; }
public override IEnumerable <Status> Run() { Creature.CurrentCharacterMode = Creature.CharacterMode.Walking; Creature.OverrideCharacterMode = false; while (true) { // ERROR CHECKS / INITIALIZING Agent.Physics.Orientation = Physics.OrientMode.RotateY; //Agent.Physics.CollideMode = Physics.CollisionMode.UpDown; List <Creature.MoveAction> path = GetPath(); if (path == null) { SetPath(null); Creature.DrawIndicator(IndicatorManager.StandardIndicators.Question); yield return(Status.Fail); break; } else if (path.Count > 0) { TargetVoxel = path.ElementAt(0).Voxel; } else { yield return(Status.Success); break; } Creature.MoveAction currentAction = path.ElementAt(0); // IF WE ARE MOVING if (TargetVoxel != null) { Agent.Physics.IsSleeping = false; Agent.LocalControlTimeout.Update(DwarfTime.LastTime); ValidPathTimer.Update(DwarfTime.LastTime); // Check if the path has been made invalid if (ValidPathTimer.HasTriggered && !IsPathValid(path)) { Creature.DrawIndicator(IndicatorManager.StandardIndicators.Question); yield return(Status.Fail); } if (Agent.LocalControlTimeout.HasTriggered) { Vector3 target = TargetVoxel.Position + new Vector3(.5f, .5f, .5f); float distToTarget = (target - Agent.Position).Length(); while (distToTarget > 0.1f) { Agent.Position = 0.9f * Agent.Position + 0.1f * target; distToTarget = (target - Agent.Position).Length(); yield return(Status.Running); } Agent.LocalControlTimeout.Reset(Agent.LocalControlTimeout.TargetTimeSeconds); Creature.DrawIndicator(IndicatorManager.StandardIndicators.Question); yield return(Status.Running); } if (PreviousTargetVoxel == null) { LocalTarget = TargetVoxel.Position + new Vector3(0.5f, 0.5f, 0.5f); } else { LocalTarget = MathFunctions.ClosestPointToLineSegment(Agent.Position, PreviousTargetVoxel.Position, TargetVoxel.Position, 0.25f) + new Vector3(0.5f, 0.5f, 0.5f); } Vector3 desiredVelocity = (LocalTarget - Agent.Position); desiredVelocity.Normalize(); desiredVelocity *= Creature.Stats.MaxSpeed; Vector3 output = Agent.Creature.Controller.GetOutput((float)DwarfTime.LastTime.ElapsedGameTime.TotalSeconds, desiredVelocity, Creature.Physics.Velocity); output.Y = 0.0f; Agent.Creature.Physics.ApplyForce(output * 0.25f, (float)DwarfTime.LastTime.ElapsedGameTime.TotalSeconds); float yDifference = (LocalTarget - Agent.Position).Y; if (yDifference > 0.25f) { Agent.Jump(DwarfTime.LastTime); } if (Agent.DrawPath) { Drawer3D.DrawLineList( new List <Vector3> { LocalTarget, Agent.Creature.Physics.GlobalTransform.Translation }, Color.White, 0.01f); List <Vector3> points = path.Select(v => v.Voxel.Position + new Vector3(0.5f, 0.5f, 0.5f)).ToList(); Drawer3D.DrawLineList(points, Color.Red, 0.1f); } bool goToNextNode; if (path.Count > 1) { goToNextNode = (yDifference < 0.05 && (LocalTarget - Agent.Creature.Physics.GlobalTransform.Translation).Length() < 0.5f); } else { goToNextNode = (LocalTarget - Agent.Creature.Physics.GlobalTransform.Translation).Length() < 0.25f; } if (goToNextNode) { if (path.Count > 0) { PreviousTargetVoxel = TargetVoxel; Agent.LocalControlTimeout.Reset(Agent.LocalControlTimeout.TargetTimeSeconds); TargetVoxel = path[0].Voxel; path.RemoveAt(0); } else { PreviousTargetVoxel = null; SetPath(null); yield return(Status.Success); break; } } } else { PreviousTargetVoxel = null; Creature.DrawIndicator(IndicatorManager.StandardIndicators.Question); yield return(Status.Fail); break; } yield return(Status.Running); } }
public IEnumerable <Status> PerformCurrentAction() { Creature.MoveAction action = Path.First(); float t = 0; int currentIndex = 0; if (!GetCurrentAction(ref action, ref t, ref currentIndex)) { yield break; } int nextID = currentIndex + 1; bool hasNextAction = false; Vector3 half = Vector3.One * 0.5f; half.Y = Creature.Physics.BoundingBox.Extents().Y *2; Vector3 nextPosition = Vector3.Zero; Vector3 currPosition = action.Voxel.Position + half; Vector3 prevPosition = currPosition; if (currentIndex > 0 && Path.Count > 0) { prevPosition = Path.ElementAt(currentIndex - 1).Voxel.Position + half; } currPosition += RandomPositionOffsets[currentIndex]; if (nextID < Path.Count) { hasNextAction = true; nextPosition = Path[nextID].Voxel.Position; nextPosition += RandomPositionOffsets[nextID] + half; } Matrix transform = Agent.Physics.LocalTransform; Vector3 diff = (nextPosition - currPosition); switch (action.MoveType) { case Creature.MoveType.Walk: Creature.OverrideCharacterMode = false; Creature.CurrentCharacterMode = Creature.CharacterMode.Walking; if (hasNextAction) { transform.Translation = diff * t + currPosition; Agent.Physics.Velocity = diff; } else { transform.Translation = currPosition; } break; case Creature.MoveType.Swim: Creature.OverrideCharacterMode = false; Creature.CurrentCharacterMode = Creature.CharacterMode.Swimming; if (hasNextAction) { transform.Translation = diff * t + currPosition + new Vector3(0, 0.5f, 0); Agent.Physics.Velocity = diff; } else { transform.Translation = currPosition; } break; case Creature.MoveType.Jump: Creature.OverrideCharacterMode = false; Creature.CurrentCharacterMode = Creature.Physics.Velocity.Y > 0 ? Creature.CharacterMode.Jumping : Creature.CharacterMode.Falling; if (hasNextAction) { float z = Easing.Ballistic(t, 1.0f, 1.0f); Vector3 start = currPosition; Vector3 end = nextPosition; Vector3 dx = (end - start) * t + start; dx.Y = start.Y * (1 - t) + end.Y * (t) + z; transform.Translation = dx; Agent.Physics.Velocity = new Vector3(diff.X, (dx.Y - Agent.Physics.Position.Y), diff.Z); } else { transform.Translation = currPosition; } break; case Creature.MoveType.Fall: Creature.OverrideCharacterMode = false; Creature.CurrentCharacterMode = Creature.CharacterMode.Falling; if (hasNextAction) { transform.Translation = diff * t + currPosition; Agent.Physics.Velocity = diff; } else { transform.Translation = currPosition; } break; case Creature.MoveType.Climb: case Creature.MoveType.ClimbWalls: Creature.OverrideCharacterMode = false; Creature.CurrentCharacterMode = Creature.CharacterMode.Walking; Creature.OverrideCharacterMode = true; if (hasNextAction) { transform.Translation = diff * t + currPosition; Agent.Physics.Velocity = diff; } else { transform.Translation = currPosition; } break; case Creature.MoveType.Fly: Creature.OverrideCharacterMode = false; Creature.CurrentCharacterMode = Creature.CharacterMode.Flying; Creature.OverrideCharacterMode = true; if (hasNextAction) { transform.Translation = diff * t + currPosition; Agent.Physics.Velocity = diff; } else { transform.Translation = currPosition; } break; case Creature.MoveType.DestroyObject: if (action.InteractObject.IsDead) { Creature.OverrideCharacterMode = false; Creature.CurrentCharacterMode = Creature.CharacterMode.Walking; if (hasNextAction) { transform.Translation = diff * t + currPosition; Agent.Physics.Velocity = diff; } else { transform.Translation = currPosition; } } float current = (TrajectoryTimer.CurrentTimeSeconds); Matrix transformMatrix = Agent.Physics.LocalTransform; transformMatrix.Translation = prevPosition; var act = new MeleeAct(Creature.AI, action.InteractObject.GetRootComponent().GetChildrenOfType <Body>(true).FirstOrDefault()); act.Initialize(); foreach (Status status in act.Run()) { Agent.Physics.LocalTransform = transformMatrix; TrajectoryTimer.StartTimeSeconds = (float)DwarfTime.LastTime.TotalGameTime.TotalSeconds - current; yield return(status); } break; } Agent.Physics.LocalTransform = transform; }