(842e6af33) Human AI needs AITargets too (not much, but they are still useful). Therefor add Type property to AITargets, so that certain targets can be treated human only and others enemy only. Implement target filtering in the Enemy AI Controller.

This commit is contained in:
Joonas Rikkonen
2019-04-08 11:58:50 +03:00
parent c3ab4b6899
commit 55eecc49d8
3 changed files with 77 additions and 50 deletions
@@ -66,6 +66,22 @@ namespace Barotrauma
public float MinSoundRange, MinSightRange; public float MinSoundRange, MinSightRange;
public float MaxSoundRange = float.MaxValue, MaxSightRange = float.MaxValue; public float MaxSoundRange = float.MaxValue, MaxSightRange = float.MaxValue;
public TargetType Type { get; private set; }
public enum TargetType
{
Any,
HumanOnly,
EnemyOnly
}
public string SonarLabel;
public bool Enabled = true;
public float MinSoundRange, MinSightRange;
public float MaxSoundRange = float.MaxValue, MaxSightRange = float.MaxValue;
public Vector2 WorldPosition public Vector2 WorldPosition
{ {
get get
@@ -113,6 +129,11 @@ namespace Barotrauma
MaxSightRange = element.GetAttributeFloat("maxsightrange", SightRange); MaxSightRange = element.GetAttributeFloat("maxsightrange", SightRange);
MaxSoundRange = element.GetAttributeFloat("maxsoundrange", SoundRange); MaxSoundRange = element.GetAttributeFloat("maxsoundrange", SoundRange);
SonarLabel = element.GetAttributeString("sonarlabel", ""); SonarLabel = element.GetAttributeString("sonarlabel", "");
string typeString = element.GetAttributeString("type", "Any");
if (Enum.TryParse(typeString, out TargetType t))
{
Type = t;
}
} }
public AITarget(Entity e, float sightRange = -1, float soundRange = 0) public AITarget(Entity e, float sightRange = -1, float soundRange = 0)
@@ -1062,6 +1062,7 @@ namespace Barotrauma
{ {
continue; continue;
} }
if (target.Type == AITarget.TargetType.HumanOnly) { continue; }
// Don't attack outposts. // Don't attack outposts.
if (target.Entity.Submarine != null && target.Entity.Submarine.IsOutpost) { continue; } if (target.Entity.Submarine != null && target.Entity.Submarine.IsOutpost) { continue; }
@@ -21,8 +21,6 @@ namespace Barotrauma
private Hull currentTarget; private Hull currentTarget;
private float newTargetTimer; private float newTargetTimer;
private bool searchingNewHull;
private float standStillTimer; private float standStillTimer;
private float walkDuration; private float walkDuration;
@@ -68,41 +66,11 @@ namespace Barotrauma
} }
if (newTargetTimer <= 0.0f) if (newTargetTimer <= 0.0f)
{ {
if (!searchingNewHull) currentTarget = FindRandomHull();
{
//find all available hulls first
FindTargetHulls();
searchingNewHull = true;
return;
}
else if (targetHulls.Count > 0)
{
//choose a random available hull
var randomHull = ToolBox.SelectWeightedRandom(targetHulls, hullWeights, Rand.RandSync.Unsynced);
bool isCurrentHullOK = !HumanAIController.UnsafeHulls.Contains(character.CurrentHull) && !IsForbidden(character.CurrentHull);
if (isCurrentHullOK)
{
// Check that there is no unsafe or forbidden hulls on the way to the target
// Only do this when the current hull is ok, because otherwise the would block all paths from the current hull to the target hull.
var path = PathSteering.PathFinder.FindPath(character.SimPosition, randomHull.SimPosition);
if (path.Unreachable ||
path.Nodes.Any(n => HumanAIController.UnsafeHulls.Contains(n.CurrentHull) || IsForbidden(n.CurrentHull)))
{
//can't go to this room, remove it from the list and try another room next frame
int index = targetHulls.IndexOf(randomHull);
targetHulls.RemoveAt(index);
hullWeights.RemoveAt(index);
PathSteering.Reset();
return;
}
}
currentTarget = randomHull;
searchingNewHull = false;
}
if (currentTarget != null) if (currentTarget != null)
{ {
character.AIController.SelectTarget(currentTarget.AiTarget);
string errorMsg = null; string errorMsg = null;
#if DEBUG #if DEBUG
bool isRoomNameFound = currentTarget.RoomName != null; bool isRoomNameFound = currentTarget.RoomName != null;
@@ -195,27 +163,24 @@ namespace Barotrauma
private readonly List<Hull> targetHulls = new List<Hull>(20); private readonly List<Hull> targetHulls = new List<Hull>(20);
private readonly List<float> hullWeights = new List<float>(20); private readonly List<float> hullWeights = new List<float>(20);
private void FindTargetHulls() private Hull FindRandomHull()
{ {
var idCard = character.Inventory.FindItemByIdentifier("idcard"); var idCard = character.Inventory.FindItemByIdentifier("idcard");
Hull targetHull = null;
bool isCurrentHullOK = !HumanAIController.UnsafeHulls.Contains(character.CurrentHull) && !IsForbidden(character.CurrentHull); bool isCurrentHullOK = !HumanAIController.UnsafeHulls.Contains(character.CurrentHull) && !IsForbidden(character.CurrentHull);
//random chance of navigating back to the room where the character spawned
targetHulls.Clear(); if (Rand.Int(5) == 1 && idCard != null)
hullWeights.Clear();
foreach (var hull in Hull.hullList)
{ {
if (HumanAIController.UnsafeHulls.Contains(hull)) { continue; } foreach (WayPoint wp in WayPoint.WayPointList)
if (hull.Submarine == null) { continue; }
if (hull.Submarine.TeamID != character.TeamID) { continue; }
// If the character is inside, only take connected hulls into account.
if (character.Submarine != null && !character.Submarine.IsEntityFoundOnThisSub(hull, true)) { continue; }
if (IsForbidden(hull)) { continue; }
// Ignore hulls that are too low to stand inside
if (character.AnimController is HumanoidAnimController animController)
{ {
if (hull.CeilingHeight < ConvertUnits.ToDisplayUnits(animController.HeadPosition.Value)) if (wp.SpawnType != SpawnType.Human || wp.CurrentHull == null) { continue; }
foreach (string tag in wp.IdCardTags)
{ {
continue; if (idCard.HasTag(tag))
{
targetHull = wp.CurrentHull;
}
} }
} }
if (!targetHulls.Contains(hull)) if (!targetHulls.Contains(hull))
@@ -224,7 +189,47 @@ namespace Barotrauma
hullWeights.Add(hull.Volume); hullWeights.Add(hull.Volume);
} }
} }
if (targetHull == null)
{
targetHulls.Clear();
hullWeights.Clear();
foreach (var hull in Hull.hullList)
{
if (HumanAIController.UnsafeHulls.Contains(hull)) { continue; }
if (hull.Submarine == null) { continue; }
if (hull.Submarine.TeamID != character.TeamID) { continue; }
// If the character is inside, only take connected hulls into account.
if (character.Submarine != null && !character.Submarine.IsEntityFoundOnThisSub(hull, true)) { continue; }
if (IsForbidden(hull)) { continue; }
// Ignore hulls that are too low to stand inside
if (character.AnimController is HumanoidAnimController animController)
{
if (hull.CeilingHeight < ConvertUnits.ToDisplayUnits(animController.HeadPosition.Value))
{
continue;
}
}
if (isCurrentHullOK)
{
// Check that there is no unsafe or forbidden hulls on the way to the target
// Only do this when the current hull is ok, because otherwise the would block all paths from the current hull to the target hull.
var path = PathSteering.PathFinder.FindPath(character.SimPosition, hull.SimPosition);
if (path.Unreachable) { continue; }
if (path.Nodes.Any(n => HumanAIController.UnsafeHulls.Contains(n.CurrentHull) || IsForbidden(n.CurrentHull))) { continue; }
}
// If we want to do a steering check, we should do it here, before setting the path
//if (path.Cost > 1000.0f) { continue; }
if (!targetHulls.Contains(hull))
{
targetHulls.Add(hull);
hullWeights.Add(hull.Volume);
}
}
return ToolBox.SelectWeightedRandom(targetHulls, hullWeights, Rand.RandSync.Unsynced);
}
return targetHull;
} }
private bool IsForbidden(Hull hull) private bool IsForbidden(Hull hull)