diff --git a/Content.Shared/ActionBlocker/ActionBlockerSystem.cs b/Content.Shared/ActionBlocker/ActionBlockerSystem.cs
index 457e3875d4..43508e5312 100644
--- a/Content.Shared/ActionBlocker/ActionBlockerSystem.cs
+++ b/Content.Shared/ActionBlocker/ActionBlockerSystem.cs
@@ -83,7 +83,7 @@ namespace Content.Shared.ActionBlocker
/// check other blockers like
///
///
- public bool CanInteract(EntityUid user, EntityUid? target)
+ public bool CanInteract(EntityUid user, EntityUid? target, bool showFailedPopup = false)
{
if (!CanConsciouslyPerformAction(user))
return false;
@@ -97,7 +97,7 @@ namespace Content.Shared.ActionBlocker
if (target == null || target == user)
return true;
- var targetEv = new GettingInteractedWithAttemptEvent(user, target);
+ var targetEv = new GettingInteractedWithAttemptEvent(user, target, showFailedPopup);
RaiseLocalEvent(target.Value, ref targetEv);
return !targetEv.Cancelled;
diff --git a/Content.Shared/Containers/ItemSlot/ItemSlotsComponent.cs b/Content.Shared/Containers/ItemSlot/ItemSlotsComponent.cs
index 7a9844b48d..c652a439a5 100644
--- a/Content.Shared/Containers/ItemSlot/ItemSlotsComponent.cs
+++ b/Content.Shared/Containers/ItemSlot/ItemSlotsComponent.cs
@@ -221,7 +221,7 @@ namespace Content.Shared.Containers.ItemSlots
///
[DataField]
[Access(typeof(ItemSlotsSystem), Other = AccessPermissions.ReadWriteExecute)]
- public bool Swap = true;
+ public bool Swap = false; // WWDP immersive interactions
public string? ID => ContainerSlot?.ID;
diff --git a/Content.Shared/Hands/EntitySystems/SharedHandsSystem.Interactions.cs b/Content.Shared/Hands/EntitySystems/SharedHandsSystem.Interactions.cs
index 3952d9870b..c995771bcd 100644
--- a/Content.Shared/Hands/EntitySystems/SharedHandsSystem.Interactions.cs
+++ b/Content.Shared/Hands/EntitySystems/SharedHandsSystem.Interactions.cs
@@ -85,7 +85,7 @@ public abstract partial class SharedHandsSystem : EntitySystem
RemComp(uid);
return false;
}
-
+
private readonly Angle _dropRotationIncrement = Angle.FromDegrees(5);
private bool PreciseDropMWheelUp(in PointerInputCmdHandler.PointerInputCmdArgs args)
{
@@ -163,7 +163,7 @@ public abstract partial class SharedHandsSystem : EntitySystem
if (!TryComp(session?.AttachedEntity, out HandsComponent? component))
return;
- if (!_actionBlocker.CanInteract(session.AttachedEntity.Value, null))
+ if (!_actionBlocker.CanInteract(session.AttachedEntity.Value, null, true))
return;
if (component.ActiveHand == null || component.Hands.Count < 2)
diff --git a/Content.Shared/Interaction/Events/InteractionAttemptEvent.cs b/Content.Shared/Interaction/Events/InteractionAttemptEvent.cs
index a04c053635..92be214635 100644
--- a/Content.Shared/Interaction/Events/InteractionAttemptEvent.cs
+++ b/Content.Shared/Interaction/Events/InteractionAttemptEvent.cs
@@ -26,9 +26,11 @@
/// generic interaction.
///
[ByRefEvent]
- public struct GettingInteractedWithAttemptEvent(EntityUid uid, EntityUid? target)
+ public struct GettingInteractedWithAttemptEvent(EntityUid uid, EntityUid? target, bool showFailedPopup = false)
{
public bool Cancelled;
+ public bool Handled;
+ public bool ShowFailedPopup = showFailedPopup;
public readonly EntityUid Uid = uid;
public readonly EntityUid? Target = target;
}
diff --git a/Content.Shared/Interaction/SharedInteractionSystem.cs b/Content.Shared/Interaction/SharedInteractionSystem.cs
index be2fbaf84d..3b254abd65 100644
--- a/Content.Shared/Interaction/SharedInteractionSystem.cs
+++ b/Content.Shared/Interaction/SharedInteractionSystem.cs
@@ -161,7 +161,7 @@ namespace Content.Shared.Interaction
private void OnBoundInterfaceInteractAttempt(BoundUserInterfaceMessageAttempt ev)
{
_uiQuery.TryComp(ev.Target, out var uiComp);
- if (!_actionBlockerSystem.CanInteract(ev.Actor, ev.Target))
+ if (!_actionBlockerSystem.CanInteract(ev.Actor, ev.Target, true)) // WWDP interaction popups
{
// We permit ghosts to open uis unless explicitly blocked
if (ev.Message is not OpenBoundInterfaceMessage || !HasComp(ev.Actor) || uiComp?.BlockSpectators == true)
@@ -381,7 +381,7 @@ namespace Content.Shared.Interaction
if (_relayQuery.TryComp(user, out var relay) && relay.RelayEntity is not null)
{
// TODO this needs to be handled better. This probably bypasses many complex can-interact checks in weird roundabout ways.
- if (_actionBlockerSystem.CanInteract(user, target))
+ if (_actionBlockerSystem.CanInteract(user, target, true)) // WWDP interaction popups
{
UserInteraction(relay.RelayEntity.Value,
coordinates,
@@ -414,7 +414,7 @@ namespace Content.Shared.Interaction
return;
}
- if (checkCanInteract && !_actionBlockerSystem.CanInteract(user, target))
+ if (checkCanInteract && !_actionBlockerSystem.CanInteract(user, target, true)) // WWDP interaction popups
return;
// Check if interacted entity is in the same container, the direct child, or direct parent of the user.
@@ -988,10 +988,7 @@ namespace Content.Shared.Interaction
if (IsDeleted(user) || IsDeleted(used) || IsDeleted(target))
return false;
- if (checkCanInteract && !_actionBlockerSystem.CanInteract(user, target))
- return false;
-
- if (checkCanInteract && !_actionBlockerSystem.CanInteract(user, target))
+ if (checkCanInteract && !_actionBlockerSystem.CanInteract(user, target, true)) // WWDP interaction popups
return false;
if (checkCanUse && !_actionBlockerSystem.CanUseHeldEntity(user, used))
@@ -1005,7 +1002,9 @@ namespace Content.Shared.Interaction
if (RangedInteractDoBefore(user, used, target, clickLocation, true))
return true;
- // all interactions should only happen when in range / unobstructed, so no range check is needed
+ if (!InRangeAndAccessible(user, target)) // WWDP no interacting with items inside containers
+ return false;
+
var interactUsingEvent = new InteractUsingEvent(user, used, target, clickLocation);
RaiseLocalEvent(target, interactUsingEvent, true);
DoContactInteraction(user, used, interactUsingEvent);
@@ -1107,7 +1106,7 @@ namespace Content.Shared.Interaction
if (checkUseDelay && delayComponent != null && _useDelay.IsDelayed((used, delayComponent)))
return false;
- if (checkCanInteract && !_actionBlockerSystem.CanInteract(user, used))
+ if (checkCanInteract && !_actionBlockerSystem.CanInteract(user, used, true)) // WWDP interaction popups
return false;
if (checkAccess && !InRangeUnobstructed(user, used))
@@ -1161,7 +1160,7 @@ namespace Content.Shared.Interaction
if (checkUseDelay && delayComponent != null && _useDelay.IsDelayed((used, delayComponent)))
return true; // if the item is on cooldown, we consider this handled.
- if (checkCanInteract && !_actionBlockerSystem.CanInteract(user, used))
+ if (checkCanInteract && !_actionBlockerSystem.CanInteract(user, used, true)) // WWDP interaction popups
return false;
if (checkCanUse && !_actionBlockerSystem.CanUseHeldEntity(user, used))
@@ -1212,7 +1211,7 @@ namespace Content.Shared.Interaction
if (ev.Handled)
return true;
// WD EDIT END
-
+
// Get list of alt-interact verbs
var verbs = _verbSystem.GetLocalVerbs(target, user, typeof(AlternativeVerb)).Where(verb => ((AlternativeVerb) verb).InActiveHandOnly == false); // WD EDIT
@@ -1301,7 +1300,7 @@ namespace Content.Shared.Interaction
if (_containerSystem.IsInSameOrParentContainer(user, target, out _, out var container))
return true;
- return container != null && CanAccessViaStorage(user, target, container);
+ return false; // WWDP no interacting with items inside containers
}
///
diff --git a/Content.Shared/Interaction/SmartEquipSystem.cs b/Content.Shared/Interaction/SmartEquipSystem.cs
index bba294db28..185f95f59d 100644
--- a/Content.Shared/Interaction/SmartEquipSystem.cs
+++ b/Content.Shared/Interaction/SmartEquipSystem.cs
@@ -127,6 +127,9 @@ public sealed class SmartEquipSystem : EntitySystem
// case 2 (storage item):
if (TryComp(slotItem, out var storage))
{
+ if (!_actionBlocker.CanInteract(uid, slotItem, true)) // WWDP Interactions
+ return;
+
switch (handItem)
{
case null when storage.Container.ContainedEntities.Count == 0:
@@ -159,6 +162,9 @@ public sealed class SmartEquipSystem : EntitySystem
// case 3 (itemslot item):
if (TryComp(slotItem, out var slots))
{
+ if (!_actionBlocker.CanInteract(uid, slotItem, true)) // WWDP Interactions
+ return;
+
if (handItem == null)
{
ItemSlot? toEjectFrom = null;
diff --git a/Content.Shared/Inventory/InventorySystem.Equip.cs b/Content.Shared/Inventory/InventorySystem.Equip.cs
index 2c930834e8..30135ecc14 100644
--- a/Content.Shared/Inventory/InventorySystem.Equip.cs
+++ b/Content.Shared/Inventory/InventorySystem.Equip.cs
@@ -10,6 +10,7 @@ using Content.Shared.Inventory.Events;
using Content.Shared.Item;
using Content.Shared.Movement.Systems;
using Content.Shared.Popups;
+using Content.Shared.Storage;
using Content.Shared.Strip;
using Content.Shared.Strip.Components;
using Content.Shared.Whitelist;
@@ -30,6 +31,7 @@ public abstract partial class InventorySystem
[Dependency] private readonly SharedContainerSystem _containerSystem = default!;
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
[Dependency] private readonly SharedHandsSystem _handsSystem = default!;
+ [Dependency] private readonly SharedUserInterfaceSystem _interface = default!; // WWDP
[Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly SharedTransformSystem _transform = default!;
[Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!;
@@ -44,6 +46,8 @@ public abstract partial class InventorySystem
SubscribeLocalEvent(OnEntInserted);
SubscribeLocalEvent(OnEntRemoved);
+ SubscribeLocalEvent(OnEquipped); // WWDP
+
SubscribeAllEvent(OnUseSlot);
}
@@ -124,6 +128,15 @@ public abstract partial class InventorySystem
TryEquip(actor, actor, held.Value, ev.Slot, predicted: true, inventory: inventory, force: true, checkDoafter:true);
}
+ // WWDP IF WE PUT IT ON AND ITS NOT ACCESSIBLE CLOSE THE UI
+ private void OnEquipped(Entity item, ref GotEquippedEvent args)
+ {
+ if (item.Comp.CanBeUsedWhileWorn)
+ return;
+
+ _interface.CloseUis(item.Owner);
+ }
+
public bool TryEquip(EntityUid uid, EntityUid itemUid, string slot, bool silent = false, bool force = false, bool predicted = false,
InventoryComponent? inventory = null, ClothingComponent? clothing = null, bool checkDoafter = false) =>
TryEquip(uid, uid, itemUid, slot, silent, force, predicted, inventory, clothing, checkDoafter);
@@ -173,7 +186,7 @@ public abstract partial class InventorySystem
{
BlockDuplicate = true,
BreakOnHandChange = true,
- BreakOnMove = true,
+ BreakOnMove = false, // WWDP no breaking on move
BreakOnDamage = false, // White Dream: Do not break on recieving damage
CancelDuplicate = true,
RequireCanInteract = true,
@@ -422,7 +435,7 @@ public abstract partial class InventorySystem
{
BlockDuplicate = true,
BreakOnHandChange = true,
- BreakOnMove = true,
+ BreakOnMove = false, // WWDP no breaking on move
BreakOnDamage = false, // White Dream: Do not break on recieving damage
CancelDuplicate = true,
RequireCanInteract = true,
diff --git a/Content.Shared/Item/ItemComponent.cs b/Content.Shared/Item/ItemComponent.cs
index 0f599ebdbe..c939c5b4f1 100644
--- a/Content.Shared/Item/ItemComponent.cs
+++ b/Content.Shared/Item/ItemComponent.cs
@@ -29,6 +29,12 @@ public sealed partial class ItemComponent : Component
[DataField, AutoNetworkedField]
public string? HeldPrefix;
+ ///
+ /// WWDP - Can this item be used while equipped in someone's inventory, including pockets
+ ///
+ [DataField, AutoNetworkedField]
+ public bool CanBeUsedWhileWorn;
+
///
/// Rsi of the sprite shown on the player when this item is in their hands. Used to generate a default entry for
///
diff --git a/Content.Shared/Item/SharedItemSystem.cs b/Content.Shared/Item/SharedItemSystem.cs
index a058cb8658..611dcfe546 100644
--- a/Content.Shared/Item/SharedItemSystem.cs
+++ b/Content.Shared/Item/SharedItemSystem.cs
@@ -2,7 +2,10 @@ using Content.Shared.Hands.EntitySystems;
using Content.Shared.Interaction;
using Content.Shared.Verbs;
using Content.Shared.Examine;
+using Content.Shared.Interaction.Events;
+using Content.Shared.Inventory;
using Content.Shared.Item.ItemToggle.Components;
+using Content.Shared.Popups;
using Content.Shared.Storage;
using JetBrains.Annotations;
using Robust.Shared.Containers;
@@ -16,6 +19,8 @@ public abstract class SharedItemSystem : EntitySystem
{
[Dependency] private readonly IPrototypeManager _prototype = default!;
[Dependency] private readonly SharedHandsSystem _handsSystem = default!;
+ [Dependency] private readonly InventorySystem _inventory = default!; // WWDP
+ [Dependency] private readonly SharedPopupSystem _popup = default!; // WWDP
[Dependency] protected readonly SharedContainerSystem Container = default!;
public override void Initialize()
@@ -24,6 +29,7 @@ public abstract class SharedItemSystem : EntitySystem
SubscribeLocalEvent>(AddPickupVerb);
SubscribeLocalEvent(OnHandInteract);
SubscribeLocalEvent(OnItemAutoState);
+ SubscribeLocalEvent(OnItemInteracted); // WWDP
SubscribeLocalEvent(OnExamine);
@@ -94,6 +100,28 @@ public abstract class SharedItemSystem : EntitySystem
args.Handled = _handsSystem.TryPickup(args.User, uid, animateUser: false);
}
+ ///
+ /// WWDP - Handle attempt to interact with this item
+ /// Block interactions if it is equipped unless CanBeUsedWhileWorn
+ ///
+ private void OnItemInteracted(EntityUid uid, ItemComponent component, ref GettingInteractedWithAttemptEvent args)
+ {
+ if (uid != args.Target || args.Handled)
+ return;
+
+ if (!_inventory.TryGetContainingSlot(uid, out _))
+ return;
+
+ if (component.CanBeUsedWhileWorn)
+ return;
+
+ if (args.ShowFailedPopup)
+ _popup.PopupClient(Loc.GetString("must-be-in-hand"), args.Uid);
+
+ args.Cancelled = true;
+ args.Handled = true;
+ }
+
private void AddPickupVerb(EntityUid uid, ItemComponent component, GetVerbsEvent args)
{
if (args.Hands == null ||
diff --git a/Content.Shared/Storage/EntitySystems/SharedStorageSystem.cs b/Content.Shared/Storage/EntitySystems/SharedStorageSystem.cs
index 3afb52b959..4944b0d7c7 100644
--- a/Content.Shared/Storage/EntitySystems/SharedStorageSystem.cs
+++ b/Content.Shared/Storage/EntitySystems/SharedStorageSystem.cs
@@ -15,6 +15,7 @@ using Content.Shared.Input;
using Content.Shared.Interaction;
using Content.Shared.Interaction.Components;
using Content.Shared.Inventory;
+using Content.Shared.Inventory.Events;
using Content.Shared.Item;
using Content.Shared.Lock;
using Content.Shared.Materials;
diff --git a/Resources/Locale/en-US/_white/popups/interactions.ftl b/Resources/Locale/en-US/_white/popups/interactions.ftl
new file mode 100644
index 0000000000..ee5e9628b6
--- /dev/null
+++ b/Resources/Locale/en-US/_white/popups/interactions.ftl
@@ -0,0 +1 @@
+must-be-in-hand = Must be in hand!
diff --git a/Resources/Locale/ru-RU/_white/popups/interactions.ftl b/Resources/Locale/ru-RU/_white/popups/interactions.ftl
new file mode 100644
index 0000000000..6752450d3a
--- /dev/null
+++ b/Resources/Locale/ru-RU/_white/popups/interactions.ftl
@@ -0,0 +1 @@
+must-be-in-hand = Должно быть в руке!
diff --git a/Resources/Prototypes/Entities/Clothing/Back/backpacks.yml b/Resources/Prototypes/Entities/Clothing/Back/backpacks.yml
index 1a5f89dd13..c6f346ef38 100644
--- a/Resources/Prototypes/Entities/Clothing/Back/backpacks.yml
+++ b/Resources/Prototypes/Entities/Clothing/Back/backpacks.yml
@@ -8,6 +8,7 @@
sprite: Clothing/Back/Backpacks/backpack.rsi
state: icon
- type: Item
+ canBeUsedWhileWorn: false # WWDP
size: Huge
- type: Clothing
equipSound: /Audio/_White/Equip/clothingrustle4.ogg # WWDP
@@ -34,6 +35,10 @@
- type: ExplosionResistance
damageCoefficient: 0.9
- type: AllowsSleepInside # DeltaV - enable sleeping inside bags
+ - type: HeldSpeedModifier # WWDP slow down with bags in hand
+ mirrorClothingModifier: false
+ sprintModifier: 0.85
+ walkModifier: 0.85
- type: entity
parent: ClothingBackpack
diff --git a/Resources/Prototypes/Entities/Clothing/Back/duffel.yml b/Resources/Prototypes/Entities/Clothing/Back/duffel.yml
index 969d9a6fde..4d28a46a04 100644
--- a/Resources/Prototypes/Entities/Clothing/Back/duffel.yml
+++ b/Resources/Prototypes/Entities/Clothing/Back/duffel.yml
@@ -13,7 +13,18 @@
- type: ClothingSpeedModifier
walkModifier: 1
sprintModifier: 0.9
- - type: HeldSpeedModifier
+ - type: HeldSpeedModifier # WWDP slow down with bags in hand
+ mirrorClothingModifier: false
+ sprintModifier: 0.8
+ walkModifier: 0.8
+ - type: Clothing
+ equipDelay: 1
+ unequipDelay: 1
+ equipSound: /Audio/_White/Equip/clothingrustle2.ogg # WWDP
+ - type: EmitSoundOnPickup # WWDP
+ sound: /Audio/_White/Equip/clothingrustle2.ogg
+ - type: Item
+ canBeUsedWhileWorn: false # WWDP
- type: entity
parent: ClothingBackpackDuffel
diff --git a/Resources/Prototypes/Entities/Clothing/Back/satchel.yml b/Resources/Prototypes/Entities/Clothing/Back/satchel.yml
index 33daadcbe9..465ee411a1 100644
--- a/Resources/Prototypes/Entities/Clothing/Back/satchel.yml
+++ b/Resources/Prototypes/Entities/Clothing/Back/satchel.yml
@@ -11,6 +11,8 @@
- 0,0,1,3
- 3,0,6,3
- 8,0,9,3
+ - type: Clothing # WWDP
+ #equipSound: /Audio/_White/Equip/clothingrustle4.ogg todo sounds from the gunnening
- type: entity
parent: ClothingBackpackSatchel
diff --git a/Resources/Prototypes/Entities/Clothing/base_clothing.yml b/Resources/Prototypes/Entities/Clothing/base_clothing.yml
index 70fd8bffd7..8e1b1ac8e8 100644
--- a/Resources/Prototypes/Entities/Clothing/base_clothing.yml
+++ b/Resources/Prototypes/Entities/Clothing/base_clothing.yml
@@ -5,6 +5,7 @@
components:
- type: Item
size: Normal
+ canBeUsedWhileWorn: true # WWDP
- type: Sprite
- type: Tag
tags:
@@ -12,6 +13,8 @@
- type: StaticPrice
price: 10
- type: Clothing
+ equipDelay: 0.5 # WWDP
+ unequipDelay: 0.5 # WWDP
- type: entity
abstract: true