Fix stupid NPC. (#26868)
* init commit * Review --------- Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com>
This commit is contained in:
@@ -0,0 +1,27 @@
|
|||||||
|
using Robust.Server.Containers;
|
||||||
|
|
||||||
|
namespace Content.Server.NPC.HTN.Preconditions;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if the owner in container or not
|
||||||
|
/// </summary>
|
||||||
|
public sealed partial class InContainerPrecondition : HTNPrecondition
|
||||||
|
{
|
||||||
|
private ContainerSystem _container = default!;
|
||||||
|
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)] [DataField("isInContainer")] public bool IsInContainer = true;
|
||||||
|
|
||||||
|
public override void Initialize(IEntitySystemManager sysManager)
|
||||||
|
{
|
||||||
|
base.Initialize(sysManager);
|
||||||
|
_container = sysManager.GetEntitySystem<ContainerSystem>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool IsMet(NPCBlackboard blackboard)
|
||||||
|
{
|
||||||
|
var owner = blackboard.GetValue<EntityUid>(NPCBlackboard.Owner);
|
||||||
|
|
||||||
|
return IsInContainer && _container.IsEntityInContainer(owner) ||
|
||||||
|
!IsInContainer && !_container.IsEntityInContainer(owner);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
using Robust.Server.Containers;
|
||||||
|
|
||||||
|
namespace Content.Server.NPC.HTN.PrimitiveTasks.Operators.Combat;
|
||||||
|
|
||||||
|
public sealed partial class ContainerOperator : HTNOperator
|
||||||
|
{
|
||||||
|
[Dependency] private readonly IEntityManager _entManager = default!;
|
||||||
|
private ContainerSystem _container = default!;
|
||||||
|
private EntityQuery<TransformComponent> _transformQuery;
|
||||||
|
|
||||||
|
[DataField("shutdownState")]
|
||||||
|
public HTNPlanState ShutdownState { get; private set; } = HTNPlanState.TaskFinished;
|
||||||
|
|
||||||
|
[DataField("targetKey", required: true)]
|
||||||
|
public string TargetKey = default!;
|
||||||
|
|
||||||
|
public override void Initialize(IEntitySystemManager sysManager)
|
||||||
|
{
|
||||||
|
base.Initialize(sysManager);
|
||||||
|
_container = sysManager.GetEntitySystem<ContainerSystem>();
|
||||||
|
_transformQuery = _entManager.GetEntityQuery<TransformComponent>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Startup(NPCBlackboard blackboard)
|
||||||
|
{
|
||||||
|
base.Startup(blackboard);
|
||||||
|
var owner = blackboard.GetValue<EntityUid>(NPCBlackboard.Owner);
|
||||||
|
|
||||||
|
if (!_container.TryGetOuterContainer(owner, _transformQuery.GetComponent(owner), out var outerContainer) && outerContainer == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var target = outerContainer.Owner;
|
||||||
|
blackboard.SetValue(TargetKey, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override HTNOperatorStatus Update(NPCBlackboard blackboard, float frameTime)
|
||||||
|
{
|
||||||
|
return HTNOperatorStatus.Finished;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,140 @@
|
|||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Content.Server.NPC.Components;
|
||||||
|
using Content.Server.Storage.EntitySystems;
|
||||||
|
using Content.Shared.CombatMode;
|
||||||
|
using Robust.Server.Containers;
|
||||||
|
|
||||||
|
namespace Content.Server.NPC.HTN.PrimitiveTasks.Operators.Combat.Melee;
|
||||||
|
|
||||||
|
public sealed partial class EscapeOperator : HTNOperator, IHtnConditionalShutdown
|
||||||
|
{
|
||||||
|
[Dependency] private readonly IEntityManager _entManager = default!;
|
||||||
|
private ContainerSystem _container = default!;
|
||||||
|
private EntityStorageSystem _entityStorage = default!;
|
||||||
|
|
||||||
|
[DataField("shutdownState")]
|
||||||
|
public HTNPlanState ShutdownState { get; private set; } = HTNPlanState.TaskFinished;
|
||||||
|
|
||||||
|
[DataField("targetKey", required: true)]
|
||||||
|
public string TargetKey = default!;
|
||||||
|
|
||||||
|
public override void Initialize(IEntitySystemManager sysManager)
|
||||||
|
{
|
||||||
|
base.Initialize(sysManager);
|
||||||
|
_container = sysManager.GetEntitySystem<ContainerSystem>();
|
||||||
|
_entityStorage = sysManager.GetEntitySystem<EntityStorageSystem>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Startup(NPCBlackboard blackboard)
|
||||||
|
{
|
||||||
|
base.Startup(blackboard);
|
||||||
|
var owner = blackboard.GetValue<EntityUid>(NPCBlackboard.Owner);
|
||||||
|
var target = blackboard.GetValue<EntityUid>(TargetKey);
|
||||||
|
|
||||||
|
if (_entityStorage.TryOpenStorage(owner, target))
|
||||||
|
{
|
||||||
|
TaskShutdown(blackboard, HTNOperatorStatus.Finished);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var melee = _entManager.EnsureComponent<NPCMeleeCombatComponent>(owner);
|
||||||
|
melee.MissChance = blackboard.GetValueOrDefault<float>(NPCBlackboard.MeleeMissChance, _entManager);
|
||||||
|
melee.Target = target;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<(bool Valid, Dictionary<string, object>? Effects)> Plan(NPCBlackboard blackboard,
|
||||||
|
CancellationToken cancelToken)
|
||||||
|
{
|
||||||
|
var owner = blackboard.GetValue<EntityUid>(NPCBlackboard.Owner);
|
||||||
|
if (!blackboard.TryGetValue<EntityUid>(TargetKey, out var target, _entManager))
|
||||||
|
{
|
||||||
|
return (false, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_container.IsEntityInContainer(owner))
|
||||||
|
{
|
||||||
|
return (false, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_entityStorage.TryOpenStorage(owner, target))
|
||||||
|
{
|
||||||
|
return (false, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (true, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ConditionalShutdown(NPCBlackboard blackboard)
|
||||||
|
{
|
||||||
|
var owner = blackboard.GetValue<EntityUid>(NPCBlackboard.Owner);
|
||||||
|
_entManager.System<SharedCombatModeSystem>().SetInCombatMode(owner, false);
|
||||||
|
_entManager.RemoveComponent<NPCMeleeCombatComponent>(owner);
|
||||||
|
blackboard.Remove<EntityUid>(TargetKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void TaskShutdown(NPCBlackboard blackboard, HTNOperatorStatus status)
|
||||||
|
{
|
||||||
|
base.TaskShutdown(blackboard, status);
|
||||||
|
|
||||||
|
ConditionalShutdown(blackboard);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void PlanShutdown(NPCBlackboard blackboard)
|
||||||
|
{
|
||||||
|
base.PlanShutdown(blackboard);
|
||||||
|
|
||||||
|
ConditionalShutdown(blackboard);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override HTNOperatorStatus Update(NPCBlackboard blackboard, float frameTime)
|
||||||
|
{
|
||||||
|
base.Update(blackboard, frameTime);
|
||||||
|
var owner = blackboard.GetValue<EntityUid>(NPCBlackboard.Owner);
|
||||||
|
HTNOperatorStatus status;
|
||||||
|
|
||||||
|
if (_entManager.TryGetComponent<NPCMeleeCombatComponent>(owner, out var combat) &&
|
||||||
|
blackboard.TryGetValue<EntityUid>(TargetKey, out var target, _entManager))
|
||||||
|
{
|
||||||
|
combat.Target = target;
|
||||||
|
|
||||||
|
// Success
|
||||||
|
if (!_container.IsEntityInContainer(owner))
|
||||||
|
{
|
||||||
|
status = HTNOperatorStatus.Finished;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (_entityStorage.TryOpenStorage(owner, target))
|
||||||
|
{
|
||||||
|
status = HTNOperatorStatus.Finished;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (combat.Status)
|
||||||
|
{
|
||||||
|
case CombatStatus.TargetOutOfRange:
|
||||||
|
case CombatStatus.Normal:
|
||||||
|
status = HTNOperatorStatus.Continuing;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
status = HTNOperatorStatus.Failed;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
status = HTNOperatorStatus.Failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mark it as finished to continue the plan.
|
||||||
|
if (status == HTNOperatorStatus.Continuing && ShutdownState == HTNPlanState.PlanFinished)
|
||||||
|
{
|
||||||
|
status = HTNOperatorStatus.Finished;
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
using Content.Shared.Movement.Pulling.Components;
|
||||||
|
using Content.Shared.Movement.Pulling.Systems;
|
||||||
|
|
||||||
|
namespace Content.Server.NPC.HTN.PrimitiveTasks.Operators.Combat;
|
||||||
|
|
||||||
|
public sealed partial class UnPullOperator : HTNOperator
|
||||||
|
{
|
||||||
|
[Dependency] private readonly IEntityManager _entManager = default!;
|
||||||
|
private PullingSystem _pulling = default!;
|
||||||
|
|
||||||
|
private EntityQuery<PullableComponent> _pullableQuery;
|
||||||
|
|
||||||
|
[DataField("shutdownState")]
|
||||||
|
public HTNPlanState ShutdownState { get; private set; } = HTNPlanState.TaskFinished;
|
||||||
|
|
||||||
|
public override void Initialize(IEntitySystemManager sysManager)
|
||||||
|
{
|
||||||
|
base.Initialize(sysManager);
|
||||||
|
_pulling = sysManager.GetEntitySystem<PullingSystem>();
|
||||||
|
_pullableQuery = _entManager.GetEntityQuery<PullableComponent>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Startup(NPCBlackboard blackboard)
|
||||||
|
{
|
||||||
|
base.Startup(blackboard);
|
||||||
|
var owner = blackboard.GetValue<EntityUid>(NPCBlackboard.Owner);
|
||||||
|
|
||||||
|
_pulling.TryStopPull(owner, _pullableQuery.GetComponent(owner), owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override HTNOperatorStatus Update(NPCBlackboard blackboard, float frameTime)
|
||||||
|
{
|
||||||
|
return HTNOperatorStatus.Finished;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
using Content.Server.Buckle.Systems;
|
||||||
|
using Content.Shared.Buckle.Components;
|
||||||
|
|
||||||
|
namespace Content.Server.NPC.HTN.PrimitiveTasks.Operators.Combat;
|
||||||
|
|
||||||
|
public sealed partial class UnbuckleOperator : HTNOperator
|
||||||
|
{
|
||||||
|
[Dependency] private readonly IEntityManager _entManager = default!;
|
||||||
|
private BuckleSystem _buckle = default!;
|
||||||
|
|
||||||
|
[DataField("shutdownState")]
|
||||||
|
public HTNPlanState ShutdownState { get; private set; } = HTNPlanState.TaskFinished;
|
||||||
|
|
||||||
|
public override void Initialize(IEntitySystemManager sysManager)
|
||||||
|
{
|
||||||
|
base.Initialize(sysManager);
|
||||||
|
_buckle = sysManager.GetEntitySystem<BuckleSystem>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Startup(NPCBlackboard blackboard)
|
||||||
|
{
|
||||||
|
base.Startup(blackboard);
|
||||||
|
var owner = blackboard.GetValue<EntityUid>(NPCBlackboard.Owner);
|
||||||
|
if (!_entManager.TryGetComponent<BuckleComponent>(owner, out var buckle) || !buckle.Buckled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_buckle.TryUnbuckle(owner, owner, true, buckle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override HTNOperatorStatus Update(NPCBlackboard blackboard, float frameTime)
|
||||||
|
{
|
||||||
|
return HTNOperatorStatus.Finished;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,6 +17,29 @@
|
|||||||
- !type:HTNCompoundTask
|
- !type:HTNCompoundTask
|
||||||
task: PickupMeleeCompound
|
task: PickupMeleeCompound
|
||||||
|
|
||||||
|
- preconditions:
|
||||||
|
- !type:BuckledPrecondition
|
||||||
|
isBuckled: true
|
||||||
|
tasks:
|
||||||
|
- !type:HTNPrimitiveTask
|
||||||
|
shutdownState: TaskFinished
|
||||||
|
operator: !type:UnbuckleOperator
|
||||||
|
|
||||||
|
- preconditions:
|
||||||
|
- !type:InContainerPrecondition
|
||||||
|
isInContainer: true
|
||||||
|
tasks:
|
||||||
|
- !type:HTNCompoundTask
|
||||||
|
task: EscapeCompound
|
||||||
|
|
||||||
|
- preconditions:
|
||||||
|
- !type:PulledPrecondition
|
||||||
|
isPulled: true
|
||||||
|
tasks:
|
||||||
|
- !type:HTNPrimitiveTask
|
||||||
|
shutdownState: TaskFinished
|
||||||
|
operator: !type:UnPullOperator
|
||||||
|
|
||||||
# Melee combat (unarmed or otherwise)
|
# Melee combat (unarmed or otherwise)
|
||||||
- tasks:
|
- tasks:
|
||||||
- !type:HTNPrimitiveTask
|
- !type:HTNPrimitiveTask
|
||||||
@@ -101,6 +124,21 @@
|
|||||||
proto: NearbyMeleeTargets
|
proto: NearbyMeleeTargets
|
||||||
key: Target
|
key: Target
|
||||||
|
|
||||||
|
- type: htnCompound
|
||||||
|
id: EscapeCompound
|
||||||
|
branches:
|
||||||
|
- tasks:
|
||||||
|
- !type:HTNPrimitiveTask
|
||||||
|
shutdownState: TaskFinished
|
||||||
|
operator: !type:ContainerOperator
|
||||||
|
targetKey: Target
|
||||||
|
- !type:HTNPrimitiveTask
|
||||||
|
operator: !type:EscapeOperator
|
||||||
|
targetKey: Target
|
||||||
|
preconditions:
|
||||||
|
- !type:InContainerPrecondition
|
||||||
|
isInContainer: true
|
||||||
|
|
||||||
- type: htnCompound
|
- type: htnCompound
|
||||||
id: MeleeAttackOrderedTargetCompound
|
id: MeleeAttackOrderedTargetCompound
|
||||||
branches:
|
branches:
|
||||||
|
|||||||
Reference in New Issue
Block a user