diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 94f4084f6..815461f62 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -160,7 +160,10 @@ static tic_t neededtic; SINT8 servernode = 0; // the number of the server node SINT8 joinnode = 0; // used for CL_VIEWSERVER -char connectedservername[MAXSERVERNAME+1]; +char connectedservername[MAXSERVERNAME]; +char connectedservercontact[MAXSERVERCONTACT]; +char connectedserverdescription[MAXSERVERDESCRIPTION]; + /// \brief do we accept new players? /// \todo WORK! boolean acceptnewnode = true; @@ -867,7 +870,7 @@ static boolean CL_SendJoin(void) return HSendPacket(servernode, false, 0, sizeof (clientconfig_pak)); } -static void +void CopyCaretColors (char *p, const char *s, int n) { char *t; @@ -1140,6 +1143,10 @@ static boolean SV_SendServerConfig(INT32 node) memcpy(netbuffer->u.servercfg.server_context, server_context, 8); + strncpy(netbuffer->u.servercfg.server_name, cv_servername.string, MAXSERVERNAME); + strncpy(netbuffer->u.servercfg.server_contact, cv_server_contact.string, MAXSERVERCONTACT); + strncpy(netbuffer->u.servercfg.server_description, connectedserverdescription, MAXSERVERDESCRIPTION); + { const size_t len = sizeof (serverconfig_pak); @@ -3545,14 +3552,19 @@ void SV_ResetServer(void) // clear server_context memset(server_context, '-', 8); + memset(connectedservername, 0, MAXSERVERNAME); + memset(connectedservercontact, 0, MAXSERVERCONTACT); + memset(connectedserverdescription, 0, MAXSERVERDESCRIPTION); + CV_RevertNetVars(); DEBFILE("\n-=-=-=-=-=-=-= Server Reset =-=-=-=-=-=-=-\n\n"); } -static inline void SV_GenContext(void) +static void SV_GenContext(void) { UINT8 i; + // generate server_context, as exactly 8 bytes of randomly mixed A-Z and a-z // (hopefully M_Random is initialized!! if not this will be awfully silly!) for (i = 0; i < 8; i++) @@ -3563,6 +3575,10 @@ static inline void SV_GenContext(void) else // lowercase server_context[i] = 'a'+(a-26); } + + CopyCaretColors(connectedservername, cv_servername.string, MAXSERVERNAME); + CopyCaretColors(connectedservercontact, cv_server_contact.string, MAXSERVERCONTACT); + strncpy(connectedserverdescription, DEFAULTDESCSTRING, MAXSERVERDESCRIPTION); } // @@ -4365,6 +4381,40 @@ static void PT_LoginAuth(SINT8 node, INT32 netconsole) CONS_Printf(M_GetText("Password from %s failed.\n"), player_names[netconsole]); } +void ServerInfoUpdateSend(void) +{ + UINT32 n; + doomdata_t *netbuffer = DOOMCOM_DATA(doomcom); + + for (n = 1; n < MAXNETNODES; n++) + { + // Do Shit + if (nodeingame[n]) + { + CopyCaretColors(netbuffer->u.serverinfoupdate.servername, cv_servername.string, MAXSERVERNAME); + CopyCaretColors(netbuffer->u.serverinfoupdate.servercontact, cv_server_contact.string, MAXSERVERCONTACT); + strncpy(netbuffer->u.serverinfoupdate.serverdescription, connectedserverdescription, MAXSERVERDESCRIPTION); + + netbuffer->packettype = PT_SERVERINFOUPDATE; + HSendPacket(n, true, 0, sizeof(netbuffer->u.serverinfoupdate)); + } + } +} + +static void PT_ServerInfoUpdate(SINT8 node) +{ + doomdata_t *netbuffer = DOOMCOM_DATA(doomcom); + + if (node != servernode) + return; + + if ((size_t)doomcom->datalength < sizeof(netbuffer->u.serverinfoupdate))/* ignore partial sends */ + return; + + strncpy(connectedservername, netbuffer->u.serverinfoupdate.servername, MAXSERVERNAME); + strncpy(connectedservercontact, netbuffer->u.serverinfoupdate.servercontact, MAXSERVERCONTACT); + strncpy(connectedserverdescription, netbuffer->u.serverinfoupdate.serverdescription, MAXSERVERDESCRIPTION); +} /** Called when a PT_NODETIMEOUT packet is received * @@ -4593,7 +4643,12 @@ static void HandlePacketFromAwayNode(SINT8 node) G_SetGametype(netbuffer->u.servercfg.gametype); modifiedgame = netbuffer->u.servercfg.modifiedgame; + memcpy(server_context, netbuffer->u.servercfg.server_context, 8); + + strncpy(connectedservername, netbuffer->u.servercfg.server_name, MAXSERVERNAME); + strncpy(connectedservercontact, netbuffer->u.servercfg.server_contact, MAXSERVERCONTACT); + strncpy(connectedserverdescription, netbuffer->u.servercfg.server_description, MAXSERVERDESCRIPTION); } #ifdef HAVE_DISCORDRPC @@ -5136,6 +5191,9 @@ static void HandlePacketFromPlayer(SINT8 node) case PT_LOGINCHALLENGE: PT_LoginChallenge(node); break; + case PT_SERVERINFOUPDATE: + PT_ServerInfoUpdate(node); + break; case PT_WILLRESENDGAMESTATE: PT_WillResendGamestate(); break; diff --git a/src/d_clisrv.h b/src/d_clisrv.h index ae0e71a91..0002cdb80 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -41,6 +41,15 @@ applications may follow different packet versions. // one that defines the actual packets to // be transmitted. +#define MAXSERVERNAME 32 +#define MAXSERVERCONTACT 320 +#define MAXSERVERDESCRIPTION 320 +#define MAXSERVERDESCRIPTIONLINE 40 +#define DEFAULTDESCSTRING "Welcome to my SRB2Kart server!\n" + +// Sends over info via packets to client players. +void ServerInfoUpdateSend(void); + // Networking and tick handling related. #define BACKUPTICS 512 // more than enough for most timeouts.... #define CLIENTBACKUPTICS 32 @@ -121,6 +130,8 @@ typedef enum PT_LOGINAUTH, // Challenge response from the client. PT_PING, // Packet sent to tell clients the other client's latency to server. + + PT_SERVERINFOUPDATE, // Update server info for clients. NUMPACKETTYPE } packettype_t; @@ -211,6 +222,10 @@ struct serverconfig_pak UINT8 maxplayer; boolean allownewplayer; boolean discordinvites; + + char server_name[MAXSERVERNAME]; + char server_contact[MAXSERVERCONTACT]; + char server_description[MAXSERVERDESCRIPTION]; } ATTRPACK; struct filetx_pak @@ -259,7 +274,6 @@ struct clientconfig_pak #define SV_DEDICATED 0x40 // server is dedicated #define SV_LOTSOFADDONS 0x20 // flag used to ask for full file list in d_netfil -#define MAXSERVERNAME 32 #define MAXFILENEEDED 915 #define MAX_MIRROR_LENGTH 256 // This packet is too large @@ -296,6 +310,13 @@ struct serverinfo_pak UINT8 fileneeded[MAXFILENEEDED]; // is filled with writexxx (byteptr.h) } ATTRPACK; +struct serverinfoupdate_pak +{ + char servername[MAXSERVERNAME]; + char servercontact[MAXSERVERCONTACT]; + char serverdescription[MAXSERVERDESCRIPTION]; +}; + struct serverrefuse_pak { char reason[255]; @@ -365,28 +386,29 @@ struct doomdata_t UINT8 reserved; // Padding union { - clientcmd_pak clientpak; // 147 bytes - client2cmd_pak client2pak; // 206 bytes - client3cmd_pak client3pak; // 264 bytes(?) - client4cmd_pak client4pak; // 324 bytes(?) - servertics_pak serverpak; // 132495 bytes (more around 360, no?) - serverconfig_pak servercfg; // 773 bytes - UINT8 textcmd[MAXTEXTCMD+2]; // 66049 bytes (wut??? 64k??? More like 258 bytes...) - char filetxpak[sizeof (filetx_pak)];// 139 bytes + clientcmd_pak clientpak; + client2cmd_pak client2pak; + client3cmd_pak client3pak; + client4cmd_pak client4pak; + servertics_pak serverpak; + serverconfig_pak servercfg; + UINT8 textcmd[MAXTEXTCMD+2]; + char filetxpak[sizeof (filetx_pak)]; char fileack[sizeof (fileack_pak)]; UINT8 filereceived; - clientconfig_pak clientcfg; // 136 bytes + clientconfig_pak clientcfg; char salt[9]; UINT8 sha256sum[32]; - serverinfo_pak serverinfo; // 1024 bytes - serverrefuse_pak serverrefuse; // 65025 bytes (somehow I feel like those values are garbage...) - askinfo_pak askinfo; // 61 bytes - msaskinfo_pak msaskinfo; // 22 bytes - plrinfo playerinfo[MSCOMPAT_MAXPLAYERS];// 576 bytes(?) - plrconfig playerconfig[MAXPLAYERS]; // (up to) 528 bytes(?) - INT32 filesneedednum; // 4 bytes - filesneededconfig_pak filesneededcfg; // ??? bytes - netinfo_pak netinfo; // Don't believe their lies + serverinfo_pak serverinfo; + serverrefuse_pak serverrefuse; + serverinfoupdate_pak serverinfoupdate; + askinfo_pak askinfo; + msaskinfo_pak msaskinfo; + plrinfo playerinfo[MSCOMPAT_MAXPLAYERS]; + plrconfig playerconfig[MAXPLAYERS]; + INT32 filesneedednum; + filesneededconfig_pak filesneededcfg; + netinfo_pak netinfo; } u; // This is needed to pack diff packet types data together } ATTRPACK; @@ -452,7 +474,9 @@ extern boolean dedicated; // For dedicated server extern UINT16 software_MAXPACKETLENGTH; extern boolean acceptnewnode; extern SINT8 servernode; -extern char connectedservername[MAXSERVERNAME+1]; +extern char connectedservername[MAXSERVERNAME]; +extern char connectedservercontact[MAXSERVERCONTACT]; +extern char connectedserverdescription[MAXSERVERDESCRIPTION]; void Command_Ping_f(void); extern tic_t connectiontimeout; @@ -548,6 +572,8 @@ void CL_UpdateServerList(void); // Is there a game running boolean Playing(void); +void CopyCaretColors (char *p, const char *s, int n); + // Broadcasts special packets to other players // to notify of game exit void D_QuitNetGame(void); diff --git a/src/d_main.cpp b/src/d_main.cpp index 84a2d5b0d..52c714584 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -76,6 +76,7 @@ // SRB2Kart #include "k_grandprix.h" #include "k_boss.h" +#include "k_hud.h" #include "doomstat.h" #include "m_random.h" // P_ClearRandom #include "acs/interface.h" @@ -1213,6 +1214,10 @@ void D_StartTitle(void) // Reset GP memset(&grandprixinfo, 0, sizeof(struct grandprixinfo)); + // Reset Server mods + numcustomservermods = 0; + memset(customservermods, 0, sizeof(customservermods)); + // Reset boss info K_ResetBossInfo(); @@ -1969,8 +1974,6 @@ void D_SRB2Main(void) COM_BufExecute(); // ensure the command buffer gets executed before the map starts (+skin) - strncpy(connectedservername, cv_servername.string, MAXSERVERNAME); - if (M_CheckParm("-gametype") && M_IsNextParm()) { // from Command_Map_f diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 0f9ca3926..95a143eea 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -59,6 +59,7 @@ #include "k_pwrlv.h" #include "y_inter.h" #include "k_color.h" +#include "k_hud.h" #include "k_grandprix.h" #include "k_boss.h" #include "k_follower.h" @@ -102,6 +103,8 @@ static void Got_ScheduleTaskcmd(UINT8 **cp, INT32 playernum); static void Got_ScheduleClearcmd(UINT8 **cp, INT32 playernum); static void Got_Automatecmd(UINT8 **cp, INT32 playernum); static void Got_Cheat(UINT8 **cp, INT32 playernum); +static void Command_ScoreboardAdd(void); +static void Command_ScoreboardClear(void); static void PointLimit_OnChange(void); static void TimeLimit_OnChange(void); @@ -817,6 +820,8 @@ void D_RegisterServerCommands(void) RegisterNetXCmd(XD_AUTOMATE, Got_Automatecmd); RegisterNetXCmd(XD_CHEAT, Got_Cheat); + COM_AddCommand("scoreboard_addline", Command_ScoreboardAdd); + COM_AddCommand("scoreboard_clear", Command_ScoreboardClear); // Remote Administration COM_AddCommand("password", Command_Changepassword_f); @@ -3666,6 +3671,83 @@ static void Got_Clearscores(UINT8 **cp, INT32 playernum) CONS_Printf(M_GetText("Scores have been reset by the server.\n")); } +static void Command_ScoreboardAdd(void) +{ + if (!server) + { + CONS_Printf(M_GetText("Only the server can use this.\n")); + return; + } + + if (COM_Argc() < 2) + { + CONS_Printf(M_GetText("addscoreboard : Add text to the scoreboard\n")); + return; + } + + { + size_t i, j = COM_Argc(); + char message[MAXSERVERDESCRIPTIONLINE+1]; + char *finalstring; + INT32 strlensize = 0; + INT32 serverdesclen = 0; + + // Steal from the motd code so you don't have to put the string in quotes. + strlcpy(message, COM_Argv(1), sizeof message); + for (i = 2; i < j; i++) + { + strlcat(message, " ", sizeof message); + strlcat(message, COM_Argv(i), sizeof message); + } + + strlensize = strlen(message); + message[strlensize+1] = '\0'; + message[MAXSERVERDESCRIPTIONLINE] = '\0'; + + finalstring = Z_Calloc(MAXSERVERDESCRIPTIONLINE*sizeof(char), PU_STATIC, NULL); + + CopyCaretColors(finalstring, message, MAXSERVERDESCRIPTIONLINE); + + strlensize = strlen(finalstring); + serverdesclen = strlen(connectedserverdescription); + + if ((strlensize+1) > MAXSERVERDESCRIPTIONLINE) + { + CONS_Alert(CONS_WARNING, M_GetText("Scoreboard line is too long to add.\n")); + Z_Free(finalstring); + return; + } + + if ((serverdesclen + strlensize) > MAXSERVERDESCRIPTION) + { + CONS_Alert(CONS_WARNING, M_GetText("Scoreboard text is full so no more text can be added.\n")); + Z_Free(finalstring); + return; + } + else + { + strncat(connectedserverdescription, va("%s\n", finalstring), MAXSERVERDESCRIPTIONLINE); + CONS_Printf(M_GetText("Scoreboard text line has been added.\n")); + } + + ServerInfoUpdateSend(); + Z_Free(finalstring); + } +} + +static void Command_ScoreboardClear(void) +{ + if (!server) + { + CONS_Printf(M_GetText("Only the server can use this.\n")); + return; + } + + memset(&connectedserverdescription, 0, sizeof(connectedserverdescription)); + ServerInfoUpdateSend(); + CONS_Printf(M_GetText("Scoreboard text have been reset by the server.\n")); +} + // Team changing functions static void HandleTeamChangeCommand(UINT8 localplayer) { diff --git a/src/deh_tables.c b/src/deh_tables.c index 9b350cb81..e6037e5de 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -30,6 +30,7 @@ #include "k_bot.h" // bot constants (for lua) #include "g_input.h" // Game controls (for lua) #include "k_kart.h" // awardscaledrings_t +#include "k_hud.h" // scoreboardmod_e #include "k_waypoint.h" // waypoint values (for lua) #include "deh_tables.h" @@ -1636,5 +1637,10 @@ struct int_const_s const INT_CONST[] = { // k_waypoint.h values {"DEFAULT_WAYPOINT_RADIUS",DEFAULT_WAYPOINT_RADIUS}, + // scoreboardmod + {"SCOREBOARDMOD_NOTUSED", SCOREBOARDMOD_NOTUSED}, + {"SCOREBOARDMOD_INACTIVE", SCOREBOARDMOD_INACTIVE}, + {"SCOREBOARDMOD_ACTIVE", SCOREBOARDMOD_ACTIVE}, + {NULL,0} }; diff --git a/src/g_demo.c b/src/g_demo.c index 0bdae712a..c5d12d9e8 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -112,7 +112,7 @@ demoghost *ghosts = NULL; // DEMO RECORDING // -#define DEMOVERSION 0x0009 +#define DEMOVERSION 0x000A #define DEMOHEADER "\xF0" "BlanReplay" "\x0F" #define DF_GHOST 0x01 // This demo contains ghost data too! @@ -244,6 +244,9 @@ typedef struct UINT32 raflags; UINT8 gametype; UINT8 numlaps; + char servername[MAXSERVERNAME]; + char servercontact[MAXSERVERCONTACT]; + char serverdescription[MAXSERVERDESCRIPTION]; UINT8 numfiles; demofile_t *files; @@ -653,6 +656,7 @@ static headerstatus_e G_ReadDemoHeader(UINT8 *dp, demoheader_t *header) UINT8 attack; boolean kart = false, oldkart = false; boolean raflag = true; + boolean serverinfo = true; // these may not be present in old demo formats, so initialize them // also initialize them so the header can be free'd without issues @@ -662,6 +666,9 @@ static headerstatus_e G_ReadDemoHeader(UINT8 *dp, demoheader_t *header) header->mapmusrng = 0; header->numlaps = 0; header->raflags = 0; + memset(header->servername, 0, MAXSERVERNAME); + memset(header->servercontact, 0, MAXSERVERCONTACT); + memset(header->serverdescription, 0, MAXSERVERDESCRIPTION); header->empty = false; dp += 12; @@ -676,6 +683,10 @@ static headerstatus_e G_ReadDemoHeader(UINT8 *dp, demoheader_t *header) case DEMOVERSION: // latest always supported break; + case 0x0009: + serverinfo = false; + break; + default: // too old, cannot support. return HEADER_BADVERSION; } @@ -683,6 +694,7 @@ static headerstatus_e G_ReadDemoHeader(UINT8 *dp, demoheader_t *header) else if (!memcmp(startdp, "\xF0" "KartReplay" "\x0F", 12)) { raflag = false; + serverinfo = false; switch (header->demoversion) { case 0x0001: // SRB2Kart 1.0.x (only staff ghosts supported) @@ -736,6 +748,13 @@ static headerstatus_e G_ReadDemoHeader(UINT8 *dp, demoheader_t *header) header->raflags = READUINT32(dp); } + if (serverinfo) + { + READSTRINGN(dp, header->servername, MAXSERVERNAME); + READSTRINGN(dp, header->servercontact, MAXSERVERCONTACT); + READSTRINGN(dp, header->serverdescription, MAXSERVERDESCRIPTION); + } + if (oldkart) { if (header->demoflags & DF_MULTIPLAYER) @@ -2755,6 +2774,9 @@ void G_BeginRecording(void) WRITEUINT8(demobuf.p, demoflags); WRITEUINT32(demobuf.p, raflags); + WRITESTRINGN(demobuf.p, connectedservername, MAXSERVERNAME); + WRITESTRINGN(demobuf.p, connectedservercontact, MAXSERVERCONTACT); + WRITESTRINGN(demobuf.p, connectedserverdescription, MAXSERVERDESCRIPTION); WRITEUINT8(demobuf.p, gametype & 0xFF); WRITEUINT8(demobuf.p, numlaps); @@ -3765,6 +3787,11 @@ void G_DoPlayDemo(char *defdemoname) P_SetRandSeed(header.randseed); G_InitNew(demoflags & DF_ENCORE, gamemap, true, true, false); // Doesn't matter whether you reset or not here, given changes to resetplayer. + // Setup server name, contact and description. + strncpy(connectedservername, header.servername, MAXSERVERNAME); + strncpy(connectedservercontact, header.servercontact, MAXSERVERCONTACT); + strncpy(connectedserverdescription, header.serverdescription, MAXSERVERDESCRIPTION); + for (pnum = 0; pnum < header.numplayers; pnum++) { // oldghost init doesn't work here, players aren't immediately spawned anymore diff --git a/src/hu_stuff.c b/src/hu_stuff.c index fe0e98e80..2d308f4d2 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -2253,13 +2253,13 @@ void HU_Erase(void) static int Ping_gfx_num (int lag) { - if (lag <= 2) + if (lag < 2) return 0; - else if (lag <= 4) + else if (lag < 4) return 1; - else if (lag <= 7) + else if (lag < 7) return 2; - else if (lag <= 10) + else if (lag < 10) return 3; else return 4; @@ -2268,46 +2268,54 @@ Ping_gfx_num (int lag) static int Ping_gfx_color (int lag) { - if (lag <= 2) + if (lag < 2) return SKINCOLOR_JAWZ; - else if (lag <= 4) + else if (lag < 4) return SKINCOLOR_MINT; - else if (lag <= 7) + else if (lag < 7) return SKINCOLOR_GOLD; - else if (lag <= 10) + else if (lag < 10) return SKINCOLOR_RASPBERRY; else return SKINCOLOR_MAGENTA; } static int -PL_gfx_color (int pl) +PL_gfx_color (int pl, boolean mode) { - if (pl <= 2) - return 72; - else if (pl <= 4) - return 54; - else if (pl <= 6) - return 35; + if (mode) + { + if (pl < 2) + return SKINCOLOR_GOLD; + else if (pl < 4) + return SKINCOLOR_ORANGE; + else if (pl < 6) + return SKINCOLOR_CRIMSON; + else + return SKINCOLOR_MAGENTA; + } else - return 181; + { + if (pl < 2) + return 72; + else if (pl < 4) + return 54; + else if (pl < 6) + return 35; + else + return 181; + } } static const UINT8 * -Ping_gfx_colormap (UINT32 ping, boolean gentleman) +Ping_gfx_colormap (UINT32 ping, UINT32 lag) { - const UINT8 *colormap = NULL; - - colormap = R_GetTranslationColormap(TC_RAINBOW, Ping_gfx_color(ping), GTC_CACHE); + const UINT8 *colormap = R_GetTranslationColormap(TC_RAINBOW, Ping_gfx_color(lag), GTC_CACHE); if (servermaxping && ping > servermaxping && hu_tick < 4) { // flash ping red if too high - colormap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_RASPBERRY, GTC_CACHE); - } - else if (gentleman) - { - colormap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_PASTEL, GTC_CACHE); + colormap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_WHITE, GTC_CACHE); } return colormap; @@ -2327,34 +2335,42 @@ Ping_conversion (UINT32 lag) // // HU_drawPing // -void HU_drawPing(INT32 x, INT32 y, UINT32 ping, UINT32 mindelay, UINT32 pl, INT32 flags) +void HU_drawPing(INT32 x, INT32 y, UINT32 ping, UINT32 mindelay, UINT32 pl, INT32 flags, boolean icon) { INT32 measureid = cv_pingmeasurement.value ? 1 : 0; INT32 gfxnum; // gfx to draw UINT32 lag = max(ping, mindelay); + UINT8 *colormap = NULL; gfxnum = Ping_gfx_num(ping); if (pl) { - V_DrawFill( - -pinggfx[gfxnum]->leftoffset + x + 2 - 1, - -pinggfx[gfxnum]->topoffset + y - 1, - pinggfx[gfxnum]->width + 2, - pinggfx[gfxnum]->height + 2, - PL_gfx_color(pl) | flags - ); + if (icon) + { + V_DrawFill( + -pinggfx[gfxnum]->leftoffset + x + 2 - 1, + -pinggfx[gfxnum]->topoffset + y - 1, + pinggfx[gfxnum]->width + 2, + pinggfx[gfxnum]->height + 2, + PL_gfx_color(pl, false) | flags + ); + } + colormap = R_GetTranslationColormap(TC_RAINBOW, PL_gfx_color(pl, true), GTC_CACHE); } if (measureid == 1) - V_DrawScaledPatch(x+11 - pingmeasure[measureid]->width, y+11, flags, pingmeasure[measureid]); + V_DrawMappedPatch(x+11 - pingmeasure[measureid]->width, y+11, flags, pingmeasure[measureid], colormap); - V_DrawScaledPatch(x+2, y, flags, pinggfx[gfxnum]); + if (icon) + { + V_DrawScaledPatch(x+2, y, flags, pinggfx[gfxnum]); + } - x = V_DrawPingNum(x + (measureid == 1 ? 11 - pingmeasure[measureid]->width : 10), y+11, flags, Ping_conversion(lag), Ping_gfx_colormap(ping, ping <= lag)); + x = V_DrawPingNum(x + (measureid == 1 ? 11 - pingmeasure[measureid]->width : 10), y+11, flags, Ping_conversion(lag), Ping_gfx_colormap(ping, lag)); if (measureid == 0) - V_DrawScaledPatch(x+1 - pingmeasure[measureid]->width, y+11, flags, pingmeasure[measureid]); + V_DrawMappedPatch(x+1 - pingmeasure[measureid]->width, y+11, flags, pingmeasure[measureid], colormap); } void @@ -2472,11 +2488,26 @@ static void HU_DrawRankings(void) hilicol = V_YELLOWMAP; } - // draw the current gametype in the lower right - if (modeattacking) - V_DrawString(4, 188, hilicol|V_SNAPTOBOTTOM|V_SNAPTOLEFT, "Record Attack"); + if (!demo.playback) + { + // draw the current map in the lower left + char *maptitle = G_BuildMapTitle(gamemap); + + if (maptitle) + { + V_DrawString(4, 188, hilicol|V_SNAPTOBOTTOM|V_SNAPTOLEFT, maptitle); + Z_Free(maptitle); + } + else + { + V_DrawString(4, 188, hilicol|V_SNAPTOBOTTOM|V_SNAPTOLEFT, "UNKNOWN"); + } + } else - V_DrawString(4, 188, hilicol|V_SNAPTOBOTTOM|V_SNAPTOLEFT, gametype_cons_t[gametype].strvalue); + { + // draw the current gametype in the lower left + V_DrawString(4, 188, hilicol|V_SNAPTOBOTTOM|V_SNAPTOLEFT, (modeattacking) ? "Record Attack" : gametype_cons_t[gametype].strvalue); + } if ((gametyperules & (GTR_TIMELIMIT|GTR_POINTLIMIT)) && !bossinfo.boss) { @@ -2532,7 +2563,7 @@ static void HU_DrawRankings(void) { tab[i].num = -1; tab[i].name = NULL; - tab[i].count = INT32_MAX; + tab[i].string[0] = '\0'; if (!playeringame[i] || players[i].spectator || !players[i].mo) continue; @@ -2563,13 +2594,19 @@ static void HU_DrawRankings(void) if ((gametyperules & GTR_CIRCUIT)) { - if (circuitmap) - tab[scorelines].count = players[i].laps; + if (!players[i].exiting) + sprintf(tab[scorelines].string, "Lap %d", players[i].laps); else - tab[scorelines].count = players[i].realtime; + { + INT32 min = G_TicsToMinutes(players[i].realtime, true); + INT32 sec = G_TicsToSeconds(players[i].realtime); + INT32 cen = G_TicsToCentiseconds(players[i].realtime); + + sprintf(tab[scorelines].string, "%i'%02i\"%02i", min, sec, cen); + } } else - tab[scorelines].count = players[i].roundscore; + sprintf(tab[scorelines].string, "%d", players[i].roundscore); scorelines++; @@ -2579,7 +2616,15 @@ static void HU_DrawRankings(void) #endif } - K_DrawTabRankings(((scorelines > 8) ? 32 : 40), 33, tab, scorelines, whiteplayer, hilicol); + if (cv_newtabranking.value) + { + INT32 xoffset = K_DrawNeoTabRankings(0, 33, tab, scorelines, whiteplayer, hilicol, true); + K_DrawServerDescrption(xoffset+10, 33); + } + else + { + K_DrawTabRankings(((scorelines > 8) ? 32 : 40), 33, tab, scorelines, whiteplayer, hilicol); + } // draw spectators in a ticker across the bottom if (netgame && G_GametypeHasSpectators()) diff --git a/src/hu_stuff.h b/src/hu_stuff.h index a1b99fe32..0ccb9f60c 100644 --- a/src/hu_stuff.h +++ b/src/hu_stuff.h @@ -77,7 +77,7 @@ extern char english_shiftxform[]; struct playersort_t { - UINT32 count; + char string[48]; INT32 num; const char *name; }; @@ -133,7 +133,7 @@ void HU_Drawer(void); char HU_dequeueChatChar(void); void HU_Erase(void); void HU_clearChatChars(void); -void HU_drawPing(INT32 x, INT32 y, UINT32 ping, UINT32 mindelay, UINT32 pl, INT32 flags); +void HU_drawPing(INT32 x, INT32 y, UINT32 ping, UINT32 mindelay, UINT32 pl, INT32 flags, boolean icon); void HU_drawMiniPing (INT32 x, INT32 y, UINT32 ping, UINT32 lag, INT32 flags); INT32 HU_CreateTeamScoresTbl(playersort_t *tab, UINT32 dmtotals[]); diff --git a/src/k_hud.c b/src/k_hud.c index 7ea338ccb..0894b5b6c 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -100,6 +100,8 @@ consvar_t cv_driftgaugeoffset = CVAR_INIT ("kartdriftgaugeoffset", "-10", CV_SAV static CV_PossibleValue_t HudColor_cons_t[MAXSKINCOLORS+1]; consvar_t cv_colorizedhudcolor = CVAR_INIT ("colorizedhudcolor", "Skin Color", CV_SAVE, HudColor_cons_t, NULL); +consvar_t cv_newtabranking = CVAR_INIT ("newtabranking", "On", CV_SAVE, CV_OnOff, NULL); + //{ Patch Definitions static patch_t *kp_nodraw; @@ -254,6 +256,7 @@ void K_RegisterKartHUDStuff(void) CV_RegisterVar(&cv_smoothposition); CV_RegisterVar(&cv_driftgauge); CV_RegisterVar(&cv_driftgaugeoffset); + CV_RegisterVar(&cv_newtabranking); } void K_LoadKartHUDGraphics(void) @@ -2109,18 +2112,248 @@ static void K_drawBossHealthBar(void) } // -// HU_DrawTabRankings -- moved here to take advantage of kart stuff! +// K_DrawNeoTabRankings -- A new way to view ingame info! +// returns starting x of right offset for drawing your own info in there! // +INT32 K_DrawNeoTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, INT32 whiteplayer, INT32 hilicol, boolean split) +{ + INT32 i, rightoffset = split ? 160 - 6: BASEVIDWIDTH - 6; + const UINT8 *colormap = NULL; + UINT16 hightlightcolor = 0; + INT32 dupadjust = (vid.width/vid.dupx), duptweak = (dupadjust - BASEVIDWIDTH)/2; + INT32 basey = y, basex = x, y2, x2; + + scorelines--; + + x += 4; + y += 9*scorelines; + + V_DrawFill(1-duptweak, 26, dupadjust-2, 1, 0); // Draw a horizontal line because it looks nice! + + if (split) + { + V_DrawFill(x + rightoffset + 6, 26, 1, 162, 0); // Draw a vertical line because it looks nice! + } + + for (i = scorelines; i >= 0; i--) + { + INT32 pos = CLAMP(players[tab[i].num].position, 0 , MAXPLAYERS); + char playername[MAXPLAYERNAME+1]; + + if (players[tab[i].num].spectator || !players[tab[i].num].mo) + continue; //ignore them. + + if (netgame) // don't draw ping offline + { + if (players[tab[i].num].bot) + { + V_DrawThinString(x - 18 + 25, y, 0, "CPU"); + } + else if (tab[i].num != serverplayer || !server_lagless) + { + INT32 xoff = cv_pingmeasurement.value == 1 ? 33 : 26; + + HU_drawPing(x - 18 + xoff , y-10, playerpingtable[tab[i].num], playerdelaytable[tab[i].num], playerpacketlosstable[tab[i].num], 0, false); + } + else if (tab[i].num == serverplayer) + { + V_DrawThinString(x - 18 + 25, y, 0, "SRV"); + } + } + + STRBUFCPY(playername, tab[i].name); + + if (players[tab[i].num].mo->color) + { + colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo->color, GTC_CACHE); + if (players[tab[i].num].mo->colorized) + colormap = R_GetTranslationColormap(TC_RAINBOW, players[tab[i].num].mo->color, GTC_CACHE); + else + colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo->color, GTC_CACHE); + + hightlightcolor = skincolors[players[tab[i].num].mo->color].chatcolor; + } + + V_DrawScaledPatch(x-5, y+1, 0, kp_facenum[pos]); + + x2 = netgame ? x + (BASEVIDWIDTH/20) : x; + y2 = y; + + V_DrawThinString(x2 + 20, y2, ((tab[i].num == whiteplayer) ? hightlightcolor : 0)|V_ALLOWLOWERCASE|V_6WIDTHSPACE, playername); + + V_DrawFixedPatch((x2+11)*FRACUNIT, (y+1)*FRACUNIT, FRACUNIT/2, 0, faceprefix[players[tab[i].num].skin][FACE_RANK], colormap); + + /*if (gametype == GT_BATTLE && players[tab[i].num].bumper > 0) -- not enough space for this + { + INT32 bumperx = x+19; + V_DrawMappedPatch(bumperx-2, y-4, 0, kp_tinybumper[0], colormap); + for (j = 1; j < players[tab[i].num].bumper; j++) + { + bumperx += 5; + V_DrawMappedPatch(bumperx, y-4, 0, kp_tinybumper[1], colormap); + } + }*/ + + if (tab[i].num == whiteplayer) + V_DrawFixedPatch((x2+11)*FRACUNIT, (y+1)*FRACUNIT, FRACUNIT/2, 0, kp_facehighlight[(leveltime / 4) % 8], NULL); + + if ((gametyperules & GTR_BUMPERS) && players[tab[i].num].bumper <= 0) + V_DrawScaledPatch(x2-4, y-7, 0, kp_ranknobumpers); + + if (tab[i].string[0] != '\0') + V_DrawRightAlignedThinString(x+rightoffset+2, y, V_6WIDTHSPACE, tab[i].string); + + y -= 9; + } + return x+rightoffset; +} + +servermods_t customservermods[MAXSERVERMODS]; +UINT8 numcustomservermods = 0; + +// Adds a new mod to the scoreboard display. +void K_AddNewScoreboardMod(const char *name, const consvar_t *cvar, SINT8 active) +{ + UINT32 hashcompare = HASH32(name, MAXSERVERMODNAME); + UINT8 i; + + for (i = 0; i < MAXSERVERMODS; i++) + { + if (customservermods[i].hash == hashcompare) + { + CONS_Alert(CONS_WARNING, "Scoreboard mod '%s' has already been added to the scoreboard.\n", name); + return; + } + } + + if (numcustomservermods+1 == MAXSERVERMODS) + { + CONS_Alert(CONS_ERROR, "Maximum Amount of scoreboard mods has been reached.\n"); + return; + } + + strncpy(customservermods[numcustomservermods].modname, name, MAXSERVERMODNAME); + customservermods[numcustomservermods].hash = hashcompare; + customservermods[numcustomservermods].cvar = cvar; + customservermods[numcustomservermods].active = CLAMP(active, SCOREBOARDMOD_NOTUSED, SCOREBOARDMOD_ACTIVE); + customservermods[numcustomservermods].valid = true; + numcustomservermods++; +} + +// Change the status of static scoreboard displays. +void K_SetScoreboardModStatus(const char *name, SINT8 active) +{ + UINT32 hashcompare = HASH32(name, MAXSERVERMODNAME); + UINT8 i; + + for (i = 0; i < MAXSERVERMODS; i++) + { + if (customservermods[i].hash == hashcompare) + { + customservermods[i].active = CLAMP(active, SCOREBOARDMOD_NOTUSED, SCOREBOARDMOD_ACTIVE); + return; + } + } + + CONS_Alert(CONS_WARNING, "Server mod '%s' does not exist so status cannot be changed.\n", name); +} + +#define BASEMODS 11 +void K_DrawServerMods(INT32 x, INT32 y) +{ + UINT8 i, j; + INT32 xoff = 0, yoff = 10; + UINT8 numdrawn = 0; + + servermods_t basemods[BASEMODS] = + { + {"Rings", 0, NULL, K_RingsActive() > 0, true}, + {"4-Tier Drifts", 0, NULL, K_PurpleDriftActive() > 0, true}, + {"Slipdash", 0, NULL, K_SlipdashActive() > 0, true}, + {"Stacking", 0, NULL, K_StackingActive() > 0, true}, + {"Chaining", 0, NULL, K_ChainingActive() > 0, true}, + {"Chain Offroad", 0, &cv_kartchainingoffroad, -1, true}, + {"Slope Boost", 0, NULL, K_PurpleDriftActive() > 0, true}, + {"Drafting", 0, NULL, K_PurpleDriftActive() > 0, true}, + {"Bump Spark", 0, &cv_kartbumpspark, -1, true}, + {"Bump Spring", 0, &cv_kartbumpspring, -1, true}, + {"Alt. Invin.", 0, NULL, K_GetKartInvinType() == KARTINVIN_ALTERN, true} + }; + + for (j = 0; j < 2; j++) + { + UINT8 modcount = j == 0 ? BASEMODS : numcustomservermods; + servermods_t *modslist = j == 0 ? basemods : customservermods; + + // Draw the the modlist. + for (i = 0; i < modcount; i++) + { + boolean drawdis = false; + + if (modslist[i].valid) + { + if (modslist[i].cvar && modslist[i].cvar->value) + { + drawdis = true; + } + else if (modslist[i].active == SCOREBOARDMOD_ACTIVE) + { + drawdis = true; + } + + if (drawdis && modslist[i].modname[0] != '\0') + { + V_DrawSmallString(x+xoff, y+yoff, V_6WIDTHSPACE|V_ALLOWLOWERCASE, modslist[i].modname); + numdrawn++; + + if ((numdrawn % 2) == 0) + { + xoff -= 50; + yoff += 5; + } + else if ((numdrawn % 1) == 0) + { + xoff += 50; + } + } + } + } + } + + if (numdrawn > 0) + V_DrawThinString(x, y, V_6WIDTHSPACE|V_ALLOWLOWERCASE|V_GRAYMAP, "Gameplay / Balance Changes:"); + +} +#undef BASEMODS + +void K_DrawServerDescrption(INT32 x, INT32 y) +{ + UINT8 i, newlinecount = 0; + if (connectedservername[0] != '\0') + V_DrawThinString(x, y, V_6WIDTHSPACE|V_ALLOWLOWERCASE, connectedservername); + + V_DrawSmallString(x, y+10, V_6WIDTHSPACE|V_ALLOWLOWERCASE|V_GRAYMAP, va("Contact: %s", (connectedservercontact[0] != '\0') ? connectedservercontact : "")); + + if (connectedserverdescription[0] != '\0') + { + V_DrawSmallString(x, y+20, V_6WIDTHSPACE|V_ALLOWLOWERCASE, connectedserverdescription); + + for (i = 0; connectedserverdescription[i]; i++) + newlinecount += (connectedserverdescription[i] == '\n'); + } + + K_DrawServerMods(x, y + 25 + newlinecount*6); +} + +// The old school one.... void K_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, INT32 whiteplayer, INT32 hilicol) { INT32 i, rightoffset = 240; - const UINT8 *colormap; + UINT8 *colormap = NULL; + UINT16 hightlightcolor = 0; INT32 dupadjust = (vid.width/vid.dupx), duptweak = (dupadjust - BASEVIDWIDTH)/2; int basey = y, basex = x, y2; - //this function is designed for 9 or less score lines only - //I_Assert(scorelines <= 9); -- not today bitch, kart fixed it up - V_DrawFill(1-duptweak, 26, dupadjust-2, 1, 0); // Draw a horizontal line because it looks nice! scorelines--; @@ -2139,7 +2372,7 @@ void K_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, IN for (i = scorelines; i >= 0; i--) { - char strtime[MAXPLAYERNAME+1]; + char playername[MAXPLAYERNAME+1]; if (players[tab[i].num].spectator || !players[tab[i].num].mo) continue; //ignore them. @@ -2152,19 +2385,18 @@ void K_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, IN } else if (tab[i].num != serverplayer || !server_lagless) { - HU_drawPing(x + ((i < 8) ? -17 : rightoffset + 11), y-4, playerpingtable[tab[i].num], playerdelaytable[tab[i].num], playerpacketlosstable[tab[i].num], 0); + HU_drawPing(x + ((i < 8) ? -17 : rightoffset + 11), y-4, playerpingtable[tab[i].num], playerdelaytable[tab[i].num], playerpacketlosstable[tab[i].num], 0, true); + } + else if (tab[i].num == serverplayer) + { + V_DrawString(x + ((i < 8) ? -25 : rightoffset + 3), y-2, V_SNAPTOLEFT, "SRV"); } } - STRBUFCPY(strtime, tab[i].name); + STRBUFCPY(playername, tab[i].name); y2 = y; - if (scorelines >= 8) - V_DrawThinString(x + 20, y2, ((tab[i].num == whiteplayer) ? hilicol : 0)|V_ALLOWLOWERCASE|V_6WIDTHSPACE, strtime); - else - V_DrawString(x + 20, y2, ((tab[i].num == whiteplayer) ? hilicol : 0)|V_ALLOWLOWERCASE, strtime); - if (players[tab[i].num].mo->color) { colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo->color, GTC_CACHE); @@ -2173,19 +2405,27 @@ void K_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, IN else colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo->color, GTC_CACHE); - V_DrawMappedPatch(x, y-4, 0, faceprefix[players[tab[i].num].skin][FACE_RANK], colormap); - /*if (gametype == GT_BATTLE && players[tab[i].num].bumper > 0) -- not enough space for this - { - INT32 bumperx = x+19; - V_DrawMappedPatch(bumperx-2, y-4, 0, kp_tinybumper[0], colormap); - for (j = 1; j < players[tab[i].num].bumper; j++) - { - bumperx += 5; - V_DrawMappedPatch(bumperx, y-4, 0, kp_tinybumper[1], colormap); - } - }*/ + hightlightcolor = skincolors[players[tab[i].num].mo->color].chatcolor; } + if (scorelines >= 8) + V_DrawThinString(x + 20, y2, ((tab[i].num == whiteplayer) ? hightlightcolor : 0)|V_ALLOWLOWERCASE|V_6WIDTHSPACE, playername); + else + V_DrawString(x + 20, y2, ((tab[i].num == whiteplayer) ? hightlightcolor : 0)|V_ALLOWLOWERCASE, playername); + + V_DrawMappedPatch(x, y-4, 0, faceprefix[players[tab[i].num].skin][FACE_RANK], colormap); + + /*if (gametype == GT_BATTLE && players[tab[i].num].bumper > 0) -- not enough space for this + { + INT32 bumperx = x+19; + V_DrawMappedPatch(bumperx-2, y-4, 0, kp_tinybumper[0], colormap); + for (j = 1; j < players[tab[i].num].bumper; j++) + { + bumperx += 5; + V_DrawMappedPatch(bumperx, y-4, 0, kp_tinybumper[1], colormap); + } + }*/ + if (tab[i].num == whiteplayer) V_DrawScaledPatch(x, y-4, 0, kp_facehighlight[(leveltime / 4) % 8]); @@ -2200,31 +2440,8 @@ void K_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, IN V_DrawScaledPatch(x-5, y+6, 0, kp_facenum[pos]); } - if (gametype == GT_RACE) - { -#define timestring(time) va("%i'%02i\"%02i", G_TicsToMinutes(time, true), G_TicsToSeconds(time), G_TicsToCentiseconds(time)) - if (scorelines >= 8) - { - if (players[tab[i].num].exiting) - V_DrawRightAlignedThinString(x+rightoffset, y-1, hilicol|V_6WIDTHSPACE, timestring(players[tab[i].num].realtime)); - else if (players[tab[i].num].pflags & PF_NOCONTEST) - V_DrawRightAlignedThinString(x+rightoffset, y-1, V_6WIDTHSPACE, "NO CONTEST."); - else if (circuitmap) - V_DrawRightAlignedThinString(x+rightoffset, y-1, V_6WIDTHSPACE, va("Lap %d", tab[i].count)); - } - else - { - if (players[tab[i].num].exiting) - V_DrawRightAlignedString(x+rightoffset, y, hilicol, timestring(players[tab[i].num].realtime)); - else if (players[tab[i].num].pflags & PF_NOCONTEST) - V_DrawRightAlignedThinString(x+rightoffset, y-1, 0, "NO CONTEST."); - else if (circuitmap) - V_DrawRightAlignedString(x+rightoffset, y, 0, va("Lap %d", tab[i].count)); - } -#undef timestring - } - else - V_DrawRightAlignedString(x+rightoffset, y, 0, va("%u", tab[i].count)); + if (tab[i].string[0] != '\0') + V_DrawRightAlignedThinString(x+rightoffset, y-1, V_6WIDTHSPACE, tab[i].string); y -= 18; if (i == 8) diff --git a/src/k_hud.h b/src/k_hud.h index 321182e35..5e4d4e6ab 100644 --- a/src/k_hud.h +++ b/src/k_hud.h @@ -62,6 +62,8 @@ extern consvar_t cv_colorizeditembox; extern consvar_t cv_darkitembox; extern consvar_t cv_colorizedhudcolor; +extern consvar_t cv_newtabranking; + struct trackingResult_t { fixed_t x, y; @@ -97,7 +99,35 @@ void K_LoadKartHUDGraphics(void); void K_drawKartHUD(void); void K_drawKartFreePlay(void); void K_drawKartTimestamp(tic_t drawtime, INT32 TX, INT32 TY, INT16 emblemmap, UINT8 mode); +INT32 K_DrawNeoTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, INT32 whiteplayer, INT32 hilicol, boolean split); void K_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, INT32 whiteplayer, INT32 hilicol); + +#define MAXSERVERMODS 255 +#define MAXSERVERMODNAME 13 + +struct servermods_t +{ + char modname[MAXSERVERMODNAME]; + UINT32 hash; + const consvar_t *cvar; + SINT8 active; // -1 is N/A (example: if using cvar activation), 0 is off, 1 is on. + boolean valid; +}; + +typedef enum +{ + SCOREBOARDMOD_NOTUSED = -1, + SCOREBOARDMOD_INACTIVE, + SCOREBOARDMOD_ACTIVE, +} scoreboardmod_e; + +extern servermods_t customservermods[MAXSERVERMODS]; +extern UINT8 numcustomservermods; +void K_AddNewScoreboardMod(const char *name, const consvar_t *cvar, SINT8 active); +void K_SetScoreboardModStatus(const char *name, SINT8 active); + +void K_DrawServerDescrption(INT32 x, INT32 y); + void K_DrawDriftGauge(void); void K_ResetAfterImageValues(void); #ifdef __cplusplus diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 9aeff1ce8..8d9b23125 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -4349,6 +4349,29 @@ static int lib_kAwardScaledPlayerRings(lua_State *L) return 0; } +static int lib_kAddNewScoreboardMod(lua_State *L) +{ + const char *modname = luaL_checkstring(L, 1); + const char *cvarname = lua_isnil(L, 2) ? NULL : luaL_checkstring(L, 2); + const consvar_t *cvar = lua_isnil(L, 2) ? NULL : CV_FindVar(cvarname); + SINT8 active = SCOREBOARDMOD_NOTUSED; + + if (!cvarname || !cvar) + active = SCOREBOARDMOD_ACTIVE; + + K_AddNewScoreboardMod(modname, cvar, active); + return 0; +} + +static int lib_kSetScoreboardModStatus(lua_State *L) +{ + const char *modname = luaL_checkstring(L, 1); + SINT8 active = CLAMP(luaL_checkinteger(L, 2), SCOREBOARDMOD_NOTUSED, SCOREBOARDMOD_ACTIVE); + + K_SetScoreboardModStatus(modname, active); + return 0; +} + static int lib_kPlayerUsesBotMovement(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); @@ -5257,6 +5280,10 @@ static luaL_Reg lib[] = { {"K_AwardPlayerRings", lib_kAwardPlayerRings}, {"K_AwardScaledPlayerRings", lib_kAwardScaledPlayerRings}, + // k_hud + {"K_AddNewScoreboardMod", lib_kAddNewScoreboardMod}, + {"K_SetScoreboardModStatus", lib_kSetScoreboardModStatus}, + // k_waypoint {"K_NextRespawnWaypointIndex", lib_kNextRespawnWaypointIndex}, {"K_GetFinishLineWaypoint", lib_kGetFinishLineWaypoint}, diff --git a/src/m_menu.c b/src/m_menu.c index 31cdb5540..998665711 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -6429,8 +6429,6 @@ INT32 MR_StartServer(INT32 choice) multiplayer = true; - strncpy(connectedservername, cv_servername.string, MAXSERVERNAME); - // Still need to reset devmode cht_debug = 0; diff --git a/src/mserv.c b/src/mserv.c index 50bf100c1..ae1212891 100644 --- a/src/mserv.c +++ b/src/mserv.c @@ -22,6 +22,8 @@ #include "mserv.h" #include "m_menu.h" #include "z_zone.h" +#include "byteptr.h" +#include "i_net.h" #ifdef HAVE_DISCORDRPC #include "discord.h" @@ -503,6 +505,15 @@ Update_parameters (void) UpdateServer(); } #endif/*MASTERSERVER*/ + + // Lets update Clients on this info. + if (Playing() && server) + { + CopyCaretColors(connectedservername, cv_servername.string, MAXSERVERNAME); + CopyCaretColors(connectedservercontact, cv_server_contact.string, MAXSERVERCONTACT); + + ServerInfoUpdateSend(); + } } static void MasterServer_OnChange(void) diff --git a/src/screen.c b/src/screen.c index 5f492b6e3..1973b6f58 100644 --- a/src/screen.c +++ b/src/screen.c @@ -603,7 +603,7 @@ void SCR_DisplayLocalPing(void) if (( cv_showping.value == 1 || (cv_showping.value == 2 && ping > servermaxping) )) // only show 2 (warning) if our ping is at a bad level { INT32 dispy = cv_ticrate.value ? 160 : 181; - HU_drawPing(307, dispy, ping, mindelay, pl, V_SNAPTORIGHT | V_SNAPTOBOTTOM | V_HUDTRANS); + HU_drawPing(307, dispy, ping, mindelay, pl, V_SNAPTORIGHT | V_SNAPTOBOTTOM, true); } } diff --git a/src/typedef.h b/src/typedef.h index 72323f202..b34af2b44 100644 --- a/src/typedef.h +++ b/src/typedef.h @@ -62,6 +62,7 @@ TYPEDEF (fileack_pak); TYPEDEF (clientconfig_pak); TYPEDEF (serverinfo_pak); TYPEDEF (serverrefuse_pak); +TYPEDEF (serverinfoupdate_pak); TYPEDEF (askinfo_pak); TYPEDEF (msaskinfo_pak); TYPEDEF (plrinfo); @@ -176,6 +177,7 @@ TYPEDEF (followercategory_t); // k_hud.h TYPEDEF (trackingResult_t); +TYPEDEF (servermods_t); // k_menu.h TYPEDEF (menucolor_t);