Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Health bar #13

Merged
merged 7 commits into from
Oct 24, 2024
Merged
Show file tree
Hide file tree
Changes from 4 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
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:sss="clr-namespace:Content.Client._SSS.UserInterface.Widgets"
Name="DefaultHud"
VerticalExpand="False"
VerticalAlignment="Bottom"
Expand All @@ -30,4 +31,5 @@
<hotbar:HotbarGui Name="Hotbar" Access="Protected" />
<chat:ResizableChatBox Name="Chat" Access="Protected" />
<alerts:AlertsUI Name="Alerts" Access="Protected" />
<sss:SSSStatusGui Name="SSSStatus" Access="Protected" />
</screens:DefaultGameScreen>
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ public DefaultGameScreen()
SetAnchorAndMarginPreset(Chat, LayoutPreset.TopRight, margin: 10);
SetAnchorAndMarginPreset(Alerts, LayoutPreset.TopRight, margin: 10);

SetAnchorAndMarginPreset(SSSStatus, LayoutPreset.BottomRight, margin: 10);

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:sss="clr-namespace:Content.Client._SSS.UserInterface.Widgets"
Name="SeparatedChatHud"
VerticalExpand="False"
VerticalAlignment="Bottom"
Expand All @@ -25,6 +26,7 @@
<BoxContainer Name="VoteMenu" Access="Public" Orientation="Vertical"/>
</BoxContainer>
<alerts:AlertsUI Name="Alerts" Access="Protected" />
<sss:SSSStatusGui Name="SSSStatus" Access="Protected" />
</LayoutContainer>
<PanelContainer HorizontalExpand="True" MinWidth="300">
<PanelContainer.PanelOverride>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ public SeparatedChatGameScreen()
SetAnchorAndMarginPreset(Hotbar, LayoutPreset.BottomWide, margin: 5);
SetAnchorAndMarginPreset(Alerts, LayoutPreset.CenterRight, margin: 10);

SetAnchorAndMarginPreset(SSSStatus, LayoutPreset.BottomRight, margin: 10);

ScreenContainer.OnSplitResizeFinished += () =>
OnChatResized?.Invoke(new Vector2(ScreenContainer.SplitFraction, 0));

Expand Down
254 changes: 254 additions & 0 deletions Content.Client/_SSS/UserInterface/SSSStatusUIController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@
using Content.Client._SSS.UserInterface.Widgets;
using Content.Client.GameTicking.Managers;
using Content.Client.Mind;
using Content.Client.Resources;
using Content.Client.Roles;
using Content.Shared._SSS.SuspicionGameRule.Components;
using Content.Shared.Damage;
using Content.Shared.Mobs;
using Content.Shared.Mobs.Components;
using Content.Shared.Mobs.Systems;
using Robust.Client.Graphics;
using Robust.Client.Player;
using Robust.Client.ResourceManagement;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controllers;
using Robust.Shared.Timing;

namespace Content.Client._SSS.UserInterface;

