@@ -4,6 +4,7 @@ using Content.Shared.Hands.Components;
|
||||
using Content.Shared.Movement.Systems;
|
||||
using Content.Shared.Projectiles;
|
||||
using Content.Shared.Weapons.Ranged.Events;
|
||||
using Content.Shared.Wieldable;
|
||||
|
||||
namespace Content.Shared.Hands.EntitySystems;
|
||||
|
||||
@@ -19,6 +20,8 @@ public abstract partial class SharedHandsSystem
|
||||
SubscribeLocalEvent<HandsComponent, ExtinguishEvent>(RefRelayEvent);
|
||||
SubscribeLocalEvent<HandsComponent, ProjectileReflectAttemptEvent>(RefRelayEvent);
|
||||
SubscribeLocalEvent<HandsComponent, HitScanReflectAttemptEvent>(RefRelayEvent);
|
||||
SubscribeLocalEvent<HandsComponent, WieldAttemptEvent>(RefRelayEvent);
|
||||
SubscribeLocalEvent<HandsComponent, UnwieldAttemptEvent>(RefRelayEvent);
|
||||
}
|
||||
|
||||
private void RelayEvent<T>(Entity<HandsComponent> entity, ref T args) where T : EntityEventArgs
|
||||
|
||||
@@ -24,6 +24,7 @@ using Content.Shared.Strip.Components;
|
||||
using Content.Shared.Temperature;
|
||||
using Content.Shared.Verbs;
|
||||
using Content.Shared.Weapons.Ranged.Events;
|
||||
using Content.Shared.Wieldable;
|
||||
using Content.Shared.Zombies;
|
||||
|
||||
namespace Content.Shared.Inventory;
|
||||
@@ -63,6 +64,8 @@ public partial class InventorySystem
|
||||
SubscribeLocalEvent<InventoryComponent, ProjectileReflectAttemptEvent>(RefRelayInventoryEvent);
|
||||
SubscribeLocalEvent<InventoryComponent, HitScanReflectAttemptEvent>(RefRelayInventoryEvent);
|
||||
SubscribeLocalEvent<InventoryComponent, GetContrabandDetailsEvent>(RefRelayInventoryEvent);
|
||||
SubscribeLocalEvent<InventoryComponent, WieldAttemptEvent>(RefRelayInventoryEvent);
|
||||
SubscribeLocalEvent<InventoryComponent, UnwieldAttemptEvent>(RefRelayInventoryEvent);
|
||||
|
||||
// Eye/vision events
|
||||
SubscribeLocalEvent<InventoryComponent, CanSeeAttemptEvent>(RelayInventoryEvent);
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
using Robust.Shared.GameStates;
|
||||
|
||||
namespace Content.Shared.Wieldable.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Blocks an entity from wielding items.
|
||||
/// When added to an item, it will block wielding when held in hand or equipped.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
|
||||
public sealed partial class WieldingBlockerComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// Block wielding when this item is held in a hand?
|
||||
/// </summary>
|
||||
[DataField, AutoNetworkedField]
|
||||
public bool BlockInHand = true;
|
||||
|
||||
/// <summary>
|
||||
/// Block wielding when this item is equipped?
|
||||
/// </summary>
|
||||
[DataField, AutoNetworkedField]
|
||||
public bool BlockEquipped = true;
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
using Content.Shared.Inventory;
|
||||
|
||||
namespace Content.Shared.Wieldable;
|
||||
|
||||
/// <summary>
|
||||
@@ -14,12 +16,18 @@ public readonly record struct ItemWieldedEvent(EntityUid User);
|
||||
public readonly record struct ItemUnwieldedEvent(EntityUid User, bool Force);
|
||||
|
||||
/// <summary>
|
||||
/// Raised directed on an item before a user tries to wield it.
|
||||
/// Raised directed on an user and all the items in their inventory and hands before they wield an item.
|
||||
/// If this event is cancelled wielding will not happen.
|
||||
/// </summary>
|
||||
[ByRefEvent]
|
||||
public record struct WieldAttemptEvent(EntityUid User, bool Cancelled = false)
|
||||
public record struct WieldAttemptEvent(EntityUid User, EntityUid Wielded, bool Cancelled = false) : IInventoryRelayEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Popup message for the user to tell them why they cannot wield if Cancelled
|
||||
/// </summary>
|
||||
public string? Message;
|
||||
|
||||
SlotFlags IInventoryRelayEvent.TargetSlots => SlotFlags.WITHOUT_POCKET;
|
||||
public void Cancel()
|
||||
{
|
||||
Cancelled = true;
|
||||
@@ -27,15 +35,21 @@ public record struct WieldAttemptEvent(EntityUid User, bool Cancelled = false)
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raised directed on an item before a user tries to stop wielding it willingly.
|
||||
/// Raised directed on an user and all the items in their inventory and hands before they unwield an item willingly.
|
||||
/// If this event is cancelled unwielding will not happen.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This event is not raised if the user is forced to unwield the item.
|
||||
/// </remarks>
|
||||
[ByRefEvent]
|
||||
public record struct UnwieldAttemptEvent(EntityUid User, bool Cancelled = false)
|
||||
public record struct UnwieldAttemptEvent(EntityUid User, EntityUid Wielded, bool Cancelled = false) : IInventoryRelayEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Popup message for the user to tell them why they cannot unwield if Cancelled
|
||||
/// </summary>
|
||||
public string? Message;
|
||||
|
||||
SlotFlags IInventoryRelayEvent.TargetSlots => SlotFlags.WITHOUT_POCKET;
|
||||
public void Cancel()
|
||||
{
|
||||
Cancelled = true;
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
using System.Linq;
|
||||
using Content.Shared.Camera;
|
||||
using Content.Shared.Examine;
|
||||
using Content.Shared.Hands;
|
||||
using Content.Shared.Hands.Components;
|
||||
using Content.Shared.Hands.EntitySystems;
|
||||
using Content.Shared.IdentityManagement;
|
||||
using Content.Shared.Interaction.Events;
|
||||
using Content.Shared.Inventory;
|
||||
using Content.Shared.Inventory.Events;
|
||||
using Content.Shared.Inventory.VirtualItem;
|
||||
using Content.Shared.Item;
|
||||
using Content.Shared.Movement.Components;
|
||||
@@ -22,7 +23,6 @@ using Content.Shared.Weapons.Ranged.Systems;
|
||||
using Content.Shared.Wieldable.Components;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
using Robust.Shared.Collections;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Shared.Wieldable;
|
||||
@@ -51,6 +51,12 @@ public abstract class SharedWieldableSystem : EntitySystem
|
||||
SubscribeLocalEvent<WieldableComponent, GetVerbsEvent<InteractionVerb>>(AddToggleWieldVerb);
|
||||
SubscribeLocalEvent<WieldableComponent, HandDeselectedEvent>(OnDeselectWieldable);
|
||||
|
||||
SubscribeLocalEvent<WieldingBlockerComponent, GotEquippedEvent>(OnBlockerEquipped);
|
||||
SubscribeLocalEvent<WieldingBlockerComponent, GotEquippedHandEvent>(OnBlockerEquippedHand);
|
||||
SubscribeLocalEvent<WieldingBlockerComponent, WieldAttemptEvent>(OnBlockerAttempt);
|
||||
SubscribeLocalEvent<WieldingBlockerComponent, InventoryRelayedEvent<WieldAttemptEvent>>(OnBlockerAttempt);
|
||||
SubscribeLocalEvent<WieldingBlockerComponent, HeldRelayedEvent<WieldAttemptEvent>>(OnBlockerAttempt);
|
||||
|
||||
SubscribeLocalEvent<MeleeRequiresWieldComponent, AttemptMeleeEvent>(OnMeleeAttempt);
|
||||
SubscribeLocalEvent<GunRequiresWieldComponent, ExaminedEvent>(OnExamineRequires);
|
||||
SubscribeLocalEvent<GunRequiresWieldComponent, ShotAttemptedEvent>(OnShootAttempt);
|
||||
@@ -186,14 +192,55 @@ public abstract class SharedWieldableSystem : EntitySystem
|
||||
return;
|
||||
|
||||
if (!component.Wielded)
|
||||
args.Handled = TryWield(uid, component, args.User);
|
||||
{
|
||||
TryWield(uid, component, args.User);
|
||||
args.Handled = true; // always mark as handled or we will cycle ammo when wielding is blocked
|
||||
}
|
||||
else if (component.UnwieldOnUse)
|
||||
args.Handled = TryUnwield(uid, component, args.User);
|
||||
{
|
||||
TryUnwield(uid, component, args.User);
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
if (HasComp<UseDelayComponent>(uid) && !component.UseDelayOnWield)
|
||||
args.ApplyDelay = false;
|
||||
}
|
||||
|
||||
private void OnBlockerEquipped(Entity<WieldingBlockerComponent> ent, ref GotEquippedEvent args)
|
||||
{
|
||||
if (ent.Comp.BlockEquipped)
|
||||
UnwieldAll(args.Equipee, force: true);
|
||||
}
|
||||
|
||||
private void OnBlockerEquippedHand(Entity<WieldingBlockerComponent> ent, ref GotEquippedHandEvent args)
|
||||
{
|
||||
if (ent.Comp.BlockInHand)
|
||||
UnwieldAll(args.User, force: true);
|
||||
}
|
||||
|
||||
private void OnBlockerAttempt(Entity<WieldingBlockerComponent> ent, ref InventoryRelayedEvent<WieldAttemptEvent> args)
|
||||
{
|
||||
if (ent.Comp.BlockEquipped)
|
||||
{
|
||||
args.Args.Message = Loc.GetString("wieldable-component-blocked-wield", ("blocker", ent.Owner), ("item", args.Args.Wielded));
|
||||
args.Args.Cancelled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnBlockerAttempt(Entity<WieldingBlockerComponent> ent, ref HeldRelayedEvent<WieldAttemptEvent> args)
|
||||
{
|
||||
if (ent.Comp.BlockInHand)
|
||||
{
|
||||
args.Args.Message = Loc.GetString("wieldable-component-blocked-wield", ("blocker", ent.Owner), ("item", args.Args.Wielded));
|
||||
args.Args.Cancelled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnBlockerAttempt(Entity<WieldingBlockerComponent> ent, ref WieldAttemptEvent args)
|
||||
{
|
||||
args.Cancelled = true;
|
||||
}
|
||||
|
||||
public bool CanWield(EntityUid uid, WieldableComponent component, EntityUid user, bool quiet = false)
|
||||
{
|
||||
// Do they have enough hands free?
|
||||
@@ -242,11 +289,15 @@ public abstract class SharedWieldableSystem : EntitySystem
|
||||
return false;
|
||||
}
|
||||
|
||||
var attemptEv = new WieldAttemptEvent(user);
|
||||
RaiseLocalEvent(used, ref attemptEv);
|
||||
var attemptEv = new WieldAttemptEvent(user, used);
|
||||
RaiseLocalEvent(user, ref attemptEv);
|
||||
|
||||
if (attemptEv.Cancelled)
|
||||
{
|
||||
if (attemptEv.Message != null)
|
||||
_popup.PopupClient(attemptEv.Message, user, user);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (TryComp<ItemComponent>(used, out var item))
|
||||
{
|
||||
@@ -298,11 +349,15 @@ public abstract class SharedWieldableSystem : EntitySystem
|
||||
|
||||
if (!force)
|
||||
{
|
||||
var attemptEv = new UnwieldAttemptEvent(user);
|
||||
RaiseLocalEvent(used, ref attemptEv);
|
||||
var attemptEv = new UnwieldAttemptEvent(user, used);
|
||||
RaiseLocalEvent(user, ref attemptEv);
|
||||
|
||||
if (attemptEv.Cancelled)
|
||||
{
|
||||
if (attemptEv.Message != null)
|
||||
_popup.PopupClient(attemptEv.Message, user, user);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
SetWielded((used, component), false);
|
||||
@@ -312,6 +367,19 @@ public abstract class SharedWieldableSystem : EntitySystem
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Makes an entity unwield all currently wielded items.
|
||||
/// </summary>
|
||||
/// <param name="force">If this is true we will bypass UnwieldAttemptEvent.</param>
|
||||
public void UnwieldAll(Entity<HandsComponent?> wielder, bool force = false)
|
||||
{
|
||||
foreach (var held in _hands.EnumerateHeld(wielder.Owner, wielder.Comp))
|
||||
{
|
||||
if (TryComp<WieldableComponent>(held, out var wieldable))
|
||||
TryUnwield(held, wieldable, wielder, force);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets wielded without doing any checks.
|
||||
/// </summary>
|
||||
|
||||
@@ -7,6 +7,7 @@ wieldable-component-successful-wield = You wield { THE($item) }.
|
||||
wieldable-component-failed-wield = You unwield { THE($item) }.
|
||||
wieldable-component-successful-wield-other = { CAPITALIZE(THE($user)) } wields { THE($item) }.
|
||||
wieldable-component-failed-wield-other = { CAPITALIZE(THE($user)) } unwields { THE($item) }.
|
||||
wieldable-component-blocked-wield = { CAPITALIZE(THE($blocker)) } blocks you from wielding { THE($item) }.
|
||||
|
||||
wieldable-component-no-hands = You don't have enough hands!
|
||||
wieldable-component-not-enough-free-hands = {$number ->
|
||||
|
||||
Reference in New Issue
Block a user