Improve hands & pulling (#4389)
This commit is contained in:
committed by
GitHub
parent
73e4946e27
commit
632e72b817
3
Content.Client/Hands/HandVirtualPullItemStatus.xaml
Normal file
3
Content.Client/Hands/HandVirtualPullItemStatus.xaml
Normal file
@@ -0,0 +1,3 @@
|
||||
<Control xmlns="https://spacestation14.io">
|
||||
<Label StyleClasses="ItemStatus" Text="Pulling" />
|
||||
</Control>
|
||||
13
Content.Client/Hands/HandVirtualPullItemStatus.xaml.cs
Normal file
13
Content.Client/Hands/HandVirtualPullItemStatus.xaml.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
|
||||
namespace Content.Client.Hands
|
||||
{
|
||||
public sealed class HandVirtualPullItemStatus : Control
|
||||
{
|
||||
public HandVirtualPullItemStatus()
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,8 @@
|
||||
using System.Collections.Generic;
|
||||
using Content.Client.Animations;
|
||||
using Content.Client.HUD;
|
||||
using Content.Shared.Hands.Components;
|
||||
using Content.Shared.Item;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Players;
|
||||
using Robust.Shared.Timing;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Content.Client.Hands
|
||||
{
|
||||
@@ -18,16 +11,7 @@ namespace Content.Client.Hands
|
||||
[ComponentReference(typeof(SharedHandsComponent))]
|
||||
public class HandsComponent : SharedHandsComponent
|
||||
{
|
||||
[Dependency] private readonly IGameHud _gameHud = default!;
|
||||
|
||||
[ViewVariables]
|
||||
public HandsGui? Gui { get; private set; }
|
||||
|
||||
protected override void OnRemove()
|
||||
{
|
||||
ClearGui();
|
||||
base.OnRemove();
|
||||
}
|
||||
public HandsGui? Gui { get; set; }
|
||||
|
||||
public override void HandleComponentState(ComponentState? curState, ComponentState? nextState)
|
||||
{
|
||||
@@ -38,94 +22,23 @@ namespace Content.Client.Hands
|
||||
|
||||
foreach (var handState in state.Hands)
|
||||
{
|
||||
var newHand = new Hand(handState.Name, handState.Enabled, handState.Location);
|
||||
var newHand = new Hand(handState.Name, handState.Location);
|
||||
Hands.Add(newHand);
|
||||
}
|
||||
|
||||
ActiveHand = state.ActiveHand;
|
||||
|
||||
UpdateHandContainers();
|
||||
UpdateHandVisualizer();
|
||||
UpdateHandsGuiState();
|
||||
}
|
||||
|
||||
public void SettupGui()
|
||||
{
|
||||
if (Gui == null)
|
||||
{
|
||||
Gui = new HandsGui();
|
||||
_gameHud.HandsContainer.AddChild(Gui);
|
||||
Gui.HandClick += args => OnHandClick(args.HandClicked);
|
||||
Gui.HandActivate += args => OnActivateInHand(args.HandUsed);
|
||||
UpdateHandsGuiState();
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearGui()
|
||||
{
|
||||
Gui?.Dispose();
|
||||
Gui = null;
|
||||
}
|
||||
|
||||
public override void HandleNetworkMessage(ComponentMessage message, INetChannel netChannel, ICommonSession? session = null)
|
||||
{
|
||||
base.HandleNetworkMessage(message, netChannel, session);
|
||||
|
||||
switch (message)
|
||||
{
|
||||
case PickupAnimationMessage msg:
|
||||
RunPickupAnimation(msg);
|
||||
break;
|
||||
}
|
||||
Owner.EntityManager.EventBus.RaiseEvent(EventSource.Local, new HandsModifiedMessage { Hands = this });
|
||||
}
|
||||
|
||||
public override void HandsModified()
|
||||
{
|
||||
base.HandsModified();
|
||||
|
||||
UpdateHandContainers();
|
||||
UpdateHandVisualizer();
|
||||
UpdateHandsGuiState();
|
||||
}
|
||||
|
||||
private void OnHandClick(string handClicked)
|
||||
{
|
||||
if (!TryGetHand(handClicked, out var pressedHand))
|
||||
return;
|
||||
|
||||
if (!TryGetActiveHand(out var activeHand))
|
||||
return;
|
||||
|
||||
var pressedEntity = pressedHand.HeldEntity;
|
||||
var activeEntity = activeHand.HeldEntity;
|
||||
|
||||
if (pressedHand == activeHand && activeEntity != null)
|
||||
{
|
||||
SendNetworkMessage(new UseInHandMsg()); //use item in hand
|
||||
return;
|
||||
}
|
||||
|
||||
if (pressedHand != activeHand && pressedEntity == null)
|
||||
{
|
||||
SendNetworkMessage(new ClientChangedHandMsg(pressedHand.Name)); //swap hand
|
||||
return;
|
||||
}
|
||||
|
||||
if (pressedHand != activeHand && pressedEntity != null && activeEntity != null)
|
||||
{
|
||||
SendNetworkMessage(new ClientAttackByInHandMsg(pressedHand.Name)); //use active item on held item
|
||||
return;
|
||||
}
|
||||
|
||||
if (pressedHand != activeHand && pressedEntity != null && activeEntity == null)
|
||||
{
|
||||
SendNetworkMessage(new MoveItemFromHandMsg(pressedHand.Name)); //move item in hand to active hand
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnActivateInHand(string handActivated)
|
||||
{
|
||||
SendNetworkMessage(new ActivateInHandMsg(handActivated));
|
||||
base.HandsModified();
|
||||
}
|
||||
|
||||
public void UpdateHandContainers()
|
||||
@@ -149,27 +62,10 @@ namespace Content.Client.Hands
|
||||
appearance.SetData(HandsVisuals.VisualState, GetHandsVisualState());
|
||||
}
|
||||
|
||||
public void UpdateHandsGuiState()
|
||||
{
|
||||
Gui?.SetState(GetHandsGuiState());
|
||||
}
|
||||
|
||||
private HandsGuiState GetHandsGuiState()
|
||||
{
|
||||
var handStates = new List<GuiHand>();
|
||||
|
||||
foreach (var hand in ReadOnlyHands)
|
||||
{
|
||||
var handState = new GuiHand(hand.Name, hand.Location, hand.HeldEntity, hand.Enabled);
|
||||
handStates.Add(handState);
|
||||
}
|
||||
return new HandsGuiState(handStates, ActiveHand);
|
||||
}
|
||||
|
||||
private HandsVisualState GetHandsVisualState()
|
||||
{
|
||||
var hands = new List<HandVisualState>();
|
||||
foreach (var hand in ReadOnlyHands)
|
||||
foreach (var hand in Hands)
|
||||
{
|
||||
if (hand.HeldEntity == null)
|
||||
continue;
|
||||
@@ -182,16 +78,5 @@ namespace Content.Client.Hands
|
||||
}
|
||||
return new(hands);
|
||||
}
|
||||
|
||||
private void RunPickupAnimation(PickupAnimationMessage msg)
|
||||
{
|
||||
if (!Owner.EntityManager.TryGetEntity(msg.EntityUid, out var entity))
|
||||
return;
|
||||
|
||||
if (!IoCManager.Resolve<IGameTiming>().IsFirstTimePredicted)
|
||||
return;
|
||||
|
||||
ReusableAnimations.AnimateEntityPickup(entity, msg.InitialPosition, msg.PickupDirection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
6
Content.Client/Hands/HandsGui.xaml
Normal file
6
Content.Client/Hands/HandsGui.xaml
Normal file
@@ -0,0 +1,6 @@
|
||||
<Control xmlns="https://spacestation14.io">
|
||||
<BoxContainer Orientation="Vertical">
|
||||
<Control Name="StatusContainer" />
|
||||
<BoxContainer Name="HandsContainer" Orientation="Horizontal" HorizontalAlignment="Center" />
|
||||
</BoxContainer>
|
||||
</Control>
|
||||
@@ -1,87 +1,84 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using Content.Client.HUD;
|
||||
using Content.Client.Items.Managers;
|
||||
using Content.Client.Items.UI;
|
||||
using Content.Client.Resources;
|
||||
using Content.Shared;
|
||||
using Content.Shared.CCVar;
|
||||
using Content.Shared.Hands.Components;
|
||||
using Content.Shared.Input;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Client.ResourceManagement;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Input;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Timing;
|
||||
using Robust.Shared.ViewVariables;
|
||||
using static Robust.Client.UserInterface.Controls.BoxContainer;
|
||||
|
||||
namespace Content.Client.Hands
|
||||
{
|
||||
public class HandsGui : Control
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class HandsGui : Control
|
||||
{
|
||||
[Dependency] private readonly IResourceCache _resourceCache = default!;
|
||||
[Dependency] private readonly IItemSlotManager _itemSlotManager = default!;
|
||||
[Dependency] private readonly IGameHud _gameHud = default!;
|
||||
[Dependency] private readonly INetConfigurationManager _configManager = default!;
|
||||
|
||||
private readonly HandsSystem _handsSystem;
|
||||
private readonly HandsComponent _handsComponent;
|
||||
|
||||
private Texture StorageTexture => _gameHud.GetHudTexture("back.png");
|
||||
private Texture BlockedTexture => _resourceCache.GetTexture("/Textures/Interface/Inventory/blocked.png");
|
||||
|
||||
private ItemStatusPanel StatusPanel { get; }
|
||||
|
||||
private BoxContainer HandsContainer { get; }
|
||||
|
||||
[ViewVariables]
|
||||
public IReadOnlyList<GuiHand> Hands => _hands;
|
||||
private List<GuiHand> _hands = new();
|
||||
[ViewVariables] private GuiHand[] _hands = Array.Empty<GuiHand>();
|
||||
|
||||
private string? ActiveHand { get; set; }
|
||||
|
||||
public Action<HandClickEventArgs>? HandClick; //TODO: Move to Eventbus
|
||||
|
||||
public Action<HandActivateEventArgs>? HandActivate; //TODO: Move to Eventbus
|
||||
|
||||
public HandsGui()
|
||||
public HandsGui(HandsComponent hands, HandsSystem handsSystem)
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
_configManager.OnValueChanged(CCVars.HudTheme, UpdateHudTheme);
|
||||
_handsComponent = hands;
|
||||
_handsSystem = handsSystem;
|
||||
|
||||
AddChild(new BoxContainer
|
||||
{
|
||||
Orientation = LayoutOrientation.Horizontal,
|
||||
SeparationOverride = 0,
|
||||
HorizontalAlignment = HAlignment.Center,
|
||||
Children =
|
||||
{
|
||||
new BoxContainer
|
||||
{
|
||||
Orientation = LayoutOrientation.Vertical,
|
||||
Children =
|
||||
{
|
||||
(StatusPanel = ItemStatusPanel.FromSide(HandLocation.Middle)),
|
||||
(HandsContainer = new BoxContainer
|
||||
{
|
||||
Orientation = LayoutOrientation.Horizontal,
|
||||
HorizontalAlignment = HAlignment.Center
|
||||
}),
|
||||
}
|
||||
},
|
||||
}
|
||||
});
|
||||
RobustXamlLoader.Load(this);
|
||||
IoCManager.InjectDependencies(this);
|
||||
|
||||
StatusPanel = ItemStatusPanel.FromSide(HandLocation.Middle);
|
||||
StatusContainer.AddChild(StatusPanel);
|
||||
StatusPanel.SetPositionFirst();
|
||||
}
|
||||
|
||||
public void SetState(HandsGuiState state)
|
||||
protected override void EnteredTree()
|
||||
{
|
||||
base.EnteredTree();
|
||||
|
||||
_handsSystem.GuiStateUpdated += HandsSystemOnGuiStateUpdated;
|
||||
_configManager.OnValueChanged(CCVars.HudTheme, UpdateHudTheme);
|
||||
|
||||
HandsSystemOnGuiStateUpdated();
|
||||
}
|
||||
|
||||
protected override void ExitedTree()
|
||||
{
|
||||
base.ExitedTree();
|
||||
|
||||
_handsSystem.GuiStateUpdated -= HandsSystemOnGuiStateUpdated;
|
||||
_configManager.UnsubValueChanged(CCVars.HudTheme, UpdateHudTheme);
|
||||
}
|
||||
|
||||
private void HandsSystemOnGuiStateUpdated()
|
||||
{
|
||||
var state = _handsSystem.GetGuiState();
|
||||
|
||||
ActiveHand = state.ActiveHand;
|
||||
_hands = state.GuiHands;
|
||||
Array.Sort(_hands, HandOrderComparer.Instance);
|
||||
UpdateGui();
|
||||
}
|
||||
|
||||
@@ -97,12 +94,15 @@ namespace Content.Client.Hands
|
||||
|
||||
var handName = hand.Name;
|
||||
newButton.OnPressed += args => OnHandPressed(args, handName);
|
||||
newButton.OnStoragePressed += args => OnStoragePressed(handName);
|
||||
|
||||
newButton.Blocked.Visible = !hand.Enabled;
|
||||
newButton.OnStoragePressed += _ => OnStoragePressed(handName);
|
||||
|
||||
_itemSlotManager.SetItemSlot(newButton, hand.HeldItem);
|
||||
|
||||
// Show blocked overlay if hand is pulling.
|
||||
newButton.Blocked.Visible =
|
||||
hand.HeldItem != null && hand.HeldItem.HasComponent<HandVirtualPullComponent>();
|
||||
}
|
||||
|
||||
if (TryGetActiveHand(out var activeHand))
|
||||
{
|
||||
activeHand.HandButton.SetActiveHand(true);
|
||||
@@ -114,7 +114,7 @@ namespace Content.Client.Hands
|
||||
{
|
||||
if (args.Function == EngineKeyFunctions.UIClick)
|
||||
{
|
||||
HandClick?.Invoke(new HandClickEventArgs(handName));
|
||||
_handsSystem.UIHandClick(_handsComponent, handName);
|
||||
}
|
||||
else if (TryGetHand(handName, out var hand))
|
||||
{
|
||||
@@ -124,7 +124,7 @@ namespace Content.Client.Hands
|
||||
|
||||
private void OnStoragePressed(string handName)
|
||||
{
|
||||
HandActivate?.Invoke(new HandActivateEventArgs(handName));
|
||||
_handsSystem.UIHandActivate(handName);
|
||||
}
|
||||
|
||||
private bool TryGetActiveHand([NotNullWhen(true)] out GuiHand? activeHand)
|
||||
@@ -145,6 +145,7 @@ namespace Content.Client.Hands
|
||||
if (hand.Name == handName)
|
||||
foundHand = hand;
|
||||
}
|
||||
|
||||
return foundHand != null;
|
||||
}
|
||||
|
||||
@@ -153,7 +154,9 @@ namespace Content.Client.Hands
|
||||
base.FrameUpdate(args);
|
||||
|
||||
foreach (var hand in _hands)
|
||||
{
|
||||
_itemSlotManager.UpdateCooldown(hand.HandButton, hand.HeldItem);
|
||||
}
|
||||
}
|
||||
|
||||
private HandButton MakeHandButton(HandLocation buttonLocation)
|
||||
@@ -173,23 +176,31 @@ namespace Content.Client.Hands
|
||||
UpdateGui();
|
||||
}
|
||||
|
||||
public class HandClickEventArgs
|
||||
private sealed class HandOrderComparer : IComparer<GuiHand>
|
||||
{
|
||||
public string HandClicked { get; }
|
||||
public static readonly HandOrderComparer Instance = new();
|
||||
|
||||
public HandClickEventArgs(string handClicked)
|
||||
public int Compare(GuiHand? x, GuiHand? y)
|
||||
{
|
||||
HandClicked = handClicked;
|
||||
}
|
||||
}
|
||||
if (ReferenceEquals(x, y)) return 0;
|
||||
if (ReferenceEquals(null, y)) return 1;
|
||||
if (ReferenceEquals(null, x)) return -1;
|
||||
|
||||
public class HandActivateEventArgs
|
||||
{
|
||||
public string HandUsed { get; }
|
||||
var orderX = Map(x.HandLocation);
|
||||
var orderY = Map(y.HandLocation);
|
||||
|
||||
public HandActivateEventArgs(string handUsed)
|
||||
{
|
||||
HandUsed = handUsed;
|
||||
return orderX.CompareTo(orderY);
|
||||
|
||||
static int Map(HandLocation loc)
|
||||
{
|
||||
return loc switch
|
||||
{
|
||||
HandLocation.Left => 3,
|
||||
HandLocation.Middle => 2,
|
||||
HandLocation.Right => 1,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(loc), loc, null)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -203,7 +214,7 @@ namespace Content.Client.Hands
|
||||
/// The set of hands to be displayed.
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
public List<GuiHand> GuiHands { get; } = new();
|
||||
public GuiHand[] GuiHands { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The name of the currently active hand.
|
||||
@@ -211,7 +222,7 @@ namespace Content.Client.Hands
|
||||
[ViewVariables]
|
||||
public string? ActiveHand { get; }
|
||||
|
||||
public HandsGuiState(List<GuiHand> guiHands, string? activeHand = null)
|
||||
public HandsGuiState(GuiHand[] guiHands, string? activeHand = null)
|
||||
{
|
||||
GuiHands = guiHands;
|
||||
ActiveHand = activeHand;
|
||||
@@ -247,18 +258,11 @@ namespace Content.Client.Hands
|
||||
[ViewVariables]
|
||||
public HandButton HandButton { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// If this hand can be used by the player.
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
public bool Enabled { get; }
|
||||
|
||||
public GuiHand(string name, HandLocation handLocation, IEntity? heldItem, bool enabled)
|
||||
public GuiHand(string name, HandLocation handLocation, IEntity? heldItem)
|
||||
{
|
||||
Name = name;
|
||||
HandLocation = handLocation;
|
||||
HeldItem = heldItem;
|
||||
Enabled = enabled;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
using Content.Shared.Hands;
|
||||
using Content.Shared.Hands.Components;
|
||||
using Content.Shared.Input;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Input.Binding;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Players;
|
||||
|
||||
namespace Content.Client.Hands
|
||||
{
|
||||
internal sealed class HandsSystem : SharedHandsSystem
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<HandsComponent, PlayerAttachedEvent>((_, component, _) => component.SettupGui());
|
||||
SubscribeLocalEvent<HandsComponent, PlayerDetachedEvent>((_, component, _) => component.ClearGui());
|
||||
|
||||
CommandBinds.Builder
|
||||
.Bind(ContentKeyFunctions.SwapHands, InputCmdHandler.FromDelegate(SwapHandsPressed))
|
||||
.Bind(ContentKeyFunctions.Drop, new PointerInputCmdHandler(DropPressed))
|
||||
.Register<HandsSystem>();
|
||||
}
|
||||
|
||||
public override void Shutdown()
|
||||
{
|
||||
CommandBinds.Unregister<HandsSystem>();
|
||||
base.Shutdown();
|
||||
}
|
||||
|
||||
private void SwapHandsPressed(ICommonSession? session)
|
||||
{
|
||||
if (session == null)
|
||||
return;
|
||||
|
||||
var player = session.AttachedEntity;
|
||||
|
||||
if (player == null)
|
||||
return;
|
||||
|
||||
if (!player.TryGetComponent(out SharedHandsComponent? hands))
|
||||
return;
|
||||
|
||||
if (!hands.TryGetSwapHandsResult(out var nextHand))
|
||||
return;
|
||||
|
||||
EntityManager.RaisePredictiveEvent(new RequestSetHandEvent(nextHand));
|
||||
}
|
||||
|
||||
private bool DropPressed(ICommonSession? session, EntityCoordinates coords, EntityUid uid)
|
||||
{
|
||||
if (session == null)
|
||||
return false;
|
||||
|
||||
var player = session.AttachedEntity;
|
||||
|
||||
if (player == null)
|
||||
return false;
|
||||
|
||||
if (!player.TryGetComponent(out SharedHandsComponent? hands))
|
||||
return false;
|
||||
|
||||
var activeHand = hands.ActiveHand;
|
||||
|
||||
if (activeHand == null)
|
||||
return false;
|
||||
|
||||
EntityManager.RaisePredictiveEvent(new RequestDropHeldEntityEvent(activeHand, coords));
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void HandleContainerModified(EntityUid uid, SharedHandsComponent component, ContainerModifiedMessage args)
|
||||
{
|
||||
component.HandsModified();
|
||||
}
|
||||
}
|
||||
}
|
||||
18
Content.Client/Hands/Systems/HandVirtualPullSystem.cs
Normal file
18
Content.Client/Hands/Systems/HandVirtualPullSystem.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using Content.Client.Items;
|
||||
using Content.Shared.Hands.Components;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
namespace Content.Client.Hands
|
||||
{
|
||||
[UsedImplicitly]
|
||||
public sealed class HandVirtualPullSystem : EntitySystem
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
Subs.ItemStatus<HandVirtualPullComponent>(_ => new HandVirtualPullItemStatus());
|
||||
}
|
||||
}
|
||||
}
|
||||
149
Content.Client/Hands/Systems/HandsSystem.cs
Normal file
149
Content.Client/Hands/Systems/HandsSystem.cs
Normal file
@@ -0,0 +1,149 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Content.Client.Animations;
|
||||
using Content.Client.HUD;
|
||||
using Content.Shared.Hands;
|
||||
using Content.Shared.Hands.Components;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Input.Binding;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Client.Hands
|
||||
{
|
||||
[UsedImplicitly]
|
||||
public sealed class HandsSystem : SharedHandsSystem
|
||||
{
|
||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||
[Dependency] private readonly IGameHud _gameHud = default!;
|
||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||
|
||||
public event Action? GuiStateUpdated;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<HandsComponent, PlayerAttachedEvent>(HandlePlayerAttached);
|
||||
SubscribeLocalEvent<HandsComponent, PlayerDetachedEvent>(HandlePlayerDetached);
|
||||
SubscribeLocalEvent<HandsComponent, ComponentRemove>(HandleCompRemove);
|
||||
SubscribeLocalEvent<HandsModifiedMessage>(HandleHandsModified);
|
||||
|
||||
SubscribeNetworkEvent<PickupAnimationMessage>(HandlePickupAnimation);
|
||||
}
|
||||
|
||||
public override void Shutdown()
|
||||
{
|
||||
CommandBinds.Unregister<HandsSystem>();
|
||||
base.Shutdown();
|
||||
}
|
||||
|
||||
private void HandleHandsModified(HandsModifiedMessage ev)
|
||||
{
|
||||
if (ev.Hands.Owner == _playerManager.LocalPlayer?.ControlledEntity)
|
||||
GuiStateUpdated?.Invoke();
|
||||
}
|
||||
|
||||
protected override void HandleContainerModified(EntityUid uid, SharedHandsComponent component, ContainerModifiedMessage args)
|
||||
{
|
||||
if (uid == _playerManager.LocalPlayer?.ControlledEntity?.Uid)
|
||||
GuiStateUpdated?.Invoke();
|
||||
}
|
||||
|
||||
private void HandlePickupAnimation(PickupAnimationMessage msg)
|
||||
{
|
||||
if (!EntityManager.TryGetEntity(msg.EntityUid, out var entity))
|
||||
return;
|
||||
|
||||
if (!_gameTiming.IsFirstTimePredicted)
|
||||
return;
|
||||
|
||||
ReusableAnimations.AnimateEntityPickup(entity, msg.InitialPosition, msg.PickupDirection);
|
||||
}
|
||||
|
||||
public HandsGuiState GetGuiState()
|
||||
{
|
||||
var player = _playerManager.LocalPlayer?.ControlledEntity;
|
||||
|
||||
if (player == null || !player.TryGetComponent(out HandsComponent? hands))
|
||||
return new HandsGuiState(Array.Empty<GuiHand>());
|
||||
|
||||
var states = hands.Hands
|
||||
.Select(hand => new GuiHand(hand.Name, hand.Location, hand.HeldEntity))
|
||||
.ToArray();
|
||||
|
||||
return new HandsGuiState(states, hands.ActiveHand);
|
||||
}
|
||||
|
||||
public void UIHandClick(HandsComponent hands, string handName)
|
||||
{
|
||||
if (!hands.TryGetHand(handName, out var pressedHand))
|
||||
return;
|
||||
|
||||
if (!hands.TryGetActiveHand(out var activeHand))
|
||||
return;
|
||||
|
||||
var pressedEntity = pressedHand.HeldEntity;
|
||||
var activeEntity = activeHand.HeldEntity;
|
||||
|
||||
if (pressedHand == activeHand && activeEntity != null)
|
||||
{
|
||||
// use item in hand
|
||||
// it will always be attack_self() in my heart.
|
||||
RaiseNetworkEvent(new UseInHandMsg());
|
||||
return;
|
||||
}
|
||||
|
||||
if (pressedHand != activeHand && pressedEntity == null)
|
||||
{
|
||||
// change active hand
|
||||
RaiseNetworkEvent(new RequestSetHandEvent(handName));
|
||||
return;
|
||||
}
|
||||
|
||||
if (pressedHand != activeHand && pressedEntity != null && activeEntity != null)
|
||||
{
|
||||
// use active item on held item
|
||||
RaiseNetworkEvent(new ClientInteractUsingInHandMsg(pressedHand.Name));
|
||||
return;
|
||||
}
|
||||
|
||||
if (pressedHand != activeHand && pressedEntity != null && activeEntity == null)
|
||||
{
|
||||
// use active item on held item
|
||||
RaiseNetworkEvent(new MoveItemFromHandMsg(pressedHand.Name));
|
||||
}
|
||||
}
|
||||
|
||||
public void UIHandActivate(string handName)
|
||||
{
|
||||
RaiseNetworkEvent (new ActivateInHandMsg(handName));
|
||||
}
|
||||
|
||||
private void HandlePlayerAttached(EntityUid uid, HandsComponent component, PlayerAttachedEvent args)
|
||||
{
|
||||
component.Gui = new HandsGui(component, this);
|
||||
_gameHud.HandsContainer.AddChild(component.Gui);
|
||||
}
|
||||
|
||||
private static void HandlePlayerDetached(EntityUid uid, HandsComponent component, PlayerDetachedEvent args)
|
||||
{
|
||||
ClearGui(component);
|
||||
}
|
||||
|
||||
private static void HandleCompRemove(EntityUid uid, HandsComponent component, ComponentRemove args)
|
||||
{
|
||||
ClearGui(component);
|
||||
}
|
||||
|
||||
private static void ClearGui(HandsComponent comp)
|
||||
{
|
||||
comp.Gui?.Orphan();
|
||||
comp.Gui = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user