public sealed class SSSStatusUIController : UIController, IOnSystemChanged<DamageableSystem>
{
[Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly IResourceCache _resourceCache = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;
private ISawmill _log = default!;
Callmore marked this conversation as resolved.
Show resolved Hide resolved
[UISystemDependency] private readonly MobThresholdSystem? _mobThreshold;
[UISystemDependency] private readonly ClientGameTicker? _clientGameTicker;
[UISystemDependency] private readonly RoleSystem? _role;
[UISystemDependency] private readonly MindSystem? _mind;

private StyleBoxTexture _roleStyleBox = default!;

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

_log = Logger.GetSawmill("StatusUI");

SubscribeNetworkEvent<SuspicionRuleTimerUpdate>(UpdateTimerEnd);
SubscribeNetworkEvent<SuspicionRulePreroundStarted>(PreroundStarted);
SubscribeNetworkEvent<SuspicionRuleUpdateRole>(UpdateRoleDisplay);
SubscribeNetworkEvent<SuspicionRulePlayerSpawn>(UpdatePlayerSpawn);

_log.Info($"{nameof(SSSStatusUIController)} loaded.");
Callmore marked this conversation as resolved.
Show resolved Hide resolved

var styleBox = new StyleBoxTexture()
{
Texture = _resourceCache.GetTexture("/Textures/Interface/Nano/button.svg.96dpi.png"),
};
styleBox.SetPatchMargin(StyleBox.Margin.All, 10);

_roleStyleBox = styleBox;
}

private TimeSpan _lastEndTime;
private TimeSpan _lastDrawnSeconds;

private (string, Color)? _queuedRole = null;
private (string, float, float)? _queuedHealth = null;

public override void FrameUpdate(FrameEventArgs args)
{
base.FrameUpdate(args);

// I LOVE THIS HACK I LOVE THIS HACK I LOVE THIS HACK I LOVE THIS HACK
SetRoleFromQueued();
SetHealthBarFromQueued();

// TODO: limit this to only update when the timer is not the same
if (_clientGameTicker is null)
return;

if (_lastEndTime == TimeSpan.MinValue)
return;

var drawTime = _lastEndTime.Subtract(_clientGameTicker.RoundDuration());
if ((int)drawTime.TotalSeconds != (int)_lastDrawnSeconds.TotalSeconds)
{
UpdateTimer(drawTime);
_lastDrawnSeconds = drawTime;
}
}

private SSSStatusGui? StatusUI => UIManager.GetActiveUIWidgetOrNull<SSSStatusGui>();

public void UpdateHealth(Entity<DamageableComponent> ent)
{

if (!EntityManager.TryGetComponent<MobStateComponent>(ent, out var mobState))
return;

if (mobState.CurrentState == MobState.Dead)
{
SetHealthBarCustom("DEAD", 0, 100);
Callmore marked this conversation as resolved.
Show resolved Hide resolved
return;
}

if (!EntityManager.TryGetComponent<MobThresholdsComponent>(ent, out var mobThresholds))
return;

if (_mobThreshold is null)
return;

var maxHp = _mobThreshold.GetThresholdForState(ent, MobState.Critical, mobThresholds);
var hp = Math.Max(Math.Ceiling((maxHp - ent.Comp.TotalDamage).Double()), 0);
// var hp = Math.Max((maxHp - ent.Comp.TotalDamage).Float(), 0);
Callmore marked this conversation as resolved.
Show resolved Hide resolved

SetHealthBar((float)hp, maxHp.Float());
}

private void SetHealthBarCustom(string text, float value, float maxValue)
{
var ui = StatusUI;

if (ui == null)
{
_queuedHealth = (text, value, maxValue);
return;
}

ui.HealthNumber.Text = text;
ui.HealthBar.MaxValue = maxValue;
ui.HealthBar.Value = value;
}

private bool SetHealthBarFromQueued()
{
if (_queuedHealth is null)
return false;

var ui = StatusUI;
if (ui is null)
return false;

var (text, value, maxValue) = _queuedHealth.Value;

ui.HealthNumber.Text = text;
ui.HealthBar.MaxValue = maxValue;
ui.HealthBar.Value = value;
_queuedHealth = null;

return true;
}

private void SetHealthBar(float hp, float maxHp)
{
SetHealthBarCustom($"\u2665 {hp}", hp, maxHp);
Callmore marked this conversation as resolved.
Show resolved Hide resolved
}

private void UpdateTimer(TimeSpan ts)
{
var ui = StatusUI;

if (ui == null)
return;

if (ts < TimeSpan.Zero)
{
ts = TimeSpan.Zero;
}

// nice job c#, TimeSpan.ToString doesn't support having no leading zeros
ui.TimerText.Text = $"{ts.Minutes}:{ts.Seconds:00}";
}

public void UpdateTimerEnd(SuspicionRuleTimerUpdate ev, EntitySessionEventArgs args)
{
_log.Info($"WHAT AT {ev.EndTime}");
Callmore marked this conversation as resolved.
Show resolved Hide resolved
_lastEndTime = ev.EndTime;
}

public void PreroundStarted(SuspicionRulePreroundStarted ev, EntitySessionEventArgs args)
{
_lastEndTime = ev.PreroundEndTime;
SetRoleCustom("Preround", Color.DarkGray);
Callmore marked this conversation as resolved.
Show resolved Hide resolved
}

private void SetRoleCustom(string role, Color color)
{
var ui = StatusUI;

if (ui is null)
{
_queuedRole = (role, color);
return;
}

ui.RoleBG.PanelOverride = new StyleBoxTexture(_roleStyleBox) { Modulate = color };
ui.RoleText.Text = role;
}

private bool SetRoleFromQueued()
{
if (_queuedRole is null)
return false;

var ui = StatusUI;
if (ui is null)
return false;

var (role, color) = _queuedRole.Value;

ui.RoleBG.PanelOverride = new StyleBoxTexture(_roleStyleBox) { Modulate = color };
ui.RoleText.Text = role;
_queuedRole = null;

return true;
}

private void SetRoleToPreround()
{
SetRoleCustom("Preround", Color.DarkGray);
Callmore marked this conversation as resolved.
Show resolved Hide resolved
}

private void SetRoleToObserbing()
{
SetRoleCustom("Obserbing", Color.DarkGray);
Callmore marked this conversation as resolved.
Show resolved Hide resolved
}

public void UpdateRoleDisplay(SuspicionRuleUpdateRole ev, EntitySessionEventArgs args)
{
// ui.RoleBG.PanelOverride = new StyleBoxTexture(_roleStyleBox) { Modulate = Color.FromName(ev.NewRole.GetRoleColor()) };
// ui.RoleText.Text = ev.NewRole.ToString();
Callmore marked this conversation as resolved.
Show resolved Hide resolved
SetRoleCustom(ev.NewRole.ToString(), Color.FromName(ev.NewRole.GetRoleColor()));
}

public void UpdatePlayerSpawn(SuspicionRulePlayerSpawn ev, EntitySessionEventArgs args)
{
if (ev.GameState == SuspicionGameState.Preparing)
{
SetRoleToPreround();

if (EntityManager.TryGetComponent<DamageableComponent>(_playerManager.LocalEntity!.Value, out var damagable))
UpdateHealth((_playerManager.LocalEntity!.Value, damagable));
}
else
{
SetRoleToObserbing();
SetHealthBar(0, 100);
}

_lastEndTime = ev.EndTime;
}

public void OnSystemLoaded(DamageableSystem system)
{
system.OnPlayerDamageChanged += UpdateHealth;
}

public void OnSystemUnloaded(DamageableSystem system)
{
system.OnPlayerDamageChanged -= UpdateHealth;
}
}
39 changes: 39 additions & 0 deletions Content.Client/_SSS/UserInterface/Widgets/SSSStatusGui.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<widgets:SSSStatusGui
xmlns="https://spacestation14.io"
xmlns:widgets="clr-namespace:Content.Client._SSS.UserInterface.Widgets"
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
xmlns:graphics="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
VerticalAlignment="Bottom"
HorizontalAlignment="Right"
>

