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
This commit is contained in:
@@ -17,10 +17,10 @@ namespace Content.Client.GameObjects.Components.Items
|
|||||||
[ComponentReference(typeof(ISharedHandsComponent))]
|
[ComponentReference(typeof(ISharedHandsComponent))]
|
||||||
public class HandsComponent : SharedHandsComponent
|
public class HandsComponent : SharedHandsComponent
|
||||||
{
|
{
|
||||||
private HandsGui? _gui;
|
|
||||||
|
|
||||||
[Dependency] private readonly IGameHud _gameHud = default!;
|
[Dependency] private readonly IGameHud _gameHud = default!;
|
||||||
|
|
||||||
|
private HandsGui? _gui;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
private readonly List<Hand> _hands = new List<Hand>();
|
private readonly List<Hand> _hands = new List<Hand>();
|
||||||
|
|
||||||
|
|||||||
@@ -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<IEntity> Allies { get; } = new HashSet<IEntity>();
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -47,6 +47,7 @@ namespace Content.Client.UserInterface
|
|||||||
Action<bool> SandboxButtonToggled { get; set; }
|
Action<bool> SandboxButtonToggled { get; set; }
|
||||||
|
|
||||||
Control HandsContainer { get; }
|
Control HandsContainer { get; }
|
||||||
|
Control SuspicionContainer { get; }
|
||||||
Control InventoryQuickButtonContainer { get; }
|
Control InventoryQuickButtonContainer { get; }
|
||||||
|
|
||||||
bool CombatPanelVisible { get; set; }
|
bool CombatPanelVisible { get; set; }
|
||||||
@@ -79,6 +80,7 @@ namespace Content.Client.UserInterface
|
|||||||
[Dependency] private readonly IInputManager _inputManager = default!;
|
[Dependency] private readonly IInputManager _inputManager = default!;
|
||||||
|
|
||||||
public Control HandsContainer { get; private set; }
|
public Control HandsContainer { get; private set; }
|
||||||
|
public Control SuspicionContainer { get; private set; }
|
||||||
public Control InventoryQuickButtonContainer { get; private set; }
|
public Control InventoryQuickButtonContainer { get; private set; }
|
||||||
|
|
||||||
public bool CombatPanelVisible
|
public bool CombatPanelVisible
|
||||||
@@ -242,6 +244,17 @@ namespace Content.Client.UserInterface
|
|||||||
LayoutContainer.SetAnchorAndMarginPreset(HandsContainer, LayoutContainer.LayoutPreset.CenterBottom);
|
LayoutContainer.SetAnchorAndMarginPreset(HandsContainer, LayoutContainer.LayoutPreset.CenterBottom);
|
||||||
LayoutContainer.SetGrowHorizontal(HandsContainer, LayoutContainer.GrowDirection.Both);
|
LayoutContainer.SetGrowHorizontal(HandsContainer, LayoutContainer.GrowDirection.Both);
|
||||||
LayoutContainer.SetGrowVertical(HandsContainer, LayoutContainer.GrowDirection.Begin);
|
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()
|
private void ButtonTutorialOnOnToggled()
|
||||||
|
|||||||
116
Content.Client/UserInterface/Suspicion/SuspicionGui.cs
Normal file
116
Content.Client/UserInterface/Suspicion/SuspicionGui.cs
Normal file
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
using Content.Server.Mobs.Roles.Suspicion;
|
||||||
using Content.Shared.GameObjects.Components.Damage;
|
using Content.Shared.GameObjects.Components.Damage;
|
||||||
|
using Content.Shared.GameObjects.Components.Suspicion;
|
||||||
using Content.Shared.GameObjects.EntitySystems;
|
using Content.Shared.GameObjects.EntitySystems;
|
||||||
|
using Robust.Server.GameObjects;
|
||||||
|
using Robust.Server.Interfaces.GameObjects;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.GameObjects.Systems;
|
||||||
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
using Robust.Shared.Localization;
|
using Robust.Shared.Localization;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
|
using Robust.Shared.ViewVariables;
|
||||||
|
|
||||||
namespace Content.Server.GameObjects.Components.Suspicion
|
namespace Content.Server.GameObjects.Components.Suspicion
|
||||||
{
|
{
|
||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
public class SuspicionRoleComponent : Component, IExamine
|
public class SuspicionRoleComponent : SharedSuspicionRoleComponent, IExamine
|
||||||
{
|
{
|
||||||
public override string Name => "SuspicionRole";
|
private Role? _role;
|
||||||
|
private readonly HashSet<SuspicionRoleComponent> _allies = new HashSet<SuspicionRoleComponent>();
|
||||||
|
|
||||||
|
[ViewVariables]
|
||||||
|
public Role? Role
|
||||||
|
{
|
||||||
|
get => _role;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_role == value)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_role = value;
|
||||||
|
|
||||||
|
Dirty();
|
||||||
|
|
||||||
|
var suspicionRoleSystem = EntitySystem.Get<SuspicionRoleSystem>();
|
||||||
|
|
||||||
|
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()
|
public bool IsDead()
|
||||||
{
|
{
|
||||||
return Owner.TryGetComponent(out IDamageableComponent damageable) &&
|
return Owner.TryGetComponent(out IDamageableComponent? damageable) &&
|
||||||
damageable.CurrentDamageState == DamageState.Dead;
|
damageable.CurrentDamageState == DamageState.Dead;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IsInnocent()
|
||||||
|
{
|
||||||
|
return Owner.TryGetComponent(out MindComponent? mind) &&
|
||||||
|
mind.HasMind &&
|
||||||
|
mind.Mind!.HasRole<SuspicionInnocentRole>();
|
||||||
|
}
|
||||||
|
|
||||||
public bool IsTraitor()
|
public bool IsTraitor()
|
||||||
{
|
{
|
||||||
return Owner.TryGetComponent(out MindComponent mind) &&
|
return Owner.TryGetComponent(out MindComponent? mind) &&
|
||||||
mind.HasMind &&
|
mind.HasMind &&
|
||||||
mind.Mind!.HasRole<SuspicionTraitorRole>();
|
mind.Mind!.HasRole<SuspicionTraitorRole>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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<SuspicionRoleComponent> 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)
|
void IExamine.Examine(FormattedMessage message, bool inDetailsRange)
|
||||||
{
|
{
|
||||||
if (!IsDead())
|
if (!IsDead())
|
||||||
@@ -39,5 +193,43 @@ namespace Content.Server.GameObjects.Components.Suspicion
|
|||||||
|
|
||||||
message.AddMarkup(tooltip);
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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<SuspicionRoleComponent> _traitors = new HashSet<SuspicionRoleComponent>();
|
||||||
|
|
||||||
|
public IReadOnlyCollection<SuspicionRoleComponent> 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
using Content.Server.GameTicking.GameRules;
|
using Content.Server.GameTicking.GameRules;
|
||||||
using Content.Server.Interfaces.Chat;
|
using Content.Server.Interfaces.Chat;
|
||||||
using Content.Server.Interfaces.GameTicking;
|
using Content.Server.Interfaces.GameTicking;
|
||||||
using Content.Server.Mobs.Roles;
|
|
||||||
using Content.Server.Players;
|
using Content.Server.Players;
|
||||||
using Robust.Server.Interfaces.Player;
|
using Robust.Server.Interfaces.Player;
|
||||||
using Robust.Shared.Interfaces.Random;
|
using Robust.Shared.Interfaces.Random;
|
||||||
@@ -11,6 +10,8 @@ using Robust.Shared.Random;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Server.GameObjects.Components.Suspicion;
|
using Content.Server.GameObjects.Components.Suspicion;
|
||||||
|
using Content.Server.Mobs.Roles;
|
||||||
|
using Content.Server.Mobs.Roles.Suspicion;
|
||||||
using Content.Shared.Roles;
|
using Content.Shared.Roles;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.Interfaces.Configuration;
|
using Robust.Shared.Interfaces.Configuration;
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using Content.Server.GameObjects.EntitySystems;
|
|||||||
using Content.Server.Interfaces.Chat;
|
using Content.Server.Interfaces.Chat;
|
||||||
using Content.Server.Interfaces.GameTicking;
|
using Content.Server.Interfaces.GameTicking;
|
||||||
using Content.Server.Mobs.Roles;
|
using Content.Server.Mobs.Roles;
|
||||||
|
using Content.Server.Mobs.Roles.Suspicion;
|
||||||
using Content.Server.Players;
|
using Content.Server.Players;
|
||||||
using Content.Shared.GameObjects.Components.Damage;
|
using Content.Shared.GameObjects.Components.Damage;
|
||||||
using Robust.Server.GameObjects.EntitySystems;
|
using Robust.Server.GameObjects.EntitySystems;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Server.GameObjects.Components.Mobs;
|
using Content.Server.GameObjects.Components.Mobs;
|
||||||
|
using Content.Server.Mobs.Roles;
|
||||||
using Content.Server.Players;
|
using Content.Server.Players;
|
||||||
using Robust.Server.Interfaces.GameObjects;
|
using Robust.Server.Interfaces.GameObjects;
|
||||||
using Robust.Server.Interfaces.Player;
|
using Robust.Server.Interfaces.Player;
|
||||||
@@ -95,7 +96,7 @@ namespace Content.Server.Mobs
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gives this mind a new role.
|
/// Gives this mind a new role.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="t">The type of the role to give.</param>
|
/// <param name="role">The type of the role to give.</param>
|
||||||
/// <returns>The instance of the role.</returns>
|
/// <returns>The instance of the role.</returns>
|
||||||
/// <exception cref="ArgumentException">
|
/// <exception cref="ArgumentException">
|
||||||
/// Thrown if we already have a role with this type.
|
/// Thrown if we already have a role with this type.
|
||||||
@@ -109,13 +110,17 @@ namespace Content.Server.Mobs
|
|||||||
|
|
||||||
_roles.Add(role);
|
_roles.Add(role);
|
||||||
role.Greet();
|
role.Greet();
|
||||||
|
|
||||||
|
var message = new RoleAddedMessage(role);
|
||||||
|
OwnedEntity?.SendMessage(OwnedMob, message);
|
||||||
|
|
||||||
return role;
|
return role;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Removes a role from this mind.
|
/// Removes a role from this mind.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="t">The type of the role to remove.</param>
|
/// <param name="role">The type of the role to remove.</param>
|
||||||
/// <exception cref="ArgumentException">
|
/// <exception cref="ArgumentException">
|
||||||
/// Thrown if we do not have this role.
|
/// Thrown if we do not have this role.
|
||||||
/// </exception>
|
/// </exception>
|
||||||
@@ -126,9 +131,10 @@ namespace Content.Server.Mobs
|
|||||||
throw new ArgumentException($"We do not have this role: {role}");
|
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);
|
_roles.Remove(role);
|
||||||
|
|
||||||
|
var message = new RoleRemovedMessage(role);
|
||||||
|
OwnedEntity?.SendMessage(OwnedMob, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HasRole<T>() where T : Role
|
public bool HasRole<T>() where T : Role
|
||||||
|
|||||||
7
Content.Server/Mobs/Roles/RoleAddedMessage.cs
Normal file
7
Content.Server/Mobs/Roles/RoleAddedMessage.cs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
namespace Content.Server.Mobs.Roles
|
||||||
|
{
|
||||||
|
public class RoleAddedMessage : RoleMessage
|
||||||
|
{
|
||||||
|
public RoleAddedMessage(Role role) : base(role) { }
|
||||||
|
}
|
||||||
|
}
|
||||||
14
Content.Server/Mobs/Roles/RoleMessage.cs
Normal file
14
Content.Server/Mobs/Roles/RoleMessage.cs
Normal file
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
7
Content.Server/Mobs/Roles/RoleRemovedMessage.cs
Normal file
7
Content.Server/Mobs/Roles/RoleRemovedMessage.cs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
namespace Content.Server.Mobs.Roles
|
||||||
|
{
|
||||||
|
public class RoleRemovedMessage : RoleMessage
|
||||||
|
{
|
||||||
|
public RoleRemovedMessage(Role role) : base(role) { }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,9 +2,9 @@ using Content.Server.Interfaces.Chat;
|
|||||||
using Content.Shared.Roles;
|
using Content.Shared.Roles;
|
||||||
using Robust.Shared.IoC;
|
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; }
|
public AntagPrototype Prototype { get; }
|
||||||
|
|
||||||
7
Content.Server/Mobs/Roles/Suspicion/SuspicionRole.cs
Normal file
7
Content.Server/Mobs/Roles/Suspicion/SuspicionRole.cs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
namespace Content.Server.Mobs.Roles.Suspicion
|
||||||
|
{
|
||||||
|
public abstract class SuspicionRole : Role
|
||||||
|
{
|
||||||
|
protected SuspicionRole(Mind mind) : base(mind) { }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Server.Interfaces.Chat;
|
using Content.Server.Interfaces.Chat;
|
||||||
|
using Content.Server.Mobs.Roles.Suspicion;
|
||||||
using Content.Shared.Roles;
|
using Content.Shared.Roles;
|
||||||
using Robust.Server.GameObjects.EntitySystems;
|
using Robust.Server.GameObjects.EntitySystems;
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
@@ -9,7 +10,7 @@ using Robust.Shared.Localization;
|
|||||||
|
|
||||||
namespace Content.Server.Mobs.Roles
|
namespace Content.Server.Mobs.Roles
|
||||||
{
|
{
|
||||||
public sealed class SuspicionTraitorRole : Role
|
public sealed class SuspicionTraitorRole : SuspicionRole
|
||||||
{
|
{
|
||||||
public AntagPrototype Prototype { get; }
|
public AntagPrototype Prototype { get; }
|
||||||
|
|
||||||
@@ -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<EntityUid> Allies;
|
||||||
|
|
||||||
|
public SuspicionAlliesMessage(HashSet<EntityUid> allies)
|
||||||
|
{
|
||||||
|
Directed = true;
|
||||||
|
Allies = allies;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SuspicionAlliesMessage(IEnumerable<EntityUid> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -71,6 +71,7 @@
|
|||||||
public const uint CUFFED = 1065;
|
public const uint CUFFED = 1065;
|
||||||
public const uint HANDCUFFS = 1066;
|
public const uint HANDCUFFS = 1066;
|
||||||
public const uint BATTERY_BARREL = 1067;
|
public const uint BATTERY_BARREL = 1067;
|
||||||
|
public const uint SUSPICION_ROLE = 1068;
|
||||||
|
|
||||||
// Net IDs for integration tests.
|
// Net IDs for integration tests.
|
||||||
public const uint PREDICTION_TEST = 10001;
|
public const uint PREDICTION_TEST = 10001;
|
||||||
|
|||||||
Reference in New Issue
Block a user