diff --git a/Content.Server/Actions/Events/DisarmAttemptEvent.cs b/Content.Server/Actions/Events/DisarmAttemptEvent.cs
deleted file mode 100644
index 162731d6b6..0000000000
--- a/Content.Server/Actions/Events/DisarmAttemptEvent.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-namespace Content.Server.Actions.Events
-{
- public sealed class DisarmAttemptEvent : CancellableEntityEventArgs
- {
- public readonly EntityUid TargetUid;
- public readonly EntityUid DisarmerUid;
- public readonly EntityUid? TargetItemInHandUid;
-
- public DisarmAttemptEvent(EntityUid targetUid, EntityUid disarmerUid, EntityUid? targetItemInHandUid = null)
- {
- TargetUid = targetUid;
- DisarmerUid = disarmerUid;
- TargetItemInHandUid = targetItemInHandUid;
- }
- }
-}
diff --git a/Content.Server/Weapons/Melee/MeleeWeaponSystem.cs b/Content.Server/Weapons/Melee/MeleeWeaponSystem.cs
index 0fcaaa6f4f..60fa69649e 100644
--- a/Content.Server/Weapons/Melee/MeleeWeaponSystem.cs
+++ b/Content.Server/Weapons/Melee/MeleeWeaponSystem.cs
@@ -1,5 +1,4 @@
using System.Linq;
-using Content.Server.Actions.Events;
using Content.Server.Body.Components;
using Content.Server.Body.Systems;
using Content.Server.Chemistry.Components;
@@ -8,6 +7,7 @@ using Content.Server.CombatMode.Disarm;
using Content.Server.Contests;
using Content.Server.Examine;
using Content.Server.Movement.Systems;
+using Content.Shared.Actions.Events;
using Content.Shared.Administration.Components;
using Content.Shared.CombatMode;
using Content.Shared.Damage;
@@ -25,7 +25,6 @@ using Content.Shared.Weapons.Melee.Events;
using Robust.Server.Player;
using Robust.Shared.Audio;
using Robust.Shared.Map;
-using Robust.Shared.Physics;
using Robust.Shared.Player;
using Robust.Shared.Players;
using Robust.Shared.Random;
diff --git a/Content.Server/Wieldable/Components/IncreaseDamageOnWieldComponent.cs b/Content.Server/Wieldable/Components/IncreaseDamageOnWieldComponent.cs
deleted file mode 100644
index 083bd514b8..0000000000
--- a/Content.Server/Wieldable/Components/IncreaseDamageOnWieldComponent.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using Content.Shared.Damage;
-
-namespace Content.Server.Wieldable.Components
-{
- [RegisterComponent, Access(typeof(WieldableSystem))]
- public sealed class IncreaseDamageOnWieldComponent : Component
- {
- [DataField("damage", required: true)]
- public DamageSpecifier BonusDamage = default!;
- }
-}
diff --git a/Content.Server/Wieldable/Components/WieldableComponent.cs b/Content.Server/Wieldable/Components/WieldableComponent.cs
deleted file mode 100644
index f54d87e239..0000000000
--- a/Content.Server/Wieldable/Components/WieldableComponent.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-using Robust.Shared.Audio;
-
-namespace Content.Server.Wieldable.Components
-{
- ///
- /// Used for objects that can be wielded in two or more hands,
- ///
- [RegisterComponent, Access(typeof(WieldableSystem))]
- public sealed class WieldableComponent : Component
- {
- [DataField("wieldSound")]
- public SoundSpecifier? WieldSound = new SoundPathSpecifier("/Audio/Effects/thudswoosh.ogg");
-
- [DataField("unwieldSound")]
- public SoundSpecifier? UnwieldSound;
-
- ///
- /// Number of free hands required (excluding the item itself) required
- /// to wield it
- ///
- [DataField("freeHandsRequired")]
- public int FreeHandsRequired = 1;
-
- public bool Wielded = false;
-
- [DataField("wieldedInhandPrefix")]
- public string WieldedInhandPrefix = "wielded";
-
- public string? OldInhandPrefix = null;
-
- [DataField("wieldTime")]
- public float WieldTime = 1.5f;
- }
-}
diff --git a/Content.Server/Wieldable/WieldableSystem.cs b/Content.Server/Wieldable/WieldableSystem.cs
deleted file mode 100644
index f158655e47..0000000000
--- a/Content.Server/Wieldable/WieldableSystem.cs
+++ /dev/null
@@ -1,263 +0,0 @@
-using Content.Server.Actions.Events;
-using Content.Server.Hands.Systems;
-using Content.Server.Wieldable.Components;
-using Content.Shared.DoAfter;
-using Content.Shared.Hands;
-using Content.Shared.Hands.Components;
-using Content.Shared.Hands.EntitySystems;
-using Content.Shared.Interaction.Events;
-using Content.Shared.Item;
-using Content.Shared.Popups;
-using Content.Shared.Verbs;
-using Content.Shared.Weapons.Melee.Events;
-using Content.Shared.Wieldable;
-using Robust.Shared.Player;
-
-namespace Content.Server.Wieldable
-{
- public sealed class WieldableSystem : EntitySystem
- {
- [Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
- [Dependency] private readonly HandVirtualItemSystem _virtualItemSystem = default!;
- [Dependency] private readonly SharedHandsSystem _handsSystem = default!;
- [Dependency] private readonly SharedItemSystem _itemSystem = default!;
- [Dependency] private readonly SharedPopupSystem _popupSystem = default!;
- [Dependency] private readonly SharedAudioSystem _audioSystem = default!;
-
- public override void Initialize()
- {
- base.Initialize();
-
- SubscribeLocalEvent(OnUseInHand);
- SubscribeLocalEvent(OnDoAfter);
- SubscribeLocalEvent(OnItemUnwielded);
- SubscribeLocalEvent(OnItemLeaveHand);
- SubscribeLocalEvent(OnVirtualItemDeleted);
- SubscribeLocalEvent>(AddToggleWieldVerb);
- SubscribeLocalEvent(OnDisarmAttemptEvent);
-
- SubscribeLocalEvent(OnMeleeHit);
- }
-
- private void OnDisarmAttemptEvent(EntityUid uid, WieldableComponent component, DisarmAttemptEvent args)
- {
- if (component.Wielded)
- args.Cancel();
- }
-
- private void AddToggleWieldVerb(EntityUid uid, WieldableComponent component, GetVerbsEvent args)
- {
- if (args.Hands == null || !args.CanAccess || !args.CanInteract)
- return;
-
- if (!_handsSystem.IsHolding(args.User, uid, out _, args.Hands))
- return;
-
- // TODO VERB TOOLTIPS Make CanWield or some other function return string, set as verb tooltip and disable
- // verb. Or just don't add it to the list if the action is not executable.
-
- // TODO VERBS ICON + localization
- InteractionVerb verb = new()
- {
- Text = component.Wielded ? Loc.GetString("wieldable-verb-text-unwield") : Loc.GetString("wieldable-verb-text-wield"),
- Act = component.Wielded
- ? () => AttemptUnwield(component.Owner, component, args.User)
- : () => AttemptWield(component.Owner, component, args.User)
- };
-
- args.Verbs.Add(verb);
- }
-
- private void OnUseInHand(EntityUid uid, WieldableComponent component, UseInHandEvent args)
- {
- if (args.Handled)
- return;
- if(!component.Wielded)
- AttemptWield(uid, component, args.User);
- else
- AttemptUnwield(uid, component, args.User);
- }
-
- public bool CanWield(EntityUid uid, WieldableComponent component, EntityUid user, bool quiet=false)
- {
- // Do they have enough hands free?
- if (!EntityManager.TryGetComponent(user, out var hands))
- {
- if(!quiet)
- _popupSystem.PopupEntity(Loc.GetString("wieldable-component-no-hands"), user, user);
- return false;
- }
-
- // Is it.. actually in one of their hands?
- if (!_handsSystem.IsHolding(user, uid, out _, hands))
- {
- if (!quiet)
- _popupSystem.PopupEntity(Loc.GetString("wieldable-component-not-in-hands", ("item", uid)), user, user);
- return false;
- }
-
- if (hands.CountFreeHands() < component.FreeHandsRequired)
- {
- if (!quiet)
- {
- var message = Loc.GetString("wieldable-component-not-enough-free-hands",
- ("number", component.FreeHandsRequired), ("item", uid));
- _popupSystem.PopupEntity(message, user, user);
- }
- return false;
- }
-
- // Seems legit.
- return true;
- }
-
- ///
- /// Attempts to wield an item, creating a DoAfter..
- ///
- public void AttemptWield(EntityUid used, WieldableComponent component, EntityUid user)
- {
- if (!CanWield(used, component, user))
- return;
- var ev = new BeforeWieldEvent();
- RaiseLocalEvent(used, ev);
-
- if (ev.Cancelled)
- return;
-
- var doargs = new DoAfterArgs(user, component.WieldTime, new WieldableDoAfterEvent(), used, used: used)
- {
- BreakOnUserMove = false,
- BreakOnDamage = true
- };
-
- _doAfter.TryStartDoAfter(doargs);
- }
-
- ///
- /// Attempts to unwield an item, with no DoAfter.
- ///
- public void AttemptUnwield(EntityUid used, WieldableComponent component, EntityUid user)
- {
- var ev = new BeforeUnwieldEvent();
- RaiseLocalEvent(used, ev);
-
- if (ev.Cancelled)
- return;
-
- var targEv = new ItemUnwieldedEvent(user);
-
- RaiseLocalEvent(used, targEv);
- }
-
- private void OnDoAfter(EntityUid uid, WieldableComponent component, DoAfterEvent args)
- {
- if (args.Handled || args.Cancelled || !CanWield(uid, component, args.Args.User) || component.Wielded)
- return;
-
- if (TryComp(uid, out var item))
- {
- component.OldInhandPrefix = item.HeldPrefix;
- _itemSystem.SetHeldPrefix(uid, component.WieldedInhandPrefix, item);
- }
-
- component.Wielded = true;
-
- if (component.WieldSound != null)
- _audioSystem.PlayPvs(component.WieldSound, uid);
-
- for (int i = 0; i < component.FreeHandsRequired; i++)
- {
- _virtualItemSystem.TrySpawnVirtualItemInHand(uid, args.Args.User);
- }
-
- _popupSystem.PopupEntity(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);
-
- args.Handled = true;
- }
-
- private void OnItemUnwielded(EntityUid uid, WieldableComponent component, ItemUnwieldedEvent args)
- {
- if (args.User == null)
- return;
- if (!component.Wielded)
- return;
-
- if (TryComp(uid, out var item))
- {
- _itemSystem.SetHeldPrefix(uid, component.OldInhandPrefix, item);
- }
-
- component.Wielded = false;
-
- if (!args.Force) // don't play sound/popup if this was a forced unwield
- {
- if (component.UnwieldSound != null)
- _audioSystem.PlayPvs(component.UnwieldSound, uid);
-
- _popupSystem.PopupEntity(Loc.GetString("wieldable-component-failed-wield",
- ("item", uid)), args.User.Value, args.User.Value);
- _popupSystem.PopupEntity(Loc.GetString("wieldable-component-failed-wield-other",
- ("user", args.User.Value), ("item", uid)), args.User.Value, Filter.PvsExcept(args.User.Value), true);
- }
-
- _virtualItemSystem.DeleteInHandsMatching(args.User.Value, uid);
- }
-
- private void OnItemLeaveHand(EntityUid uid, WieldableComponent component, GotUnequippedHandEvent args)
- {
- if (!component.Wielded || component.Owner != args.Unequipped)
- return;
- RaiseLocalEvent(uid, new ItemUnwieldedEvent(args.User, force: true), true);
- }
-
- private void OnVirtualItemDeleted(EntityUid uid, WieldableComponent component, VirtualItemDeletedEvent args)
- {
- if (args.BlockingEntity == uid && component.Wielded)
- AttemptUnwield(args.BlockingEntity, component, args.User);
- }
-
- private void OnMeleeHit(EntityUid uid, IncreaseDamageOnWieldComponent component, MeleeHitEvent args)
- {
- if (EntityManager.TryGetComponent(uid, out var wield))
- {
- if (!wield.Wielded)
- return;
- }
- if (args.Handled)
- return;
-
- args.BonusDamage += component.BonusDamage;
- }
- }
-
- #region Events
-
- public sealed class BeforeWieldEvent : CancellableEntityEventArgs
- {
- }
-
- public sealed class BeforeUnwieldEvent : CancellableEntityEventArgs
- {
- }
-
- ///
- /// Raised on the item that has been unwielded.
- ///
- public sealed class ItemUnwieldedEvent : EntityEventArgs
- {
- public EntityUid? User;
- ///
- /// Whether the item is being forced to be unwielded, or if the player chose to unwield it themselves.
- ///
- public bool Force;
-
- public ItemUnwieldedEvent(EntityUid? user = null, bool force=false)
- {
- User = user;
- Force = force;
- }
- }
-
- #endregion
-}
diff --git a/Content.Shared/Actions/Events/DisarmAttemptEvent.cs b/Content.Shared/Actions/Events/DisarmAttemptEvent.cs
new file mode 100644
index 0000000000..8252205846
--- /dev/null
+++ b/Content.Shared/Actions/Events/DisarmAttemptEvent.cs
@@ -0,0 +1,15 @@
+namespace Content.Shared.Actions.Events;
+
+public sealed class DisarmAttemptEvent : CancellableEntityEventArgs
+{
+ public readonly EntityUid TargetUid;
+ public readonly EntityUid DisarmerUid;
+ public readonly EntityUid? TargetItemInHandUid;
+
+ public DisarmAttemptEvent(EntityUid targetUid, EntityUid disarmerUid, EntityUid? targetItemInHandUid = null)
+ {
+ TargetUid = targetUid;
+ DisarmerUid = disarmerUid;
+ TargetItemInHandUid = targetItemInHandUid;
+ }
+}
\ No newline at end of file
diff --git a/Content.Shared/Wieldable/BeforeUnwieldEvent.cs b/Content.Shared/Wieldable/BeforeUnwieldEvent.cs
new file mode 100644
index 0000000000..4328ba50c4
--- /dev/null
+++ b/Content.Shared/Wieldable/BeforeUnwieldEvent.cs
@@ -0,0 +1,5 @@
+namespace Content.Shared.Wieldable;
+
+public sealed class BeforeUnwieldEvent : CancellableEntityEventArgs
+{
+}
\ No newline at end of file
diff --git a/Content.Shared/Wieldable/BeforeWieldEvent.cs b/Content.Shared/Wieldable/BeforeWieldEvent.cs
new file mode 100644
index 0000000000..744a009f9c
--- /dev/null
+++ b/Content.Shared/Wieldable/BeforeWieldEvent.cs
@@ -0,0 +1,5 @@
+namespace Content.Shared.Wieldable;
+
+public sealed class BeforeWieldEvent : CancellableEntityEventArgs
+{
+}
\ No newline at end of file
diff --git a/Content.Shared/Wieldable/Components/IncreaseDamageOnWieldComponent.cs b/Content.Shared/Wieldable/Components/IncreaseDamageOnWieldComponent.cs
new file mode 100644
index 0000000000..4d453d5197
--- /dev/null
+++ b/Content.Shared/Wieldable/Components/IncreaseDamageOnWieldComponent.cs
@@ -0,0 +1,10 @@
+using Content.Shared.Damage;
+
+namespace Content.Shared.Wieldable.Components;
+
+[RegisterComponent, Access(typeof(WieldableSystem))]
+public sealed class IncreaseDamageOnWieldComponent : Component
+{
+ [DataField("damage", required: true)]
+ public DamageSpecifier BonusDamage = default!;
+}
\ No newline at end of file
diff --git a/Content.Shared/Wieldable/Components/WieldableComponent.cs b/Content.Shared/Wieldable/Components/WieldableComponent.cs
new file mode 100644
index 0000000000..541a5a6fde
--- /dev/null
+++ b/Content.Shared/Wieldable/Components/WieldableComponent.cs
@@ -0,0 +1,35 @@
+using Robust.Shared.Audio;
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Wieldable.Components;
+
+///
+/// Used for objects that can be wielded in two or more hands,
+///
+[RegisterComponent, NetworkedComponent, Access(typeof(WieldableSystem)), AutoGenerateComponentState]
+public sealed partial class WieldableComponent : Component
+{
+ [DataField("wieldSound")]
+ public SoundSpecifier? WieldSound = new SoundPathSpecifier("/Audio/Effects/thudswoosh.ogg");
+
+ [DataField("unwieldSound")]
+ public SoundSpecifier? UnwieldSound;
+
+ ///
+ /// Number of free hands required (excluding the item itself) required
+ /// to wield it
+ ///
+ [DataField("freeHandsRequired")]
+ public int FreeHandsRequired = 1;
+
+ [AutoNetworkedField, DataField("wielded")]
+ public bool Wielded = false;
+
+ [DataField("wieldedInhandPrefix")]
+ public string WieldedInhandPrefix = "wielded";
+
+ public string? OldInhandPrefix = null;
+
+ [DataField("wieldTime")]
+ public float WieldTime = 1.5f;
+}
diff --git a/Content.Shared/Wieldable/ItemUnwieldedEvent.cs b/Content.Shared/Wieldable/ItemUnwieldedEvent.cs
new file mode 100644
index 0000000000..f980d45802
--- /dev/null
+++ b/Content.Shared/Wieldable/ItemUnwieldedEvent.cs
@@ -0,0 +1,23 @@
+namespace Content.Shared.Wieldable;
+
+#region Events
+
+///
+/// Raised on the item that has been unwielded.
+///
+public sealed class ItemUnwieldedEvent : EntityEventArgs
+{
+ public EntityUid? User;
+ ///
+ /// Whether the item is being forced to be unwielded, or if the player chose to unwield it themselves.
+ ///
+ public bool Force;
+
+ public ItemUnwieldedEvent(EntityUid? user = null, bool force=false)
+ {
+ User = user;
+ Force = force;
+ }
+}
+
+#endregion
diff --git a/Content.Shared/Wieldable/WieldableSystem.cs b/Content.Shared/Wieldable/WieldableSystem.cs
new file mode 100644
index 0000000000..929856367b
--- /dev/null
+++ b/Content.Shared/Wieldable/WieldableSystem.cs
@@ -0,0 +1,232 @@
+using Content.Shared.Actions.Events;
+using Content.Shared.DoAfter;
+using Content.Shared.Hands;
+using Content.Shared.Hands.Components;
+using Content.Shared.Hands.EntitySystems;
+using Content.Shared.Interaction.Events;
+using Content.Shared.Item;
+using Content.Shared.Popups;
+using Content.Shared.Verbs;
+using Content.Shared.Weapons.Melee.Events;
+using Content.Shared.Wieldable.Components;
+using Robust.Shared.Player;
+
+namespace Content.Shared.Wieldable;
+
+public sealed class WieldableSystem : EntitySystem
+{
+ [Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
+ [Dependency] private readonly SharedHandVirtualItemSystem _virtualItemSystem = default!;
+ [Dependency] private readonly SharedHandsSystem _handsSystem = default!;
+ [Dependency] private readonly SharedItemSystem _itemSystem = default!;
+ [Dependency] private readonly SharedPopupSystem _popupSystem = default!;
+ [Dependency] private readonly SharedAudioSystem _audioSystem = default!;
+
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ SubscribeLocalEvent(OnUseInHand);
+ SubscribeLocalEvent(OnDoAfter);
+ SubscribeLocalEvent(OnItemUnwielded);
+ SubscribeLocalEvent(OnItemLeaveHand);
+ SubscribeLocalEvent(OnVirtualItemDeleted);
+ SubscribeLocalEvent>(AddToggleWieldVerb);
+ SubscribeLocalEvent(OnDisarmAttemptEvent);
+
+ SubscribeLocalEvent(OnMeleeHit);
+ }
+
+ private void OnDisarmAttemptEvent(EntityUid uid, WieldableComponent component, DisarmAttemptEvent args)
+ {
+ if (component.Wielded)
+ args.Cancel();
+ }
+
+ private void AddToggleWieldVerb(EntityUid uid, WieldableComponent component, GetVerbsEvent args)
+ {
+ if (args.Hands == null || !args.CanAccess || !args.CanInteract)
+ return;
+
+ if (!_handsSystem.IsHolding(args.User, uid, out _, args.Hands))
+ return;
+
+ // TODO VERB TOOLTIPS Make CanWield or some other function return string, set as verb tooltip and disable
+ // verb. Or just don't add it to the list if the action is not executable.
+
+ // TODO VERBS ICON
+ InteractionVerb verb = new()
+ {
+ Text = component.Wielded ? Loc.GetString("wieldable-verb-text-unwield") : Loc.GetString("wieldable-verb-text-wield"),
+ Act = component.Wielded
+ ? () => AttemptUnwield(uid, component, args.User)
+ : () => AttemptWield(uid, component, args.User)
+ };
+
+ args.Verbs.Add(verb);
+ }
+
+ private void OnUseInHand(EntityUid uid, WieldableComponent component, UseInHandEvent args)
+ {
+ if (args.Handled)
+ return;
+ if(!component.Wielded)
+ AttemptWield(uid, component, args.User);
+ else
+ AttemptUnwield(uid, component, args.User);
+ }
+
+ public bool CanWield(EntityUid uid, WieldableComponent component, EntityUid user, bool quiet=false)
+ {
+ // Do they have enough hands free?
+ if (!EntityManager.TryGetComponent(user, out var hands))
+ {
+ if(!quiet)
+ _popupSystem.PopupClient(Loc.GetString("wieldable-component-no-hands"), user, user);
+ return false;
+ }
+
+ // Is it.. actually in one of their hands?
+ if (!_handsSystem.IsHolding(user, uid, out _, hands))
+ {
+ if (!quiet)
+ _popupSystem.PopupClient(Loc.GetString("wieldable-component-not-in-hands", ("item", uid)), user, user);
+ return false;
+ }
+
+ if (hands.CountFreeHands() < component.FreeHandsRequired)
+ {
+ if (!quiet)
+ {
+ var message = Loc.GetString("wieldable-component-not-enough-free-hands",
+ ("number", component.FreeHandsRequired), ("item", uid));
+ _popupSystem.PopupClient(message, user, user);
+ }
+ return false;
+ }
+
+ // Seems legit.
+ return true;
+ }
+
+ ///
+ /// Attempts to wield an item, creating a DoAfter..
+ ///
+ public void AttemptWield(EntityUid used, WieldableComponent component, EntityUid user)
+ {
+ if (!CanWield(used, component, user))
+ return;
+ var ev = new BeforeWieldEvent();
+ RaiseLocalEvent(used, ev);
+
+ if (ev.Cancelled)
+ return;
+
+ var doargs = new DoAfterArgs(user, component.WieldTime, new WieldableDoAfterEvent(), used, used: used)
+ {
+ BreakOnUserMove = false,
+ BreakOnDamage = true
+ };
+
+ _doAfter.TryStartDoAfter(doargs);
+ }
+
+ ///
+ /// Attempts to unwield an item, with no DoAfter.
+ ///
+ public void AttemptUnwield(EntityUid used, WieldableComponent component, EntityUid user)
+ {
+ var ev = new BeforeUnwieldEvent();
+ RaiseLocalEvent(used, ev);
+
+ if (ev.Cancelled)
+ return;
+
+ var targEv = new ItemUnwieldedEvent(user);
+
+ RaiseLocalEvent(used, targEv);
+ }
+
+ private void OnDoAfter(EntityUid uid, WieldableComponent component, DoAfterEvent args)
+ {
+ if (args.Handled || args.Cancelled || !CanWield(uid, component, args.Args.User) || component.Wielded)
+ return;
+
+ if (TryComp(uid, out var item))
+ {
+ component.OldInhandPrefix = item.HeldPrefix;
+ _itemSystem.SetHeldPrefix(uid, component.WieldedInhandPrefix, item);
+ }
+
+ component.Wielded = true;
+
+ if (component.WieldSound != null)
+ _audioSystem.PlayPredicted(component.WieldSound, uid, args.User);
+
+ for (var i = 0; i < component.FreeHandsRequired; i++)
+ {
+ _virtualItemSystem.TrySpawnVirtualItemInHand(uid, args.Args.User);
+ }
+
+ _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);
+
+ Dirty(component);
+ args.Handled = true;
+ }
+
+ private void OnItemUnwielded(EntityUid uid, WieldableComponent component, ItemUnwieldedEvent args)
+ {
+ if (args.User == null)
+ return;
+ if (!component.Wielded)
+ return;
+
+ if (TryComp(uid, out var item))
+ {
+ _itemSystem.SetHeldPrefix(uid, component.OldInhandPrefix, item);
+ }
+
+ component.Wielded = false;
+
+ if (!args.Force) // don't play sound/popup if this was a forced unwield
+ {
+ if (component.UnwieldSound != null)
+ _audioSystem.PlayPredicted(component.UnwieldSound, uid, args.User);
+
+ _popupSystem.PopupClient(Loc.GetString("wieldable-component-failed-wield",
+ ("item", uid)), args.User.Value, args.User.Value);
+ _popupSystem.PopupEntity(Loc.GetString("wieldable-component-failed-wield-other",
+ ("user", args.User.Value), ("item", uid)), args.User.Value, Filter.PvsExcept(args.User.Value), true);
+ }
+
+ Dirty(component);
+ _virtualItemSystem.DeleteInHandsMatching(args.User.Value, uid);
+ }
+
+ private void OnItemLeaveHand(EntityUid uid, WieldableComponent component, GotUnequippedHandEvent args)
+ {
+ if (!component.Wielded || uid != args.Unequipped)
+ return;
+ RaiseLocalEvent(uid, new ItemUnwieldedEvent(args.User, force: true), true);
+ }
+
+ private void OnVirtualItemDeleted(EntityUid uid, WieldableComponent component, VirtualItemDeletedEvent args)
+ {
+ if (args.BlockingEntity == uid && component.Wielded)
+ AttemptUnwield(args.BlockingEntity, component, args.User);
+ }
+
+ private void OnMeleeHit(EntityUid uid, IncreaseDamageOnWieldComponent component, MeleeHitEvent args)
+ {
+ if (EntityManager.TryGetComponent(uid, out var wield))
+ {
+ if (!wield.Wielded)
+ return;
+ }
+ if (args.Handled)
+ return;
+
+ args.BonusDamage += component.BonusDamage;
+ }
+}