From 47ee14227e624bc31a63a39f28a52c651f20d296 Mon Sep 17 00:00:00 2001 From: Joonas Rikkonen Date: Mon, 8 Apr 2019 12:01:54 +0300 Subject: [PATCH] (551008fc1) Abandon FixLeakObjective when the goto subobjective cannot be completed. Reset AIObjectiveLoops when the objective is activated or added. Don't clear ignored targets periodically by default. Calculate AIObjectiveGoTo CloseEnough when the objective is created. Don't use arm length in CloseEnough, because it's not used in range checks. Partial fixes to #1343. --- .../Characters/AI/Objectives/AIObjective.cs | 1 + .../AI/Objectives/AIObjectiveFixLeak.cs | 10 ++++-- .../AI/Objectives/AIObjectiveGoTo.cs | 27 ++++++++++------ .../AI/Objectives/AIObjectiveLoop.cs | 31 +++++++++++-------- .../AI/Objectives/AIObjectiveManager.cs | 12 +++++-- .../AI/Objectives/AIObjectiveRepairItem.cs | 3 +- 6 files changed, 56 insertions(+), 28 deletions(-) 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); }