Bandaid medibots (#11718)
This commit is contained in:
@@ -42,7 +42,7 @@ public sealed class MoveToOperator : HTNOperator
|
||||
/// Where the pathfinding result will be stored (if applicable). This gets removed after execution.
|
||||
/// </summary>
|
||||
[ViewVariables, DataField("pathfindKey")]
|
||||
public string PathfindKey = "MovementPathfind";
|
||||
public string PathfindKey = NPCBlackboard.PathfindKey;
|
||||
|
||||
/// <summary>
|
||||
/// How close we need to get before considering movement finished.
|
||||
|
||||
@@ -30,7 +30,7 @@ public sealed class PickAccessibleComponentOperator : HTNOperator
|
||||
/// Where the pathfinding result will be stored (if applicable). This gets removed after execution.
|
||||
/// </summary>
|
||||
[ViewVariables, DataField("pathfindKey")]
|
||||
public string PathfindKey = "MovementPathfind";
|
||||
public string PathfindKey = NPCBlackboard.PathfindKey;
|
||||
|
||||
public override void Initialize(IEntitySystemManager sysManager)
|
||||
{
|
||||
|
||||
@@ -23,7 +23,7 @@ public sealed class PickAccessibleOperator : HTNOperator
|
||||
/// Where the pathfinding result will be stored (if applicable). This gets removed after execution.
|
||||
/// </summary>
|
||||
[ViewVariables, DataField("pathfindKey")]
|
||||
public string PathfindKey = "MovementPathfind";
|
||||
public string PathfindKey = NPCBlackboard.PathfindKey;
|
||||
|
||||
public override void Initialize(IEntitySystemManager sysManager)
|
||||
{
|
||||
|
||||
@@ -50,6 +50,9 @@ public sealed class MedibotInjectOperator : HTNOperator
|
||||
if (!_entManager.TryGetComponent<MedibotComponent>(owner, out var botComp))
|
||||
return HTNOperatorStatus.Failed;
|
||||
|
||||
// To avoid spam, the rest of this needs fixing.
|
||||
_entManager.EnsureComponent<NPCRecentlyInjectedComponent>(target);
|
||||
|
||||
if (!_entManager.TryGetComponent<DamageableComponent>(target, out var damage))
|
||||
return HTNOperatorStatus.Failed;
|
||||
|
||||
@@ -62,20 +65,18 @@ public sealed class MedibotInjectOperator : HTNOperator
|
||||
if (damage.TotalDamage == 0)
|
||||
return HTNOperatorStatus.Failed;
|
||||
|
||||
if (damage.TotalDamage <= MedibotComponent.StandardMedDamageThreshold)
|
||||
if (damage.TotalDamage >= MedibotComponent.EmergencyMedDamageThreshold)
|
||||
{
|
||||
_solutionSystem.TryAddReagent(target, injectable, botComp.StandardMed, botComp.StandardMedInjectAmount, out var accepted);
|
||||
_entManager.EnsureComponent<NPCRecentlyInjectedComponent>(target);
|
||||
_solutionSystem.TryAddReagent(target, injectable, botComp.EmergencyMed, botComp.EmergencyMedInjectAmount, out var accepted);
|
||||
_popupSystem.PopupEntity(Loc.GetString("hypospray-component-feel-prick-message"), target, Filter.Entities(target));
|
||||
SoundSystem.Play("/Audio/Items/hypospray.ogg", Filter.Pvs(target), target);
|
||||
_chat.TrySendInGameICMessage(owner, Loc.GetString("medibot-finish-inject"), InGameICChatType.Speak, false);
|
||||
return HTNOperatorStatus.Finished;
|
||||
}
|
||||
|
||||
if (damage.TotalDamage >= MedibotComponent.EmergencyMedDamageThreshold)
|
||||
if (damage.TotalDamage >= MedibotComponent.StandardMedDamageThreshold)
|
||||
{
|
||||
_solutionSystem.TryAddReagent(target, injectable, botComp.EmergencyMed, botComp.EmergencyMedInjectAmount, out var accepted);
|
||||
_entManager.EnsureComponent<NPCRecentlyInjectedComponent>(target);
|
||||
_solutionSystem.TryAddReagent(target, injectable, botComp.StandardMed, botComp.StandardMedInjectAmount, out var accepted);
|
||||
_popupSystem.PopupEntity(Loc.GetString("hypospray-component-feel-prick-message"), target, Filter.Entities(target));
|
||||
SoundSystem.Play("/Audio/Items/hypospray.ogg", Filter.Pvs(target), target);
|
||||
_chat.TrySendInGameICMessage(owner, Loc.GetString("medibot-finish-inject"), InGameICChatType.Speak, false);
|
||||
|
||||
@@ -2,7 +2,9 @@ using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server.Chemistry.Components.SolutionManager;
|
||||
using Content.Server.NPC.Components;
|
||||
using Content.Server.NPC.Pathfinding;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.MobState.Components;
|
||||
|
||||
namespace Content.Server.NPC.HTN.PrimitiveTasks.Operators.Specific;
|
||||
@@ -11,6 +13,7 @@ public sealed class PickNearbyInjectableOperator : HTNOperator
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _entManager = default!;
|
||||
private EntityLookupSystem _lookup = default!;
|
||||
private PathfindingSystem _pathfinding = default!;
|
||||
|
||||
[ViewVariables, DataField("rangeKey")] public string RangeKey = NPCBlackboard.MedibotInjectRange;
|
||||
|
||||
@@ -30,6 +33,7 @@ public sealed class PickNearbyInjectableOperator : HTNOperator
|
||||
{
|
||||
base.Initialize(sysManager);
|
||||
_lookup = sysManager.GetEntitySystem<EntityLookupSystem>();
|
||||
_pathfinding = sysManager.GetEntitySystem<PathfindingSystem>();
|
||||
}
|
||||
|
||||
public override async Task<(bool Valid, Dictionary<string, object>? Effects)> Plan(NPCBlackboard blackboard,
|
||||
@@ -53,10 +57,16 @@ public sealed class PickNearbyInjectableOperator : HTNOperator
|
||||
damage.TotalDamage > 0 &&
|
||||
!recentlyInjected.HasComponent(entity))
|
||||
{
|
||||
var path = await _pathfinding.GetPath(owner, entity, SharedInteractionSystem.InteractionRange, cancelToken);
|
||||
|
||||
if (path.Result == PathResult.NoPath)
|
||||
continue;
|
||||
|
||||
return (true, new Dictionary<string, object>()
|
||||
{
|
||||
{TargetKey, entity},
|
||||
{TargetMoveKey, _entManager.GetComponent<TransformComponent>(entity).Coordinates}
|
||||
{TargetMoveKey, _entManager.GetComponent<TransformComponent>(entity).Coordinates},
|
||||
{NPCBlackboard.PathfindKey, path},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,6 +196,11 @@ public sealed class NPCBlackboard : IEnumerable<KeyValuePair<string, object>>
|
||||
public const string OwnerCoordinates = "OwnerCoordinates";
|
||||
public const string MovementTarget = "MovementTarget";
|
||||
|
||||
/// <summary>
|
||||
/// Can the NPC click open entities such as doors.
|
||||
/// </summary>
|
||||
public const string NavInteract = "NavInteract";
|
||||
|
||||
/// <summary>
|
||||
/// Can the NPC pry open doors for steering.
|
||||
/// </summary>
|
||||
@@ -205,6 +210,12 @@ public sealed class NPCBlackboard : IEnumerable<KeyValuePair<string, object>>
|
||||
/// Can the NPC smash obstacles for steering.
|
||||
/// </summary>
|
||||
public const string NavSmash = "NavSmash";
|
||||
|
||||
/// <summary>
|
||||
/// Default key storage for a movement pathfind.
|
||||
/// </summary>
|
||||
public const string PathfindKey = "MovementPathfind";
|
||||
|
||||
public const string RotateSpeed = "RotateSpeed";
|
||||
public const string VisionRadius = "VisionRadius";
|
||||
public const float MeleeRange = 1f;
|
||||
|
||||
@@ -19,4 +19,9 @@ public enum PathFlags : byte
|
||||
/// Can stuff like walls be broken.
|
||||
/// </summary>
|
||||
Smashing = 1 << 2,
|
||||
|
||||
/// <summary>
|
||||
/// Can we open stuff that requires interaction (e.g. click-open doors).
|
||||
/// </summary>
|
||||
Interact = 1 << 3,
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ public sealed partial class PathfindingSystem
|
||||
|
||||
// TODO: Handling power + door prying
|
||||
// Door we should be able to open
|
||||
if (isDoor && !isAccess)
|
||||
if (isDoor && !isAccess && (request.Flags & PathFlags.Interact) != 0x0)
|
||||
{
|
||||
modifier += 0.5f;
|
||||
}
|
||||
|
||||
@@ -280,6 +280,21 @@ namespace Content.Server.NPC.Pathfinding
|
||||
return distance;
|
||||
}
|
||||
|
||||
public async Task<PathResultEvent> GetPath(
|
||||
EntityUid entity,
|
||||
EntityUid target,
|
||||
float range,
|
||||
CancellationToken cancelToken,
|
||||
PathFlags flags = PathFlags.None)
|
||||
{
|
||||
if (!TryComp<TransformComponent>(entity, out var xform) ||
|
||||
!TryComp<TransformComponent>(target, out var targetXform))
|
||||
return new PathResultEvent(PathResult.NoPath, new Queue<PathPoly>());
|
||||
|
||||
var request = GetRequest(entity, xform.Coordinates, targetXform.Coordinates, range, cancelToken, flags);
|
||||
return await GetPath(request);
|
||||
}
|
||||
|
||||
public async Task<PathResultEvent> GetPath(
|
||||
EntityUid entity,
|
||||
EntityCoordinates start,
|
||||
@@ -385,16 +400,21 @@ namespace Content.Server.NPC.Pathfinding
|
||||
{
|
||||
var flags = PathFlags.None;
|
||||
|
||||
if (blackboard.TryGetValue<bool>(NPCBlackboard.NavPry, out var pry))
|
||||
if (blackboard.TryGetValue<bool>(NPCBlackboard.NavPry, out var pry) && pry)
|
||||
{
|
||||
flags |= PathFlags.Prying;
|
||||
}
|
||||
|
||||
if (blackboard.TryGetValue<bool>(NPCBlackboard.NavSmash, out var smash))
|
||||
if (blackboard.TryGetValue<bool>(NPCBlackboard.NavSmash, out var smash) && smash)
|
||||
{
|
||||
flags |= PathFlags.Smashing;
|
||||
}
|
||||
|
||||
if (blackboard.TryGetValue<bool>(NPCBlackboard.NavInteract, out var interact) && interact)
|
||||
{
|
||||
flags |= PathFlags.Interact;
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ public sealed partial class NPCSteeringSystem
|
||||
if (!doorQuery.TryGetComponent(ent, out var door))
|
||||
continue;
|
||||
|
||||
if (!door.BumpOpen)
|
||||
if (!door.BumpOpen && (component.Flags & PathFlags.Interact) != 0x0)
|
||||
{
|
||||
if (door.State != DoorState.Opening)
|
||||
{
|
||||
@@ -71,6 +71,10 @@ public sealed partial class NPCSteeringSystem
|
||||
return SteeringObstacleStatus.Continuing;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return SteeringObstacleStatus.Failed;
|
||||
}
|
||||
}
|
||||
|
||||
return SteeringObstacleStatus.Completed;
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
- type: HTN
|
||||
rootTask: XenoCompound
|
||||
blackboard:
|
||||
NavInteract: !type:Bool
|
||||
true
|
||||
NavPry: !type:Bool
|
||||
true
|
||||
NavSmash: !type:Bool
|
||||
|
||||
Reference in New Issue
Block a user