Skip to content
This repository was archived by the owner on Aug 22, 2025. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions Content.Client/Inventory/ClientInventorySystem.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Content.Client.Clothing;
using Content.Client.Examine;
using Content.Client.Verbs.UI;
using Content.Shared._White.Targeting;
using Content.Shared.Interaction;
using Content.Shared.Inventory;
using Content.Shared.Inventory.Events;
Expand Down Expand Up @@ -46,7 +47,22 @@ public override void Initialize()
_equipEventsQueue.Enqueue((comp, args)));
SubscribeLocalEvent<InventorySlotsComponent, DidUnequipEvent>((_, comp, args) =>
_equipEventsQueue.Enqueue((comp, args)));

// PARSEC EDIT START
SubscribeLocalEvent<InventorySlotsComponent, RefreshInventorySlotsEvent>(RefreshInventorySlots);
// PARSEC EDIT END
}

// PARSEC EDIT START
public void RefreshInventorySlots(EntityUid uid, InventorySlotsComponent component, RefreshInventorySlotsEvent args)
{
if (component.SlotData.TryGetValue(args.SlotName, out var slotData)
&& _playerManager.LocalEntity == uid)
{
OnSlotRemoved?.Invoke(slotData);
}
}
// PARSEC EDIT END

public override void Update(float frameTime)
{
Expand Down
2 changes: 2 additions & 0 deletions Content.Client/UserInterface/Screens/DefaultGameScreen.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
xmlns:hotbar="clr-namespace:Content.Client.UserInterface.Systems.Hotbar.Widgets"
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
xmlns:inventory="clr-namespace:Content.Client.UserInterface.Systems.Inventory.Widgets"
xmlns:targetdoll="clr-namespace:Content.Client._White.Targeting.Ui"
Name="DefaultHud"
VerticalExpand="False"
VerticalAlignment="Bottom"
Expand All @@ -28,6 +29,7 @@
<widgets:GhostGui Name="Ghost" Access="Protected" />
<inventory:InventoryGui Name="Inventory" Access="Protected" />
<hotbar:HotbarGui Name="Hotbar" Access="Protected" />
<targetdoll:TargetingWidget Name="Targeting" Access="Protected"/>
<chat:ResizableChatBox Name="Chat" Access="Protected" />
<alerts:AlertsUI Name="Alerts" Access="Protected" />
</screens:DefaultGameScreen>
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public DefaultGameScreen()
SetAnchorAndMarginPreset(Hotbar, LayoutPreset.BottomWide, margin: 5);
SetAnchorAndMarginPreset(Chat, LayoutPreset.TopRight, margin: 10);
SetAnchorAndMarginPreset(Alerts, LayoutPreset.TopRight, margin: 10);
SetAnchorAndMarginPreset(Targeting, LayoutPreset.BottomRight, margin: 10); // PARSEC

Chat.OnResized += ChatOnResized;
Chat.OnChatResizeFinish += ChatOnResizeFinish;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
xmlns:graphics="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
xmlns:inventory="clr-namespace:Content.Client.UserInterface.Systems.Inventory.Widgets"
xmlns:targetdoll="clr-namespace:Content.Client._White.Targeting.Ui"
Name="SeparatedChatHud"
VerticalExpand="False"
VerticalAlignment="Bottom"
Expand All @@ -20,6 +21,7 @@
<widgets:GhostGui Name="Ghost" Access="Protected" />
<inventory:InventoryGui Name="Inventory" Access="Protected"/>
<hotbar:HotbarGui Name="Hotbar" Access="Protected"/>
<targetdoll:TargetingWidget Name="Targeting" Access="Protected"/>
<BoxContainer Name="TopLeftContainer" Orientation="Vertical">
<actions:ActionsBar Name="Actions" Access="Protected" />
<BoxContainer Name="VoteMenu" Access="Public" Orientation="Vertical"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public SeparatedChatGameScreen()
SetAnchorAndMarginPreset(Ghost, LayoutPreset.BottomWide, margin: 80);
SetAnchorAndMarginPreset(Hotbar, LayoutPreset.BottomWide, margin: 5);
SetAnchorAndMarginPreset(Alerts, LayoutPreset.CenterRight, margin: 10);
SetAnchorAndMarginPreset(Targeting, LayoutPreset.BottomRight, margin: 10); // PARSEC

ScreenContainer.OnSplitResizeFinished += () =>
OnChatResized?.Invoke(new Vector2(ScreenContainer.SplitFraction, 0));
Expand Down
74 changes: 74 additions & 0 deletions Content.Client/_White/Targeting/Systems/TargetingSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
using Content.Shared._White.Targeting;
using Content.Shared._White.Targeting.Components;
using Robust.Client.Player;
using Robust.Shared.Player;

namespace Content.Client._White.Targeting.Systems;

public sealed class TargetingSystem : EntitySystem
{
[Dependency] private readonly IPlayerManager _playerManager = default!;

public event Action<TargetingComponent>? TargetingStartup;
public event Action? TargetingShutdown;
public event Action<TargetingComponent>? PartStatusStartup;
public event Action<TargetingComponent>? PartStatusUpdate;
public event Action? PartStatusShutdown;

public override void Initialize()
{
base.Initialize();

SubscribeLocalEvent<TargetingComponent, LocalPlayerAttachedEvent>(PlayerAttached);
SubscribeLocalEvent<TargetingComponent, LocalPlayerDetachedEvent>(PlayerDetached);

SubscribeLocalEvent<TargetingComponent, ComponentStartup>(OnTargetingStartup);
SubscribeLocalEvent<TargetingComponent, ComponentShutdown>(OnTargetingShutdown);

SubscribeNetworkEvent<TargetingIntegrityChangeEvent>(OnTargetingIntegrityChange);
}

private void PlayerAttached(EntityUid uid, TargetingComponent component, LocalPlayerAttachedEvent args)
{
TargetingStartup?.Invoke(component);
PartStatusStartup?.Invoke(component);
}

private void PlayerDetached(EntityUid uid, TargetingComponent component, LocalPlayerDetachedEvent args)
{
TargetingShutdown?.Invoke();
PartStatusShutdown?.Invoke();
}

private void OnTargetingStartup(EntityUid uid, TargetingComponent component, ComponentStartup args)
{
if (_playerManager.LocalEntity != uid)
return;

TargetingStartup?.Invoke(component);
PartStatusStartup?.Invoke(component);
}

private void OnTargetingShutdown(EntityUid uid, TargetingComponent component, ComponentShutdown args)
{
if (_playerManager.LocalEntity != uid)
return;

TargetingShutdown?.Invoke();
PartStatusShutdown?.Invoke();
}

private void OnTargetingIntegrityChange(TargetingIntegrityChangeEvent args)
{
if(!TryGetEntity(args.Entity, out var uid))
return;

if(!TryComp(uid, out TargetingComponent? component))
return;

if (!_playerManager.LocalEntity.Equals(uid) || !args.NeedRefresh)
return;

PartStatusUpdate?.Invoke(component);
}
}
80 changes: 80 additions & 0 deletions Content.Client/_White/Targeting/TargetingController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
using Content.Client._White.Targeting.Systems;
using Content.Client._White.Targeting.Ui;
using Content.Client.Gameplay;
using Content.Shared._White.Targeting;
using Content.Shared._White.Targeting.Components;
using Robust.Client.Player;
using Robust.Client.UserInterface.Controllers;

namespace Content.Client._White.Targeting;

public sealed class TargetingController : UIController, IOnStateEntered<GameplayState>, IOnSystemChanged<TargetingSystem>
{
[Dependency] private readonly IEntityManager _entManager = default!;
[Dependency] private readonly IEntityNetworkManager _net = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;

private TargetingComponent? _targetingComponent;
private TargetingWidget? TargetingControl => UIManager.GetActiveUIWidgetOrNull<TargetingWidget>();

public void OnSystemLoaded(TargetingSystem system)
{
system.TargetingStartup += AddTargetingControl;
system.TargetingShutdown += RemoveTargetingControl;
}

public void OnSystemUnloaded(TargetingSystem system)
{
system.TargetingStartup -= AddTargetingControl;
system.TargetingShutdown -= RemoveTargetingControl;
}

public void OnStateEntered(GameplayState state)
{
if (TargetingControl == null)
return;

TargetingControl.SetTargetDollVisible(_targetingComponent != null);

if (_targetingComponent != null)
TargetingControl.SetBodyPartsVisible(_targetingComponent.TargetBodyPart);
}

public void AddTargetingControl(TargetingComponent component)
{
_targetingComponent = component;

if (TargetingControl != null)
{
TargetingControl.SetTargetDollVisible(_targetingComponent != null);

if (_targetingComponent != null)
TargetingControl.SetBodyPartsVisible(_targetingComponent.TargetBodyPart);
}

}

public void RemoveTargetingControl()
{
TargetingControl?.SetTargetDollVisible(false);

_targetingComponent = null;
}

public void CycleTarget(TargetingBodyParts bodyPart)
{
if (_playerManager.LocalEntity is not { } user
|| _entManager.GetComponent<TargetingComponent>(user) is not { } targetingComponent
|| TargetingControl == null)
return;

var player = _entManager.GetNetEntity(user);

if (bodyPart == targetingComponent.TargetBodyPart)
return;

var msg = new TargetingChangeBodyPartEvent(player, bodyPart);
_net.SendSystemNetworkMessage(msg);
TargetingControl?.SetBodyPartsVisible(bodyPart);
}
}
Loading