Merged scoreboard from #1171

This commit is contained in:
Jordy Ruiz 2018-11-08 16:32:04 +01:00
parent 5125cf7dd6
commit 8ec70a1bde
2 changed files with 324 additions and 135 deletions

View file

@ -12,9 +12,9 @@
#include <game/client/gameclient.h>
#include <game/client/localization.h>
#include <game/client/render.h>
#include <game/client/ui.h>
#include <game/client/components/countryflags.h>
#include <game/client/components/motd.h>
#include <game/client/components/skins.h>
#include "menus.h"
#include "scoreboard.h"
@ -22,6 +22,7 @@
CScoreboard::CScoreboard()
{
m_PlayerLines = 0;
OnReset();
}
@ -33,6 +34,9 @@ void CScoreboard::ConKeyScoreboard(IConsole::IResult *pResult, void *pUserData)
void CScoreboard::OnReset()
{
m_Active = false;
for(int i = 0; i < MAX_CLIENTS; i++)
m_aPlayerStats[i].Reset();
}
void CScoreboard::OnRelease()
@ -47,55 +51,85 @@ void CScoreboard::OnConsoleInit()
void CScoreboard::RenderGoals(float x, float y, float w)
{
float h = 50.0f;
CUIRect Rect = {x, y, w, h};
float h = 20.0f;
Graphics()->BlendNormal();
RenderTools()->DrawRoundRect(&Rect, vec4(0.0f, 0.0f, 0.0f, 0.5f), 10.0f);
CUIRect Rect = {x, y, w, h};
RenderTools()->DrawRoundRect(&Rect, vec4(0.0f, 0.0f, 0.0f, 0.25f), 5.0f);
// render goals
y += 10.0f;
y += 2.0f;
if(m_pClient->m_GameInfo.m_ScoreLimit)
{
char aBuf[64];
str_format(aBuf, sizeof(aBuf), "%s: %d", Localize("Score limit"), m_pClient->m_GameInfo.m_ScoreLimit);
TextRender()->Text(0, x+10.0f, y, 20.0f, aBuf, -1);
TextRender()->Text(0, x+10.0f, y, 12.0f, aBuf, -1);
}
if(m_pClient->m_GameInfo.m_TimeLimit)
{
char aBuf[64];
str_format(aBuf, sizeof(aBuf), Localize("Time limit: %d min"), m_pClient->m_GameInfo.m_TimeLimit);
TextRender()->Text(0, x+230.0f, y, 20.0f, aBuf, -1);
float tw = TextRender()->TextWidth(0, 12.0f, aBuf, -1);
TextRender()->Text(0, x+w/2-tw/2, y, 12.0f, aBuf, -1);
}
if(m_pClient->m_GameInfo.m_MatchNum && m_pClient->m_GameInfo.m_MatchCurrent)
{
char aBuf[64];
str_format(aBuf, sizeof(aBuf), "%s %d/%d", Localize("Match"), m_pClient->m_GameInfo.m_MatchCurrent, m_pClient->m_GameInfo.m_MatchNum);
float tw = TextRender()->TextWidth(0, 20.0f, aBuf, -1);
TextRender()->Text(0, x+w-tw-10.0f, y, 20.0f, aBuf, -1);
float tw = TextRender()->TextWidth(0, 12.0f, aBuf, -1);
TextRender()->Text(0, x+w-tw-10.0f, y, 12.0f, aBuf, -1);
}
}
void CScoreboard::RenderSpectators(float x, float y, float w)
float CScoreboard::RenderSpectators(float x, float y, float w)
{
float h = 140.0f;
CUIRect Rect = {x, y, w, h};
float h = 20.0f;
float StartY = y;
int NumSpectators = 0;
for(int i = 0; i < MAX_CLIENTS; i++)
if(m_pClient->m_aClients[i].m_Active && m_pClient->m_aClients[i].m_Team == TEAM_SPECTATORS)
NumSpectators++;
char aBuf[64];
char SpectatorBuf[64];
str_format(SpectatorBuf, sizeof(SpectatorBuf), "%s (%d):", Localize("Spectators"), NumSpectators);
float tw = TextRender()->TextWidth(0, 12.0f, SpectatorBuf, -1);
// do all the text without rendering it once
CTextCursor Cursor;
TextRender()->SetCursor(&Cursor, x, y, 12.0f, TEXTFLAG_ALLOW_NEWLINE);
Cursor.m_LineWidth = w-tw-20.0f;
bool Multiple = false;
for(int i = 0; i < MAX_CLIENTS; ++i)
{
const CNetObj_PlayerInfo *pInfo = m_pClient->m_Snap.m_paPlayerInfos[i];
if(!pInfo || m_pClient->m_aClients[i].m_Team != TEAM_SPECTATORS)
continue;
if(Multiple)
TextRender()->TextEx(&Cursor, ", ", -1);
TextRender()->TextEx(&Cursor, m_pClient->m_aClients[i].m_aName, -1);
str_format(aBuf, sizeof(aBuf), " (%s)", m_pClient->m_aClients[i].m_aClan);
TextRender()->TextEx(&Cursor, aBuf, -1);
Multiple = true;
}
// background
float RectHeight = 3*h+(Cursor.m_Y-Cursor.m_StartY);
Graphics()->BlendNormal();
RenderTools()->DrawRoundRect(&Rect, vec4(0.0f, 0.0f, 0.0f, 0.5f), 10.0f);
CUIRect Rect = {x, y, w, RectHeight};
RenderTools()->DrawRoundRect(&Rect, vec4(0.0f, 0.0f, 0.0f, 0.25f), 5.0f);
// Headline
y += 10.0f;
TextRender()->Text(0, x+10.0f, y, 28.0f, Localize("Spectators"), w-20.0f);
// spectator names
y += 30.0f;
bool Multiple = false;
CTextCursor Cursor;
TextRender()->SetCursor(&Cursor, x+10.0f, y, 22.0f, TEXTFLAG_RENDER);
Cursor.m_LineWidth = w-20.0f;
Cursor.m_MaxLines = 4;
TextRender()->Text(0, x+10.0f, y, 12.0f, SpectatorBuf, w-20.0f);
// spectator names and now render everything
x += tw+2.0f+10.0f;
Multiple = false;
TextRender()->SetCursor(&Cursor, x, y, 12.0f, TEXTFLAG_RENDER|TEXTFLAG_ALLOW_NEWLINE);
Cursor.m_LineWidth = w-tw-20.0f;
for(int i = 0; i < MAX_CLIENTS; ++i)
{
const CNetObj_PlayerInfo *pInfo = m_pClient->m_Snap.m_paPlayerInfos[i];
@ -106,41 +140,104 @@ void CScoreboard::RenderSpectators(float x, float y, float w)
TextRender()->TextEx(&Cursor, ", ", -1);
if(pInfo->m_PlayerFlags&PLAYERFLAG_WATCHING)
TextRender()->TextColor(1.0f, 1.0f, 0.0f, 1.0f);
char aBuf[64];
str_format(aBuf, sizeof(aBuf), "%s", g_Config.m_ClShowsocial ? m_pClient->m_aClients[i].m_aName : "");
RenderTools()->DrawClientID(TextRender(), &Cursor, i);
TextRender()->TextEx(&Cursor, m_pClient->m_aClients[i].m_aName, -1);
str_format(aBuf, sizeof(aBuf), " (%s)", m_pClient->m_aClients[i].m_aClan);
TextRender()->TextEx(&Cursor, aBuf, -1);
TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f);
Multiple = true;
}
return RectHeight;
}
void CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const char *pTitle)
float CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const char *pTitle, int Align)
{
if(Team == TEAM_SPECTATORS)
return;
return 0.0f;
float h = 760.0f;
CUIRect Rect = {x, y, w, h};
float HeadlineHeight = 40.0f;
float TitleFontsize = 20.0f;
float HeadlineFontsize = 12.0f;
float LineHeight = 20.0f;
float TeeSizeMod = 1.0f;
float Spacing = 2.0f;
float NameOffset = x+4.0f, NameLength = 136.0f;
float TeeOffset = x+4.0f, TeeLength = 25*TeeSizeMod;
float ClanOffset = NameOffset+NameLength, ClanLength = 90.0f;
float KillOffset = ClanOffset+ClanLength, KillLength = 30.0f;
float DeathOffset = KillOffset+KillLength, DeathLength = 30.0f;
float ScoreOffset = DeathOffset+DeathLength, ScoreLength = 35.0f;
float PingOffset = ScoreOffset+ScoreLength, PingLength = 35.0f;
float tw = 0.0f;
bool NoTitle = pTitle? false : true;
// count players
int NumPlayers = 0;
for(int i = 0; i < MAX_CLIENTS; i++)
if(m_pClient->m_aClients[i].m_Active && m_pClient->m_aClients[i].m_Team == Team)
NumPlayers++;
m_PlayerLines = max(m_PlayerLines, NumPlayers);
char aBuf[128] = {0};
// background
Graphics()->BlendNormal();
RenderTools()->DrawRoundRect(&Rect, vec4(0.0f, 0.0f, 0.0f, 0.5f), 17.0f);
vec4 Color;
if(Team == TEAM_RED && m_pClient->m_GameInfo.m_GameFlags&GAMEFLAG_TEAMS)
Color = vec4(0.975f, 0.17f, 0.17f, 0.75f);
else if(Team == TEAM_BLUE)
Color = vec4(0.17f, 0.46f, 0.975f, 0.75f);
else
Color = vec4(0.0f, 0.0f, 0.0f, 0.5f);
CUIRect Rect = {x, y, w, HeadlineHeight};
RenderTools()->DrawRoundRect(&Rect, Color, 5.0f);
// render title
float TitleFontsize = 40.0f;
if(!pTitle)
if(NoTitle)
{
if(m_pClient->m_Snap.m_pGameData->m_GameStateFlags&GAMESTATEFLAG_GAMEOVER)
pTitle = Localize("Game over");
else if(m_pClient->m_Snap.m_pGameData->m_GameStateFlags&GAMESTATEFLAG_ROUNDOVER)
pTitle = Localize("Round over");
else
pTitle = Localize("Score board");
pTitle = Localize("Scoreboard");
}
else
{
if(Team == TEAM_BLUE)
str_format(aBuf, sizeof(aBuf), "(%d) %s", NumPlayers, pTitle);
else
str_format(aBuf, sizeof(aBuf), "%s (%d)", pTitle, NumPlayers);
}
if(Align == -1)
{
tw = TextRender()->TextWidth(0, TitleFontsize, pTitle, -1);
TextRender()->Text(0, x+20.0f, y+5.0f, TitleFontsize, pTitle, -1);
if(!NoTitle)
{
str_format(aBuf, sizeof(aBuf), " (%d)", NumPlayers);
TextRender()->TextColor(1.0f, 1.0f, 1.0f, 0.5f);
TextRender()->Text(0, x+20.0f+tw, y+5.0f, TitleFontsize, aBuf, -1);
TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f);
}
}
else
{
tw = TextRender()->TextWidth(0, TitleFontsize, pTitle, -1);
if(!NoTitle)
{
str_format(aBuf, sizeof(aBuf), "(%d) ", NumPlayers);
float PlayersTextWidth = TextRender()->TextWidth(0, TitleFontsize, aBuf, -1);
TextRender()->TextColor(1.0f, 1.0f, 1.0f, 0.5f);
TextRender()->Text(0, x+w-tw-PlayersTextWidth-20.0f, y+5.0f, TitleFontsize, aBuf, -1);
TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f);
}
tw = TextRender()->TextWidth(0, TitleFontsize, pTitle, -1);
TextRender()->Text(0, x+w-tw-20.0f, y+5.0f, TitleFontsize, pTitle, -1);
}
TextRender()->Text(0, x+20.0f, y, TitleFontsize, pTitle, -1);
char aBuf[128] = {0};
if(m_pClient->m_GameInfo.m_GameFlags&GAMEFLAG_TEAMS)
{
int Score = Team == TEAM_RED ? m_pClient->m_Snap.m_pGameDataTeam->m_TeamscoreRed : m_pClient->m_Snap.m_pGameDataTeam->m_TeamscoreBlue;
@ -148,7 +245,7 @@ void CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const ch
}
else
{
if(m_pClient->m_Snap.m_SpecInfo.m_Active && m_pClient->m_Snap.m_SpecInfo.m_SpectatorID >= 0 && m_pClient->m_Snap.m_SpecInfo.m_SpectatorID < MAX_CLIENTS &&
if(m_pClient->m_Snap.m_SpecInfo.m_Active && m_pClient->m_Snap.m_SpecInfo.m_SpectatorID != SPEC_FREEVIEW &&
m_pClient->m_Snap.m_paPlayerInfos[m_pClient->m_Snap.m_SpecInfo.m_SpectatorID])
{
int Score = m_pClient->m_Snap.m_paPlayerInfos[m_pClient->m_Snap.m_SpecInfo.m_SpectatorID]->m_Score;
@ -160,59 +257,57 @@ void CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const ch
str_format(aBuf, sizeof(aBuf), "%d", Score);
}
}
float tw = TextRender()->TextWidth(0, TitleFontsize, aBuf, -1);
TextRender()->Text(0, x+w-tw-20.0f, y, TitleFontsize, aBuf, -1);
// calculate measurements
x += 10.0f;
float LineHeight = 60.0f;
float TeeSizeMod = 1.0f;
float Spacing = 16.0f;
if(m_pClient->m_GameInfo.m_aTeamSize[Team] > 12)
if(Align == -1)
{
LineHeight = 40.0f;
TeeSizeMod = 0.8f;
Spacing = 0.0f;
tw = TextRender()->TextWidth(0, TitleFontsize, aBuf, -1);
TextRender()->Text(0, x+w-tw-20.0f, y+5.0f, TitleFontsize, aBuf, -1);
}
else if(m_pClient->m_GameInfo.m_aTeamSize[Team] > 8)
{
LineHeight = 50.0f;
TeeSizeMod = 0.9f;
Spacing = 8.0f;
}
float ScoreOffset = x+10.0f, ScoreLength = 60.0f;
float TeeOffset = ScoreOffset+ScoreLength, TeeLength = 60*TeeSizeMod;
float NameOffset = TeeOffset+TeeLength, NameLength = 300.0f-TeeLength;
float PingOffset = x+610.0f, PingLength = 65.0f;
float CountryOffset = PingOffset-(LineHeight-Spacing-TeeSizeMod*5.0f)*2.0f, CountryLength = (LineHeight-Spacing-TeeSizeMod*5.0f)*2.0f;
float ClanOffset = x+370.0f, ClanLength = 230.0f-CountryLength;
else
TextRender()->Text(0, x+20.0f, y+5.0f, TitleFontsize, aBuf, -1);
// render headlines
y += 50.0f;
float HeadlineFontsize = 22.0f;
TextRender()->TextColor(1.0f, 1.0f, 1.0f, 0.7f);
tw = TextRender()->TextWidth(0, HeadlineFontsize, Localize("Score"), -1);
TextRender()->Text(0, ScoreOffset+ScoreLength-tw, y, HeadlineFontsize, Localize("Score"), -1);
y += HeadlineHeight;
TextRender()->Text(0, NameOffset, y, HeadlineFontsize, Localize("Name"), -1);
Graphics()->BlendNormal();
{
CUIRect Rect = {x, y, w, LineHeight*(m_PlayerLines+1)};
RenderTools()->DrawRoundRect(&Rect, vec4(0.0f, 0.0f, 0.0f, 0.25f), 5.0f);
}
if(m_PlayerLines)
{
CUIRect Rect = {x, y+LineHeight, w, LineHeight*(m_PlayerLines)};
RenderTools()->DrawRoundRect(&Rect, vec4(0.0f, 0.0f, 0.0f, 0.25f), 5.0f);
}
TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f);
TextRender()->Text(0, NameOffset, y+Spacing, HeadlineFontsize, Localize("Name"), -1);
tw = TextRender()->TextWidth(0, HeadlineFontsize, Localize("Clan"), -1);
TextRender()->Text(0, ClanOffset+ClanLength/2-tw/2, y, HeadlineFontsize, Localize("Clan"), -1);
TextRender()->Text(0, ClanOffset+ClanLength/2-tw/2, y+Spacing, HeadlineFontsize, Localize("Clan"), -1);
TextRender()->TextColor(1.0f, 1.0f, 1.0f, 0.5f);
tw = TextRender()->TextWidth(0, HeadlineFontsize, Localize("K"), -1);
TextRender()->Text(0, KillOffset+KillLength/2-tw/2, y+Spacing, HeadlineFontsize, Localize("K"), -1);
tw = TextRender()->TextWidth(0, HeadlineFontsize, Localize("D"), -1);
TextRender()->Text(0, DeathOffset+DeathLength/2-tw/2, y+Spacing, HeadlineFontsize, Localize("D"), -1);
TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f);
tw = TextRender()->TextWidth(0, HeadlineFontsize, Localize("Score"), -1);
TextRender()->Text(0, ScoreOffset+ScoreLength/2-tw/2, y+Spacing, HeadlineFontsize, Localize("Score"), -1);
tw = TextRender()->TextWidth(0, HeadlineFontsize, Localize("Ping"), -1);
TextRender()->Text(0, PingOffset+PingLength-tw, y, HeadlineFontsize, Localize("Ping"), -1);
TextRender()->Text(0, PingOffset+PingLength-tw, y+Spacing, HeadlineFontsize, Localize("Ping"), -1);
TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f);
// render player entries
y += HeadlineFontsize*2.0f;
float FontSize = 24.0f;
y += LineHeight;
float FontSize = HeadlineFontsize;
CTextCursor Cursor;
for(int RenderDead = 0; RenderDead < 2; ++RenderDead)
{
float ColorAlpha = RenderDead ? 0.5f : 1.0f;
TextRender()->TextColor(1.0f, 1.0f, 1.0f, ColorAlpha);
for(int i = 0; i < MAX_CLIENTS; i++)
{
// make sure that we render the correct team
@ -221,22 +316,24 @@ void CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const ch
(RenderDead && !(pInfo->m_pPlayerInfo->m_PlayerFlags&PLAYERFLAG_DEAD)))
continue;
// color for text
vec3 TextColor = vec3(1.0f, 1.0f, 1.0f);
// background so it's easy to find the local player or the followed one in spectator mode
if(m_pClient->m_LocalClientID == pInfo->m_ClientID || (m_pClient->m_Snap.m_SpecInfo.m_Active && pInfo->m_ClientID == m_pClient->m_Snap.m_SpecInfo.m_SpectatorID))
{
Rect.x = x;
Rect.y = y;
Rect.w = w-20.0f;
Rect.h = LineHeight;
RenderTools()->DrawRoundRect(&Rect, vec4(1.0f, 1.0f, 1.0f, 0.25f*ColorAlpha), 15.0f);
}
CUIRect Rect = {x, y, w, LineHeight};
RenderTools()->DrawRoundRect(&Rect, vec4(1.0f, 1.0f, 1.0f, 0.75f*ColorAlpha), 5.0f);
// score
str_format(aBuf, sizeof(aBuf), "%d", clamp(pInfo->m_pPlayerInfo->m_Score, -999, 999));
tw = TextRender()->TextWidth(0, FontSize, aBuf, -1);
TextRender()->SetCursor(&Cursor, ScoreOffset+ScoreLength-tw, y+Spacing, FontSize, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END);
Cursor.m_LineWidth = ScoreLength;
TextRender()->TextEx(&Cursor, aBuf, -1);
// make color for own entry black
TextColor = vec3(0.0f, 0.0f, 0.0f);
TextRender()->TextOutlineColor(1.0f, 1.0f, 1.0f, 0.25f);
}
else
TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.3f);
// set text color
TextRender()->TextColor(TextColor.r, TextColor.g, TextColor.b, ColorAlpha);
// flag
if(m_pClient->m_GameInfo.m_GameFlags&GAMEFLAG_FLAGS && m_pClient->m_Snap.m_pGameDataFlag &&
@ -250,7 +347,7 @@ void CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const ch
RenderTools()->SelectSprite(m_pClient->m_aClients[pInfo->m_ClientID].m_Team==TEAM_RED ? SPRITE_FLAG_BLUE : SPRITE_FLAG_RED, SPRITE_FLAG_FLIP_X);
float Size = LineHeight;
IGraphics::CQuadItem QuadItem(TeeOffset+0.0f, y-5.0f-Spacing/2.0f, Size/2.0f, Size);
IGraphics::CQuadItem QuadItem(TeeOffset+0.0f, y-2.0f-Spacing/2.0f, Size/2.0f, Size);
Graphics()->QuadsDrawTL(&QuadItem, 1);
Graphics()->QuadsEnd();
}
@ -261,20 +358,15 @@ void CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const ch
Graphics()->BlendNormal();
Graphics()->TextureSet(g_pData->m_aImages[IMAGE_DEADTEE].m_Id);
Graphics()->QuadsBegin();
if(m_pClient->m_GameInfo.m_GameFlags&GAMEFLAG_TEAMS)
{
vec4 Color = m_pClient->m_pSkins->GetColorV4(m_pClient->m_pSkins->GetTeamColor(true, 0, m_pClient->m_aClients[pInfo->m_ClientID].m_Team, SKINPART_BODY), false);
Graphics()->SetColor(Color.r, Color.g, Color.b, Color.a);
}
IGraphics::CQuadItem QuadItem(TeeOffset, y-5.0f, 64*TeeSizeMod, 64*TeeSizeMod);
IGraphics::CQuadItem QuadItem(TeeOffset, y+Spacing, 20*TeeSizeMod, 20*TeeSizeMod);
Graphics()->QuadsDrawTL(&QuadItem, 1);
Graphics()->QuadsEnd();
}
else
{
CTeeRenderInfo TeeInfo = m_pClient->m_aClients[pInfo->m_ClientID].m_RenderInfo;
TeeInfo.m_Size *= TeeSizeMod;
RenderTools()->RenderTee(CAnimState::GetIdle(), &TeeInfo, EMOTE_NORMAL, vec2(1.0f, 0.0f), vec2(TeeOffset+TeeLength/2, y+LineHeight/2));
TeeInfo.m_Size = 20*TeeSizeMod;
RenderTools()->RenderTee(CAnimState::GetIdle(), &TeeInfo, EMOTE_NORMAL, vec2(1.0f, 0.0f), vec2(TeeOffset+TeeLength/2, y+LineHeight/2+Spacing));
}
// name
@ -283,37 +375,58 @@ void CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const ch
TextRender()->TextColor(1.0f, 0.5f, 0.5f, ColorAlpha);
else if(RenderDead && pInfo->m_pPlayerInfo->m_PlayerFlags&PLAYERFLAG_WATCHING)
TextRender()->TextColor(1.0f, 1.0f, 0.0f, ColorAlpha);
TextRender()->SetCursor(&Cursor, NameOffset, y+Spacing, FontSize, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END);
Cursor.m_LineWidth = NameLength;
char aBuf[64];
str_format(aBuf, sizeof(aBuf), "%s", g_Config.m_ClShowsocial ? m_pClient->m_aClients[pInfo->m_ClientID].m_aName : "");
RenderTools()->DrawClientID(TextRender(), &Cursor, pInfo->m_ClientID);
TextRender()->TextEx(&Cursor, aBuf, -1);
TextRender()->TextColor(1.0f, 1.0f, 1.0f, ColorAlpha);
TextRender()->SetCursor(&Cursor, NameOffset+TeeLength, y+Spacing, FontSize, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END);
Cursor.m_LineWidth = NameLength-TeeLength;
TextRender()->TextEx(&Cursor, m_pClient->m_aClients[pInfo->m_ClientID].m_aName, str_length(m_pClient->m_aClients[pInfo->m_ClientID].m_aName));
TextRender()->TextColor(TextColor.r, TextColor.g, TextColor.b, ColorAlpha);
// clan
tw = TextRender()->TextWidth(0, FontSize, m_pClient->m_aClients[pInfo->m_ClientID].m_aClan, -1);
tw = TextRender()->TextWidth(0, FontSize, m_pClient->m_aClients[pInfo->m_ClientID].m_aClan, -1/*, TEXTFLAG_STOP_AT_END, ClanLength*/);
TextRender()->SetCursor(&Cursor, ClanOffset+ClanLength/2-tw/2, y+Spacing, FontSize, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END);
Cursor.m_LineWidth = ClanLength;
TextRender()->TextEx(&Cursor, (g_Config.m_ClShowsocial ? m_pClient->m_aClients[pInfo->m_ClientID].m_aClan : ""), -1);
TextRender()->TextEx(&Cursor, m_pClient->m_aClients[pInfo->m_ClientID].m_aClan, -1);
// K
TextRender()->TextColor(TextColor.r, TextColor.g, TextColor.b, 0.5f*ColorAlpha);
str_format(aBuf, sizeof(aBuf), "%d", clamp(m_aPlayerStats[pInfo->m_ClientID].m_Kills, 0, 999));
tw = TextRender()->TextWidth(0, FontSize, aBuf, -1);
TextRender()->SetCursor(&Cursor, KillOffset+KillLength/2-tw/2, y+Spacing, FontSize, TEXTFLAG_RENDER);
Cursor.m_LineWidth = KillLength;
TextRender()->TextEx(&Cursor, aBuf, -1);
// D
str_format(aBuf, sizeof(aBuf), "%d", clamp(m_aPlayerStats[pInfo->m_ClientID].m_Deaths, 0, 999));
tw = TextRender()->TextWidth(0, FontSize, aBuf, -1);
TextRender()->SetCursor(&Cursor, DeathOffset+DeathLength/2-tw/2, y+Spacing, FontSize, TEXTFLAG_RENDER);
Cursor.m_LineWidth = DeathLength;
TextRender()->TextEx(&Cursor, aBuf, -1);
// score
TextRender()->TextColor(TextColor.r, TextColor.g, TextColor.b, ColorAlpha);
str_format(aBuf, sizeof(aBuf), "%d", clamp(pInfo->m_pPlayerInfo->m_Score, -999, 999));
tw = TextRender()->TextWidth(0, FontSize, aBuf, -1);
TextRender()->SetCursor(&Cursor, ScoreOffset+ScoreLength/2-tw/2, y+Spacing, FontSize, TEXTFLAG_RENDER);
Cursor.m_LineWidth = ScoreLength;
TextRender()->TextEx(&Cursor, aBuf, -1);
// country flag
vec4 Color(1.0f, 1.0f, 1.0f, 0.5f*ColorAlpha);
/*vec4 Color(1.0f, 1.0f, 1.0f, 0.5f*ColorAlpha);
m_pClient->m_pCountryFlags->Render(m_pClient->m_aClients[pInfo->m_ClientID].m_Country, &Color,
CountryOffset, y+(Spacing+TeeSizeMod*5.0f)/2.0f, CountryLength, LineHeight-Spacing-TeeSizeMod*5.0f);
CountryOffset, y+(Spacing+TeeSizeMod*5.0f)/2.0f, CountryLength, LineHeight-Spacing-TeeSizeMod*5.0f);*/
// ping
str_format(aBuf, sizeof(aBuf), "%d", clamp(pInfo->m_pPlayerInfo->m_Latency, 0, 1000));
TextRender()->TextColor(1.0f, 1.0f, 1.0f, 0.7f);
str_format(aBuf, sizeof(aBuf), "%d", clamp(pInfo->m_pPlayerInfo->m_Latency, 0, 999));
tw = TextRender()->TextWidth(0, FontSize, aBuf, -1);
TextRender()->SetCursor(&Cursor, PingOffset+PingLength-tw, y+Spacing, FontSize, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END);
TextRender()->SetCursor(&Cursor, PingOffset+PingLength-tw, y+Spacing, FontSize, TEXTFLAG_RENDER);
Cursor.m_LineWidth = PingLength;
TextRender()->TextEx(&Cursor, aBuf, -1);
TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f);
y += LineHeight+Spacing;
y += LineHeight;
}
}
TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f);
TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.3f);
return HeadlineHeight+LineHeight*(m_PlayerLines+1);
}
void CScoreboard::RenderRecordingNotification(float x)
@ -322,16 +435,15 @@ void CScoreboard::RenderRecordingNotification(float x)
return;
//draw the box
CUIRect Rect = {x, 0.0f, 180.0f, 50.0f};
CUIRect RectBox = {x, 0.0f, 180.0f, 50.0f};
vec4 Color = vec4(0.0f, 0.0f, 0.0f, 0.4f);
Graphics()->BlendNormal();
RenderTools()->DrawUIRect(&Rect, vec4(0.0f, 0.0f, 0.0f, 0.4f), CUI::CORNER_B, 15.0f);
RenderTools()->DrawUIRect(&RectBox, Color, CUI::CORNER_B, 15.0f);
//draw the red dot
Rect.x = x+20;
Rect.y = 15.0f;
Rect.w = 20.0f;
Rect.h = 20.0f;
RenderTools()->DrawRoundRect(&Rect, vec4(1.0f, 0.0f, 0.0f, 1.0f), 10.0f);
CUIRect RectRedDot = {x+20, 15.0f, 20.0f, 20.0f};
Color = vec4(1.0f, 0.0f, 0.0f, 1.0f);
RenderTools()->DrawRoundRect(&RectRedDot, Color, 10.0f);
//draw the text
char aBuf[64];
@ -345,22 +457,36 @@ void CScoreboard::OnRender()
if(!Active())
return;
// don't render scoreboard if menu is open
if(m_pClient->m_pMenus->IsActive())
return;
// if the score board is active, then we should clear the motd message aswell
if(m_pClient->m_pMotd->IsActive())
m_pClient->m_pMotd->Clear();
float Width = 400*3.0f*Graphics()->ScreenAspect();
float Height = 400*3.0f;
CUIRect Screen = *UI()->Screen();
Graphics()->MapScreen(Screen.x, Screen.y, Screen.w, Screen.h);
Graphics()->MapScreen(0, 0, Width, Height);
float w = 700.0f;
float Width = Screen.w;
float w = 364.0f;
if(m_pClient->m_Snap.m_pGameData)
{
if(!(m_pClient->m_GameInfo.m_GameFlags&GAMEFLAG_TEAMS))
RenderScoreboard(Width/2-w/2, 150.0f, w, 0, 0);
{
float ScoreboardHeight = RenderScoreboard(Width/2-w/2, 70.0f, w, 0, 0, -1);
float SpectatorHeight = RenderSpectators(Width/2-w/2, 73.0f+ScoreboardHeight, w);
RenderGoals(Width/2-w/2, 73.0f+ScoreboardHeight, w);
// scoreboard size
m_TotalRect.x = Width/2-w/2;
m_TotalRect.y = 70.0f;
m_TotalRect.w = w;
m_TotalRect.h = ScoreboardHeight+SpectatorHeight+3.0f;
}
else if(m_pClient->m_Snap.m_pGameDataTeam)
{
const char *pRedClanName = GetClanName(TEAM_RED);
@ -398,17 +524,48 @@ void CScoreboard::OnRender()
TextRender()->Text(0, Width/2-w/2, 39, 86.0f, aText, -1);
}
RenderScoreboard(Width/2-w-5.0f, 150.0f, w, TEAM_RED, pRedClanName ? pRedClanName : Localize("Red team"));
RenderScoreboard(Width/2+5.0f, 150.0f, w, TEAM_BLUE, pBlueClanName ? pBlueClanName : Localize("Blue team"));
}
float ScoreboardHeight = RenderScoreboard(Width/2-w-1.5f, 70.0f, w, TEAM_RED, pRedClanName ? pRedClanName : Localize("Red team"), -1);
RenderScoreboard(Width/2+1.5f, 70.0f, w, TEAM_BLUE, pBlueClanName ? pBlueClanName : Localize("Blue team"), 1);
RenderGoals(Width/2-w/2, 150+760+10, w);
RenderSpectators(Width/2-w/2, 150+760+10+50+10, w);
float SpectatorHeight = RenderSpectators(Width/2-w-1.5f, 73.0f+ScoreboardHeight, w*2.0f+3.0f);
RenderGoals(Width/2-w-1.5f, 73.0f+ScoreboardHeight, w*2.0f+3.0f);
// scoreboard size
m_TotalRect.x = Width/2-w-1.5f;
m_TotalRect.y = 70.0f;
m_TotalRect.w = w*2.0f+3.0f;
m_TotalRect.h = ScoreboardHeight+SpectatorHeight+3.0f;
}
}
RenderRecordingNotification((Width/7)*4);
}
void CScoreboard::OnMessage(int MsgType, void *pRawMsg)
{
if(MsgType == NETMSGTYPE_SV_KILLMSG)
{
CNetMsg_Sv_KillMsg *pMsg = (CNetMsg_Sv_KillMsg *)pRawMsg;
m_aPlayerStats[pMsg->m_Victim].m_Deaths++;
if(pMsg->m_Victim != pMsg->m_Killer)
m_aPlayerStats[pMsg->m_Killer].m_Kills++;
}
else if(MsgType == NETMSGTYPE_SV_CLIENTDROP && Client()->State() != IClient::STATE_DEMOPLAYBACK)
{
CNetMsg_Sv_ClientDrop *pMsg = (CNetMsg_Sv_ClientDrop *)pRawMsg;
if(m_pClient->m_LocalClientID == pMsg->m_ClientID || !m_pClient->m_aClients[pMsg->m_ClientID].m_Active)
{
if(g_Config.m_Debug)
Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client", "invalid clientdrop");
return;
}
ResetPlayerStats(pMsg->m_ClientID);
}
}
bool CScoreboard::Active()
{
// disable scoreboard if the menu is active
@ -419,10 +576,6 @@ bool CScoreboard::Active()
if(m_Active)
return true;
// skip if motd is present
if(m_pClient->m_pMotd->IsActive())
return false;
if(m_pClient->m_LocalClientID != -1 && m_pClient->m_aClients[m_pClient->m_LocalClientID].m_Team != TEAM_SPECTATORS)
{
// we are not a spectator, check if we are dead, don't follow a player and the game isn't paused
@ -438,6 +591,16 @@ bool CScoreboard::Active()
return false;
}
void CScoreboard::ResetPlayerStats(int ClientID)
{
m_aPlayerStats[ClientID].Reset();
}
CUIRect CScoreboard::GetScoreboardRect()
{
return m_TotalRect;
}
const char *CScoreboard::GetClanName(int Team)
{
int ClanPlayers = 0;
@ -466,3 +629,15 @@ const char *CScoreboard::GetClanName(int Team)
else
return 0;
}
CScoreboard::CPlayerStats::CPlayerStats()
{
m_Kills = 0;
m_Deaths = 0;
}
void CScoreboard::CPlayerStats::Reset()
{
m_Kills = 0;
m_Deaths = 0;
}

View file

@ -7,8 +7,8 @@
class CScoreboard : public CComponent
{
void RenderGoals(float x, float y, float w);
void RenderSpectators(float x, float y, float w);
void RenderScoreboard(float x, float y, float w, int Team, const char *pTitle);
float RenderSpectators(float x, float y, float w);
float RenderScoreboard(float x, float y, float w, int Team, const char *pTitle, int Align);
void RenderRecordingNotification(float x);
static void ConKeyScoreboard(IConsole::IResult *pResult, void *pUserData);
@ -16,6 +16,17 @@ class CScoreboard : public CComponent
const char *GetClanName(int Team);
bool m_Active;
int m_PlayerLines;
class CUIRect m_TotalRect;
class CPlayerStats
{
public:
int m_Kills;
int m_Deaths;
CPlayerStats();
void Reset();
};
CPlayerStats m_aPlayerStats[16];
public:
CScoreboard();
@ -23,8 +34,11 @@ public:
virtual void OnConsoleInit();
virtual void OnRender();
virtual void OnRelease();
bool Active();
virtual void OnMessage(int MsgType, void *pRawMsg);
bool Active();
void ResetPlayerStats(int ClientID);
class CUIRect GetScoreboardRect();
};
#endif