Weapon block component during selection (#3110)

This commit is contained in:
Sidzaru 2025-09-27 00:24:03 +03:00 committed by GitHub
parent 431dac6e9a
commit 1b03779569
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 73 additions and 43 deletions

View file

@ -34,12 +34,6 @@ public sealed partial class MeleeWeaponComponent : Component
[AutoPausedField]
public TimeSpan NextAttack;
/// <summary>
/// Starts attack cooldown when equipped if true.
/// </summary>
[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

View file

@ -129,27 +129,44 @@ public abstract class SharedMeleeWeaponSystem : EntitySystem
}
}
private void OnMeleeSelected(EntityUid uid, MeleeWeaponComponent component, HandSelectedEvent args)
private void OnMeleeSelected(Entity<MeleeWeaponComponent> 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<EquipDelayComponent>(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)

View file

@ -0,0 +1,13 @@
using Robust.Shared.GameStates;
namespace Content.Shared.Weapons;
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
public sealed partial class EquipDelayComponent : Component
{
/// <summary>
/// Delay before the next attack after picking up a weapon, in seconds.
/// </summary>
[DataField("delay"), AutoNetworkedField]
public float EquipDelayTime = 0.3f;
}

View file

@ -209,12 +209,6 @@ public sealed partial class GunComponent : Component
[AutoNetworkedField, ViewVariables(VVAccess.ReadWrite)]
public float FireRateModified;
/// <summary>
/// Starts fire cooldown when equipped if true.
/// </summary>
[DataField]
public bool ResetOnHandSelected = true;
/// <summary>
/// The base value for how fast the projectile moves.
/// </summary>
@ -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.
/// </summary>
[DataField(customTypeSerializer:typeof(TimeOffsetSerializer))]
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer))]
[AutoNetworkedField]
[AutoPausedField]
public TimeSpan NextFire = TimeSpan.Zero;

View file

@ -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<GunComponent> 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<EquipDelayComponent>(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));
}
}
}

View file

@ -19,7 +19,6 @@
- Handcuffs
- type: MeleeWeapon
wideAnimationRotation: 90
resetOnHandSelected: false
animation: WeaponArcDisarm
damage:
types: