(ab2157c70) Remove KeepDivingGear property, because it can cause issues when the objective tree is deep. Checking the property is possible via recursion, but it seems that the checks can miss a frame. Instead, let's just make it simple and remove the diving suit only when idling.

This commit is contained in:
Joonas Rikkonen
2019-05-16 05:37:46 +03:00
parent c060c90cba
commit 96eb27140e
24 changed files with 334 additions and 175 deletions
@@ -164,7 +164,7 @@ namespace Barotrauma
{
bool oxygenLow = Character.OxygenAvailable < CharacterHealth.LowOxygenThreshold;
bool highPressure = Character.CurrentHull == null || Character.CurrentHull.LethalPressure > 0 && Character.PressureProtection <= 0;
bool shouldKeepTheGearOn = objectiveManager.CurrentObjective.KeepDivingGearOn;
bool shouldKeepTheGearOn = !ObjectiveManager.IsCurrentObjective<AIObjectiveIdle>();
bool removeDivingSuit = (oxygenLow && !highPressure) || (!shouldKeepTheGearOn && Character.CurrentHull.WaterPercentage < 1 && !Character.IsClimbing && steeringManager == insideSteering && !PathSteering.InStairs);
if (removeDivingSuit)
@@ -12,7 +12,6 @@ namespace Barotrauma
public abstract string DebugTag { get; }
public virtual bool ForceRun => false;
public virtual bool KeepDivingGearOn => false;
/// <summary>
/// Run the main objective with all subobjectives concurrently?
@@ -11,7 +11,6 @@ namespace Barotrauma
class AIObjectiveCombat : AIObjective
{
public override string DebugTag => "combat";
public override bool KeepDivingGearOn => true;
public bool useCoolDown = true;
const float CoolDown = 10.0f;
@@ -11,7 +11,6 @@ namespace Barotrauma
{
public override string DebugTag => "extinguish fire";
public override bool ForceRun => true;
public override bool KeepDivingGearOn => true;
public override bool ConcurrentObjectives => true;
private readonly Hull targetHull;
@@ -8,7 +8,6 @@ namespace Barotrauma
{
public override string DebugTag => "extinguish fires";
public override bool ForceRun => true;
public override bool KeepDivingGearOn => true;
public AIObjectiveExtinguishFires(Character character, AIObjectiveManager objectiveManager, float priorityModifier = 1) : base(character, objectiveManager, priorityModifier) { }
@@ -10,7 +10,6 @@ namespace Barotrauma
class AIObjectiveFightIntruders : AIObjectiveLoop<Character>
{
public override string DebugTag => "fight intruders";
public override bool KeepDivingGearOn => true;
public AIObjectiveFightIntruders(Character character, AIObjectiveManager objectiveManager, float priorityModifier = 1)
: base(character, objectiveManager, priorityModifier) { }
@@ -10,7 +10,6 @@ namespace Barotrauma
{
public override string DebugTag => "find safety";
public override bool ForceRun => true;
public override bool KeepDivingGearOn => true;
// TODO: expose?
const float priorityIncrease = 25;
@@ -559,6 +558,49 @@ namespace Barotrauma
{
character.AIController.SteeringManager.Reset();
}
if (goToObjective != null) { return; }
if (currentHull == null) { return; }
//goto objective doesn't exist (a safe hull not found, or a path to a safe hull not found)
// -> attempt to manually steer away from hazards
Vector2 escapeVel = Vector2.Zero;
foreach (FireSource fireSource in currentHull.FireSources)
{
Vector2 dir = character.Position - fireSource.Position;
float distMultiplier = MathHelper.Clamp(100.0f / Vector2.Distance(fireSource.Position, character.Position), 0.1f, 10.0f);
escapeVel += new Vector2(Math.Sign(dir.X) * distMultiplier, !character.IsClimbing ? 0 : Math.Sign(dir.Y) * distMultiplier);
}
foreach (Character enemy in Character.CharacterList)
{
//don't run from friendly NPCs
if (enemy.TeamID == Character.TeamType.FriendlyNPC) { continue; }
//friendly NPCs don't run away from anything but characters controlled by EnemyAIController (= monsters)
if (character.TeamID == Character.TeamType.FriendlyNPC && !(enemy.AIController is EnemyAIController)) { continue; }
if (enemy.CurrentHull == currentHull && !enemy.IsDead && !enemy.IsUnconscious &&
(enemy.AIController is EnemyAIController || enemy.TeamID != character.TeamID))
{
Vector2 dir = character.Position - enemy.Position;
float distMultiplier = MathHelper.Clamp(100.0f / Vector2.Distance(enemy.Position, character.Position), 0.1f, 10.0f);
escapeVel += new Vector2(Math.Sign(dir.X) * distMultiplier, !character.IsClimbing ? 0 : Math.Sign(dir.Y) * distMultiplier);
}
}
if (escapeVel != Vector2.Zero)
{
//only move if we haven't reached the edge of the room
if ((escapeVel.X < 0 && character.Position.X > currentHull.Rect.X + 50) ||
(escapeVel.X > 0 && character.Position.X < currentHull.Rect.Right - 50))
{
character.AIController.SteeringManager.SteeringManual(deltaTime, escapeVel);
}
else
{
character.AnimController.TargetDir = escapeVel.X < 0.0f ? Direction.Right : Direction.Left;
character.AIController.SteeringManager.Reset();
}
}
else
{
character.AIController.SteeringManager.Reset();
}
}
}
@@ -10,8 +10,6 @@ namespace Barotrauma
class AIObjectiveFixLeak : AIObjective
{
public override string DebugTag => "fix leak";
public override bool KeepDivingGearOn => true;
public override bool ForceRun => true;
public Gap Leak { get; private set; }
@@ -323,6 +321,31 @@ namespace Barotrauma
{
#if DEBUG
DebugConsole.ThrowError("AIObjectiveFixLeak failed - the item \"" + weldingTool + "\" has no RepairTool component but is tagged as a welding tool");
#endif
abandon = true;
return;
}
Vector2 gapDiff = Leak.WorldPosition - character.WorldPosition;
// TODO: use the collider size/reach?
if (!character.AnimController.InWater && Math.Abs(gapDiff.X) < 100 && gapDiff.Y < 0.0f && gapDiff.Y > -150)
{
HumanAIController.AnimController.Crouching = true;
}
float reach = ConvertUnits.ToSimUnits(repairTool.Range);
bool canOperate = ConvertUnits.ToSimUnits(gapDiff.Length()) < reach;
if (canOperate)
{
TryAddSubObjective(ref operateObjective, () => new AIObjectiveOperateItem(repairTool, character, objectiveManager, option: "", requireEquip: true, operateTarget: Leak));
}
else
{
TryAddSubObjective(ref gotoObjective, () => new AIObjectiveGoTo(ConvertUnits.ToSimUnits(GetStandPosition()), character, objectiveManager) { CloseEnough = reach * 0.75f });
}
var repairTool = weldingTool.GetComponent<RepairTool>();
if (repairTool == null)
{
#if DEBUG
DebugConsole.ThrowError("AIObjectiveFixLeak failed - the item \"" + weldingTool + "\" has no RepairTool component but is tagged as a welding tool");
#endif
abandon = true;
return;
@@ -9,7 +9,6 @@ namespace Barotrauma
class AIObjectiveFixLeaks : AIObjectiveLoop<Gap>
{
public override string DebugTag => "fix leaks";
public override bool KeepDivingGearOn => true;
public override bool ForceRun => true;
public AIObjectiveFixLeaks(Character character, AIObjectiveManager objectiveManager, float priorityModifier = 1) : base(character, objectiveManager, priorityModifier) { }
@@ -1,6 +1,7 @@
using FarseerPhysics;
using Microsoft.Xna.Framework;
using System;
using System.Linq;
namespace Barotrauma
{
@@ -23,8 +24,6 @@ namespace Barotrauma
public bool AllowGoingOutside { get; set; }
public bool CheckVisibility { get; set; }
public override bool KeepDivingGearOn => findDivingGear != null;
public override float GetPriority()
{
if (FollowControlledCharacter && Character.Controlled == null) { return 0.0f; }
@@ -74,21 +74,6 @@ namespace Barotrauma
}
}
public override void Update(float deltaTime)
{
if (objectiveManager.CurrentObjective == this)
{
if (randomTimer > 0)
{
randomTimer -= deltaTime;
}
else
{
SetRandom();
}
}
}
public override bool IsCompleted() => false;
public override bool CanBeCompleted => true;
@@ -136,6 +136,10 @@ namespace Barotrauma
{
isCompleted = true;
}
if (component.AIOperate(deltaTime, character, this))
{
isCompleted = true;
}
}
else
{
@@ -10,7 +10,6 @@ namespace Barotrauma
class AIObjectivePumpWater : AIObjectiveLoop<Pump>
{
public override string DebugTag => "pump water";
public override bool KeepDivingGearOn => true;
private IEnumerable<Pump> pumpList;
public AIObjectivePumpWater(Character character, AIObjectiveManager objectiveManager, string option, float priorityModifier = 1)
@@ -11,8 +11,6 @@ namespace Barotrauma
{
public override string DebugTag => "repair item";
public override bool KeepDivingGearOn => true;
public Item Item { get; private set; }
private AIObjectiveGoTo goToObjective;
@@ -8,7 +8,6 @@ namespace Barotrauma
class AIObjectiveRepairItems : AIObjectiveLoop<Item>
{
public override string DebugTag => "repair items";
public override bool KeepDivingGearOn => true;
/// <summary>
/// Should the character only attempt to fix items they have the skills to fix, or any damaged item
@@ -12,7 +12,6 @@ namespace Barotrauma
{
public override string DebugTag => "rescue";
public override bool ForceRun => true;
public override bool KeepDivingGearOn => true;
const float TreatmentDelay = 0.5f;
@@ -8,8 +8,6 @@ namespace Barotrauma
{
public override string DebugTag => "rescue all";
public override bool KeepDivingGearOn => true;
//only treat characters whose vitality is below this (0.8 = 80% of max vitality)
public const float VitalityThreshold = 0.8f;