Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Grab #30011

Open
wants to merge 23 commits into
base: master
Choose a base branch
from
Open

Grab #30011

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Content.Server/Alert/Click/StopPulling.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public void AlertClicked(EntityUid player)
if (entManager.TryGetComponent(player, out PullerComponent? puller) &&
entManager.TryGetComponent(puller.Pulling, out PullableComponent? pullableComp))
{
ps.TryStopPull(puller.Pulling.Value, pullableComp, user: player);
ps.TryLowerGrabStage(puller.Pulling.Value, player, true);
}
}
}
Expand Down
11 changes: 10 additions & 1 deletion Content.Server/Body/Systems/RespiratorSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
using JetBrains.Annotations;
using Robust.Shared.Prototypes;
using Robust.Shared.Timing;
using Content.Shared.Movement.Pulling.Systems;
using Content.Shared.Movement.Pulling.Components;

namespace Content.Server.Body.Systems;

Expand Down Expand Up @@ -59,6 +61,13 @@ private void OnUnpaused(Entity<RespiratorComponent> ent, ref EntityUnpausedEvent
ent.Comp.NextUpdate += args.PausedTime;
}

public bool CanBreathe(EntityUid uid)
{
if (TryComp<PullableComponent>(uid, out var pullable) && pullable.GrabStage == GrabStage.Suffocate)
return false;
return true;
}

public override void Update(float frameTime)
{
base.Update(frameTime);
Expand Down Expand Up @@ -91,7 +100,7 @@ public override void Update(float frameTime)
}
}

