diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjective.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjective.cs index ba4320194..7824857ad 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjective.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjective.cs @@ -140,6 +140,7 @@ namespace Barotrauma protected virtual bool ShouldInterruptSubObjective(AIObjective subObjective) => false; public virtual void OnSelected() { } + public virtual void Reset() { } protected abstract void Act(float deltaTime); diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveFixLeak.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveFixLeak.cs index d575a62e4..9115f3993 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveFixLeak.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveFixLeak.cs @@ -101,7 +101,8 @@ namespace Barotrauma HumanAIController.AnimController.Crouching = true; } - float reach = HumanAIController.AnimController.ArmLength + ConvertUnits.ToSimUnits(repairTool.Range); + //float reach = HumanAIController.AnimController.ArmLength + ConvertUnits.ToSimUnits(repairTool.Range); + float reach = ConvertUnits.ToSimUnits(repairTool.Range); bool cannotReach = ConvertUnits.ToSimUnits(gapDiff.Length()) > reach; if (cannotReach) { @@ -110,14 +111,19 @@ namespace Barotrauma // Check if the objective is already removed -> completed/impossible if (!subObjectives.Contains(gotoObjective)) { + if (!gotoObjective.CanBeCompleted) + { + abandon = true; + } gotoObjective = null; + return; } } else { gotoObjective = new AIObjectiveGoTo(ConvertUnits.ToSimUnits(GetStandPosition()), character) { - CloseEnough = reach * 0.75f + CloseEnough = reach }; if (!subObjectives.Contains(gotoObjective)) { diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveGoTo.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveGoTo.cs index f96dd6153..6cadf0d2e 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveGoTo.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveGoTo.cs @@ -66,9 +66,12 @@ namespace Barotrauma if (!canComplete) { #if DEBUG - DebugConsole.NewMessage($"{character.Name}: Cannot reach the target."); + DebugConsole.NewMessage($"{character.Name}: Cannot reach the target: {(Target != null ? Target.ToString() : TargetPos.ToString())}", Color.Yellow); #endif - character.Speak(TextManager.Get("DialogCannotReach"), identifier: "cannotreach", minDurationBetweenSimilar: 10.0f); + if (HumanAIController.ObjectiveManager.CurrentOrder != null) + { + character.Speak(TextManager.Get("DialogCannotReach"), identifier: "cannotreach", minDurationBetweenSimilar: 10.0f); + } character.AIController.SteeringManager.Reset(); } return canComplete; @@ -89,6 +92,7 @@ namespace Barotrauma waitUntilPathUnreachable = 1.0f; this.getDivingGearIfNeeded = getDivingGearIfNeeded; + CalculateCloseEnough(); } @@ -100,6 +104,7 @@ namespace Barotrauma waitUntilPathUnreachable = 5.0f; this.getDivingGearIfNeeded = getDivingGearIfNeeded; + CalculateCloseEnough(); } protected override void Act(float deltaTime) @@ -149,9 +154,10 @@ namespace Barotrauma } else { - bool targetIsOutside = (Target != null && Target.Submarine == null) || - (SteeringManager == PathSteering && PathSteering.CurrentPath != null && PathSteering.CurrentPath.HasOutdoorsNodes); - if (targetIsOutside && character.CurrentHull != null && !AllowGoingOutside) + bool isInside = character.CurrentHull != null; + bool insideSteering = SteeringManager == PathSteering && PathSteering.CurrentPath != null; + bool targetIsOutside = (Target != null && Target.Submarine == null) || (insideSteering && PathSteering.CurrentPath.HasOutdoorsNodes); + if (isInside && targetIsOutside && !AllowGoingOutside) { cannotReach = true; } @@ -186,11 +192,8 @@ namespace Barotrauma bool completed = false; - float allowedDistance = CloseEnough; - if (Target is Item item) { - allowedDistance = Math.Max(ConvertUnits.ToSimUnits(item.InteractDistance), CloseEnough); if (item.IsInsideTrigger(character.WorldPosition)) completed = true; } else if (Target is Character targetCharacter) @@ -198,7 +201,7 @@ namespace Barotrauma if (character.CanInteractWith(targetCharacter)) completed = true; } - completed = completed || Vector2.DistanceSquared(Target != null ? Target.SimPosition : targetPos, character.SimPosition) < allowedDistance * allowedDistance; + completed = completed || Vector2.DistanceSquared(Target != null ? Target.SimPosition : targetPos, character.SimPosition) < CloseEnough * CloseEnough; if (completed) character.AIController.SteeringManager.Reset(); @@ -214,5 +217,11 @@ namespace Barotrauma return (objective.targetPos == targetPos); } + + private void CalculateCloseEnough() + { + float interactionDistance = Target is Item i ? ConvertUnits.ToSimUnits(i.InteractDistance) : 0; + CloseEnough = Math.Max(interactionDistance, CloseEnough); + } } } diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveLoop.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveLoop.cs index 0be3827fd..00c02f3bd 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveLoop.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveLoop.cs @@ -10,15 +10,16 @@ namespace Barotrauma protected List targets = new List(); protected Dictionary objectives = new Dictionary(); protected HashSet ignoreList = new HashSet(); - protected readonly float ignoreListClearInterval = 30; private float ignoreListTimer; - protected readonly float targetUpdateInterval = 2; private float targetUpdateTimer; + // By default, doesn't clear the list automatically + protected virtual float IgnoreListClearInterval => 0; + protected virtual float TargetUpdateInterval => 2; + public AIObjectiveLoop(Character character, string option) : base(character, option) { - FindTargets(); - CreateObjectives(); + Reset(); } protected override void Act(float deltaTime) { } @@ -28,15 +29,18 @@ namespace Barotrauma public override void Update(AIObjectiveManager objectiveManager, float deltaTime) { base.Update(objectiveManager, deltaTime); - if (ignoreListTimer > ignoreListClearInterval) + if (IgnoreListClearInterval > 0) { - Reset(); + if (ignoreListTimer > IgnoreListClearInterval) + { + Reset(); + } + else + { + ignoreListTimer += deltaTime; + } } - else - { - ignoreListTimer += deltaTime; - } - if (targetUpdateTimer > targetUpdateInterval) + if (targetUpdateTimer >= TargetUpdateInterval) { targetUpdateTimer = 0; UpdateTargets(); @@ -52,6 +56,7 @@ namespace Barotrauma if (!objective.Value.CanBeCompleted) { ignoreList.Add(target); + targetUpdateTimer = TargetUpdateInterval; } if (!targets.Contains(target)) { @@ -59,13 +64,13 @@ namespace Barotrauma } } SyncRemovedObjectives(objectives, GetList()); - if (objectives.None()) + if (objectives.None() && targets.Any()) { CreateObjectives(); } } - private void Reset() + public override void Reset() { ignoreList.Clear(); ignoreListTimer = 0; diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveManager.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveManager.cs index 988518098..acafac1ed 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveManager.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveManager.cs @@ -34,9 +34,15 @@ namespace Barotrauma public void AddObjective(AIObjective objective) { - if (Objectives.Find(o => o.IsDuplicate(objective)) != null) return; - - Objectives.Add(objective); + var duplicate = Objectives.Find(o => o.IsDuplicate(objective)); + if (duplicate != null) + { + duplicate.Reset(); + } + else + { + Objectives.Add(objective); + } } public Dictionary DelayedObjectives { get; private set; } = new Dictionary(); diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveRepairItem.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveRepairItem.cs index deb96d2a7..fd2d1c962 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveRepairItem.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveRepairItem.cs @@ -131,7 +131,8 @@ namespace Barotrauma goToObjective = new AIObjectiveGoTo(Item, character); if (repairTool != null) { - goToObjective.CloseEnough = (HumanAIController.AnimController.ArmLength + ConvertUnits.ToSimUnits(repairTool.Range)) * 0.75f; + //goToObjective.CloseEnough = (HumanAIController.AnimController.ArmLength + ConvertUnits.ToSimUnits(repairTool.Range)) * 0.75f; + goToObjective.CloseEnough = ConvertUnits.ToSimUnits(repairTool.Range); } AddSubObjective(goToObjective); }