6
2025-12-18 02:55:17 +03:00

235 lines
9.6 KiB
C#

using Content.Shared._RMC14.Wieldable.Components;
using Content.Shared._RMC14.Wieldable.Events;
using Content.Shared.Hands;
using Content.Shared.Hands.Components;
using Content.Shared.Interaction.Events;
using Content.Shared.Inventory;
using Content.Shared.Inventory.Events;
using Content.Shared.Movement.Systems;
using Content.Shared.Popups;
using Content.Shared.Timing;
using Content.Shared.Weapons.Ranged.Events;
using Content.Shared.Wieldable;
using Content.Shared.Wieldable.Components;
using Robust.Shared.Containers;
using Robust.Shared.Prototypes;
using Robust.Shared.Timing;
namespace Content.Shared._RMC14.Wieldable;
public sealed class RMCWieldableSystem : EntitySystem
{
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly InventorySystem _inventorySystem = default!;
[Dependency] private readonly MovementSpeedModifierSystem _movementSpeedModifierSystem = default!;
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
[Dependency] private readonly UseDelaySystem _useDelaySystem = default!;
[Dependency] private readonly SharedContainerSystem _container = default!;
private const string WieldUseDelayID = "RMCWieldDelay";
public override void Initialize()
{
SubscribeLocalEvent<WieldableSpeedModifiersComponent, GotEquippedHandEvent>(OnGotEquippedHand);
SubscribeLocalEvent<WieldableSpeedModifiersComponent, GotUnequippedHandEvent>(OnGotUnequippedHand);
SubscribeLocalEvent<WieldableSpeedModifiersComponent, HeldRelayedEvent<RefreshMovementSpeedModifiersEvent>>(OnRefreshMovementSpeedModifiers);
SubscribeLocalEvent<WieldableSpeedModifiersComponent, ItemUnwieldedEvent>(OnItemUnwielded);
SubscribeLocalEvent<WieldableSpeedModifiersComponent, ItemWieldedEvent>(OnItemWielded);
SubscribeLocalEvent<WieldableSpeedModifiersComponent, MapInitEvent>(OnMapInit);
SubscribeLocalEvent<WieldSlowdownCompensationComponent, GotEquippedEvent>(OnGotEquipped);
SubscribeLocalEvent<WieldSlowdownCompensationComponent, GotUnequippedEvent>(OnGotUnequipped);
SubscribeLocalEvent<WieldDelayComponent, GotEquippedHandEvent>(OnGotEquippedHand);
SubscribeLocalEvent<WieldDelayComponent, MapInitEvent>(OnMapInit);
SubscribeLocalEvent<WieldDelayComponent, UseInHandEvent>(OnUseInHand);
SubscribeLocalEvent<WieldDelayComponent, ShotAttemptedEvent>(OnShotAttempt);
SubscribeLocalEvent<WieldDelayComponent, ItemWieldedEvent>(OnItemWieldedWithDelay);
SubscribeLocalEvent<InventoryComponent, RefreshWieldSlowdownCompensationEvent>(_inventorySystem.RelayEvent);
}
private void OnMapInit(Entity<WieldableSpeedModifiersComponent> wieldable, ref MapInitEvent args)
{
RefreshSpeedModifiers((wieldable.Owner, wieldable.Comp));
}
private void OnMapInit(Entity<WieldDelayComponent> wieldable, ref MapInitEvent args)
{
wieldable.Comp.ModifiedDelay = wieldable.Comp.BaseDelay;
}
#region Wield speed modifiers
private void OnGotEquippedHand(Entity<WieldableSpeedModifiersComponent> wieldable, ref GotEquippedHandEvent args)
{
_movementSpeedModifierSystem.RefreshMovementSpeedModifiers(args.User);
}
private void OnGotUnequippedHand(Entity<WieldableSpeedModifiersComponent> wieldable, ref GotUnequippedHandEvent args)
{
_movementSpeedModifierSystem.RefreshMovementSpeedModifiers(args.User);
}
private void OnRefreshMovementSpeedModifiers(Entity<WieldableSpeedModifiersComponent> wieldable, ref HeldRelayedEvent<RefreshMovementSpeedModifiersEvent> args)
{
if (TryComp(wieldable.Owner, out TransformComponent? transformComponent) &&
transformComponent.ParentUid.Valid &&
TryComp(transformComponent.ParentUid, out WieldSlowdownCompensationUserComponent? userComponent))
{
args.Args.ModifySpeed(
Math.Min(wieldable.Comp.ModifiedWalk + userComponent.Walk, 1f),
Math.Min(wieldable.Comp.ModifiedSprint + userComponent.Sprint, 1f));
return;
}
args.Args.ModifySpeed(wieldable.Comp.ModifiedWalk, wieldable.Comp.ModifiedSprint);
}
public void RefreshSpeedModifiers(Entity<WieldableSpeedModifiersComponent?> wieldable)
{
wieldable.Comp = EnsureComp<WieldableSpeedModifiersComponent>(wieldable);
var walkSpeed = wieldable.Comp.BaseWalk;
var sprintSpeed = wieldable.Comp.BaseSprint;
if (!TryComp(wieldable.Owner, out WieldableComponent? wieldableComponent) || !wieldableComponent.Wielded)
{
walkSpeed = 1f;
sprintSpeed = 1f;
}
var ev = new GetWieldableSpeedModifiersEvent(walkSpeed, sprintSpeed);
RaiseLocalEvent(wieldable, ref ev);
wieldable.Comp.ModifiedWalk = ev.Walk > 0 ? ev.Walk : 0;
wieldable.Comp.ModifiedSprint = ev.Sprint > 0 ? ev.Sprint : 0;
RefreshModifiersOnParent(wieldable.Owner);
}
private void OnItemUnwielded(Entity<WieldableSpeedModifiersComponent> wieldable, ref ItemUnwieldedEvent args)
{
RefreshSpeedModifiers((wieldable.Owner, wieldable.Comp));
}
private void OnItemWielded(Entity<WieldableSpeedModifiersComponent> wieldable, ref ItemWieldedEvent args)
{
RefreshSpeedModifiers((wieldable.Owner, wieldable.Comp));
}
private void RefreshModifiersOnParent(EntityUid wieldableUid)
{
if (!TryComp(wieldableUid, out TransformComponent? transformComponent) ||
!transformComponent.ParentUid.Valid ||
!TryComp(transformComponent.ParentUid, out HandsComponent? handsComponent) ||
handsComponent.ActiveHandEntity != wieldableUid)
{
return;
}
_movementSpeedModifierSystem.RefreshMovementSpeedModifiers(transformComponent.ParentUid);
}
#endregion
#region Wield slowdown compensation
private void OnGotEquipped(Entity<WieldSlowdownCompensationComponent> armour, ref GotEquippedEvent args)
{
EnsureComp(args.Equipee, out WieldSlowdownCompensationUserComponent comp);
RefreshWieldSlowdownCompensation((args.Equipee, comp));
}
private void OnGotUnequipped(Entity<WieldSlowdownCompensationComponent> armour, ref GotUnequippedEvent args)
{
EnsureComp(args.Equipee, out WieldSlowdownCompensationUserComponent comp);
RefreshWieldSlowdownCompensation((args.Equipee, comp));
}
private void RefreshWieldSlowdownCompensation(Entity<WieldSlowdownCompensationUserComponent> user)
{
var ev = new RefreshWieldSlowdownCompensationEvent(~SlotFlags.POCKET);
RaiseLocalEvent(user.Owner, ref ev);
user.Comp.Walk = ev.Walk;
user.Comp.Walk = ev.Sprint;
}
private void OnRefreshWieldSlowdownCompensation(Entity<WieldSlowdownCompensationComponent> armour, ref InventoryRelayedEvent<RefreshWieldSlowdownCompensationEvent> args)
{
args.Args.Walk += armour.Comp.Walk;
args.Args.Sprint += armour.Comp.Sprint;
}
#endregion
#region Wield delay
private void OnGotEquippedHand(Entity<WieldDelayComponent> wieldable, ref GotEquippedHandEvent args)
{
_useDelaySystem.SetLength(wieldable.Owner, wieldable.Comp.ModifiedDelay, WieldUseDelayID);
_useDelaySystem.TryResetDelay(wieldable.Owner, id: WieldUseDelayID);
}
private void OnUseInHand(Entity<WieldDelayComponent> wieldable, ref UseInHandEvent args)
{
if (!TryComp(wieldable.Owner, out UseDelayComponent? useDelayComponent) ||
!_useDelaySystem.IsDelayed((wieldable.Owner, useDelayComponent), WieldUseDelayID))
{
return;
}
args.Handled = true;
if (!_useDelaySystem.TryGetDelayInfo((wieldable.Owner, useDelayComponent), out var info, WieldUseDelayID))
{
return;
}
var time = $"{(info.EndTime - _timing.CurTime).TotalSeconds:F1}";
_popupSystem.PopupClient(Loc.GetString("rmc-wield-use-delay", ("seconds", time), ("wieldable", wieldable.Owner)), args.User, args.User);
}
public void RefreshWieldDelay(Entity<WieldDelayComponent?> wieldable)
{
wieldable.Comp = EnsureComp<WieldDelayComponent>(wieldable);
var ev = new GetWieldDelayEvent(wieldable.Comp.BaseDelay);
RaiseLocalEvent(wieldable, ref ev);
wieldable.Comp.ModifiedDelay = ev.Delay >= TimeSpan.Zero ? ev.Delay : TimeSpan.Zero;
}
private void OnItemWieldedWithDelay(Entity<WieldDelayComponent> wieldable, ref ItemWieldedEvent args)
{
// TODO RMC14 +0.5s if Dazed
var skillModifiedDelay = wieldable.Comp.ModifiedDelay;
if (_container.TryGetContainingContainer((wieldable, null), out var container))
skillModifiedDelay -= TimeSpan.FromSeconds(0.2) * 1; // ADT ЗАТЫЧКА
_useDelaySystem.SetLength(wieldable.Owner, skillModifiedDelay, WieldUseDelayID);
_useDelaySystem.TryResetDelay(wieldable.Owner, id: WieldUseDelayID);
}
public void OnShotAttempt(Entity<WieldDelayComponent> wieldable, ref ShotAttemptedEvent args)
{
if (!TryComp(wieldable.Owner, out UseDelayComponent? useDelayComponent) ||
!_useDelaySystem.IsDelayed((wieldable.Owner, useDelayComponent), WieldUseDelayID) ||
!_useDelaySystem.TryGetDelayInfo((wieldable.Owner, useDelayComponent), out var info, WieldUseDelayID))
{
return;
}
args.Cancel();
var time = $"{(info.EndTime - _timing.CurTime).TotalSeconds:F1}";
//_popupSystem.PopupClient(Loc.GetString("rmc-shoot-use-delay", ("seconds", time), ("wieldable", wieldable.Owner)), args.User, args.User);
// Uncomment when there's a cooldown on popups from a source.
}
#endregion
}