From a7a07be18141fd1502d5d6447a20a20cf783d77c Mon Sep 17 00:00:00 2001 From: VMSolidus Date: Thu, 19 Sep 2024 20:22:02 -0400 Subject: [PATCH] Less Aggressive Juking --- .../NPC/Components/NPCJukeComponent.cs | 12 ++++--- .../Operators/Combat/JukeOperator.cs | 18 ++++++++-- Content.Server/NPC/Systems/NPCJukeSystem.cs | 33 ++++++++----------- 3 files changed, 37 insertions(+), 26 deletions(-) diff --git a/Content.Server/NPC/Components/NPCJukeComponent.cs b/Content.Server/NPC/Components/NPCJukeComponent.cs index 2c4136c24b9..768feeca6fc 100644 --- a/Content.Server/NPC/Components/NPCJukeComponent.cs +++ b/Content.Server/NPC/Components/NPCJukeComponent.cs @@ -1,4 +1,3 @@ -using Content.Server.NPC.HTN.PrimitiveTasks.Operators.Combat; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; namespace Content.Server.NPC.Components; @@ -6,17 +5,20 @@ namespace Content.Server.NPC.Components; [RegisterComponent, AutoGenerateComponentPause] public sealed partial class NPCJukeComponent : Component { - [DataField("jukeType")] + [DataField] public JukeType JukeType = JukeType.Away; - [DataField("jukeDuration")] + [DataField] public float JukeDuration = 0.5f; - [DataField("nextJuke", customTypeSerializer:typeof(TimeOffsetSerializer))] + [DataField] + public float JukeCooldown = 3f; + + [DataField(customTypeSerializer: typeof(TimeOffsetSerializer))] [AutoPausedField] public TimeSpan NextJuke; - [DataField("targetTile")] + [DataField] public Vector2i? TargetTile; } diff --git a/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Combat/JukeOperator.cs b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Combat/JukeOperator.cs index 02a3b085104..68029f5a4c2 100644 --- a/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Combat/JukeOperator.cs +++ b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Combat/JukeOperator.cs @@ -6,17 +6,31 @@ public sealed partial class JukeOperator : HTNOperator, IHtnConditionalShutdown { [Dependency] private readonly IEntityManager _entManager = default!; - [DataField("jukeType")] + [DataField] public JukeType JukeType = JukeType.AdjacentTile; - [DataField("shutdownState")] + [DataField] public HTNPlanState ShutdownState { get; private set; } = HTNPlanState.PlanFinished; + /// + /// Controls how long(in seconds) the NPC will move while juking. + /// + [DataField] + public float JukeDuration = 0.5f; + + /// + /// Controls how often (in seconds) an NPC will try to juke. + /// + [DataField] + public float JukeCooldown = 3f; + public override void Startup(NPCBlackboard blackboard) { base.Startup(blackboard); var juke = _entManager.EnsureComponent(blackboard.GetValue(NPCBlackboard.Owner)); juke.JukeType = JukeType; + juke.JukeDuration = JukeDuration; + juke.JukeCooldown = JukeCooldown; } public override HTNOperatorStatus Update(NPCBlackboard blackboard, float frameTime) diff --git a/Content.Server/NPC/Systems/NPCJukeSystem.cs b/Content.Server/NPC/Systems/NPCJukeSystem.cs index da9fa1f7615..5a724762ef6 100644 --- a/Content.Server/NPC/Systems/NPCJukeSystem.cs +++ b/Content.Server/NPC/Systems/NPCJukeSystem.cs @@ -3,6 +3,7 @@ using Content.Server.NPC.Events; using Content.Server.NPC.HTN.PrimitiveTasks.Operators.Combat; using Content.Server.Weapons.Melee; +using Content.Shared.Coordinates.Helpers; using Content.Shared.NPC; using Content.Shared.Weapons.Melee; using Robust.Shared.Collections; @@ -38,22 +39,19 @@ public override void Initialize() private void OnJukeSteering(EntityUid uid, NPCJukeComponent component, ref NPCSteeringEvent args) { - if (component.JukeType == JukeType.AdjacentTile) + if (_timing.CurTime < component.NextJuke) { - if (_npcRangedQuery.TryGetComponent(uid, out var ranged) && - ranged.Status == CombatStatus.NotInSight) - { - component.TargetTile = null; - return; - } + component.TargetTile = null; + return; + } - if (_timing.CurTime < component.NextJuke) - { - component.TargetTile = null; - return; - } + component.NextJuke = _timing.CurTime + TimeSpan.FromSeconds(component.JukeCooldown); - if (!TryComp(args.Transform.GridUid, out var grid)) + if (component.JukeType == JukeType.AdjacentTile) + { + if (_npcRangedQuery.TryGetComponent(uid, out var ranged) + && ranged.Status is CombatStatus.NotInSight + || !TryComp(args.Transform.GridUid, out var grid)) { component.TargetTile = null; return; @@ -107,12 +105,11 @@ private void OnJukeSteering(EntityUid uid, NPCJukeComponent component, ref NPCSt var elapsed = _timing.CurTime - component.NextJuke; - // Finished juke, reset timer. - if (elapsed.TotalSeconds > component.JukeDuration || - currentTile == component.TargetTile) + // Finished juke. + if (elapsed.TotalSeconds > component.JukeDuration + || currentTile == component.TargetTile) { component.TargetTile = null; - component.NextJuke = _timing.CurTime + TimeSpan.FromSeconds(component.JukeDuration); return; } @@ -155,9 +152,7 @@ private void OnJukeSteering(EntityUid uid, NPCJukeComponent component, ref NPCSt var obstacleDirection = _transform.GetWorldPosition(melee.Target) - args.WorldPosition; if (obstacleDirection == Vector2.Zero) - { obstacleDirection = _random.NextVector2(); - } // If they're moving away then pursue anyway. // If just hit then always back up a bit.