Merge pull request #802 from FL-OZ/round_end_screen
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using Content.Client.Interfaces;
|
||||
using Content.Client.State;
|
||||
using Content.Client.UserInterface;
|
||||
using Content.Shared;
|
||||
using Robust.Client.Interfaces.State;
|
||||
using Robust.Shared.Interfaces.Network;
|
||||
@@ -35,10 +36,13 @@ namespace Content.Client.GameTicking
|
||||
_netManager.RegisterNetMessage<MsgTickerJoinGame>(nameof(MsgTickerJoinGame), JoinGame);
|
||||
_netManager.RegisterNetMessage<MsgTickerLobbyStatus>(nameof(MsgTickerLobbyStatus), LobbyStatus);
|
||||
_netManager.RegisterNetMessage<MsgTickerLobbyInfo>(nameof(MsgTickerLobbyInfo), LobbyInfo);
|
||||
_netManager.RegisterNetMessage<MsgRoundEndMessage>(nameof(MsgRoundEndMessage), RoundEnd);
|
||||
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void JoinLobby(MsgTickerJoinLobby message)
|
||||
{
|
||||
_stateManager.RequestStateChange<LobbyState>();
|
||||
@@ -64,5 +68,13 @@ namespace Content.Client.GameTicking
|
||||
{
|
||||
_stateManager.RequestStateChange<GameScreen>();
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
101
Content.Client/UserInterface/RoundEndSummaryWindow.cs
Normal file
101
Content.Client/UserInterface/RoundEndSummaryWindow.cs
Normal file
@@ -0,0 +1,101 @@
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.Interfaces.Input;
|
||||
using Robust.Client.Interfaces.ResourceManagement;
|
||||
using Robust.Client.ResourceManagement;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Maths;
|
||||
using Content.Client.Utility;
|
||||
using Robust.Client.Player;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using static Robust.Client.UserInterface.Controls.ItemList;
|
||||
using static Content.Shared.SharedGameTicker;
|
||||
using System;
|
||||
|
||||
namespace Content.Client.UserInterface
|
||||
{
|
||||
public sealed class RoundEndSummaryWindow : SS14Window
|
||||
{
|
||||
private VBoxContainer RoundEndSummaryTab { get; }
|
||||
private VBoxContainer PlayerManifestoTab { get; }
|
||||
private TabContainer RoundEndWindowTabs { get; }
|
||||
protected override Vector2? CustomSize => (520, 580);
|
||||
|
||||
public RoundEndSummaryWindow(string gm, TimeSpan roundTimeSpan, List<RoundEndPlayerInfo> info )
|
||||
{
|
||||
|
||||
Title = Loc.GetString("Round End Summary");
|
||||
|
||||
//Round End Window is split into two tabs, one about the round stats
|
||||
//and the other is a list of RoundEndPlayerInfo for each player.
|
||||
//This tab would be a good place for things like: "x many people died.",
|
||||
//"clown slipped the crew x times.", "x shots were fired this round.", etc.
|
||||
//Also good for serious info.
|
||||
RoundEndSummaryTab = new VBoxContainer()
|
||||
{
|
||||
Name = Loc.GetString("Round Information")
|
||||
};
|
||||
|
||||
//Tab for listing unique info per player.
|
||||
PlayerManifestoTab = new VBoxContainer()
|
||||
{
|
||||
Name = Loc.GetString("Player Manifesto")
|
||||
};
|
||||
|
||||
RoundEndWindowTabs = new TabContainer();
|
||||
RoundEndWindowTabs.AddChild(RoundEndSummaryTab);
|
||||
RoundEndWindowTabs.AddChild(PlayerManifestoTab);
|
||||
|
||||
Contents.AddChild(RoundEndWindowTabs);
|
||||
|
||||
//Gamemode Name
|
||||
var gamemodeLabel = new RichTextLabel();
|
||||
gamemodeLabel.SetMarkup(Loc.GetString("Round of [color=white]{0}[/color] has ended.", gm));
|
||||
RoundEndSummaryTab.AddChild(gamemodeLabel);
|
||||
|
||||
//Duration
|
||||
var roundTimeLabel = new RichTextLabel();
|
||||
roundTimeLabel.SetMarkup(Loc.GetString("It lasted for [color=yellow]{0} hours, {1} minutes, and {2} seconds.",
|
||||
roundTimeSpan.Hours,roundTimeSpan.Minutes,roundTimeSpan.Seconds));
|
||||
RoundEndSummaryTab.AddChild(roundTimeLabel);
|
||||
|
||||
//Initialize what will be the list of players display.
|
||||
var scrollContainer = new ScrollContainer();
|
||||
scrollContainer.SizeFlagsVertical = SizeFlags.FillExpand;
|
||||
var innerScrollContainer = new VBoxContainer();
|
||||
|
||||
//Put antags on top of the list.
|
||||
var manifestSortedList = info.OrderBy(p => !p.Antag);
|
||||
//Create labels for each player info.
|
||||
foreach (var plyinfo in manifestSortedList)
|
||||
{
|
||||
|
||||
var playerInfoText = new RichTextLabel()
|
||||
{
|
||||
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]."));
|
||||
innerScrollContainer.AddChild(playerInfoText);
|
||||
}
|
||||
|
||||
scrollContainer.AddChild(innerScrollContainer);
|
||||
//Attach the entire ScrollContainer that holds all the playerinfo.
|
||||
PlayerManifestoTab.AddChild(scrollContainer);
|
||||
|
||||
//Finally, display the window.
|
||||
OpenCentered();
|
||||
MoveToFront();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace Content.Server.GameTicking
|
||||
namespace Content.Server.GameTicking
|
||||
{
|
||||
/// <summary>
|
||||
/// A round-start setup preset, such as which antagonists to spawn.
|
||||
@@ -6,6 +6,7 @@ namespace Content.Server.GameTicking
|
||||
public abstract class GamePreset
|
||||
{
|
||||
public abstract void Start();
|
||||
public virtual string ModeTitle => "Sandbox";
|
||||
public virtual string Description => "Secret!";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Content.Server.GameTicking.GameRules;
|
||||
using Content.Server.GameTicking.GameRules;
|
||||
using Content.Server.Interfaces.GameTicking;
|
||||
using Robust.Shared.IoC;
|
||||
|
||||
@@ -15,6 +15,7 @@ namespace Content.Server.GameTicking.GamePresets
|
||||
_gameTicker.AddGameRule<RuleDeathMatch>();
|
||||
}
|
||||
|
||||
public override string Description => "Deathmatch, go and kill everybody else to win!";
|
||||
public override string ModeTitle => "Deathmatch";
|
||||
public override string Description => "Kill anything that moves!";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Content.Server.Sandbox;
|
||||
using Content.Server.Sandbox;
|
||||
using Robust.Shared.IoC;
|
||||
|
||||
namespace Content.Server.GameTicking.GamePresets
|
||||
@@ -14,6 +14,7 @@ namespace Content.Server.GameTicking.GamePresets
|
||||
_sandboxManager.IsSandboxEnabled = true;
|
||||
}
|
||||
|
||||
public override string Description => "Sandbox, go and build something!";
|
||||
public override string ModeTitle => "Sandbox";
|
||||
public override string Description => "No stress, build something!";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ namespace Content.Server.GameTicking
|
||||
private const string PlayerPrototypeName = "HumanMob_Content";
|
||||
private const string ObserverPrototypeName = "MobObserver";
|
||||
private const string MapFile = "Maps/stationstation.yml";
|
||||
private static TimeSpan _roundStartTimeSpan;
|
||||
|
||||
[ViewVariables] private readonly List<GameRule> _gameRules = new List<GameRule>();
|
||||
[ViewVariables] private readonly List<ManifestEntry> _manifest = new List<ManifestEntry>();
|
||||
@@ -110,6 +111,7 @@ namespace Content.Server.GameTicking
|
||||
_netManager.RegisterNetMessage<MsgTickerJoinGame>(nameof(MsgTickerJoinGame));
|
||||
_netManager.RegisterNetMessage<MsgTickerLobbyStatus>(nameof(MsgTickerLobbyStatus));
|
||||
_netManager.RegisterNetMessage<MsgTickerLobbyInfo>(nameof(MsgTickerLobbyInfo));
|
||||
_netManager.RegisterNetMessage<MsgRoundEndMessage>(nameof(MsgRoundEndMessage));
|
||||
|
||||
SetStartPreset(_configurationManager.GetCVar<string>("game.defaultpreset"));
|
||||
|
||||
@@ -219,6 +221,7 @@ namespace Content.Server.GameTicking
|
||||
SpawnPlayer(player, job, false);
|
||||
}
|
||||
|
||||
_roundStartTimeSpan = IoCManager.Resolve<IGameTiming>().RealTime;
|
||||
_sendStatusToAll();
|
||||
}
|
||||
|
||||
@@ -240,7 +243,33 @@ namespace Content.Server.GameTicking
|
||||
|
||||
RunLevel = GameRunLevel.PostRound;
|
||||
|
||||
SendServerMessage("The round has ended!");
|
||||
//Tell every client the round has ended.
|
||||
var roundEndMessage = _netManager.CreateNetMessage<MsgRoundEndMessage>();
|
||||
roundEndMessage.GamemodeTitle = MakeGamePreset().ModeTitle;
|
||||
|
||||
//Get the timespan of the round.
|
||||
roundEndMessage.RoundDuration = IoCManager.Resolve<IGameTiming>().RealTime.Subtract(_roundStartTimeSpan);
|
||||
|
||||
//Generate a list of basic player info to display in the end round summary.
|
||||
var listOfPlayerInfo = new List<RoundEndPlayerInfo>();
|
||||
foreach(var ply in _playerManager.GetAllPlayers().OrderBy(p => p.Name))
|
||||
{
|
||||
if(ply.AttachedEntity.TryGetComponent<MindComponent>(out var mindComponent)
|
||||
&& mindComponent.HasMind)
|
||||
{
|
||||
var playerEndRoundInfo = new RoundEndPlayerInfo()
|
||||
{
|
||||
PlayerOOCName = ply.Name,
|
||||
PlayerICName = mindComponent.Mind.CurrentEntity.Name,
|
||||
Role = mindComponent.Mind.AllRoles.FirstOrDefault()?.Name ?? Loc.GetString("Unkown"),
|
||||
Antag = false
|
||||
};
|
||||
listOfPlayerInfo.Add(playerEndRoundInfo);
|
||||
}
|
||||
}
|
||||
|
||||
roundEndMessage.AllPlayersEndInfo = listOfPlayerInfo;
|
||||
_netManager.ServerSendToAll(roundEndMessage);
|
||||
}
|
||||
|
||||
public void Respawn(IPlayerSession targetPlayer)
|
||||
@@ -654,10 +683,12 @@ namespace Content.Server.GameTicking
|
||||
|
||||
private string GetInfoText()
|
||||
{
|
||||
var gameMode = MakeGamePreset().Description;
|
||||
var gmTitle = MakeGamePreset().ModeTitle;
|
||||
var desc = MakeGamePreset().Description;
|
||||
return _localization.GetString(@"Hi and welcome to [color=white]Space Station 14![/color]
|
||||
|
||||
The current game mode is [color=white]{0}[/color]", gameMode);
|
||||
The current game mode is: [color=white]{0}[/color].
|
||||
[color=yellow]{1}[/color]", gmTitle, desc );
|
||||
}
|
||||
|
||||
private void UpdateInfoText()
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Lidgren.Network;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.Interfaces.Network;
|
||||
using Robust.Shared.Network;
|
||||
|
||||
@@ -114,5 +116,79 @@ namespace Content.Shared
|
||||
buffer.Write(TextBlob);
|
||||
}
|
||||
}
|
||||
public struct RoundEndPlayerInfo
|
||||
{
|
||||
public string PlayerOOCName;
|
||||
public string PlayerICName;
|
||||
public string Role;
|
||||
public bool Antag;
|
||||
|
||||
}
|
||||
|
||||
protected class MsgRoundEndMessage : NetMessage
|
||||
{
|
||||
|
||||
#region REQUIRED
|
||||
|
||||
public const MsgGroups GROUP = MsgGroups.Command;
|
||||
public const string NAME = nameof(MsgRoundEndMessage);
|
||||
public MsgRoundEndMessage(INetChannel channel) : base(NAME, GROUP) { }
|
||||
|
||||
#endregion
|
||||
|
||||
public string GamemodeTitle;
|
||||
public TimeSpan RoundDuration;
|
||||
|
||||
|
||||
public uint PlayerCount;
|
||||
|
||||
public List<RoundEndPlayerInfo> AllPlayersEndInfo;
|
||||
|
||||
public override void ReadFromBuffer(NetIncomingMessage buffer)
|
||||
{
|
||||
GamemodeTitle = buffer.ReadString();
|
||||
|
||||
var hours = buffer.ReadInt32();
|
||||
var mins = buffer.ReadInt32();
|
||||
var seconds = buffer.ReadInt32();
|
||||
RoundDuration = new TimeSpan(hours, mins, seconds);
|
||||
|
||||
PlayerCount = buffer.ReadUInt32();
|
||||
AllPlayersEndInfo = new List<RoundEndPlayerInfo>();
|
||||
for(var i = 0; i < PlayerCount + 1; i++)
|
||||
{
|
||||
var readPlayerData = new RoundEndPlayerInfo
|
||||
{
|
||||
PlayerOOCName = buffer.ReadString(),
|
||||
PlayerICName = buffer.ReadString(),
|
||||
Role = buffer.ReadString(),
|
||||
Antag = buffer.ReadBoolean()
|
||||
};
|
||||
|
||||
AllPlayersEndInfo.Add(readPlayerData);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public override void WriteToBuffer(NetOutgoingMessage buffer)
|
||||
{
|
||||
buffer.Write(GamemodeTitle);
|
||||
buffer.Write(RoundDuration.Hours);
|
||||
buffer.Write(RoundDuration.Minutes);
|
||||
buffer.Write(RoundDuration.Seconds);
|
||||
|
||||
|
||||
buffer.Write(PlayerCount);
|
||||
foreach(var playerEndInfo in AllPlayersEndInfo)
|
||||
{
|
||||
buffer.Write(playerEndInfo.PlayerOOCName);
|
||||
buffer.Write(playerEndInfo.PlayerICName);
|
||||
buffer.Write(playerEndInfo.Role);
|
||||
buffer.Write(playerEndInfo.Antag);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user