Skip to content

Commit

Permalink
add: grab
Browse files Browse the repository at this point in the history
  • Loading branch information
Spatison committed Aug 28, 2024
1 parent a625d9e commit 2491ff2
Show file tree
Hide file tree
Showing 27 changed files with 939 additions and 35 deletions.
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 @@ -10,6 +10,8 @@
using Content.Shared.Damage;
using Content.Shared.Database;
using Content.Shared.Mobs.Systems;
using Content.Shared.Movement.Pulling.Components;
using Content.Shared.Movement.Pulling.Systems;
using JetBrains.Annotations;
using Robust.Shared.Timing;

Expand Down Expand Up @@ -50,6 +52,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 @@ -82,7 +91,7 @@ public override void Update(float frameTime)
}
}

if (respirator.Saturation < respirator.SuffocationThreshold)
if (respirator.Saturation < respirator.SuffocationThreshold || !CanBreathe(uid))
{
if (_gameTiming.CurTime >= respirator.LastGaspPopupTime + respirator.GaspPopupCooldown)
{
Expand Down
24 changes: 23 additions & 1 deletion Content.Server/Hands/Systems/HandsSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using Content.Shared.Body.Part;
using Content.Shared.CombatMode;
using Content.Shared.Explosion;
using Content.Shared.Hands;
using Content.Shared.Hands.Components;
using Content.Shared.Hands.EntitySystems;
using Content.Shared.Input;
Expand Down Expand Up @@ -88,7 +89,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);

if (!_handsSystem.TryDrop(uid, component.ActiveHand!, null, checkActionBlocker: false))
return;
Expand Down Expand Up @@ -168,6 +169,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 @@ -211,6 +224,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
2 changes: 1 addition & 1 deletion Content.Server/Implants/SubdermalImplantSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,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/AdminFrozenSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,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 @@ -133,7 +133,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 @@ -95,7 +95,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
37 changes: 37 additions & 0 deletions Content.Shared/Hands/EntitySystems/SharedHandsSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,43 @@ public bool TryGetEmptyHand(EntityUid uid, [NotNullWhen(true)] out Hand? emptyHa
return false;
}

public bool TryGetActiveHand(Entity<HandsComponent?> entity, [NotNullWhen(true)] out Hand? hand)
{
if (!Resolve(entity, ref entity.Comp, false))
{
hand = null;
return false;
}

hand = entity.Comp.ActiveHand;
return hand != null;
}

public bool TryGetActiveItem(Entity<HandsComponent?> entity, [NotNullWhen(true)] out EntityUid? item)
{
if (!TryGetActiveHand(entity, out var hand))
{
item = null;
return false;
}

item = hand.HeldEntity;
return item != null;
}

public Hand? GetActiveHand(Entity<HandsComponent?> entity)
{
if (!Resolve(entity, ref entity.Comp))
return null;

return entity.Comp.ActiveHand;
}

public EntityUid? GetActiveItem(Entity<HandsComponent?> entity)
{
return GetActiveHand(entity)?.HeldEntity;
}

/// <summary>
/// Enumerate over hands, starting with the currently active hand.
/// </summary>
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
50 changes: 42 additions & 8 deletions Content.Shared/Inventory/VirtualItem/SharedVirtualItemSystem.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
using System.Diagnostics.CodeAnalysis;
using Content.Shared.Hands;
using Content.Shared.Hands.Components;
using Content.Shared.Hands.EntitySystems;
using Content.Shared.Interaction;
using Content.Shared.Inventory.Events;
using Content.Shared.Item;
using Content.Shared.Popups;
using Robust.Shared.Containers;
using Robust.Shared.Network;
using Robust.Shared.Prototypes;
Expand All @@ -29,6 +31,7 @@ public abstract class SharedVirtualItemSystem : EntitySystem
[Dependency] private readonly SharedItemSystem _itemSystem = default!;
[Dependency] private readonly InventorySystem _inventorySystem = default!;
[Dependency] private readonly SharedHandsSystem _handsSystem = default!;
[Dependency] private readonly SharedPopupSystem _popup = default!;

[ValidatePrototypeId<EntityPrototype>]
private const string VirtualItem = "VirtualItem";
Expand Down Expand Up @@ -76,18 +79,49 @@ private void OnBeforeRangedInteract(Entity<VirtualItemComponent> ent, ref Before
/// </summary>
/// <param name="blockingEnt">The entity we will make a virtual entity copy of</param>
/// <param name="user">The entity that we want to insert the virtual entity</param>
public bool TrySpawnVirtualItemInHand(EntityUid blockingEnt, EntityUid user)
public bool TrySpawnVirtualItemInHand(EntityUid blockingEnt, EntityUid user, bool dropOthers = false)
{
return TrySpawnVirtualItemInHand(blockingEnt, user, out _);
return TrySpawnVirtualItemInHand(blockingEnt, user, out _, dropOthers);
}

/// <inheritdoc cref="TrySpawnVirtualItemInHand(Robust.Shared.GameObjects.EntityUid,Robust.Shared.GameObjects.EntityUid)"/>
public bool TrySpawnVirtualItemInHand(EntityUid blockingEnt, EntityUid user, [NotNullWhen(true)] out EntityUid? virtualItem)
public bool TrySpawnVirtualItemInHand(EntityUid blockingEnt, EntityUid user, [NotNullWhen(true)] out EntityUid? virtualItem, bool dropOthers = false, Hand? empty = null)
{
if (!TrySpawnVirtualItem(blockingEnt, user, out virtualItem) || !_handsSystem.TryGetEmptyHand(user, out var hand))
virtualItem = null;
if (empty == null && !_handsSystem.TryGetEmptyHand(user, out empty))
{
if (!dropOthers)
return false;

foreach (var hand in _handsSystem.EnumerateHands(user))
{
if (hand.HeldEntity is not { } held)
continue;

if (held == blockingEnt)
continue;

if (HasComp<VirtualItemComponent>(held))
continue;

if (!_handsSystem.TryDrop(user, hand))
continue;

if (!TerminatingOrDeleted(held))
_popup.PopupClient(Loc.GetString("virtual-item-dropped-other", ("dropped", held)), user, user);

empty = hand;
break;
}
}

if (empty == null)
return false;

if (!TrySpawnVirtualItem(blockingEnt, user, out virtualItem))
return false;

_handsSystem.DoPickup(user, hand, virtualItem.Value);
_handsSystem.DoPickup(user, empty, virtualItem.Value);
return true;
}

Expand Down Expand Up @@ -188,7 +222,7 @@ public bool TrySpawnVirtualItem(EntityUid blockingEnt, EntityUid user, [NotNullW

var pos = Transform(user).Coordinates;
virtualItem = Spawn(VirtualItem, pos);
var virtualItemComp = Comp<VirtualItemComponent>(virtualItem.Value);
var virtualItemComp = EnsureComp<VirtualItemComponent>(virtualItem.Value);
virtualItemComp.BlockingEntity = blockingEnt;
Dirty(virtualItem.Value, virtualItemComp);
return true;
Expand All @@ -199,10 +233,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
20 changes: 20 additions & 0 deletions Content.Shared/Movement/Pulling/Components/PullableComponent.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using Content.Shared.Movement.Pulling.Systems;
using Robust.Shared.GameStates;

namespace Content.Shared.Movement.Pulling.Components;
Expand Down Expand Up @@ -36,4 +37,23 @@ public sealed partial class PullableComponent : Component
[Access(typeof(Systems.PullingSystem), Other = AccessPermissions.ReadExecute)]
[AutoNetworkedField, DataField]
public bool PrevFixedRotation;


[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

0 comments on commit 2491ff2

Please sign in to comment.