Add ore bag area pickups (#19358)
This commit is contained in:
@@ -9,11 +9,11 @@ namespace Content.Client.Animations
|
||||
{
|
||||
public static class ReusableAnimations
|
||||
{
|
||||
public static void AnimateEntityPickup(EntityUid entity, EntityCoordinates initialPosition, Vector2 finalPosition, Angle initialAngle, IEntityManager? entMan = null)
|
||||
public static void AnimateEntityPickup(EntityUid entity, EntityCoordinates initialCoords, Vector2 finalPosition, Angle initialAngle, IEntityManager? entMan = null)
|
||||
{
|
||||
IoCManager.Resolve(ref entMan);
|
||||
|
||||
if (entMan.Deleted(entity) || !initialPosition.IsValid(entMan))
|
||||
if (entMan.Deleted(entity) || !initialCoords.IsValid(entMan))
|
||||
return;
|
||||
|
||||
var metadata = entMan.GetComponent<MetaDataComponent>(entity);
|
||||
@@ -21,7 +21,7 @@ namespace Content.Client.Animations
|
||||
if (entMan.IsPaused(entity, metadata))
|
||||
return;
|
||||
|
||||
var animatableClone = entMan.SpawnEntity("clientsideclone", initialPosition);
|
||||
var animatableClone = entMan.SpawnEntity("clientsideclone", initialCoords);
|
||||
string val = entMan.GetComponent<MetaDataComponent>(entity).EntityName;
|
||||
entMan.System<MetaDataSystem>().SetEntityName(animatableClone, val);
|
||||
|
||||
@@ -35,7 +35,8 @@ namespace Content.Client.Animations
|
||||
sprite.Visible = true;
|
||||
|
||||
var animations = entMan.GetComponent<AnimationPlayerComponent>(animatableClone);
|
||||
animations.AnimationCompleted += (_) => {
|
||||
animations.AnimationCompleted += (_) =>
|
||||
{
|
||||
entMan.DeleteEntity(animatableClone);
|
||||
};
|
||||
|
||||
@@ -55,7 +56,7 @@ namespace Content.Client.Animations
|
||||
InterpolationMode = AnimationInterpolationMode.Linear,
|
||||
KeyFrames =
|
||||
{
|
||||
new AnimationTrackProperty.KeyFrame(initialPosition.Position, 0),
|
||||
new AnimationTrackProperty.KeyFrame(initialCoords.Position, 0),
|
||||
new AnimationTrackProperty.KeyFrame(finalPosition, 0.125f)
|
||||
}
|
||||
},
|
||||
|
||||
@@ -52,8 +52,6 @@ namespace Content.Client.Hands.Systems
|
||||
SubscribeLocalEvent<HandsComponent, ComponentHandleState>(HandleComponentState);
|
||||
SubscribeLocalEvent<HandsComponent, VisualsChangedEvent>(OnVisualsChanged);
|
||||
|
||||
SubscribeNetworkEvent<PickupAnimationEvent>(HandlePickupAnimation);
|
||||
|
||||
OnHandSetActive += OnHandActivated;
|
||||
}
|
||||
|
||||
@@ -121,30 +119,6 @@ namespace Content.Client.Hands.Systems
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region PickupAnimation
|
||||
private void HandlePickupAnimation(PickupAnimationEvent msg)
|
||||
{
|
||||
PickupAnimation(GetEntity(msg.ItemUid), GetCoordinates(msg.InitialPosition), msg.FinalPosition, msg.InitialAngle);
|
||||
}
|
||||
|
||||
public override void PickupAnimation(EntityUid item, EntityCoordinates initialPosition, Vector2 finalPosition, Angle initialAngle,
|
||||
EntityUid? exclude)
|
||||
{
|
||||
PickupAnimation(item, initialPosition, finalPosition, initialAngle);
|
||||
}
|
||||
|
||||
public void PickupAnimation(EntityUid item, EntityCoordinates initialPosition, Vector2 finalPosition, Angle initialAngle)
|
||||
{
|
||||
if (!_gameTiming.IsFirstTimePredicted)
|
||||
return;
|
||||
|
||||
if (finalPosition.EqualsApprox(initialPosition.Position, tolerance: 0.1f))
|
||||
return;
|
||||
|
||||
ReusableAnimations.AnimateEntityPickup(item, initialPosition, finalPosition, initialAngle);
|
||||
}
|
||||
#endregion
|
||||
|
||||
public void ReloadHandButtons()
|
||||
{
|
||||
if (!TryGetPlayerHands(out var hands))
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
using Content.Client.Animations;
|
||||
using Content.Shared.Hands;
|
||||
using Content.Shared.Storage;
|
||||
using Content.Shared.Storage.EntitySystems;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Client.Storage.Systems;
|
||||
@@ -16,6 +18,7 @@ public sealed class StorageSystem : SharedStorageSystem
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeNetworkEvent<PickupAnimationEvent>(HandlePickupAnimation);
|
||||
SubscribeNetworkEvent<AnimateInsertingEntitiesEvent>(HandleAnimatingInsertingEntities);
|
||||
}
|
||||
|
||||
@@ -25,6 +28,38 @@ public sealed class StorageSystem : SharedStorageSystem
|
||||
StorageUpdated?.Invoke(uid, component);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void PlayPickupAnimation(EntityUid uid, EntityCoordinates initialCoordinates, EntityCoordinates finalCoordinates,
|
||||
Angle initialRotation, EntityUid? user = null)
|
||||
{
|
||||
if (!_timing.IsFirstTimePredicted)
|
||||
return;
|
||||
|
||||
PickupAnimation(uid, initialCoordinates, finalCoordinates, initialRotation);
|
||||
}
|
||||
|
||||
private void HandlePickupAnimation(PickupAnimationEvent msg)
|
||||
{
|
||||
PickupAnimation(GetEntity(msg.ItemUid), GetCoordinates(msg.InitialPosition), GetCoordinates(msg.FinalPosition), msg.InitialAngle);
|
||||
}
|
||||
|
||||
public void PickupAnimation(EntityUid item, EntityCoordinates initialCoords, EntityCoordinates finalCoords, Angle initialAngle)
|
||||
{
|
||||
if (!_timing.IsFirstTimePredicted)
|
||||
return;
|
||||
|
||||
if (finalCoords.InRange(EntityManager, _transform, initialCoords, 0.1f) ||
|
||||
!Exists(initialCoords.EntityId) || !Exists(finalCoords.EntityId))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var finalMapPos = finalCoords.ToMapPos(EntityManager, _transform);
|
||||
var finalPos = _transform.GetInvWorldMatrix(initialCoords.EntityId).Transform(finalMapPos);
|
||||
|
||||
ReusableAnimations.AnimateEntityPickup(item, initialCoords, finalPos, initialAngle);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Animate the newly stored entities in <paramref name="msg"/> flying towards this storage's position
|
||||
/// </summary>
|
||||
|
||||
@@ -172,7 +172,7 @@ public abstract partial class InteractionTest
|
||||
{
|
||||
var playerEnt = SEntMan.GetEntity(Player);
|
||||
|
||||
Assert.That(HandSys.TryPickup(playerEnt, item, Hands.ActiveHand, false, false, false, Hands));
|
||||
Assert.That(HandSys.TryPickup(playerEnt, item, Hands.ActiveHand, false, false, Hands));
|
||||
|
||||
// turn on welders
|
||||
if (enableWelder && SEntMan.TryGetComponent(item, out welder) && !welder.Lit)
|
||||
@@ -213,7 +213,7 @@ public abstract partial class InteractionTest
|
||||
|
||||
await Server.WaitPost(() =>
|
||||
{
|
||||
Assert.That(HandSys.TryPickup(SEntMan.GetEntity(Player), uid.Value, Hands.ActiveHand, false, false, false, Hands, item));
|
||||
Assert.That(HandSys.TryPickup(SEntMan.GetEntity(Player), uid.Value, Hands.ActiveHand, false, false, Hands, item));
|
||||
});
|
||||
|
||||
await RunTicks(1);
|
||||
|
||||
@@ -201,7 +201,7 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
for (var i = 0; i < message.Number; i++)
|
||||
{
|
||||
var item = Spawn(PillPrototypeId, Transform(container).Coordinates);
|
||||
_storageSystem.Insert(container, item, user, storage);
|
||||
_storageSystem.Insert(container, item, out _, user: user, storage);
|
||||
_labelSystem.Label(item, message.Label);
|
||||
|
||||
var itemSolution = _solutionContainerSystem.EnsureSolution(item, SharedChemMaster.PillSolutionName);
|
||||
|
||||
@@ -96,7 +96,7 @@ public sealed class PartExchangerSystem : EntitySystem
|
||||
//put the unused parts back into rped. (this also does the "swapping")
|
||||
foreach (var (unused, _) in machineParts)
|
||||
{
|
||||
_storage.Insert(storageUid, unused, playSound: false);
|
||||
_storage.Insert(storageUid, unused, out _, playSound: false);
|
||||
}
|
||||
_construction.RefreshParts(uid, machine);
|
||||
}
|
||||
@@ -146,7 +146,7 @@ public sealed class PartExchangerSystem : EntitySystem
|
||||
//put the unused parts back into rped. (this also does the "swapping")
|
||||
foreach (var (unused, _) in machineParts)
|
||||
{
|
||||
_storage.Insert(storageEnt, unused, playSound: false);
|
||||
_storage.Insert(storageEnt, unused, out _, playSound: false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -43,8 +43,6 @@ namespace Content.Server.Hands.Systems
|
||||
[Dependency] private readonly PullingSystem _pullingSystem = default!;
|
||||
[Dependency] private readonly ThrowingSystem _throwingSystem = default!;
|
||||
[Dependency] private readonly StorageSystem _storageSystem = default!;
|
||||
[Dependency] private readonly ISharedPlayerManager _player = default!;
|
||||
[Dependency] private readonly IConfigurationManager _configuration = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -94,20 +92,6 @@ namespace Content.Server.Hands.Systems
|
||||
args.Handled = true; // no shove/stun.
|
||||
}
|
||||
|
||||
public override void PickupAnimation(EntityUid item, EntityCoordinates initialPosition, Vector2 finalPosition, Angle initialAngle,
|
||||
EntityUid? exclude)
|
||||
{
|
||||
if (finalPosition.EqualsApprox(initialPosition.Position, tolerance: 0.1f))
|
||||
return;
|
||||
|
||||
var filter = Filter.Pvs(item, entityManager: EntityManager, playerManager: _player, cfgManager: _configuration);
|
||||
|
||||
if (exclude != null)
|
||||
filter = filter.RemoveWhereAttachedEntity(entity => entity == exclude);
|
||||
|
||||
RaiseNetworkEvent(new PickupAnimationEvent(GetNetEntity(item), GetNetCoordinates(initialPosition), finalPosition, initialAngle), filter);
|
||||
}
|
||||
|
||||
protected override void HandleEntityRemoved(EntityUid uid, HandsComponent hands, EntRemovedFromContainerMessage args)
|
||||
{
|
||||
base.HandleEntityRemoved(uid, hands, args);
|
||||
|
||||
@@ -31,7 +31,7 @@ public sealed partial class StorageSystem
|
||||
if (entityStorageComp != null && EntityStorage.Insert(ent, uid))
|
||||
continue;
|
||||
|
||||
if (storageComp != null && Insert(uid, ent, storageComp: storageComp, playSound: false))
|
||||
if (storageComp != null && Insert(uid, ent, out _, storageComp: storageComp, playSound: false))
|
||||
continue;
|
||||
|
||||
Log.Error($"Tried to StorageFill {item} inside {ToPrettyString(uid)} but can't.");
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Content.Server.Administration.Managers;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.Ghost;
|
||||
using Content.Shared.Hands;
|
||||
using Content.Shared.Lock;
|
||||
using Content.Shared.Storage;
|
||||
using Content.Shared.Storage.Components;
|
||||
@@ -9,6 +10,7 @@ using Content.Shared.Timing;
|
||||
using Content.Shared.Verbs;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Players;
|
||||
using Robust.Shared.Utility;
|
||||
@@ -120,6 +122,14 @@ public sealed partial class StorageSystem : SharedStorageSystem
|
||||
_uiSystem.OpenUi(bui, player.PlayerSession);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void PlayPickupAnimation(EntityUid uid, EntityCoordinates initialCoordinates, EntityCoordinates finalCoordinates,
|
||||
Angle initialRotation, EntityUid? user = null)
|
||||
{
|
||||
var filter = Filter.Pvs(uid).RemoveWhereAttachedEntity(e => e == user);
|
||||
RaiseNetworkEvent(new PickupAnimationEvent(GetNetEntity(uid), GetNetCoordinates(initialCoordinates), GetNetCoordinates(finalCoordinates), initialRotation), filter);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If the user has nested-UIs open (e.g., PDA UI open when pda is in a backpack), close them.
|
||||
/// </summary>
|
||||
|
||||
@@ -58,7 +58,7 @@ public abstract partial class SharedHandsSystem : EntitySystem
|
||||
if (hand == null)
|
||||
return false;
|
||||
|
||||
return TryPickup(uid, entity, hand, checkActionBlocker, animateUser, animate, handsComp, item);
|
||||
return TryPickup(uid, entity, hand, checkActionBlocker, animate, handsComp, item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -83,7 +83,7 @@ public abstract partial class SharedHandsSystem : EntitySystem
|
||||
if (!TryGetEmptyHand(uid, out var hand, handsComp))
|
||||
return false;
|
||||
|
||||
return TryPickup(uid, entity, hand, checkActionBlocker, animateUser, animate, handsComp, item);
|
||||
return TryPickup(uid, entity, hand, checkActionBlocker, animate, handsComp, item);
|
||||
}
|
||||
|
||||
public bool TryPickup(
|
||||
@@ -91,7 +91,6 @@ public abstract partial class SharedHandsSystem : EntitySystem
|
||||
EntityUid entity,
|
||||
Hand hand,
|
||||
bool checkActionBlocker = true,
|
||||
bool animateUser = false,
|
||||
bool animate = true,
|
||||
HandsComponent? handsComp = null,
|
||||
ItemComponent? item = null)
|
||||
@@ -117,7 +116,7 @@ public abstract partial class SharedHandsSystem : EntitySystem
|
||||
&& MetaData(entity).VisibilityMask == MetaData(uid).VisibilityMask) // Don't animate aghost pickups.
|
||||
{
|
||||
var initialPosition = EntityCoordinates.FromMap(coordinateEntity, itemPos, EntityManager);
|
||||
PickupAnimation(entity, initialPosition, xform.LocalPosition, itemXform.LocalRotation, animateUser ? null : uid);
|
||||
_storage.PlayPickupAnimation(entity, initialPosition, xform.Coordinates, itemXform.LocalRotation, uid);
|
||||
}
|
||||
}
|
||||
DoPickup(uid, hand, entity, handsComp);
|
||||
@@ -199,7 +198,7 @@ public abstract partial class SharedHandsSystem : EntitySystem
|
||||
if (uid == null
|
||||
|| !Resolve(uid.Value, ref handsComp, false)
|
||||
|| !TryGetEmptyHand(uid.Value, out var hand, handsComp)
|
||||
|| !TryPickup(uid.Value, entity, hand, checkActionBlocker, animateUser, animate, handsComp, item))
|
||||
|| !TryPickup(uid.Value, entity, hand, checkActionBlocker, animate, handsComp, item))
|
||||
{
|
||||
// TODO make this check upwards for any container, and parent to that.
|
||||
// Currently this just checks the direct parent, so items can still teleport through containers.
|
||||
@@ -227,12 +226,9 @@ public abstract partial class SharedHandsSystem : EntitySystem
|
||||
|
||||
_adminLogger.Add(LogType.Pickup, LogImpact.Low, $"{ToPrettyString(uid):user} picked up {ToPrettyString(entity):entity}");
|
||||
|
||||
Dirty(hands);
|
||||
Dirty(uid, hands);
|
||||
|
||||
if (hand == hands.ActiveHand)
|
||||
RaiseLocalEvent(entity, new HandSelectedEvent(uid), false);
|
||||
}
|
||||
|
||||
public abstract void PickupAnimation(EntityUid item, EntityCoordinates initialPosition, Vector2 finalPosition, Angle initialAngle,
|
||||
EntityUid? exclude);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ using Content.Shared.Administration.Logs;
|
||||
using Content.Shared.Hands.Components;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Item;
|
||||
using Content.Shared.Storage.EntitySystems;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.Input.Binding;
|
||||
|
||||
@@ -17,6 +18,8 @@ public abstract partial class SharedHandsSystem : EntitySystem
|
||||
[Dependency] private readonly SharedContainerSystem _containerSystem = default!;
|
||||
[Dependency] private readonly SharedInteractionSystem _interactionSystem = default!;
|
||||
[Dependency] private readonly SharedItemSystem _items = default!;
|
||||
[Dependency] private readonly SharedStorageSystem _storage = default!;
|
||||
[Dependency] protected readonly SharedTransformSystem TransformSystem = default!;
|
||||
|
||||
protected event Action<HandsComponent?>? OnHandSetActive;
|
||||
|
||||
|
||||
@@ -114,16 +114,24 @@ namespace Content.Shared.Hands
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Plays a clientside pickup animation by copying the specified entity.
|
||||
/// </summary>
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class PickupAnimationEvent : EntityEventArgs
|
||||
{
|
||||
public NetEntity ItemUid { get; }
|
||||
public NetCoordinates InitialPosition { get; }
|
||||
public Vector2 FinalPosition { get; }
|
||||
public Angle InitialAngle { get; }
|
||||
/// <summary>
|
||||
/// Entity to be copied for the clientside animation.
|
||||
/// </summary>
|
||||
public readonly NetEntity ItemUid;
|
||||
public readonly NetCoordinates InitialPosition;
|
||||
public readonly NetCoordinates FinalPosition;
|
||||
public readonly Angle InitialAngle;
|
||||
|
||||
public PickupAnimationEvent(NetEntity itemUid, NetCoordinates initialPosition,
|
||||
Vector2 finalPosition, Angle initialAngle)
|
||||
public PickupAnimationEvent(NetEntity itemUid,
|
||||
NetCoordinates initialPosition,
|
||||
NetCoordinates finalPosition,
|
||||
Angle initialAngle)
|
||||
{
|
||||
ItemUid = itemUid;
|
||||
FinalPosition = finalPosition;
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
using System.Numerics;
|
||||
using Content.Shared.Examine;
|
||||
using Content.Shared.Hands;
|
||||
using Content.Shared.Hands.Components;
|
||||
using Content.Shared.Hands.EntitySystems;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Shared.Storage.EntitySystems;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Physics.Systems;
|
||||
@@ -25,6 +27,7 @@ namespace Content.Shared.Stacks
|
||||
[Dependency] private readonly EntityLookupSystem _entityLookup = default!;
|
||||
[Dependency] private readonly SharedPhysicsSystem _physics = default!;
|
||||
[Dependency] protected readonly SharedPopupSystem Popup = default!;
|
||||
[Dependency] private readonly SharedStorageSystem _storage = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -56,6 +59,8 @@ namespace Content.Shared.Stacks
|
||||
if (!TryComp(args.Used, out StackComponent? recipientStack))
|
||||
return;
|
||||
|
||||
var localRotation = Transform(args.Used).LocalRotation;
|
||||
|
||||
if (!TryMergeStacks(uid, args.Used, out var transfered, stack, recipientStack))
|
||||
return;
|
||||
|
||||
@@ -67,10 +72,11 @@ namespace Content.Shared.Stacks
|
||||
return;
|
||||
|
||||
var popupPos = args.ClickLocation;
|
||||
var userCoords = Transform(args.User).Coordinates;
|
||||
|
||||
if (!popupPos.IsValid(EntityManager))
|
||||
{
|
||||
popupPos = Transform(args.User).Coordinates;
|
||||
popupPos = userCoords;
|
||||
}
|
||||
|
||||
switch (transfered)
|
||||
@@ -90,16 +96,18 @@ namespace Content.Shared.Stacks
|
||||
Popup.PopupCoordinates(Loc.GetString("comp-stack-already-full"), popupPos, Filter.Local(), false);
|
||||
break;
|
||||
}
|
||||
|
||||
_storage.PlayPickupAnimation(args.Used, popupPos, userCoords, localRotation, args.User);
|
||||
}
|
||||
|
||||
private bool TryMergeStacks(
|
||||
EntityUid donor,
|
||||
EntityUid recipient,
|
||||
out int transfered,
|
||||
out int transferred,
|
||||
StackComponent? donorStack = null,
|
||||
StackComponent? recipientStack = null)
|
||||
{
|
||||
transfered = 0;
|
||||
transferred = 0;
|
||||
if (donor == recipient)
|
||||
return false;
|
||||
|
||||
@@ -109,10 +117,10 @@ namespace Content.Shared.Stacks
|
||||
if (string.IsNullOrEmpty(recipientStack.StackTypeId) || !recipientStack.StackTypeId.Equals(donorStack.StackTypeId))
|
||||
return false;
|
||||
|
||||
transfered = Math.Min(donorStack.Count, GetAvailableSpace(recipientStack));
|
||||
SetCount(donor, donorStack.Count - transfered, donorStack);
|
||||
SetCount(recipient, recipientStack.Count + transfered, recipientStack);
|
||||
return true;
|
||||
transferred = Math.Min(donorStack.Count, GetAvailableSpace(recipientStack));
|
||||
SetCount(donor, donorStack.Count - transferred, donorStack);
|
||||
SetCount(recipient, recipientStack.Count + transferred, recipientStack);
|
||||
return transferred > 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
36
Content.Shared/Storage/Components/MagnetPickupComponent.cs
Normal file
36
Content.Shared/Storage/Components/MagnetPickupComponent.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using Content.Shared.Inventory;
|
||||
using Content.Shared.Tag;
|
||||
using Content.Shared.Whitelist;
|
||||
|
||||
namespace Content.Server.Storage.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Applies an ongoing pickup area around the attached entity.
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public sealed partial class MagnetPickupComponent : Component
|
||||
{
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField("nextScan")]
|
||||
public TimeSpan NextScan = TimeSpan.Zero;
|
||||
|
||||
/// <summary>
|
||||
/// What container slot the magnet needs to be in to work.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField("slotFlags")]
|
||||
public SlotFlags SlotFlags = SlotFlags.BELT;
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField("range")]
|
||||
public float Range = 1f;
|
||||
|
||||
[ValidatePrototypeId<TagPrototype>]
|
||||
private const string DefaultTag = "Ore";
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField("whitelist")]
|
||||
public EntityWhitelist? Whitelist = new()
|
||||
{
|
||||
Tags = new List<string>()
|
||||
{
|
||||
DefaultTag,
|
||||
}
|
||||
};
|
||||
}
|
||||
105
Content.Shared/Storage/EntitySystems/MagnetPickupSystem.cs
Normal file
105
Content.Shared/Storage/EntitySystems/MagnetPickupSystem.cs
Normal file
@@ -0,0 +1,105 @@
|
||||
using Content.Server.Storage.Components;
|
||||
using Content.Shared.Hands;
|
||||
using Content.Shared.Inventory;
|
||||
using Content.Shared.Stacks;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Physics.Components;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Shared.Storage.EntitySystems;
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="MagnetPickupComponent"/>
|
||||
/// </summary>
|
||||
public sealed class MagnetPickupSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
[Dependency] private readonly EntityLookupSystem _lookup = default!;
|
||||
[Dependency] private readonly InventorySystem _inventory = default!;
|
||||
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
||||
[Dependency] private readonly SharedStorageSystem _storage = default!;
|
||||
|
||||
private static readonly TimeSpan ScanDelay = TimeSpan.FromSeconds(1);
|
||||
|
||||
private EntityQuery<PhysicsComponent> _physicsQuery;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
_physicsQuery = GetEntityQuery<PhysicsComponent>();
|
||||
SubscribeLocalEvent<MagnetPickupComponent, MapInitEvent>(OnMagnetMapInit);
|
||||
SubscribeLocalEvent<MagnetPickupComponent, EntityUnpausedEvent>(OnMagnetUnpaused);
|
||||
}
|
||||
|
||||
private void OnMagnetUnpaused(EntityUid uid, MagnetPickupComponent component, ref EntityUnpausedEvent args)
|
||||
{
|
||||
component.NextScan += args.PausedTime;
|
||||
}
|
||||
|
||||
private void OnMagnetMapInit(EntityUid uid, MagnetPickupComponent component, MapInitEvent args)
|
||||
{
|
||||
component.NextScan = _timing.CurTime;
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
base.Update(frameTime);
|
||||
var query = EntityQueryEnumerator<MagnetPickupComponent, StorageComponent, TransformComponent>();
|
||||
var currentTime = _timing.CurTime;
|
||||
|
||||
while (query.MoveNext(out var uid, out var comp, out var storage, out var xform))
|
||||
{
|
||||
if (comp.NextScan < currentTime)
|
||||
continue;
|
||||
|
||||
comp.NextScan += ScanDelay;
|
||||
|
||||
// No space
|
||||
if (storage.StorageUsed >= storage.StorageCapacityMax)
|
||||
continue;
|
||||
|
||||
if (!_inventory.TryGetContainingSlot(uid, out var slotDef))
|
||||
continue;
|
||||
|
||||
if ((slotDef.SlotFlags & comp.SlotFlags) == 0x0)
|
||||
continue;
|
||||
|
||||
var parentUid = xform.ParentUid;
|
||||
var playedSound = false;
|
||||
var finalCoords = xform.Coordinates;
|
||||
var moverCoords = _transform.GetMoverCoordinates(uid, xform);
|
||||
|
||||
foreach (var near in _lookup.GetEntitiesInRange(uid, comp.Range, LookupFlags.Dynamic | LookupFlags.Sundries))
|
||||
{
|
||||
if (comp.Whitelist?.IsValid(near, EntityManager) == false)
|
||||
continue;
|
||||
|
||||
if (!_physicsQuery.TryGetComponent(near, out var physics) || physics.BodyStatus != BodyStatus.OnGround)
|
||||
continue;
|
||||
|
||||
if (near == parentUid)
|
||||
continue;
|
||||
|
||||
// TODO: Probably move this to storage somewhere when it gets cleaned up
|
||||
// TODO: This sucks but you need to fix a lot of stuff to make it better
|
||||
// the problem is that stack pickups delete the original entity, which is fine, but due to
|
||||
// game state handling we can't show a lerp animation for it.
|
||||
var nearXform = Transform(near);
|
||||
var nearMap = nearXform.MapPosition;
|
||||
var nearCoords = EntityCoordinates.FromMap(moverCoords.EntityId, nearMap, _transform, EntityManager);
|
||||
|
||||
if (!_storage.Insert(uid, near, out var stacked, storageComp: storage, playSound: !playedSound))
|
||||
continue;
|
||||
|
||||
// Play pickup animation for either the stack entity or the original entity.
|
||||
if (stacked != null)
|
||||
_storage.PlayPickupAnimation(stacked.Value, nearCoords, finalCoords, nearXform.LocalRotation);
|
||||
else
|
||||
_storage.PlayPickupAnimation(near, nearCoords, finalCoords, nearXform.LocalRotation);
|
||||
|
||||
playedSound = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ using Content.Shared.CombatMode;
|
||||
using Content.Shared.Containers.ItemSlots;
|
||||
using Content.Shared.Destructible;
|
||||
using Content.Shared.DoAfter;
|
||||
using Content.Shared.Hands;
|
||||
using Content.Shared.Hands.Components;
|
||||
using Content.Shared.Hands.EntitySystems;
|
||||
using Content.Shared.Implants.Components;
|
||||
@@ -37,7 +38,7 @@ public abstract class SharedStorageSystem : EntitySystem
|
||||
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
||||
[Dependency] protected readonly SharedAudioSystem Audio = default!;
|
||||
[Dependency] private readonly SharedCombatModeSystem _combatMode = default!;
|
||||
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
||||
[Dependency] protected readonly SharedTransformSystem _transform = default!;
|
||||
[Dependency] private readonly SharedStackSystem _stack = default!;
|
||||
[Dependency] protected readonly UseDelaySystem UseDelay = default!;
|
||||
|
||||
@@ -435,7 +436,7 @@ public abstract class SharedStorageSystem : EntitySystem
|
||||
|
||||
foreach (var entity in entities.ToArray())
|
||||
{
|
||||
Insert(target, entity, user, targetComp, playSound: false);
|
||||
Insert(target, entity, out _, user: user, targetComp, playSound: false);
|
||||
}
|
||||
|
||||
Audio.PlayPredicted(sourceComp.StorageInsertSound, target, user);
|
||||
@@ -495,8 +496,10 @@ public abstract class SharedStorageSystem : EntitySystem
|
||||
/// Inserts into the storage container
|
||||
/// </summary>
|
||||
/// <returns>true if the entity was inserted, false otherwise</returns>
|
||||
public bool Insert(EntityUid uid, EntityUid insertEnt, EntityUid? user = null, StorageComponent? storageComp = null, bool playSound = true)
|
||||
public bool Insert(EntityUid uid, EntityUid insertEnt, out EntityUid? stackedEntity, EntityUid? user = null, StorageComponent? storageComp = null, bool playSound = true)
|
||||
{
|
||||
stackedEntity = null;
|
||||
|
||||
if (!Resolve(uid, ref storageComp) || !CanInsert(uid, insertEnt, out _, storageComp))
|
||||
return false;
|
||||
|
||||
@@ -522,6 +525,7 @@ public abstract class SharedStorageSystem : EntitySystem
|
||||
if (!_stack.TryAdd(insertEnt, ent, insertStack, containedStack))
|
||||
continue;
|
||||
|
||||
stackedEntity = ent;
|
||||
var remaining = insertStack.Count;
|
||||
toInsertCount -= toInsertCount - remaining;
|
||||
|
||||
@@ -596,11 +600,17 @@ public abstract class SharedStorageSystem : EntitySystem
|
||||
if (!Resolve(uid, ref storageComp) || !_sharedInteractionSystem.InRangeUnobstructed(player, uid))
|
||||
return false;
|
||||
|
||||
if (!Insert(uid, toInsert, player, storageComp))
|
||||
if (!Insert(uid, toInsert, out _, user: player, storageComp))
|
||||
{
|
||||
_popupSystem.PopupClient(Loc.GetString("comp-storage-cant-insert"), uid, player);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Plays a clientside pickup animation for the specified uid.
|
||||
/// </summary>
|
||||
public abstract void PlayPickupAnimation(EntityUid uid, EntityCoordinates initialCoordinates,
|
||||
EntityCoordinates finalCoordinates, Angle initialRotation, EntityUid? user = null);
|
||||
}
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
name: ore bag
|
||||
id: OreBag
|
||||
parent: BaseStorageItem
|
||||
description: A robust bag for salvage specialists and miners alike to carry large amounts of ore.
|
||||
description: A robust bag for salvage specialists and miners alike to carry large amounts of ore. Magnetises any nearby ores when attached to a belt.
|
||||
components:
|
||||
- type: MagnetPickup
|
||||
- type: Sprite
|
||||
sprite: Objects/Specific/Mining/ore_bag.rsi
|
||||
state: icon
|
||||
|
||||
@@ -40,7 +40,9 @@ The crusher devices are your first and last line of defense against space fauna
|
||||
<GuideEntityEmbed Entity="OreBag"/>
|
||||
<GuideEntityEmbed Entity="ClothingBeltUtilityFilled"/>
|
||||
</Box>
|
||||
Mining equipment and a full utility belt are needed to be able to plunder the full value of a salvage. The mining to quickly gather ore for the ore processor to make usefull, and the tools of the utility belt for breaking things apart and moving high value objects out.
|
||||
The pickaxe and mining drill are both useful for mining rocks or breaking structures quickly.
|
||||
The ore bag magnetises nearby ore and automatically picks it up if equipped to a belt slot.
|
||||
The utility belt can be useful for holding miscellaneous items when not occupied by your ore bag.
|
||||
|
||||
## How to make money as a salvager
|
||||
<Box>
|
||||
|
||||
Reference in New Issue
Block a user