Merge pull request #802 from FL-OZ/round_end_screen

This commit is contained in:
Pieter-Jan Briers
2020-04-16 22:33:38 +02:00
committed by GitHub
7 changed files with 232 additions and 9 deletions

View File

@@ -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);
}
}
}

View 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();
}
}
}

View File

@@ -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!";
}
}

View File

@@ -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!";
}
}

View File

@@ -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!";
}
}

View File

@@ -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()

View File

@@ -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);
}
}
}
}
}