CatStation/Content.Shared/Throwing/CatchableSystem.cs
ArtisticRoomba 376f16504c
Content.Shared EntityQuery<T> dependency injection refactor (#43498)
* part 1

* second pass

* final fix

* last fix i swear

* an even bigger genius

* regex missed this

* should be all of em?

* oops

* yeah

* Revert "should be all of em?"

This reverts commit 4dd54d1b9a76977b4cf8d6008358e4dacdee6eb1.

---------

Co-authored-by: Princess Cheeseballs <66055347+Pronana@users.noreply.github.com>
2026-04-11 21:30:36 +00:00

79 lines
3.3 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 readonly INetManager _net = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly SharedHandsSystem _hands = default!;
[Dependency] private readonly SharedPopupSystem _popup = default!;
[Dependency] private readonly ThrownItemSystem _thrown = default!;
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly EntityWhitelistSystem _whitelist = default!;
[Dependency] private readonly EntityQuery<HandsComponent> _handsQuery = default!;
[Dependency] private readonly 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 PopupPredicted or 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, args.Target, args.Target);
_popup.PopupEntity(othersMessage, args.Target, Filter.PvsExcept(args.Target), true);
_audio.PlayPvs(ent.Comp.CatchSuccessSound, args.Target);
}
}