Merge branch 'master' into mathmerge
This commit is contained in:
@@ -40,7 +40,12 @@ namespace Content.Client.Atmos
|
||||
|
||||
foreach (var mapGrid in _mapManager.FindGridsIntersecting(mapId, worldBounds))
|
||||
{
|
||||
foreach (var tile in mapGrid.GetTilesIntersecting(worldBounds))
|
||||
if (!_gasTileOverlaySystem.HasData(mapGrid.Index))
|
||||
continue;
|
||||
|
||||
var gridBounds = new Box2(mapGrid.WorldToLocal(worldBounds.BottomLeft), mapGrid.WorldToLocal(worldBounds.TopRight));
|
||||
|
||||
foreach (var tile in mapGrid.GetTilesIntersecting(gridBounds))
|
||||
{
|
||||
foreach (var (texture, color) in _gasTileOverlaySystem.GetOverlays(mapGrid.Index, tile.GridIndices))
|
||||
{
|
||||
|
||||
@@ -35,6 +35,8 @@ namespace Content.Client.Chat
|
||||
|
||||
public bool ReleaseFocusOnEnter { get; set; } = true;
|
||||
|
||||
public bool ClearOnEnter { get; set; } = true;
|
||||
|
||||
public ChatBox()
|
||||
{
|
||||
/*MarginLeft = -475.0f;
|
||||
@@ -166,12 +168,18 @@ namespace Content.Client.Chat
|
||||
|
||||
private void Input_OnTextEntered(LineEdit.LineEditEventArgs args)
|
||||
{
|
||||
// We set it there to true so it's set to false by TextSubmitted.Invoke if necessary
|
||||
ClearOnEnter = true;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(args.Text))
|
||||
{
|
||||
TextSubmitted?.Invoke(this, args.Text);
|
||||
}
|
||||
|
||||
Input.Clear();
|
||||
if (ClearOnEnter)
|
||||
{
|
||||
Input.Clear();
|
||||
}
|
||||
|
||||
if (ReleaseFocusOnEnter)
|
||||
{
|
||||
|
||||
@@ -1,17 +1,21 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Content.Client.Interfaces.Chat;
|
||||
using Content.Shared.Chat;
|
||||
using Robust.Client.Console;
|
||||
using Robust.Client.Interfaces.Graphics.ClientEye;
|
||||
using Robust.Client.Interfaces.UserInterface;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.Interfaces.Network;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Timing;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
@@ -45,6 +49,11 @@ namespace Content.Client.Chat
|
||||
/// </summary>
|
||||
private const int SpeechBubbleCap = 4;
|
||||
|
||||
/// <summary>
|
||||
/// The max amount of characters an entity can send in one message
|
||||
/// </summary>
|
||||
private int _maxMessageLength = 1000;
|
||||
|
||||
private const char ConCmdSlash = '/';
|
||||
private const char OOCAlias = '[';
|
||||
private const char MeAlias = '@';
|
||||
@@ -89,11 +98,15 @@ namespace Content.Client.Chat
|
||||
public void Initialize()
|
||||
{
|
||||
_netManager.RegisterNetMessage<MsgChatMessage>(MsgChatMessage.NAME, _onChatMessage);
|
||||
_netManager.RegisterNetMessage<ChatMaxMsgLengthMessage>(ChatMaxMsgLengthMessage.NAME, _onMaxLengthReceived);
|
||||
|
||||
_speechBubbleRoot = new LayoutContainer();
|
||||
LayoutContainer.SetAnchorPreset(_speechBubbleRoot, LayoutContainer.LayoutPreset.Wide);
|
||||
_userInterfaceManager.StateRoot.AddChild(_speechBubbleRoot);
|
||||
_speechBubbleRoot.SetPositionFirst();
|
||||
|
||||
// When connexion is achieved, request the max chat message length
|
||||
_netManager.Connected += new EventHandler<NetChannelArgs>(RequestMaxLength);
|
||||
}
|
||||
|
||||
public void FrameUpdate(FrameEventArgs delta)
|
||||
@@ -213,6 +226,15 @@ namespace Content.Client.Chat
|
||||
if (string.IsNullOrWhiteSpace(text))
|
||||
return;
|
||||
|
||||
// Check if message is longer than the character limit
|
||||
if (text.Length > _maxMessageLength)
|
||||
{
|
||||
string locWarning = Loc.GetString("Your message exceeds {0} character limit", _maxMessageLength);
|
||||
_currentChatBox?.AddLine(locWarning, ChatChannel.Server, Color.Orange);
|
||||
_currentChatBox.ClearOnEnter = false; // The text shouldn't be cleared if it hasn't been sent
|
||||
return;
|
||||
}
|
||||
|
||||
switch (text[0])
|
||||
{
|
||||
case ConCmdSlash:
|
||||
@@ -225,13 +247,17 @@ namespace Content.Client.Chat
|
||||
case OOCAlias:
|
||||
{
|
||||
var conInput = text.Substring(1);
|
||||
if (string.IsNullOrWhiteSpace(conInput))
|
||||
return;
|
||||
_console.ProcessCommand($"ooc \"{CommandParsing.Escape(conInput)}\"");
|
||||
break;
|
||||
}
|
||||
case AdminChatAlias:
|
||||
{
|
||||
var conInput = text.Substring(1);
|
||||
if(_groupController.CanCommand("asay")){
|
||||
if (string.IsNullOrWhiteSpace(conInput))
|
||||
return;
|
||||
if (_groupController.CanCommand("asay")){
|
||||
_console.ProcessCommand($"asay \"{CommandParsing.Escape(conInput)}\"");
|
||||
}
|
||||
else
|
||||
@@ -243,6 +269,8 @@ namespace Content.Client.Chat
|
||||
case MeAlias:
|
||||
{
|
||||
var conInput = text.Substring(1);
|
||||
if (string.IsNullOrWhiteSpace(conInput))
|
||||
return;
|
||||
_console.ProcessCommand($"me \"{CommandParsing.Escape(conInput)}\"");
|
||||
break;
|
||||
}
|
||||
@@ -323,8 +351,6 @@ namespace Content.Client.Chat
|
||||
|
||||
private void _onChatMessage(MsgChatMessage msg)
|
||||
{
|
||||
Logger.Debug($"{msg.Channel}: {msg.Message}");
|
||||
|
||||
// Log all incoming chat to repopulate when filter is un-toggled
|
||||
var storedMessage = new StoredChatMessage(msg);
|
||||
filteredHistory.Add(storedMessage);
|
||||
@@ -347,6 +373,17 @@ namespace Content.Client.Chat
|
||||
}
|
||||
}
|
||||
|
||||
private void _onMaxLengthReceived(ChatMaxMsgLengthMessage msg)
|
||||
{
|
||||
_maxMessageLength = msg.MaxMessageLength;
|
||||
}
|
||||
|
||||
private void RequestMaxLength(object sender, NetChannelArgs args)
|
||||
{
|
||||
ChatMaxMsgLengthMessage msg = _netManager.CreateNetMessage<ChatMaxMsgLengthMessage>();
|
||||
_netManager.ClientSendMessage(msg);
|
||||
}
|
||||
|
||||
private void AddSpeechBubble(MsgChatMessage msg, SpeechBubble.SpeechType speechType)
|
||||
{
|
||||
if (!_entityManager.TryGetEntity(msg.SenderEntity, out var entity))
|
||||
|
||||
@@ -5,6 +5,7 @@ using Content.Client.Interfaces.Chat;
|
||||
using Content.Client.Interfaces.Parallax;
|
||||
using Content.Client.Parallax;
|
||||
using Content.Client.Sandbox;
|
||||
using Content.Client.StationEvents;
|
||||
using Content.Client.UserInterface;
|
||||
using Content.Client.UserInterface.Stylesheets;
|
||||
using Content.Client.Utility;
|
||||
@@ -31,6 +32,7 @@ namespace Content.Client
|
||||
IoCManager.Register<IStylesheetManager, StylesheetManager>();
|
||||
IoCManager.Register<IScreenshotHook, ScreenshotHook>();
|
||||
IoCManager.Register<IClickMapManager, ClickMapManager>();
|
||||
IoCManager.Register<IStationEventManager, StationEventManager>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ using Content.Client.Interfaces.Parallax;
|
||||
using Content.Client.Parallax;
|
||||
using Content.Client.Sandbox;
|
||||
using Content.Client.State;
|
||||
using Content.Client.StationEvents;
|
||||
using Content.Client.UserInterface;
|
||||
using Content.Client.UserInterface.Stylesheets;
|
||||
using Content.Shared.GameObjects.Components;
|
||||
@@ -150,6 +151,7 @@ namespace Content.Client
|
||||
IoCManager.Resolve<IChatManager>().Initialize();
|
||||
IoCManager.Resolve<ISandboxManager>().Initialize();
|
||||
IoCManager.Resolve<IClientPreferencesManager>().Initialize();
|
||||
IoCManager.Resolve<IStationEventManager>().Initialize();
|
||||
|
||||
_baseClient.RunLevelChanged += (sender, args) =>
|
||||
{
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
using Content.Client.Atmos;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.Interfaces.Graphics.Overlays;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
|
||||
namespace Content.Client.GameObjects.Components.Atmos
|
||||
{
|
||||
[RegisterComponent]
|
||||
public class CanSeeGasesComponent : Component
|
||||
{
|
||||
[Dependency] private readonly IOverlayManager _overlayManager = default!;
|
||||
|
||||
public override string Name => "CanSeeGases";
|
||||
|
||||
public override void HandleMessage(ComponentMessage message, IComponent component)
|
||||
{
|
||||
base.HandleMessage(message, component);
|
||||
|
||||
switch (message)
|
||||
{
|
||||
case PlayerAttachedMsg _:
|
||||
if(!_overlayManager.HasOverlay(nameof(GasTileOverlay)))
|
||||
_overlayManager.AddOverlay(new GasTileOverlay());
|
||||
break;
|
||||
|
||||
case PlayerDetachedMsg _:
|
||||
if(!_overlayManager.HasOverlay(nameof(GasTileOverlay)))
|
||||
_overlayManager.RemoveOverlay(nameof(GasTileOverlay));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
using System;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.Animations;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.GameObjects.Components.Animations;
|
||||
using Robust.Client.Interfaces.GameObjects.Components;
|
||||
using Robust.Shared.Animations;
|
||||
using Robust.Shared.Maths;
|
||||
using Content.Shared.GameObjects.Components;
|
||||
|
||||
namespace Content.Client.GameObjects.Components.Atmos
|
||||
{
|
||||
[UsedImplicitly]
|
||||
public class ExtinguisherVisualizer : AppearanceVisualizer
|
||||
{
|
||||
|
||||
public override void OnChangeData(AppearanceComponent component)
|
||||
{
|
||||
base.OnChangeData(component);
|
||||
|
||||
if (component.Deleted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (component.TryGetData<double>(ExtinguisherVisuals.Rotation, out var degrees))
|
||||
{
|
||||
SetRotation(component, Angle.FromDegrees(degrees));
|
||||
}
|
||||
}
|
||||
|
||||
private void SetRotation(AppearanceComponent component, Angle rotation)
|
||||
{
|
||||
var sprite = component.Owner.GetComponent<ISpriteComponent>();
|
||||
|
||||
if (!sprite.Owner.TryGetComponent(out AnimationPlayerComponent animation))
|
||||
{
|
||||
sprite.Rotation = rotation;
|
||||
return;
|
||||
}
|
||||
|
||||
if (animation.HasRunningAnimation("rotate"))
|
||||
{
|
||||
animation.Stop("rotate");
|
||||
}
|
||||
|
||||
animation.Play(new Animation
|
||||
{
|
||||
Length = TimeSpan.FromSeconds(0.125),
|
||||
AnimationTracks =
|
||||
{
|
||||
new AnimationTrackComponentProperty
|
||||
{
|
||||
ComponentType = typeof(ISpriteComponent),
|
||||
Property = nameof(ISpriteComponent.Rotation),
|
||||
InterpolationMode = AnimationInterpolationMode.Linear,
|
||||
KeyFrames =
|
||||
{
|
||||
new AnimationTrackProperty.KeyFrame(sprite.Rotation, 0),
|
||||
new AnimationTrackProperty.KeyFrame(rotation, 0.125f)
|
||||
}
|
||||
}
|
||||
}
|
||||
}, "rotate");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
#nullable enable
|
||||
using Content.Client.GameObjects.Components.Disposal;
|
||||
using Content.Client.Interfaces.GameObjects.Components.Interaction;
|
||||
using Content.Shared.GameObjects.Components.Body;
|
||||
using Content.Shared.GameObjects.Components.Damage;
|
||||
using Robust.Client.Interfaces.GameObjects.Components;
|
||||
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.Body
|
||||
{
|
||||
[RegisterComponent]
|
||||
[ComponentReference(typeof(IDamageableComponent))]
|
||||
[ComponentReference(typeof(IBodyManagerComponent))]
|
||||
public class BodyManagerComponent : SharedBodyManagerComponent, IClientDraggable
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
#pragma warning restore 649
|
||||
|
||||
public bool ClientCanDropOn(CanDropEventArgs eventArgs)
|
||||
{
|
||||
return eventArgs.Target.HasComponent<DisposalUnitComponent>();
|
||||
}
|
||||
|
||||
public bool ClientCanDrag(CanDragEventArgs eventArgs)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void HandleNetworkMessage(ComponentMessage message, INetChannel netChannel, ICommonSession? session = null)
|
||||
{
|
||||
if (!Owner.TryGetComponent(out ISpriteComponent? sprite))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (message)
|
||||
{
|
||||
case BodyPartAddedMessage partAdded:
|
||||
sprite.LayerSetVisible(partAdded.RSIMap, true);
|
||||
sprite.LayerSetRSI(partAdded.RSIMap, partAdded.RSIPath);
|
||||
sprite.LayerSetState(partAdded.RSIMap, partAdded.RSIState);
|
||||
break;
|
||||
case BodyPartRemovedMessage partRemoved:
|
||||
sprite.LayerSetVisible(partRemoved.RSIMap, false);
|
||||
|
||||
if (!partRemoved.Dropped.HasValue ||
|
||||
!_entityManager.TryGetEntity(partRemoved.Dropped.Value, out var entity) ||
|
||||
!entity.TryGetComponent(out ISpriteComponent? droppedSprite))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
var color = sprite[partRemoved.RSIMap].Color;
|
||||
|
||||
droppedSprite.LayerSetColor(0, color);
|
||||
break;
|
||||
case MechanismSpriteAddedMessage mechanismAdded:
|
||||
sprite.LayerSetVisible(mechanismAdded.RSIMap, true);
|
||||
break;
|
||||
case MechanismSpriteRemovedMessage mechanismRemoved:
|
||||
sprite.LayerSetVisible(mechanismRemoved.RSIMap, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,13 @@
|
||||
using System.Collections.Generic;
|
||||
using Content.Shared.Health.BodySystem.BodyScanner;
|
||||
using Content.Shared.Body.Scanner;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.GameObjects.Components.UserInterface;
|
||||
using Robust.Shared.GameObjects.Components.UserInterface;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Content.Client.Health.BodySystem.BodyScanner
|
||||
namespace Content.Client.GameObjects.Components.Body.Scanner
|
||||
{
|
||||
[UsedImplicitly]
|
||||
public class BodyScannerBoundUserInterface : BoundUserInterface
|
||||
{
|
||||
[ViewVariables]
|
||||
@@ -17,9 +19,7 @@ namespace Content.Client.Health.BodySystem.BodyScanner
|
||||
[ViewVariables]
|
||||
private Dictionary<string, BodyScannerBodyPartData> _parts;
|
||||
|
||||
public BodyScannerBoundUserInterface(ClientUserInterfaceComponent owner, object uiKey) : base(owner, uiKey)
|
||||
{
|
||||
}
|
||||
public BodyScannerBoundUserInterface(ClientUserInterfaceComponent owner, object uiKey) : base(owner, uiKey) { }
|
||||
|
||||
protected override void Open()
|
||||
{
|
||||
@@ -34,7 +34,9 @@ namespace Content.Client.Health.BodySystem.BodyScanner
|
||||
base.UpdateState(state);
|
||||
|
||||
if (!(state is BodyScannerInterfaceState scannerState))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_template = scannerState.Template;
|
||||
_parts = scannerState.Parts;
|
||||
@@ -45,7 +47,13 @@ namespace Content.Client.Health.BodySystem.BodyScanner
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
_display.Dispose();
|
||||
_template = null;
|
||||
_parts.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using Content.Shared.Body.Scanner;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Maths;
|
||||
using static Robust.Client.UserInterface.Controls.ItemList;
|
||||
|
||||
namespace Content.Client.GameObjects.Components.Body.Scanner
|
||||
{
|
||||
public sealed class BodyScannerDisplay : SS14Window
|
||||
{
|
||||
private BodyScannerTemplateData _template;
|
||||
|
||||
private Dictionary<string, BodyScannerBodyPartData> _parts;
|
||||
|
||||
private List<string> _slots;
|
||||
|
||||
private BodyScannerBodyPartData _currentBodyPart;
|
||||
|
||||
public BodyScannerDisplay(BodyScannerBoundUserInterface owner)
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
Owner = owner;
|
||||
Title = Loc.GetString("Body Scanner");
|
||||
|
||||
var hSplit = new HBoxContainer
|
||||
{
|
||||
Children =
|
||||
{
|
||||
// Left half
|
||||
new ScrollContainer
|
||||
{
|
||||
SizeFlagsHorizontal = SizeFlags.FillExpand,
|
||||
Children =
|
||||
{
|
||||
(BodyPartList = new ItemList())
|
||||
}
|
||||
},
|
||||
// Right half
|
||||
new VBoxContainer
|
||||
{
|
||||
SizeFlagsHorizontal = SizeFlags.FillExpand,
|
||||
Children =
|
||||
{
|
||||
// Top half of the right half
|
||||
new VBoxContainer
|
||||
{
|
||||
SizeFlagsVertical = SizeFlags.FillExpand,
|
||||
Children =
|
||||
{
|
||||
(BodyPartLabel = new Label()),
|
||||
new HBoxContainer
|
||||
{
|
||||
Children =
|
||||
{
|
||||
new Label
|
||||
{
|
||||
Text = "Health: "
|
||||
},
|
||||
(BodyPartHealth = new Label())
|
||||
}
|
||||
},
|
||||
new ScrollContainer
|
||||
{
|
||||
SizeFlagsVertical = SizeFlags.FillExpand,
|
||||
Children =
|
||||
{
|
||||
(MechanismList = new ItemList())
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
// Bottom half of the right half
|
||||
(MechanismInfoLabel = new RichTextLabel
|
||||
{
|
||||
SizeFlagsVertical = SizeFlags.FillExpand
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Contents.AddChild(hSplit);
|
||||
|
||||
BodyPartList.OnItemSelected += BodyPartOnItemSelected;
|
||||
MechanismList.OnItemSelected += MechanismOnItemSelected;
|
||||
}
|
||||
|
||||
public BodyScannerBoundUserInterface Owner { get; }
|
||||
|
||||
protected override Vector2? CustomSize => (800, 600);
|
||||
|
||||
private ItemList BodyPartList { get; }
|
||||
|
||||
private Label BodyPartLabel { get; }
|
||||
|
||||
private Label BodyPartHealth { get; }
|
||||
|
||||
private ItemList MechanismList { get; }
|
||||
|
||||
private RichTextLabel MechanismInfoLabel { get; }
|
||||
|
||||
public void UpdateDisplay(BodyScannerTemplateData template, Dictionary<string, BodyScannerBodyPartData> parts)
|
||||
{
|
||||
_template = template;
|
||||
_parts = parts;
|
||||
_slots = new List<string>();
|
||||
BodyPartList.Clear();
|
||||
|
||||
foreach (var slotName in _parts.Keys)
|
||||
{
|
||||
// We have to do this since ItemLists only return the index of what item is
|
||||
// selected and dictionaries don't allow you to explicitly grab things by index.
|
||||
// So we put the contents of the dictionary into a list so
|
||||
// that we can grab the list by index. I don't know either.
|
||||
_slots.Add(slotName);
|
||||
|
||||
BodyPartList.AddItem(Loc.GetString(slotName));
|
||||
}
|
||||
}
|
||||
|
||||
public void BodyPartOnItemSelected(ItemListSelectedEventArgs args)
|
||||
{
|
||||
if (_parts.TryGetValue(_slots[args.ItemIndex], out _currentBodyPart)) {
|
||||
UpdateBodyPartBox(_currentBodyPart, _slots[args.ItemIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateBodyPartBox(BodyScannerBodyPartData part, string slotName)
|
||||
{
|
||||
BodyPartLabel.Text = $"{Loc.GetString(slotName)}: {Loc.GetString(part.Name)}";
|
||||
BodyPartHealth.Text = $"{part.CurrentDurability}/{part.MaxDurability}";
|
||||
|
||||
MechanismList.Clear();
|
||||
foreach (var mechanism in part.Mechanisms) {
|
||||
MechanismList.AddItem(mechanism.Name);
|
||||
}
|
||||
}
|
||||
|
||||
public void MechanismOnItemSelected(ItemListSelectedEventArgs args)
|
||||
{
|
||||
UpdateMechanismBox(_currentBodyPart.Mechanisms[args.ItemIndex]);
|
||||
}
|
||||
|
||||
private void UpdateMechanismBox(BodyScannerMechanismData mechanism)
|
||||
{
|
||||
// TODO: Improve UI
|
||||
if (mechanism == null)
|
||||
{
|
||||
MechanismInfoLabel.SetMessage("");
|
||||
return;
|
||||
}
|
||||
|
||||
var message =
|
||||
Loc.GetString(
|
||||
$"{mechanism.Name}\nHealth: {mechanism.CurrentDurability}/{mechanism.MaxDurability}\n{mechanism.Description}");
|
||||
|
||||
MechanismInfoLabel.SetMessage(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,29 +1,30 @@
|
||||
using Content.Shared.Health.BodySystem.Surgery;
|
||||
#nullable enable
|
||||
using Content.Shared.Body.Surgery;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.GameObjects.Components.UserInterface;
|
||||
using Robust.Shared.GameObjects.Components.UserInterface;
|
||||
|
||||
namespace Content.Client.Health.BodySystem.Surgery
|
||||
namespace Content.Client.GameObjects.Components.Body.Surgery
|
||||
{
|
||||
|
||||
//TODO : Make window close if target or surgery tool gets too far away from user.
|
||||
// TODO : Make window close if target or surgery tool gets too far away from user.
|
||||
|
||||
/// <summary>
|
||||
/// Generic client-side UI list popup that allows users to choose from an option of limbs or organs to operate on.
|
||||
/// Generic client-side UI list popup that allows users to choose from an option
|
||||
/// of limbs or organs to operate on.
|
||||
/// </summary>
|
||||
[UsedImplicitly]
|
||||
public class GenericSurgeryBoundUserInterface : BoundUserInterface
|
||||
{
|
||||
private GenericSurgeryWindow? _window;
|
||||
|
||||
private GenericSurgeryWindow _window;
|
||||
|
||||
public GenericSurgeryBoundUserInterface(ClientUserInterfaceComponent owner, object uiKey) : base(owner, uiKey)
|
||||
{
|
||||
|
||||
}
|
||||
public GenericSurgeryBoundUserInterface(ClientUserInterfaceComponent owner, object uiKey) : base(owner, uiKey) { }
|
||||
|
||||
protected override void Open()
|
||||
{
|
||||
_window = new GenericSurgeryWindow();
|
||||
|
||||
_window.OpenCentered();
|
||||
_window.OnClose += Close;
|
||||
}
|
||||
|
||||
protected override void ReceiveMessage(BoundUserInterfaceMessage message)
|
||||
@@ -44,40 +45,42 @@ namespace Content.Client.Health.BodySystem.Surgery
|
||||
|
||||
private void HandleBodyPartRequest(RequestBodyPartSurgeryUIMessage msg)
|
||||
{
|
||||
_window.BuildDisplay(msg.Targets, BodyPartSelectedCallback);
|
||||
_window?.BuildDisplay(msg.Targets, BodyPartSelectedCallback);
|
||||
}
|
||||
|
||||
private void HandleMechanismRequest(RequestMechanismSurgeryUIMessage msg)
|
||||
{
|
||||
_window.BuildDisplay(msg.Targets, MechanismSelectedCallback);
|
||||
_window?.BuildDisplay(msg.Targets, MechanismSelectedCallback);
|
||||
}
|
||||
|
||||
private void HandleBodyPartSlotRequest(RequestBodyPartSlotSurgeryUIMessage msg)
|
||||
{
|
||||
_window.BuildDisplay(msg.Targets, BodyPartSlotSelectedCallback);
|
||||
_window?.BuildDisplay(msg.Targets, BodyPartSlotSelectedCallback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void BodyPartSelectedCallback(int selectedOptionData)
|
||||
{
|
||||
SendMessage(new ReceiveBodyPartSurgeryUIMessage(selectedOptionData));
|
||||
}
|
||||
|
||||
private void MechanismSelectedCallback(int selectedOptionData)
|
||||
{
|
||||
SendMessage(new ReceiveMechanismSurgeryUIMessage(selectedOptionData));
|
||||
}
|
||||
|
||||
private void BodyPartSlotSelectedCallback(int selectedOptionData)
|
||||
{
|
||||
SendMessage(new ReceiveBodyPartSlotSurgeryUIMessage(selectedOptionData));
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
base.Dispose(disposing);
|
||||
if (!disposing)
|
||||
return;
|
||||
_window.Dispose();
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
_window?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,58 +1,62 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Maths;
|
||||
|
||||
namespace Content.Client.Health.BodySystem.Surgery
|
||||
namespace Content.Client.GameObjects.Components.Body.Surgery
|
||||
{
|
||||
public class GenericSurgeryWindow : SS14Window
|
||||
{
|
||||
public delegate void CloseCallback();
|
||||
public delegate void OptionSelectedCallback(int selectedOptionData);
|
||||
|
||||
private Control _vSplitContainer;
|
||||
private VBoxContainer _optionsBox;
|
||||
private readonly VBoxContainer _optionsBox;
|
||||
private OptionSelectedCallback _optionSelectedCallback;
|
||||
|
||||
|
||||
protected override Vector2? CustomSize => (300, 400);
|
||||
|
||||
public GenericSurgeryWindow()
|
||||
{
|
||||
Title = Loc.GetString("Select surgery target...");
|
||||
RectClipContent = true;
|
||||
_vSplitContainer = new VBoxContainer();
|
||||
var listScrollContainer = new ScrollContainer
|
||||
{
|
||||
SizeFlagsVertical = SizeFlags.FillExpand,
|
||||
SizeFlagsHorizontal = SizeFlags.FillExpand,
|
||||
HScrollEnabled = true,
|
||||
VScrollEnabled = true
|
||||
};
|
||||
_optionsBox = new VBoxContainer
|
||||
{
|
||||
SizeFlagsHorizontal = SizeFlags.FillExpand
|
||||
};
|
||||
listScrollContainer.AddChild(_optionsBox);
|
||||
_vSplitContainer.AddChild(listScrollContainer);
|
||||
Contents.AddChild(_vSplitContainer);
|
||||
|
||||
var vSplitContainer = new VBoxContainer
|
||||
{
|
||||
Children =
|
||||
{
|
||||
new ScrollContainer
|
||||
{
|
||||
SizeFlagsVertical = SizeFlags.FillExpand,
|
||||
SizeFlagsHorizontal = SizeFlags.FillExpand,
|
||||
HScrollEnabled = true,
|
||||
VScrollEnabled = true,
|
||||
Children =
|
||||
{
|
||||
(_optionsBox = new VBoxContainer
|
||||
{
|
||||
SizeFlagsHorizontal = SizeFlags.FillExpand
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Contents.AddChild(vSplitContainer);
|
||||
}
|
||||
|
||||
public void BuildDisplay(Dictionary<string, int> data, OptionSelectedCallback callback)
|
||||
{
|
||||
_optionsBox.DisposeAllChildren();
|
||||
_optionSelectedCallback = callback;
|
||||
|
||||
foreach (var (displayText, callbackData) in data)
|
||||
{
|
||||
var button = new SurgeryButton(callbackData);
|
||||
button.SetOnToggleBehavior(OnButtonPressed);
|
||||
button.SetDisplayText(CultureInfo.CurrentCulture.TextInfo.ToTitleCase(displayText));
|
||||
|
||||
button.SetOnToggleBehavior(OnButtonPressed);
|
||||
button.SetDisplayText(Loc.GetString(displayText));
|
||||
|
||||
_optionsBox.AddChild(button);
|
||||
}
|
||||
@@ -60,17 +64,23 @@ namespace Content.Client.Health.BodySystem.Surgery
|
||||
|
||||
private void OnButtonPressed(BaseButton.ButtonEventArgs args)
|
||||
{
|
||||
var pressedButton = (SurgeryButton)args.Button.Parent;
|
||||
_optionSelectedCallback(pressedButton.CallbackData);
|
||||
if (args.Button.Parent is SurgeryButton surgery)
|
||||
{
|
||||
_optionSelectedCallback(surgery.CallbackData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SurgeryButton : PanelContainer
|
||||
{
|
||||
public Button Button { get; }
|
||||
|
||||
private SpriteView SpriteView { get; }
|
||||
|
||||
private Control EntityControl { get; }
|
||||
|
||||
private Label DisplayText { get; }
|
||||
|
||||
public int CallbackData { get; }
|
||||
|
||||
public SurgeryButton(int callbackData)
|
||||
@@ -84,25 +94,28 @@ namespace Content.Client.Health.BodySystem.Surgery
|
||||
ToggleMode = true,
|
||||
MouseFilter = MouseFilterMode.Stop
|
||||
};
|
||||
|
||||
AddChild(Button);
|
||||
var hBoxContainer = new HBoxContainer();
|
||||
SpriteView = new SpriteView
|
||||
|
||||
AddChild(new HBoxContainer
|
||||
{
|
||||
CustomMinimumSize = new Vector2(32.0f, 32.0f)
|
||||
};
|
||||
DisplayText = new Label
|
||||
{
|
||||
SizeFlagsVertical = SizeFlags.ShrinkCenter,
|
||||
Text = "N/A",
|
||||
};
|
||||
hBoxContainer.AddChild(SpriteView);
|
||||
hBoxContainer.AddChild(DisplayText);
|
||||
EntityControl = new Control
|
||||
{
|
||||
SizeFlagsHorizontal = SizeFlags.FillExpand
|
||||
};
|
||||
hBoxContainer.AddChild(EntityControl);
|
||||
AddChild(hBoxContainer);
|
||||
Children =
|
||||
{
|
||||
(SpriteView = new SpriteView
|
||||
{
|
||||
CustomMinimumSize = new Vector2(32.0f, 32.0f)
|
||||
}),
|
||||
(DisplayText = new Label
|
||||
{
|
||||
SizeFlagsVertical = SizeFlags.ShrinkCenter,
|
||||
Text = "N/A",
|
||||
}),
|
||||
(new Control
|
||||
{
|
||||
SizeFlagsHorizontal = SizeFlags.FillExpand
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void SetDisplayText(string text)
|
||||
@@ -37,7 +37,7 @@ namespace Content.Client.GameObjects.Components
|
||||
/// <returns>True if the click worked, false otherwise.</returns>
|
||||
public bool CheckClick(Vector2 worldPos, out int drawDepth, out uint renderOrder)
|
||||
{
|
||||
if (!Owner.TryGetComponent(out ISpriteComponent sprite) || !sprite.Visible)
|
||||
if (!Owner.TryGetComponent(out ISpriteComponent? sprite) || !sprite.Visible)
|
||||
{
|
||||
drawDepth = default;
|
||||
renderOrder = default;
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Content.Shared.GameObjects.Components.Damage;
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
namespace Content.Client.GameObjects.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Fuck I really hate doing this
|
||||
/// TODO: make sure the client only gets damageable component on the clientside entity for its player mob
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public class DamageableComponent : SharedDamageableComponent
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Name => "Damageable";
|
||||
|
||||
public Dictionary<DamageType, int> CurrentDamage = new Dictionary<DamageType, int>();
|
||||
|
||||
public override void HandleComponentState(ComponentState curState, ComponentState nextState)
|
||||
{
|
||||
base.HandleComponentState(curState, nextState);
|
||||
|
||||
if(curState is DamageComponentState damagestate)
|
||||
{
|
||||
CurrentDamage = damagestate.CurrentDamage;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
#nullable enable
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.GameObjects.Components.UserInterface;
|
||||
using Robust.Shared.GameObjects.Components.UserInterface;
|
||||
using Robust.Shared.Localization;
|
||||
using static Content.Shared.GameObjects.Components.Disposal.SharedDisposalRouterComponent;
|
||||
|
||||
namespace Content.Client.GameObjects.Components.Disposal
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a <see cref="DisposalRouterWindow"/> and updates it when new server messages are received.
|
||||
/// </summary>
|
||||
[UsedImplicitly]
|
||||
public class DisposalRouterBoundUserInterface : BoundUserInterface
|
||||
{
|
||||
private DisposalRouterWindow? _window;
|
||||
|
||||
public DisposalRouterBoundUserInterface(ClientUserInterfaceComponent owner, object uiKey) : base(owner, uiKey)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void Open()
|
||||
{
|
||||
base.Open();
|
||||
|
||||
_window = new DisposalRouterWindow();
|
||||
|
||||
_window.OpenCentered();
|
||||
_window.OnClose += Close;
|
||||
|
||||
_window.Confirm.OnPressed += _ => ButtonPressed(UiAction.Ok, _window.TagInput.Text);
|
||||
_window.TagInput.OnTextEntered += args => ButtonPressed(UiAction.Ok, args.Text);
|
||||
|
||||
}
|
||||
|
||||
private void ButtonPressed(UiAction action, string tag)
|
||||
{
|
||||
SendMessage(new UiActionMessage(action, tag));
|
||||
_window?.Close();
|
||||
}
|
||||
|
||||
protected override void UpdateState(BoundUserInterfaceState state)
|
||||
{
|
||||
base.UpdateState(state);
|
||||
|
||||
if (!(state is DisposalRouterUserInterfaceState cast))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_window?.UpdateState(cast);
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
base.Dispose(disposing);
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
_window?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using Content.Shared.GameObjects.Components.Disposal;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Maths;
|
||||
using static Content.Shared.GameObjects.Components.Disposal.SharedDisposalRouterComponent;
|
||||
|
||||
namespace Content.Client.GameObjects.Components.Disposal
|
||||
{
|
||||
/// <summary>
|
||||
/// Client-side UI used to control a <see cref="SharedDisposalRouterComponent"/>
|
||||
/// </summary>
|
||||
public class DisposalRouterWindow : SS14Window
|
||||
{
|
||||
public readonly LineEdit TagInput;
|
||||
public readonly Button Confirm;
|
||||
|
||||
protected override Vector2? CustomSize => (400, 80);
|
||||
|
||||
public DisposalRouterWindow()
|
||||
{
|
||||
Title = Loc.GetString("Disposal Router");
|
||||
|
||||
Contents.AddChild(new VBoxContainer
|
||||
{
|
||||
Children =
|
||||
{
|
||||
new Label {Text = Loc.GetString("Tags:")},
|
||||
new Control {CustomMinimumSize = (0, 10)},
|
||||
new HBoxContainer
|
||||
{
|
||||
Children =
|
||||
{
|
||||
(TagInput = new LineEdit {SizeFlagsHorizontal = SizeFlags.Expand, CustomMinimumSize = (320, 0),
|
||||
ToolTip = Loc.GetString("A comma separated list of tags"), IsValid = tags => TagRegex.IsMatch(tags)}),
|
||||
new Control {CustomMinimumSize = (10, 0)},
|
||||
(Confirm = new Button {Text = Loc.GetString("Confirm")})
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public void UpdateState(DisposalRouterUserInterfaceState state)
|
||||
{
|
||||
TagInput.Text = state.Tags;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
#nullable enable
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.GameObjects.Components.UserInterface;
|
||||
using Robust.Shared.GameObjects.Components.UserInterface;
|
||||
using Robust.Shared.Localization;
|
||||
using static Content.Shared.GameObjects.Components.Disposal.SharedDisposalTaggerComponent;
|
||||
|
||||
namespace Content.Client.GameObjects.Components.Disposal
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a <see cref="DisposalTaggerWindow"/> and updates it when new server messages are received.
|
||||
/// </summary>
|
||||
[UsedImplicitly]
|
||||
public class DisposalTaggerBoundUserInterface : BoundUserInterface
|
||||
{
|
||||
private DisposalTaggerWindow? _window;
|
||||
|
||||
public DisposalTaggerBoundUserInterface(ClientUserInterfaceComponent owner, object uiKey) : base(owner, uiKey)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void Open()
|
||||
{
|
||||
base.Open();
|
||||
|
||||
_window = new DisposalTaggerWindow();
|
||||
|
||||
_window.OpenCentered();
|
||||
_window.OnClose += Close;
|
||||
|
||||
_window.Confirm.OnPressed += _ => ButtonPressed(UiAction.Ok, _window.TagInput.Text);
|
||||
_window.TagInput.OnTextEntered += args => ButtonPressed(UiAction.Ok, args.Text);
|
||||
|
||||
}
|
||||
|
||||
private void ButtonPressed(UiAction action, string tag)
|
||||
{
|
||||
SendMessage(new UiActionMessage(action, tag));
|
||||
_window?.Close();
|
||||
}
|
||||
|
||||
protected override void UpdateState(BoundUserInterfaceState state)
|
||||
{
|
||||
base.UpdateState(state);
|
||||
|
||||
if (!(state is DisposalTaggerUserInterfaceState cast))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_window?.UpdateState(cast);
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
base.Dispose(disposing);
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
_window?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using Content.Shared.GameObjects.Components.Disposal;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Maths;
|
||||
using static Content.Shared.GameObjects.Components.Disposal.SharedDisposalTaggerComponent;
|
||||
|
||||
namespace Content.Client.GameObjects.Components.Disposal
|
||||
{
|
||||
/// <summary>
|
||||
/// Client-side UI used to control a <see cref="SharedDisposalTaggerComponent"/>
|
||||
/// </summary>
|
||||
public class DisposalTaggerWindow : SS14Window
|
||||
{
|
||||
public readonly LineEdit TagInput;
|
||||
public readonly Button Confirm;
|
||||
|
||||
protected override Vector2? CustomSize => (400, 80);
|
||||
|
||||
public DisposalTaggerWindow()
|
||||
{
|
||||
Title = Loc.GetString("Disposal Tagger");
|
||||
|
||||
Contents.AddChild(new VBoxContainer
|
||||
{
|
||||
Children =
|
||||
{
|
||||
new Label {Text = Loc.GetString("Tag:")},
|
||||
new Control {CustomMinimumSize = (0, 10)},
|
||||
new HBoxContainer
|
||||
{
|
||||
Children =
|
||||
{
|
||||
(TagInput = new LineEdit {SizeFlagsHorizontal = SizeFlags.Expand, CustomMinimumSize = (320, 0),
|
||||
IsValid = tag => TagRegex.IsMatch(tag)}),
|
||||
new Control {CustomMinimumSize = (10, 0)},
|
||||
(Confirm = new Button {Text = Loc.GetString("Confirm")})
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public void UpdateState(DisposalTaggerUserInterfaceState state)
|
||||
{
|
||||
TagInput.Text = state.Tag;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -148,7 +148,7 @@ namespace Content.Client.GameObjects.Components.Items
|
||||
return;
|
||||
}
|
||||
|
||||
if (!entity.TryGetComponent(out ItemComponent item)) return;
|
||||
if (!entity.TryGetComponent(out ItemComponent? item)) return;
|
||||
|
||||
var maybeInHands = item.GetInHandStateInfo(hand.Location);
|
||||
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.GameObjects.Components.UserInterface;
|
||||
using Robust.Shared.GameObjects.Components.UserInterface;
|
||||
using static Content.Shared.GameObjects.Components.Medical.SharedMedicalScannerComponent;
|
||||
|
||||
namespace Content.Client.GameObjects.Components.MedicalScanner
|
||||
{
|
||||
[UsedImplicitly]
|
||||
public class MedicalScannerBoundUserInterface : BoundUserInterface
|
||||
{
|
||||
public MedicalScannerBoundUserInterface(ClientUserInterfaceComponent owner, object uiKey) : base(owner, uiKey)
|
||||
@@ -20,6 +22,7 @@ namespace Content.Client.GameObjects.Components.MedicalScanner
|
||||
Title = Owner.Owner.Name,
|
||||
};
|
||||
_window.OnClose += Close;
|
||||
_window.ScanButton.OnPressed += _ => SendMessage(new UiButtonPressedMessage(UiButton.ScanDNA));
|
||||
_window.OpenCentered();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
using System.Text;
|
||||
using Content.Shared.Damage;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Maths;
|
||||
using static Content.Shared.GameObjects.Components.Medical.SharedMedicalScannerComponent;
|
||||
|
||||
@@ -8,28 +12,63 @@ namespace Content.Client.GameObjects.Components.MedicalScanner
|
||||
{
|
||||
public class MedicalScannerWindow : SS14Window
|
||||
{
|
||||
public readonly Button ScanButton;
|
||||
private readonly Label _diagnostics;
|
||||
protected override Vector2? CustomSize => (485, 90);
|
||||
|
||||
public MedicalScannerWindow()
|
||||
{
|
||||
Contents.AddChild(new VBoxContainer
|
||||
{
|
||||
Children =
|
||||
{
|
||||
(ScanButton = new Button
|
||||
{
|
||||
Text = "Scan and Save DNA"
|
||||
}),
|
||||
(_diagnostics = new Label
|
||||
{
|
||||
Text = ""
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void Populate(MedicalScannerBoundUserInterfaceState state)
|
||||
{
|
||||
Contents.RemoveAllChildren();
|
||||
var text = new StringBuilder();
|
||||
if (state.MaxHealth == 0)
|
||||
{
|
||||
text.Append("No patient data.");
|
||||
} else
|
||||
{
|
||||
text.Append($"Patient's health: {state.CurrentHealth}/{state.MaxHealth}\n");
|
||||
|
||||
if (state.DamageDictionary != null)
|
||||
{
|
||||
foreach (var (dmgType, amount) in state.DamageDictionary)
|
||||
{
|
||||
text.Append($"\n{dmgType}: {amount}");
|
||||
}
|
||||
}
|
||||
if (!state.Entity.HasValue ||
|
||||
!state.HasDamage() ||
|
||||
!IoCManager.Resolve<IEntityManager>().TryGetEntity(state.Entity.Value, out var entity))
|
||||
{
|
||||
_diagnostics.Text = Loc.GetString("No patient data.");
|
||||
ScanButton.Disabled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
text.Append($"{entity.Name}{Loc.GetString("'s health:")}\n");
|
||||
|
||||
foreach (var (@class, classAmount) in state.DamageClasses)
|
||||
{
|
||||
text.Append($"\n{Loc.GetString("{0}: {1}", @class, classAmount)}");
|
||||
|
||||
foreach (var type in @class.ToTypes())
|
||||
{
|
||||
if (!state.DamageTypes.TryGetValue(type, out var typeAmount))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
text.Append($"\n- {Loc.GetString("{0}: {1}", type, typeAmount)}");
|
||||
}
|
||||
|
||||
text.Append("\n");
|
||||
}
|
||||
|
||||
_diagnostics.Text = text.ToString();
|
||||
ScanButton.Disabled = state.IsScanned;
|
||||
}
|
||||
Contents.AddChild(new Label(){Text = text.ToString()});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace Content.Client.GameObjects.Components.Mobs
|
||||
private const float RestoreRateRamp = 0.1f;
|
||||
|
||||
// The maximum magnitude of the kick applied to the camera at any point.
|
||||
private const float KickMagnitudeMax = 5f;
|
||||
private const float KickMagnitudeMax = 2f;
|
||||
|
||||
private Vector2 _currentKick;
|
||||
private float _lastKickTime;
|
||||
|
||||
@@ -44,8 +44,8 @@ namespace Content.Client.GameObjects.Components.Mobs
|
||||
sprite.LayerSetColor(HumanoidVisualLayers.Hair, Appearance.HairColor);
|
||||
sprite.LayerSetColor(HumanoidVisualLayers.FacialHair, Appearance.FacialHairColor);
|
||||
|
||||
sprite.LayerSetState(HumanoidVisualLayers.Chest, Sex == Sex.Male ? "human_chest_m" : "human_chest_f");
|
||||
sprite.LayerSetState(HumanoidVisualLayers.Head, Sex == Sex.Male ? "human_head_m" : "human_head_f");
|
||||
sprite.LayerSetState(HumanoidVisualLayers.Chest, Sex == Sex.Male ? "torso_m" : "torso_f");
|
||||
sprite.LayerSetState(HumanoidVisualLayers.Head, Sex == Sex.Male ? "head_m" : "head_f");
|
||||
|
||||
sprite.LayerSetVisible(HumanoidVisualLayers.StencilMask, Sex == Sex.Female);
|
||||
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
using Content.Client.GameObjects.Components.Disposal;
|
||||
using Content.Client.Interfaces.GameObjects.Components.Interaction;
|
||||
using Content.Shared.GameObjects.Components.Mobs;
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
namespace Content.Client.GameObjects.Components.Mobs
|
||||
{
|
||||
[RegisterComponent]
|
||||
[ComponentReference(typeof(SharedSpeciesComponent))]
|
||||
public class SpeciesComponent : SharedSpeciesComponent, IClientDraggable
|
||||
{
|
||||
bool IClientDraggable.ClientCanDropOn(CanDropEventArgs eventArgs)
|
||||
{
|
||||
return eventArgs.Target.HasComponent<DisposalUnitComponent>();
|
||||
}
|
||||
|
||||
bool IClientDraggable.ClientCanDrag(CanDragEventArgs eventArgs)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -34,7 +34,7 @@ namespace Content.Client.GameObjects.Components.Mobs
|
||||
WalkModifierOverride = state.WalkModifierOverride;
|
||||
RunModifierOverride = state.RunModifierOverride;
|
||||
|
||||
if (Owner.TryGetComponent(out MovementSpeedModifierComponent movement))
|
||||
if (Owner.TryGetComponent(out MovementSpeedModifierComponent? movement))
|
||||
{
|
||||
movement.RefreshMovementSpeedModifiers();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
using Robust.Shared.GameObjects;
|
||||
using Content.Shared.GameObjects.Components.Movement;
|
||||
|
||||
namespace Content.Client.GameObjects.Components.Movement
|
||||
{
|
||||
[RegisterComponent]
|
||||
[ComponentReference(typeof(IClimbable))]
|
||||
public class ClimbableComponent : SharedClimbableComponent
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameObjects.Components;
|
||||
using Content.Shared.GameObjects.Components.Movement;
|
||||
using Content.Client.Interfaces.GameObjects.Components.Interaction;
|
||||
using Content.Shared.Physics;
|
||||
|
||||
namespace Content.Client.GameObjects.Components.Movement
|
||||
{
|
||||
[RegisterComponent]
|
||||
public class ClimbingComponent : SharedClimbingComponent, IClientDraggable
|
||||
{
|
||||
public override void HandleComponentState(ComponentState curState, ComponentState nextState)
|
||||
{
|
||||
if (!(curState is ClimbModeComponentState climbModeState) || Body == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
IsClimbing = climbModeState.Climbing;
|
||||
}
|
||||
|
||||
public override bool IsClimbing { get; set; }
|
||||
|
||||
bool IClientDraggable.ClientCanDropOn(CanDropEventArgs eventArgs)
|
||||
{
|
||||
return eventArgs.Target.HasComponent<IClimbable>();
|
||||
}
|
||||
|
||||
bool IClientDraggable.ClientCanDrag(CanDragEventArgs eventArgs)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,7 @@ namespace Content.Client.GameObjects.Components.Nutrition
|
||||
|
||||
_currentHungerThreshold = hunger.CurrentThreshold;
|
||||
|
||||
if (Owner.TryGetComponent(out MovementSpeedModifierComponent movement))
|
||||
if (Owner.TryGetComponent(out MovementSpeedModifierComponent? movement))
|
||||
{
|
||||
movement.RefreshMovementSpeedModifiers();
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace Content.Client.GameObjects.Components.Nutrition
|
||||
|
||||
_currentThirstThreshold = thirst.CurrentThreshold;
|
||||
|
||||
if (Owner.TryGetComponent(out MovementSpeedModifierComponent movement))
|
||||
if (Owner.TryGetComponent(out MovementSpeedModifierComponent? movement))
|
||||
{
|
||||
movement.RefreshMovementSpeedModifiers();
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Content.Shared.GameObjects.Components.PDA;
|
||||
using Content.Shared.GameObjects.Components.PDA;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.Interfaces.GameObjects.Components;
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace Content.Client.GameObjects.Components.PDA
|
||||
private enum PDAVisualLayers
|
||||
{
|
||||
Base,
|
||||
Unlit
|
||||
Flashlight
|
||||
}
|
||||
|
||||
|
||||
@@ -22,13 +22,13 @@ namespace Content.Client.GameObjects.Components.PDA
|
||||
return;
|
||||
}
|
||||
var sprite = component.Owner.GetComponent<ISpriteComponent>();
|
||||
sprite.LayerSetVisible(PDAVisualLayers.Unlit, false);
|
||||
if(!component.TryGetData<bool>(PDAVisuals.ScreenLit, out var isScreenLit))
|
||||
sprite.LayerSetVisible(PDAVisualLayers.Flashlight, false);
|
||||
if(!component.TryGetData<bool>(PDAVisuals.FlashlightLit, out var isScreenLit))
|
||||
{
|
||||
return;
|
||||
}
|
||||
sprite.LayerSetState(PDAVisualLayers.Unlit, "unlit_pda_screen");
|
||||
sprite.LayerSetVisible(PDAVisualLayers.Unlit, isScreenLit);
|
||||
sprite.LayerSetState(PDAVisualLayers.Flashlight, "light_overlay");
|
||||
sprite.LayerSetVisible(PDAVisualLayers.Flashlight, isScreenLit);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using Content.Shared.GameObjects.Components.Mobs;
|
||||
using Content.Shared.GameObjects.Components.Rotation;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.Animations;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.GameObjects.Components.Animations;
|
||||
@@ -7,22 +8,23 @@ using Robust.Client.Interfaces.GameObjects.Components;
|
||||
using Robust.Shared.Animations;
|
||||
using Robust.Shared.Maths;
|
||||
|
||||
namespace Content.Client.GameObjects.Components.Mobs
|
||||
namespace Content.Client.GameObjects.Components.Rotation
|
||||
{
|
||||
public class SpeciesVisualizer : AppearanceVisualizer
|
||||
[UsedImplicitly]
|
||||
public class RotationVisualizer : AppearanceVisualizer
|
||||
{
|
||||
public override void OnChangeData(AppearanceComponent component)
|
||||
{
|
||||
base.OnChangeData(component);
|
||||
|
||||
if (component.TryGetData<SharedSpeciesComponent.MobState>(SharedSpeciesComponent.MobVisuals.RotationState, out var state))
|
||||
if (component.TryGetData<RotationState>(RotationVisuals.RotationState, out var state))
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case SharedSpeciesComponent.MobState.Standing:
|
||||
case RotationState.Vertical:
|
||||
SetRotation(component, 0);
|
||||
break;
|
||||
case SharedSpeciesComponent.MobState.Down:
|
||||
case RotationState.Horizontal:
|
||||
SetRotation(component, Angle.FromDegrees(90));
|
||||
break;
|
||||
}
|
||||
@@ -40,7 +42,9 @@ namespace Content.Client.GameObjects.Components.Mobs
|
||||
}
|
||||
|
||||
if (animation.HasRunningAnimation("rotate"))
|
||||
{
|
||||
animation.Stop("rotate");
|
||||
}
|
||||
|
||||
animation.Play(new Animation
|
||||
{
|
||||
@@ -143,7 +143,7 @@ namespace Content.Client.GameObjects.EntitySystems.DoAfter
|
||||
{
|
||||
base.FrameUpdate(args);
|
||||
|
||||
if (AttachedEntity?.IsValid() != true || !AttachedEntity.TryGetComponent(out DoAfterComponent doAfterComponent))
|
||||
if (AttachedEntity?.IsValid() != true || !AttachedEntity.TryGetComponent(out DoAfterComponent? doAfterComponent))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ namespace Content.Client.GameObjects.EntitySystems.DoAfter
|
||||
Gui ??= new DoAfterGui();
|
||||
Gui.AttachedEntity = entity;
|
||||
|
||||
if (entity.TryGetComponent(out DoAfterComponent doAfterComponent))
|
||||
if (entity.TryGetComponent(out DoAfterComponent? doAfterComponent))
|
||||
{
|
||||
foreach (var (_, doAfter) in doAfterComponent.DoAfters)
|
||||
{
|
||||
@@ -87,7 +87,7 @@ namespace Content.Client.GameObjects.EntitySystems.DoAfter
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_player.TryGetComponent(out DoAfterComponent doAfterComponent))
|
||||
if (!_player.TryGetComponent(out DoAfterComponent? doAfterComponent))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,13 +1,19 @@
|
||||
using System;
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Content.Client.Atmos;
|
||||
using Content.Client.GameObjects.Components.Atmos;
|
||||
using Content.Shared.Atmos;
|
||||
using Content.Shared.GameObjects.EntitySystems;
|
||||
using Content.Shared.GameObjects.EntitySystems.Atmos;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.GameObjects.EntitySystems;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.Interfaces.Graphics.Overlays;
|
||||
using Robust.Client.Interfaces.ResourceManagement;
|
||||
using Robust.Client.ResourceManagement;
|
||||
using Robust.Client.Utility;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Interfaces.Map;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Maths;
|
||||
@@ -16,8 +22,9 @@ using Robust.Shared.Utility;
|
||||
namespace Content.Client.GameObjects.EntitySystems
|
||||
{
|
||||
[UsedImplicitly]
|
||||
public sealed class GasTileOverlaySystem : SharedGasTileOverlaySystem
|
||||
internal sealed class GasTileOverlaySystem : SharedGasTileOverlaySystem
|
||||
{
|
||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||
[Dependency] private readonly IResourceCache _resourceCache = default!;
|
||||
|
||||
private readonly Dictionary<float, Color> _fireCache = new Dictionary<float, Color>();
|
||||
@@ -36,19 +43,20 @@ namespace Content.Client.GameObjects.EntitySystems
|
||||
private readonly float[][] _fireFrameDelays = new float[FireStates][];
|
||||
private readonly int[] _fireFrameCounter = new int[FireStates];
|
||||
private readonly Texture[][] _fireFrames = new Texture[FireStates][];
|
||||
|
||||
private Dictionary<GridId, Dictionary<MapIndices, GasOverlayData>> _overlay = new Dictionary<GridId, Dictionary<MapIndices, GasOverlayData>>();
|
||||
|
||||
private Dictionary<GridId, Dictionary<MapIndices, GasOverlayChunk>> _tileData =
|
||||
new Dictionary<GridId, Dictionary<MapIndices, GasOverlayChunk>>();
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeNetworkEvent(new EntityEventHandler<GasTileOverlayMessage>(OnTileOverlayMessage));
|
||||
SubscribeNetworkEvent<GasOverlayMessage>(HandleGasOverlayMessage);
|
||||
_mapManager.OnGridRemoved += OnGridRemoved;
|
||||
|
||||
for (var i = 0; i < Atmospherics.TotalNumberOfGases; i++)
|
||||
{
|
||||
var gas = Atmospherics.GetGas(i);
|
||||
switch (gas.GasOverlay)
|
||||
var overlay = Atmospherics.GetOverlay(i);
|
||||
switch (overlay)
|
||||
{
|
||||
case SpriteSpecifier.Rsi animated:
|
||||
var rsi = _resourceCache.GetResource<RSIResource>(animated.RsiPath).RSI;
|
||||
@@ -82,13 +90,77 @@ namespace Content.Client.GameObjects.EntitySystems
|
||||
_fireFrameDelays[i] = state.GetDelays();
|
||||
_fireFrameCounter[i] = 0;
|
||||
}
|
||||
|
||||
var overlayManager = IoCManager.Resolve<IOverlayManager>();
|
||||
if(!overlayManager.HasOverlay(nameof(GasTileOverlay)))
|
||||
overlayManager.AddOverlay(new GasTileOverlay());
|
||||
}
|
||||
|
||||
private void HandleGasOverlayMessage(GasOverlayMessage message)
|
||||
{
|
||||
foreach (var (indices, data) in message.OverlayData)
|
||||
{
|
||||
var chunk = GetOrCreateChunk(message.GridId, indices);
|
||||
chunk.Update(data, indices);
|
||||
}
|
||||
}
|
||||
|
||||
// Slightly different to the server-side system version
|
||||
private GasOverlayChunk GetOrCreateChunk(GridId gridId, MapIndices indices)
|
||||
{
|
||||
if (!_tileData.TryGetValue(gridId, out var chunks))
|
||||
{
|
||||
chunks = new Dictionary<MapIndices, GasOverlayChunk>();
|
||||
_tileData[gridId] = chunks;
|
||||
}
|
||||
|
||||
var chunkIndices = GetGasChunkIndices(indices);
|
||||
|
||||
if (!chunks.TryGetValue(chunkIndices, out var chunk))
|
||||
{
|
||||
chunk = new GasOverlayChunk(gridId, chunkIndices);
|
||||
chunks[chunkIndices] = chunk;
|
||||
}
|
||||
|
||||
return chunk;
|
||||
}
|
||||
|
||||
public override void Shutdown()
|
||||
{
|
||||
base.Shutdown();
|
||||
_mapManager.OnGridRemoved -= OnGridRemoved;
|
||||
var overlayManager = IoCManager.Resolve<IOverlayManager>();
|
||||
if(!overlayManager.HasOverlay(nameof(GasTileOverlay)))
|
||||
overlayManager.RemoveOverlay(nameof(GasTileOverlay));
|
||||
}
|
||||
|
||||
private void OnGridRemoved(GridId gridId)
|
||||
{
|
||||
if (_tileData.ContainsKey(gridId))
|
||||
{
|
||||
_tileData.Remove(gridId);
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasData(GridId gridId)
|
||||
{
|
||||
return _tileData.ContainsKey(gridId);
|
||||
}
|
||||
|
||||
public (Texture, Color color)[] GetOverlays(GridId gridIndex, MapIndices indices)
|
||||
{
|
||||
if (!_overlay.TryGetValue(gridIndex, out var tiles) || !tiles.TryGetValue(indices, out var overlays))
|
||||
if (!_tileData.TryGetValue(gridIndex, out var chunks))
|
||||
return Array.Empty<(Texture, Color)>();
|
||||
|
||||
var chunkIndex = GetGasChunkIndices(indices);
|
||||
if (!chunks.TryGetValue(chunkIndex, out var chunk))
|
||||
return Array.Empty<(Texture, Color)>();
|
||||
|
||||
var overlays = chunk.GetData(indices);
|
||||
|
||||
if (overlays.Gas == null)
|
||||
return Array.Empty<(Texture, Color)>();
|
||||
|
||||
var fire = overlays.FireState != 0;
|
||||
var length = overlays.Gas.Length + (fire ? 1 : 0);
|
||||
|
||||
@@ -112,23 +184,6 @@ namespace Content.Client.GameObjects.EntitySystems
|
||||
return list;
|
||||
}
|
||||
|
||||
private void OnTileOverlayMessage(GasTileOverlayMessage ev)
|
||||
{
|
||||
if(ev.ClearAllOtherOverlays)
|
||||
_overlay.Clear();
|
||||
|
||||
foreach (var data in ev.OverlayData)
|
||||
{
|
||||
if (!_overlay.TryGetValue(data.GridIndex, out var gridOverlays))
|
||||
{
|
||||
gridOverlays = new Dictionary<MapIndices, GasOverlayData>();
|
||||
_overlay.Add(data.GridIndex, gridOverlays);
|
||||
}
|
||||
|
||||
gridOverlays[data.GridIndices] = data.Data;
|
||||
}
|
||||
}
|
||||
|
||||
public override void FrameUpdate(float frameTime)
|
||||
{
|
||||
base.FrameUpdate(frameTime);
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace Content.Client.GameObjects.EntitySystems
|
||||
{
|
||||
var playerEnt = _playerManager.LocalPlayer?.ControlledEntity;
|
||||
|
||||
if (playerEnt == null || !playerEnt.TryGetComponent(out IMoverComponent mover))
|
||||
if (playerEnt == null || !playerEnt.TryGetComponent(out IMoverComponent? mover))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Content.Client.Interfaces;
|
||||
using Content.Client.State;
|
||||
using Content.Client.UserInterface;
|
||||
using Content.Shared;
|
||||
using Content.Shared.Network.NetMessages;
|
||||
using Robust.Client.Interfaces.Graphics;
|
||||
using Robust.Client.Interfaces.State;
|
||||
using Robust.Shared.Interfaces.Network;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Utility;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
@@ -22,12 +26,16 @@ namespace Content.Client.GameTicking
|
||||
|
||||
[ViewVariables] public bool AreWeReady { get; private set; }
|
||||
[ViewVariables] public bool IsGameStarted { get; private set; }
|
||||
[ViewVariables] public bool DisallowedLateJoin { get; private set; }
|
||||
[ViewVariables] public string ServerInfoBlob { get; private set; }
|
||||
[ViewVariables] public DateTime StartTime { get; private set; }
|
||||
[ViewVariables] public bool Paused { get; private set; }
|
||||
[ViewVariables] public Dictionary<NetSessionId, bool> Ready { get; private set; }
|
||||
|
||||
public event Action InfoBlobUpdated;
|
||||
public event Action LobbyStatusUpdated;
|
||||
public event Action LobbyReadyUpdated;
|
||||
public event Action LobbyLateJoinStatusUpdated;
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
@@ -38,11 +46,23 @@ namespace Content.Client.GameTicking
|
||||
_netManager.RegisterNetMessage<MsgTickerLobbyStatus>(nameof(MsgTickerLobbyStatus), LobbyStatus);
|
||||
_netManager.RegisterNetMessage<MsgTickerLobbyInfo>(nameof(MsgTickerLobbyInfo), LobbyInfo);
|
||||
_netManager.RegisterNetMessage<MsgTickerLobbyCountdown>(nameof(MsgTickerLobbyCountdown), LobbyCountdown);
|
||||
_netManager.RegisterNetMessage<MsgTickerLobbyReady>(nameof(MsgTickerLobbyReady), LobbyReady);
|
||||
_netManager.RegisterNetMessage<MsgRoundEndMessage>(nameof(MsgRoundEndMessage), RoundEnd);
|
||||
_netManager.RegisterNetMessage<MsgRequestWindowAttention>(nameof(MsgRequestWindowAttention), msg =>
|
||||
{
|
||||
IoCManager.Resolve<IClyde>().RequestWindowAttention();
|
||||
});
|
||||
_netManager.RegisterNetMessage<MsgTickerLateJoinStatus>(nameof(MsgTickerLateJoinStatus), LateJoinStatus);
|
||||
|
||||
Ready = new Dictionary<NetSessionId, bool>();
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
private void LateJoinStatus(MsgTickerLateJoinStatus message)
|
||||
{
|
||||
DisallowedLateJoin = message.Disallowed;
|
||||
LobbyLateJoinStatusUpdated?.Invoke();
|
||||
}
|
||||
|
||||
|
||||
private void JoinLobby(MsgTickerJoinLobby message)
|
||||
@@ -56,6 +76,8 @@ namespace Content.Client.GameTicking
|
||||
IsGameStarted = message.IsRoundStarted;
|
||||
AreWeReady = message.YouAreReady;
|
||||
Paused = message.Paused;
|
||||
if (IsGameStarted)
|
||||
Ready.Clear();
|
||||
|
||||
LobbyStatusUpdated?.Invoke();
|
||||
}
|
||||
@@ -78,11 +100,20 @@ namespace Content.Client.GameTicking
|
||||
Paused = message.Paused;
|
||||
}
|
||||
|
||||
private void LobbyReady(MsgTickerLobbyReady message)
|
||||
{
|
||||
// Merge the Dictionaries
|
||||
foreach (var p in message.PlayerReady)
|
||||
{
|
||||
Ready[p.Key] = p.Value;
|
||||
}
|
||||
LobbyReadyUpdated?.Invoke();
|
||||
}
|
||||
|
||||
private void RoundEnd(MsgRoundEndMessage message)
|
||||
{
|
||||
|
||||
//This is not ideal at all, but I don't see an immediately better fit anywhere else.
|
||||
var roundEnd = new RoundEndSummaryWindow(message.GamemodeTitle, message.RoundDuration, message.AllPlayersEndInfo);
|
||||
var roundEnd = new RoundEndSummaryWindow(message.GamemodeTitle, message.RoundEndText, message.RoundDuration, message.AllPlayersEndInfo);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,155 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using Content.Shared.Health.BodySystem.BodyScanner;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Maths;
|
||||
using static Robust.Client.UserInterface.Controls.ItemList;
|
||||
|
||||
namespace Content.Client.Health.BodySystem.BodyScanner
|
||||
{
|
||||
public sealed class BodyScannerDisplay : SS14Window
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly ILocalizationManager _loc;
|
||||
#pragma warning restore 649
|
||||
|
||||
public BodyScannerBoundUserInterface Owner { get; private set; }
|
||||
protected override Vector2? CustomSize => (800, 600);
|
||||
private ItemList BodyPartList { get; }
|
||||
private Label BodyPartLabel { get; }
|
||||
private Label BodyPartHealth { get; }
|
||||
private ItemList MechanismList { get; }
|
||||
private RichTextLabel MechanismInfoLabel { get; }
|
||||
|
||||
|
||||
private BodyScannerTemplateData _template;
|
||||
private Dictionary<string, BodyScannerBodyPartData> _parts;
|
||||
private List<string> _slots;
|
||||
private BodyScannerBodyPartData _currentBodyPart;
|
||||
|
||||
|
||||
public BodyScannerDisplay(BodyScannerBoundUserInterface owner)
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
Owner = owner;
|
||||
Title = _loc.GetString("Body Scanner");
|
||||
|
||||
var hSplit = new HBoxContainer();
|
||||
Contents.AddChild(hSplit);
|
||||
|
||||
//Left half
|
||||
var scrollBox = new ScrollContainer
|
||||
{
|
||||
SizeFlagsHorizontal = SizeFlags.FillExpand,
|
||||
};
|
||||
hSplit.AddChild(scrollBox);
|
||||
BodyPartList = new ItemList { };
|
||||
scrollBox.AddChild(BodyPartList);
|
||||
BodyPartList.OnItemSelected += BodyPartOnItemSelected;
|
||||
|
||||
//Right half
|
||||
var vSplit = new VBoxContainer
|
||||
{
|
||||
SizeFlagsHorizontal = SizeFlags.FillExpand,
|
||||
};
|
||||
hSplit.AddChild(vSplit);
|
||||
|
||||
//Top half of the right half
|
||||
var limbBox = new VBoxContainer
|
||||
{
|
||||
SizeFlagsVertical = SizeFlags.FillExpand
|
||||
};
|
||||
vSplit.AddChild(limbBox);
|
||||
BodyPartLabel = new Label();
|
||||
limbBox.AddChild(BodyPartLabel);
|
||||
var limbHealthHBox = new HBoxContainer();
|
||||
limbBox.AddChild(limbHealthHBox);
|
||||
var healthLabel = new Label
|
||||
{
|
||||
Text = "Health: "
|
||||
};
|
||||
limbHealthHBox.AddChild(healthLabel);
|
||||
BodyPartHealth = new Label();
|
||||
limbHealthHBox.AddChild(BodyPartHealth);
|
||||
var limbScroll = new ScrollContainer
|
||||
{
|
||||
SizeFlagsVertical = SizeFlags.FillExpand
|
||||
};
|
||||
limbBox.AddChild(limbScroll);
|
||||
MechanismList = new ItemList();
|
||||
limbScroll.AddChild(MechanismList);
|
||||
MechanismList.OnItemSelected += MechanismOnItemSelected;
|
||||
|
||||
//Bottom half of the right half
|
||||
MechanismInfoLabel = new RichTextLabel
|
||||
{
|
||||
SizeFlagsVertical = SizeFlags.FillExpand
|
||||
};
|
||||
vSplit.AddChild(MechanismInfoLabel);
|
||||
}
|
||||
|
||||
|
||||
public void UpdateDisplay(BodyScannerTemplateData template, Dictionary<string, BodyScannerBodyPartData> parts)
|
||||
{
|
||||
_template = template;
|
||||
_parts = parts;
|
||||
_slots = new List<string>();
|
||||
BodyPartList.Clear();
|
||||
foreach (var (key, value) in _parts)
|
||||
{
|
||||
_slots.Add(key); //We have to do this since ItemLists only return the index of what item is selected and dictionaries don't allow you to explicitly grab things by index.
|
||||
//So we put the contents of the dictionary into a list so that we can grab the list by index. I don't know either.
|
||||
BodyPartList.AddItem(CultureInfo.CurrentCulture.TextInfo.ToTitleCase(key));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void BodyPartOnItemSelected(ItemListSelectedEventArgs args)
|
||||
{
|
||||
if(_parts.TryGetValue(_slots[args.ItemIndex], out _currentBodyPart)) {
|
||||
UpdateBodyPartBox(_currentBodyPart, _slots[args.ItemIndex]);
|
||||
}
|
||||
}
|
||||
private void UpdateBodyPartBox(BodyScannerBodyPartData part, string slotName)
|
||||
{
|
||||
BodyPartLabel.Text = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(slotName) + ": " + CultureInfo.CurrentCulture.TextInfo.ToTitleCase(part.Name);
|
||||
BodyPartHealth.Text = part.CurrentDurability + "/" + part.MaxDurability;
|
||||
|
||||
MechanismList.Clear();
|
||||
foreach (var mechanism in part.Mechanisms) {
|
||||
MechanismList.AddItem(mechanism.Name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void MechanismOnItemSelected(ItemListSelectedEventArgs args)
|
||||
{
|
||||
UpdateMechanismBox(_currentBodyPart.Mechanisms[args.ItemIndex]);
|
||||
}
|
||||
private void UpdateMechanismBox(BodyScannerMechanismData mechanism)
|
||||
{
|
||||
//TODO: Make UI look less shit and clean up whatever the fuck this is lmao
|
||||
if (mechanism != null)
|
||||
{
|
||||
string message = "";
|
||||
message += mechanism.Name;
|
||||
message += "\nHealth: ";
|
||||
message += mechanism.CurrentDurability;
|
||||
message += "/";
|
||||
message += mechanism.MaxDurability;
|
||||
message += "\n";
|
||||
message += mechanism.Description;
|
||||
MechanismInfoLabel.SetMessage(message);
|
||||
}
|
||||
else
|
||||
{
|
||||
MechanismInfoLabel.SetMessage("");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -96,7 +96,6 @@
|
||||
"BarSign",
|
||||
"DroppedBodyPart",
|
||||
"DroppedMechanism",
|
||||
"BodyManager",
|
||||
"SolarPanel",
|
||||
"BodyScanner",
|
||||
"Stunbaton",
|
||||
@@ -143,6 +142,8 @@
|
||||
"Listening",
|
||||
"Radio",
|
||||
"DisposalHolder",
|
||||
"DisposalTagger",
|
||||
"DisposalRouter",
|
||||
"DisposalTransit",
|
||||
"DisposalEntry",
|
||||
"DisposalJunction",
|
||||
@@ -157,6 +158,10 @@
|
||||
"Vapor",
|
||||
"DamageOnHighSpeedImpact",
|
||||
"Barotrauma",
|
||||
"GasSprayer",
|
||||
"GasVapor",
|
||||
"MobStateManager",
|
||||
"Metabolism",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ namespace Content.Client.Input
|
||||
common.AddFunction(ContentKeyFunctions.OpenTutorial);
|
||||
common.AddFunction(ContentKeyFunctions.TakeScreenshot);
|
||||
common.AddFunction(ContentKeyFunctions.TakeScreenshotNoUI);
|
||||
common.AddFunction(ContentKeyFunctions.Point);
|
||||
|
||||
var human = contexts.GetContext("human");
|
||||
human.AddFunction(ContentKeyFunctions.SwapHands);
|
||||
@@ -37,9 +38,6 @@ namespace Content.Client.Input
|
||||
human.AddFunction(ContentKeyFunctions.MouseMiddle);
|
||||
human.AddFunction(ContentKeyFunctions.ToggleCombatMode);
|
||||
human.AddFunction(ContentKeyFunctions.WideAttack);
|
||||
human.AddFunction(ContentKeyFunctions.Point);
|
||||
human.AddFunction(ContentKeyFunctions.TryPullObject);
|
||||
human.AddFunction(ContentKeyFunctions.MovePulledObject);
|
||||
|
||||
var ghost = contexts.New("ghost", "common");
|
||||
ghost.AddFunction(EngineKeyFunctions.MoveUp);
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using Robust.Shared.Network;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Content.Client.Interfaces
|
||||
{
|
||||
@@ -7,11 +9,15 @@ namespace Content.Client.Interfaces
|
||||
bool IsGameStarted { get; }
|
||||
string ServerInfoBlob { get; }
|
||||
bool AreWeReady { get; }
|
||||
bool DisallowedLateJoin { get; }
|
||||
DateTime StartTime { get; }
|
||||
bool Paused { get; }
|
||||
Dictionary<NetSessionId, bool> Ready { get; }
|
||||
|
||||
void Initialize();
|
||||
event Action InfoBlobUpdated;
|
||||
event Action LobbyStatusUpdated;
|
||||
event Action LobbyReadyUpdated;
|
||||
event Action LobbyLateJoinStatusUpdated;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,7 +226,10 @@ namespace Content.Client.State
|
||||
|
||||
// client side command handlers will always be sent the local player session.
|
||||
var session = PlayerManager.LocalPlayer.Session;
|
||||
inputSys.HandleInputCommand(session, func, message);
|
||||
if (inputSys.HandleInputCommand(session, func, message))
|
||||
{
|
||||
args.Handle();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,14 +99,20 @@ namespace Content.Client.State
|
||||
|
||||
_playerManager.PlayerListUpdated += PlayerManagerOnPlayerListUpdated;
|
||||
_clientGameTicker.InfoBlobUpdated += UpdateLobbyUi;
|
||||
_clientGameTicker.LobbyStatusUpdated += UpdateLobbyUi;
|
||||
_clientGameTicker.LobbyStatusUpdated += LobbyStatusUpdated;
|
||||
_clientGameTicker.LobbyReadyUpdated += LobbyReadyUpdated;
|
||||
_clientGameTicker.LobbyLateJoinStatusUpdated += LobbyLateJoinStatusUpdated;
|
||||
}
|
||||
|
||||
public override void Shutdown()
|
||||
{
|
||||
_playerManager.PlayerListUpdated -= PlayerManagerOnPlayerListUpdated;
|
||||
_clientGameTicker.InfoBlobUpdated -= UpdateLobbyUi;
|
||||
_clientGameTicker.LobbyStatusUpdated -= UpdateLobbyUi;
|
||||
_clientGameTicker.LobbyStatusUpdated -= LobbyStatusUpdated;
|
||||
_clientGameTicker.LobbyReadyUpdated -= LobbyReadyUpdated;
|
||||
_clientGameTicker.LobbyLateJoinStatusUpdated -= LobbyLateJoinStatusUpdated;
|
||||
|
||||
_clientGameTicker.Ready.Clear();
|
||||
|
||||
_lobby.Dispose();
|
||||
_characterSetup.Dispose();
|
||||
@@ -149,7 +155,30 @@ namespace Content.Client.State
|
||||
_lobby.StartTime.Text = Loc.GetString("Round Starts In: {0}", text);
|
||||
}
|
||||
|
||||
private void PlayerManagerOnPlayerListUpdated(object sender, EventArgs e) => UpdatePlayerList();
|
||||
private void PlayerManagerOnPlayerListUpdated(object sender, EventArgs e)
|
||||
{
|
||||
// Remove disconnected sessions from the Ready Dict
|
||||
foreach (var p in _clientGameTicker.Ready)
|
||||
{
|
||||
if (!_playerManager.SessionsDict.TryGetValue(p.Key, out _))
|
||||
{
|
||||
_clientGameTicker.Ready.Remove(p.Key);
|
||||
}
|
||||
}
|
||||
UpdatePlayerList();
|
||||
}
|
||||
private void LobbyReadyUpdated() => UpdatePlayerList();
|
||||
|
||||
private void LobbyStatusUpdated()
|
||||
{
|
||||
UpdatePlayerList();
|
||||
UpdateLobbyUi();
|
||||
}
|
||||
|
||||
private void LobbyLateJoinStatusUpdated()
|
||||
{
|
||||
_lobby.ReadyButton.Disabled = _clientGameTicker.DisallowedLateJoin;
|
||||
}
|
||||
|
||||
private void UpdateLobbyUi()
|
||||
{
|
||||
@@ -169,6 +198,7 @@ namespace Content.Client.State
|
||||
_lobby.StartTime.Text = "";
|
||||
_lobby.ReadyButton.Text = Loc.GetString("Ready Up");
|
||||
_lobby.ReadyButton.ToggleMode = true;
|
||||
_lobby.ReadyButton.Disabled = false;
|
||||
_lobby.ReadyButton.Pressed = _clientGameTicker.AreWeReady;
|
||||
}
|
||||
|
||||
@@ -178,10 +208,24 @@ namespace Content.Client.State
|
||||
private void UpdatePlayerList()
|
||||
{
|
||||
_lobby.OnlinePlayerItemList.Clear();
|
||||
_lobby.PlayerReadyList.Clear();
|
||||
|
||||
foreach (var session in _playerManager.Sessions.OrderBy(s => s.Name))
|
||||
{
|
||||
_lobby.OnlinePlayerItemList.AddItem(session.Name);
|
||||
|
||||
var readyState = "";
|
||||
// Don't show ready state if we're ingame
|
||||
if (!_clientGameTicker.IsGameStarted)
|
||||
{
|
||||
var ready = false;
|
||||
if (session.SessionId == _playerManager.LocalPlayer.SessionId)
|
||||
ready = _clientGameTicker.AreWeReady;
|
||||
else
|
||||
_clientGameTicker.Ready.TryGetValue(session.SessionId, out ready);
|
||||
readyState = ready ? Loc.GetString("Ready") : Loc.GetString("Not Ready");
|
||||
}
|
||||
_lobby.PlayerReadyList.AddItem(readyState, null, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,6 +237,7 @@ namespace Content.Client.State
|
||||
}
|
||||
|
||||
_console.ProcessCommand($"toggleready {newReady}");
|
||||
UpdatePlayerList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
13
Content.Client/StationEvents/IStationEventManager.cs
Normal file
13
Content.Client/StationEvents/IStationEventManager.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Content.Client.StationEvents
|
||||
{
|
||||
public interface IStationEventManager
|
||||
{
|
||||
public List<string>? StationEvents { get; }
|
||||
public void Initialize();
|
||||
public event Action OnStationEventsReceived;
|
||||
}
|
||||
}
|
||||
42
Content.Client/StationEvents/StationEventManager.cs
Normal file
42
Content.Client/StationEvents/StationEventManager.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
#nullable enable
|
||||
using Content.Shared.StationEvents;
|
||||
using Robust.Shared.Interfaces.Network;
|
||||
using Robust.Shared.IoC;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Content.Client.StationEvents
|
||||
{
|
||||
class StationEventManager : SharedStationEvent, IStationEventManager
|
||||
{
|
||||
private List<string>? _events;
|
||||
public List<string>? StationEvents
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_events == null)
|
||||
RequestEvents();
|
||||
return _events;
|
||||
}
|
||||
}
|
||||
public event Action? OnStationEventsReceived;
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
var netManager = IoCManager.Resolve<IClientNetManager>();
|
||||
netManager.RegisterNetMessage<MsgGetStationEvents>(nameof(MsgGetStationEvents), EventHandler);
|
||||
netManager.Disconnect += (sender, msg) => _events = null;
|
||||
}
|
||||
|
||||
private void EventHandler(MsgGetStationEvents msg)
|
||||
{
|
||||
_events = msg.Events;
|
||||
OnStationEventsReceived?.Invoke();
|
||||
}
|
||||
public void RequestEvents()
|
||||
{
|
||||
var netManager = IoCManager.Resolve<IClientNetManager>();
|
||||
netManager.ClientSendMessage(netManager.CreateNetMessage<MsgGetStationEvents>());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,7 @@ namespace Content.Client.UserInterface
|
||||
|
||||
protected override void Draw(DrawingHandleScreen handle)
|
||||
{
|
||||
Span<float> x = stackalloc float[10];
|
||||
Color color;
|
||||
|
||||
var lerp = 1f - MathF.Abs(Progress); // for future bikeshedding purposes
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Content.Client.Chat;
|
||||
using Content.Client.Chat;
|
||||
using Content.Client.Interfaces;
|
||||
using Content.Client.UserInterface.Stylesheets;
|
||||
using Content.Client.Utility;
|
||||
@@ -22,6 +22,7 @@ namespace Content.Client.UserInterface
|
||||
public Button LeaveButton { get; }
|
||||
public ChatBox Chat { get; }
|
||||
public ItemList OnlinePlayerItemList { get; }
|
||||
public ItemList PlayerReadyList { get; }
|
||||
public ServerInfo ServerInfo { get; }
|
||||
public LobbyCharacterPreviewPanel CharacterPreview { get; }
|
||||
|
||||
@@ -219,7 +220,25 @@ namespace Content.Client.UserInterface
|
||||
MarginBottomOverride = 3,
|
||||
Children =
|
||||
{
|
||||
(OnlinePlayerItemList = new ItemList())
|
||||
new HBoxContainer
|
||||
{
|
||||
SizeFlagsHorizontal = SizeFlags.FillExpand,
|
||||
CustomMinimumSize = (50,50),
|
||||
Children =
|
||||
{
|
||||
(OnlinePlayerItemList = new ItemList
|
||||
{
|
||||
SizeFlagsVertical = SizeFlags.FillExpand,
|
||||
SizeFlagsHorizontal = SizeFlags.FillExpand,
|
||||
}),
|
||||
(PlayerReadyList = new ItemList
|
||||
{
|
||||
SizeFlagsVertical = SizeFlags.FillExpand,
|
||||
SizeFlagsHorizontal = SizeFlags.FillExpand,
|
||||
SizeFlagsStretchRatio = 0.2f
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
new NanoHeading
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Content.Client.Utility;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Shared.Localization;
|
||||
@@ -17,7 +18,7 @@ namespace Content.Client.UserInterface
|
||||
private TabContainer RoundEndWindowTabs { get; }
|
||||
protected override Vector2? CustomSize => (520, 580);
|
||||
|
||||
public RoundEndSummaryWindow(string gm, TimeSpan roundTimeSpan, List<RoundEndPlayerInfo> info )
|
||||
public RoundEndSummaryWindow(string gm, string roundEnd, TimeSpan roundTimeSpan, List<RoundEndPlayerInfo> info)
|
||||
{
|
||||
|
||||
Title = Loc.GetString("Round End Summary");
|
||||
@@ -49,6 +50,14 @@ namespace Content.Client.UserInterface
|
||||
gamemodeLabel.SetMarkup(Loc.GetString("Round of [color=white]{0}[/color] has ended.", gm));
|
||||
RoundEndSummaryTab.AddChild(gamemodeLabel);
|
||||
|
||||
//Round end text
|
||||
if (!string.IsNullOrEmpty(roundEnd))
|
||||
{
|
||||
var roundendLabel = new RichTextLabel();
|
||||
roundendLabel.SetMarkup(Loc.GetString(roundEnd));
|
||||
RoundEndSummaryTab.AddChild(roundendLabel);
|
||||
}
|
||||
|
||||
//Duration
|
||||
var roundTimeLabel = new RichTextLabel();
|
||||
roundTimeLabel.SetMarkup(Loc.GetString("It lasted for [color=yellow]{0} hours, {1} minutes, and {2} seconds.",
|
||||
@@ -65,30 +74,40 @@ namespace Content.Client.UserInterface
|
||||
//Create labels for each player info.
|
||||
foreach (var plyinfo in manifestSortedList)
|
||||
{
|
||||
|
||||
var playerInfoText = new RichTextLabel()
|
||||
{
|
||||
SizeFlagsVertical = SizeFlags.Fill
|
||||
SizeFlagsVertical = SizeFlags.Fill,
|
||||
};
|
||||
|
||||
//TODO: On Hover display a popup detailing more play info.
|
||||
//For example: their antag goals and if they completed them sucessfully.
|
||||
var icNameColor = plyinfo.Antag ? "red" : "white";
|
||||
playerInfoText.SetMarkup(
|
||||
Loc.GetString($"[color=gray]{plyinfo.PlayerOOCName}[/color] was [color={icNameColor}]{plyinfo.PlayerICName}[/color] playing role of [color=orange]{plyinfo.Role}[/color]."));
|
||||
Loc.GetString("[color=gray]{0}[/color] was [color={1}]{2}[/color] playing role of [color=orange]{3}[/color].",
|
||||
plyinfo.PlayerOOCName, icNameColor, plyinfo.PlayerICName, Loc.GetString(plyinfo.Role)));
|
||||
innerScrollContainer.AddChild(playerInfoText);
|
||||
}
|
||||
|
||||
scrollContainer.AddChild(innerScrollContainer);
|
||||
//Attach the entire ScrollContainer that holds all the playerinfo.
|
||||
PlayerManifestoTab.AddChild(scrollContainer);
|
||||
// TODO: 1240 Overlap, remove once it's fixed. Temp Hack to make the lines not overlap
|
||||
PlayerManifestoTab.OnVisibilityChanged += PlayerManifestoTab_OnVisibilityChanged;
|
||||
|
||||
//Finally, display the window.
|
||||
OpenCentered();
|
||||
MoveToFront();
|
||||
|
||||
}
|
||||
|
||||
private void PlayerManifestoTab_OnVisibilityChanged(Control obj)
|
||||
{
|
||||
if (obj.Visible)
|
||||
{
|
||||
// For some reason the lines get not properly drawn with the right height
|
||||
// so we just force a update
|
||||
ForceRunLayoutUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user