From 1b03779569d11f3d416dfbcedddf33fb5f602d28 Mon Sep 17 00:00:00 2001 From: Sidzaru <110207359+Sidzaru@users.noreply.github.com> Date: Sat, 27 Sep 2025 00:24:03 +0300 Subject: [PATCH] Weapon block component during selection (#3110) --- .../Weapons/Melee/MeleeWeaponComponent.cs | 6 --- .../Weapons/Melee/SharedMeleeWeaponSystem.cs | 41 +++++++++++----- .../Weapons/Misc/EquipDelayComponent.cs | 13 +++++ .../Weapons/Ranged/Components/GunComponent.cs | 8 +--- .../Systems/SharedGunSystem.Interactions.cs | 47 ++++++++++++------- .../Entities/Objects/Misc/handcuffs.yml | 1 - 6 files changed, 73 insertions(+), 43 deletions(-) create mode 100644 Content.Shared/Weapons/Misc/EquipDelayComponent.cs diff --git a/Content.Shared/Weapons/Melee/MeleeWeaponComponent.cs b/Content.Shared/Weapons/Melee/MeleeWeaponComponent.cs index 84e88156ad..6ae4857547 100644 --- a/Content.Shared/Weapons/Melee/MeleeWeaponComponent.cs +++ b/Content.Shared/Weapons/Melee/MeleeWeaponComponent.cs @@ -34,12 +34,6 @@ public sealed partial class MeleeWeaponComponent : Component [AutoPausedField] public TimeSpan NextAttack; - /// - /// Starts attack cooldown when equipped if true. - /// - [DataField, AutoNetworkedField] - public bool ResetOnHandSelected = true; - /* * Melee combat works based around 2 types of attacks: * 1. Click attacks with left-click. This attacks whatever is under your mnouse diff --git a/Content.Shared/Weapons/Melee/SharedMeleeWeaponSystem.cs b/Content.Shared/Weapons/Melee/SharedMeleeWeaponSystem.cs index c032b8b926..98a6e746c0 100644 --- a/Content.Shared/Weapons/Melee/SharedMeleeWeaponSystem.cs +++ b/Content.Shared/Weapons/Melee/SharedMeleeWeaponSystem.cs @@ -129,27 +129,44 @@ public abstract class SharedMeleeWeaponSystem : EntitySystem } } - private void OnMeleeSelected(EntityUid uid, MeleeWeaponComponent component, HandSelectedEvent args) + private void OnMeleeSelected(Entity ent, ref HandSelectedEvent args) { - var attackRate = GetAttackRate(uid, args.User, component); - if (attackRate.Equals(0f)) - return; + var uid = ent.Owner; - if (!component.ResetOnHandSelected) + var attackRate = GetAttackRate(uid, args.User, ent); + if (attackRate == 0f) return; if (Paused(uid)) return; - // If someone swaps to this weapon then reset its cd. - var curTime = Timing.CurTime; - var minimum = curTime + TimeSpan.FromSeconds(1 / attackRate); + if (TryComp(uid, out var delayComp)) + { + var delay = delayComp.EquipDelayTime; + var curTime = Timing.CurTime; - if (minimum < component.NextAttack) - return; + var minimum = curTime + TimeSpan.FromSeconds(delay); - component.NextAttack = minimum; - DirtyField(uid, component, nameof(MeleeWeaponComponent.NextAttack)); + if (minimum < ent.Comp.NextAttack) + return; + + ent.Comp.NextAttack = minimum; + + DirtyField(uid, ent.Comp, nameof(MeleeWeaponComponent.NextAttack)); + } + else + { + var curTime = Timing.CurTime; + + var minimum = curTime + TimeSpan.FromSeconds(0.3); + + if (minimum < ent.Comp.NextAttack) + return; + + ent.Comp.NextAttack = minimum; + + DirtyField(uid, ent.Comp, nameof(MeleeWeaponComponent.NextAttack)); + } } private void OnGetBonusMeleeDamage(EntityUid uid, BonusMeleeDamageComponent component, ref GetMeleeDamageEvent args) diff --git a/Content.Shared/Weapons/Misc/EquipDelayComponent.cs b/Content.Shared/Weapons/Misc/EquipDelayComponent.cs new file mode 100644 index 0000000000..d198aca5f2 --- /dev/null +++ b/Content.Shared/Weapons/Misc/EquipDelayComponent.cs @@ -0,0 +1,13 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared.Weapons; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +public sealed partial class EquipDelayComponent : Component +{ + /// + /// Delay before the next attack after picking up a weapon, in seconds. + /// + [DataField("delay"), AutoNetworkedField] + public float EquipDelayTime = 0.3f; +} \ No newline at end of file diff --git a/Content.Shared/Weapons/Ranged/Components/GunComponent.cs b/Content.Shared/Weapons/Ranged/Components/GunComponent.cs index 86e6ec777f..3e9828badd 100644 --- a/Content.Shared/Weapons/Ranged/Components/GunComponent.cs +++ b/Content.Shared/Weapons/Ranged/Components/GunComponent.cs @@ -209,12 +209,6 @@ public sealed partial class GunComponent : Component [AutoNetworkedField, ViewVariables(VVAccess.ReadWrite)] public float FireRateModified; - /// - /// Starts fire cooldown when equipped if true. - /// - [DataField] - public bool ResetOnHandSelected = true; - /// /// The base value for how fast the projectile moves. /// @@ -232,7 +226,7 @@ public sealed partial class GunComponent : Component /// When the gun is next available to be shot. /// Can be set multiple times in a single tick due to guns firing faster than a single tick time. /// - [DataField(customTypeSerializer:typeof(TimeOffsetSerializer))] + [DataField(customTypeSerializer: typeof(TimeOffsetSerializer))] [AutoNetworkedField] [AutoPausedField] public TimeSpan NextFire = TimeSpan.Zero; diff --git a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Interactions.cs b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Interactions.cs index 2fece720f9..0f02f83cd7 100644 --- a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Interactions.cs +++ b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Interactions.cs @@ -66,7 +66,7 @@ public abstract partial class SharedGunSystem if (component.SelectedMode == fire) return; - DebugTools.Assert((component.AvailableModes & fire) != 0x0); + DebugTools.Assert((component.AvailableModes & fire) != 0x0); component.SelectedMode = fire; if (!Paused(uid)) @@ -110,32 +110,45 @@ public abstract partial class SharedGunSystem SelectFire(uid, component, args.Mode, args.Performer); } - private void OnGunSelected(EntityUid uid, GunComponent component, HandSelectedEvent args) + private void OnGunSelected(Entity ent, ref HandSelectedEvent args) { + var uid = ent.Owner; + if (Timing.ApplyingState) - return; - - if (component.FireRateModified <= 0) return; - var fireDelay = 1f / component.FireRateModified; - if (fireDelay.Equals(0f)) - return; - - if (!component.ResetOnHandSelected) + if (ent.Comp.FireRateModified <= 0) return; if (Paused(uid)) return; - // If someone swaps to this weapon then reset its cd. - var curTime = Timing.CurTime; - var minimum = curTime + TimeSpan.FromSeconds(fireDelay); + if (TryComp(uid, out var delayComp)) + { + var delay = delayComp.EquipDelayTime; + var curTime = Timing.CurTime; - if (minimum < component.NextFire) - return; + var minimum = curTime + TimeSpan.FromSeconds(delay); - component.NextFire = minimum; - Dirty(uid, component); + if (minimum < ent.Comp.NextFire) + return; + + ent.Comp.NextFire = minimum; + + DirtyField(uid, ent.Comp, nameof(GunComponent.NextFire)); + } + else + { + var curTime = Timing.CurTime; + + var minimum = curTime + TimeSpan.FromSeconds(0.3); + + if (minimum < ent.Comp.NextFire) + return; + + ent.Comp.NextFire = minimum; + + DirtyField(uid, ent.Comp, nameof(GunComponent.NextFire)); + } } } diff --git a/Resources/Prototypes/Entities/Objects/Misc/handcuffs.yml b/Resources/Prototypes/Entities/Objects/Misc/handcuffs.yml index 66ab826ac2..3c5fd8039d 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/handcuffs.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/handcuffs.yml @@ -19,7 +19,6 @@ - Handcuffs - type: MeleeWeapon wideAnimationRotation: 90 - resetOnHandSelected: false animation: WeaponArcDisarm damage: types: