Scriptified scoreboard drawing
This commit is contained in:
parent
30a7ccb7da
commit
706d1b6978
16 changed files with 617 additions and 415 deletions
|
|
@ -1840,6 +1840,51 @@ DEFINE_ACTION_FUNCTION(_Screen, DrawLineFrame)
|
|||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_Screen, GetTextureWidth)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_INT(textureId);
|
||||
PARAM_BOOL(animated);
|
||||
|
||||
FGameTexture *tex = textureId >= 1 ? TexMan.GetGameTexture(FSetTextureID(textureId), animated) : nullptr;
|
||||
|
||||
ACTION_RETURN_FLOAT(tex ? tex->GetDisplayWidth() : -1);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_Screen, GetTextureHeight)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_INT(textureId);
|
||||
PARAM_BOOL(animated);
|
||||
|
||||
FGameTexture *tex = textureId >= 1 ? TexMan.GetGameTexture(FSetTextureID(textureId), animated) : nullptr;
|
||||
|
||||
ACTION_RETURN_FLOAT(tex ? tex->GetDisplayHeight() : -1);
|
||||
}
|
||||
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_Screen, GetTextureLeftOffset)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_INT(textureId);
|
||||
PARAM_BOOL(animated);
|
||||
|
||||
FGameTexture *tex = textureId >= 1 ? TexMan.GetGameTexture(FSetTextureID(textureId), animated) : nullptr;
|
||||
|
||||
ACTION_RETURN_FLOAT(tex ? tex->GetDisplayLeftOffset() : -1);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_Screen, GetTextureTopOffset)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_INT(textureId);
|
||||
PARAM_BOOL(animated);
|
||||
|
||||
FGameTexture *tex = textureId >= 1 ? TexMan.GetGameTexture(FSetTextureID(textureId), animated) : nullptr;
|
||||
|
||||
ACTION_RETURN_FLOAT(tex ? tex->GetDisplayTopOffset() : -1);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(FCanvas, DrawLineFrame)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(FCanvas);
|
||||
|
|
|
|||
|
|
@ -564,6 +564,52 @@ DEFINE_ACTION_FUNCTION_NATIVE(FStringStruct, Substitute, StringSubst)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int StringCompare(FString *self, const FString &other)
|
||||
{
|
||||
return self->Compare(other);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_NATIVE(FStringStruct, Compare, StringCompare)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(FString);
|
||||
PARAM_STRING(other);
|
||||
ACTION_RETURN_INT(StringCompare(self, other));
|
||||
}
|
||||
|
||||
static int StringCompareNoCase(FString *self, const FString &other)
|
||||
{
|
||||
return self->CompareNoCase(other);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_NATIVE(FStringStruct, CompareNoCase, StringCompareNoCase)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(FString);
|
||||
PARAM_STRING(other);
|
||||
ACTION_RETURN_INT(StringCompareNoCase(self, other));
|
||||
}
|
||||
|
||||
static int StringIsEmpty(FString *self)
|
||||
{
|
||||
return self->IsEmpty();
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_NATIVE(FStringStruct, IsEmpty, StringIsEmpty)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(FString);
|
||||
ACTION_RETURN_INT(StringIsEmpty(self));
|
||||
}
|
||||
|
||||
static int StringIsNotEmpty(FString *self)
|
||||
{
|
||||
return self->IsNotEmpty();
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_NATIVE(FStringStruct, IsNotEmpty, StringIsNotEmpty)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(FString);
|
||||
ACTION_RETURN_INT(StringIsNotEmpty(self));
|
||||
}
|
||||
|
||||
static void StringStripRight(FString* self, const FString& junk)
|
||||
{
|
||||
if (junk.IsNotEmpty()) self->StripRight(junk);
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@
|
|||
#include "c_buttons.h"
|
||||
#include "d_buttons.h"
|
||||
#include "v_draw.h"
|
||||
#include "r_utility.h"
|
||||
|
||||
enum
|
||||
{
|
||||
|
|
@ -241,6 +242,7 @@ void CT_PasteChat(const char *clip)
|
|||
|
||||
void CT_Drawer (void)
|
||||
{
|
||||
auto &vp = r_viewpoint;
|
||||
auto drawer = twod;
|
||||
FFont *displayfont = NewConsoleFont;
|
||||
|
||||
|
|
@ -254,7 +256,7 @@ void CT_Drawer (void)
|
|||
{
|
||||
// todo: check for summary screen
|
||||
}
|
||||
if (!skipit) HU_DrawScores (&players[consoleplayer]);
|
||||
if (!skipit) HU_DrawScores (consoleplayer, vp.TicFrac);
|
||||
}
|
||||
if (chatmodeon)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -232,6 +232,12 @@ DEFINE_ACTION_FUNCTION(_PlayerInfo, GetDisplayColor)
|
|||
ACTION_RETURN_INT(c);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_PlayerInfo, GetAverageLatency)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(player_t);
|
||||
ACTION_RETURN_INT(ClientStates[self - players].AverageLatency);
|
||||
}
|
||||
|
||||
// Find out which teams are present. If there is only one,
|
||||
// then another team should be chosen at random.
|
||||
//
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@
|
|||
static void HU_DoDrawScores (player_t *, player_t *[MAXPLAYERS]);
|
||||
static void HU_DrawTimeRemaining (int y);
|
||||
static void HU_DrawPlayer(player_t *, bool, int, int, int, int, int, int, int, int, int);
|
||||
static void HU_DrawColorBar(int x, int y, int height, int playernum);
|
||||
|
||||
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
||||
|
||||
|
|
@ -132,8 +133,6 @@ void HU_SortPlayers
|
|||
*/
|
||||
|
||||
bool SB_ForceActive = false;
|
||||
static FFont *displayFont;
|
||||
static int FontScale;
|
||||
|
||||
|
||||
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
||||
|
|
@ -146,345 +145,12 @@ static int FontScale;
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void HU_DrawScores(player_t* player)
|
||||
void HU_DrawScores(int player, double ticFrac)
|
||||
{
|
||||
displayFont = NewSmallFont;
|
||||
FontScale = max<int>(screen->GetHeight() / 400, 1);
|
||||
|
||||
int numPlayers = 0;
|
||||
for (int i = 0; i < MAXPLAYERS; ++i)
|
||||
numPlayers += playeringame[i];
|
||||
|
||||
if (numPlayers > 8)
|
||||
FontScale = static_cast<int>(ceil(FontScale * 0.75));
|
||||
|
||||
if (deathmatch)
|
||||
IFVIRTUALPTR(StatusBar, DBaseStatusBar, Scoreboard_DrawScores)
|
||||
{
|
||||
if (teamplay)
|
||||
{
|
||||
if (!sb_teamdeathmatch_enable)
|
||||
return;
|
||||
}
|
||||
else if (!sb_deathmatch_enable)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (!multiplayer || !sb_cooperative_enable)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
player_t* sortedPlayers[MAXPLAYERS];
|
||||
if (player->camera && player->camera->player)
|
||||
player = player->camera->player;
|
||||
|
||||
sortedPlayers[MAXPLAYERS - 1] = player;
|
||||
for (int i = 0, j = 0; j < MAXPLAYERS - 1; ++i, ++j)
|
||||
{
|
||||
if (&players[i] == player)
|
||||
++i;
|
||||
sortedPlayers[j] = &players[i];
|
||||
}
|
||||
|
||||
if (teamplay && deathmatch)
|
||||
qsort(sortedPlayers, MAXPLAYERS, sizeof(player_t*), compareteams);
|
||||
else
|
||||
qsort(sortedPlayers, MAXPLAYERS, sizeof(player_t*), comparepoints);
|
||||
|
||||
HU_DoDrawScores(player, sortedPlayers);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// HU_GetPlayerWidths
|
||||
//
|
||||
// Returns the widest player name and class icon.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void HU_GetPlayerWidths(int& maxNameWidth, int& maxScoreWidth, int& maxIconHeight)
|
||||
{
|
||||
constexpr char NameLabel[] = "Name";
|
||||
|
||||
displayFont = NewSmallFont;
|
||||
maxNameWidth = displayFont->StringWidth(NameLabel);
|
||||
maxScoreWidth = 0;
|
||||
maxIconHeight = 0;
|
||||
|
||||
for (int i = 0; i < MAXPLAYERS; ++i)
|
||||
{
|
||||
if (!playeringame[i])
|
||||
continue;
|
||||
|
||||
int width = displayFont->StringWidth(players[i].userinfo.GetName(16));
|
||||
if (width > maxNameWidth)
|
||||
maxNameWidth = width;
|
||||
|
||||
auto icon = FSetTextureID(players[i].mo->IntVar(NAME_ScoreIcon));
|
||||
if (icon.isValid())
|
||||
{
|
||||
auto pic = TexMan.GetGameTexture(icon);
|
||||
width = int(pic->GetDisplayWidth() - pic->GetDisplayLeftOffset() + 2.5);
|
||||
if (width > maxScoreWidth)
|
||||
maxScoreWidth = width;
|
||||
|
||||
// The icon's top offset does not count toward its height, because
|
||||
// zdoom.pk3's standard Hexen class icons are designed that way.
|
||||
int height = int(pic->GetDisplayHeight() - pic->GetDisplayTopOffset() + 0.5);
|
||||
if (height > maxIconHeight)
|
||||
maxIconHeight = height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// HU_DoDrawScores
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static void HU_DrawFontScaled(double x, double y, int color, const char *text)
|
||||
{
|
||||
DrawText(twod, displayFont, color, x / FontScale, y / FontScale, text, DTA_VirtualWidth, twod->GetWidth() / FontScale, DTA_VirtualHeight, twod->GetHeight() / FontScale, TAG_END);
|
||||
}
|
||||
|
||||
static void HU_DoDrawScores(player_t* player, player_t* sortedPlayers[MAXPLAYERS])
|
||||
{
|
||||
int color = sb_cooperative_headingcolor;
|
||||
if (deathmatch)
|
||||
{
|
||||
if (teamplay)
|
||||
color = sb_teamdeathmatch_headingcolor;
|
||||
else
|
||||
color = sb_deathmatch_headingcolor;
|
||||
}
|
||||
|
||||
int maxNameWidth, maxScoreWidth, maxIconHeight;
|
||||
HU_GetPlayerWidths(maxNameWidth, maxScoreWidth, maxIconHeight);
|
||||
int height = displayFont->GetHeight() * FontScale;
|
||||
int lineHeight = max<int>(height, maxIconHeight * CleanYfac);
|
||||
int yPadding = (lineHeight - height + 1) / 2;
|
||||
|
||||
int bottom = StatusBar->GetTopOfStatusbar();
|
||||
int y = max<int>(48 * CleanYfac, (bottom - MAXPLAYERS * (height + CleanYfac + 1)) / 2);
|
||||
|
||||
HU_DrawTimeRemaining(bottom - height);
|
||||
|
||||
if (teamplay && deathmatch)
|
||||
{
|
||||
y -= (BigFont->GetHeight() + 8) * CleanYfac;
|
||||
|
||||
for (size_t i = 0u; i < Teams.Size(); ++i)
|
||||
{
|
||||
Teams[i].m_iPlayerCount = 0;
|
||||
Teams[i].m_iScore = 0;
|
||||
}
|
||||
|
||||
int numTeams = 0;
|
||||
for (int i = 0; i < MAXPLAYERS; ++i)
|
||||
{
|
||||
if (playeringame[sortedPlayers[i]-players] && FTeam::IsValid(sortedPlayers[i]->userinfo.GetTeam()))
|
||||
{
|
||||
if (Teams[sortedPlayers[i]->userinfo.GetTeam()].m_iPlayerCount++ == 0)
|
||||
++numTeams;
|
||||
|
||||
Teams[sortedPlayers[i]->userinfo.GetTeam()].m_iScore += sortedPlayers[i]->fragcount;
|
||||
}
|
||||
}
|
||||
|
||||
int scoreXWidth = twod->GetWidth() / max<int>(8, numTeams);
|
||||
int numScores = 0;
|
||||
for (size_t i = 0u; i < Teams.Size(); ++i)
|
||||
{
|
||||
if (Teams[i].m_iPlayerCount)
|
||||
++numScores;
|
||||
}
|
||||
|
||||
int scoreX = (twod->GetWidth() - scoreXWidth * (numScores - 1)) / 2;
|
||||
for (size_t i = 0u; i < Teams.Size(); ++i)
|
||||
{
|
||||
if (!Teams[i].m_iPlayerCount)
|
||||
continue;
|
||||
|
||||
char score[80];
|
||||
mysnprintf(score, countof(score), "%d", Teams[i].m_iScore);
|
||||
|
||||
DrawText(twod, BigFont, Teams[i].GetTextColor(),
|
||||
scoreX - BigFont->StringWidth(score)*CleanXfac/2, y, score,
|
||||
DTA_CleanNoMove, true, TAG_DONE);
|
||||
|
||||
scoreX += scoreXWidth;
|
||||
}
|
||||
|
||||
y += (BigFont->GetHeight() + 8) * CleanYfac;
|
||||
}
|
||||
|
||||
const char* text_color = GStrings.GetString("SCORE_COLOR"),
|
||||
*text_frags = GStrings.GetString(deathmatch ? "SCORE_FRAGS" : "SCORE_KILLS"),
|
||||
*text_name = GStrings.GetString("SCORE_NAME"),
|
||||
*text_delay = GStrings.GetString("SCORE_DELAY");
|
||||
|
||||
int col2 = (displayFont->StringWidth(text_color) + 16) * FontScale;
|
||||
int col3 = col2 + (displayFont->StringWidth(text_frags) + 16) * FontScale;
|
||||
int col4 = col3 + maxScoreWidth * FontScale;
|
||||
int col5 = col4 + (maxNameWidth + 16) * FontScale;
|
||||
int x = (twod->GetWidth() >> 1) - (((displayFont->StringWidth(text_delay) * FontScale) + col5) >> 1);
|
||||
|
||||
//HU_DrawFontScaled(x, y, color, text_color);
|
||||
HU_DrawFontScaled(x + col2, y, color, text_frags);
|
||||
HU_DrawFontScaled(x + col4, y, color, text_name);
|
||||
HU_DrawFontScaled(x + col5, y, color, text_delay);
|
||||
|
||||
y += height + 6 * CleanYfac;
|
||||
bottom -= height;
|
||||
|
||||
for (int i = 0; i < MAXPLAYERS && y <= bottom; ++i)
|
||||
{
|
||||
if (!playeringame[sortedPlayers[i] - players])
|
||||
continue;
|
||||
|
||||
HU_DrawPlayer(sortedPlayers[i], player == sortedPlayers[i], x, col2, col3, col4, col5, maxNameWidth, y, yPadding, lineHeight);
|
||||
y += lineHeight + CleanYfac;
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// HU_DrawTimeRemaining
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static void HU_DrawTimeRemaining (int y)
|
||||
{
|
||||
if (deathmatch && timelimit && gamestate == GS_LEVEL)
|
||||
{
|
||||
char str[80];
|
||||
int timeleft = (int)(timelimit * TICRATE * 60) - primaryLevel->maptime;
|
||||
int hours, minutes, seconds;
|
||||
|
||||
if (timeleft < 0)
|
||||
timeleft = 0;
|
||||
|
||||
hours = timeleft / (TICRATE * 3600);
|
||||
timeleft -= hours * TICRATE * 3600;
|
||||
minutes = timeleft / (TICRATE * 60);
|
||||
timeleft -= minutes * TICRATE * 60;
|
||||
seconds = timeleft / TICRATE;
|
||||
|
||||
if (hours)
|
||||
mysnprintf (str, countof(str), "Level ends in %d:%02d:%02d", hours, minutes, seconds);
|
||||
else
|
||||
mysnprintf (str, countof(str), "Level ends in %d:%02d", minutes, seconds);
|
||||
|
||||
HU_DrawFontScaled(twod->GetWidth() / 2 - displayFont->StringWidth(str) / 2 * FontScale, y, CR_GRAY, str);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// HU_DrawPlayer
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static void HU_DrawPlayer (player_t *player, bool highlight, int col1, int col2, int col3, int col4, int col5, int maxnamewidth, int y, int ypadding, int height)
|
||||
{
|
||||
int color;
|
||||
char str[80];
|
||||
|
||||
if (highlight)
|
||||
{
|
||||
// The teamplay mode uses colors to show teams, so we need some
|
||||
// other way to do highlighting. And it may as well be used for
|
||||
// all modes for the sake of consistancy.
|
||||
Dim(twod, MAKERGB(200,245,255), 0.125f, col1 - 12*FontScale, y - 1, col5 + (maxnamewidth + 24)*FontScale, height + 2);
|
||||
}
|
||||
|
||||
col2 += col1;
|
||||
col3 += col1;
|
||||
col4 += col1;
|
||||
col5 += col1;
|
||||
|
||||
color = HU_GetRowColor(player, highlight);
|
||||
HU_DrawColorBar(col1, y, height, (int)(player - players));
|
||||
mysnprintf (str, countof(str), "%d", deathmatch ? player->fragcount : player->killcount);
|
||||
|
||||
HU_DrawFontScaled(col2, y + ypadding, color, player->playerstate == PST_DEAD && !deathmatch ? "DEAD" : str);
|
||||
|
||||
auto icon = FSetTextureID(player->mo->IntVar(NAME_ScoreIcon));
|
||||
if (icon.isValid())
|
||||
{
|
||||
DrawTexture(twod, icon, false, col3, y,
|
||||
DTA_CleanNoMove, true,
|
||||
TAG_DONE);
|
||||
}
|
||||
|
||||
HU_DrawFontScaled(col4, y + ypadding, color, player->userinfo.GetName());
|
||||
|
||||
mysnprintf(str, countof(str), "%u", ClientStates[player - players].AverageLatency);
|
||||
|
||||
HU_DrawFontScaled(col5, y + ypadding, color, str);
|
||||
|
||||
const int team = player->userinfo.GetTeam();
|
||||
if (team != TEAM_NONE && teamplay && Teams[team].GetLogo().IsNotEmpty ())
|
||||
{
|
||||
auto pic = TexMan.GetGameTextureByName(Teams[player->userinfo.GetTeam()].GetLogo().GetChars ());
|
||||
DrawTexture(twod, pic, col1 - (pic->GetDisplayWidth() + 2) * CleanXfac, y,
|
||||
DTA_CleanNoMove, true, TAG_DONE);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// HU_DrawColorBar
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void HU_DrawColorBar(int x, int y, int height, int playernum)
|
||||
{
|
||||
float h, s, v, r, g, b;
|
||||
|
||||
D_GetPlayerColor (playernum, &h, &s, &v, NULL);
|
||||
HSVtoRGB (&r, &g, &b, h, s, v);
|
||||
|
||||
ClearRect(twod, x, y, x + 24*FontScale, y + height, -1,
|
||||
MAKEARGB(255,clamp(int(r*255.f),0,255),
|
||||
clamp(int(g*255.f),0,255),
|
||||
clamp(int(b*255.f),0,255)));
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// HU_GetRowColor
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int HU_GetRowColor(player_t *player, bool highlight)
|
||||
{
|
||||
if (teamplay && deathmatch)
|
||||
{
|
||||
if (FTeam::IsValid (player->userinfo.GetTeam()))
|
||||
return Teams[player->userinfo.GetTeam()].GetTextColor();
|
||||
else
|
||||
return CR_GREY;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!highlight)
|
||||
{
|
||||
if (demoplayback && player == &players[consoleplayer])
|
||||
{
|
||||
return CR_GOLD;
|
||||
}
|
||||
else
|
||||
{
|
||||
return deathmatch ? sb_deathmatch_otherplayercolor : sb_cooperative_otherplayercolor;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return deathmatch ? sb_deathmatch_yourplayercolor : sb_cooperative_yourplayercolor;
|
||||
}
|
||||
VMValue params[] = { (DObject*)StatusBar, player, ticFrac };
|
||||
VMCall(func, params, countof(params), nullptr, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -42,16 +42,8 @@ void CT_Drawer (void);
|
|||
|
||||
// [RH] Draw deathmatch scores
|
||||
|
||||
void HU_DrawScores(player_t* me);
|
||||
void HU_GetPlayerWidths(int& maxNameWidth, int& maxScoreWidth, int& maxIconHeight);
|
||||
void HU_DrawColorBar(int x, int y, int height, int playernum);
|
||||
int HU_GetRowColor(player_t *player, bool hightlight);
|
||||
void HU_DrawScores(int me, double ticFrac);
|
||||
|
||||
extern bool SB_ForceActive;
|
||||
|
||||
// Sorting routines
|
||||
|
||||
int comparepoints(const void *arg1, const void *arg2);
|
||||
int compareteams(const void *arg1, const void *arg2);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -2369,6 +2369,13 @@ DEFINE_ACTION_FUNCTION_NATIVE(FLevelLocals, GetUDMFString, ZGetUDMFString)
|
|||
ACTION_RETURN_STRING(GetUDMFString(self, type, index, key));
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(FLevelLocals, PlayerNum)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals);
|
||||
PARAM_POINTER(player, player_t);
|
||||
ACTION_RETURN_INT(self->PlayerNum(player));
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(FLevelLocals, GetChecksum)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals);
|
||||
|
|
|
|||
|
|
@ -1219,69 +1219,6 @@ DObject* WI_Start(wbstartstruct_t *wbstartstruct)
|
|||
//
|
||||
//====================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DStatusScreen, GetPlayerWidths)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
int maxnamewidth, maxscorewidth, maxiconheight;
|
||||
HU_GetPlayerWidths(maxnamewidth, maxscorewidth, maxiconheight);
|
||||
if (numret > 0) ret[0].SetInt(maxnamewidth);
|
||||
if (numret > 1) ret[1].SetInt(maxscorewidth);
|
||||
if (numret > 2) ret[2].SetInt(maxiconheight);
|
||||
return min(numret, 3);
|
||||
}
|
||||
|
||||
//====================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//====================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DStatusScreen, GetRowColor)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_POINTER(p, player_t);
|
||||
PARAM_BOOL(highlight);
|
||||
ACTION_RETURN_INT(HU_GetRowColor(p, highlight));
|
||||
}
|
||||
|
||||
//====================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//====================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DStatusScreen, GetSortedPlayers)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_POINTER(array, TArray<int>);
|
||||
PARAM_BOOL(teamplay);
|
||||
|
||||
player_t *sortedplayers[MAXPLAYERS];
|
||||
// Sort all players
|
||||
for (int i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
sortedplayers[i] = &players[i];
|
||||
}
|
||||
|
||||
if (teamplay)
|
||||
qsort(sortedplayers, MAXPLAYERS, sizeof(player_t *), compareteams);
|
||||
else
|
||||
qsort(sortedplayers, MAXPLAYERS, sizeof(player_t *), comparepoints);
|
||||
|
||||
array->Resize(MAXPLAYERS);
|
||||
for (unsigned i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
(*array)[i] = int(sortedplayers[i] - players);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//====================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//====================================================================
|
||||
|
||||
DEFINE_FIELD_X(WBPlayerStruct, wbplayerstruct_t, skills);
|
||||
DEFINE_FIELD_X(WBPlayerStruct, wbplayerstruct_t, sitems);
|
||||
DEFINE_FIELD_X(WBPlayerStruct, wbplayerstruct_t, ssecret);
|
||||
|
|
|
|||
|
|
@ -308,6 +308,7 @@ version "4.15.1"
|
|||
#include "zscript/ui/statusbar/sbarinfowrapper.zs"
|
||||
#include "zscript/ui/statusbar/statusbar.zs"
|
||||
#include "zscript/ui/statusbar/strife_sbar.zs"
|
||||
#include "zscript/ui/statusbar/scoreboard.zs"
|
||||
|
||||
#include "zscript/ui/intermission.zs"
|
||||
|
||||
|
|
|
|||
|
|
@ -3002,6 +3002,8 @@ struct PlayerInfo native play // self is what internally is known as player_t
|
|||
native clearscope bool GetClassicFlight() const;
|
||||
native void SendPitchLimits();
|
||||
native clearscope bool HasWeaponsInSlot(int slot) const;
|
||||
|
||||
native clearscope int GetAverageLatency() const;
|
||||
|
||||
// The actual implementation is on PlayerPawn where it can be overridden. Use that directly in the future.
|
||||
deprecated("3.7", "MorphPlayer() should be used on a PlayerPawn object") bool MorphPlayer(PlayerInfo activator, class<PlayerPawn> spawnType, int duration, EMorphFlags style, class<Actor> enterFlash = "TeleportFog", class<Actor> exitFlash = "TeleportFog")
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
// for flag changer functions.
|
||||
const FLAG_NO_CHANGE = -1;
|
||||
const MAXPLAYERS = 64;
|
||||
const TEAM_NONE = 255;
|
||||
const TEAM_MAXIMUM = 16;
|
||||
|
||||
enum EStateUseFlags
|
||||
{
|
||||
|
|
|
|||
|
|
@ -587,6 +587,8 @@ struct LevelLocals native
|
|||
native clearscope int ActorOnLineSide(Actor mo, Line l) const;
|
||||
native clearscope int BoxOnLineSide(Vector2 pos, double radius, Line l) const;
|
||||
|
||||
native clearscope int PlayerNum(PlayerInfo player) const;
|
||||
|
||||
native String GetChecksum() const;
|
||||
|
||||
native void ChangeSky(TextureID sky1, TextureID sky2 );
|
||||
|
|
|
|||
|
|
@ -578,6 +578,11 @@ struct Screen native
|
|||
native static void ClearStencil();
|
||||
native static void SetTransform(Shape2DTransform transform);
|
||||
native static void ClearTransform();
|
||||
|
||||
native static double GetTextureWidth(TextureID texture, bool animated = false);
|
||||
native static double GetTextureHeight(TextureID texture, bool animated = false);
|
||||
native static double GetTextureLeftOffset(TextureID texture, bool animated = false);
|
||||
native static double GetTextureTopOffset(TextureID texture, bool animated = false);
|
||||
}
|
||||
|
||||
struct Font native
|
||||
|
|
@ -948,6 +953,12 @@ struct StringStruct native unsafe(internal)
|
|||
native void StripLeft(String junk = "");
|
||||
native void StripRight(String junk = "");
|
||||
native void StripLeftRight(String junk = "");
|
||||
|
||||
native int Compare(String other) const; // strcmp
|
||||
native int CompareNoCase(String other) const; // stricmp
|
||||
|
||||
native bool IsEmpty() const; // strcmp
|
||||
native bool IsNotEmpty() const; // stricmp
|
||||
}
|
||||
|
||||
struct Translation version("2.4")
|
||||
|
|
|
|||
|
|
@ -967,7 +967,40 @@ class StatusScreen : ScreenJob abstract version("2.5")
|
|||
protected virtual void updateStats() {}
|
||||
protected virtual void drawStats() {}
|
||||
|
||||
native static int, int, int GetPlayerWidths();
|
||||
native static Color GetRowColor(PlayerInfo player, bool highlight);
|
||||
native static void GetSortedPlayers(in out Array<int> sorted, bool teamplay);
|
||||
static int, int, int GetPlayerWidths()
|
||||
{
|
||||
int maxNameWidth;
|
||||
int maxScoreWidth;
|
||||
int maxIconHeight;
|
||||
|
||||
StatusBar.Scoreboard_GetPlayerWidths(maxNameWidth, maxScoreWidth, maxIconHeight);
|
||||
|
||||
return maxNameWidth, maxScoreWidth, maxIconHeight;
|
||||
}
|
||||
|
||||
static Color GetRowColor(PlayerInfo player, bool highlight)
|
||||
{
|
||||
return StatusBar.Scoreboard_GetRowColor(player, highlight);
|
||||
}
|
||||
|
||||
static void GetSortedPlayers(in out Array<int> sorted, bool teamplay)
|
||||
{
|
||||
sorted.clear();
|
||||
for(int i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if(playeringame[i])
|
||||
{
|
||||
sorted.Push(i);
|
||||
}
|
||||
}
|
||||
|
||||
if(teamplay)
|
||||
{
|
||||
StatusBar.Scoreboard_SortPlayers(sorted, BaseStatusBar.Scoreboard_CompareByTeams);
|
||||
}
|
||||
else
|
||||
{
|
||||
StatusBar.Scoreboard_SortPlayers(sorted, BaseStatusBar.Scoreboard_CompareByPoints);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
449
wadsrc/static/zscript/ui/statusbar/scoreboard.zs
Normal file
449
wadsrc/static/zscript/ui/statusbar/scoreboard.zs
Normal file
|
|
@ -0,0 +1,449 @@
|
|||
|
||||
extend class BaseStatusBar
|
||||
{
|
||||
Font scoreboardFont;
|
||||
|
||||
virtual void InitScoreboard()
|
||||
{
|
||||
scoreboardFont = NewSmallFont;
|
||||
}
|
||||
|
||||
static clearscope int Scoreboard_CompareByTeams(int playerA, int playerB)
|
||||
{
|
||||
// Compare first by teams, then by frags, then by name.
|
||||
PlayerInfo p1 = players[playerA];
|
||||
PlayerInfo p2 = players[playerB];
|
||||
|
||||
int diff = p1.GetTeam() - p2.GetTeam();
|
||||
|
||||
if(diff == 0)
|
||||
{
|
||||
diff = p2.fragcount - p1.fragcount;
|
||||
if(diff == 0)
|
||||
{
|
||||
diff = p1.GetUserName().CompareNoCase(p2.GetUserName());
|
||||
}
|
||||
}
|
||||
return diff;
|
||||
}
|
||||
|
||||
static clearscope int Scoreboard_CompareByPoints(int playerA, int playerB)
|
||||
{
|
||||
// Compare first by frags/kills, then by name.
|
||||
PlayerInfo p1 = players[playerA];
|
||||
PlayerInfo p2 = players[playerB];
|
||||
|
||||
int diff = deathmatch ? (p2.fragcount - p1.fragcount) : (p2.killcount - p1.killcount);
|
||||
|
||||
if(diff == 0)
|
||||
{
|
||||
diff = p1.GetUserName().CompareNoCase(p2.GetUserName());
|
||||
}
|
||||
return diff;
|
||||
}
|
||||
|
||||
static void Scoreboard_SortPlayers(out Array<int> players, Function<clearscope int(int, int)> compareFunc)
|
||||
{
|
||||
Array<int> unsorted;
|
||||
unsorted.Move(players);
|
||||
|
||||
players.Push(unsorted[0]);
|
||||
|
||||
for(int i = 1; i < unsorted.Size(); i++)
|
||||
{
|
||||
bool inserted = false;
|
||||
|
||||
for(int j = 0; j < players.Size(); j++)
|
||||
{
|
||||
if(compareFunc.Call(players[j], unsorted[i]) > 0)
|
||||
{
|
||||
players.Insert(j, unsorted[i]);
|
||||
inserted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!inserted)
|
||||
{
|
||||
players.Push(unsorted[i]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
virtual void Scoreboard_DrawScores(int playerNum, double ticFrac)
|
||||
{
|
||||
if(deathmatch)
|
||||
{
|
||||
if(teamplay)
|
||||
{
|
||||
if(!sb_teamdeathmatch_enable)
|
||||
return;
|
||||
}
|
||||
else if(!sb_deathmatch_enable)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if(!multiplayer || !sb_cooperative_enable)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(!scoreboardFont) InitScoreboard();
|
||||
|
||||
PlayerInfo player = players[playernum];
|
||||
|
||||
if(player.camera && player.camera.player)
|
||||
{
|
||||
player = player.camera.player;
|
||||
playerNum = Level.PlayerNum(player);
|
||||
}
|
||||
|
||||
Array<int> sortedPlayers;
|
||||
|
||||
for(int i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if(playeringame[i])
|
||||
{
|
||||
sortedPlayers.Push(i);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
console.printf("SortedPlayers was [");
|
||||
|
||||
foreach(p : sortedPlayers)
|
||||
{
|
||||
console.printf("%d", p);
|
||||
}
|
||||
|
||||
console.printf("]");
|
||||
*/
|
||||
|
||||
if(teamplay && deathmatch)
|
||||
{
|
||||
Scoreboard_SortPlayers(sortedPlayers, Scoreboard_CompareByTeams);
|
||||
}
|
||||
else
|
||||
{
|
||||
Scoreboard_SortPlayers(sortedPlayers, Scoreboard_CompareByPoints);
|
||||
}
|
||||
|
||||
/*
|
||||
console.printf("SortedPlayers is now [");
|
||||
|
||||
foreach(p : sortedPlayers)
|
||||
{
|
||||
console.printf("%d", p);
|
||||
}
|
||||
|
||||
console.printf("]");
|
||||
*/
|
||||
|
||||
int numPlayers = sortedPlayers.size();
|
||||
|
||||
int FontScale = max(screen.GetHeight() / 400, 1);
|
||||
|
||||
if(numPlayers > 8)
|
||||
FontScale = int(ceil(FontScale * 0.75));
|
||||
|
||||
Scoreboard_DoDrawScores(player, sortedPlayers, FontScale, ticFrac);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// HU_DrawFontScaled
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void Scoreboard_DrawFontScaled(double x, double y, Color color, String text, int FontScale)
|
||||
{
|
||||
screen.DrawText(scoreboardFont, color, x / FontScale, y / FontScale, text, DTA_VirtualWidth, screen.GetWidth() / FontScale, DTA_VirtualHeight, screen.GetHeight() / FontScale);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// HU_DoDrawScores
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
virtual void Scoreboard_DoDrawScores(PlayerInfo player, Array<int> sortedPlayers, int FontScale, double ticFrac)
|
||||
{
|
||||
Color _color = sb_cooperative_headingcolor;
|
||||
if(deathmatch)
|
||||
{
|
||||
if (teamplay)
|
||||
_color = sb_teamdeathmatch_headingcolor;
|
||||
else
|
||||
_color = sb_deathmatch_headingcolor;
|
||||
}
|
||||
|
||||
int maxNameWidth, maxScoreWidth, maxIconHeight;
|
||||
Scoreboard_GetPlayerWidths(maxNameWidth, maxScoreWidth, maxIconHeight);
|
||||
int height = scoreboardFont.GetHeight() * FontScale;
|
||||
int lineHeight = max(height, maxIconHeight * CleanYfac);
|
||||
int yPadding = (lineHeight - height + 1) / 2;
|
||||
|
||||
int bottom = GetTopOfStatusbar();
|
||||
int y = max(48 * CleanYfac, (bottom - MAXPLAYERS * (height + CleanYfac + 1)) / 2);
|
||||
|
||||
Scoreboard_DrawTimeRemaining(bottom - height, FontScale);
|
||||
|
||||
Array<int> teamPlayerCounts;
|
||||
Array<int> teamScores;
|
||||
|
||||
teamPlayerCounts.Resize(Teams.Size());
|
||||
teamScores.Resize(Teams.Size());
|
||||
|
||||
if(teamplay && deathmatch)
|
||||
{
|
||||
y -= (BigFont.GetHeight() + 8) * CleanYfac;
|
||||
|
||||
int numTeams = 0;
|
||||
for(int i = 0; i < MAXPLAYERS; ++i)
|
||||
{
|
||||
PlayerInfo p = players[sortedPlayers[i]];
|
||||
if (playeringame[sortedPlayers[i]] && Team.IsValid(p.GetTeam()))
|
||||
{
|
||||
if (teamPlayerCounts[p.GetTeam()]++ == 0)
|
||||
++numTeams;
|
||||
|
||||
teamScores[p.GetTeam()] += p.fragcount;
|
||||
}
|
||||
}
|
||||
|
||||
int scoreXWidth = screen.GetWidth() / max(8, numTeams);
|
||||
int numScores = 0;
|
||||
for(int i = 0; i < Teams.Size(); ++i)
|
||||
{
|
||||
if (teamPlayerCounts[i])
|
||||
++numScores;
|
||||
}
|
||||
|
||||
int scoreX = (screen.GetWidth() - scoreXWidth * (numScores - 1)) / 2;
|
||||
for(int i = 0; i < Teams.Size(); ++i)
|
||||
{
|
||||
if (!teamPlayerCounts[i])
|
||||
continue;
|
||||
|
||||
String score = String.Format("%d", teamScores[i]);
|
||||
|
||||
screen.DrawText(BigFont, Teams[i].GetTextColor(),
|
||||
scoreX - BigFont.StringWidth(score)*CleanXfac/2, y, score,
|
||||
DTA_CleanNoMove, true);
|
||||
|
||||
scoreX += scoreXWidth;
|
||||
}
|
||||
|
||||
y += (BigFont.GetHeight() + 8) * CleanYfac;
|
||||
}
|
||||
|
||||
String text_color = StringTable.Localize("$SCORE_COLOR"),
|
||||
text_frags = StringTable.Localize(deathmatch ? "$SCORE_FRAGS" : "$SCORE_KILLS"),
|
||||
text_name = StringTable.Localize("$SCORE_NAME"),
|
||||
text_delay = StringTable.Localize("$SCORE_DELAY");
|
||||
|
||||
int col2 = (scoreboardFont.StringWidth(text_color) + 16) * FontScale;
|
||||
int col3 = col2 + (scoreboardFont.StringWidth(text_frags) + 16) * FontScale;
|
||||
int col4 = col3 + maxScoreWidth * FontScale;
|
||||
int col5 = col4 + (maxNameWidth + 16) * FontScale;
|
||||
int x = (screen.GetWidth() >> 1) - (((scoreboardFont.StringWidth(text_delay) * FontScale) + col5) >> 1);
|
||||
|
||||
//Scoreboard_DrawFontScaled(x, y, _color, text_color);
|
||||
Scoreboard_DrawFontScaled(x + col2, y, _color, text_frags, FontScale);
|
||||
Scoreboard_DrawFontScaled(x + col4, y, _color, text_name, FontScale);
|
||||
Scoreboard_DrawFontScaled(x + col5, y, _color, text_delay, FontScale);
|
||||
|
||||
y += height + 6 * CleanYfac;
|
||||
bottom -= height;
|
||||
|
||||
for(int i = 0; i < sortedPlayers.Size() && y <= bottom; ++i)
|
||||
{
|
||||
Scoreboard_DrawPlayer(players[sortedPlayers[i]], Level.PlayerNum(player) == sortedPlayers[i], x, col2, col3, col4, col5, maxNameWidth, y, yPadding, lineHeight, FontScale);
|
||||
y += lineHeight + CleanYfac;
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// HU_DrawTimeRemaining
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void Scoreboard_DrawTimeRemaining(int y, int FontScale)
|
||||
{
|
||||
if(deathmatch && timelimit && gamestate == GS_LEVEL)
|
||||
{
|
||||
int timeleft = int(timelimit * GameTicRate * 60) - Level.maptime;
|
||||
|
||||
int hours, minutes, seconds;
|
||||
|
||||
if(timeleft < 0) timeleft = 0;
|
||||
|
||||
hours = timeleft / (GameTicRate * 3600);
|
||||
timeleft -= hours * GameTicRate * 3600;
|
||||
minutes = timeleft / (GameTicRate * 60);
|
||||
timeleft -= minutes * GameTicRate * 60;
|
||||
seconds = timeleft / GameTicRate;
|
||||
|
||||
String str;
|
||||
if(hours)
|
||||
{
|
||||
str = String.Format("Level ends in %d:%02d:%02d", hours, minutes, seconds);
|
||||
}
|
||||
else
|
||||
{
|
||||
str = String.Format("Level ends in %d:%02d", minutes, seconds);
|
||||
}
|
||||
|
||||
Scoreboard_DrawFontScaled(screen.GetWidth() / 2 - scoreboardFont.StringWidth(str) / 2 * FontScale, y, Font.CR_GRAY, str, FontScale);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// HU_DrawPlayer
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void Scoreboard_DrawPlayer(PlayerInfo player, bool highlight, int col1, int col2, int col3, int col4, int col5, int maxnamewidth, int y, int ypadding, int height, int FontScale)
|
||||
{
|
||||
String str;
|
||||
|
||||
if(highlight)
|
||||
{
|
||||
// The teamplay mode uses colors to show teams, so we need some
|
||||
// other way to do highlighting. And it may as well be used for
|
||||
// all modes for the sake of consistancy.
|
||||
screen.Dim(Color(200,245,255), 0.125f, col1 - 12 * FontScale, y - 1, col5 + (maxnamewidth + 24) * FontScale, height + 2);
|
||||
}
|
||||
|
||||
col2 += col1;
|
||||
col3 += col1;
|
||||
col4 += col1;
|
||||
col5 += col1;
|
||||
|
||||
Color _color = Scoreboard_GetRowColor(player, highlight);
|
||||
Scoreboard_DrawColorBar(col1, y, height, player, FontScale);
|
||||
|
||||
str = String.Format("%d", deathmatch ? player.fragcount : player.killcount);
|
||||
|
||||
Scoreboard_DrawFontScaled(col2, y + ypadding, _color, player.playerstate == PST_DEAD && !deathmatch ? "DEAD" : str, FontScale);
|
||||
|
||||
TextureID icon = player.mo.ScoreIcon;
|
||||
|
||||
if(icon.isValid())
|
||||
{
|
||||
screen.DrawTexture(icon, false, col3, y, DTA_CleanNoMove, true);
|
||||
}
|
||||
|
||||
Scoreboard_DrawFontScaled(col4, y + ypadding, _color, player.GetUserName(), FontScale);
|
||||
|
||||
str = String.Format("%d", player.GetAverageLatency());
|
||||
|
||||
Scoreboard_DrawFontScaled(col5, y + ypadding, _color, str, FontScale);
|
||||
|
||||
int team = player.GetTeam();
|
||||
|
||||
if(team != TEAM_NONE && teamplay && Teams[team].GetLogoName().IsNotEmpty())
|
||||
{
|
||||
TextureID pic = Teams[team].GetLogo();
|
||||
screen.DrawTexture(pic, col1 - (screen.GetTextureWidth(pic) + 2) * CleanXfac, y, DTA_CleanNoMove, true);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// HU_DrawColorBar
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static void Scoreboard_DrawColorBar(int x, int y, int height, PlayerInfo player, int FontScale)
|
||||
{
|
||||
Screen.Clear(x, y, x + 24 * FontScale, y + height, player.GetDisplayColor());
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// HU_GetRowColor
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static Color Scoreboard_GetRowColor(PlayerInfo player, bool highlight)
|
||||
{
|
||||
if(teamplay && deathmatch)
|
||||
{
|
||||
if(Team.IsValid(player.GetTeam()))
|
||||
{
|
||||
Color teamColor = Teams[player.GetTeam()].GetTextColor();
|
||||
return teamColor;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Font.CR_GREY;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!highlight)
|
||||
{
|
||||
if(demoplayback && Level.PlayerNum(player) == consoleplayer)
|
||||
{
|
||||
return Font.CR_GOLD;
|
||||
}
|
||||
else
|
||||
{
|
||||
return deathmatch ? sb_deathmatch_otherplayercolor : sb_cooperative_otherplayercolor;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return deathmatch ? sb_deathmatch_yourplayercolor : sb_cooperative_yourplayercolor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// HU_GetPlayerWidths
|
||||
//
|
||||
// Returns the widest player name and class icon.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void Scoreboard_GetPlayerWidths(int& maxNameWidth, int& maxScoreWidth, int& maxIconHeight)
|
||||
{
|
||||
if(!scoreboardFont) InitScoreboard();
|
||||
|
||||
maxNameWidth = scoreboardFont.StringWidth("Name");
|
||||
maxScoreWidth = 0;
|
||||
maxIconHeight = 0;
|
||||
|
||||
for (int i = 0; i < MAXPLAYERS; ++i)
|
||||
{
|
||||
if (!playeringame[i])
|
||||
continue;
|
||||
|
||||
int width = scoreboardFont.StringWidth(players[i].GetUserName(16));
|
||||
if (width > maxNameWidth)
|
||||
maxNameWidth = width;
|
||||
|
||||
TextureID icon = players[i].mo.ScoreIcon;
|
||||
if (icon.isValid())
|
||||
{
|
||||
width = int(screen.GetTextureWidth(icon) - screen.GetTextureLeftOffset(icon) + 2.5);
|
||||
if (width > maxScoreWidth)
|
||||
maxScoreWidth = width;
|
||||
|
||||
// The icon's top offset does not count toward its height, because
|
||||
// zdoom.pk3's standard Hexen class icons are designed that way.
|
||||
int height = int(screen.GetTextureHeight(icon) - screen.GetTextureTopOffset(icon) + 0.5);
|
||||
if (height > maxIconHeight)
|
||||
maxIconHeight = height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -214,6 +214,7 @@ class BaseStatusBar : StatusBarCore native
|
|||
|
||||
virtual void Init()
|
||||
{
|
||||
InitScoreboard();
|
||||
}
|
||||
|
||||
virtual void Draw (int state, double TicFrac)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue