예제 #1
0
        public void Wander(float deltaTime)
        {
            if (character.IsClimbing)
            {
                return;
            }
            //steer away from edges of the hull
            var currentHull = character.CurrentHull;

            if (currentHull != null)
            {
                float roomWidth = currentHull.Rect.Width;
                if (roomWidth < WallAvoidDistance * 4)
                {
                    PathSteering.Reset();
                }
                else
                {
                    float leftDist  = character.Position.X - currentHull.Rect.X;
                    float rightDist = currentHull.Rect.Right - character.Position.X;
                    if (leftDist < WallAvoidDistance && rightDist < WallAvoidDistance)
                    {
                        if (Math.Abs(rightDist - leftDist) > WallAvoidDistance / 2)
                        {
                            PathSteering.SteeringManual(deltaTime, Vector2.UnitX * Math.Sign(rightDist - leftDist));
                        }
                        else
                        {
                            PathSteering.Reset();
                        }
                    }
                    else if (leftDist < WallAvoidDistance)
                    {
                        float speed = (WallAvoidDistance - leftDist) / WallAvoidDistance;
                        PathSteering.SteeringManual(deltaTime, Vector2.UnitX * MathHelper.Clamp(speed, 0.25f, 1));
                        PathSteering.WanderAngle = 0.0f;
                    }
                    else if (rightDist < WallAvoidDistance)
                    {
                        float speed = (WallAvoidDistance - rightDist) / WallAvoidDistance;
                        PathSteering.SteeringManual(deltaTime, -Vector2.UnitX * MathHelper.Clamp(speed, 0.25f, 1));
                        PathSteering.WanderAngle = MathHelper.Pi;
                    }
                    else
                    {
                        SteeringManager.SteeringWander();
                    }
                }
            }
            else
            {
                SteeringManager.SteeringWander();
            }
            if (!character.AnimController.InWater)
            {
                //reset vertical steering to prevent dropping down from platforms etc
                character.AIController.SteeringManager.ResetY();
            }
        }
예제 #2
0
        protected override void Act(float deltaTime)
        {
            if (PathSteering == null)
            {
                return;
            }

            //don't keep dragging others when idling
            if (character.SelectedCharacter != null)
            {
                character.DeselectCharacter();
            }
            if (!character.IsClimbing)
            {
                character.SelectedConstruction = null;
            }

            bool currentTargetIsInvalid = currentTarget == null || IsForbidden(currentTarget) ||
                                          (PathSteering.CurrentPath != null && PathSteering.CurrentPath.Nodes.Any(n => HumanAIController.UnsafeHulls.Contains(n.CurrentHull)));

            if (currentTargetIsInvalid || (currentTarget == null && IsForbidden(character.CurrentHull)))
            {
                newTargetTimer  = 0;
                standStillTimer = 0;
            }
            if (character.AnimController.InWater || character.IsClimbing)
            {
                standStillTimer = 0;
            }
            if (newTargetTimer <= 0.0f)
            {
                currentTarget = FindRandomHull();

                if (currentTarget != null)
                {
                    string errorMsg = null;
#if DEBUG
                    bool isRoomNameFound = currentTarget.RoomName != null;
                    errorMsg = "(Character " + character.Name + " idling, target " + (isRoomNameFound ? currentTarget.RoomName : currentTarget.ToString()) + ")";
#endif
                    var path = PathSteering.PathFinder.FindPath(character.SimPosition, currentTarget.SimPosition, errorMsg);
                    PathSteering.SetPath(path);
                }

                newTargetTimer = currentTarget != null && character.AnimController.InWater ? newTargetIntervalMin : Rand.Range(newTargetIntervalMin, newTargetIntervalMax);
            }

            newTargetTimer -= deltaTime;

            //wander randomly
            // - if reached the end of the path
            // - if the target is unreachable
            // - if the path requires going outside
            if (SteeringManager != PathSteering || (PathSteering.CurrentPath != null &&
                                                    (PathSteering.CurrentPath.NextNode == null || PathSteering.CurrentPath.Unreachable || PathSteering.CurrentPath.HasOutdoorsNodes)))
            {
                standStillTimer -= deltaTime;
                if (standStillTimer > 0.0f)
                {
                    walkDuration = Rand.Range(walkDurationMin, walkDurationMax);
                    PathSteering.Reset();
                    return;
                }
                if (standStillTimer < -walkDuration)
                {
                    standStillTimer = Rand.Range(standStillMin, standStillMax);
                }

                Wander(deltaTime);
                return;
            }

            if (currentTarget != null)
            {
                character.AIController.SteeringManager.SteeringSeek(currentTarget.SimPosition);
            }
        }
