(913cde46d) Refactor AIObjectiveUsing to use the TryAddSubObjective method. Reorganize a bit.

This commit is contained in:
Joonas Rikkonen
2019-05-16 05:50:04 +03:00
parent 5d7cc6599c
commit 566f1d16e4
12 changed files with 473 additions and 166 deletions
@@ -25,7 +25,14 @@ namespace Barotrauma
{
_weapon = value;
_weaponComponent = null;
reloadWeaponObjective = null;
if (reloadWeaponObjective != null)
{
if (subObjectives.Contains(reloadWeaponObjective))
{
subObjectives.Remove(reloadWeaponObjective);
}
reloadWeaponObjective = null;
}
}
}
private ItemComponent _weaponComponent;
@@ -44,6 +51,8 @@ namespace Barotrauma
}
}
public override bool ConcurrentObjectives => true;
private readonly AIObjectiveFindSafety findSafety;
private readonly HashSet<RangedWeapon> rangedWeapons = new HashSet<RangedWeapon>();
private readonly HashSet<MeleeWeapon> meleeWeapons = new HashSet<MeleeWeapon>();
@@ -83,6 +92,33 @@ namespace Barotrauma
}
}
public override float GetPriority() => (Enemy != null && (Enemy.Removed || Enemy.IsDead)) ? 0 : Math.Min(100 * PriorityModifier, 100);
public override bool IsDuplicate(AIObjective otherObjective)
{
if (!(otherObjective is AIObjectiveCombat objective)) return false;
return objective.Enemy == Enemy;
}
public override void OnSelected() => Weapon = null;
public override bool IsCompleted()
{
bool completed = (Enemy != null && (Enemy.Removed || Enemy.IsDead)) || (useCoolDown && coolDownTimer <= 0);
if (completed)
{
if (objectiveManager.CurrentOrder == this && Enemy != null && Enemy.IsDead)
{
character.Speak(TextManager.Get("DialogTargetDown"), null, 3.0f, "targetdown", 30.0f);
}
if (Weapon != null)
{
Unequip();
}
}
return completed;
}
protected override void Act(float deltaTime)
{
if (useCoolDown)
@@ -239,52 +275,52 @@ namespace Barotrauma
private void Retreat(float deltaTime)
{
followTargetObjective = null;
if (followTargetObjective != null)
{
if (subObjectives.Contains(followTargetObjective))
{
subObjectives.Remove(followTargetObjective);
}
followTargetObjective = null;
}
if (retreatObjective != null && retreatObjective.Target != retreatTarget)
{
retreatObjective = null;
}
if (retreatTarget == null || (retreatObjective != null && !retreatObjective.CanBeCompleted))
{
retreatTarget = findSafety.FindBestHull(new List<Hull>() { character.CurrentHull });
}
if (retreatTarget != null)
{
if (retreatObjective == null || retreatObjective.Target != retreatTarget)
{
retreatObjective = new AIObjectiveGoTo(retreatTarget, character, objectiveManager, false, true);
}
retreatObjective.TryComplete(deltaTime);
}
TryAddSubObjective(ref retreatObjective, () => new AIObjectiveGoTo(retreatTarget, character, objectiveManager, false, true));
}
private void Engage(float deltaTime)
{
retreatTarget = null;
retreatObjective = null;
if (followTargetObjective == null)
if (retreatObjective != null)
{
followTargetObjective = new AIObjectiveGoTo(Enemy, character, objectiveManager, repeat: true, getDivingGearIfNeeded: true)
if (subObjectives.Contains(retreatObjective))
{
subObjectives.Remove(retreatObjective);
}
retreatObjective = null;
}
TryAddSubObjective(ref followTargetObjective,
constructor: () => new AIObjectiveGoTo(Enemy, character, objectiveManager, repeat: true, getDivingGearIfNeeded: true)
{
AllowGoingOutside = true,
IgnoreIfTargetDead = true,
CheckVisibility = true
};
}
if (WeaponComponent is RangedWeapon)
{
followTargetObjective.CloseEnough = 3;
}
else if (WeaponComponent is MeleeWeapon mw)
{
followTargetObjective.CloseEnough = ConvertUnits.ToSimUnits(mw.Range);
}
else if (WeaponComponent is RepairTool rt)
{
followTargetObjective.CloseEnough = ConvertUnits.ToSimUnits(rt.Range);
}
else if (WeaponComponent is RepairTool rt)
{
SteeringManager.Reset();
Mode = CombatMode.Retreat;
}
followTargetObjective.TryComplete(deltaTime);
CheckVisibility = true,
CloseEnough =
WeaponComponent is RangedWeapon ? 3 :
WeaponComponent is MeleeWeapon mw ? ConvertUnits.ToSimUnits(mw.Range) :
WeaponComponent is RepairTool rt ? ConvertUnits.ToSimUnits(rt.Range) : 0.5f
},
onAbandon: () =>
{
SteeringManager.Reset();
Mode = CombatMode.Retreat;
});
}
private bool Reload(float deltaTime)
@@ -297,31 +333,17 @@ namespace Barotrauma
Item containedItem = containedItems.FirstOrDefault(it => it.Condition > 0.0f && requiredItem.MatchesItem(it));
if (containedItem == null)
{
if (reloadWeaponObjective == null)
{
reloadWeaponObjective = new AIObjectiveContainItem(character, requiredItem.Identifiers, Weapon.GetComponent<ItemContainer>(), objectiveManager);
}
TryAddSubObjective(ref reloadWeaponObjective,
constructor: () => new AIObjectiveContainItem(character, requiredItem.Identifiers, Weapon.GetComponent<ItemContainer>(), objectiveManager),
onAbandon: () =>
{
SteeringManager.Reset();
Mode = CombatMode.Retreat;
});
}
}
}
if (reloadWeaponObjective != null)
{
if (reloadWeaponObjective.IsCompleted())
{
reloadWeaponObjective = null;
}
else if (!reloadWeaponObjective.CanBeCompleted)
{
SteeringManager.Reset();
Mode = CombatMode.Retreat;
}
else
{
reloadWeaponObjective.TryComplete(deltaTime);
}
return false;
}
return true;
return reloadWeaponObjective == null || reloadWeaponObjective.IsCompleted();
}
private IEnumerable<FarseerPhysics.Dynamics.Body> myBodies;
@@ -392,36 +414,6 @@ namespace Barotrauma
}
}
public override bool IsCompleted()
{
bool completed = (Enemy != null && (Enemy.Removed || Enemy.IsDead)) || (useCoolDown && coolDownTimer <= 0);
if (completed)
{
if (objectiveManager.CurrentOrder == this && Enemy != null && Enemy.IsDead)
{
character.Speak(TextManager.Get("DialogTargetDown"), null, 3.0f, "targetdown", 30.0f);
}
if (Weapon != null)
{
Unequip();
}
}
return completed;
}
public override bool CanBeCompleted => !abandon &&
(reloadWeaponObjective == null || reloadWeaponObjective.CanBeCompleted) &&
(retreatObjective == null || retreatObjective.CanBeCompleted) &&
(followTargetObjective == null || followTargetObjective.CanBeCompleted);
public override float GetPriority() => (Enemy != null && (Enemy.Removed || Enemy.IsDead)) ? 0 : Math.Min(100 * PriorityModifier, 100);
public override bool IsDuplicate(AIObjective otherObjective)
{
if (!(otherObjective is AIObjectiveCombat objective)) return false;
return objective.Enemy == Enemy;
}
//private float CalculateEnemyStrength()
//{
// float enemyStrength = 0;
@@ -300,6 +300,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;
@@ -73,6 +73,21 @@ 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;
@@ -106,6 +106,10 @@ namespace Barotrauma
{
isCompleted = true;
}
if (component.AIOperate(deltaTime, character, this))
{
isCompleted = true;
}
}
else
{
@@ -905,6 +905,25 @@ namespace Barotrauma.Items.Components
}
}
if (targetItem.Prefab.DeconstructItems.Any())
{
inputContainer.Inventory.RemoveItem(targetItem);
Entity.Spawner.AddToRemoveQueue(targetItem);
MoveInputQueue();
PutItemsToLinkedContainer();
}
else
{
if (outputContainer.Inventory.Items.All(i => i != null))
{
targetItem.Drop(dropper: null);
}
else
{
outputContainer.Inventory.TryPutItem(targetItem, user: null, createNetworkEvent: true);
}
}
if (targetItem.Prefab.DeconstructItems.Any())
{
inputContainer.Inventory.RemoveItem(targetItem);
@@ -212,33 +212,6 @@ namespace Barotrauma.Items.Components
}
}
public Vector2? PosToMaintain
{
get { return posToMaintain; }
set { posToMaintain = value; }
}
struct ObstacleDebugInfo
{
public Vector2 Point1;
public Vector2 Point2;
public Vector2? Intersection;
public float Dot;
public Vector2 AvoidStrength;
public ObstacleDebugInfo(GraphEdge edge, Vector2? intersection, float dot, Vector2 avoidStrength)
{
Point1 = edge.Point1;
Point2 = edge.Point2;
Intersection = intersection;
Dot = dot;
AvoidStrength = avoidStrength;
}
}
//edge point 1, edge point 2, avoid strength
private List<ObstacleDebugInfo> debugDrawObstacles = new List<ObstacleDebugInfo>();
@@ -1704,6 +1704,10 @@ namespace Barotrauma
{
ApplyStatusEffects(!waterProof && inWater ? ActionType.InWater : ActionType.NotInWater, deltaTime);
}
if (!broken)
{
ApplyStatusEffects(!waterProof && inWater ? ActionType.InWater : ActionType.NotInWater, deltaTime);
}
ApplyStatusEffects(!waterProof && inWater ? ActionType.InWater : ActionType.NotInWater, deltaTime);
if (body == null || !body.Enabled || !inWater || ParentInventory != null || Removed) { return; }
@@ -531,6 +531,25 @@ namespace Barotrauma
}
}
public string DisplayName
{
get;
private set;
}
private string roomName;
[Editable, Serialize("", true, translationTextTag: "RoomName.")]
public string RoomName
{
get { return roomName; }
set
{
if (roomName == value) { return; }
roomName = value;
DisplayName = TextManager.Get(roomName, returnNull: true) ?? roomName;
}
}
public override Rectangle Rect
{
get