From 548ef3dedb182108404f25df262378002084b1c2 Mon Sep 17 00:00:00 2001 From: DrSmugleaf Date: Thu, 27 Aug 2020 16:39:29 +0200 Subject: [PATCH] Add HUD button that displays your SSS role and allies (#1895) * Add button that displays your SSS role and allies * Capitalize button name * Add cases for 0, 1 and invalid number of allies * Make the ally syncing system saner --- .../Components/Items/HandsComponent.cs | 4 +- .../Suspicion/SuspicionRoleComponent.cs | 109 ++++++++++ Content.Client/UserInterface/GameHud.cs | 13 ++ .../UserInterface/Suspicion/SuspicionGui.cs | 116 ++++++++++ .../Suspicion/SuspicionRoleComponent.cs | 202 +++++++++++++++++- .../EntitySystems/SuspicionRoleSystem.cs | 51 +++++ .../GamePresets/PresetSuspicion.cs | 3 +- .../GameTicking/GameRules/RuleSuspicion.cs | 1 + Content.Server/Mobs/Mind.cs | 14 +- Content.Server/Mobs/Roles/RoleAddedMessage.cs | 7 + Content.Server/Mobs/Roles/RoleMessage.cs | 14 ++ .../Mobs/Roles/RoleRemovedMessage.cs | 7 + .../{ => Suspicion}/SuspicionInnocentRole.cs | 4 +- .../Mobs/Roles/Suspicion/SuspicionRole.cs | 7 + .../{ => Suspicion}/SuspicionTraitorRole.cs | 3 +- .../Suspicion/SharedSuspicionRoleComponent.cs | 75 +++++++ Content.Shared/GameObjects/ContentNetIDs.cs | 1 + 17 files changed, 616 insertions(+), 15 deletions(-) create mode 100644 Content.Client/GameObjects/Components/Suspicion/SuspicionRoleComponent.cs create mode 100644 Content.Client/UserInterface/Suspicion/SuspicionGui.cs create mode 100644 Content.Server/GameObjects/EntitySystems/SuspicionRoleSystem.cs create mode 100644 Content.Server/Mobs/Roles/RoleAddedMessage.cs create mode 100644 Content.Server/Mobs/Roles/RoleMessage.cs create mode 100644 Content.Server/Mobs/Roles/RoleRemovedMessage.cs rename Content.Server/Mobs/Roles/{ => Suspicion}/SuspicionInnocentRole.cs (89%) create mode 100644 Content.Server/Mobs/Roles/Suspicion/SuspicionRole.cs rename Content.Server/Mobs/Roles/{ => Suspicion}/SuspicionTraitorRole.cs (94%) create mode 100644 Content.Shared/GameObjects/Components/Suspicion/SharedSuspicionRoleComponent.cs diff --git a/Content.Client/GameObjects/Components/Items/HandsComponent.cs b/Content.Client/GameObjects/Components/Items/HandsComponent.cs index 4a11eeb584..2750547ad3 100644 --- a/Content.Client/GameObjects/Components/Items/HandsComponent.cs +++ b/Content.Client/GameObjects/Components/Items/HandsComponent.cs @@ -17,10 +17,10 @@ namespace Content.Client.GameObjects.Components.Items [ComponentReference(typeof(ISharedHandsComponent))] public class HandsComponent : SharedHandsComponent { - private HandsGui? _gui; - [Dependency] private readonly IGameHud _gameHud = default!; + private HandsGui? _gui; + /// private readonly List _hands = new List(); diff --git a/Content.Client/GameObjects/Components/Suspicion/SuspicionRoleComponent.cs b/Content.Client/GameObjects/Components/Suspicion/SuspicionRoleComponent.cs new file mode 100644 index 0000000000..82cf727f90 --- /dev/null +++ b/Content.Client/GameObjects/Components/Suspicion/SuspicionRoleComponent.cs @@ -0,0 +1,109 @@ +#nullable enable +using System.Collections.Generic; +using System.Linq; +using Content.Client.UserInterface; +using Content.Client.UserInterface.Suspicion; +using Content.Shared.GameObjects.Components.Suspicion; +using Robust.Client.GameObjects; +using Robust.Shared.GameObjects; +using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.Interfaces.Network; +using Robust.Shared.IoC; +using Robust.Shared.Players; + +namespace Content.Client.GameObjects.Components.Suspicion +{ + [RegisterComponent] + public class SuspicionRoleComponent : SharedSuspicionRoleComponent + { + [Dependency] private readonly IGameHud _gameHud = default!; + [Dependency] private readonly IEntityManager _entityManager = default!; + + private SuspicionGui? _gui; + private string? _role; + private bool? _antagonist; + + public string? Role + { + get => _role; + set + { + _role = value; + _gui?.UpdateLabel(); + Dirty(); + } + } + + public bool? Antagonist + { + get => _antagonist; + set + { + _antagonist = value; + _gui?.UpdateLabel(); + Dirty(); + } + } + + public HashSet Allies { get; } = new HashSet(); + + public override void HandleComponentState(ComponentState? curState, ComponentState? nextState) + { + base.HandleComponentState(curState, nextState); + + if (!(curState is SuspicionRoleComponentState state)) + { + return; + } + + _role = state.Role; + _antagonist = state.Antagonist; + } + + public override void HandleMessage(ComponentMessage message, IComponent? component) + { + base.HandleMessage(message, component); + + switch (message) + { + case PlayerAttachedMsg _: + if (_gui == null) + { + _gui = new SuspicionGui(); + } + else + { + _gui.Parent?.RemoveChild(_gui); + } + + _gameHud.SuspicionContainer.AddChild(_gui); + _gui.UpdateLabel(); + + break; + case PlayerDetachedMsg _: + _gui?.Parent?.RemoveChild(_gui); + break; + } + } + + public override void HandleNetworkMessage(ComponentMessage message, INetChannel netChannel, ICommonSession? session = null) + { + base.HandleNetworkMessage(message, netChannel, session); + + switch (message) + { + case SuspicionAlliesMessage msg: + Allies.Clear(); + Allies.UnionWith(msg.Allies.Select(_entityManager.GetEntity)); + break; + } + } + + public override void OnRemove() + { + base.OnRemove(); + + _gui?.Dispose(); + } + } +} diff --git a/Content.Client/UserInterface/GameHud.cs b/Content.Client/UserInterface/GameHud.cs index ced6e8a15b..51ed48c2ad 100644 --- a/Content.Client/UserInterface/GameHud.cs +++ b/Content.Client/UserInterface/GameHud.cs @@ -47,6 +47,7 @@ namespace Content.Client.UserInterface Action SandboxButtonToggled { get; set; } Control HandsContainer { get; } + Control SuspicionContainer { get; } Control InventoryQuickButtonContainer { get; } bool CombatPanelVisible { get; set; } @@ -79,6 +80,7 @@ namespace Content.Client.UserInterface [Dependency] private readonly IInputManager _inputManager = default!; public Control HandsContainer { get; private set; } + public Control SuspicionContainer { get; private set; } public Control InventoryQuickButtonContainer { get; private set; } public bool CombatPanelVisible @@ -242,6 +244,17 @@ namespace Content.Client.UserInterface LayoutContainer.SetAnchorAndMarginPreset(HandsContainer, LayoutContainer.LayoutPreset.CenterBottom); LayoutContainer.SetGrowHorizontal(HandsContainer, LayoutContainer.GrowDirection.Both); LayoutContainer.SetGrowVertical(HandsContainer, LayoutContainer.GrowDirection.Begin); + + SuspicionContainer = new MarginContainer + { + SizeFlagsHorizontal = Control.SizeFlags.ShrinkCenter + }; + + RootControl.AddChild(SuspicionContainer); + + LayoutContainer.SetAnchorAndMarginPreset(SuspicionContainer, LayoutContainer.LayoutPreset.BottomLeft, margin: 10); + LayoutContainer.SetGrowHorizontal(SuspicionContainer, LayoutContainer.GrowDirection.End); + LayoutContainer.SetGrowVertical(SuspicionContainer, LayoutContainer.GrowDirection.Begin); } private void ButtonTutorialOnOnToggled() diff --git a/Content.Client/UserInterface/Suspicion/SuspicionGui.cs b/Content.Client/UserInterface/Suspicion/SuspicionGui.cs new file mode 100644 index 0000000000..e466eb8074 --- /dev/null +++ b/Content.Client/UserInterface/Suspicion/SuspicionGui.cs @@ -0,0 +1,116 @@ +using System; +using System.Globalization; +using Content.Client.GameObjects.Components.Suspicion; +using Content.Shared.Interfaces; +using Robust.Client.Player; +using Robust.Client.UserInterface; +using Robust.Client.UserInterface.Controls; +using Robust.Shared.IoC; +using Robust.Shared.Localization; +using Robust.Shared.Maths; +using Robust.Shared.Timing; +using static Robust.Client.UserInterface.Controls.BaseButton; + +namespace Content.Client.UserInterface.Suspicion +{ + public class SuspicionGui : Control + { +#pragma warning disable 0649 + [Dependency] private readonly IPlayerManager _playerManager; +#pragma warning restore 0649 + + private readonly VBoxContainer _container; + private readonly Button _roleButton; + + private string _previousRoleName; + private bool _previousAntagonist; + + public SuspicionGui() + { + IoCManager.InjectDependencies(this); + + AddChild(_container = new VBoxContainer + { + SeparationOverride = 0, + Children = + { + (_roleButton = new Button + { + Name = "Suspicion Role Button" + }) + } + }); + + _roleButton.CustomMinimumSize = (200, 60); + _roleButton.OnPressed += RoleButtonPressed; + } + + private void RoleButtonPressed(ButtonEventArgs obj) + { + if (!TryGetComponent(out var role)) + { + return; + } + + if (!role.Antagonist ?? false) + { + return; + } + + var allies = string.Join(", ", role.Allies); + var message = role.Allies.Count switch + { + 0 => Loc.GetString("You have no allies"), + 1 => Loc.GetString("Your ally is {0}", allies), + var n when n > 2 => Loc.GetString("Your allies are {0}", allies), + _ => throw new ArgumentException($"Invalid number of allies: {role.Allies.Count}") + }; + + role.Owner.PopupMessage(role.Owner, message); + } + + private bool TryGetComponent(out SuspicionRoleComponent suspicion) + { + suspicion = default; + + return _playerManager?.LocalPlayer?.ControlledEntity?.TryGetComponent(out suspicion) == true; + } + + public void UpdateLabel() + { + if (!TryGetComponent(out var suspicion)) + { + Visible = false; + return; + } + + if (suspicion.Role == null || suspicion.Antagonist == null) + { + Visible = false; + return; + } + + if (_previousRoleName == suspicion.Role && _previousAntagonist == suspicion.Antagonist) + { + return; + } + + _previousRoleName = suspicion.Role; + _previousAntagonist = suspicion.Antagonist.Value; + + var buttonText = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(_previousRoleName); + buttonText = Loc.GetString(buttonText); + + _roleButton.Text = buttonText; + _roleButton.ModulateSelfOverride = _previousAntagonist ? Color.Red : Color.Green; + + Visible = true; + } + + protected override void FrameUpdate(FrameEventArgs args) + { + base.FrameUpdate(args); + UpdateLabel(); + } + } +} diff --git a/Content.Server/GameObjects/Components/Suspicion/SuspicionRoleComponent.cs b/Content.Server/GameObjects/Components/Suspicion/SuspicionRoleComponent.cs index d982130afa..70071bc28b 100644 --- a/Content.Server/GameObjects/Components/Suspicion/SuspicionRoleComponent.cs +++ b/Content.Server/GameObjects/Components/Suspicion/SuspicionRoleComponent.cs @@ -1,31 +1,185 @@ -using Content.Server.GameObjects.Components.Mobs; +#nullable enable +using System.Collections.Generic; +using System.Linq; +using Content.Server.GameObjects.Components.Mobs; +using Content.Server.GameObjects.EntitySystems; +using Content.Server.Mobs; using Content.Server.Mobs.Roles; +using Content.Server.Mobs.Roles.Suspicion; using Content.Shared.GameObjects.Components.Damage; +using Content.Shared.GameObjects.Components.Suspicion; using Content.Shared.GameObjects.EntitySystems; +using Robust.Server.GameObjects; +using Robust.Server.Interfaces.GameObjects; using Robust.Shared.GameObjects; +using Robust.Shared.GameObjects.Systems; +using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Localization; using Robust.Shared.Utility; +using Robust.Shared.ViewVariables; namespace Content.Server.GameObjects.Components.Suspicion { [RegisterComponent] - public class SuspicionRoleComponent : Component, IExamine + public class SuspicionRoleComponent : SharedSuspicionRoleComponent, IExamine { - public override string Name => "SuspicionRole"; + private Role? _role; + private readonly HashSet _allies = new HashSet(); + + [ViewVariables] + public Role? Role + { + get => _role; + set + { + if (_role == value) + { + return; + } + + _role = value; + + Dirty(); + + var suspicionRoleSystem = EntitySystem.Get(); + + if (value == null || !value.Antagonist) + { + ClearAllies(); + suspicionRoleSystem.RemoveTraitor(this); + } + else if (value.Antagonist) + { + SetAllies(suspicionRoleSystem.Traitors); + suspicionRoleSystem.AddTraitor(this); + } + } + } + + [ViewVariables] public bool KnowsAllies => IsTraitor(); public bool IsDead() { - return Owner.TryGetComponent(out IDamageableComponent damageable) && + return Owner.TryGetComponent(out IDamageableComponent? damageable) && damageable.CurrentDamageState == DamageState.Dead; } + public bool IsInnocent() + { + return Owner.TryGetComponent(out MindComponent? mind) && + mind.HasMind && + mind.Mind!.HasRole(); + } + public bool IsTraitor() { - return Owner.TryGetComponent(out MindComponent mind) && + return Owner.TryGetComponent(out MindComponent? mind) && mind.HasMind && mind.Mind!.HasRole(); } + public void SyncRoles() + { + if (!Owner.TryGetComponent(out MindComponent? mind) || + !mind.HasMind) + { + return; + } + + Role = mind.Mind!.AllRoles.First(role => role is SuspicionRole); + } + + public void AddAlly(SuspicionRoleComponent ally) + { + if (ally == this) + { + return; + } + + _allies.Add(ally); + + if (KnowsAllies && Owner.TryGetComponent(out IActorComponent? actor)) + { + var channel = actor.playerSession.ConnectedClient; + DebugTools.AssertNotNull(channel); + + var message = new SuspicionAllyAddedMessage(ally.Owner.Uid); + + SendNetworkMessage(message, channel); + } + } + + public bool RemoveAlly(SuspicionRoleComponent ally) + { + if (ally == this) + { + return false; + } + + if (_allies.Remove(ally)) + { + if (KnowsAllies && Owner.TryGetComponent(out IActorComponent? actor)) + { + var channel = actor.playerSession.ConnectedClient; + DebugTools.AssertNotNull(channel); + + var message = new SuspicionAllyRemovedMessage(ally.Owner.Uid); + + SendNetworkMessage(message, channel); + } + + return true; + } + + return false; + } + + public void SetAllies(IEnumerable allies) + { + _allies.Clear(); + + foreach (var ally in allies) + { + if (ally == this) + { + continue; + } + + _allies.Add(ally); + } + + if (!KnowsAllies || + !Owner.TryGetComponent(out IActorComponent? actor)) + { + return; + } + + var channel = actor.playerSession.ConnectedClient; + DebugTools.AssertNotNull(channel); + + var message = new SuspicionAlliesMessage(_allies.Select(role => role.Owner.Uid)); + + SendNetworkMessage(message, channel); + } + + public void ClearAllies() + { + _allies.Clear(); + + if (!KnowsAllies || + !Owner.TryGetComponent(out IActorComponent? actor)) + { + return; + } + + var channel = actor.playerSession.ConnectedClient; + DebugTools.AssertNotNull(channel); + + var message = new SuspicionAlliesClearedMessage(); + + SendNetworkMessage(message, channel); + } + void IExamine.Examine(FormattedMessage message, bool inDetailsRange) { if (!IsDead()) @@ -39,5 +193,43 @@ namespace Content.Server.GameObjects.Components.Suspicion message.AddMarkup(tooltip); } + + public override void OnRemove() + { + Role = null; + base.OnRemove(); + } + + public override ComponentState GetComponentState() + { + return Role == null + ? new SuspicionRoleComponentState(null, null) + : new SuspicionRoleComponentState(Role?.Name, Role?.Antagonist); + } + + public override void HandleMessage(ComponentMessage message, IComponent? component) + { + base.HandleMessage(message, component); + + if (!(message is RoleMessage msg) || + !(msg.Role is SuspicionRole role)) + { + return; + } + + switch (message) + { + case PlayerAttachedMsg _: + case PlayerDetachedMsg _: + SyncRoles(); + break; + case RoleAddedMessage _: + Role = role; + break; + case RoleRemovedMessage _: + Role = null; + break; + } + } } } diff --git a/Content.Server/GameObjects/EntitySystems/SuspicionRoleSystem.cs b/Content.Server/GameObjects/EntitySystems/SuspicionRoleSystem.cs new file mode 100644 index 0000000000..936fe24185 --- /dev/null +++ b/Content.Server/GameObjects/EntitySystems/SuspicionRoleSystem.cs @@ -0,0 +1,51 @@ +using System.Collections.Generic; +using Content.Server.GameObjects.Components.Suspicion; +using JetBrains.Annotations; +using Robust.Shared.GameObjects.Systems; + +namespace Content.Server.GameObjects.EntitySystems +{ + [UsedImplicitly] + public class SuspicionRoleSystem : EntitySystem + { + private readonly HashSet _traitors = new HashSet(); + + public IReadOnlyCollection Traitors => _traitors; + + public void AddTraitor(SuspicionRoleComponent role) + { + if (!_traitors.Add(role)) + { + return; + } + + foreach (var traitor in _traitors) + { + traitor.AddAlly(role); + } + + role.SetAllies(_traitors); + } + + public void RemoveTraitor(SuspicionRoleComponent role) + { + if (!_traitors.Remove(role)) + { + return; + } + + foreach (var traitor in _traitors) + { + traitor.RemoveAlly(role); + } + + role.ClearAllies(); + } + + public override void Shutdown() + { + _traitors.Clear(); + base.Shutdown(); + } + } +} diff --git a/Content.Server/GameTicking/GamePresets/PresetSuspicion.cs b/Content.Server/GameTicking/GamePresets/PresetSuspicion.cs index 81eeb43d22..eb192dbea6 100644 --- a/Content.Server/GameTicking/GamePresets/PresetSuspicion.cs +++ b/Content.Server/GameTicking/GamePresets/PresetSuspicion.cs @@ -1,7 +1,6 @@ using Content.Server.GameTicking.GameRules; using Content.Server.Interfaces.Chat; using Content.Server.Interfaces.GameTicking; -using Content.Server.Mobs.Roles; using Content.Server.Players; using Robust.Server.Interfaces.Player; using Robust.Shared.Interfaces.Random; @@ -11,6 +10,8 @@ using Robust.Shared.Random; using System.Collections.Generic; using System.Linq; using Content.Server.GameObjects.Components.Suspicion; +using Content.Server.Mobs.Roles; +using Content.Server.Mobs.Roles.Suspicion; using Content.Shared.Roles; using Robust.Shared.GameObjects; using Robust.Shared.Interfaces.Configuration; diff --git a/Content.Server/GameTicking/GameRules/RuleSuspicion.cs b/Content.Server/GameTicking/GameRules/RuleSuspicion.cs index b67888d6f0..0161ab409a 100644 --- a/Content.Server/GameTicking/GameRules/RuleSuspicion.cs +++ b/Content.Server/GameTicking/GameRules/RuleSuspicion.cs @@ -5,6 +5,7 @@ using Content.Server.GameObjects.EntitySystems; using Content.Server.Interfaces.Chat; using Content.Server.Interfaces.GameTicking; using Content.Server.Mobs.Roles; +using Content.Server.Mobs.Roles.Suspicion; using Content.Server.Players; using Content.Shared.GameObjects.Components.Damage; using Robust.Server.GameObjects.EntitySystems; diff --git a/Content.Server/Mobs/Mind.cs b/Content.Server/Mobs/Mind.cs index b0247fc202..1fc6e5f71c 100644 --- a/Content.Server/Mobs/Mind.cs +++ b/Content.Server/Mobs/Mind.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using Content.Server.GameObjects.Components.Mobs; +using Content.Server.Mobs.Roles; using Content.Server.Players; using Robust.Server.Interfaces.GameObjects; using Robust.Server.Interfaces.Player; @@ -95,7 +96,7 @@ namespace Content.Server.Mobs /// /// Gives this mind a new role. /// - /// The type of the role to give. + /// The type of the role to give. /// The instance of the role. /// /// Thrown if we already have a role with this type. @@ -109,13 +110,17 @@ namespace Content.Server.Mobs _roles.Add(role); role.Greet(); + + var message = new RoleAddedMessage(role); + OwnedEntity?.SendMessage(OwnedMob, message); + return role; } /// /// Removes a role from this mind. /// - /// The type of the role to remove. + /// The type of the role to remove. /// /// Thrown if we do not have this role. /// @@ -126,9 +131,10 @@ namespace Content.Server.Mobs throw new ArgumentException($"We do not have this role: {role}"); } - // This can definitely get more complex removal hooks later, - // when we need it. _roles.Remove(role); + + var message = new RoleRemovedMessage(role); + OwnedEntity?.SendMessage(OwnedMob, message); } public bool HasRole() where T : Role diff --git a/Content.Server/Mobs/Roles/RoleAddedMessage.cs b/Content.Server/Mobs/Roles/RoleAddedMessage.cs new file mode 100644 index 0000000000..c4de66e333 --- /dev/null +++ b/Content.Server/Mobs/Roles/RoleAddedMessage.cs @@ -0,0 +1,7 @@ +namespace Content.Server.Mobs.Roles +{ + public class RoleAddedMessage : RoleMessage + { + public RoleAddedMessage(Role role) : base(role) { } + } +} diff --git a/Content.Server/Mobs/Roles/RoleMessage.cs b/Content.Server/Mobs/Roles/RoleMessage.cs new file mode 100644 index 0000000000..1a4489ddc7 --- /dev/null +++ b/Content.Server/Mobs/Roles/RoleMessage.cs @@ -0,0 +1,14 @@ +using Robust.Shared.GameObjects; + +namespace Content.Server.Mobs.Roles +{ + public class RoleMessage : ComponentMessage + { + public readonly Role Role; + + public RoleMessage(Role role) + { + Role = role; + } + } +} diff --git a/Content.Server/Mobs/Roles/RoleRemovedMessage.cs b/Content.Server/Mobs/Roles/RoleRemovedMessage.cs new file mode 100644 index 0000000000..0e8cd0ef85 --- /dev/null +++ b/Content.Server/Mobs/Roles/RoleRemovedMessage.cs @@ -0,0 +1,7 @@ +namespace Content.Server.Mobs.Roles +{ + public class RoleRemovedMessage : RoleMessage + { + public RoleRemovedMessage(Role role) : base(role) { } + } +} diff --git a/Content.Server/Mobs/Roles/SuspicionInnocentRole.cs b/Content.Server/Mobs/Roles/Suspicion/SuspicionInnocentRole.cs similarity index 89% rename from Content.Server/Mobs/Roles/SuspicionInnocentRole.cs rename to Content.Server/Mobs/Roles/Suspicion/SuspicionInnocentRole.cs index 570e307c79..0fab5b7059 100644 --- a/Content.Server/Mobs/Roles/SuspicionInnocentRole.cs +++ b/Content.Server/Mobs/Roles/Suspicion/SuspicionInnocentRole.cs @@ -2,9 +2,9 @@ using Content.Server.Interfaces.Chat; using Content.Shared.Roles; using Robust.Shared.IoC; -namespace Content.Server.Mobs.Roles +namespace Content.Server.Mobs.Roles.Suspicion { - public class SuspicionInnocentRole : Role + public class SuspicionInnocentRole : SuspicionRole { public AntagPrototype Prototype { get; } diff --git a/Content.Server/Mobs/Roles/Suspicion/SuspicionRole.cs b/Content.Server/Mobs/Roles/Suspicion/SuspicionRole.cs new file mode 100644 index 0000000000..f9b46aecd3 --- /dev/null +++ b/Content.Server/Mobs/Roles/Suspicion/SuspicionRole.cs @@ -0,0 +1,7 @@ +namespace Content.Server.Mobs.Roles.Suspicion +{ + public abstract class SuspicionRole : Role + { + protected SuspicionRole(Mind mind) : base(mind) { } + } +} diff --git a/Content.Server/Mobs/Roles/SuspicionTraitorRole.cs b/Content.Server/Mobs/Roles/Suspicion/SuspicionTraitorRole.cs similarity index 94% rename from Content.Server/Mobs/Roles/SuspicionTraitorRole.cs rename to Content.Server/Mobs/Roles/Suspicion/SuspicionTraitorRole.cs index f10bf273e8..d265bb23bf 100644 --- a/Content.Server/Mobs/Roles/SuspicionTraitorRole.cs +++ b/Content.Server/Mobs/Roles/Suspicion/SuspicionTraitorRole.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Linq; using Content.Server.Interfaces.Chat; +using Content.Server.Mobs.Roles.Suspicion; using Content.Shared.Roles; using Robust.Server.GameObjects.EntitySystems; using Robust.Shared.Audio; @@ -9,7 +10,7 @@ using Robust.Shared.Localization; namespace Content.Server.Mobs.Roles { - public sealed class SuspicionTraitorRole : Role + public sealed class SuspicionTraitorRole : SuspicionRole { public AntagPrototype Prototype { get; } diff --git a/Content.Shared/GameObjects/Components/Suspicion/SharedSuspicionRoleComponent.cs b/Content.Shared/GameObjects/Components/Suspicion/SharedSuspicionRoleComponent.cs new file mode 100644 index 0000000000..c31e2e7cce --- /dev/null +++ b/Content.Shared/GameObjects/Components/Suspicion/SharedSuspicionRoleComponent.cs @@ -0,0 +1,75 @@ +#nullable enable +using System; +using System.Collections.Generic; +using System.Linq; +using Robust.Shared.GameObjects; +using Robust.Shared.Serialization; + +namespace Content.Shared.GameObjects.Components.Suspicion +{ + public abstract class SharedSuspicionRoleComponent : Component + { + public sealed override string Name => "SuspicionRole"; + public sealed override uint? NetID => ContentNetIDs.SUSPICION_ROLE; + } + + [Serializable, NetSerializable] + public class SuspicionRoleComponentState : ComponentState + { + public readonly string? Role; + public readonly bool? Antagonist; + + public SuspicionRoleComponentState(string? role, bool? antagonist) : base(ContentNetIDs.SUSPICION_ROLE) + { + Role = role; + Antagonist = antagonist; + } + } + + [Serializable, NetSerializable] + public class SuspicionAlliesMessage : ComponentMessage + { + public readonly HashSet Allies; + + public SuspicionAlliesMessage(HashSet allies) + { + Directed = true; + Allies = allies; + } + + public SuspicionAlliesMessage(IEnumerable allies) : this(allies.ToHashSet()) { } + } + + [Serializable, NetSerializable] + public class SuspicionAllyAddedMessage : ComponentMessage + { + public readonly EntityUid Ally; + + public SuspicionAllyAddedMessage(EntityUid ally) + { + Directed = true; + Ally = ally; + } + } + + [Serializable, NetSerializable] + public class SuspicionAllyRemovedMessage : ComponentMessage + { + public readonly EntityUid Ally; + + public SuspicionAllyRemovedMessage(EntityUid ally) + { + Directed = true; + Ally = ally; + } + } + + [Serializable, NetSerializable] + public class SuspicionAlliesClearedMessage : ComponentMessage + { + public SuspicionAlliesClearedMessage() + { + Directed = true; + } + } +} diff --git a/Content.Shared/GameObjects/ContentNetIDs.cs b/Content.Shared/GameObjects/ContentNetIDs.cs index 32ede76f3d..3f127c68c4 100644 --- a/Content.Shared/GameObjects/ContentNetIDs.cs +++ b/Content.Shared/GameObjects/ContentNetIDs.cs @@ -71,6 +71,7 @@ public const uint CUFFED = 1065; public const uint HANDCUFFS = 1066; public const uint BATTERY_BARREL = 1067; + public const uint SUSPICION_ROLE = 1068; // Net IDs for integration tests. public const uint PREDICTION_TEST = 10001;