if (respirator.Saturation < respirator.SuffocationThreshold)
if (respirator.Saturation < respirator.SuffocationThreshold || !CanBreathe(uid))
{
if (_gameTiming.CurTime >= respirator.LastGaspEmoteTime + respirator.GaspEmoteCooldown)
{
Expand Down
25 changes: 24 additions & 1 deletion Content.Server/Hands/Systems/HandsSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
using Robust.Shared.Random;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
using Content.Shared.Hands;
using Content.Shared.Inventory.VirtualItem;

namespace Content.Server.Hands.Systems
{
Expand Down Expand Up @@ -90,7 +92,7 @@ private void OnDisarmed(EntityUid uid, HandsComponent component, DisarmedEvent a

// Break any pulls
if (TryComp(uid, out PullerComponent? puller) && TryComp(puller.Pulling, out PullableComponent? pullable))
_pullingSystem.TryStopPull(puller.Pulling.Value, pullable);
_pullingSystem.TryStopPull(puller.Pulling.Value, pullable, ignoreGrab: true);

var offsetRandomCoordinates = _transformSystem.GetMoverCoordinates(args.Target).Offset(_random.NextVector2(1f, 1.5f));
if (!ThrowHeldItem(args.Target, offsetRandomCoordinates))
Expand Down Expand Up @@ -173,6 +175,18 @@ private bool HandleThrowItem(ICommonSession? playerSession, EntityCoordinates co
if (playerSession?.AttachedEntity is not {Valid: true} player || !Exists(player))
return false;

if (TryGetActiveItem(player, out var item) && TryComp<VirtualItemComponent>(item, out var virtComp))
{
var userEv = new VirtualItemDropAttemptEvent(virtComp.BlockingEntity, player, item.Value, true);
RaiseLocalEvent(player, userEv);

var targEv = new VirtualItemDropAttemptEvent(virtComp.BlockingEntity, player, item.Value, true);
RaiseLocalEvent(virtComp.BlockingEntity, targEv);

if (userEv.Cancelled || targEv.Cancelled)
return false;
}

return ThrowHeldItem(player, coordinates);
}

Expand Down Expand Up @@ -216,6 +230,15 @@ hands.ActiveHandEntity is not { } throwEnt ||
var ev = new BeforeThrowEvent(throwEnt, direction, throwStrength, player);
RaiseLocalEvent(player, ref ev);

if (TryComp<VirtualItemComponent>(throwEnt, out var virt))
{
var userEv = new VirtualItemThrownEvent(virt.BlockingEntity, player, throwEnt, direction);
RaiseLocalEvent(player, userEv);

var targEv = new VirtualItemThrownEvent(virt.BlockingEntity, player, throwEnt, direction);
RaiseLocalEvent(virt.BlockingEntity, targEv);
}

if (ev.Cancelled)
return true;

Expand Down
4 changes: 2 additions & 2 deletions Content.Server/Implants/SubdermalImplantSystem.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Content.Server.Cuffs;
using Content.Server.Cuffs;
using Content.Server.Forensics;
using Content.Server.Humanoid;
using Content.Server.Implants.Components;
Expand Down Expand Up @@ -108,7 +108,7 @@ private void OnScramImplant(EntityUid uid, SubdermalImplantComponent component,
// We need stop the user from being pulled so they don't just get "attached" with whoever is pulling them.
// This can for example happen when the user is cuffed and being pulled.
if (TryComp<PullableComponent>(ent, out var pull) && _pullingSystem.IsPulled(ent, pull))
_pullingSystem.TryStopPull(ent, pull);
_pullingSystem.TryStopPull(ent, pull, ignoreGrab: true);

var xform = Transform(ent);
var targetCoords = SelectRandomTileInRange(xform, implant.TeleportRadius);
Expand Down
2 changes: 1 addition & 1 deletion Content.Shared/Administration/SharedAdminFrozenSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ private void OnStartup(EntityUid uid, AdminFrozenComponent component, ComponentS
{
if (TryComp<PullableComponent>(uid, out var pullable))
{
_pulling.TryStopPull(uid, pullable);
_pulling.TryStopPull(uid, pullable, ignoreGrab: true);
}

UpdateCanMove(uid, component, args);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ private void OnAnchorComplete(EntityUid uid, AnchorableComponent component, TryA

if (TryComp<PullableComponent>(uid, out var pullable) && pullable.Puller != null)
{
_pulling.TryStopPull(uid, pullable);
_pulling.TryStopPull(uid, pullable, ignoreGrab: true);
}

// TODO: Anchoring snaps rn anyway!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using Robust.Shared.Map;
using Robust.Shared.Player;
using Robust.Shared.Utility;
using Content.Shared.Hands;

namespace Content.Shared.Hands.EntitySystems;

Expand Down Expand Up @@ -98,7 +99,25 @@ private void SwapHandsPressed(ICommonSession? session)
private bool DropPressed(ICommonSession? session, EntityCoordinates coords, EntityUid netEntity)
{
if (TryComp(session?.AttachedEntity, out HandsComponent? hands) && hands.ActiveHand != null)
TryDrop(session.AttachedEntity.Value, hands.ActiveHand, coords, handsComp: hands);
{
if (session != null)
{
var ent = session.AttachedEntity.Value;

if (TryGetActiveItem(ent, out var item) && TryComp<VirtualItemComponent>(item, out var virtComp))
{
var userEv = new VirtualItemDropAttemptEvent(virtComp.BlockingEntity, ent, item.Value, false);
RaiseLocalEvent(ent, userEv);

var targEv = new VirtualItemDropAttemptEvent(virtComp.BlockingEntity, ent, item.Value, false);
RaiseLocalEvent(virtComp.BlockingEntity, targEv);

if (userEv.Cancelled || targEv.Cancelled)
return false;
}
TryDrop(ent, hands.ActiveHand, coords, handsComp: hands);
}
}

// always send to server.
return false;
Expand Down
43 changes: 42 additions & 1 deletion Content.Shared/Hands/HandEvents.cs
Original file line number Diff line number Diff line change
Expand Up @@ -148,11 +148,52 @@ public sealed class VirtualItemDeletedEvent : EntityEventArgs
{
public EntityUid BlockingEntity;
public EntityUid User;
public EntityUid VirtualItem;

public VirtualItemDeletedEvent(EntityUid blockingEntity, EntityUid user)
public VirtualItemDeletedEvent(EntityUid blockingEntity, EntityUid user, EntityUid virtualItem)
{
BlockingEntity = blockingEntity;
User = user;
VirtualItem = virtualItem;
}
}

/// <summary>
/// Raised directed on both the blocking entity and user when
/// a virtual hand item is thrown (at least attempted to).
/// </summary>
public sealed class VirtualItemThrownEvent : EntityEventArgs
{
public EntityUid BlockingEntity;
public EntityUid User;
public EntityUid VirtualItem;
public Vector2 Direction;
public VirtualItemThrownEvent(EntityUid blockingEntity, EntityUid user, EntityUid virtualItem, Vector2 direction)
{
BlockingEntity = blockingEntity;
User = user;
VirtualItem = virtualItem;
Direction = direction;
}
}

/// <summary>
/// Raised directed on both the blocking entity and user when
/// user tries to drop it by keybind.
/// Cancellable.
/// </summary>
public sealed class VirtualItemDropAttemptEvent : CancellableEntityEventArgs
{
public EntityUid BlockingEntity;
public EntityUid User;
public EntityUid VirtualItem;
public bool Throw;
public VirtualItemDropAttemptEvent(EntityUid blockingEntity, EntityUid user, EntityUid virtualItem, bool thrown)
{
BlockingEntity = blockingEntity;
User = user;
VirtualItem = virtualItem;
Throw = thrown;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,10 +235,10 @@ public bool TrySpawnVirtualItem(EntityUid blockingEnt, EntityUid user, [NotNullW
/// </summary>
public void DeleteVirtualItem(Entity<VirtualItemComponent> item, EntityUid user)
{
var userEv = new VirtualItemDeletedEvent(item.Comp.BlockingEntity, user);
var userEv = new VirtualItemDeletedEvent(item.Comp.BlockingEntity, user, item.Owner);
RaiseLocalEvent(user, userEv);

var targEv = new VirtualItemDeletedEvent(item.Comp.BlockingEntity, user);
var targEv = new VirtualItemDeletedEvent(item.Comp.BlockingEntity, user, item.Owner);
RaiseLocalEvent(item.Comp.BlockingEntity, targEv);

if (TerminatingOrDeleted(item))
Expand Down
14 changes: 14 additions & 0 deletions Content.Shared/MartialArts/Components/GrabThrownComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using Robust.Shared.GameStates;
using Content.Shared.Damage;

namespace Content.Shared.MartialArts.Components;

[RegisterComponent, NetworkedComponent]
public sealed partial class GrabThrownComponent : Component
{
public DamageSpecifier? DamageOnCollide;

public DamageSpecifier? WallDamageOnCollide;

public float? StaminaDamageOnCollide;
}
93 changes: 93 additions & 0 deletions Content.Shared/MartialArts/Systems/GrabThrownSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
using Content.Shared.Damage.Systems;
using Content.Shared.Damage;
using Content.Shared.Effects;
using Content.Shared.MartialArts.Components;
using Content.Shared.Throwing;
using Robust.Shared.Network;
using Robust.Shared.Physics.Events;
using Robust.Shared.Player;
using System.Numerics;

namespace Content.Shared.MartialArts.Systems;

public sealed class GrabThrownSystem : EntitySystem
{
[Dependency] private readonly DamageableSystem _damageable = default!;
[Dependency] private readonly SharedColorFlashEffectSystem _color = default!;
[Dependency] private readonly StaminaSystem _stamina = default!;
[Dependency] private readonly ThrowingSystem _throwing = default!;
[Dependency] private readonly INetManager _netMan = default!;

public override void Initialize()
{
base.Initialize();

SubscribeLocalEvent<GrabThrownComponent, StartCollideEvent>(HandleCollide);
SubscribeLocalEvent<GrabThrownComponent, StopThrowEvent>(OnStopThrow);
}

private void HandleCollide(EntityUid uid, GrabThrownComponent component, ref StartCollideEvent args)
{
if (_netMan.IsClient) // To avoid effect spam
return;

if (!HasComp<ThrownItemComponent>(uid))
{
RemComp<GrabThrownComponent>(uid);
return;
}

if (!args.OurFixture.Hard || !args.OtherFixture.Hard)
return;

if (!HasComp<DamageableComponent>(uid))
RemComp<GrabThrownComponent>(uid);

var speed = args.OurBody.LinearVelocity.Length();


if (component.StaminaDamageOnCollide != null)
_stamina.TakeStaminaDamage(uid, component.StaminaDamageOnCollide.Value);

var damageScale = speed;

if (component.DamageOnCollide != null)
_damageable.TryChangeDamage(uid, component.DamageOnCollide * damageScale);

if (component.WallDamageOnCollide != null)
_damageable.TryChangeDamage(args.OtherEntity, component.WallDamageOnCollide * damageScale);

_color.RaiseEffect(Color.Red, new List<EntityUid>() { uid }, Filter.Pvs(uid, entityManager: EntityManager));

RemComp<GrabThrownComponent>(uid);
}

private void OnStopThrow(EntityUid uid, GrabThrownComponent comp, StopThrowEvent args) // We dont need this comp to exsist after fall
{
if (HasComp<GrabThrownComponent>(uid))
RemComp<GrabThrownComponent>(uid);
}

/// <summary>
/// Throwing entity to the direction and ensures GrabThrownComponent with params
/// </summary>
/// <param name="uid">Entity to throw</param>
/// <param name="vector">Direction</param>
/// <param name="staminaDamage">Stamina damage on collide</param>
/// <param name="damageToUid">Damage to entity on collide</param>
/// <param name="damageToWall">Damage to wall or anything that was hit by entity</param>
public void Throw(
EntityUid uid,
Vector2 vector,
float? staminaDamage = null,
DamageSpecifier? damageToUid = null,
DamageSpecifier? damageToWall = null)
{
_throwing.TryThrow(uid, vector, 5f, animated: false);

var comp = EnsureComp<GrabThrownComponent>(uid);
comp.StaminaDamageOnCollide = staminaDamage;
comp.DamageOnCollide = damageToUid;
comp.WallDamageOnCollide = damageToWall;
}
}
20 changes: 20 additions & 0 deletions Content.Shared/Movement/Pulling/Components/PullableComponent.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using Content.Shared.Alert;
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
using Content.Shared.Movement.Pulling.Systems;
using Robust.Shared.Timing;

namespace Content.Shared.Movement.Pulling.Components;

Expand Down Expand Up @@ -41,4 +43,22 @@ public sealed partial class PullableComponent : Component

[DataField]
public ProtoId<AlertPrototype> PulledAlert = "Pulled";

[DataField]
public Dictionary<GrabStage, short> PulledAlertAlertSeverity = new()
{
{ GrabStage.No, 0 },
{ GrabStage.Soft, 1 },
{ GrabStage.Hard, 2 },
{ GrabStage.Suffocate, 3 },
};

[AutoNetworkedField, DataField]
public GrabStage GrabStage = GrabStage.No;

[AutoNetworkedField, DataField]
public float GrabEscapeChance = 1f;

[AutoNetworkedField]
public TimeSpan NextEscapeAttempt = TimeSpan.Zero;
}
Loading
Loading