diff --git a/Content.Client/UserInterface/Screens/DefaultGameScreen.xaml b/Content.Client/UserInterface/Screens/DefaultGameScreen.xaml index 54aeffe72c..6199270e05 100644 --- a/Content.Client/UserInterface/Screens/DefaultGameScreen.xaml +++ b/Content.Client/UserInterface/Screens/DefaultGameScreen.xaml @@ -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" @@ -30,4 +31,5 @@ + diff --git a/Content.Client/UserInterface/Screens/DefaultGameScreen.xaml.cs b/Content.Client/UserInterface/Screens/DefaultGameScreen.xaml.cs index 12f8422aeb..c51811e9b7 100644 --- a/Content.Client/UserInterface/Screens/DefaultGameScreen.xaml.cs +++ b/Content.Client/UserInterface/Screens/DefaultGameScreen.xaml.cs @@ -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; diff --git a/Content.Client/UserInterface/Screens/SeparatedChatGameScreen.xaml b/Content.Client/UserInterface/Screens/SeparatedChatGameScreen.xaml index 7f1d1bcd5b..c2d664d113 100644 --- a/Content.Client/UserInterface/Screens/SeparatedChatGameScreen.xaml +++ b/Content.Client/UserInterface/Screens/SeparatedChatGameScreen.xaml @@ -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" @@ -25,6 +26,7 @@ + diff --git a/Content.Client/UserInterface/Screens/SeparatedChatGameScreen.xaml.cs b/Content.Client/UserInterface/Screens/SeparatedChatGameScreen.xaml.cs index e04d377d32..54bc8f5848 100644 --- a/Content.Client/UserInterface/Screens/SeparatedChatGameScreen.xaml.cs +++ b/Content.Client/UserInterface/Screens/SeparatedChatGameScreen.xaml.cs @@ -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)); diff --git a/Content.Client/_SSS/UserInterface/SSSStatusUIController.cs b/Content.Client/_SSS/UserInterface/SSSStatusUIController.cs new file mode 100644 index 0000000000..474e9bc431 --- /dev/null +++ b/Content.Client/_SSS/UserInterface/SSSStatusUIController.cs @@ -0,0 +1,253 @@ +using Content.Client._SSS.UserInterface.Widgets; +using Content.Client.Gameplay; +using Content.Client.GameTicking.Managers; +using Content.Shared._SSS.SuspicionGameRule; +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.Player; +using Robust.Client.UserInterface; +using Robust.Client.UserInterface.Controllers; +using Robust.Shared.Timing; + +namespace Content.Client._SSS.UserInterface; + +public sealed class SSSStatusUIController : UIController, IOnSystemChanged, IOnStateChanged +{ + private ISawmill _log = default!; + + [Dependency] private readonly IPlayerManager _playerManager = default!; + + [UISystemDependency] private readonly MobThresholdSystem? _mobThreshold = default!; + [UISystemDependency] private readonly ClientGameTicker? _clientGameTicker = default!; + + public override void Initialize() + { + base.Initialize(); + + _log = Logger.GetSawmill("StatusUI"); + + SubscribeNetworkEvent(UpdateTimerEnd); + SubscribeNetworkEvent(PreroundStarted); + SubscribeNetworkEvent(UpdateRoleDisplay); + SubscribeNetworkEvent(UpdatePlayerSpawn); + } + + 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(); + + public void UpdateHealth(Entity ent) + { + + if (!EntityManager.TryGetComponent(ent, out var mobState)) + return; + + if (mobState.CurrentState == MobState.Dead) + { + SetHealthBarUI(Loc.GetString("suspicion-status-ui-health-dead"), 0, 100); + return; + } + + if (!EntityManager.TryGetComponent(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); + + SetHealthBar((float)hp, maxHp.Float()); + } + + private void SetHealthBarUI(string text, float value, float maxValue) + { + var ui = StatusUI; + + if (ui == null) + { + _queuedHealth = (text, value, maxValue); + return; + } + + ui.SetHealthBar(text, value, maxValue); + } + + 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.SetHealthBar(text, value, maxValue); + _queuedHealth = null; + + return true; + } + + private void SetHealthBar(float hp, float maxHp) + { + SetHealthBarUI($"\u2665 {hp}", hp, maxHp); + } + + 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) + { + _lastEndTime = ev.EndTime; + } + + public void PreroundStarted(SuspicionRulePreroundStarted ev, EntitySessionEventArgs args) + { + _lastEndTime = ev.PreroundEndTime; + SetRoleToPreround(); + } + + private void SetRoleUI(string role, Color color) + { + var ui = StatusUI; + + if (ui is null) + { + _queuedRole = (role, color); + return; + } + + ui.SetRole(role, color); + } + + private bool SetRoleFromQueued() + { + if (_queuedRole is null) + return false; + + var ui = StatusUI; + if (ui is null) + return false; + + var (role, color) = _queuedRole.Value; + ui.SetRole(role, color); + _queuedRole = null; + + return true; + } + + private void SetRoleToPreround() + { + SetRoleUI(Loc.GetString("suspicion-status-ui-role-preround"), Color.Gray); + } + + private void SetRoleToObserbing() + { + SetRoleUI(Loc.GetString("suspicion-status-ui-role-obserbing"), Color.Gray); + } + + public void UpdateRoleDisplay(SuspicionRuleUpdateRole ev, EntitySessionEventArgs args) + { + var roleName = Loc.GetString(ev.NewRole switch + { + SuspicionRole.Traitor => "roles-antag-suspicion-traitor-name", + SuspicionRole.Detective => "roles-antag-suspicion-detective-name", + SuspicionRole.Innocent => "roles-antag-suspicion-innocent-name", + _ => "roles-antag-suspicion-unknown", + }); + SetRoleUI(roleName, Color.FromName(ev.NewRole.GetRoleColor())); + } + + public void UpdatePlayerSpawn(SuspicionRulePlayerSpawn ev, EntitySessionEventArgs args) + { + if (ev.GameState == SuspicionGameState.Preparing) + { + SetRoleToPreround(); + + if (EntityManager.TryGetComponent(_playerManager.LocalEntity!.Value, out var damagable)) + UpdateHealth((_playerManager.LocalEntity!.Value, damagable)); + } + else + { + SetRoleToObserbing(); + SetHealthBar(0, 100); + } + + _lastEndTime = ev.EndTime; + } + + public void OnSystemLoaded(SSSStatusUISystem system) + { + system.OnPlayerDamageChanged += UpdateHealth; + } + + public void OnSystemUnloaded(SSSStatusUISystem system) + { + system.OnPlayerDamageChanged -= UpdateHealth; + } + + public void OnStateEntered(GameplayState state) + { + if (EntityManager.TryGetComponent(_playerManager.LocalEntity!.Value, out var damagable)) + UpdateHealth((_playerManager.LocalEntity!.Value, damagable)); + else + SetHealthBar(0, 100); + + UpdateTimer(TimeSpan.Zero); + + SetRoleUI("-", Color.Black); + } + + public void OnStateExited(GameplayState state) + { + SetHealthBarUI("-", 0, 100); + + UpdateTimer(TimeSpan.Zero); + + SetRoleUI("-", Color.Black); + } +} diff --git a/Content.Client/_SSS/UserInterface/SSSStatusUISystem.cs b/Content.Client/_SSS/UserInterface/SSSStatusUISystem.cs new file mode 100644 index 0000000000..c54e94b7af --- /dev/null +++ b/Content.Client/_SSS/UserInterface/SSSStatusUISystem.cs @@ -0,0 +1,28 @@ +using Content.Shared.Damage; +using Robust.Shared.Player; + +namespace Content.Client._SSS.UserInterface; + +public sealed partial class SSSStatusUISystem : EntitySystem +{ + [Dependency] private readonly ISharedPlayerManager _playerManager = default!; + + public event Action>? OnPlayerDamageChanged; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnDamageChanged); + } + + private void OnDamageChanged(Entity ent, ref DamageChangedEvent args) + { + var (uid, damagable) = ent; + + if (uid == _playerManager.LocalEntity) + { + OnPlayerDamageChanged?.Invoke(ent); + } + } +} diff --git a/Content.Client/_SSS/UserInterface/Widgets/SSSStatusGui.xaml b/Content.Client/_SSS/UserInterface/Widgets/SSSStatusGui.xaml new file mode 100644 index 0000000000..e7e308d32c --- /dev/null +++ b/Content.Client/_SSS/UserInterface/Widgets/SSSStatusGui.xaml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Content.Client/_SSS/UserInterface/Widgets/SSSStatusGui.xaml.cs b/Content.Client/_SSS/UserInterface/Widgets/SSSStatusGui.xaml.cs new file mode 100644 index 0000000000..e66a8f525e --- /dev/null +++ b/Content.Client/_SSS/UserInterface/Widgets/SSSStatusGui.xaml.cs @@ -0,0 +1,41 @@ +using Content.Client.Resources; +using Robust.Client.AutoGenerated; +using Robust.Client.Graphics; +using Robust.Client.ResourceManagement; +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.XAML; + +namespace Content.Client._SSS.UserInterface.Widgets; + +[GenerateTypedNameReferences] +public sealed partial class SSSStatusGui : UIWidget +{ + private readonly StyleBoxTexture _roleStyleBox; + + public SSSStatusGui() + { + RobustXamlLoader.Load(this); + + var resourceCache = IoCManager.Resolve(); + + var styleBox = new StyleBoxTexture() + { + Texture = resourceCache.GetTexture("/Textures/Interface/Nano/button.svg.96dpi.png"), + }; + styleBox.SetPatchMargin(StyleBox.Margin.All, 10); + _roleStyleBox = styleBox; + } + + public void SetHealthBar(string text, float value, float maxValue) + { + HealthNumber.Text = text; + HealthBar.MaxValue = maxValue; + HealthBar.Value = value; + } + + public void SetRole(string role, Color color) + { + RoleBG.PanelOverride = new StyleBoxTexture(_roleStyleBox) { Modulate = color }; + RoleText.Text = role; + } +} diff --git a/Content.Server/_SSS/SuspicionGameRule/SuspicionRuleSystem.Rules.cs b/Content.Server/_SSS/SuspicionGameRule/SuspicionRuleSystem.Rules.cs index 61796df987..d8ab4a99ed 100644 --- a/Content.Server/_SSS/SuspicionGameRule/SuspicionRuleSystem.Rules.cs +++ b/Content.Server/_SSS/SuspicionGameRule/SuspicionRuleSystem.Rules.cs @@ -1,8 +1,10 @@ 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; +using Content.Shared._SSS.SuspicionGameRule.Components; using Content.Shared.Chat; using Content.Shared.Damage; using Content.Shared.Damage.Prototypes; @@ -11,13 +13,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; @@ -64,6 +63,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) diff --git a/Content.Server/_SSS/SuspicionGameRule/SuspicionRuleSystem.Spawning.cs b/Content.Server/_SSS/SuspicionGameRule/SuspicionRuleSystem.Spawning.cs index 1b7b3952f4..e119dd524a 100644 --- a/Content.Server/_SSS/SuspicionGameRule/SuspicionRuleSystem.Spawning.cs +++ b/Content.Server/_SSS/SuspicionGameRule/SuspicionRuleSystem.Spawning.cs @@ -1,5 +1,4 @@ using System.Linq; -using Content.Server._SSS.SuspicionGameRule.Components; using Content.Server.Administration.Commands; using Content.Server.Atmos.Components; using Content.Server.GameTicking; @@ -9,6 +8,9 @@ using Content.Server.Roles; using Content.Server.Temperature.Components; using Content.Server.Traits.Assorted; +using Content.Shared._SSS; +using Content.Shared._SSS.SuspicionGameRule; +using Content.Shared._SSS.SuspicionGameRule.Components; using Content.Shared.Access; using Content.Shared.Access.Components; using Content.Shared.Atmos.Rotting; @@ -122,6 +124,8 @@ private void StartRound(EntityUid uid, SuspicionRuleComponent component, GameRul Loc.GetString("traitor-briefing"), Color.Red, _traitorStartSound); + + RaiseNetworkEvent(new SuspicionRuleUpdateRole(SuspicionRole.Traitor), ownedEntity.Value); } for (var i = traitorCount; i < traitorCount + detectiveCount; i++) @@ -146,6 +150,7 @@ private void StartRound(EntityUid uid, SuspicionRuleComponent component, GameRul Loc.GetString("detective-briefing"), Color.Blue, briefingSound:null); + RaiseNetworkEvent(new SuspicionRuleUpdateRole(SuspicionRole.Detective), ownedEntity.Value); } // Anyone who isn't a traitor will get the innocent role. @@ -164,9 +169,14 @@ private void StartRound(EntityUid uid, SuspicionRuleComponent component, GameRul Loc.GetString("innocent-briefing"), briefingColor: Color.Green, briefingSound:null); + + RaiseNetworkEvent(new SuspicionRuleUpdateRole(SuspicionRole.Innocent), ownedEntity.Value); } _chatManager.DispatchServerAnnouncement($"The round has started. There are {traitorCount} traitors among us."); + + // SIMYON WHY + RaiseNetworkEvent(new SuspicionRuleTimerUpdate(_gameTicker.RoundDuration() + component.EndAt)); } private void OnBeforeSpawn(PlayerBeforeSpawnEvent ev) @@ -176,6 +186,7 @@ private void OnBeforeSpawn(PlayerBeforeSpawnEvent ev) .Select(p => new ProtoId(p.ID)) .ToArray(); + var query = EntityQueryEnumerator(); while (query.MoveNext(out var uid, out var sus, out var gameRule)) { @@ -188,9 +199,31 @@ private void OnBeforeSpawn(PlayerBeforeSpawnEvent ev) _chatManager.DispatchServerMessage(ev.Player, "Sorry, the game has already started. You have been made an observer."); GameTicker.SpawnObserver(ev.Player); // Players can't join mid-round. ev.Handled = true; + if (sus.GameState == SuspicionGameState.InProgress) + { + RaiseNetworkEvent(new SuspicionRulePlayerSpawn() + { + GameState = SuspicionGameState.InProgress, + EndTime = _gameTicker.RoundDuration() + sus.EndAt, + }, ev.Player); + } + else if (sus.GameState == SuspicionGameState.PostRound) + { + RaiseNetworkEvent(new SuspicionRulePlayerSpawn() + { + GameState = SuspicionGameState.PostRound, + EndTime = TimeSpan.MinValue, + }, ev.Player); + } return; } + RaiseNetworkEvent(new SuspicionRulePlayerSpawn() + { + GameState = SuspicionGameState.Preparing, + EndTime = TimeSpan.FromSeconds(sus.PreparingDuration), + }, ev.Player); + var newMind = _mindSystem.CreateMind(ev.Player.UserId, ev.Profile.Name); _mindSystem.SetUserId(newMind, ev.Player.UserId); diff --git a/Content.Server/_SSS/SuspicionGameRule/SuspicionRuleSystem.Utility.cs b/Content.Server/_SSS/SuspicionGameRule/SuspicionRuleSystem.Utility.cs index c95fea4ee7..5f56d83774 100644 --- a/Content.Server/_SSS/SuspicionGameRule/SuspicionRuleSystem.Utility.cs +++ b/Content.Server/_SSS/SuspicionGameRule/SuspicionRuleSystem.Utility.cs @@ -1,4 +1,4 @@ -using Content.Server._SSS.SuspicionGameRule.Components; +using Content.Shared._SSS.SuspicionGameRule.Components; using Content.Shared.Chat; using Content.Shared.FixedPoint; using Content.Shared.Humanoid; @@ -7,7 +7,6 @@ using Content.Shared.Mind.Components; using Content.Shared.Roles; using Content.Shared.Store.Components; -using Robust.Server.Containers; using Robust.Shared.Map; using Robust.Shared.Physics.Components; diff --git a/Content.Server/_SSS/SuspicionGameRule/SuspicionRuleSystem.cs b/Content.Server/_SSS/SuspicionGameRule/SuspicionRuleSystem.cs index 1fdaa5fd73..cd13d4f57e 100644 --- a/Content.Server/_SSS/SuspicionGameRule/SuspicionRuleSystem.cs +++ b/Content.Server/_SSS/SuspicionGameRule/SuspicionRuleSystem.cs @@ -1,5 +1,4 @@ using System.Linq; -using Content.Server._SSS.SuspicionGameRule.Components; using Content.Server.Access.Systems; using Content.Server.Administration.Systems; using Content.Server.Antag; @@ -17,6 +16,9 @@ using Content.Server.RoundEnd; using Content.Server.Station.Systems; using Content.Server.Store.Systems; +using Content.Shared._SSS; +using Content.Shared._SSS.SuspicionGameRule; +using Content.Shared._SSS.SuspicionGameRule.Components; using Content.Shared.Damage; using Content.Shared.Examine; using Content.Shared.GameTicking.Components; @@ -57,6 +59,7 @@ public sealed partial class SuspicionRuleSystem : GameRuleSystem _chatManager.DispatchServerAnnouncement("The round will start in 5 seconds.")); Timer.Spawn(TimeSpan.FromSeconds(component.PreparingDuration), () => StartRound(uid, component, gameRule)); Log.Debug("Starting a game of Suspicion."); + + RaiseNetworkEvent(new SuspicionRulePreroundStarted(TimeSpan.FromSeconds(component.PreparingDuration))); } public override void Update(float frameTime) diff --git a/Content.Server/_SSS/SuspicionRadarSystem.cs b/Content.Server/_SSS/SuspicionRadarSystem.cs index 33709b0737..095b08ed7e 100644 --- a/Content.Server/_SSS/SuspicionRadarSystem.cs +++ b/Content.Server/_SSS/SuspicionRadarSystem.cs @@ -1,7 +1,8 @@ -using Content.Server._SSS.SuspicionGameRule.Components; -using Content.Server.Mind; +using Content.Server.Mind; using Content.Server.Roles; +using Content.Shared._SSS; using Content.Shared._SSS.RadarOverlay; +using Content.Shared._SSS.SuspicionGameRule.Components; using Content.Shared.Implants.Components; using Content.Shared.Mobs; using Content.Shared.Mobs.Systems; diff --git a/Content.Server/_SSS/SuspicionGameRule/Components/SuspicionRadarComponent.cs b/Content.Shared/_SSS/SuspicionGameRule/Components/SuspicionRadarComponent.cs similarity index 71% rename from Content.Server/_SSS/SuspicionGameRule/Components/SuspicionRadarComponent.cs rename to Content.Shared/_SSS/SuspicionGameRule/Components/SuspicionRadarComponent.cs index ab54b20b35..7ea237d4a0 100644 --- a/Content.Server/_SSS/SuspicionGameRule/Components/SuspicionRadarComponent.cs +++ b/Content.Shared/_SSS/SuspicionGameRule/Components/SuspicionRadarComponent.cs @@ -1,4 +1,4 @@ -namespace Content.Server._SSS.SuspicionGameRule.Components; +namespace Content.Shared._SSS.SuspicionGameRule.Components; [RegisterComponent] public sealed partial class SuspicionRadarComponent : Component diff --git a/Content.Server/_SSS/SuspicionGameRule/Components/SuspicionRoleComponent.cs b/Content.Shared/_SSS/SuspicionGameRule/Components/SuspicionRoleComponent.cs similarity index 83% rename from Content.Server/_SSS/SuspicionGameRule/Components/SuspicionRoleComponent.cs rename to Content.Shared/_SSS/SuspicionGameRule/Components/SuspicionRoleComponent.cs index 39290aa13c..fb6d4ce15a 100644 --- a/Content.Server/_SSS/SuspicionGameRule/Components/SuspicionRoleComponent.cs +++ b/Content.Shared/_SSS/SuspicionGameRule/Components/SuspicionRoleComponent.cs @@ -1,6 +1,7 @@ using Content.Shared.Roles; +using Robust.Shared.Serialization; -namespace Content.Server._SSS.SuspicionGameRule.Components; +namespace Content.Shared._SSS.SuspicionGameRule.Components; [RegisterComponent] public sealed partial class SuspicionRoleComponent : BaseMindRoleComponent @@ -23,6 +24,7 @@ public static string GetRoleColor(this SuspicionRole role) } } +[Serializable, NetSerializable] public enum SuspicionRole { Pending, diff --git a/Content.Server/_SSS/SuspicionGameRule/Components/SuspicionRuleComponent.cs b/Content.Shared/_SSS/SuspicionGameRule/Components/SuspicionRuleComponent.cs similarity index 95% rename from Content.Server/_SSS/SuspicionGameRule/Components/SuspicionRuleComponent.cs rename to Content.Shared/_SSS/SuspicionGameRule/Components/SuspicionRuleComponent.cs index 4cf80242a1..4b7267213e 100644 --- a/Content.Server/_SSS/SuspicionGameRule/Components/SuspicionRuleComponent.cs +++ b/Content.Shared/_SSS/SuspicionGameRule/Components/SuspicionRuleComponent.cs @@ -1,13 +1,12 @@ using Content.Shared.NPC.Prototypes; -using Content.Shared.Radio; using Content.Shared.Roles; -using Robust.Shared.Map; using Robust.Shared.Prototypes; +using Robust.Shared.Serialization; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; -namespace Content.Server._SSS.SuspicionGameRule.Components; +namespace Content.Shared._SSS.SuspicionGameRule.Components; -[RegisterComponent, Access(typeof(SuspicionRuleSystem))] +[RegisterComponent] public sealed partial class SuspicionRuleComponent : Component { #region State management diff --git a/Content.Shared/_SSS/SuspicionGameRule/SuspicionRuleEvents.cs b/Content.Shared/_SSS/SuspicionGameRule/SuspicionRuleEvents.cs new file mode 100644 index 0000000000..dba69bbf74 --- /dev/null +++ b/Content.Shared/_SSS/SuspicionGameRule/SuspicionRuleEvents.cs @@ -0,0 +1,30 @@ +using Content.Shared._SSS.SuspicionGameRule.Components; +using Robust.Shared.Serialization; + +namespace Content.Shared._SSS.SuspicionGameRule; + + +[Serializable, NetSerializable] +public sealed class SuspicionRuleTimerUpdate(TimeSpan endTime) : EntityEventArgs +{ + public TimeSpan EndTime = endTime; +} + +[Serializable, NetSerializable] +public sealed class SuspicionRulePreroundStarted(TimeSpan preroundEndTime) : EntityEventArgs +{ + public TimeSpan PreroundEndTime = preroundEndTime; +} + +[Serializable, NetSerializable] +public sealed class SuspicionRuleUpdateRole(SuspicionRole newRole) : EntityEventArgs +{ + public readonly SuspicionRole NewRole = newRole; +} + +[Serializable, NetSerializable] +public sealed class SuspicionRulePlayerSpawn : EntityEventArgs +{ + public SuspicionGameState GameState; + public TimeSpan EndTime; +} diff --git a/Content.Server/_SSS/SuspicionGameRule/Components/SuspicionPlayerComponent.cs b/Content.Shared/_SSS/SuspicionPlayerComponent.cs similarity index 95% rename from Content.Server/_SSS/SuspicionGameRule/Components/SuspicionPlayerComponent.cs rename to Content.Shared/_SSS/SuspicionPlayerComponent.cs index aaf87622b1..c98b262997 100644 --- a/Content.Server/_SSS/SuspicionGameRule/Components/SuspicionPlayerComponent.cs +++ b/Content.Shared/_SSS/SuspicionPlayerComponent.cs @@ -1,4 +1,4 @@ -namespace Content.Server._SSS; +namespace Content.Shared._SSS; /// /// Main component that marks a player "active" in a round of SSS. diff --git a/Resources/Locale/en-US/_SSS/suspicion.ftl b/Resources/Locale/en-US/_SSS/suspicion.ftl index 87fc82ad75..f8337cf629 100644 --- a/Resources/Locale/en-US/_SSS/suspicion.ftl +++ b/Resources/Locale/en-US/_SSS/suspicion.ftl @@ -14,3 +14,9 @@ roles-antag-suspicion-pending-name = Pending roles-antag-suspicion-pending-objective = The game is still starting, wait for your role to be assigned. roles-antag-suspicion-detective-name = Detective roles-antag-suspicion-detective-objective = Discover and eliminate all traitors with your special tools. + +roles-antag-suspicion-unknown = Unknown + +suspicion-status-ui-health-dead = DEAD +suspicion-status-ui-role-obserbing = Obserbing +suspicion-status-ui-role-preround = Preround