Add SSS traitor label and fix ally sync (#2200)
This commit is contained in:
@@ -1,15 +1,19 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using Content.Client.UserInterface;
|
using Content.Client.UserInterface;
|
||||||
using Content.Client.UserInterface.Suspicion;
|
using Content.Client.UserInterface.Suspicion;
|
||||||
using Content.Shared.GameObjects.Components.Suspicion;
|
using Content.Shared.GameObjects.Components.Suspicion;
|
||||||
using Robust.Client.GameObjects;
|
using Robust.Client.GameObjects;
|
||||||
|
using Robust.Client.Interfaces.Graphics.ClientEye;
|
||||||
|
using Robust.Client.Interfaces.Graphics.Overlays;
|
||||||
|
using Robust.Client.Interfaces.Input;
|
||||||
|
using Robust.Client.Interfaces.ResourceManagement;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.Interfaces.GameObjects;
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
using Robust.Shared.Interfaces.Network;
|
using Robust.Shared.Interfaces.Network;
|
||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
using Robust.Shared.Players;
|
using Robust.Shared.Players;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
namespace Content.Client.GameObjects.Components.Suspicion
|
namespace Content.Client.GameObjects.Components.Suspicion
|
||||||
{
|
{
|
||||||
@@ -18,6 +22,12 @@ namespace Content.Client.GameObjects.Components.Suspicion
|
|||||||
{
|
{
|
||||||
[Dependency] private readonly IGameHud _gameHud = default!;
|
[Dependency] private readonly IGameHud _gameHud = default!;
|
||||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||||
|
[Dependency] private readonly IOverlayManager _overlayManager = default!;
|
||||||
|
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||||
|
[Dependency] private readonly IResourceCache _resourceCache = default!;
|
||||||
|
[Dependency] private readonly IComponentManager _componentManager = default!;
|
||||||
|
[Dependency] private readonly IInputManager _inputManager = default!;
|
||||||
|
[Dependency] private readonly IEyeManager _eyeManager = default!;
|
||||||
|
|
||||||
private SuspicionGui? _gui;
|
private SuspicionGui? _gui;
|
||||||
private string? _role;
|
private string? _role;
|
||||||
@@ -28,6 +38,11 @@ namespace Content.Client.GameObjects.Components.Suspicion
|
|||||||
get => _role;
|
get => _role;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
|
if (_role == value)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_role = value;
|
_role = value;
|
||||||
_gui?.UpdateLabel();
|
_gui?.UpdateLabel();
|
||||||
Dirty();
|
Dirty();
|
||||||
@@ -39,13 +54,70 @@ namespace Content.Client.GameObjects.Components.Suspicion
|
|||||||
get => _antagonist;
|
get => _antagonist;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
|
if (_antagonist == value)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_antagonist = value;
|
_antagonist = value;
|
||||||
_gui?.UpdateLabel();
|
_gui?.UpdateLabel();
|
||||||
|
|
||||||
|
if (value ?? false)
|
||||||
|
{
|
||||||
|
AddTraitorOverlay();
|
||||||
|
}
|
||||||
|
|
||||||
Dirty();
|
Dirty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public HashSet<IEntity> Allies { get; } = new HashSet<IEntity>();
|
public HashSet<EntityUid> Allies { get; } = new HashSet<EntityUid>();
|
||||||
|
|
||||||
|
private bool AddAlly(EntityUid ally)
|
||||||
|
{
|
||||||
|
if (!Allies.Add(ally))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_overlayManager.TryGetOverlay<TraitorOverlay>(nameof(TraitorOverlay), out var overlay))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return overlay.AddAlly(ally);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool RemoveAlly(EntityUid ally)
|
||||||
|
{
|
||||||
|
if (!Allies.Remove(ally))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_overlayManager.TryGetOverlay<TraitorOverlay>(nameof(TraitorOverlay), out var overlay))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return overlay.RemoveAlly(ally);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddTraitorOverlay()
|
||||||
|
{
|
||||||
|
if (_overlayManager.HasOverlay(nameof(TraitorOverlay)))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var overlay = new TraitorOverlay(Owner, _entityManager, _resourceCache, _eyeManager);
|
||||||
|
_overlayManager.AddOverlay(overlay);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RemoveTraitorOverlay()
|
||||||
|
{
|
||||||
|
_overlayManager.RemoveOverlay(nameof(TraitorOverlay));
|
||||||
|
}
|
||||||
|
|
||||||
public override void HandleComponentState(ComponentState? curState, ComponentState? nextState)
|
public override void HandleComponentState(ComponentState? curState, ComponentState? nextState)
|
||||||
{
|
{
|
||||||
@@ -56,8 +128,8 @@ namespace Content.Client.GameObjects.Components.Suspicion
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_role = state.Role;
|
Role = state.Role;
|
||||||
_antagonist = state.Antagonist;
|
Antagonist = state.Antagonist;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void HandleMessage(ComponentMessage message, IComponent? component)
|
public override void HandleMessage(ComponentMessage message, IComponent? component)
|
||||||
@@ -79,9 +151,15 @@ namespace Content.Client.GameObjects.Components.Suspicion
|
|||||||
_gameHud.SuspicionContainer.AddChild(_gui);
|
_gameHud.SuspicionContainer.AddChild(_gui);
|
||||||
_gui.UpdateLabel();
|
_gui.UpdateLabel();
|
||||||
|
|
||||||
|
if (_antagonist ?? false)
|
||||||
|
{
|
||||||
|
AddTraitorOverlay();
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case PlayerDetachedMsg _:
|
case PlayerDetachedMsg _:
|
||||||
_gui?.Parent?.RemoveChild(_gui);
|
_gui?.Parent?.RemoveChild(_gui);
|
||||||
|
RemoveTraitorOverlay();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -93,9 +171,26 @@ namespace Content.Client.GameObjects.Components.Suspicion
|
|||||||
switch (message)
|
switch (message)
|
||||||
{
|
{
|
||||||
case SuspicionAlliesMessage msg:
|
case SuspicionAlliesMessage msg:
|
||||||
|
{
|
||||||
Allies.Clear();
|
Allies.Clear();
|
||||||
Allies.UnionWith(msg.Allies.Select(_entityManager.GetEntity));
|
|
||||||
|
foreach (var uid in msg.Allies)
|
||||||
|
{
|
||||||
|
AddAlly(uid);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
case SuspicionAllyAddedMessage msg:
|
||||||
|
{
|
||||||
|
AddAlly(msg.Ally);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SuspicionAllyRemovedMessage msg:
|
||||||
|
{
|
||||||
|
RemoveAlly(msg.Ally);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,6 +199,7 @@ namespace Content.Client.GameObjects.Components.Suspicion
|
|||||||
base.OnRemove();
|
base.OnRemove();
|
||||||
|
|
||||||
_gui?.Dispose();
|
_gui?.Dispose();
|
||||||
|
RemoveTraitorOverlay();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,120 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using Content.Shared.GameObjects.EntitySystems;
|
||||||
|
using Robust.Client.Graphics;
|
||||||
|
using Robust.Client.Graphics.Drawing;
|
||||||
|
using Robust.Client.Graphics.Overlays;
|
||||||
|
using Robust.Client.Interfaces.Graphics.ClientEye;
|
||||||
|
using Robust.Client.Interfaces.ResourceManagement;
|
||||||
|
using Robust.Client.ResourceManagement;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.GameObjects.Components;
|
||||||
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
|
using Robust.Shared.Localization;
|
||||||
|
using Robust.Shared.Maths;
|
||||||
|
|
||||||
|
namespace Content.Client.GameObjects.Components.Suspicion
|
||||||
|
{
|
||||||
|
public class TraitorOverlay : Overlay
|
||||||
|
{
|
||||||
|
private readonly IEntityManager _entityManager;
|
||||||
|
private readonly IEyeManager _eyeManager;
|
||||||
|
|
||||||
|
public override OverlaySpace Space => OverlaySpace.ScreenSpace;
|
||||||
|
private readonly Font _font;
|
||||||
|
|
||||||
|
private readonly IEntity _user;
|
||||||
|
private readonly HashSet<EntityUid> _allies = new HashSet<EntityUid>();
|
||||||
|
private readonly string _traitorText = Loc.GetString("Traitor");
|
||||||
|
|
||||||
|
public TraitorOverlay(
|
||||||
|
IEntity user,
|
||||||
|
IEntityManager entityManager,
|
||||||
|
IResourceCache resourceCache,
|
||||||
|
IEyeManager eyeManager)
|
||||||
|
: base(nameof(TraitorOverlay))
|
||||||
|
{
|
||||||
|
_entityManager = entityManager;
|
||||||
|
_eyeManager = eyeManager;
|
||||||
|
|
||||||
|
_font = new VectorFont(resourceCache.GetResource<FontResource>("/Fonts/NotoSans/NotoSans-Regular.ttf"), 10);
|
||||||
|
|
||||||
|
_user = user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AddAlly(EntityUid ally)
|
||||||
|
{
|
||||||
|
return _allies.Add(ally);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool RemoveAlly(EntityUid ally)
|
||||||
|
{
|
||||||
|
return _allies.Remove(ally);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Draw(DrawingHandleBase handle, OverlaySpace currentSpace)
|
||||||
|
{
|
||||||
|
switch (currentSpace)
|
||||||
|
{
|
||||||
|
case OverlaySpace.ScreenSpace:
|
||||||
|
DrawScreen((DrawingHandleScreen) handle);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawScreen(DrawingHandleScreen screen)
|
||||||
|
{
|
||||||
|
var viewport = _eyeManager.GetWorldViewport();
|
||||||
|
|
||||||
|
foreach (var uid in _allies)
|
||||||
|
{
|
||||||
|
// Otherwise the entity can not exist yet
|
||||||
|
if (!_entityManager.TryGetEntity(uid, out var ally))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ally.TryGetComponent(out ICollidableComponent collidable))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ExamineSystemShared.InRangeUnOccluded(_user.Transform.MapPosition, ally.Transform.MapPosition, 15,
|
||||||
|
entity => entity == _user || entity == ally))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// all entities have a TransformComponent
|
||||||
|
var transform = collidable.Entity.Transform;
|
||||||
|
|
||||||
|
// if not on the same map, continue
|
||||||
|
if (transform.MapID != _eyeManager.CurrentMap || !transform.IsMapTransform)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var worldBox = collidable.WorldAABB;
|
||||||
|
|
||||||
|
// if not on screen, or too small, continue
|
||||||
|
if (!worldBox.Intersects(in viewport) || worldBox.IsEmpty())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var screenCoordinates = _eyeManager.WorldToScreen(collidable.WorldAABB.TopLeft + (0, 0.5f));
|
||||||
|
DrawString(screen, _font, screenCoordinates, _traitorText, Color.OrangeRed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void DrawString(DrawingHandleScreen handle, Font font, Vector2 pos, string str, Color color)
|
||||||
|
{
|
||||||
|
var baseLine = new Vector2(pos.X, font.GetAscent(1) + pos.Y);
|
||||||
|
|
||||||
|
foreach (var chr in str)
|
||||||
|
{
|
||||||
|
var advance = font.DrawChar(handle, chr, baseLine, 1, color);
|
||||||
|
baseLine += new Vector2(advance, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
using Content.Client.GameObjects.Components.Suspicion;
|
using Content.Client.GameObjects.Components.Suspicion;
|
||||||
using Content.Shared.Interfaces;
|
using Content.Shared.Interfaces;
|
||||||
using Robust.Client.Player;
|
using Robust.Client.Player;
|
||||||
using Robust.Client.UserInterface;
|
using Robust.Client.UserInterface;
|
||||||
using Robust.Client.UserInterface.Controls;
|
using Robust.Client.UserInterface.Controls;
|
||||||
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
using Robust.Shared.Localization;
|
using Robust.Shared.Localization;
|
||||||
using Robust.Shared.Maths;
|
using Robust.Shared.Maths;
|
||||||
@@ -15,9 +17,8 @@ namespace Content.Client.UserInterface.Suspicion
|
|||||||
{
|
{
|
||||||
public class SuspicionGui : Control
|
public class SuspicionGui : Control
|
||||||
{
|
{
|
||||||
#pragma warning disable 0649
|
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||||
[Dependency] private readonly IPlayerManager _playerManager;
|
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||||
#pragma warning restore 0649
|
|
||||||
|
|
||||||
private readonly VBoxContainer _container;
|
private readonly VBoxContainer _container;
|
||||||
private readonly Button _roleButton;
|
private readonly Button _roleButton;
|
||||||
@@ -57,7 +58,8 @@ namespace Content.Client.UserInterface.Suspicion
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var allies = string.Join(", ", role.Allies);
|
var allies = string.Join(", ",
|
||||||
|
role.Allies.Select(uid => _entityManager.GetEntity(uid).Name));
|
||||||
var message = role.Allies.Count switch
|
var message = role.Allies.Count switch
|
||||||
{
|
{
|
||||||
0 => Loc.GetString("You have no allies"),
|
0 => Loc.GetString("You have no allies"),
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ namespace Content.Shared.GameObjects.EntitySystems
|
|||||||
ignoreInsideBlocker: true);
|
ignoreInsideBlocker: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool InRangeUnOccluded(MapCoordinates origin, MapCoordinates other, float range, Ignored predicate, bool ignoreInsideBlocker = true)
|
public static bool InRangeUnOccluded(MapCoordinates origin, MapCoordinates other, float range, Ignored predicate, bool ignoreInsideBlocker = true)
|
||||||
{
|
{
|
||||||
var occluderSystem = Get<OccluderSystem>();
|
var occluderSystem = Get<OccluderSystem>();
|
||||||
if (!origin.InRange(other, range)) return false;
|
if (!origin.InRange(other, range)) return false;
|
||||||
|
|||||||
Reference in New Issue
Block a user