(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.

This commit is contained in:
Joonas Rikkonen
2019-04-08 12:01:54 +03:00
parent 55eecc49d8
commit 47ee14227e
6 changed files with 56 additions and 28 deletions

View File

@@ -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);

View File

@@ -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))
{

View File

@@ -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);
}
}
}

View File

@@ -10,15 +10,16 @@ namespace Barotrauma
protected List<T> targets = new List<T>();
protected Dictionary<T, AIObjective> objectives = new Dictionary<T, AIObjective>();
protected HashSet<T> ignoreList = new HashSet<T>();
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;

View File

@@ -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<AIObjective, CoroutineHandle> DelayedObjectives { get; private set; } = new Dictionary<AIObjective, CoroutineHandle>();

View File

@@ -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);
}