CatStation/Content.Shared/Throwing/CatchableSystem.cs
Whatstone a88d2c5164
Cleanup: Resolve remaining PopupSystem warnings in Content.Shared (#44685)
* PopupClient to PopupEntity/Coordinates

* PopupPredictedX to PopupEntity/Cursor/Coordinates

* The rest of the damn owl

* nullability fixes

* Buckle cleanup

* cleanup, address PR comments

* ExecutionSystem: one popup method

* correct my filthy lies

* Apply most of ajcm's suggestions

* return user to SharedItemRecallSystem.cs

* Fix lingering Ensnarable broadcast popups

* targeted drain popups

* fix lingering untargeted Guardian popups

I read the comment on GuardianHostRecall.  Oops.

* target stethoscope popups

* fix the PDA vibration popup

* Fix target for encryption key removal popup

* anomaly scanner: args.User, not uid

* disposal unit comment, bcast pda vibration popup
2026-07-16 21:54:33 +00:00

78 lines
3.2 KiB
C#

using Content.Shared.CombatMode;
using Content.Shared.Hands.Components;
using Content.Shared.Hands.EntitySystems;
using Content.Shared.IdentityManagement;
using Content.Shared.Popups;
using Content.Shared.Random.Helpers;
using Content.Shared.Whitelist;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Network;
using Robust.Shared.Player;
using Robust.Shared.Random;
using Robust.Shared.Timing;
namespace Content.Shared.Throwing;
public sealed partial class CatchableSystem : EntitySystem
{
[Dependency] private INetManager _net = default!;
[Dependency] private SharedAudioSystem _audio = default!;
[Dependency] private SharedHandsSystem _hands = default!;
[Dependency] private SharedPopupSystem _popup = default!;
[Dependency] private ThrownItemSystem _thrown = default!;
[Dependency] private IGameTiming _timing = default!;
[Dependency] private EntityWhitelistSystem _whitelist = default!;
[Dependency] private EntityQuery<HandsComponent> _handsQuery = default!;
[Dependency] private EntityQuery<CombatModeComponent> _combatModeQuery = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<CatchableComponent, ThrowDoHitEvent>(OnDoHit);
}
private void OnDoHit(Entity<CatchableComponent> ent, ref ThrowDoHitEvent args)
{
if (!_handsQuery.TryGetComponent(args.Target, out var handsComp))
return; // don't do anything for walls etc
// Is the catcher in combat mode if required?
if (ent.Comp.RequireCombatMode && (!_combatModeQuery.TryComp(args.Target, out var combatModeComp) || !combatModeComp.IsInCombatMode))
return;
// Is the catcher able to catch this item?
if (!_whitelist.IsWhitelistPassOrNull(ent.Comp.CatcherWhitelist, args.Target))
return;
var attemptEv = new CatchAttemptEvent(ent.Owner, ent.Comp.CatchChance);
RaiseLocalEvent(args.Target, ref attemptEv);
if (attemptEv.Cancelled)
return;
if (!SharedRandomExtensions.PredictedProb(_timing, ent.Comp.CatchChance, GetNetEntity(ent)))
return;
// Try to catch!
if (!_hands.TryPickupAnyHand(args.Target, ent.Owner, handsComp: handsComp, animate: false))
return; // The hands are full!
// Success!
// We picked it up already but we still have to raise the throwing stop (but not the landing) events at the right time,
// otherwise it will raise the events for that later while still in your hand
_thrown.StopThrow(ent.Owner, args.Component);
// Collisions don't work properly with PlayPredicted.
// So we make this server only.
if (_net.IsClient)
return;
var selfMessage = Loc.GetString("catchable-component-success-self", ("item", ent.Owner), ("catcher", Identity.Entity(args.Target, EntityManager)));
var othersMessage = Loc.GetString("catchable-component-success-others", ("item", ent.Owner), ("catcher", Identity.Entity(args.Target, EntityManager)));
_popup.PopupEntity(selfMessage, othersMessage, args.Target, args.Target);
_audio.PlayPvs(ent.Comp.CatchSuccessSound, args.Target);
}
}