예제 #3
0
        protected override void Act(float deltaTime)
        {
            if (PathSteering == null)
            {
                return;
            }

            //don't keep dragging others when idling
            if (character.SelectedCharacter != null)
            {
                character.DeselectCharacter();
            }
            if (!character.IsClimbing)
            {
                character.SelectedConstruction = null;
            }

            bool currentHullForbidden = IsForbidden(character.CurrentHull);

            if (!currentHullForbidden && !character.AnimController.InWater && !character.IsClimbing && HumanAIController.ObjectiveManager.WaitTimer > 0)
            {
                SteeringManager.Reset();
                return;
            }

            bool currentTargetIsInvalid = currentTarget == null || IsForbidden(currentTarget) ||
                                          (PathSteering.CurrentPath != null && PathSteering.CurrentPath.Nodes.Any(n => HumanAIController.UnsafeHulls.Contains(n.CurrentHull)));

            if (currentTargetIsInvalid || (currentTarget == null && currentHullForbidden))
            {
                newTargetTimer  = 0;
                standStillTimer = 0;
            }
            else if (character.IsClimbing)
            {
                if (currentTarget == null)
                {
                    newTargetTimer = 0;
                }
                else
                {
                    // Don't allow new targets when climbing.
                    newTargetTimer = Math.Max(newTargetIntervalMin, newTargetTimer);
                }
            }
            else if (character.AnimController.InWater)
            {
                if (currentTarget == null)
                {
                    newTargetTimer = 0;
                }
            }
            if (newTargetTimer <= 0.0f)
            {
                if (!searchingNewHull)
                {
                    //find all available hulls first
                    FindTargetHulls();
                    searchingNewHull = true;
                    return;
                }
                else if (targetHulls.Count > 0)
                {
                    //choose a random available hull
                    var randomHull = ToolBox.SelectWeightedRandom(targetHulls, hullWeights, Rand.RandSync.Unsynced);

                    bool isCurrentHullOK = !HumanAIController.UnsafeHulls.Contains(character.CurrentHull) && !IsForbidden(character.CurrentHull);
                    if (isCurrentHullOK)
                    {
                        // Check that there is no unsafe or forbidden hulls on the way to the target
                        // Only do this when the current hull is ok, because otherwise the would block all paths from the current hull to the target hull.
                        var path = PathSteering.PathFinder.FindPath(character.SimPosition, randomHull.SimPosition);
                        if (path.Unreachable ||
                            path.Nodes.Any(n => HumanAIController.UnsafeHulls.Contains(n.CurrentHull) || IsForbidden(n.CurrentHull)))
                        {
                            //can't go to this room, remove it from the list and try another room next frame
                            int index = targetHulls.IndexOf(randomHull);
                            targetHulls.RemoveAt(index);
                            hullWeights.RemoveAt(index);
                            PathSteering.Reset();
                            return;
                        }
                    }
                    currentTarget    = randomHull;
                    searchingNewHull = false;
                }

                if (currentTarget != null)
                {
                    character.AIController.SelectTarget(currentTarget.AiTarget);
                    string errorMsg = null;
#if DEBUG
                    bool isRoomNameFound = currentTarget.RoomName != null;
                    errorMsg = "(Character " + character.Name + " idling, target " + (isRoomNameFound ? currentTarget.RoomName : currentTarget.ToString()) + ")";
#endif
                    var path = PathSteering.PathFinder.FindPath(character.SimPosition, currentTarget.SimPosition, errorMsg);
                    PathSteering.SetPath(path);
                }

                newTargetTimer = currentTarget != null && character.AnimController.InWater ? newTargetIntervalMin : Rand.Range(newTargetIntervalMin, newTargetIntervalMax);
            }

            newTargetTimer -= deltaTime;

            //wander randomly
            // - if reached the end of the path
            // - if the target is unreachable
            // - if the path requires going outside
            if (!character.IsClimbing)
            {
                if (SteeringManager != PathSteering || (PathSteering.CurrentPath != null &&
                                                        (PathSteering.CurrentPath.NextNode == null || PathSteering.CurrentPath.Unreachable || PathSteering.CurrentPath.HasOutdoorsNodes)))
                {
                    if (!character.AnimController.InWater)
                    {
                        standStillTimer -= deltaTime;
                        if (standStillTimer > 0.0f)
                        {
                            walkDuration = Rand.Range(walkDurationMin, walkDurationMax);
                            PathSteering.Reset();
                            return;
                        }
                        if (standStillTimer < -walkDuration)
                        {
                            standStillTimer = Rand.Range(standStillMin, standStillMax);
                        }
                    }
                    Wander(deltaTime);
                    return;
                }
            }

            if (currentTarget != null)
            {
                character.AIController.SteeringManager.SteeringSeek(currentTarget.SimPosition);
            }
        }