Files
Delta-v/Content.Shared/_DV/Grappling/Components/GrapplerComponent.cs
T
BarryNorfolk 63b2eadada [K9] Rework Grappling (#5337)
* Remove unused ProtoId

* Remove unused variable

* Move the entire of grappling into shared

* Move grappler to Secdog base to enable all secdogs to grapple

* Fix prediction on grappling from move to shared

* Also block any StandUpAttempt events

* Remove secdog hand disabling and up cooldown to 15 seconds

* Add grapple activation modes

* Implement new activation mode handling

* Allow damage accumlated to release grapples

* Add initial damage to activation mode

* Immediately refresh modifiers on releasing of grapple

* Check accumulated damage constantly, clear damage via timer

* Only emit popups from server side

* Update Laika's grappler component to use new activation mode

* Add event for entering stamina crit

* Release grapple when victim enters crit

* Minor rewording of grapple starting

* Typo

* Rely solely on the shared system for grappling now

* Change activation mode from class to interface
2026-04-11 17:35:25 +02:00

127 lines
3.9 KiB
C#

using Content.Shared._DV.Grappling.EntitySystems;
using Content.Shared.Alert;
using Content.Shared.FixedPoint;
using Robust.Shared.Audio;
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
namespace Content.Shared._DV.Grappling.Components;
/// <summary>
/// Marks this entity as a grappler.
/// </summary>
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
[Access(typeof(SharedGrapplingSystem))]
public sealed partial class GrapplerComponent : Component
{
/// <summary>
/// How much time is required to escape a grapple from this entity.
/// </summary>
[DataField]
public TimeSpan EscapeTime = TimeSpan.FromSeconds(15);
/// <summary>
/// The sound to play when the grapple action is successful on a target.
/// </summary>
[DataField]
public SoundSpecifier GrappleSound = new SoundPathSpecifier("/Audio/_DV/Grappling/grapple_action.ogg");
/// <summary>
/// Whether this entity can move by itself while grappling.
/// </summary>
[DataField]
public bool CanMoveWhileGrappling = false;
/// <summary>
/// Whether this entity should also lay prone when grappling.
/// </summary>
[DataField]
public bool ProneOnGrapple = false;
/// <summary>
/// Whether grapples from this entity should disable no, a random, or all hands of the victim.
/// </summary>
[DataField]
public HandDisabling HandDisabling = HandDisabling.None;
/// <summary>
/// What localized string is to be used for the body part in the grapple.
/// I.e. Jaws, Hands, Claws, etc.
/// </summary>
[DataField(required: true)]
public LocId GrapplingPart;
/// <summary>
/// The entity, if any, which this unit is grappling.
/// </summary>
[DataField]
[AutoNetworkedField]
public EntityUid? ActiveVictim = null;
/// <summary>
/// Cooldown for grappling to apply at the moment the grapple is broken.
/// </summary>
[DataField]
public TimeSpan Cooldown = TimeSpan.FromSeconds(5);
/// <summary>
/// Time when the cooldown for the grapple will be over.
/// </summary>
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), AutoNetworkedField]
public TimeSpan CooldownEnd;
/// <summary>
/// Which alert to show when a victim is grappled.
/// </summary>
[DataField]
public ProtoId<AlertPrototype> GrappledAlert = "Grappled";
/// <summary>
/// The joint ID used between the grappler and victim.
/// </summary>
[DataField, AutoNetworkedField]
public string? PullJointId = null;
/// <summary>
/// How the grapple from this entity will take effect.
/// </summary>
[DataField]
public IGrapplerActivationMode ActivationMode = new GrapplerActivationImmediate();
/// <summary>
/// How much damage this grappler can sustain before the grapple is forcibly broken.
/// </summary>
[DataField]
public FixedPoint2 DamageThreshold = 5f;
/// <summary>
/// How much damage the grappler has accumulated since the last update.
/// </summary>
[DataField, AutoNetworkedField]
public FixedPoint2 DamageAccumulated = 0f;
/// <summary>
/// When the next clear for damage accumulated should occur.
/// </summary>
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), AutoNetworkedField]
public TimeSpan NextDamageClear = TimeSpan.MinValue;
/// <summary>
/// Time between clears for the accumulated damage on the grappler.
/// </summary>
[DataField]
public TimeSpan DamageClearCooldown = TimeSpan.FromSeconds(2);
}
/// <summary>
/// Whether hands should be disabled by the grappling.
/// </summary>
public enum HandDisabling
{
None, // No hands to be disabled.
SingleRandom, // A single hand is disabled at random from available hands.
SingleActive, // The active hand is disabled.
All, // All hands are disabled.
}