diff --git a/Content.Shared/Weapons/Melee/Components/MeleeRequiresWieldComponent.cs b/Content.Shared/Weapons/Melee/Components/MeleeRequiresWieldComponent.cs
index 6cf12d58f2..cc05574224 100644
--- a/Content.Shared/Weapons/Melee/Components/MeleeRequiresWieldComponent.cs
+++ b/Content.Shared/Weapons/Melee/Components/MeleeRequiresWieldComponent.cs
@@ -1,3 +1,4 @@
+using Content.Shared.Wieldable;
using Robust.Shared.GameStates;
namespace Content.Shared.Weapons.Melee.Components;
@@ -5,7 +6,7 @@ namespace Content.Shared.Weapons.Melee.Components;
///
/// Indicates that this meleeweapon requires wielding to be useable.
///
-[RegisterComponent, NetworkedComponent]
+[RegisterComponent, NetworkedComponent, Access(typeof(WieldableSystem))]
public sealed class MeleeRequiresWieldComponent : Component
{
diff --git a/Content.Shared/Weapons/Ranged/Components/GunRequiresWieldComponent.cs b/Content.Shared/Weapons/Ranged/Components/GunRequiresWieldComponent.cs
index b0aca3af14..e8b93c60fd 100644
--- a/Content.Shared/Weapons/Ranged/Components/GunRequiresWieldComponent.cs
+++ b/Content.Shared/Weapons/Ranged/Components/GunRequiresWieldComponent.cs
@@ -1,3 +1,4 @@
+using Content.Shared.Wieldable;
using Robust.Shared.GameStates;
namespace Content.Shared.Weapons.Ranged.Components;
@@ -5,7 +6,7 @@ namespace Content.Shared.Weapons.Ranged.Components;
///
/// Indicates that this gun requires wielding to be useable.
///
-[RegisterComponent, NetworkedComponent]
+[RegisterComponent, NetworkedComponent, Access(typeof(WieldableSystem))]
public sealed class GunRequiresWieldComponent : Component
{
diff --git a/Content.Shared/Weapons/Ranged/Components/GunWieldBonusComponent.cs b/Content.Shared/Weapons/Ranged/Components/GunWieldBonusComponent.cs
new file mode 100644
index 0000000000..58c5fec2d8
--- /dev/null
+++ b/Content.Shared/Weapons/Ranged/Components/GunWieldBonusComponent.cs
@@ -0,0 +1,20 @@
+using Content.Shared.Wieldable;
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Weapons.Ranged.Components;
+
+///
+/// Applies an accuracy bonus upon wielding.
+///
+[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, Access(typeof(WieldableSystem))]
+public sealed partial class GunWieldBonusComponent : Component
+{
+ [ViewVariables(VVAccess.ReadWrite), DataField("minAngle"), AutoNetworkedField]
+ public Angle MinAngle = Angle.FromDegrees(-43);
+
+ ///
+ /// Angle bonus applied upon being wielded.
+ ///
+ [ViewVariables(VVAccess.ReadWrite), DataField("maxAngle"), AutoNetworkedField]
+ public Angle MaxAngle = Angle.FromDegrees(-43);
+}
diff --git a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Ballistic.cs b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Ballistic.cs
index abafb4c95f..fd60b4fbf1 100644
--- a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Ballistic.cs
+++ b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Ballistic.cs
@@ -29,6 +29,9 @@ public abstract partial class SharedGunSystem
private void OnBallisticUse(EntityUid uid, BallisticAmmoProviderComponent component, UseInHandEvent args)
{
+ if (args.Handled)
+ return;
+
ManualCycle(uid, component, Transform(uid).MapPosition, args.User);
args.Handled = true;
}
diff --git a/Content.Shared/Wieldable/Components/WieldableComponent.cs b/Content.Shared/Wieldable/Components/WieldableComponent.cs
index 541a5a6fde..5a8c533c29 100644
--- a/Content.Shared/Wieldable/Components/WieldableComponent.cs
+++ b/Content.Shared/Wieldable/Components/WieldableComponent.cs
@@ -26,7 +26,7 @@ public sealed partial class WieldableComponent : Component
public bool Wielded = false;
[DataField("wieldedInhandPrefix")]
- public string WieldedInhandPrefix = "wielded";
+ public string? WieldedInhandPrefix = "wielded";
public string? OldInhandPrefix = null;
diff --git a/Content.Shared/Wieldable/ItemWieldedEvent.cs b/Content.Shared/Wieldable/ItemWieldedEvent.cs
new file mode 100644
index 0000000000..15e204728a
--- /dev/null
+++ b/Content.Shared/Wieldable/ItemWieldedEvent.cs
@@ -0,0 +1,7 @@
+namespace Content.Shared.Wieldable;
+
+///
+/// Raised directed on an entity when it is wielded.
+///
+[ByRefEvent]
+public readonly record struct ItemWieldedEvent;
diff --git a/Content.Shared/Wieldable/WieldableSystem.cs b/Content.Shared/Wieldable/WieldableSystem.cs
index df73ff636c..0e2b52b9e2 100644
--- a/Content.Shared/Wieldable/WieldableSystem.cs
+++ b/Content.Shared/Wieldable/WieldableSystem.cs
@@ -39,6 +39,8 @@ public sealed class WieldableSystem : EntitySystem
SubscribeLocalEvent(OnMeleeAttempt);
SubscribeLocalEvent(OnShootAttempt);
+ SubscribeLocalEvent(OnGunWielded);
+ SubscribeLocalEvent(OnGunUnwielded);
SubscribeLocalEvent(OnGetMeleeDamage);
}
@@ -63,6 +65,26 @@ public sealed class WieldableSystem : EntitySystem
}
}
+ private void OnGunUnwielded(EntityUid uid, GunWieldBonusComponent component, ItemUnwieldedEvent args)
+ {
+ if (!TryComp(uid, out var gun))
+ return;
+
+ gun.MinAngle -= component.MinAngle;
+ gun.MaxAngle -= component.MaxAngle;
+ Dirty(gun);
+ }
+
+ private void OnGunWielded(EntityUid uid, GunWieldBonusComponent component, ref ItemWieldedEvent args)
+ {
+ if (!TryComp(uid, out var gun))
+ return;
+
+ gun.MinAngle += component.MinAngle;
+ gun.MaxAngle += component.MaxAngle;
+ Dirty(gun);
+ }
+
private void OnDisarmAttemptEvent(EntityUid uid, WieldableComponent component, DisarmAttemptEvent args)
{
if (component.Wielded)
@@ -197,6 +219,9 @@ public sealed class WieldableSystem : EntitySystem
_popupSystem.PopupClient(Loc.GetString("wieldable-component-successful-wield", ("item", uid)), args.Args.User, args.Args.User);
_popupSystem.PopupEntity(Loc.GetString("wieldable-component-successful-wield-other", ("user", args.Args.User),("item", uid)), args.Args.User, Filter.PvsExcept(args.Args.User), true);
+ var ev = new ItemWieldedEvent();
+ RaiseLocalEvent(uid, ref ev);
+
Dirty(component);
args.Handled = true;
}
diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Basic/base_pka.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Basic/base_pka.yml
index 34dac2a80e..d5fd65554b 100644
--- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Basic/base_pka.yml
+++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Basic/base_pka.yml
@@ -8,9 +8,17 @@
- type: Item
sprite: Objects/Weapons/Guns/Basic/kinetic_accelerator.rsi
size: 30
+ - type: GunWieldBonus
+ minAngle: -43
+ maxAngle: -43
+ - type: Wieldable
+ wieldedInhandPrefix: null
- type: Gun
fireRate: 0.75
selectedMode: SemiAuto
+ angleDecay: 45
+ minAngle: 44
+ maxAngle: 45
availableModes:
- SemiAuto
soundGunshot:
@@ -24,7 +32,7 @@
True: { visible: False }
False: { visible: True }
- type: RechargeBasicEntityAmmo
- rechargeCooldown: 1
+ rechargeCooldown: 0.75
rechargeSound:
path: /Audio/Weapons/Guns/MagIn/kinetic_reload.ogg
- type: BasicEntityAmmoProvider