Fix turrets not shooting in space (#12820)
* Fix turrets not shooting in space * Faster target acquisition
This commit is contained in:
@@ -30,7 +30,8 @@ public abstract class NPCCombatOperator : HTNOperator
|
|||||||
/// Regardless of pathfinding or LOS these are the max we'll check
|
/// Regardless of pathfinding or LOS these are the max we'll check
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private const int MaxConsideredTargets = 10;
|
private const int MaxConsideredTargets = 10;
|
||||||
private const int MaxTargetCount = 5;
|
|
||||||
|
protected virtual bool IsRanged => false;
|
||||||
|
|
||||||
public override void Initialize(IEntitySystemManager sysManager)
|
public override void Initialize(IEntitySystemManager sysManager)
|
||||||
{
|
{
|
||||||
@@ -66,6 +67,7 @@ public abstract class NPCCombatOperator : HTNOperator
|
|||||||
private async Task<List<(EntityUid Entity, float Rating, float Distance)>> GetTargets(NPCBlackboard blackboard)
|
private async Task<List<(EntityUid Entity, float Rating, float Distance)>> GetTargets(NPCBlackboard blackboard)
|
||||||
{
|
{
|
||||||
var owner = blackboard.GetValue<EntityUid>(NPCBlackboard.Owner);
|
var owner = blackboard.GetValue<EntityUid>(NPCBlackboard.Owner);
|
||||||
|
var ownerCoordinates = blackboard.GetValueOrDefault<EntityCoordinates>(NPCBlackboard.OwnerCoordinates, EntManager);
|
||||||
var radius = blackboard.GetValueOrDefault<float>(NPCBlackboard.VisionRadius, EntManager);
|
var radius = blackboard.GetValueOrDefault<float>(NPCBlackboard.VisionRadius, EntManager);
|
||||||
var targets = new List<(EntityUid Entity, float Rating, float Distance)>();
|
var targets = new List<(EntityUid Entity, float Rating, float Distance)>();
|
||||||
|
|
||||||
@@ -73,18 +75,14 @@ public abstract class NPCCombatOperator : HTNOperator
|
|||||||
var xformQuery = EntManager.GetEntityQuery<TransformComponent>();
|
var xformQuery = EntManager.GetEntityQuery<TransformComponent>();
|
||||||
var mobQuery = EntManager.GetEntityQuery<MobStateComponent>();
|
var mobQuery = EntManager.GetEntityQuery<MobStateComponent>();
|
||||||
var canMove = blackboard.GetValueOrDefault<bool>(NPCBlackboard.CanMove, EntManager);
|
var canMove = blackboard.GetValueOrDefault<bool>(NPCBlackboard.CanMove, EntManager);
|
||||||
var cancelToken = new CancellationTokenSource();
|
|
||||||
var count = 0;
|
var count = 0;
|
||||||
|
var paths = new List<Task>();
|
||||||
|
// TODO: Really this should be a part of perception so we don't have to constantly re-plan targets.
|
||||||
|
|
||||||
if (xformQuery.TryGetComponent(existingTarget, out var targetXform))
|
// Special-case existing target.
|
||||||
|
if (EntManager.EntityExists(existingTarget))
|
||||||
{
|
{
|
||||||
var distance = await _pathfinding.GetPathDistance(owner, targetXform.Coordinates,
|
paths.Add(UpdateTarget(owner, existingTarget, existingTarget, ownerCoordinates, blackboard, radius, canMove, xformQuery, targets));
|
||||||
SharedInteractionSystem.InteractionRange, cancelToken.Token, _pathfinding.GetFlags(blackboard));
|
|
||||||
|
|
||||||
if (distance != null)
|
|
||||||
{
|
|
||||||
targets.Add((existingTarget, GetRating(blackboard, existingTarget, existingTarget, distance.Value, canMove, xformQuery), distance.Value));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Need a perception system instead
|
// TODO: Need a perception system instead
|
||||||
@@ -94,7 +92,7 @@ public abstract class NPCCombatOperator : HTNOperator
|
|||||||
{
|
{
|
||||||
if (mobQuery.TryGetComponent(target, out var mobState) &&
|
if (mobQuery.TryGetComponent(target, out var mobState) &&
|
||||||
mobState.CurrentState > DamageState.Alive ||
|
mobState.CurrentState > DamageState.Alive ||
|
||||||
!xformQuery.TryGetComponent(target, out targetXform))
|
target == existingTarget)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -104,27 +102,61 @@ public abstract class NPCCombatOperator : HTNOperator
|
|||||||
if (count >= MaxConsideredTargets)
|
if (count >= MaxConsideredTargets)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (!ExamineSystemShared.InRangeUnOccluded(owner, target, radius, null))
|
paths.Add(UpdateTarget(owner, target, existingTarget, ownerCoordinates, blackboard, radius, canMove, xformQuery, targets));
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var distance = await _pathfinding.GetPathDistance(owner, targetXform.Coordinates,
|
|
||||||
SharedInteractionSystem.InteractionRange, cancelToken.Token, _pathfinding.GetFlags(blackboard));
|
|
||||||
|
|
||||||
if (distance == null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
targets.Add((target, GetRating(blackboard, target, existingTarget, distance.Value, canMove, xformQuery), distance.Value));
|
|
||||||
|
|
||||||
if (targets.Count >= MaxTargetCount)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await Task.WhenAll(paths);
|
||||||
|
|
||||||
targets.Sort((x, y) => y.Rating.CompareTo(x.Rating));
|
targets.Sort((x, y) => y.Rating.CompareTo(x.Rating));
|
||||||
return targets;
|
return targets;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task UpdateTarget(
|
||||||
|
EntityUid owner,
|
||||||
|
EntityUid target,
|
||||||
|
EntityUid existingTarget,
|
||||||
|
EntityCoordinates ownerCoordinates,
|
||||||
|
NPCBlackboard blackboard,
|
||||||
|
float radius,
|
||||||
|
bool canMove,
|
||||||
|
EntityQuery<TransformComponent> xformQuery,
|
||||||
|
List<(EntityUid Entity, float Rating, float Distance)> targets)
|
||||||
|
{
|
||||||
|
if (!xformQuery.TryGetComponent(target, out var targetXform))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var inLos = false;
|
||||||
|
|
||||||
|
// If it's not an existing target then check LOS.
|
||||||
|
if (target != existingTarget)
|
||||||
|
{
|
||||||
|
inLos = ExamineSystemShared.InRangeUnOccluded(owner, target, radius, null);
|
||||||
|
|
||||||
|
if (!inLos)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Turret or the likes, check LOS only.
|
||||||
|
if (IsRanged && !canMove)
|
||||||
|
{
|
||||||
|
inLos = inLos || ExamineSystemShared.InRangeUnOccluded(owner, target, radius, null);
|
||||||
|
|
||||||
|
if (!inLos || !targetXform.Coordinates.TryDistance(EntManager, ownerCoordinates, out var distance))
|
||||||
|
return;
|
||||||
|
|
||||||
|
targets.Add((target, GetRating(blackboard, target, existingTarget, distance, canMove, xformQuery), distance));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var nDistance = await _pathfinding.GetPathDistance(owner, targetXform.Coordinates,
|
||||||
|
SharedInteractionSystem.InteractionRange, default, _pathfinding.GetFlags(blackboard));
|
||||||
|
|
||||||
|
if (nDistance == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
targets.Add((target, GetRating(blackboard, target, existingTarget, nDistance.Value, canMove, xformQuery), nDistance.Value));
|
||||||
|
}
|
||||||
|
|
||||||
protected abstract float GetRating(NPCBlackboard blackboard, EntityUid uid, EntityUid existingTarget, float distance, bool canMove,
|
protected abstract float GetRating(NPCBlackboard blackboard, EntityUid uid, EntityUid existingTarget, float distance, bool canMove,
|
||||||
EntityQuery<TransformComponent> xformQuery);
|
EntityQuery<TransformComponent> xformQuery);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ namespace Content.Server.NPC.HTN.PrimitiveTasks.Operators.Ranged;
|
|||||||
[UsedImplicitly]
|
[UsedImplicitly]
|
||||||
public sealed class PickRangedTargetOperator : NPCCombatOperator
|
public sealed class PickRangedTargetOperator : NPCCombatOperator
|
||||||
{
|
{
|
||||||
|
protected override bool IsRanged => true;
|
||||||
|
|
||||||
protected override float GetRating(NPCBlackboard blackboard, EntityUid uid, EntityUid existingTarget, float distance, bool canMove, EntityQuery<TransformComponent> xformQuery)
|
protected override float GetRating(NPCBlackboard blackboard, EntityUid uid, EntityUid existingTarget, float distance, bool canMove, EntityQuery<TransformComponent> xformQuery)
|
||||||
{
|
{
|
||||||
// Yeah look I just came up with values that seemed okay but they will need a lot of tweaking.
|
// Yeah look I just came up with values that seemed okay but they will need a lot of tweaking.
|
||||||
|
|||||||
Reference in New Issue
Block a user