diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/AITarget.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/AITarget.cs index 42f9d6515..166f89537 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/AITarget.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/AITarget.cs @@ -66,6 +66,22 @@ namespace Barotrauma public float MinSoundRange, MinSightRange; 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 { get @@ -113,6 +129,11 @@ namespace Barotrauma MaxSightRange = element.GetAttributeFloat("maxsightrange", SightRange); MaxSoundRange = element.GetAttributeFloat("maxsoundrange", SoundRange); 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) diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs index fab1137c8..6a3befb3c 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs @@ -1062,6 +1062,7 @@ namespace Barotrauma { continue; } + if (target.Type == AITarget.TargetType.HumanOnly) { continue; } // Don't attack outposts. if (target.Entity.Submarine != null && target.Entity.Submarine.IsOutpost) { continue; } diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveIdle.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveIdle.cs index 34d03462d..ac684c3cb 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveIdle.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveIdle.cs @@ -21,8 +21,6 @@ namespace Barotrauma private Hull currentTarget; private float newTargetTimer; - private bool searchingNewHull; - private float standStillTimer; private float walkDuration; @@ -68,41 +66,11 @@ namespace Barotrauma } if (newTargetTimer <= 0.0f) { - if (!searchingNewHull) - { - //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; - } + currentTarget = FindRandomHull(); if (currentTarget != null) { + character.AIController.SelectTarget(currentTarget.AiTarget); string errorMsg = null; #if DEBUG bool isRoomNameFound = currentTarget.RoomName != null; @@ -195,27 +163,24 @@ namespace Barotrauma private readonly List targetHulls = new List(20); private readonly List hullWeights = new List(20); - private void FindTargetHulls() + private Hull FindRandomHull() { var idCard = character.Inventory.FindItemByIdentifier("idcard"); + Hull targetHull = null; bool isCurrentHullOK = !HumanAIController.UnsafeHulls.Contains(character.CurrentHull) && !IsForbidden(character.CurrentHull); - - targetHulls.Clear(); - hullWeights.Clear(); - foreach (var hull in Hull.hullList) + //random chance of navigating back to the room where the character spawned + if (Rand.Int(5) == 1 && idCard != null) { - 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) + foreach (WayPoint wp in WayPoint.WayPointList) { - 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)) @@ -224,7 +189,47 @@ namespace Barotrauma 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)