<!--
VerticalExpand="True"
Orientation="Horizontal"
-->
<Control>
Callmore marked this conversation as resolved.
Show resolved Hide resolved

<PanelContainer StyleClasses="AngleRect" />
<BoxContainer Orientation="Vertical" Margin="8">
<BoxContainer Orientation="Horizontal">
<Control>
<PanelContainer Name="RoleBG" Access="Public">
</PanelContainer>
<Label Name="RoleText" Access="Public" Text="Traitor?" Margin="4"/>
</Control>
<Label Name="TimerText" Access="Public" Text="5:00" Align="Right" HorizontalExpand="True" />
</BoxContainer>
<Control MinSize="0 4" />
<Control MinSize="200 20">
<ProgressBar Name="HealthBar" Access="Public" Value="75" MaxValue="100">
<ProgressBar.ForegroundStyleBoxOverride>
<graphics:StyleBoxFlat BackgroundColor="#DE3A3A" />
</ProgressBar.ForegroundStyleBoxOverride>
</ProgressBar>
<Label Name="HealthNumber" Access="Public" Text="100" Align="Right" />
</Control>
</BoxContainer>

</Control>

</widgets:SSSStatusGui>
14 changes: 14 additions & 0 deletions Content.Client/_SSS/UserInterface/Widgets/SSSStatusGui.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;

namespace Content.Client._SSS.UserInterface.Widgets;

[GenerateTypedNameReferences]
public sealed partial class SSSStatusGui : UIWidget
{
public SSSStatusGui()
{
RobustXamlLoader.Load(this);
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
using System.Linq;
using Content.Server._SSS.GridMarker;
using Content.Server._SSS.SuspicionGameRule.Components;
using Content.Server.Communications;
using Content.Server.Ghost;
using Content.Shared._SSS;
using Content.Shared._SSS.SuspicionGameRule.Components;
using Content.Shared.Chat;
using Content.Shared.Damage;
using Content.Shared.Damage.Prototypes;
Expand All @@ -11,13 +12,10 @@
using Content.Shared.GameTicking.Components;
using Content.Shared.Ghost;
using Content.Shared.Hands.Components;
using Content.Shared.Implants.Components;
using Content.Shared.Mobs;
using Content.Shared.Mobs.Components;
using Content.Shared.Overlays;
using Content.Shared.Popups;
using Content.Shared.Store.Components;
using Robust.Shared.Network;

namespace Content.Server._SSS.SuspicionGameRule;

Expand Down Expand Up @@ -64,6 +62,8 @@ private void OnMobStateChanged(EntityUid uid, SuspicionPlayerComponent component
sus.EndAt += TimeSpan.FromSeconds(sus.TimeAddedPerKill);
sus.AnnouncedTimeLeft.Clear();

RaiseNetworkEvent(new SuspicionRuleTimerUpdate(_gameTicker.RoundDuration() + sus.EndAt));

var allTraitors = FindAllOfType(SuspicionRole.Traitor);
// Ok this is fucking horrible
foreach (var traitor in allTraitors)
Expand Down
Loading
Loading