mirror of
https://github.com/WWhiteDreamProject/wwdpublic.git
synced 2026-04-17 05:27:38 +03:00
[Tweak] Immersive Interactions (#288)
* no interacting with items inside containers * no inventory interactions * the backpackening * item slots no swap * bags slow in hands * update sounds * oops * fix * fix linter --------- Co-authored-by: vanx <discord@vanxxxx>
This commit is contained in:
@@ -83,7 +83,7 @@ namespace Content.Shared.ActionBlocker
|
||||
/// check other blockers like <see cref="CanPickup(EntityUid)"/>
|
||||
/// </remarks>
|
||||
/// <returns></returns>
|
||||
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;
|
||||
|
||||
@@ -221,7 +221,7 @@ namespace Content.Shared.Containers.ItemSlots
|
||||
/// </remarks>
|
||||
[DataField]
|
||||
[Access(typeof(ItemSlotsSystem), Other = AccessPermissions.ReadWriteExecute)]
|
||||
public bool Swap = true;
|
||||
public bool Swap = false; // WWDP immersive interactions
|
||||
|
||||
public string? ID => ContainerSlot?.ID;
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ public abstract partial class SharedHandsSystem : EntitySystem
|
||||
RemComp<HoldingDropComponent>(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)
|
||||
|
||||
@@ -26,9 +26,11 @@
|
||||
/// generic interaction.
|
||||
/// </summary>
|
||||
[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;
|
||||
}
|
||||
|
||||
@@ -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<GhostComponent>(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
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -127,6 +127,9 @@ public sealed class SmartEquipSystem : EntitySystem
|
||||
// case 2 (storage item):
|
||||
if (TryComp<StorageComponent>(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<ItemSlotsComponent>(slotItem, out var slots))
|
||||
{
|
||||
if (!_actionBlocker.CanInteract(uid, slotItem, true)) // WWDP Interactions
|
||||
return;
|
||||
|
||||
if (handItem == null)
|
||||
{
|
||||
ItemSlot? toEjectFrom = null;
|
||||
|
||||
@@ -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<InventoryComponent, EntInsertedIntoContainerMessage>(OnEntInserted);
|
||||
SubscribeLocalEvent<InventoryComponent, EntRemovedFromContainerMessage>(OnEntRemoved);
|
||||
|
||||
SubscribeLocalEvent<ItemComponent, GotEquippedEvent>(OnEquipped); // WWDP
|
||||
|
||||
SubscribeAllEvent<UseSlotNetworkMessage>(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<ItemComponent> 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,
|
||||
|
||||
@@ -29,6 +29,12 @@ public sealed partial class ItemComponent : Component
|
||||
[DataField, AutoNetworkedField]
|
||||
public string? HeldPrefix;
|
||||
|
||||
/// <summary>
|
||||
/// WWDP - Can this item be used while equipped in someone's inventory, including pockets
|
||||
/// </summary>
|
||||
[DataField, AutoNetworkedField]
|
||||
public bool CanBeUsedWhileWorn;
|
||||
|
||||
/// <summary>
|
||||
/// Rsi of the sprite shown on the player when this item is in their hands. Used to generate a default entry for <see cref="InhandVisuals"/>
|
||||
/// </summary>
|
||||
|
||||
@@ -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<ItemComponent, GetVerbsEvent<InteractionVerb>>(AddPickupVerb);
|
||||
SubscribeLocalEvent<ItemComponent, InteractHandEvent>(OnHandInteract);
|
||||
SubscribeLocalEvent<ItemComponent, AfterAutoHandleStateEvent>(OnItemAutoState);
|
||||
SubscribeLocalEvent<ItemComponent, GettingInteractedWithAttemptEvent>(OnItemInteracted); // WWDP
|
||||
|
||||
SubscribeLocalEvent<ItemComponent, ExaminedEvent>(OnExamine);
|
||||
|
||||
@@ -94,6 +100,28 @@ public abstract class SharedItemSystem : EntitySystem
|
||||
args.Handled = _handsSystem.TryPickup(args.User, uid, animateUser: false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// WWDP - Handle attempt to interact with this item
|
||||
/// Block interactions if it is equipped unless CanBeUsedWhileWorn
|
||||
/// </summary>
|
||||
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<InteractionVerb> args)
|
||||
{
|
||||
if (args.Hands == null ||
|
||||
|
||||
@@ -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;
|
||||
|
||||
1
Resources/Locale/en-US/_white/popups/interactions.ftl
Normal file
1
Resources/Locale/en-US/_white/popups/interactions.ftl
Normal file
@@ -0,0 +1 @@
|
||||
must-be-in-hand = Must be in hand!
|
||||
1
Resources/Locale/ru-RU/_white/popups/interactions.ftl
Normal file
1
Resources/Locale/ru-RU/_white/popups/interactions.ftl
Normal file
@@ -0,0 +1 @@
|
||||
must-be-in-hand = Должно быть в руке!
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user