From ac7c249fd20d12fb3b8435f2b79abb06b7c04d67 Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Tue, 31 Jul 2018 11:10:02 +0200 Subject: [PATCH 01/71] SRB2chat test rework --- src/console.c | 24 +- src/d_main.c | 23 +- src/d_netcmd.c | 10 + src/dehacked.c | 28 +- src/doomdef.h | 1 + src/g_game.c | 37 +- src/g_game.h | 1 + src/hardware/hw_draw.c | 104 ++++ src/hardware/hw_main.h | 2 + src/hu_stuff.c | 1340 ++++++++++++++++++++++++++++++++++++---- src/hu_stuff.h | 14 +- src/lua_baselib.c | 55 +- src/m_menu.c | 40 +- src/v_video.c | 150 +++++ src/v_video.h | 3 + 15 files changed, 1687 insertions(+), 145 deletions(-) diff --git a/src/console.c b/src/console.c index 3c06561ce..357f1ef84 100644 --- a/src/console.c +++ b/src/console.c @@ -844,7 +844,7 @@ boolean CON_Responder(event_t *ev) // ...why shouldn't it eat the key? if it doesn't, it just means you // can control Sonic from the console, which is silly - return true; //return false; + return true;//return false; } // command completion forward (tab) and backward (shift-tab) @@ -1037,16 +1037,26 @@ boolean CON_Responder(event_t *ev) } else if (key == KEY_KPADSLASH) key = '/'; - - if (shiftdown) + + // capslock + if (key == KEY_CAPSLOCK) // it's a toggle. + { + if (capslock) + capslock = false; + else + capslock = true; + return true; + } + + if (capslock ^ shiftdown) // gets capslock to work because capslock is cool key = shiftxform[key]; // enter a char into the command prompt if (key < 32 || key > 127) - return true; // even if key can't be printed, eat it anyway + return true; // add key to cmd line here - if (key >= 'A' && key <= 'Z' && !shiftdown) //this is only really necessary for dedicated servers + if (key >= 'A' && key <= 'Z' && !(shiftdown ^ capslock)) //this is only really necessary for dedicated servers key = key + 'a' - 'A'; if (input_sel != input_cur) @@ -1433,8 +1443,8 @@ static void CON_DrawHudlines(void) if (con_hudlines <= 0) return; - if (chat_on) - y = charheight; // leave place for chat input in the first row of text + if (chat_on && cv_consolechat.value) + y = charheight; // leave place for chat input in the first row of text (only do it if consolechat is on.) else y = 0; diff --git a/src/d_main.c b/src/d_main.c index fbec5f7d8..159a2e3e0 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -181,6 +181,7 @@ void D_PostEvent_end(void) {}; UINT8 shiftdown = 0; // 0x1 left, 0x2 right UINT8 ctrldown = 0; // 0x1 left, 0x2 right UINT8 altdown = 0; // 0x1 left, 0x2 right +boolean capslock = 0; // you'd never guess what this does. // // D_ModifierKeyResponder // Sets global shift/ctrl/alt variables, never actually eats events @@ -730,6 +731,11 @@ void D_StartTitle(void) CON_ToggleOff(); // Reset the palette +#ifdef HWRENDER + if (rendermode == render_opengl) + HWR_SetPaletteColor(0); + else +#endif if (rendermode != render_none) V_SetPaletteLump("PLAYPAL"); } @@ -1063,7 +1069,7 @@ void D_SRB2Main(void) // add any files specified on the command line with -file wadfile // to the wad list - if (!(M_CheckParm("-connect") && !M_CheckParm("-server"))) + if (!(M_CheckParm("-connect"))) { if (M_CheckParm("-file")) { @@ -1219,15 +1225,7 @@ void D_SRB2Main(void) R_Init(); // setting up sound - if (dedicated) - { - nosound = true; - nomidimusic = nodigimusic = true; - } - else - { - CONS_Printf("S_Init(): Setting up sound.\n"); - } + CONS_Printf("S_Init(): Setting up sound.\n"); if (M_CheckParm("-nosound")) nosound = true; if (M_CheckParm("-nomusic")) // combines -nomidimusic and -nodigmusic @@ -1326,7 +1324,7 @@ void D_SRB2Main(void) ultimatemode = true; } - if (autostart || netgame) + if (autostart || netgame || M_CheckParm("+connect") || M_CheckParm("-connect")) { gameaction = ga_nothing; @@ -1364,7 +1362,8 @@ void D_SRB2Main(void) } } - if (server && !M_CheckParm("+map")) + if (server && !M_CheckParm("+map") && !M_CheckParm("+connect") + && !M_CheckParm("-connect")) { // Prevent warping to nonexistent levels if (W_CheckNumForName(G_BuildMapName(pstartmap)) == LUMPERROR) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 673d64fd8..dbd26a738 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -582,6 +582,7 @@ void D_RegisterServerCommands(void) */ void D_RegisterClientCommands(void) { + const char *username; INT32 i; for (i = 0; i < MAXSKINCOLORS; i++) @@ -638,6 +639,8 @@ void D_RegisterClientCommands(void) #endif // register these so it is saved to config + if ((username = I_GetUserName())) + cv_playername.defaultvalue = username; CV_RegisterVar(&cv_playername); CV_RegisterVar(&cv_playercolor); CV_RegisterVar(&cv_skin); // r_things.c (skin NAME) @@ -676,6 +679,13 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_usegamma); // m_menu.c + CV_RegisterVar(&cv_compactscoreboard); + CV_RegisterVar(&cv_chatheight); + CV_RegisterVar(&cv_chatwidth); + CV_RegisterVar(&cv_chattime); + CV_RegisterVar(&cv_chatspamprotection); + CV_RegisterVar(&cv_consolechat); + CV_RegisterVar(&cv_chatnotifications); CV_RegisterVar(&cv_crosshair); CV_RegisterVar(&cv_crosshair2); CV_RegisterVar(&cv_alwaysfreelook); diff --git a/src/dehacked.c b/src/dehacked.c index b7e874b16..ac2aa9a85 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8286,8 +8286,34 @@ static inline int lib_getenum(lua_State *L) } else if (fastcmp(word, "token")) { lua_pushinteger(L, token); return 1; + } else if (fastcmp(word,"consoleplayer")) { + if (!playeringame[consoleplayer]) + return 0; + LUA_PushUserdata(L, &players[consoleplayer], META_PLAYER); + return 1; + } else if (fastcmp(word,"displayplayer")) { + if (!playeringame[displayplayer]) + return 0; + LUA_PushUserdata(L, &players[displayplayer], META_PLAYER); + return 1; + } else if (fastcmp(word,"secondarydisplayplayer")) { + if (!playeringame[displayplayer]) + return 0; + LUA_PushUserdata(L, &players[secondarydisplayplayer], META_PLAYER); + return 1; + } else if (fastcmp(word, "timelimitintics")) { + lua_pushinteger(L, timelimitintics); + return 1; + } else if (fastcmp(word,"hidetime")) { + lua_pushinteger(L, hidetime); + return 1; + } else if (fastcmp(word, "pointlimit")) { + lua_pushinteger(L, cv_pointlimit.value); + return 1; + } else if (fastcmp(word,"allowjoin")) { + lua_pushboolean(L, cv_allownewplayer.value); + return 1; } - return 0; } diff --git a/src/doomdef.h b/src/doomdef.h index 7f641558f..50e7c717d 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -396,6 +396,7 @@ extern INT32 cv_debug; // Modifier key variables, accessible anywhere extern UINT8 shiftdown, ctrldown, altdown; +extern boolean capslock; // if we ever make our alloc stuff... #define ZZ_Alloc(x) Z_Malloc(x, PU_STATIC, NULL) diff --git a/src/g_game.c b/src/g_game.c index bcae69fda..d70a8a30e 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -347,6 +347,32 @@ static CV_PossibleValue_t joyaxis_cons_t[] = {{0, "None"}, #endif #endif +// don't mind me putting these here, I was lazy to figure out where else I could put those without blowing up the compiler. + +// it automatically becomes compact with 20+ players, but if you like it, I guess you can turn that on! +consvar_t cv_compactscoreboard= {"compactscoreboard", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; + +// chat timer thingy +static CV_PossibleValue_t chattime_cons_t[] = {{5, "MIN"}, {999, "MAX"}, {0, NULL}}; +consvar_t cv_chattime = {"chattime", "8", CV_SAVE, chattime_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; + +// chatwidth +static CV_PossibleValue_t chatwidth_cons_t[] = {{64, "MIN"}, {150, "MAX"}, {0, NULL}}; +consvar_t cv_chatwidth = {"chatwidth", "150", CV_SAVE, chatwidth_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; + +// chatheight +static CV_PossibleValue_t chatheight_cons_t[] = {{6, "MIN"}, {22, "MAX"}, {0, NULL}}; +consvar_t cv_chatheight= {"chatheight", "8", CV_SAVE, chatheight_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; + +// chat notifications (do you want to hear beeps? I'd understand if you didn't.) +consvar_t cv_chatnotifications= {"chatnotifications", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; + +// chat spam protection (why would you want to disable that???) +consvar_t cv_chatspamprotection= {"chatspamprotection", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; + +// old shit console chat. (mostly exists for stuff like terminal, not because I cared if anyone liked the old chat.) +consvar_t cv_consolechat= {"consolechat", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; + consvar_t cv_crosshair = {"crosshair", "Cross", CV_SAVE, crosshair_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_crosshair2 = {"crosshair2", "Cross", CV_SAVE, crosshair_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_invertmouse = {"invertmouse", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -1240,6 +1266,10 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics) if ((cmd->forwardmove || cmd->sidemove || cmd->buttons) && displayplayer != consoleplayer) displayplayer = consoleplayer; + + if (playeringame[consoleplayer]) // do not run on title screen. + LUAh_PlayerCmd(player, cmd); // run this hook after we've done everything. Why? Because that way we can check what buttons we're pressing and what we're doing in that frame rather than using last frame's info! + } // like the g_buildticcmd 1 but using mouse2, gamcontrolbis, ... @@ -1535,6 +1565,10 @@ void G_BuildTiccmd2(ticcmd_t *cmd, INT32 realtics) localangle2 += (cmd->angleturn<<16); cmd->angleturn = (INT16)(localangle2 >> 16); } + + if (playeringame[consoleplayer]) // do not run on title screen. + LUAh_PlayerCmd(player, cmd); + } // User has designated that they want @@ -3588,8 +3622,7 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean unlocktriggers = 0; // clear itemfinder, just in case - if (!dedicated) // except in dedicated servers, where it is not registered and can actually I_Error debug builds - CV_StealthSetValue(&cv_itemfinder, 0); + CV_StealthSetValue(&cv_itemfinder, 0); } // internal game map diff --git a/src/g_game.h b/src/g_game.h index ada82404c..cd0a71f22 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -54,6 +54,7 @@ extern tic_t timeinmap; // Ticker for time spent in level (used for levelcard di extern INT16 rw_maximums[NUM_WEAPONS]; // used in game menu +extern consvar_t cv_chatwidth, cv_chatnotifications, cv_chatheight, cv_chattime, cv_consolechat, cv_chatspamprotection, cv_compactscoreboard; extern consvar_t cv_crosshair, cv_crosshair2; extern consvar_t cv_invertmouse, cv_alwaysfreelook, cv_mousemove; extern consvar_t cv_sideaxis,cv_turnaxis,cv_moveaxis,cv_lookaxis,cv_fireaxis,cv_firenaxis; diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index 84081dd25..e09b327e7 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -791,6 +791,110 @@ void HWR_drawAMline(const fline_t *fl, INT32 color) HWD.pfnDraw2DLine(&v1, &v2, color_rgba); } +// -------------------+ +// HWR_DrawConsoleFill : draw flat coloured transparent rectangle because that's cool, and hw sucks less than sw for that. +// -------------------+ +void HWR_DrawConsoleFill(INT32 x, INT32 y, INT32 w, INT32 h, UINT32 color, INT32 options) +{ + FOutVector v[4]; + FSurfaceInfo Surf; + float fx, fy, fw, fh; + + if (w < 0 || h < 0) + return; // consistency w/ software + +// 3--2 +// | /| +// |/ | +// 0--1 + + fx = (float)x; + fy = (float)y; + fw = (float)w; + fh = (float)h; + + if (!(options & V_NOSCALESTART)) + { + float dupx = (float)vid.dupx, dupy = (float)vid.dupy; + + if (x == 0 && y == 0 && w == BASEVIDWIDTH && h == BASEVIDHEIGHT) + { + RGBA_t rgbaColour = V_GetColor(color); + FRGBAFloat clearColour; + clearColour.red = (float)rgbaColour.s.red / 255; + clearColour.green = (float)rgbaColour.s.green / 255; + clearColour.blue = (float)rgbaColour.s.blue / 255; + clearColour.alpha = 1; + HWD.pfnClearBuffer(true, false, &clearColour); + return; + } + + fx *= dupx; + fy *= dupy; + fw *= dupx; + fh *= dupy; + + if (vid.width != BASEVIDWIDTH * vid.dupx) + { + if (options & V_SNAPTORIGHT) + fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)); + else if (!(options & V_SNAPTOLEFT)) + fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 2; + } + if (vid.height != BASEVIDHEIGHT * dupy) + { + // same thing here + if (options & V_SNAPTOBOTTOM) + fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)); + else if (!(options & V_SNAPTOTOP)) + fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 2; + } + } + + if (fx >= vid.width || fy >= vid.height) + return; + if (fx < 0) + { + fw += fx; + fx = 0; + } + if (fy < 0) + { + fh += fy; + fy = 0; + } + + if (fw <= 0 || fh <= 0) + return; + if (fx + fw > vid.width) + fw = (float)vid.width - fx; + if (fy + fh > vid.height) + fh = (float)vid.height - fy; + + fx = -1 + fx / (vid.width / 2); + fy = 1 - fy / (vid.height / 2); + fw = fw / (vid.width / 2); + fh = fh / (vid.height / 2); + + v[0].x = v[3].x = fx; + v[2].x = v[1].x = fx + fw; + v[0].y = v[1].y = fy; + v[2].y = v[3].y = fy - fh; + + //Hurdler: do we still use this argb color? if not, we should remove it + v[0].argb = v[1].argb = v[2].argb = v[3].argb = 0xff00ff00; //; + v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; + + v[0].sow = v[3].sow = 0.0f; + v[2].sow = v[1].sow = 1.0f; + v[0].tow = v[1].tow = 0.0f; + v[2].tow = v[3].tow = 1.0f; + + Surf.FlatColor.rgba = UINT2RGBA(color); + Surf.FlatColor.s.alpha = 0x80; + + HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest); +} // -----------------+ // HWR_DrawFill : draw flat coloured rectangle, with no texture diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index b0a14d3b5..ba809663a 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -52,6 +52,7 @@ void HWR_CreatePlanePolygons(INT32 bspnum); void HWR_CreateStaticLightmaps(INT32 bspnum); void HWR_PrepLevelCache(size_t pnumtextures); void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color); +void HWR_DrawConsoleFill(INT32 x, INT32 y, INT32 w, INT32 h, UINT32 color, INT32 options); // Lat: separate flags from color since color needs to be an uint to work right. void HWR_DrawPic(INT32 x,INT32 y,lumpnum_t lumpnum); void HWR_AddCommands(void); @@ -70,6 +71,7 @@ void HWR_DrawScreenFinalTexture(int width, int height); // This stuff is put here so MD2's can use them UINT32 HWR_Lighting(INT32 light, UINT32 color, UINT32 fadecolor, boolean fogblockpoly, boolean plane); +UINT32 HWR_NoColormapLighting(INT32 light, UINT32 color, UINT32 fadecolor, boolean fogblockpoly, boolean plane); // do it like cv_grfog off for non colormap stuff FUNCMATH UINT8 LightLevelToLum(INT32 l); extern CV_PossibleValue_t granisotropicmode_cons_t[]; diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 646bdcbad..435325767 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -73,6 +73,7 @@ patch_t *cred_font[CRED_FONTSIZE]; static player_t *plr; boolean chat_on; // entering a chat message? static char w_chat[HU_MAXMSGLEN]; +static INT32 c_input = 0; // let's try to make the chat input less shitty. static boolean headsupactive = false; boolean hu_showscores; // draw rankings static char hu_tick; @@ -319,6 +320,74 @@ void HU_Start(void) //====================================================================== #ifndef NONET + +// EVERY CHANGE IN THIS SCRIPT IS LOL XD! BY VINCYTM + +static UINT32 chat_nummsg_log = 0; +static UINT32 chat_nummsg_min = 0; +static UINT32 chat_scroll = 0; +static tic_t chat_scrolltime = 0; + +static INT32 chat_maxscroll = 0; // how far can we scroll? + +//static chatmsg_t chat_mini[CHAT_BUFSIZE]; // Display the last few messages sent. +//static chatmsg_t chat_log[CHAT_BUFSIZE]; // Keep every message sent to us in memory so we can scroll n shit, it's cool. + +static char chat_log[CHAT_BUFSIZE][255]; // hold the last 48 or so messages in that log. +static char chat_mini[8][255]; // display up to 8 messages that will fade away / get overwritten +static tic_t chat_timers[8]; + +static boolean chat_scrollmedown = false; // force instant scroll down on the chat log. Happens when you open it / send a message. + +// remove text from minichat table + +static INT16 addy = 0; // use this to make the messages scroll smoothly when one fades away + +static void HU_removeChatText_Mini(void) +{ + // MPC: Don't create new arrays, just iterate through an existing one + int i; + for(i=0;i= CHAT_BUFSIZE) + HU_removeChatText_Log(); + + strcpy(chat_log[chat_nummsg_log], text); + chat_nummsg_log++; + + if (chat_nummsg_min >= 8) + HU_removeChatText_Mini(); + + strcpy(chat_mini[chat_nummsg_min], text); + chat_timers[chat_nummsg_min] = TICRATE*cv_chattime.value; + chat_nummsg_min++; +} + /** Runs a say command, sending an ::XD_SAY message. * A say command consists of a signed 8-bit integer for the target, an * unsigned 8-bit flag variable, and then the message itself. @@ -337,6 +406,8 @@ void HU_Start(void) * \sa Command_Say_f, Command_Sayteam_f, Command_Sayto_f, Got_Saycmd * \author Graue */ + + static void DoSayCommand(SINT8 target, size_t usedargs, UINT8 flags) { XBOXSTATIC char buf[254]; @@ -347,9 +418,9 @@ static void DoSayCommand(SINT8 target, size_t usedargs, UINT8 flags) numwords = COM_Argc() - usedargs; I_Assert(numwords > 0); - if (cv_mute.value && !(server || adminplayer == consoleplayer)) + if (cv_mute.value && !(server || adminplayer == consoleplayer)) // TODO: Per Player mute. { - CONS_Alert(CONS_NOTICE, M_GetText("The chat is muted. You can't say anything at the moment.\n")); + HU_AddChatText(va("%s>ERROR: The chat is muted. You can't say anything.", "\x85")); return; } @@ -372,6 +443,52 @@ static void DoSayCommand(SINT8 target, size_t usedargs, UINT8 flags) strlcat(msg, " ", msgspace); strlcat(msg, COM_Argv(ix + usedargs), msgspace); } + + if (strlen(msg) > 4 && strnicmp(msg, "/pm", 3) == 0) // used /pm + { + // what we're gonna do now is check if the node exists + // with that logic, characters 4 and 5 are our numbers: + int spc = 1; // used if nodenum[1] is a space. + char *nodenum = (char*) malloc(3); + strncpy(nodenum, msg+3, 5); + // check for undesirable characters in our "number" + if (((nodenum[0] < '0') || (nodenum[0] > '9')) || ((nodenum[1] < '0') || (nodenum[1] > '9'))) + { + // check if nodenum[1] is a space + if (nodenum[1] == ' ') + spc = 0; + // let it slide + else + { + HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm \'."); + return; + } + } + // I'm very bad at C, I swear I am, additional checks eww! + if (spc != 0) + { + if (msg[5] != ' ') + { + HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm \'."); + return; + } + } + + target = atoi((const char*) nodenum); // turn that into a number + //CONS_Printf("%d\n", target); + + // check for target player, if it doesn't exist then we can't send the message! + if (playeringame[target]) // player exists + target++; // even though playernums are from 0 to 31, target is 1 to 32, so up that by 1 to have it work! + else + { + HU_AddChatText(va("\x82NOTICE: \x80Player %d does not exist.", target)); // same + return; + } + buf[0] = target; + const char *newmsg = msg+5+spc; + memcpy(msg, newmsg, 255); + } SendNetXCmd(XD_SAY, buf, strlen(msg) + 1 + msg-buf); } @@ -457,6 +574,8 @@ static void Command_CSay_f(void) DoSayCommand(0, 1, HU_CSAY); } +static tic_t stop_spamming_you_cunt[MAXPLAYERS]; + /** Receives a message, processing an ::XD_SAY command. * \sa DoSayCommand * \author Graue @@ -469,7 +588,7 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) char *msg; boolean action = false; char *ptr; - + CONS_Debug(DBG_NETPLAY,"Received SAY cmd from Player %d (%s)\n", playernum+1, player_names[playernum]); target = READSINT8(*p); @@ -514,12 +633,32 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) } } } - -#ifdef HAVE_BLUA - if (LUAh_PlayerMsg(playernum, target, flags, msg)) + + int spam_eatmsg = 0; + + // before we do anything, let's verify the guy isn't spamming, get this easier on us. + + //if (stop_spamming_you_cunt[playernum] != 0 && cv_chatspamprotection.value && !(flags & HU_CSAY)) + if (stop_spamming_you_cunt[playernum] != 0 && consoleplayer != playernum && cv_chatspamprotection.value && !(flags & HU_CSAY)) + { + CONS_Debug(DBG_NETPLAY,"Received SAY cmd too quickly from Player %d (%s), assuming as spam and blocking message.\n", playernum+1, player_names[playernum]); + stop_spamming_you_cunt[playernum] = 4; + spam_eatmsg = 1; + } + else + stop_spamming_you_cunt[playernum] = 4; // you can hold off for 4 tics, can you? + + // run the lua hook even if we were supposed to eat the msg, netgame consistency goes first. + +/*#ifdef HAVE_BLUA + if (LUAh_PlayerMsg(playernum, target, flags, msg, spam_eatmsg)) return; -#endif - +#endif*/ + // Kill PlayerMsg for now, it breaks the purpose of this EXE. + + if (spam_eatmsg) + return; // don't proceed if we were supposed to eat the message. + // If it's a CSAY, just CECHO and be done with it. if (flags & HU_CSAY) { @@ -559,18 +698,23 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) || target == 0 // To everyone || consoleplayer == target-1) // To you { - const char *cstart = "", *cend = "", *adminchar = "~", *remotechar = "@", *fmt; + const char *prefix = "", *cstart = "", *cend = "", *adminchar = "\x82~\x83", *remotechar = "\x82@\x83", *fmt, *fmt2; char *tempchar = NULL; - + // In CTF and team match, color the player's name. if (G_GametypeHasTeams()) { - cend = "\x80"; - if (players[playernum].ctfteam == 1) // red - cstart = "\x85"; + cend = ""; + if (players[playernum].ctfteam == 1) // red + cstart = "\x85"; else if (players[playernum].ctfteam == 2) // blue cstart = "\x84"; + } + + // player is a spectator? + if (players[playernum].spectator) + cstart = "\x86"; // grey name // Give admins and remote admins their symbols. if (playernum == serverplayer) @@ -579,11 +723,11 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) tempchar = (char *)Z_Calloc(strlen(cstart) + strlen(remotechar) + 1, PU_STATIC, NULL); if (tempchar) { - strcat(tempchar, cstart); if (playernum == serverplayer) strcat(tempchar, adminchar); else strcat(tempchar, remotechar); + strcat(tempchar, cstart); cstart = tempchar; } @@ -592,21 +736,61 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) // name, color end, and the message itself. // '\4' makes the message yellow and beeps; '\3' just beeps. if (action) - fmt = "\4* %s%s%s \x82%s\n"; + { + fmt = "\3* %s%s%s%s \x82%s\n"; // don't make /me yellow, yellow will be for mentions and PMs! + fmt2 = "* %s%s%s%s \x82%s"; + } else if (target == 0) // To everyone - fmt = "\3<%s%s%s> %s\n"; + { + fmt = "\3%s\x83<%s%s%s\x83>\x80 %s\n"; + fmt2 = "%s\x83<%s%s%s\x83>\x80 %s"; + } else if (target-1 == consoleplayer) // To you - fmt = "\3*%s%s%s* %s\n"; + { + prefix = "\x82[PM]"; + cstart = "\x82"; + fmt = "\4%s<%s%s>%s\x80 %s\n"; // make this yellow, however. + fmt2 = "%s<%s%s>%s\x80 %s"; + } else if (target > 0) // By you, to another player { // Use target's name. dispname = player_names[target-1]; - fmt = "\3->*%s%s%s* %s\n"; + /*fmt = "\3\x82[TO]\x80%s%s%s* %s\n"; + fmt2 = "\x82[TO]\x80%s%s%s* %s";*/ + prefix = "\x82[TO]"; + cstart = "\x82"; + fmt = "\4%s<%s%s>%s\x80 %s\n"; // make this yellow, however. + fmt2 = "%s<%s%s>%s\x80 %s"; + } else // To your team - fmt = "\3>>%s%s%s<< (team) %s\n"; - - CONS_Printf(fmt, cstart, dispname, cend, msg); + { + if (players[playernum].ctfteam == 1) // red + prefix = "\x85[TEAM]"; + else if (players[playernum].ctfteam == 2) // blue + prefix = "\x84[TEAM]"; + else + prefix = "\x83"; // makes sure this doesn't implode if you sayteam on non-team gamemodes + + fmt = "\3%s<%s%s>\x80%s %s\n"; + fmt2 = "%s<%s%s>\x80%s %s"; + + } + + if (cv_consolechat.value) + { + CONS_Printf(fmt, prefix, cstart, dispname, cend, msg); + HU_AddChatText(va(fmt2, prefix, cstart, dispname, cend, msg)); // add it reguardless, in case we decide to change our mind about our chat type. + } + else + { + HU_AddChatText(va(fmt2, prefix, cstart, dispname, cend, msg)); + CON_LogMessage(va(fmt, prefix, cstart, dispname, cend, msg)); // save to log.txt + if (cv_chatnotifications.value) + S_StartSound(NULL, sfx_radio); + } + if (tempchar) Z_Free(tempchar); } @@ -633,19 +817,48 @@ static inline boolean HU_keyInChatString(char *s, char ch) l = strlen(s); if (l < HU_MAXMSGLEN - 1) { - s[l++] = ch; - s[l]=0; + if (c_input >= strlen(s)) // don't do anything complicated + { + s[l++] = ch; + s[l]=0; + } + else + { + + // move everything past c_input for new characters: + INT32 m = HU_MAXMSGLEN-1; + for (;(m>=c_input);m--) + { + if (s[m]) + s[m+1] = (s[m]); + } + s[c_input] = ch; // and replace this. + } + c_input++; return true; } return false; } else if (ch == KEY_BACKSPACE) { - l = strlen(s); - if (l) - s[--l] = 0; - else + if (c_input <= 0) return false; + size_t i = c_input; + if (!s[i-1]) + return false; + + if (i >= strlen(s)-1) + { + s[strlen(s)-1] = 0; + c_input--; + return false; + } + + for (; (i < HU_MAXMSGLEN); i++) + { + s[i-1] = s[i]; + } + c_input--; } else if (ch != KEY_ENTER) return false; // did not eat key @@ -669,29 +882,10 @@ void HU_Ticker(void) hu_showscores = false; } -#define QUEUESIZE 256 - static boolean teamtalk = false; -static char chatchars[QUEUESIZE]; -static INT32 head = 0, tail = 0; - -// -// HU_dequeueChatChar -// -char HU_dequeueChatChar(void) -{ - char c; - - if (head != tail) - { - c = chatchars[tail]; - tail = (tail + 1) & (QUEUESIZE-1); - } - else - c = 0; - - return c; -} +/*static char chatchars[QUEUESIZE]; +static INT32 head = 0, tail = 0;*/ +// WHY DO YOU OVERCOMPLICATE EVERYTHING????????? // // @@ -702,68 +896,118 @@ static void HU_queueChatChar(char c) { char buf[2+256]; size_t ci = 2; - + char *msg = &buf[2]; do { - c = HU_dequeueChatChar(); + c = w_chat[-2+ci++]; if (!c || (c >= ' ' && !(c & 0x80))) // copy printable characters and terminating '\0' only. - buf[ci++]=c; + buf[ci-1]=c; } while (c); - + size_t i = 0; + for (;(iERROR: The chat is muted. You can't say anything.", "\x85")); return; } - + + INT32 target = 0; + + if (strlen(msg) > 4 && strnicmp(msg, "/pm", 3) == 0) // used /pm + { + // what we're gonna do now is check if the node exists + // with that logic, characters 4 and 5 are our numbers: + + // teamtalk can't send PMs, just don't send it, else everyone would be able to see it, and no one wants to see your sex RP sicko. + if (teamtalk) + { + HU_AddChatText(va("%sCannot send sayto in Say-Team.", "\x85")); + return; + } + + int spc = 1; // used if nodenum[1] is a space. + char *nodenum = (char*) malloc(3); + strncpy(nodenum, msg+3, 5); + // check for undesirable characters in our "number" + if (((nodenum[0] < '0') || (nodenum[0] > '9')) || ((nodenum[1] < '0') || (nodenum[1] > '9'))) + { + // check if nodenum[1] is a space + if (nodenum[1] == ' ') + spc = 0; + // let it slide + else + { + HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm \'."); + return; + } + } + // I'm very bad at C, I swear I am, additional checks eww! + if (spc != 0) + { + if (msg[5] != ' ') + { + HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm \'."); + return; + } + } + + target = atoi((const char*) nodenum); // turn that into a number + //CONS_Printf("%d\n", target); + + // check for target player, if it doesn't exist then we can't send the message! + if (playeringame[target]) // player exists + target++; // even though playernums are from 0 to 31, target is 1 to 32, so up that by 1 to have it work! + else + { + HU_AddChatText(va("\x82NOTICE: \x80Player %d does not exist.", target)); // same + return; + } + // we need to get rid of the /pm + const char *newmsg = msg+5+spc; + memcpy(msg, newmsg, 255); + } if (ci > 3) // don't send target+flags+empty message. { if (teamtalk) buf[0] = -1; // target else - buf[0] = 0; // target + buf[0] = target; + buf[1] = 0; // flags SendNetXCmd(XD_SAY, buf, 2 + strlen(&buf[2]) + 1); } return; } - - if (((head + 1) & (QUEUESIZE-1)) == tail) - CONS_Printf(M_GetText("[Message unsent]\n")); // message not sent - else - { - if (c == KEY_BACKSPACE) - { - if (tail != head) - head = (head - 1) & (QUEUESIZE-1); - } - else - { - chatchars[head] = c; - head = (head + 1) & (QUEUESIZE-1); - } - } } void HU_clearChatChars(void) { - while (tail != head) - HU_queueChatChar(KEY_BACKSPACE); + size_t i = 0; + for (;itype != ev_keydown) return false; // only KeyDown events now... - + if (!chat_on) { // enter chat mode @@ -775,6 +1019,7 @@ boolean HU_Responder(event_t *ev) chat_on = true; w_chat[0] = 0; teamtalk = false; + chat_scrollmedown = true; return true; } if ((ev->data1 == gamecontrol[gc_teamkey][0] || ev->data1 == gamecontrol[gc_teamkey][1]) @@ -785,11 +1030,13 @@ boolean HU_Responder(event_t *ev) chat_on = true; w_chat[0] = 0; teamtalk = true; + chat_scrollmedown = true; return true; } } else // if chat_on { + // Ignore modifier keys // Note that we do this here so users can still set // their chat keys to one of these, if they so desire. @@ -799,18 +1046,95 @@ boolean HU_Responder(event_t *ev) return true; c = (UINT8)ev->data1; - - // use console translations - if (shiftdown) + + // capslock + if (c && c == KEY_CAPSLOCK) // it's a toggle. + { + if (capslock) + capslock = false; + else + capslock = true; + return true; + } + + // use console translations + if (shiftdown ^ capslock) c = shiftxform[c]; - + + // TODO: make chat behave like the console, so that we can go back and edit stuff when we fuck up. + + // pasting. pasting is cool. chat is a bit limited, though :( + if ((c == 'v' || c == 'V') && ctrldown) + { + const char *paste = I_ClipboardPaste(); + + // create a dummy string real quickly + + if (paste == NULL) + return true; + + size_t chatlen = strlen(w_chat); + size_t pastelen = strlen(paste); + if (chatlen+pastelen > HU_MAXMSGLEN) + return true; // we can't paste this!! + + if (c_input >= strlen(w_chat)) // add it at the end of the string. + { + memcpy(&w_chat[chatlen], paste, pastelen); // copy all of that. + c_input += pastelen; + /*size_t i = 0; + for (;i=c_input;i--) + { + if (w_chat[i]) + w_chat[i+pastelen] = w_chat[i]; + + } + memcpy(&w_chat[c_input], paste, pastelen); // copy all of that. + c_input += pastelen; + return true; + } + } + if (HU_keyInChatString(w_chat,c)) + { HU_queueChatChar(c); + } if (c == KEY_ENTER) + { chat_on = false; + c_input = 0; // reset input cursor + chat_scrollmedown = true; // you hit enter, so you might wanna autoscroll to see what you just sent. :) + } else if (c == KEY_ESCAPE) + { chat_on = false; - + c_input = 0; // reset input cursor + } + else if ((c == KEY_UPARROW || c == KEY_MOUSEWHEELUP) && chat_scroll > 0) // CHAT SCROLLING YAYS! + { + chat_scroll--; + justscrolledup = true; + chat_scrolltime = 4; + } + else if ((c == KEY_DOWNARROW || c == KEY_MOUSEWHEELDOWN) && chat_scroll < chat_maxscroll && chat_maxscroll > 0) + { + chat_scroll++; + justscrolleddown = true; + chat_scrolltime = 4; + } + else if (c == KEY_LEFTARROW && c_input != 0) // i said go back + c_input--; + else if (c == KEY_RIGHTARROW && c_input < strlen(w_chat)) + c_input++; return true; } return false; @@ -820,12 +1144,472 @@ boolean HU_Responder(event_t *ev) // HEADS UP DRAWING //====================================================================== +// Gets string colormap, used for 0x80 color codes +// +static UINT8 *CHAT_GetStringColormap(INT32 colorflags) // pasted from video.c, sorry for the mess. +{ + switch ((colorflags & V_CHARCOLORMASK) >> V_CHARCOLORSHIFT) + { + case 1: // 0x81, purple + return purplemap; + case 2: // 0x82, yellow + return yellowmap; + case 3: // 0x83, lgreen + return lgreenmap; + case 4: // 0x84, blue + return bluemap; + case 5: // 0x85, red + return redmap; + case 6: // 0x86, gray + return graymap; + case 7: // 0x87, orange + return orangemap; + default: // reset + return NULL; + } +} + +// Precompile a wordwrapped string to any given width. +// This is a muuuch better method than V_WORDWRAP. +// again stolen and modified a bit from video.c, don't mind me, will need to rearrange this one day. +// this one is simplified for the chat drawer. +char *CHAT_WordWrap(INT32 x, INT32 w, INT32 option, const char *string) +{ + int c; + size_t chw, i, lastusablespace = 0; + size_t slen; + char *newstring = Z_StrDup(string); + INT32 spacewidth = (vid.width < 640) ? 8 : 4, charwidth = (vid.width < 640) ? 8 : 4; + + slen = strlen(string); + x = 0; + + for (i = 0; i < slen; ++i) + { + c = newstring[i]; + if ((UINT8)c >= 0x80 && (UINT8)c <= 0x89) //color parsing! -Inuyasha 2.16.09 + continue; + + if (c == '\n') + { + x = 0; + lastusablespace = 0; + continue; + } + + if (!(option & V_ALLOWLOWERCASE)) + c = toupper(c); + c -= HU_FONTSTART; + + if (c < 0 || c >= HU_FONTSIZE || !hu_font[c]) + { + chw = spacewidth; + lastusablespace = i; + } + else + chw = charwidth; + + x += chw; + + if (lastusablespace != 0 && x > w) + { + //CONS_Printf("Wrap at index %d\n", i); + newstring[lastusablespace] = '\n'; + i = lastusablespace+1; + lastusablespace = 0; + x = 0; + } + } + return newstring; +} + +// 30/7/18: chaty is now the distance at which the lowest point of the chat will be drawn if that makes any sense. + +INT16 chatx = 160, chaty = 192; // let's use this as our coordinates, shh + +// chat stuff by VincyTM LOL XD! + +// HU_DrawMiniChat + +static void HU_drawMiniChat(void) +{ + + if (!chat_nummsg_min) + return; // needless to say it's useless to do anything if we don't have anything to draw. + + + INT32 x = chatx+2; + INT32 charwidth = 4, charheight = 6; + INT32 dx = 0, dy = 0; + size_t i = chat_nummsg_min; + + INT32 msglines = 0; + // process all messages once without rendering anything or doing anything fancy so that we know how many lines each message has... + + for (; i>0; i--) + { + const char *msg = CHAT_WordWrap(x, cv_chatwidth.value-charwidth, V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_mini[i-1]); + size_t j = 0; + INT32 linescount = 0; + + while(msg[j]) // iterate through msg + { + if (msg[j] < HU_FONTSTART) // don't draw + { + if (msg[j] == '\n') // get back down. + { + ++j; + linescount += 1; + dx = 0; + continue; + } + else if (msg[j] & 0x80) // stolen from video.c, nice. + { + ++j; + continue; + } + + ++j; + } + else + { + j++; + } + + dx += charwidth; + if (dx >= cv_chatwidth.value) + { + dx = 0; + linescount += 1; + } + } + dy = 0; + dx = 0; + msglines += linescount+1; + } + + INT32 y = chaty - charheight*(msglines+1); + dx = 0; + dy = 0; + i = 0; + + for (; i<=(chat_nummsg_min-1); i++) // iterate through our hot messages + { + + INT32 clrflag = 0; + INT32 timer = ((cv_chattime.value*TICRATE)-chat_timers[i]) - cv_chattime.value*TICRATE+9; // see below... + INT32 transflag = (timer >= 0 && timer <= 9) ? (timer*V_10TRANS) : 0; // you can make bad jokes out of this one. + size_t j = 0; + const char *msg = CHAT_WordWrap(x, cv_chatwidth.value-charwidth, V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_mini[i]); // get the current message, and word wrap it. + + while(msg[j]) // iterate through msg + { + if (msg[j] < HU_FONTSTART) // don't draw + { + if (msg[j] == '\n') // get back down. + { + ++j; + dy += charheight; + dx = 0; + continue; + } + else if (msg[j] & 0x80) // stolen from video.c, nice. + { + clrflag = ((msg[j] & 0x7f) << V_CHARCOLORSHIFT) & V_CHARCOLORMASK; + ++j; + continue; + } + + ++j; + } + else + { + UINT8 *colormap = CHAT_GetStringColormap(clrflag); + V_DrawChatCharacter(x + dx + 2, y+dy, msg[j++] |V_SNAPTOBOTTOM|V_SNAPTORIGHT|transflag, !cv_allcaps.value, colormap); + } + + dx += charwidth; + if (dx >= cv_chatwidth.value) + { + dx = 0; + dy += charheight; + } + } + dy += charheight; + dx = 0; + } + + // decrement addy and make that shit smooth: + addy /= 2; + +} + +// HU_DrawUpArrow +// You see, we don't have arrow graphics in 2.1 and I'm too lazy to include a 2 bytes file for it. + +static void HU_DrawUpArrow(INT32 x, INT32 y, INT32 options) +{ + // Ok I'm super lazy so let's make this as the worst draw function: + V_DrawFill(x+2, y, 1, 1, 103|options); + V_DrawFill(x+1, y+1, 3, 1, 103|options); + V_DrawFill(x, y+2, 5, 1, 103|options); // that's the yellow part, I swear + + V_DrawFill(x+3, y, 1, 1, 26|options); + V_DrawFill(x+4, y+1, 1, 1, 26|options); + V_DrawFill(x+5, y+2, 1, 1, 26|options); + V_DrawFill(x, y+3, 6, 1, 26|options); // that's the black part. no racism intended. i swear. +} + +// HU_DrawDownArrow +// Should we talk about anime waifus to pass the time? This feels retarded. + +static void HU_DrawDownArrow(INT32 x, INT32 y, INT32 options) +{ + // Ok I'm super lazy so let's make this as the worst draw function: + V_DrawFill(x, y, 6, 1, 26|options); + V_DrawFill(x, y+1, 5, 1, 26|options); + V_DrawFill(x+1, y+2, 3, 1, 26|options); + V_DrawFill(x+2, y+3, 1, 1, 26|options); // that's the black part. no racism intended. i swear. + + V_DrawFill(x, y, 5, 1, 103|options); + V_DrawFill(x+1, y+1, 3, 1, 103|options); + V_DrawFill(x+2, y+2, 1, 1, 103|options); // that's the yellow part, I swear +} + +// HU_DrawChatLog +// TODO: fix dumb word wrapping issues + +static void HU_drawChatLog(INT32 offset) +{ + + // before we do anything, make sure that our scroll position isn't "illegal"; + if (chat_scroll > chat_maxscroll) + chat_scroll = chat_maxscroll; + + INT32 charwidth = (vid.width < 640) ? 8 : 4, charheight = (vid.width < 640) ? 8 : 6; + INT32 x = chatx+2, y = chaty - offset*charheight - (chat_scroll*charheight) - cv_chatheight.value*charheight - 12, dx = 0, dy = 0; + size_t i = 0; + INT32 chat_topy = y + chat_scroll*charheight; + INT32 chat_bottomy = chat_topy + cv_chatheight.value*charheight; + boolean atbottom = false; + + V_DrawFillConsoleMap(chatx, chat_topy, cv_chatwidth.value, cv_chatheight.value*charheight +2, 239|V_SNAPTOBOTTOM|V_SNAPTORIGHT); // log box + + for (i=0; i= chat_topy) && (y+dy < (chat_bottomy))) + { + UINT8 *colormap = CHAT_GetStringColormap(clrflag); + V_DrawChatCharacter(x + dx + 2, y+dy+2, msg[j++] |V_SNAPTOBOTTOM|V_SNAPTORIGHT, !cv_allcaps.value, colormap); + } + else + j++; // don't forget to increment this or we'll get stuck in the limbo. + } + + dx += charwidth; + if (dx >= cv_chatwidth.value-charwidth-2 && i= HU_FONTSTART) // end of message shouldn't count, nor should invisible characters!!!! + { + dx = 0; + dy += charheight; + } + } + dy += charheight; + dx = 0; + } + + if (((chat_scroll >= chat_maxscroll) || (chat_scrollmedown)) && !(justscrolleddown || justscrolledup || chat_scrolltime)) // was already at the bottom of the page before new maxscroll calculation and was NOT scrolling. + { + atbottom = true; // we should scroll + } + chat_scrollmedown = false; + + // getmaxscroll through a lazy hack. We do all these loops, so let's not do more loops that are gonna lag the game more. :P + chat_maxscroll = (dy/charheight)-cv_chatheight.value; // welcome to C, we don't know what min() and max() are. + if (chat_maxscroll < 0) + chat_maxscroll = 0; + + // if we're not bound by the time, autoscroll for next frame: + if (atbottom) + chat_scroll = chat_maxscroll; + + // draw arrows to indicate that we can (or not) scroll. + + if (chat_scroll > 0) + HU_DrawUpArrow(chatx-8, ((justscrolledup) ? (chat_topy-1) : (chat_topy)), V_SNAPTOBOTTOM | V_SNAPTORIGHT); + if (chat_scroll < chat_maxscroll) + HU_DrawDownArrow(chatx-8, chat_bottomy-((justscrolleddown) ? 3 : 4), V_SNAPTOBOTTOM | V_SNAPTORIGHT); + + justscrolleddown = false; + justscrolledup = false; +} + // // HU_DrawChat // // Draw chat input // + +static INT16 typelines = 1; // number of drawfill lines we need. it's some weird hack and might be one frame off but I'm lazy to make another loop. static void HU_DrawChat(void) +{ + INT32 charwidth = (vid.width < 640) ? 8 : 4, charheight = (vid.width < 640) ? 8 : 6; + INT32 t = 0, c = 0, y = chaty - ((vid.width < 640 ) ? (typelines*charheight+2) : (typelines*charheight)); + size_t i = 0; + const char *ntalk = "Say: ", *ttalk = "Team: "; + const char *talk = ntalk; + + if (teamtalk) + { + talk = ttalk; +#if 0 + if (players[consoleplayer].ctfteam == 1) + t = 0x500; // Red + else if (players[consoleplayer].ctfteam == 2) + t = 0x400; // Blue +#endif + } + + V_DrawFillConsoleMap(chatx, y-1, cv_chatwidth.value, (vid.width < 640 ) ? (typelines*charheight+2) : (typelines*charheight), 239 | V_SNAPTOBOTTOM | V_SNAPTORIGHT); + + while (talk[i]) + { + if (talk[i] < HU_FONTSTART) + ++i; + else + V_DrawChatCharacter(chatx + c + 2, y, talk[i++] |V_SNAPTOBOTTOM|V_SNAPTORIGHT, !cv_allcaps.value, NULL); + + c += charwidth; + } + + i = 0; + typelines = 1; + + if ((strlen(w_chat) == 0 || c_input == 0) && hu_tick < 4) + V_DrawChatCharacter(chatx + 2 + c, y+1, '_' |V_SNAPTOBOTTOM|V_SNAPTORIGHT|t, !cv_allcaps.value, NULL); + + while (w_chat[i]) + { + + if (c_input == (i+1) && hu_tick < 4) + { + int cursorx = (c+charwidth < cv_chatwidth.value-charwidth) ? (chatx + 2 + c+charwidth) : (chatx); // we may have to go down. + int cursory = (cursorx != chatx) ? (y) : (y+charheight); + V_DrawChatCharacter(cursorx, cursory+1, '_' |V_SNAPTOBOTTOM|V_SNAPTORIGHT|t, !cv_allcaps.value, NULL); + } + + //Hurdler: isn't it better like that? + if (w_chat[i] < HU_FONTSTART) + ++i; + else + V_DrawChatCharacter(chatx + c + 2, y, w_chat[i++] | V_SNAPTOBOTTOM|V_SNAPTORIGHT | t, !cv_allcaps.value, NULL); + + c += charwidth; + if (c > cv_chatwidth.value-charwidth) + { + c = 0; + y += charheight; + typelines += 1; + } + } + + // handle /pm list. + if (strnicmp(w_chat, "/pm", 3) == 0 && vid.width >= 400 && !teamtalk) // 320x200 unsupported kthxbai + { + i = 0; + int count = 0; + INT32 p_dispy = chaty - charheight -1; + for(i=0; (i '9'))) || ((w_chat[4] != 0) && (((w_chat[4] < '0') || (w_chat[4] > '9'))))) && (w_chat[4] != ' ')) + break; + + + char *nodenum = (char*) malloc(3); + strncpy(nodenum, w_chat+3, 4); + INT32 n = atoi((const char*) nodenum); // turn that into a number + // special cases: + + if ((n == 0) && !(w_chat[4] == '0')) + { + if (!(i<10)) + continue; + } + else if ((n == 1) && !(w_chat[3] == '0')) + { + if (!((i == 1) || ((i >= 10) && (i <= 19)))) + continue; + } + else if ((n == 2) && !(w_chat[3] == '0')) + { + if (!((i == 2) || ((i >= 20) && (i <= 29)))) + continue; + } + else if ((n == 3) && !(w_chat[3] == '0')) + { + if (!((i == 3) || ((i >= 30) && (i <= 31)))) + continue; + } + else // general case. + { + if (i != n) + continue; + } + } + + if (1 || (playeringame[i])) + { + char name[MAXPLAYERNAME+1]; + strlcpy(name, player_names[i], 7); // shorten name to 7 characters. + V_DrawFillConsoleMap(chatx-50, p_dispy- (6*count), 48, 6, 239 | V_SNAPTOBOTTOM | V_SNAPTORIGHT); // fill it like the chat so the text doesn't become hard to read because of the hud. + V_DrawSmallString(chatx-48, p_dispy- (6*count), V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_ALLOWLOWERCASE, va("\x82%d\x80 - %s", i, name)); + count++; + } + } + if (count == 0) // no results. + { + V_DrawFillConsoleMap(chatx-50, p_dispy- (6*count), 48, 6, 239 | V_SNAPTOBOTTOM | V_SNAPTORIGHT); // fill it like the chat so the text doesn't become hard to read because of the hud. + V_DrawSmallString(chatx-48, p_dispy- (6*count), V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_ALLOWLOWERCASE, "NO RESULT."); + } + } + + HU_drawChatLog(typelines-1); // typelines is the # of lines we're typing. If there's more than 1 then the log should scroll up to give us more space. + +} + +// why the fuck would you use this... + +static void HU_DrawChat_Old(void) { INT32 t = 0, c = 0, y = HU_INPUTY; size_t i = 0; @@ -833,7 +1617,6 @@ static void HU_DrawChat(void) const char *talk = ntalk; INT32 charwidth = 8 * con_scalefactor; //SHORT(hu_font['A'-HU_FONTSTART]->width) * con_scalefactor; INT32 charheight = 8 * con_scalefactor; //SHORT(hu_font['A'-HU_FONTSTART]->height) * con_scalefactor; - if (teamtalk) { talk = ttalk; @@ -859,10 +1642,21 @@ static void HU_DrawChat(void) } c += charwidth; } - + + if ((strlen(w_chat) == 0 || c_input == 0) && hu_tick < 4) + V_DrawCharacter(HU_INPUTX+c, y+2*con_scalefactor, '_' |cv_constextsize.value | V_NOSCALESTART|t, !cv_allcaps.value); + i = 0; while (w_chat[i]) { + + if (c_input == (i+1) && hu_tick < 4) + { + int cursorx = (HU_INPUTX+c+charwidth < vid.width) ? (HU_INPUTX + c + charwidth) : (HU_INPUTX); // we may have to go down. + int cursory = (cursorx != HU_INPUTX) ? (y) : (y+charheight); + V_DrawCharacter(cursorx, cursory+2*con_scalefactor, '_' |cv_constextsize.value | V_NOSCALESTART|t, !cv_allcaps.value); + } + //Hurdler: isn't it better like that? if (w_chat[i] < HU_FONTSTART) { @@ -882,9 +1676,6 @@ static void HU_DrawChat(void) y += charheight; } } - - if (hu_tick < 4) - V_DrawCharacter(HU_INPUTX + c, y, '_' | cv_constextsize.value |V_NOSCALESTART|t, !cv_allcaps.value); } @@ -1057,7 +1848,45 @@ void HU_Drawer(void) { // draw chat string plus cursor if (chat_on) - HU_DrawChat(); + { + // count down the scroll timer. + if (chat_scrolltime > 0) + chat_scrolltime--; + if (!cv_consolechat.value && vid.width >= 640) // don't even bother with 200p + HU_DrawChat(); + else + HU_DrawChat_Old(); // why the fuck......................... + } + else + { + if (!cv_consolechat.value) + { + HU_drawMiniChat(); // draw messages in a cool fashion. + chat_scrolltime = 0; // do scroll anyway. + typelines = 0; // make sure that the chat doesn't have a weird blinking huge ass square if we typed a lot last time. + } + } + + if (netgame) // would handle that in hu_drawminichat, but it's actually kinda awkward when you're typing a lot of messages. (only handle that in netgames duh) + { + size_t i = 0; + + // handle spam while we're at it: + for(; (i 0) + stop_spamming_you_cunt[i]--; + } + + // handle chat timers + for (i=0; (i 0) + chat_timers[i]--; + else + HU_removeChatText_Mini(); + } + } if (cechotimer) HU_DrawCEcho(); @@ -1153,9 +1982,9 @@ void HU_Erase(void) // clear the message lines that go away, so use _oldclearlines_ bottomline = oldclearlines; oldclearlines = con_clearlines; - if (chat_on) + if (chat_on && cv_consolechat.value) if (bottomline < 8) - bottomline = 8; + bottomline = 8; // only do it for consolechat. consolechat is gay. if (automapactive || viewwindowx == 0) // hud msgs don't need to be cleared return; @@ -1191,6 +2020,40 @@ void HU_Erase(void) // IN-LEVEL MULTIPLAYER RANKINGS //====================================================================== +// +// HU_drawPing +// +void HU_drawPing(INT32 x, INT32 y, INT32 ping, boolean notext) +{ + UINT8 numbars = 1; // how many ping bars do we draw? + UINT8 barcolor = 128; // color we use for the bars (green, yellow or red) + SINT8 i = 0; + SINT8 yoffset = 6; + if (ping < 128) + { + numbars = 3; + barcolor = 184; + } + else if (ping < 256) + { + numbars = 2; // Apparently ternaries w/ multiple statements don't look good in C so I decided against it. + barcolor = 103; + } + + INT32 dx = x+1 - (V_SmallStringWidth(va("%dms", ping), V_ALLOWLOWERCASE)/2); + if (!notext || vid.width >= 640) // how sad, we're using a shit resolution. + V_DrawSmallString(dx, y+4, V_ALLOWLOWERCASE, va("%dms", ping)); + + for (i=0; (i<3); i++) // Draw the ping bar + { + V_DrawFill(x+2 *(i-1), y+yoffset-4, 2, 8-yoffset, 31); + if (i < numbars) + V_DrawFill(x+2 *(i-1), y+yoffset-3, 1, 8-yoffset-1, barcolor); + + yoffset -= 2; + } +} + // // HU_DrawTabRankings // @@ -1208,7 +2071,15 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I { if (players[tab[i].num].spectator) continue; //ignore them. - + + if (!splitscreen) // don't draw it on splitscreen, + { + if (!(tab[i].num == serverplayer)) + HU_drawPing(x+ 253, y+2, playerpingtable[tab[i].num], false); + //else + // V_DrawSmallString(x+ 246, y+4, V_YELLOWMAP, "SERVER"); + } + V_DrawString(x + 20, y, ((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0) | ((players[tab[i].num].health > 0) ? 0 : V_60TRANS) @@ -1286,9 +2157,37 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I } // -// HU_DrawTeamTabRankings +// HU_Draw32Emeralds // -void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer) +static void HU_Draw32Emeralds(INT32 x, INT32 y, INT32 pemeralds) +{ + //Draw the emeralds, in the CORRECT order, using tiny emerald sprites. + if (pemeralds & EMERALD1) + V_DrawSmallScaledPatch(x , y, 0, tinyemeraldpics[0]); + + if (pemeralds & EMERALD2) + V_DrawSmallScaledPatch(x+4, y, 0, tinyemeraldpics[1]); + + if (pemeralds & EMERALD3) + V_DrawSmallScaledPatch(x+8, y, 0, tinyemeraldpics[2]); + + if (pemeralds & EMERALD4) + V_DrawSmallScaledPatch(x+12 , y, 0, tinyemeraldpics[3]); + + if (pemeralds & EMERALD5) + V_DrawSmallScaledPatch(x+16, y, 0, tinyemeraldpics[4]); + + if (pemeralds & EMERALD6) + V_DrawSmallScaledPatch(x+20, y, 0, tinyemeraldpics[5]); + + if (pemeralds & EMERALD7) + V_DrawSmallScaledPatch(x+24, y, 0, tinyemeraldpics[6]); +} + +// +// HU_Draw32TeamTabRankings +// +static void HU_Draw32TeamTabRankings(playersort_t *tab, INT32 whiteplayer) { INT32 i,x,y; INT32 redplayers = 0, blueplayers = 0; @@ -1298,7 +2197,124 @@ void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer) V_DrawFill(160, 26, 1, 154, 0); //Draw a vertical line to separate the two teams. V_DrawFill(1, 26, 318, 1, 0); //And a horizontal line to make a T. V_DrawFill(1, 180, 318, 1, 0); //And a horizontal line near the bottom. + + for (i = 0; i < MAXPLAYERS; i++) + { + if (players[tab[i].num].spectator) + continue; //ignore them. + if (tab[i].color == skincolor_redteam) //red + { + redplayers++; + x = 14 + (BASEVIDWIDTH/2); + y = (redplayers * 9) + 20; + } + else if (tab[i].color == skincolor_blueteam) //blue + { + blueplayers++; + x = 14; + y = (blueplayers * 9) + 20; + } + else //er? not on red or blue, so ignore them + continue; + + strlcpy(name, tab[i].name, 8); + V_DrawString(x + 10, y, + ((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0) + | ((players[tab[i].num].health > 0) ? 0 : V_TRANSLUCENT) + | V_ALLOWLOWERCASE, name); + + if (gametype == GT_CTF) + { + if (players[tab[i].num].gotflag & GF_REDFLAG) // Red + V_DrawFixedPatch((x-10)*FRACUNIT, (y)*FRACUNIT, FRACUNIT/4, 0, rflagico, 0); + else if (players[tab[i].num].gotflag & GF_BLUEFLAG) // Blue + V_DrawFixedPatch((x-10)*FRACUNIT, (y)*FRACUNIT, FRACUNIT/4, 0, bflagico, 0); + } + + // Draw emeralds + if (!players[tab[i].num].powers[pw_super] + || ((leveltime/7) & 1)) + { + HU_Draw32Emeralds(x+60, y+2, tab[i].emeralds); + } + + if (players[tab[i].num].powers[pw_super]) + { + colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo ? players[tab[i].num].mo->color : tab[i].color, GTC_CACHE); + V_DrawFixedPatch(x*FRACUNIT, y*FRACUNIT, FRACUNIT/4, 0, superprefix[players[tab[i].num].skin], colormap); + } + else + { + colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo ? players[tab[i].num].mo->color : tab[i].color, GTC_CACHE); + if (players[tab[i].num].health <= 0) + V_DrawFixedPatch(x*FRACUNIT, y*FRACUNIT, FRACUNIT/4, V_HUDTRANSHALF, faceprefix[players[tab[i].num].skin], colormap); + else + V_DrawFixedPatch(x*FRACUNIT, y*FRACUNIT, FRACUNIT/4, 0, faceprefix[players[tab[i].num].skin], colormap); + } + V_DrawRightAlignedThinString(x+128, y, ((players[tab[i].num].health > 0) ? 0 : V_TRANSLUCENT), va("%u", tab[i].count)); + if (!splitscreen) + { + if (!(tab[i].num == serverplayer)) + HU_drawPing(x+ 135, y+3, playerpingtable[tab[i].num], true); + //else + //V_DrawSmallString(x+ 129, y+4, V_YELLOWMAP, "HOST"); + } + } +} + +// +// HU_DrawTeamTabRankings +// +void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer) +{ + INT32 i,x,y; + INT32 redplayers = 0, blueplayers = 0; + boolean smol = false; + + // before we draw, we must count how many players are in each team. It makes an additional loop, but we need to know if we have to draw a big or a small ranking. + for (i = 0; i < MAXPLAYERS; i++) + { + if (players[tab[i].num].spectator) + continue; //ignore them. + + if (tab[i].color == skincolor_redteam) //red + { + if (redplayers++ > 8) + { + smol = true; + break; // don't make more loops than we need to. + } + } + else if (tab[i].color == skincolor_blueteam) //blue + { + if (blueplayers++ > 8) + { + smol = true; + break; + } + } + else //er? not on red or blue, so ignore them + continue; + + } + + // I'll be blunt with you, this may add more lines, but I'm not adding weird cases for this, so we're executing a separate function. + if (smol == true || cv_compactscoreboard.value) + { + HU_Draw32TeamTabRankings(tab, whiteplayer); + return; + } + + V_DrawFill(160, 26, 1, 154, 0); //Draw a vertical line to separate the two teams. + V_DrawFill(1, 26, 318, 1, 0); //And a horizontal line to make a T. + V_DrawFill(1, 180, 318, 1, 0); //And a horizontal line near the bottom. + + const UINT8 *colormap; + char name[MAXPLAYERNAME+1]; + + i=0, redplayers=0, blueplayers=0; + for (i = 0; i < MAXPLAYERS; i++) { if (players[tab[i].num].spectator) @@ -1321,7 +2337,7 @@ void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer) else //er? not on red or blue, so ignore them continue; - strlcpy(name, tab[i].name, 9); + strlcpy(name, tab[i].name, 7); V_DrawString(x + 20, y, ((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0) | ((players[tab[i].num].health > 0) ? 0 : V_TRANSLUCENT) @@ -1355,7 +2371,14 @@ void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer) else V_DrawSmallMappedPatch (x, y-4, 0, faceprefix[players[tab[i].num].skin], colormap); } - V_DrawRightAlignedThinString(x+120, y, ((players[tab[i].num].health > 0) ? 0 : V_TRANSLUCENT), va("%u", tab[i].count)); + V_DrawRightAlignedThinString(x+100, y, ((players[tab[i].num].health > 0) ? 0 : V_TRANSLUCENT), va("%u", tab[i].count)); + if (!splitscreen) + { + if (!(tab[i].num == serverplayer)) + HU_drawPing(x+ 113, y+2, playerpingtable[tab[i].num], false); + //else + // V_DrawSmallString(x+ 94, y+4, V_YELLOWMAP, "SERVER"); + } } } @@ -1377,7 +2400,12 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline if (players[tab[i].num].spectator) continue; //ignore them. - strlcpy(name, tab[i].name, 9); + strlcpy(name, tab[i].name, 7); + if (!(tab[i].num == serverplayer)) + HU_drawPing(x+ 113, y+2, playerpingtable[tab[i].num], false); + //else + // V_DrawSmallString(x+ 94, y+4, V_YELLOWMAP, "SERVER"); + V_DrawString(x + 20, y, ((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0) | ((players[tab[i].num].health > 0) ? 0 : V_TRANSLUCENT) @@ -1432,15 +2460,15 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline if (circuitmap) { if (players[tab[i].num].exiting) - V_DrawRightAlignedThinString(x+156, y, 0, va("%i:%02i.%02i", G_TicsToMinutes(players[tab[i].num].realtime,true), G_TicsToSeconds(players[tab[i].num].realtime), G_TicsToCentiseconds(players[tab[i].num].realtime))); + V_DrawRightAlignedThinString(x+146, y, 0, va("%i:%02i.%02i", G_TicsToMinutes(players[tab[i].num].realtime,true), G_TicsToSeconds(players[tab[i].num].realtime), G_TicsToCentiseconds(players[tab[i].num].realtime))); else - V_DrawRightAlignedThinString(x+156, y, ((players[tab[i].num].health > 0) ? 0 : V_TRANSLUCENT), va("%u", tab[i].count)); + V_DrawRightAlignedThinString(x+146, y, ((players[tab[i].num].health > 0) ? 0 : V_TRANSLUCENT), va("%u", tab[i].count)); } else - V_DrawRightAlignedThinString(x+156, y, ((players[tab[i].num].health > 0) ? 0 : V_TRANSLUCENT), va("%i:%02i.%02i", G_TicsToMinutes(tab[i].count,true), G_TicsToSeconds(tab[i].count), G_TicsToCentiseconds(tab[i].count))); + V_DrawRightAlignedThinString(x+146, y, ((players[tab[i].num].health > 0) ? 0 : V_TRANSLUCENT), va("%i:%02i.%02i", G_TicsToMinutes(tab[i].count,true), G_TicsToSeconds(tab[i].count), G_TicsToCentiseconds(tab[i].count))); } else - V_DrawRightAlignedThinString(x+120, y, ((players[tab[i].num].health > 0) ? 0 : V_TRANSLUCENT), va("%u", tab[i].count)); + V_DrawRightAlignedThinString(x+100, y, ((players[tab[i].num].health > 0) ? 0 : V_TRANSLUCENT), va("%u", tab[i].count)); y += 16; if (y > 160) @@ -1451,6 +2479,107 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline } } +// +// HU_Draw32TabRankings +// +void HU_Draw32TabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, INT32 whiteplayer) +{ + INT32 i; + const UINT8 *colormap; + char name[MAXPLAYERNAME+1]; + + V_DrawFill(160, 26, 1, 154, 0); //Draw a vertical line to separate the two sides. + V_DrawFill(1, 26, 318, 1, 0); //And a horizontal line to make a T. + V_DrawFill(1, 180, 318, 1, 0); //And a horizontal line near the bottom. + + for (i = 0; i < scorelines; i++) + { + if (players[tab[i].num].spectator) + continue; //ignore them. + + strlcpy(name, tab[i].name, 7); + if (!splitscreen) // don't draw it on splitscreen, + { + if (!(tab[i].num == serverplayer)) + HU_drawPing(x+ 135, y+3, playerpingtable[tab[i].num], true); + //else + // V_DrawSmallString(x+ 129, y+4, V_YELLOWMAP, "HOST"); + } + + V_DrawString(x + 10, y, + ((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0) + | ((players[tab[i].num].health > 0) ? 0 : V_TRANSLUCENT) + | V_ALLOWLOWERCASE, name); + + if (G_GametypeUsesLives()) //show lives + V_DrawRightAlignedThinString(x-1, y, V_ALLOWLOWERCASE, va("%d", players[tab[i].num].lives)); + else if (G_TagGametype() && players[tab[i].num].pflags & PF_TAGIT) + V_DrawFixedPatch((x-10)*FRACUNIT, (y)*FRACUNIT, FRACUNIT/4, 0, tagico, 0); + + // Draw emeralds + if (!players[tab[i].num].powers[pw_super] + || ((leveltime/7) & 1)) + { + HU_Draw32Emeralds(x+60, y+2, tab[i].emeralds); + //HU_DrawEmeralds(x-12,y+2,tab[i].emeralds); + } + + //V_DrawSmallScaledPatch (x, y-4, 0, livesback); + if (tab[i].color == 0) + { + colormap = colormaps; + if (players[tab[i].num].powers[pw_super]) + V_DrawFixedPatch(x*FRACUNIT, y*FRACUNIT, FRACUNIT/4, 0, superprefix[players[tab[i].num].skin], 0); + else + { + if (players[tab[i].num].health <= 0) + V_DrawFixedPatch(x*FRACUNIT, (y)*FRACUNIT, FRACUNIT/4, V_HUDTRANSHALF, faceprefix[players[tab[i].num].skin], 0); + else + V_DrawFixedPatch(x*FRACUNIT, (y)*FRACUNIT, FRACUNIT/4, 0, faceprefix[players[tab[i].num].skin], 0); + } + } + else + { + if (players[tab[i].num].powers[pw_super]) + { + colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo ? players[tab[i].num].mo->color : tab[i].color, GTC_CACHE); + V_DrawFixedPatch(x*FRACUNIT, y*FRACUNIT, FRACUNIT/4, 0, superprefix[players[tab[i].num].skin], colormap); + } + else + { + colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo ? players[tab[i].num].mo->color : tab[i].color, GTC_CACHE); + if (players[tab[i].num].health <= 0) + V_DrawFixedPatch(x*FRACUNIT, (y)*FRACUNIT, FRACUNIT/4, V_HUDTRANSHALF, faceprefix[players[tab[i].num].skin], colormap); + else + V_DrawFixedPatch(x*FRACUNIT, (y)*FRACUNIT, FRACUNIT/4, 0, faceprefix[players[tab[i].num].skin], colormap); + } + } + + // All data drawn with thin string for space. + if (gametype == GT_RACE) + { + if (circuitmap) + { + if (players[tab[i].num].exiting) + V_DrawRightAlignedThinString(x+128, y, 0, va("%i:%02i.%02i", G_TicsToMinutes(players[tab[i].num].realtime,true), G_TicsToSeconds(players[tab[i].num].realtime), G_TicsToCentiseconds(players[tab[i].num].realtime))); + else + V_DrawRightAlignedThinString(x+128, y, ((players[tab[i].num].health > 0) ? 0 : V_TRANSLUCENT), va("%u", tab[i].count)); + } + else + V_DrawRightAlignedThinString(x+128, y, ((players[tab[i].num].health > 0) ? 0 : V_TRANSLUCENT), va("%i:%02i.%02i", G_TicsToMinutes(tab[i].count,true), G_TicsToSeconds(tab[i].count), G_TicsToCentiseconds(tab[i].count))); + } + else + V_DrawRightAlignedThinString(x+128, y, ((players[tab[i].num].health > 0) ? 0 : V_TRANSLUCENT), va("%u", tab[i].count)); + + y += 9; + if (i == 16) + { + y = 32; + x += BASEVIDWIDTH/2; + } + } +} + // // HU_DrawEmeralds // @@ -1697,15 +2826,18 @@ static void HU_DrawRankings(void) scorelines++; } - if (scorelines > 20) - scorelines = 20; //dont draw past bottom of screen, show the best only + //if (scorelines > 20) + // scorelines = 20; //dont draw past bottom of screen, show the best only + // shush, we'll do it anyway. if (G_GametypeHasTeams()) HU_DrawTeamTabRankings(tab, whiteplayer); //separate function for Spazzo's silly request - else if (scorelines <= 9) + else if (scorelines <= 9 && !cv_compactscoreboard.value) HU_DrawTabRankings(40, 32, tab, scorelines, whiteplayer); - else + else if (scorelines <= 20 && !cv_compactscoreboard.value) HU_DrawDualTabRankings(32, 32, tab, scorelines, whiteplayer); + else + HU_Draw32TabRankings(14, 28, tab, scorelines, whiteplayer); // draw spectators in a ticker across the bottom if (!splitscreen && G_GametypeHasSpectators()) diff --git a/src/hu_stuff.h b/src/hu_stuff.h index 7b22f33f1..c288b9480 100644 --- a/src/hu_stuff.h +++ b/src/hu_stuff.h @@ -72,6 +72,18 @@ extern patch_t *bmatcico; extern patch_t *tagico; extern patch_t *tallminus; +/*typedef struct +{ + const char *msg; // The final message we display on the HUD + tic_t time; // how much time do we still keep the message around for in the mini chat? + boolean hasmention; // make the message yellow if it has a mention because that's pretty cool. +} chatmsg_t;*/ + +#define CHAT_BUFSIZE 64 // that's enough messages, right? We'll delete the older ones when that gets out of hand. + +// some functions +void HU_AddChatText(const char *text); + // set true when entering a chat message extern boolean chat_on; @@ -90,12 +102,12 @@ void HU_LoadGraphics(void); FUNCMATH void HU_Start(void); boolean HU_Responder(event_t *ev); - void HU_Ticker(void); void HU_Drawer(void); char HU_dequeueChatChar(void); void HU_Erase(void); void HU_clearChatChars(void); +void HU_drawPing(INT32 x, INT32 y, INT32 ping, boolean notext); // Lat': Ping drawer for scoreboard. void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, INT32 whiteplayer); void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer); void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, INT32 whiteplayer); diff --git a/src/lua_baselib.c b/src/lua_baselib.c index e8e8fd020..575b44520 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -20,6 +20,7 @@ #include "m_random.h" #include "s_sound.h" #include "g_game.h" +#include "hu_stuff.h" // HU_AddChatText #include "lua_script.h" #include "lua_libs.h" @@ -85,6 +86,51 @@ static int lib_print(lua_State *L) return 0; } +// Print stuff in the chat, or in the console if we can't. +static int lib_chatprint(lua_State *L) +{ + const char *str = luaL_checkstring(L, 1); // retrieve string + if (str == NULL) // error if we don't have a string! + return luaL_error(L, LUA_QL("tostring") " must return a string to " LUA_QL("chatprint")); + int len = strlen(str); + if (len > 255) // string is too long!!! + return luaL_error(L, "String exceeds the 255 characters limit of the chat buffer."); + + if (cv_consolechat.value || !netgame) + CONS_Printf("%s\n", str); + else + HU_AddChatText(str); + return 0; +} + +// Same as above, but do it for only one player. +static int lib_chatprintf(lua_State *L) +{ + int n = lua_gettop(L); /* number of arguments */ + player_t *plr; + if (n < 2) + return luaL_error(L, "chatprintf requires at least two arguments: player and text."); + + plr = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); // retrieve player + if (!plr) + return LUA_ErrInvalid(L, "player_t"); + if (plr != &players[consoleplayer]) + return 0; + + const char *str = luaL_checkstring(L, 2); // retrieve string + if (str == NULL) // error if we don't have a string! + return luaL_error(L, LUA_QL("tostring") " must return a string to " LUA_QL("chatprintf")); + int len = strlen(str); + if (len > 255) // string is too long!!! + return luaL_error(L, "String exceeds the 255 characters limit of the chat buffer."); + + if (cv_consolechat.value || !netgame) + CONS_Printf("%s\n", str); + else + HU_AddChatText(str); + return 0; +} + static int lib_evalMath(lua_State *L) { const char *word = luaL_checkstring(L, 1); @@ -1656,7 +1702,7 @@ static int lib_sStartSound(lua_State *L) const void *origin = NULL; sfxenum_t sound_id = luaL_checkinteger(L, 2); player_t *player = NULL; - NOHUD + //NOHUD // kys @whoever did this. if (sound_id >= NUMSFX) return luaL_error(L, "sfx %d out of range (0 - %d)", sound_id, NUMSFX-1); if (!lua_isnil(L, 1)) @@ -1672,7 +1718,12 @@ static int lib_sStartSound(lua_State *L) return LUA_ErrInvalid(L, "player_t"); } if (!player || P_IsLocalPlayer(player)) + { + if (hud_running) + origin = NULL; // HUD rendering startsound shouldn't have an origin, just remove it instead of having a retarded error. + S_StartSound(origin, sound_id); + } return 0; } @@ -1982,6 +2033,8 @@ static int lib_gTicsToMilliseconds(lua_State *L) static luaL_Reg lib[] = { {"print", lib_print}, + {"chatprint", lib_chatprint}, + {"chatprintf", lib_chatprintf}, {"EvalMath", lib_evalMath}, // m_random diff --git a/src/m_menu.c b/src/m_menu.c index 0ab771579..80172216b 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -293,7 +293,7 @@ static void M_ToggleMIDI(void); //Misc menu_t OP_DataOptionsDef, OP_ScreenshotOptionsDef, OP_EraseDataDef; -menu_t OP_GameOptionsDef, OP_ServerOptionsDef; +menu_t OP_GameOptionsDef, OP_ChatOptionsDef, OP_ServerOptionsDef; menu_t OP_NetgameOptionsDef, OP_GametypeOptionsDef; menu_t OP_MonitorToggleDef; static void M_ScreenshotOptions(INT32 choice); @@ -1286,22 +1286,34 @@ static menuitem_t OP_GameOptionsMenu[] = {IT_STRING | IT_CVAR | IT_CV_STRING, NULL, "Master server", &cv_masterserver, 10}, #endif - {IT_STRING | IT_CVAR, NULL, "Show HUD", &cv_showhud, 40}, + {IT_STRING | IT_SUBMENU, NULL, "Chat Options...", &OP_ChatOptionsDef, 40}, + {IT_STRING | IT_CVAR, NULL, "Show HUD", &cv_showhud, 50}, {IT_STRING | IT_CVAR | IT_CV_SLIDER, - NULL, "HUD Visibility", &cv_translucenthud, 50}, - {IT_STRING | IT_CVAR, NULL, "Timer Display", &cv_timetic, 60}, + NULL, "HUD Visibility", &cv_translucenthud, 60}, + {IT_STRING | IT_CVAR, NULL, "Timer Display", &cv_timetic, 70}, + {IT_STRING | IT_CVAR, NULL, "Always Compact Rankings", &cv_compactscoreboard, 80}, #ifdef SEENAMES - {IT_STRING | IT_CVAR, NULL, "HUD Player Names", &cv_seenames, 80}, + {IT_STRING | IT_CVAR, NULL, "HUD Player Names", &cv_seenames, 90}, #endif - {IT_STRING | IT_CVAR, NULL, "Log Hazard Damage", &cv_hazardlog, 90}, + {IT_STRING | IT_CVAR, NULL, "Log Hazard Damage", &cv_hazardlog, 100}, - {IT_STRING | IT_CVAR, NULL, "Console Back Color", &cons_backcolor, 100}, - {IT_STRING | IT_CVAR, NULL, "Console Text Size", &cv_constextsize,110}, - {IT_STRING | IT_CVAR, NULL, "Uppercase Console", &cv_allcaps, 120}, + {IT_STRING | IT_CVAR, NULL, "Console Back Color", &cons_backcolor, 110}, + {IT_STRING | IT_CVAR, NULL, "Console Text Size", &cv_constextsize,120}, + {IT_STRING | IT_CVAR, NULL, "Uppercase Console", &cv_allcaps, 130}, {IT_STRING | IT_CVAR, NULL, "Title Screen Demos", &cv_rollingdemos, 140}, }; +static menuitem_t OP_ChatOptionsMenu[] = +{ + {IT_STRING | IT_CVAR, NULL, "Chat Width", &cv_chatwidth, 10}, + {IT_STRING | IT_CVAR, NULL, "Chat Height", &cv_chatheight, 20}, + {IT_STRING | IT_CVAR, NULL, "Message Timer", &cv_chattime, 30}, + {IT_STRING | IT_CVAR, NULL, "Chat Notifications", &cv_chatnotifications, 40}, + {IT_STRING | IT_CVAR, NULL, "Spam Protection", &cv_chatspamprotection, 50}, + {IT_STRING | IT_CVAR, NULL, "Old Console Chat", &cv_consolechat, 60}, +}; + static menuitem_t OP_ServerOptionsMenu[] = { {IT_STRING | IT_SUBMENU, NULL, "General netgame options...", &OP_NetgameOptionsDef, 10}, @@ -1697,6 +1709,7 @@ menu_t OP_ServerOptionsDef = DEFAULTMENUSTYLE("M_SERVER", OP_ServerOptionsMenu, menu_t OP_NetgameOptionsDef = DEFAULTMENUSTYLE("M_SERVER", OP_NetgameOptionsMenu, &OP_ServerOptionsDef, 30, 30); menu_t OP_GametypeOptionsDef = DEFAULTMENUSTYLE("M_SERVER", OP_GametypeOptionsMenu, &OP_ServerOptionsDef, 30, 30); +menu_t OP_ChatOptionsDef = DEFAULTMENUSTYLE("M_GAME", OP_ChatOptionsMenu, &OP_GameOptionsDef, 30, 30); menu_t OP_MonitorToggleDef = { "M_SERVER", @@ -2696,7 +2709,7 @@ void M_Init(void) CV_RegisterVar(&cv_newgametype); CV_RegisterVar(&cv_chooseskin); CV_RegisterVar(&cv_autorecord); - + if (dedicated) return; @@ -6295,13 +6308,6 @@ static void M_DrawConnectIPMenu(void) static void M_ConnectIP(INT32 choice) { (void)choice; - - if (*setupm_ip == 0) - { - M_StartMessage("You must specify an IP address.\n", NULL, MM_NOTHING); - return; - } - COM_BufAddText(va("connect \"%s\"\n", setupm_ip)); // A little "please wait" message. diff --git a/src/v_video.c b/src/v_video.c index 161c03d0b..52397bba6 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -834,6 +834,130 @@ void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c) memset(dest, (UINT8)(c&255), w * vid.bpp); } +// THANK YOU MPC!!! + +void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c) +{ + UINT8 *dest; + const UINT8 *deststop; + INT32 u, v; + UINT32 alphalevel = 0; + + if (rendermode == render_none) + return; + +#ifdef HWRENDER + if (rendermode != render_soft && rendermode != render_none) + { + UINT32 hwcolor; + switch (cons_backcolor.value) + { + case 0: hwcolor = 0xffffff00; break; // White + case 1: hwcolor = 0x80808000; break; // Gray + case 2: hwcolor = 0x40201000; break; // Brown + case 3: hwcolor = 0xff000000; break; // Red + case 4: hwcolor = 0xff800000; break; // Orange + case 5: hwcolor = 0x80800000; break; // Yellow + case 6: hwcolor = 0x00800000; break; // Green + case 7: hwcolor = 0x0000ff00; break; // Blue + case 8: hwcolor = 0x4080ff00; break; // Cyan + // Default green + default: hwcolor = 0x00800000; break; + } + HWR_DrawConsoleFill(x, y, w, h, hwcolor, c); // we still use the regular color stuff but only for flags. actual draw color is "hwcolor" for this. + return; + } +#endif + + if (!(c & V_NOSCALESTART)) + { + INT32 dupx = vid.dupx, dupy = vid.dupy; + + if (x == 0 && y == 0 && w == BASEVIDWIDTH && h == BASEVIDHEIGHT) + { // Clear the entire screen, from dest to deststop. Yes, this really works. + memset(screens[0], (UINT8)(c&255), vid.width * vid.height * vid.bpp); + return; + } + + x *= dupx; + y *= dupy; + w *= dupx; + h *= dupy; + + // Center it if necessary + if (vid.width != BASEVIDWIDTH * dupx) + { + // dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx, + // so center this imaginary screen + if (c & V_SNAPTORIGHT) + x += (vid.width - (BASEVIDWIDTH * dupx)); + else if (!(c & V_SNAPTOLEFT)) + x += (vid.width - (BASEVIDWIDTH * dupx)) / 2; + } + if (vid.height != BASEVIDHEIGHT * dupy) + { + // same thing here + if (c & V_SNAPTOBOTTOM) + y += (vid.height - (BASEVIDHEIGHT * dupy)); + else if (!(c & V_SNAPTOTOP)) + y += (vid.height - (BASEVIDHEIGHT * dupy)) / 2; + } + } + + if (x >= vid.width || y >= vid.height) + return; // off the screen + if (x < 0) { + w += x; + x = 0; + } + if (y < 0) { + h += y; + y = 0; + } + + if (w <= 0 || h <= 0) + return; // zero width/height wouldn't draw anything + if (x + w > vid.width) + w = vid.width-x; + if (y + h > vid.height) + h = vid.height-y; + + dest = screens[0] + y*vid.width + x; + + if ((alphalevel = ((c & V_ALPHAMASK) >> V_ALPHASHIFT))) + { + if (alphalevel == 13) + alphalevel = hudminusalpha[cv_translucenthud.value]; + else if (alphalevel == 14) + alphalevel = 10 - cv_translucenthud.value; + else if (alphalevel == 15) + alphalevel = hudplusalpha[cv_translucenthud.value]; + + if (alphalevel >= 10) + return; // invis + } + + c &= 255; + + if (!alphalevel) { + for (v = 0; v < h; v++, dest += vid.width) { + for (u = 0; u < w; u++) { + dest[u] = consolebgmap[dest[u]]; + } + } + } else { // mpc 12-04-2018 + const UINT8 *fadetable = ((UINT8 *)transtables + ((alphalevel-1)<y) ? y : x + w = clip(w,vid.width); + h = clip(h,vid.height); + for (v = 0; v < h; v++, dest += vid.width) { + for (u = 0; u < w; u++) { + dest[u] = fadetable[consolebgmap[dest[u]]]; + } + } + } +} + // // Fills a box of pixels using a flat texture as a pattern, scaled to screen size. // @@ -1054,6 +1178,32 @@ void V_DrawCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed) V_DrawScaledPatch(x, y, flags, hu_font[c]); } +// Writes a single character for the chat. (draw WHITE if bit 7 set) +// Essentially the same as the above but it's small or big depending on what resolution you've chosen to huge.. +// +void V_DrawChatCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed, UINT8 *colormap) +{ + INT32 w, flags; + //const UINT8 *colormap = V_GetStringColormap(c); + + flags = c & ~(V_CHARCOLORMASK | V_PARAMMASK); + c &= 0x7f; + if (lowercaseallowed) + c -= HU_FONTSTART; + else + c = toupper(c) - HU_FONTSTART; + if (c < 0 || c >= HU_FONTSIZE || !hu_font[c]) + return; + + w = (vid.width < 640 ) ? (SHORT(hu_font[c]->width)/2) : (SHORT(hu_font[c]->width)); // use normal sized characters if we're using a terribly low resolution. + if (x + w > vid.width) + return; + + V_DrawFixedPatch(x*FRACUNIT, y*FRACUNIT, (vid.width < 640) ? (FRACUNIT) : (FRACUNIT/2), flags, hu_font[c], colormap); + + +} + // Precompile a wordwrapped string to any given width. // This is a muuuch better method than V_WORDWRAP. char *V_WordWrap(INT32 x, INT32 w, INT32 option, const char *string) diff --git a/src/v_video.h b/src/v_video.h index 353f84c1d..a8e8d6e67 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -139,6 +139,7 @@ void V_DrawScaledPic (INT32 px1, INT32 py1, INT32 scrn, INT32 lumpnum); // fill a box with a single color void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c); +void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c); // fill a box with a flat as a pattern void V_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatnum); @@ -149,6 +150,8 @@ void V_DrawFadeConsBack(INT32 plines); // draw a single character void V_DrawCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed); +// draw a single character, but for the chat +void V_DrawChatCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed, UINT8 *colormap); void V_DrawLevelTitle(INT32 x, INT32 y, INT32 option, const char *string); From ad187c26f0341e47cbe055f2dc9eca2b8c906755 Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Tue, 31 Jul 2018 15:57:19 +0200 Subject: [PATCH 02/71] Repositionning chat & bugfixes --- src/dehacked.c | 27 -------------------- src/g_game.c | 12 ++------- src/hardware/hw_main.h | 1 - src/hu_stuff.c | 58 ++++++++++++++++++++++++------------------ 4 files changed, 35 insertions(+), 63 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index ac2aa9a85..de5638055 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8286,33 +8286,6 @@ static inline int lib_getenum(lua_State *L) } else if (fastcmp(word, "token")) { lua_pushinteger(L, token); return 1; - } else if (fastcmp(word,"consoleplayer")) { - if (!playeringame[consoleplayer]) - return 0; - LUA_PushUserdata(L, &players[consoleplayer], META_PLAYER); - return 1; - } else if (fastcmp(word,"displayplayer")) { - if (!playeringame[displayplayer]) - return 0; - LUA_PushUserdata(L, &players[displayplayer], META_PLAYER); - return 1; - } else if (fastcmp(word,"secondarydisplayplayer")) { - if (!playeringame[displayplayer]) - return 0; - LUA_PushUserdata(L, &players[secondarydisplayplayer], META_PLAYER); - return 1; - } else if (fastcmp(word, "timelimitintics")) { - lua_pushinteger(L, timelimitintics); - return 1; - } else if (fastcmp(word,"hidetime")) { - lua_pushinteger(L, hidetime); - return 1; - } else if (fastcmp(word, "pointlimit")) { - lua_pushinteger(L, cv_pointlimit.value); - return 1; - } else if (fastcmp(word,"allowjoin")) { - lua_pushboolean(L, cv_allownewplayer.value); - return 1; } return 0; } diff --git a/src/g_game.c b/src/g_game.c index d70a8a30e..734b01f32 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -358,7 +358,7 @@ consvar_t cv_chattime = {"chattime", "8", CV_SAVE, chattime_cons_t, NULL, 0, NUL // chatwidth static CV_PossibleValue_t chatwidth_cons_t[] = {{64, "MIN"}, {150, "MAX"}, {0, NULL}}; -consvar_t cv_chatwidth = {"chatwidth", "150", CV_SAVE, chatwidth_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_chatwidth = {"chatwidth", "128", CV_SAVE, chatwidth_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; // chatheight static CV_PossibleValue_t chatheight_cons_t[] = {{6, "MIN"}, {22, "MAX"}, {0, NULL}}; @@ -1266,10 +1266,6 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics) if ((cmd->forwardmove || cmd->sidemove || cmd->buttons) && displayplayer != consoleplayer) displayplayer = consoleplayer; - - if (playeringame[consoleplayer]) // do not run on title screen. - LUAh_PlayerCmd(player, cmd); // run this hook after we've done everything. Why? Because that way we can check what buttons we're pressing and what we're doing in that frame rather than using last frame's info! - } // like the g_buildticcmd 1 but using mouse2, gamcontrolbis, ... @@ -1564,11 +1560,7 @@ void G_BuildTiccmd2(ticcmd_t *cmd, INT32 realtics) { localangle2 += (cmd->angleturn<<16); cmd->angleturn = (INT16)(localangle2 >> 16); - } - - if (playeringame[consoleplayer]) // do not run on title screen. - LUAh_PlayerCmd(player, cmd); - + } } // User has designated that they want diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index ba809663a..a03be132a 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -71,7 +71,6 @@ void HWR_DrawScreenFinalTexture(int width, int height); // This stuff is put here so MD2's can use them UINT32 HWR_Lighting(INT32 light, UINT32 color, UINT32 fadecolor, boolean fogblockpoly, boolean plane); -UINT32 HWR_NoColormapLighting(INT32 light, UINT32 color, UINT32 fadecolor, boolean fogblockpoly, boolean plane); // do it like cv_grfog off for non colormap stuff FUNCMATH UINT8 LightLevelToLum(INT32 l); extern CV_PossibleValue_t granisotropicmode_cons_t[]; diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 435325767..310fdd176 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -1225,7 +1225,7 @@ char *CHAT_WordWrap(INT32 x, INT32 w, INT32 option, const char *string) // 30/7/18: chaty is now the distance at which the lowest point of the chat will be drawn if that makes any sense. -INT16 chatx = 160, chaty = 192; // let's use this as our coordinates, shh +INT16 chatx = 16, chaty = 172; // let's use this as our coordinates, shh // chat stuff by VincyTM LOL XD! @@ -1325,7 +1325,7 @@ static void HU_drawMiniChat(void) else { UINT8 *colormap = CHAT_GetStringColormap(clrflag); - V_DrawChatCharacter(x + dx + 2, y+dy, msg[j++] |V_SNAPTOBOTTOM|V_SNAPTORIGHT|transflag, !cv_allcaps.value, colormap); + V_DrawChatCharacter(x + dx + 2, y+dy, msg[j++] |V_SNAPTOBOTTOM|V_SNAPTOLEFT|transflag, !cv_allcaps.value, colormap); } dx += charwidth; @@ -1386,14 +1386,14 @@ static void HU_drawChatLog(INT32 offset) if (chat_scroll > chat_maxscroll) chat_scroll = chat_maxscroll; - INT32 charwidth = (vid.width < 640) ? 8 : 4, charheight = (vid.width < 640) ? 8 : 6; + INT32 charwidth = 4, charheight = 6; INT32 x = chatx+2, y = chaty - offset*charheight - (chat_scroll*charheight) - cv_chatheight.value*charheight - 12, dx = 0, dy = 0; size_t i = 0; INT32 chat_topy = y + chat_scroll*charheight; INT32 chat_bottomy = chat_topy + cv_chatheight.value*charheight; boolean atbottom = false; - V_DrawFillConsoleMap(chatx, chat_topy, cv_chatwidth.value, cv_chatheight.value*charheight +2, 239|V_SNAPTOBOTTOM|V_SNAPTORIGHT); // log box + V_DrawFillConsoleMap(chatx, chat_topy, cv_chatwidth.value, cv_chatheight.value*charheight +2, 239|V_SNAPTOBOTTOM|V_SNAPTOLEFT); // log box for (i=0; i= chat_topy) && (y+dy < (chat_bottomy))) { UINT8 *colormap = CHAT_GetStringColormap(clrflag); - V_DrawChatCharacter(x + dx + 2, y+dy+2, msg[j++] |V_SNAPTOBOTTOM|V_SNAPTORIGHT, !cv_allcaps.value, colormap); + V_DrawChatCharacter(x + dx + 2, y+dy+2, msg[j++] |V_SNAPTOBOTTOM|V_SNAPTOLEFT, !cv_allcaps.value, colormap); } else j++; // don't forget to increment this or we'll get stuck in the limbo. @@ -1460,9 +1460,9 @@ static void HU_drawChatLog(INT32 offset) // draw arrows to indicate that we can (or not) scroll. if (chat_scroll > 0) - HU_DrawUpArrow(chatx-8, ((justscrolledup) ? (chat_topy-1) : (chat_topy)), V_SNAPTOBOTTOM | V_SNAPTORIGHT); + HU_DrawUpArrow(chatx-8, ((justscrolledup) ? (chat_topy-1) : (chat_topy)), V_SNAPTOBOTTOM | V_SNAPTOLEFT); if (chat_scroll < chat_maxscroll) - HU_DrawDownArrow(chatx-8, chat_bottomy-((justscrolleddown) ? 3 : 4), V_SNAPTOBOTTOM | V_SNAPTORIGHT); + HU_DrawDownArrow(chatx-8, chat_bottomy-((justscrolleddown) ? 3 : 4), V_SNAPTOBOTTOM | V_SNAPTOLEFT); justscrolleddown = false; justscrolledup = false; @@ -1477,8 +1477,8 @@ static void HU_drawChatLog(INT32 offset) static INT16 typelines = 1; // number of drawfill lines we need. it's some weird hack and might be one frame off but I'm lazy to make another loop. static void HU_DrawChat(void) { - INT32 charwidth = (vid.width < 640) ? 8 : 4, charheight = (vid.width < 640) ? 8 : 6; - INT32 t = 0, c = 0, y = chaty - ((vid.width < 640 ) ? (typelines*charheight+2) : (typelines*charheight)); + INT32 charwidth = 4, charheight = 6; + INT32 t = 0, c = 0, y = chaty - (typelines*charheight); size_t i = 0; const char *ntalk = "Say: ", *ttalk = "Team: "; const char *talk = ntalk; @@ -1494,14 +1494,14 @@ static void HU_DrawChat(void) #endif } - V_DrawFillConsoleMap(chatx, y-1, cv_chatwidth.value, (vid.width < 640 ) ? (typelines*charheight+2) : (typelines*charheight), 239 | V_SNAPTOBOTTOM | V_SNAPTORIGHT); + V_DrawFillConsoleMap(chatx, y-1, cv_chatwidth.value, (typelines*charheight), 239 | V_SNAPTOBOTTOM | V_SNAPTOLEFT); while (talk[i]) { if (talk[i] < HU_FONTSTART) ++i; else - V_DrawChatCharacter(chatx + c + 2, y, talk[i++] |V_SNAPTOBOTTOM|V_SNAPTORIGHT, !cv_allcaps.value, NULL); + V_DrawChatCharacter(chatx + c + 2, y, talk[i++] |V_SNAPTOBOTTOM|V_SNAPTOLEFT, !cv_allcaps.value, NULL); c += charwidth; } @@ -1510,26 +1510,34 @@ static void HU_DrawChat(void) typelines = 1; if ((strlen(w_chat) == 0 || c_input == 0) && hu_tick < 4) - V_DrawChatCharacter(chatx + 2 + c, y+1, '_' |V_SNAPTOBOTTOM|V_SNAPTORIGHT|t, !cv_allcaps.value, NULL); - + V_DrawChatCharacter(chatx + 2 + c, y+1, '_' |V_SNAPTOBOTTOM|V_SNAPTOLEFT|t, !cv_allcaps.value, NULL); + while (w_chat[i]) { - - if (c_input == (i+1) && hu_tick < 4) + boolean skippedline = false; + if (c_input == (i+1)) { - int cursorx = (c+charwidth < cv_chatwidth.value-charwidth) ? (chatx + 2 + c+charwidth) : (chatx); // we may have to go down. - int cursory = (cursorx != chatx) ? (y) : (y+charheight); - V_DrawChatCharacter(cursorx, cursory+1, '_' |V_SNAPTOBOTTOM|V_SNAPTORIGHT|t, !cv_allcaps.value, NULL); + int cursorx = (c+charwidth < cv_chatwidth.value-charwidth) ? (chatx + 2 + c+charwidth) : (chatx+1); // we may have to go down. + int cursory = (cursorx != chatx+1) ? (y) : (y+charheight); + if (hu_tick < 4) + V_DrawChatCharacter(cursorx, cursory+1, '_' |V_SNAPTOBOTTOM|V_SNAPTOLEFT|t, !cv_allcaps.value, NULL); + + if (cursorx == chatx+1) // a weirdo hack + { + typelines += 1; + skippedline = true; + } + } //Hurdler: isn't it better like that? if (w_chat[i] < HU_FONTSTART) ++i; else - V_DrawChatCharacter(chatx + c + 2, y, w_chat[i++] | V_SNAPTOBOTTOM|V_SNAPTORIGHT | t, !cv_allcaps.value, NULL); + V_DrawChatCharacter(chatx + c + 2, y, w_chat[i++] | V_SNAPTOBOTTOM|V_SNAPTOLEFT | t, !cv_allcaps.value, NULL); c += charwidth; - if (c > cv_chatwidth.value-charwidth) + if (c > cv_chatwidth.value-(charwidth*2) && !skippedline) { c = 0; y += charheight; @@ -1587,19 +1595,19 @@ static void HU_DrawChat(void) } } - if (1 || (playeringame[i])) + if (playeringame[i]) { char name[MAXPLAYERNAME+1]; strlcpy(name, player_names[i], 7); // shorten name to 7 characters. - V_DrawFillConsoleMap(chatx-50, p_dispy- (6*count), 48, 6, 239 | V_SNAPTOBOTTOM | V_SNAPTORIGHT); // fill it like the chat so the text doesn't become hard to read because of the hud. - V_DrawSmallString(chatx-48, p_dispy- (6*count), V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_ALLOWLOWERCASE, va("\x82%d\x80 - %s", i, name)); + V_DrawFillConsoleMap(chatx+ cv_chatwidth.value + 2, p_dispy- (6*count), 48, 6, 239 | V_SNAPTOBOTTOM | V_SNAPTOLEFT); // fill it like the chat so the text doesn't become hard to read because of the hud. + V_DrawSmallString(chatx+ cv_chatwidth.value + 4, p_dispy- (6*count), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, va("\x82%d\x80 - %s", i, name)); count++; } } if (count == 0) // no results. { - V_DrawFillConsoleMap(chatx-50, p_dispy- (6*count), 48, 6, 239 | V_SNAPTOBOTTOM | V_SNAPTORIGHT); // fill it like the chat so the text doesn't become hard to read because of the hud. - V_DrawSmallString(chatx-48, p_dispy- (6*count), V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_ALLOWLOWERCASE, "NO RESULT."); + V_DrawFillConsoleMap(chatx-50, p_dispy- (6*count), 48, 6, 239 | V_SNAPTOBOTTOM | V_SNAPTOLEFT); // fill it like the chat so the text doesn't become hard to read because of the hud. + V_DrawSmallString(chatx-48, p_dispy- (6*count), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, "NO RESULT."); } } From 03dc4c968095dc6847fb4e68c1a4af31afb78728 Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Tue, 31 Jul 2018 23:56:23 +0200 Subject: [PATCH 03/71] Fixed sub 400p chat for console --- src/console.c | 2 +- src/hu_stuff.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/console.c b/src/console.c index 357f1ef84..0adde1d13 100644 --- a/src/console.c +++ b/src/console.c @@ -1443,7 +1443,7 @@ static void CON_DrawHudlines(void) if (con_hudlines <= 0) return; - if (chat_on && cv_consolechat.value) + if (chat_on && (cv_consolechat.value || vid.width < 640)) y = charheight; // leave place for chat input in the first row of text (only do it if consolechat is on.) else y = 0; diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 310fdd176..5544e0755 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -1860,7 +1860,7 @@ void HU_Drawer(void) // count down the scroll timer. if (chat_scrolltime > 0) chat_scrolltime--; - if (!cv_consolechat.value && vid.width >= 640) // don't even bother with 200p + if (!cv_consolechat.value && vid.width > 320) // don't even bother with 200p HU_DrawChat(); else HU_DrawChat_Old(); // why the fuck......................... From 8747a8529d60a074acacf8b6d8c858644309703f Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Sun, 19 Aug 2018 10:58:29 +0200 Subject: [PATCH 04/71] Changed chat position, Added chat back tint Fixed word wrapping glitches --- src/d_netcmd.c | 1 + src/g_game.c | 3 + src/g_game.h | 2 +- src/hu_stuff.c | 193 ++++++++++++++++++++++++++----------------------- src/m_menu.c | 13 ++-- 5 files changed, 116 insertions(+), 96 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index dbd26a738..895ad3084 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -684,6 +684,7 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_chatwidth); CV_RegisterVar(&cv_chattime); CV_RegisterVar(&cv_chatspamprotection); + CV_RegisterVar(&cv_chatbacktint); CV_RegisterVar(&cv_consolechat); CV_RegisterVar(&cv_chatnotifications); CV_RegisterVar(&cv_crosshair); diff --git a/src/g_game.c b/src/g_game.c index 734b01f32..d0141b2b1 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -370,6 +370,9 @@ consvar_t cv_chatnotifications= {"chatnotifications", "On", CV_SAVE, CV_OnOff, N // chat spam protection (why would you want to disable that???) consvar_t cv_chatspamprotection= {"chatspamprotection", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +// minichat text background +consvar_t cv_chatbacktint = {"chatbacktint", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; + // old shit console chat. (mostly exists for stuff like terminal, not because I cared if anyone liked the old chat.) consvar_t cv_consolechat= {"consolechat", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; diff --git a/src/g_game.h b/src/g_game.h index cd0a71f22..83e70b640 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -54,7 +54,7 @@ extern tic_t timeinmap; // Ticker for time spent in level (used for levelcard di extern INT16 rw_maximums[NUM_WEAPONS]; // used in game menu -extern consvar_t cv_chatwidth, cv_chatnotifications, cv_chatheight, cv_chattime, cv_consolechat, cv_chatspamprotection, cv_compactscoreboard; +extern consvar_t cv_chatwidth, cv_chatnotifications, cv_chatheight, cv_chattime, cv_consolechat, cv_chatbacktint, cv_chatspamprotection, cv_compactscoreboard; extern consvar_t cv_crosshair, cv_crosshair2; extern consvar_t cv_invertmouse, cv_alwaysfreelook, cv_mousemove; extern consvar_t cv_sideaxis,cv_turnaxis,cv_moveaxis,cv_lookaxis,cv_fireaxis,cv_firenaxis; diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 5544e0755..e8940a192 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -1223,9 +1223,10 @@ char *CHAT_WordWrap(INT32 x, INT32 w, INT32 option, const char *string) return newstring; } + // 30/7/18: chaty is now the distance at which the lowest point of the chat will be drawn if that makes any sense. -INT16 chatx = 16, chaty = 172; // let's use this as our coordinates, shh +INT16 chatx = 13, chaty = 169; // let's use this as our coordinates, shh // chat stuff by VincyTM LOL XD! @@ -1233,34 +1234,37 @@ INT16 chatx = 16, chaty = 172; // let's use this as our coordinates, shh static void HU_drawMiniChat(void) { - if (!chat_nummsg_min) return; // needless to say it's useless to do anything if we don't have anything to draw. - - - INT32 x = chatx+2; - INT32 charwidth = 4, charheight = 6; + + INT32 x = chatx+2; + INT32 charwidth = 4, charheight = 6; INT32 dx = 0, dy = 0; size_t i = chat_nummsg_min; - + boolean prev_linereturn = false; // a hack to prevent double \n while I have no idea why they happen in the first place. + INT32 msglines = 0; // process all messages once without rendering anything or doing anything fancy so that we know how many lines each message has... - + for (; i>0; i--) - { - const char *msg = CHAT_WordWrap(x, cv_chatwidth.value-charwidth, V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_mini[i-1]); + { + const char *msg = CHAT_WordWrap(x+2, cv_chatwidth.value-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_mini[i-1]); size_t j = 0; INT32 linescount = 0; - + while(msg[j]) // iterate through msg - { + { if (msg[j] < HU_FONTSTART) // don't draw - { + { if (msg[j] == '\n') // get back down. { ++j; - linescount += 1; - dx = 0; + if (!prev_linereturn) + { + linescount += 1; + dx = 0; + } + prev_linereturn = true; continue; } else if (msg[j] & 0x80) // stolen from video.c, nice. @@ -1268,14 +1272,14 @@ static void HU_drawMiniChat(void) ++j; continue; } - - ++j; + + ++j; } else { j++; } - + prev_linereturn = false; dx += charwidth; if (dx >= cv_chatwidth.value) { @@ -1287,30 +1291,34 @@ static void HU_drawMiniChat(void) dx = 0; msglines += linescount+1; } - + INT32 y = chaty - charheight*(msglines+1); - dx = 0; + dx = 0; dy = 0; i = 0; - + prev_linereturn = false; + for (; i<=(chat_nummsg_min-1); i++) // iterate through our hot messages { - INT32 clrflag = 0; - INT32 timer = ((cv_chattime.value*TICRATE)-chat_timers[i]) - cv_chattime.value*TICRATE+9; // see below... + INT32 timer = ((cv_chattime.value*TICRATE)-chat_timers[i]) - cv_chattime.value*TICRATE+9; // see below... INT32 transflag = (timer >= 0 && timer <= 9) ? (timer*V_10TRANS) : 0; // you can make bad jokes out of this one. size_t j = 0; - const char *msg = CHAT_WordWrap(x, cv_chatwidth.value-charwidth, V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_mini[i]); // get the current message, and word wrap it. - + const char *msg = CHAT_WordWrap(x+2, cv_chatwidth.value-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_mini[i]); // get the current message, and word wrap it. + while(msg[j]) // iterate through msg - { + { if (msg[j] < HU_FONTSTART) // don't draw - { + { if (msg[j] == '\n') // get back down. { ++j; - dy += charheight; - dx = 0; + if (!prev_linereturn) + { + dy += charheight; + dx = 0; + } + prev_linereturn = true; continue; } else if (msg[j] & 0x80) // stolen from video.c, nice. @@ -1319,16 +1327,21 @@ static void HU_drawMiniChat(void) ++j; continue; } - - ++j; + + ++j; } else { UINT8 *colormap = CHAT_GetStringColormap(clrflag); + + if (cv_chatbacktint.value) // on request of wolfy + V_DrawFillConsoleMap(x + dx + 2, y+dy, charwidth, charheight, 239|V_SNAPTOBOTTOM|V_SNAPTOLEFT); + V_DrawChatCharacter(x + dx + 2, y+dy, msg[j++] |V_SNAPTOBOTTOM|V_SNAPTOLEFT|transflag, !cv_allcaps.value, colormap); } - + dx += charwidth; + prev_linereturn = false; if (dx >= cv_chatwidth.value) { dx = 0; @@ -1338,10 +1351,10 @@ static void HU_drawMiniChat(void) dy += charheight; dx = 0; } - + // decrement addy and make that shit smooth: addy /= 2; - + } // HU_DrawUpArrow @@ -1381,29 +1394,29 @@ static void HU_DrawDownArrow(INT32 x, INT32 y, INT32 options) static void HU_drawChatLog(INT32 offset) { - + // before we do anything, make sure that our scroll position isn't "illegal"; if (chat_scroll > chat_maxscroll) chat_scroll = chat_maxscroll; - + INT32 charwidth = 4, charheight = 6; INT32 x = chatx+2, y = chaty - offset*charheight - (chat_scroll*charheight) - cv_chatheight.value*charheight - 12, dx = 0, dy = 0; - size_t i = 0; + UINT32 i = 0; INT32 chat_topy = y + chat_scroll*charheight; INT32 chat_bottomy = chat_topy + cv_chatheight.value*charheight; boolean atbottom = false; - + V_DrawFillConsoleMap(chatx, chat_topy, cv_chatwidth.value, cv_chatheight.value*charheight +2, 239|V_SNAPTOBOTTOM|V_SNAPTOLEFT); // log box - + for (i=0; i= chat_topy) && (y+dy < (chat_bottomy))) - { + { UINT8 *colormap = CHAT_GetStringColormap(clrflag); V_DrawChatCharacter(x + dx + 2, y+dy+2, msg[j++] |V_SNAPTOBOTTOM|V_SNAPTOLEFT, !cv_allcaps.value, colormap); } else j++; // don't forget to increment this or we'll get stuck in the limbo. } - + dx += charwidth; if (dx >= cv_chatwidth.value-charwidth-2 && i= HU_FONTSTART) // end of message shouldn't count, nor should invisible characters!!!! { @@ -1441,32 +1454,34 @@ static void HU_drawChatLog(INT32 offset) dy += charheight; dx = 0; } - + if (((chat_scroll >= chat_maxscroll) || (chat_scrollmedown)) && !(justscrolleddown || justscrolledup || chat_scrolltime)) // was already at the bottom of the page before new maxscroll calculation and was NOT scrolling. { atbottom = true; // we should scroll } chat_scrollmedown = false; - + // getmaxscroll through a lazy hack. We do all these loops, so let's not do more loops that are gonna lag the game more. :P - chat_maxscroll = (dy/charheight)-cv_chatheight.value; // welcome to C, we don't know what min() and max() are. - if (chat_maxscroll < 0) + chat_maxscroll = (dy/charheight); // welcome to C, we don't know what min() and max() are. + if (chat_maxscroll <= (UINT32)cv_chatheight.value) chat_maxscroll = 0; - + else + chat_maxscroll -= cv_chatheight.value; + // if we're not bound by the time, autoscroll for next frame: if (atbottom) chat_scroll = chat_maxscroll; - + // draw arrows to indicate that we can (or not) scroll. - + if (chat_scroll > 0) HU_DrawUpArrow(chatx-8, ((justscrolledup) ? (chat_topy-1) : (chat_topy)), V_SNAPTOBOTTOM | V_SNAPTOLEFT); if (chat_scroll < chat_maxscroll) HU_DrawDownArrow(chatx-8, chat_bottomy-((justscrolleddown) ? 3 : 4), V_SNAPTOBOTTOM | V_SNAPTOLEFT); - + justscrolleddown = false; justscrolledup = false; -} +} // // HU_DrawChat @@ -1476,13 +1491,13 @@ static void HU_drawChatLog(INT32 offset) static INT16 typelines = 1; // number of drawfill lines we need. it's some weird hack and might be one frame off but I'm lazy to make another loop. static void HU_DrawChat(void) -{ +{ INT32 charwidth = 4, charheight = 6; INT32 t = 0, c = 0, y = chaty - (typelines*charheight); - size_t i = 0; + UINT32 i = 0; const char *ntalk = "Say: ", *ttalk = "Team: "; const char *talk = ntalk; - + if (teamtalk) { talk = ttalk; @@ -1493,9 +1508,9 @@ static void HU_DrawChat(void) t = 0x400; // Blue #endif } - + V_DrawFillConsoleMap(chatx, y-1, cv_chatwidth.value, (typelines*charheight), 239 | V_SNAPTOBOTTOM | V_SNAPTOLEFT); - + while (talk[i]) { if (talk[i] < HU_FONTSTART) @@ -1505,13 +1520,13 @@ static void HU_DrawChat(void) c += charwidth; } - + i = 0; typelines = 1; - + if ((strlen(w_chat) == 0 || c_input == 0) && hu_tick < 4) V_DrawChatCharacter(chatx + 2 + c, y+1, '_' |V_SNAPTOBOTTOM|V_SNAPTOLEFT|t, !cv_allcaps.value, NULL); - + while (w_chat[i]) { boolean skippedline = false; @@ -1520,16 +1535,16 @@ static void HU_DrawChat(void) int cursorx = (c+charwidth < cv_chatwidth.value-charwidth) ? (chatx + 2 + c+charwidth) : (chatx+1); // we may have to go down. int cursory = (cursorx != chatx+1) ? (y) : (y+charheight); if (hu_tick < 4) - V_DrawChatCharacter(cursorx, cursory+1, '_' |V_SNAPTOBOTTOM|V_SNAPTOLEFT|t, !cv_allcaps.value, NULL); - + V_DrawChatCharacter(cursorx, cursory+1, '_' |V_SNAPTOBOTTOM|V_SNAPTOLEFT|t, !cv_allcaps.value, NULL); + if (cursorx == chatx+1) // a weirdo hack { typelines += 1; skippedline = true; - } - - } - + } + + } + //Hurdler: isn't it better like that? if (w_chat[i] < HU_FONTSTART) ++i; @@ -1547,56 +1562,56 @@ static void HU_DrawChat(void) // handle /pm list. if (strnicmp(w_chat, "/pm", 3) == 0 && vid.width >= 400 && !teamtalk) // 320x200 unsupported kthxbai - { + { i = 0; - int count = 0; + INT32 count = 0; INT32 p_dispy = chaty - charheight -1; for(i=0; (i '9'))) || ((w_chat[4] != 0) && (((w_chat[4] < '0') || (w_chat[4] > '9'))))) && (w_chat[4] != ' ')) break; - - + + char *nodenum = (char*) malloc(3); strncpy(nodenum, w_chat+3, 4); - INT32 n = atoi((const char*) nodenum); // turn that into a number + UINT32 n = atoi((const char*) nodenum); // turn that into a number // special cases: - + if ((n == 0) && !(w_chat[4] == '0')) - { + { if (!(i<10)) - continue; + continue; } else if ((n == 1) && !(w_chat[3] == '0')) - { + { if (!((i == 1) || ((i >= 10) && (i <= 19)))) continue; } else if ((n == 2) && !(w_chat[3] == '0')) - { + { if (!((i == 2) || ((i >= 20) && (i <= 29)))) continue; } else if ((n == 3) && !(w_chat[3] == '0')) - { + { if (!((i == 3) || ((i >= 30) && (i <= 31)))) continue; } else // general case. - { + { if (i != n) continue; } } - + if (playeringame[i]) - { + { char name[MAXPLAYERNAME+1]; strlcpy(name, player_names[i], 7); // shorten name to 7 characters. V_DrawFillConsoleMap(chatx+ cv_chatwidth.value + 2, p_dispy- (6*count), 48, 6, 239 | V_SNAPTOBOTTOM | V_SNAPTOLEFT); // fill it like the chat so the text doesn't become hard to read because of the hud. @@ -1608,11 +1623,11 @@ static void HU_DrawChat(void) { V_DrawFillConsoleMap(chatx-50, p_dispy- (6*count), 48, 6, 239 | V_SNAPTOBOTTOM | V_SNAPTOLEFT); // fill it like the chat so the text doesn't become hard to read because of the hud. V_DrawSmallString(chatx-48, p_dispy- (6*count), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, "NO RESULT."); - } + } } - + HU_drawChatLog(typelines-1); // typelines is the # of lines we're typing. If there's more than 1 then the log should scroll up to give us more space. - + } // why the fuck would you use this... diff --git a/src/m_menu.c b/src/m_menu.c index 80172216b..edc11ffe7 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1306,12 +1306,13 @@ static menuitem_t OP_GameOptionsMenu[] = static menuitem_t OP_ChatOptionsMenu[] = { - {IT_STRING | IT_CVAR, NULL, "Chat Width", &cv_chatwidth, 10}, - {IT_STRING | IT_CVAR, NULL, "Chat Height", &cv_chatheight, 20}, - {IT_STRING | IT_CVAR, NULL, "Message Timer", &cv_chattime, 30}, - {IT_STRING | IT_CVAR, NULL, "Chat Notifications", &cv_chatnotifications, 40}, - {IT_STRING | IT_CVAR, NULL, "Spam Protection", &cv_chatspamprotection, 50}, - {IT_STRING | IT_CVAR, NULL, "Old Console Chat", &cv_consolechat, 60}, + {IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Chat Box Width", &cv_chatwidth, 10}, + {IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Chat Box Height", &cv_chatheight, 20}, + {IT_STRING | IT_CVAR, NULL, "Message Fadeout Time", &cv_chattime, 30}, + {IT_STRING | IT_CVAR, NULL, "Chat Notifications", &cv_chatnotifications, 40}, + {IT_STRING | IT_CVAR, NULL, "Spam Protection", &cv_chatspamprotection, 50}, + {IT_STRING | IT_CVAR, NULL, "Chat background tint", &cv_chatbacktint, 60}, + {IT_STRING | IT_CVAR, NULL, "Old Console Chat", &cv_consolechat, 70}, }; static menuitem_t OP_ServerOptionsMenu[] = From b09019dc4a676227a31030672b86c8f2405b0d93 Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Sun, 19 Aug 2018 11:12:21 +0200 Subject: [PATCH 05/71] Fix old chat detection. --- src/console.c | 2 +- src/hu_stuff.c | 8 ++++---- src/hu_stuff.h | 1 + src/lua_baselib.c | 4 ++-- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/console.c b/src/console.c index 0adde1d13..505ab8312 100644 --- a/src/console.c +++ b/src/console.c @@ -1443,7 +1443,7 @@ static void CON_DrawHudlines(void) if (con_hudlines <= 0) return; - if (chat_on && (cv_consolechat.value || vid.width < 640)) + if (chat_on && OLDCHAT) y = charheight; // leave place for chat input in the first row of text (only do it if consolechat is on.) else y = 0; diff --git a/src/hu_stuff.c b/src/hu_stuff.c index e8940a192..4142e8d84 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -778,7 +778,7 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) } - if (cv_consolechat.value) + if OLDCHAT { CONS_Printf(fmt, prefix, cstart, dispname, cend, msg); HU_AddChatText(va(fmt2, prefix, cstart, dispname, cend, msg)); // add it reguardless, in case we decide to change our mind about our chat type. @@ -1875,14 +1875,14 @@ void HU_Drawer(void) // count down the scroll timer. if (chat_scrolltime > 0) chat_scrolltime--; - if (!cv_consolechat.value && vid.width > 320) // don't even bother with 200p + if (!OLDCHAT) HU_DrawChat(); else HU_DrawChat_Old(); // why the fuck......................... } else { - if (!cv_consolechat.value) + if (!OLDCHAT) { HU_drawMiniChat(); // draw messages in a cool fashion. chat_scrolltime = 0; // do scroll anyway. @@ -2005,7 +2005,7 @@ void HU_Erase(void) // clear the message lines that go away, so use _oldclearlines_ bottomline = oldclearlines; oldclearlines = con_clearlines; - if (chat_on && cv_consolechat.value) + if (chat_on && OLDCHAT) if (bottomline < 8) bottomline = 8; // only do it for consolechat. consolechat is gay. diff --git a/src/hu_stuff.h b/src/hu_stuff.h index c288b9480..f8fcd3756 100644 --- a/src/hu_stuff.h +++ b/src/hu_stuff.h @@ -80,6 +80,7 @@ extern patch_t *tallminus; } chatmsg_t;*/ #define CHAT_BUFSIZE 64 // that's enough messages, right? We'll delete the older ones when that gets out of hand. +#define OLDCHAT (cv_consolechat.value || dedicated || !netgame || vid.width < 640) // some functions void HU_AddChatText(const char *text); diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 575b44520..41bfd0083 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -96,7 +96,7 @@ static int lib_chatprint(lua_State *L) if (len > 255) // string is too long!!! return luaL_error(L, "String exceeds the 255 characters limit of the chat buffer."); - if (cv_consolechat.value || !netgame) + if (OLDCHAT) CONS_Printf("%s\n", str); else HU_AddChatText(str); @@ -124,7 +124,7 @@ static int lib_chatprintf(lua_State *L) if (len > 255) // string is too long!!! return luaL_error(L, "String exceeds the 255 characters limit of the chat buffer."); - if (cv_consolechat.value || !netgame) + if (OLDCHAT) CONS_Printf("%s\n", str); else HU_AddChatText(str); From 40b4d63620a4f78994922bb323b01ae4dd631556 Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Sun, 19 Aug 2018 11:25:20 +0200 Subject: [PATCH 06/71] Fix capslock being wonky. --- src/console.c | 7 ++++++- src/hu_stuff.c | 14 +++++++++----- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/console.c b/src/console.c index 505ab8312..c9e3c357e 100644 --- a/src/console.c +++ b/src/console.c @@ -1048,7 +1048,12 @@ boolean CON_Responder(event_t *ev) return true; } - if (capslock ^ shiftdown) // gets capslock to work because capslock is cool + if (key >= 'a' && key <= 'z') + { + if (capslock ^ shiftdown) + key = shiftxform[key]; + } + else if (shiftdown) key = shiftxform[key]; // enter a char into the command prompt diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 4142e8d84..d191874bd 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -1057,12 +1057,16 @@ boolean HU_Responder(event_t *ev) return true; } - // use console translations - if (shiftdown ^ capslock) + // use console translations + + if (c >= 'a' && c <= 'z') + { + if (capslock ^ shiftdown) + c = shiftxform[c]; + } + else if (shiftdown) c = shiftxform[c]; - - // TODO: make chat behave like the console, so that we can go back and edit stuff when we fuck up. - + // pasting. pasting is cool. chat is a bit limited, though :( if ((c == 'v' || c == 'V') && ctrldown) { From b32f50648d8641ac6627201b7df89b4ed6a8aded Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 15 Dec 2018 20:46:42 -0500 Subject: [PATCH 07/71] Merge branch 'addons_menu' into 'master' Addons menu See merge request KartKrew/Kart!8 --- src/console.c | 4 + src/d_clisrv.h | 3 +- src/d_main.c | 37 ++- src/d_netcmd.c | 45 ++-- src/d_netfil.c | 81 ++----- src/d_netfil.h | 1 - src/filesrch.c | 473 ++++++++++++++++++++++++++++++++++++- src/filesrch.h | 68 ++++++ src/m_menu.c | 619 ++++++++++++++++++++++++++++++++++++++++++++++++- src/m_menu.h | 5 + src/p_setup.c | 3 + src/v_video.c | 7 + src/w_wad.c | 76 +++--- src/w_wad.h | 1 + 14 files changed, 1285 insertions(+), 138 deletions(-) diff --git a/src/console.c b/src/console.c index 2c148bc69..79f2c8c48 100644 --- a/src/console.c +++ b/src/console.c @@ -33,6 +33,7 @@ #include "i_system.h" #include "d_main.h" #include "m_menu.h" +#include "filesrch.h" #ifdef _WINDOWS #include "win32/win_main.h" @@ -1261,12 +1262,15 @@ void CONS_Alert(alerttype_t level, const char *fmt, ...) switch (level) { case CONS_NOTICE: + // no notice for notices, hehe CONS_Printf("\x83" "%s" "\x80 ", M_GetText("NOTICE:")); break; case CONS_WARNING: + refreshdirmenu |= REFRESHDIR_WARNING; CONS_Printf("\x82" "%s" "\x80 ", M_GetText("WARNING:")); break; case CONS_ERROR: + refreshdirmenu |= REFRESHDIR_ERROR; CONS_Printf("\x85" "%s" "\x80 ", M_GetText("ERROR:")); break; } diff --git a/src/d_clisrv.h b/src/d_clisrv.h index fc15d0567..5d0861276 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -309,6 +309,7 @@ typedef struct } ATTRPACK clientconfig_pak; #define MAXSERVERNAME 32 +#define MAXFILENEEDED 915 // This packet is too large typedef struct { @@ -330,7 +331,7 @@ typedef struct unsigned char mapmd5[16]; UINT8 actnum; UINT8 iszone; - UINT8 fileneeded[915]; // is filled with writexxx (byteptr.h) + UINT8 fileneeded[MAXFILENEEDED]; // is filled with writexxx (byteptr.h) } ATTRPACK serverinfo_pak; typedef struct diff --git a/src/d_main.c b/src/d_main.c index 23835136a..2ee0afae7 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -74,6 +74,7 @@ int snprintf(char *str, size_t n, const char *fmt, ...); #include "m_cond.h" // condition initialization #include "fastcmp.h" #include "keys.h" +#include "filesrch.h" // refreshdirmenu, mainwadstally #ifdef CMAKECONFIG #include "config.h" @@ -586,6 +587,8 @@ void D_SRB2Loop(void) realtics = entertic - oldentertics; oldentertics = entertic; + refreshdirmenu = 0; // not sure where to put this, here as good as any? + #ifdef DEBUGFILE if (!realtics) if (debugload) @@ -855,12 +858,17 @@ static void IdentifyVersion(void) #else const char *musicfile = "music.dta"; #endif - const char *musicpath = va(pandf,srb2waddir,musicfile); - int ms = W_VerifyNMUSlumps(musicpath); // Don't forget the music! - if (ms == 1) - D_AddFile(musicpath); - else if (ms == 0) - I_Error("File %s has been modified with non-music lumps",musicfile); +#define MUSICTEST(str) \ + {\ + const char *musicpath = va(pandf,srb2waddir,str);\ + int ms = W_VerifyNMUSlumps(musicpath); \ + if (ms == 1) \ + D_AddFile(musicpath); \ + else if (ms == 0) \ + I_Error("File "str" has been modified with non-music/sound lumps"); \ + } + + MUSICTEST("music.dta") } #endif } @@ -1136,6 +1144,8 @@ void D_SRB2Main(void) #endif D_CleanFile(); + mainwads = 0; + #ifndef DEVELOP // md5s last updated 12/14/14 // Check MD5s of autoloaded files @@ -1146,15 +1156,20 @@ void D_SRB2Main(void) #ifdef USE_PATCH_DTA W_VerifyFileMD5(4, ASSET_HASH_PATCH_DTA); // patch.dta #endif - + mainwads++; // srb2.srb + mainwads++; // zones.dta + mainwads++; // player.dta + mainwads++; // rings.dta // don't check music.dta because people like to modify it, and it doesn't matter if they do // ...except it does if they slip maps in there, and that's what W_VerifyNMUSlumps is for. +#else +#ifdef USE_PATCH_DTA + mainwads++; // patch.dta +#endif + mainwads++; // music.dta #endif //ifndef DEVELOP - mainwads = 4; // there are 4 wads not to unload -#ifdef USE_PATCH_DTA - ++mainwads; // patch.dta adds one more -#endif + mainwadstally = packetsizetally; cht_Init(); diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 16788baeb..a452e0b72 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -38,6 +38,7 @@ #include "d_main.h" #include "m_random.h" #include "f_finale.h" +#include "filesrch.h" #include "mserv.h" #include "md5.h" #include "z_zone.h" @@ -689,6 +690,14 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_firenaxis); CV_RegisterVar(&cv_firenaxis2); + // filesrch.c + CV_RegisterVar(&cv_addons_option); + CV_RegisterVar(&cv_addons_folder); + CV_RegisterVar(&cv_addons_md5); + CV_RegisterVar(&cv_addons_showall); + CV_RegisterVar(&cv_addons_search_type); + CV_RegisterVar(&cv_addons_search_case); + // WARNING: the order is important when initialising mouse2 // we need the mouse2port CV_RegisterVar(&cv_mouse2port); @@ -3018,25 +3027,12 @@ static void Command_Addfile(void) break; ++p; // check total packet size and no of files currently loaded + // See W_LoadWadFile in w_wad.c + if ((numwadfiles >= MAX_WADFILES) + || ((packetsizetally + nameonlylength(fn) + 22) > MAXFILENEEDED*sizeof(UINT8))) { - size_t packetsize = 0; - serverinfo_pak *dummycheck = NULL; - - // Shut the compiler up. - (void)dummycheck; - - // See W_LoadWadFile in w_wad.c - for (i = 0; i < numwadfiles; i++) - packetsize += nameonlylength(wadfiles[i]->filename) + 22; - - packetsize += nameonlylength(fn) + 22; - - if ((numwadfiles >= MAX_WADFILES) - || (packetsize > sizeof(dummycheck->fileneeded))) - { - CONS_Alert(CONS_ERROR, M_GetText("Too many files loaded to add %s\n"), fn); - return; - } + CONS_Alert(CONS_ERROR, M_GetText("Too many files loaded to add %s\n"), fn); + return; } WRITESTRINGN(buf_p,p,240); @@ -3153,13 +3149,8 @@ static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum) } // See W_LoadWadFile in w_wad.c - for (i = 0; i < numwadfiles; i++) - packetsize += nameonlylength(wadfiles[i]->filename) + 22; - - packetsize += nameonlylength(filename) + 22; - if ((numwadfiles >= MAX_WADFILES) - || (packetsize > sizeof(dummycheck->fileneeded))) + || ((packetsizetally + nameonlylength(filename) + 22) > MAXFILENEEDED*sizeof(UINT8))) toomany = true; else ncs = findfile(filename,md5sum,true); @@ -3342,6 +3333,9 @@ static void Command_Playintro_f(void) if (netgame) return; + if (dirmenu) + closefilemenu(true); + F_StartIntro(); } @@ -3899,6 +3893,9 @@ void Command_ExitGame_f(void) cv_debug = 0; emeralds = 0; + if (dirmenu) + closefilemenu(true); + if (!modeattacking) D_StartTitle(); } diff --git a/src/d_netfil.c b/src/d_netfil.c index 7c4806580..1cc789ee7 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -104,6 +104,7 @@ INT32 lastfilenum = -1; /** Fills a serverinfo packet with information about wad files loaded. * * \todo Give this function a better name since it is in global scope. + * Used to have size limiting built in - now handed via W_LoadWadFile in w_wad.c * */ UINT8 *PutFileNeeded(void) @@ -112,29 +113,22 @@ UINT8 *PutFileNeeded(void) UINT8 *p = netbuffer->u.serverinfo.fileneeded; char wadfilename[MAX_WADPATH] = ""; UINT8 filestatus; - size_t bytesused = 0; for (i = 0; i < numwadfiles; i++) { - // If it has only music/sound lumps, mark it as unimportant - if (W_VerifyNMUSlumps(wadfiles[i]->filename)) - filestatus = 0; - else - filestatus = 1; // Important + // If it has only music/sound lumps, don't put it in the list + if (!wadfiles[i]->important) + continue; + + filestatus = 1; // Importance - not really used any more, holds 1 by default for backwards compat with MS // Store in the upper four bits if (!cv_downloading.value) filestatus += (2 << 4); // Won't send - else if ((wadfiles[i]->filesize > (UINT32)cv_maxsend.value * 1024)) - filestatus += (0 << 4); // Won't send - else + else if ((wadfiles[i]->filesize <= (UINT32)cv_maxsend.value * 1024)) filestatus += (1 << 4); // Will send if requested - - bytesused += (nameonlylength(wadfilename) + 22); - - // Don't write too far... - if (bytesused > sizeof(netbuffer->u.serverinfo.fileneeded)) - I_Error("Too many wad files added to host a game. (%s, stopped on %s)\n", sizeu1(bytesused), wadfilename); + // else + // filestatus += (0 << 4); -- Won't send, too big WRITEUINT8(p, filestatus); @@ -167,7 +161,6 @@ void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr) { fileneeded[i].status = FS_NOTFOUND; // We haven't even started looking for the file yet filestatus = READUINT8(p); // The first byte is the file status - fileneeded[i].important = (UINT8)(filestatus & 3); fileneeded[i].willsend = (UINT8)(filestatus >> 4); fileneeded[i].totalsize = READUINT32(p); // The four next bytes are the file size fileneeded[i].file = NULL; // The file isn't open yet @@ -197,7 +190,7 @@ boolean CL_CheckDownloadable(void) UINT8 i,dlstatus = 0; for (i = 0; i < fileneedednum; i++) - if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN && fileneeded[i].important) + if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN) { if (fileneeded[i].willsend == 1) continue; @@ -218,7 +211,7 @@ boolean CL_CheckDownloadable(void) // not downloadable, put reason in console CONS_Alert(CONS_NOTICE, M_GetText("You need additional files to connect to this server:\n")); for (i = 0; i < fileneedednum; i++) - if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN && fileneeded[i].important) + if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN) { CONS_Printf(" * \"%s\" (%dK)", fileneeded[i].filename, fileneeded[i].totalsize >> 10); @@ -271,7 +264,7 @@ boolean CL_SendRequestFile(void) for (i = 0; i < fileneedednum; i++) if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN - && fileneeded[i].important && (fileneeded[i].willsend == 0 || fileneeded[i].willsend == 2)) + && (fileneeded[i].willsend == 0 || fileneeded[i].willsend == 2)) { I_Error("Attempted to download files that were not sendable"); } @@ -280,8 +273,7 @@ boolean CL_SendRequestFile(void) netbuffer->packettype = PT_REQUESTFILE; p = (char *)netbuffer->u.textcmd; for (i = 0; i < fileneedednum; i++) - if ((fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD) - && fileneeded[i].important) + if ((fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD)) { totalfreespaceneeded += fileneeded[i].totalsize; nameonly(fileneeded[i].filename); @@ -339,10 +331,6 @@ INT32 CL_CheckFiles(void) INT32 ret = 1; size_t packetsize = 0; size_t filestoget = 0; - serverinfo_pak *dummycheck = NULL; - - // Shut the compiler up. - (void)dummycheck; // if (M_CheckParm("-nofiles")) // return 1; @@ -360,13 +348,7 @@ INT32 CL_CheckFiles(void) CONS_Debug(DBG_NETPLAY, "game is modified; only doing basic checks\n"); for (i = 1, j = 1; i < fileneedednum || j < numwadfiles;) { - if (i < fileneedednum && !fileneeded[i].important) - { - // Eh whatever, don't care - ++i; - continue; - } - if (j < numwadfiles && W_VerifyNMUSlumps(wadfiles[j]->filename)) + if (j < numwadfiles && !wadfiles[j]->important) { // Unimportant on our side. still don't care. ++j; @@ -392,8 +374,7 @@ INT32 CL_CheckFiles(void) } // See W_LoadWadFile in w_wad.c - for (i = 0; i < numwadfiles; i++) - packetsize += nameonlylength(wadfiles[i]->filename) + 22; + packetsize = packetsizetally; for (i = 1; i < fileneedednum; i++) { @@ -411,13 +392,13 @@ INT32 CL_CheckFiles(void) break; } } - if (fileneeded[i].status != FS_NOTFOUND || !fileneeded[i].important) + if (fileneeded[i].status != FS_NOTFOUND) continue; packetsize += nameonlylength(fileneeded[i].filename) + 22; if ((numwadfiles+filestoget >= MAX_WADFILES) - || (packetsize > sizeof(dummycheck->fileneeded))) + || (packetsize > MAXFILENEEDED*sizeof(UINT8))) return 3; filestoget++; @@ -449,27 +430,8 @@ void CL_LoadServerFiles(void) fileneeded[i].status = FS_OPEN; } else if (fileneeded[i].status == FS_MD5SUMBAD) - { - // If the file is marked important, don't even bother proceeding. - if (fileneeded[i].important) - I_Error("Wrong version of important file %s", fileneeded[i].filename); - - // If it isn't, no need to worry the user with a console message, - // although it can't hurt to put something in the debug file. - - // ...but wait a second. What if the local version is "important"? - if (!W_VerifyNMUSlumps(fileneeded[i].filename)) - I_Error("File %s should only contain music and sound effects!", - fileneeded[i].filename); - - // Okay, NOW we know it's safe. Whew. - P_AddWadFile(fileneeded[i].filename, NULL); - if (fileneeded[i].important) - G_SetGameModified(true); - fileneeded[i].status = FS_OPEN; - DEBFILE(va("File %s found but with different md5sum\n", fileneeded[i].filename)); - } - else if (fileneeded[i].important) + I_Error("Wrong version of file %s", fileneeded[i].filename); + else { const char *s; switch(fileneeded[i].status) @@ -939,10 +901,11 @@ void nameonly(char *s) { ns = &(s[j+1]); len = strlen(ns); - if (false) +#if 0 M_Memcpy(s, ns, len+1); - else +#else memmove(s, ns, len+1); +#endif return; } } diff --git a/src/d_netfil.h b/src/d_netfil.h index a7b692931..3d7c2ed59 100644 --- a/src/d_netfil.h +++ b/src/d_netfil.h @@ -35,7 +35,6 @@ typedef enum typedef struct { - UINT8 important; UINT8 willsend; // Is the server willing to send it? char filename[MAX_WADPATH]; UINT8 md5sum[16]; diff --git a/src/filesrch.c b/src/filesrch.c index 2463e7178..98be1f39c 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -31,6 +31,8 @@ #include "filesrch.h" #include "d_netfil.h" #include "m_misc.h" +#include "z_zone.h" +#include "m_menu.h" // Addons_option_Onchange #if (defined (_WIN32) && !defined (_WIN32_WCE)) && defined (_MSC_VER) && !defined (_XBOX) @@ -255,6 +257,28 @@ readdir (DIR * dirp) return (struct dirent *) 0; } +/* + * rewinddir + * + * Makes the next readdir start from the beginning. + */ +int +rewinddir (DIR * dirp) +{ + errno = 0; + + /* Check for valid DIR struct. */ + if (!dirp) + { + errno = EFAULT; + return -1; + } + + dirp->dd_stat = 0; + + return 0; +} + /* * closedir * @@ -285,6 +309,41 @@ closedir (DIR * dirp) return rc; } #endif + +static CV_PossibleValue_t addons_cons_t[] = {{0, "Default"}, +#if 1 + {1, "HOME"}, {2, "SRB2"}, +#endif + {3, "CUSTOM"}, {0, NULL}}; + +consvar_t cv_addons_option = {"addons_option", "Default", CV_SAVE|CV_CALL, addons_cons_t, Addons_option_Onchange, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_addons_folder = {"addons_folder", "", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; + +static CV_PossibleValue_t addons_md5_cons_t[] = {{0, "Name"}, {1, "Contents"}, {0, NULL}}; +consvar_t cv_addons_md5 = {"addons_md5", "Name", CV_SAVE, addons_md5_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; + +consvar_t cv_addons_showall = {"addons_showall", "No", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; + +consvar_t cv_addons_search_case = {"addons_search_case", "No", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; + +static CV_PossibleValue_t addons_search_type_cons_t[] = {{0, "Start"}, {1, "Anywhere"}, {0, NULL}}; +consvar_t cv_addons_search_type = {"addons_search_type", "Anywhere", CV_SAVE, addons_search_type_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; + +char menupath[1024]; +size_t menupathindex[menudepth]; +size_t menudepthleft = menudepth; + +char menusearch[MAXSTRINGLENGTH+1]; + +char **dirmenu, **coredirmenu; // core only local for this file +size_t sizedirmenu, sizecoredirmenu; // ditto +size_t dir_on[menudepth]; +UINT8 refreshdirmenu = 0; +char *refreshdirname = NULL; + +size_t packetsizetally = 0; +size_t mainwadstally = 0; + #if defined (_XBOX) && defined (_MSC_VER) filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum, boolean completepath, int maxsearchdepth) @@ -296,6 +355,25 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want completepath = false; return FS_NOTFOUND; } + +void closefilemenu(boolean validsize) +{ + (void)validsize; + return; +} + +void searchfilemenu(char *tempname) +{ + (void)tempname; + return; +} + +boolean preparefilemenu(boolean samedepth) +{ + (void)samedepth; + return false; +} + #elif defined (_WIN32_WCE) filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum, boolean completepath, int maxsearchdepth) @@ -346,7 +424,27 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want #endif return FS_NOTFOUND; } + +void closefilemenu(boolean validsize) +{ + (void)validsize; + return; +} + +void searchfilemenu(char *tempname) +{ + (void)tempname; + return; +} + +boolean preparefilemenu(boolean samedepth) +{ + (void)samedepth; + return false; +} + #else + filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum, boolean completepath, int maxsearchdepth) { filestatus_t retval = FS_NOTFOUND; @@ -387,25 +485,29 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want { searchpath[searchpathindex[depthleft]]=0; dent = readdir(dirhandle[depthleft]); - if (dent) - strcpy(&searchpath[searchpathindex[depthleft]],dent->d_name); if (!dent) + { closedir(dirhandle[depthleft++]); - else if (dent->d_name[0]=='.' && + continue; + } + + if (dent->d_name[0]=='.' && (dent->d_name[1]=='\0' || (dent->d_name[1]=='.' && dent->d_name[2]=='\0'))) { // we don't want to scan uptree + continue; } - else if (stat(searchpath,&fsstat) < 0) // do we want to follow symlinks? if not: change it to lstat - { - // was the file (re)moved? can't stat it - } + + // okay, now we actually want searchpath to incorporate d_name + strcpy(&searchpath[searchpathindex[depthleft]],dent->d_name); + + if (stat(searchpath,&fsstat) < 0) // do we want to follow symlinks? if not: change it to lstat + ; // was the file (re)moved? can't stat it else if (S_ISDIR(fsstat.st_mode) && depthleft) { - strcpy(&searchpath[searchpathindex[depthleft]],dent->d_name); searchpathindex[--depthleft] = strlen(searchpath) + 1; dirhandle[depthleft] = opendir(searchpath); if (!dirhandle[depthleft]) @@ -444,6 +546,361 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want free(searchname); free(searchpathindex); free(dirhandle); + return retval; } + +char exttable[NUM_EXT_TABLE][7] = { // maximum extension length (currently 4) plus 3 (null terminator, stop, and length including previous two) + "\5.txt", "\5.cfg", // exec + "\5.wad", "\6.kart", /*"\5.pk3",*/ "\5.soc", "\5.lua"}; // addfile + +char filenamebuf[MAX_WADFILES][MAX_WADPATH]; + + +static boolean filemenucmp(char *haystack, char *needle) +{ + static char localhaystack[128]; + strlcpy(localhaystack, haystack, 128); + if (!cv_addons_search_case.value) + strupr(localhaystack); + if (cv_addons_search_type.value) + return (strstr(localhaystack, needle) != 0); + return (!strncmp(localhaystack, needle, menusearch[0])); +} + +void closefilemenu(boolean validsize) +{ + // search + if (dirmenu) + { + if (dirmenu != coredirmenu) + { + if (dirmenu[0] && ((UINT8)(dirmenu[0][DIR_TYPE]) == EXT_NORESULTS)) + { + Z_Free(dirmenu[0]); + dirmenu[0] = NULL; + } + Z_Free(dirmenu); + } + dirmenu = NULL; + sizedirmenu = 0; + } + + if (coredirmenu) + { + // core + if (validsize) + { + for (; sizecoredirmenu > 0; sizecoredirmenu--) + { + Z_Free(coredirmenu[sizecoredirmenu-1]); + coredirmenu[sizecoredirmenu-1] = NULL; + } + } + else + sizecoredirmenu = 0; + + Z_Free(coredirmenu); + coredirmenu = NULL; + } + + if (refreshdirname) + Z_Free(refreshdirname); + refreshdirname = NULL; +} + +void searchfilemenu(char *tempname) +{ + size_t i, first; + char localmenusearch[MAXSTRINGLENGTH] = ""; + + if (dirmenu) + { + if (dirmenu != coredirmenu) + { + if (dirmenu[0] && ((UINT8)(dirmenu[0][DIR_TYPE]) == EXT_NORESULTS)) + { + Z_Free(dirmenu[0]); + dirmenu[0] = NULL; + } + //Z_Free(dirmenu); -- Z_Realloc later tho... + } + else + dirmenu = NULL; + } + + first = (((UINT8)(coredirmenu[0][DIR_TYPE]) == EXT_UP) ? 1 : 0); // skip UP... + + if (!menusearch[0]) + { + if (dirmenu) + Z_Free(dirmenu); + dirmenu = coredirmenu; + sizedirmenu = sizecoredirmenu; + + if (tempname) + { + for (i = first; i < sizedirmenu; i++) + { + if (!strcmp(dirmenu[i]+DIR_STRING, tempname)) + { + dir_on[menudepthleft] = i; + break; + } + } + + if (i == sizedirmenu) + dir_on[menudepthleft] = first; + + Z_Free(tempname); + } + + return; + } + + strcpy(localmenusearch, menusearch+1); + if (!cv_addons_search_case.value) + strupr(localmenusearch); + + sizedirmenu = 0; + for (i = first; i < sizecoredirmenu; i++) + { + if (filemenucmp(coredirmenu[i]+DIR_STRING, localmenusearch)) + sizedirmenu++; + } + + if (!sizedirmenu) // no results... + { + if ((!(dirmenu = Z_Realloc(dirmenu, sizeof(char *), PU_STATIC, NULL))) + || !(dirmenu[0] = Z_StrDup(va("%c\13No results...", EXT_NORESULTS)))) + I_Error("searchfilemenu(): could not create \"No results...\"."); + sizedirmenu = 1; + dir_on[menudepthleft] = 0; + if (tempname) + Z_Free(tempname); + return; + } + + if (!(dirmenu = Z_Realloc(dirmenu, sizedirmenu*sizeof(char *), PU_STATIC, NULL))) + I_Error("searchfilemenu(): could not reallocate dirmenu."); + + sizedirmenu = 0; + for (i = first; i < sizecoredirmenu; i++) + { + if (filemenucmp(coredirmenu[i]+DIR_STRING, localmenusearch)) + { + if (tempname && !strcmp(coredirmenu[i]+DIR_STRING, tempname)) + { + dir_on[menudepthleft] = sizedirmenu; + Z_Free(tempname); + tempname = NULL; + } + dirmenu[sizedirmenu++] = coredirmenu[i]; // pointer reuse + } + } + + if (tempname) + { + dir_on[menudepthleft] = 0; //first; -- can't be first, causes problems + Z_Free(tempname); + } +} + +boolean preparefilemenu(boolean samedepth) +{ + DIR *dirhandle; + struct dirent *dent; + struct stat fsstat; + size_t pos = 0, folderpos = 0, numfolders = 0; + char *tempname = NULL; + + if (samedepth) + { + if (dirmenu && dirmenu[dir_on[menudepthleft]]) + tempname = Z_StrDup(dirmenu[dir_on[menudepthleft]]+DIR_STRING); // don't need to I_Error if can't make - not important, just QoL + } + else + menusearch[0] = menusearch[1] = 0; // clear search + + if (!(dirhandle = opendir(menupath))) // get directory + { + closefilemenu(true); + return false; + } + + for (; sizecoredirmenu > 0; sizecoredirmenu--) // clear out existing items + { + Z_Free(coredirmenu[sizecoredirmenu-1]); + coredirmenu[sizecoredirmenu-1] = NULL; + } + + while (true) + { + menupath[menupathindex[menudepthleft]] = 0; + dent = readdir(dirhandle); + + if (!dent) + break; + else if (dent->d_name[0]=='.' && + (dent->d_name[1]=='\0' || + (dent->d_name[1]=='.' && + dent->d_name[2]=='\0'))) + continue; // we don't want to scan uptree + + strcpy(&menupath[menupathindex[menudepthleft]],dent->d_name); + + if (stat(menupath,&fsstat) < 0) // do we want to follow symlinks? if not: change it to lstat + ; // was the file (re)moved? can't stat it + else // is a file or directory + { + if (!S_ISDIR(fsstat.st_mode)) // file + { + if (!cv_addons_showall.value) + { + size_t len = strlen(dent->d_name)+1; + UINT8 ext; + for (ext = 0; ext < NUM_EXT_TABLE; ext++) + if (!strcasecmp(exttable[ext]+1, dent->d_name+len-(exttable[ext][0]))) break; // extension comparison + if (ext == NUM_EXT_TABLE) continue; // not an addfile-able (or exec-able) file + } + } + else // directory + numfolders++; + + sizecoredirmenu++; + } + } + + if (!sizecoredirmenu) + { + closedir(dirhandle); + closefilemenu(false); + if (tempname) + Z_Free(tempname); + return false; + } + + if (menudepthleft != menudepth-1) // Make room for UP... + { + sizecoredirmenu++; + numfolders++; + folderpos++; + } + + if (dirmenu && dirmenu == coredirmenu) + dirmenu = NULL; + + if (!(coredirmenu = Z_Realloc(coredirmenu, sizecoredirmenu*sizeof(char *), PU_STATIC, NULL))) + { + closedir(dirhandle); // just in case + I_Error("preparefilemenu(): could not reallocate coredirmenu."); + } + + rewinddir(dirhandle); + + while ((pos+folderpos) < sizecoredirmenu) + { + menupath[menupathindex[menudepthleft]] = 0; + dent = readdir(dirhandle); + + if (!dent) + break; + else if (dent->d_name[0]=='.' && + (dent->d_name[1]=='\0' || + (dent->d_name[1]=='.' && + dent->d_name[2]=='\0'))) + continue; // we don't want to scan uptree + + strcpy(&menupath[menupathindex[menudepthleft]],dent->d_name); + + if (stat(menupath,&fsstat) < 0) // do we want to follow symlinks? if not: change it to lstat + ; // was the file (re)moved? can't stat it + else // is a file or directory + { + char *temp; + size_t len = strlen(dent->d_name)+1; + UINT8 ext = EXT_FOLDER; + UINT8 folder; + + if (!S_ISDIR(fsstat.st_mode)) // file + { + if (!((numfolders+pos) < sizecoredirmenu)) continue; // crash prevention + for (; ext < NUM_EXT_TABLE; ext++) + if (!strcasecmp(exttable[ext]+1, dent->d_name+len-(exttable[ext][0]))) break; // extension comparison + if (ext == NUM_EXT_TABLE && !cv_addons_showall.value) continue; // not an addfile-able (or exec-able) file + ext += EXT_START; // moving to be appropriate position + + if (ext >= EXT_LOADSTART) + { + size_t i; + for (i = 0; i < numwadfiles; i++) + { + if (!filenamebuf[i][0]) + { + strncpy(filenamebuf[i], wadfiles[i]->filename, MAX_WADPATH); + filenamebuf[i][MAX_WADPATH - 1] = '\0'; + nameonly(filenamebuf[i]); + } + + if (strcmp(dent->d_name, filenamebuf[i])) + continue; + if (cv_addons_md5.value && !checkfilemd5(menupath, wadfiles[i]->md5sum)) + continue; + + ext |= EXT_LOADED; + } + } + else if (ext == EXT_TXT) + { + if (!strcmp(dent->d_name, "log.txt") || !strcmp(dent->d_name, "errorlog.txt")) + ext |= EXT_LOADED; + } + + if (!strcmp(dent->d_name, configfile)) + ext |= EXT_LOADED; + + folder = 0; + } + else // directory + len += (folder = 1); + + if (len > 255) + len = 255; + + if (!(temp = Z_Malloc((len+DIR_STRING+folder) * sizeof (char), PU_STATIC, NULL))) + I_Error("preparefilemenu(): could not create file entry."); + temp[DIR_TYPE] = ext; + temp[DIR_LEN] = (UINT8)(len); + strlcpy(temp+DIR_STRING, dent->d_name, len); + if (folder) + { + strcpy(temp+len, PATHSEP); + coredirmenu[folderpos++] = temp; + } + else + coredirmenu[numfolders + pos++] = temp; + } + } + + closedir(dirhandle); + + if ((menudepthleft != menudepth-1) // now for UP... entry + && !(coredirmenu[0] = Z_StrDup(va("%c\5UP...", EXT_UP)))) + I_Error("preparefilemenu(): could not create \"UP...\"."); + + menupath[menupathindex[menudepthleft]] = 0; + sizecoredirmenu = (numfolders+pos); // just in case things shrink between opening and rewind + + if (!sizecoredirmenu) + { + dir_on[menudepthleft] = 0; + closefilemenu(false); + return false; + } + + searchfilemenu(tempname); + + return true; +} + #endif diff --git a/src/filesrch.h b/src/filesrch.h index 33b148d4b..75fd70af7 100644 --- a/src/filesrch.h +++ b/src/filesrch.h @@ -6,6 +6,9 @@ #include "doomdef.h" #include "d_netfil.h" +#include "m_menu.h" // MAXSTRINGLENGTH + +extern consvar_t cv_addons_option, cv_addons_folder, cv_addons_md5, cv_addons_showall, cv_addons_search_case, cv_addons_search_type; /** \brief The filesearch function @@ -25,4 +28,69 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum, boolean completepath, int maxsearchdepth); +#define menudepth 20 + +extern char menupath[1024]; +extern size_t menupathindex[menudepth]; +extern size_t menudepthleft; + +extern char menusearch[MAXSTRINGLENGTH+1]; + +extern char **dirmenu; +extern size_t sizedirmenu; +extern size_t dir_on[menudepth]; +extern UINT8 refreshdirmenu; +extern char *refreshdirname; + +extern size_t packetsizetally; +extern size_t mainwadstally; + +typedef enum +{ + EXT_FOLDER = 0, + EXT_UP, + EXT_NORESULTS, + EXT_START, + EXT_TXT = EXT_START, + EXT_CFG, + EXT_LOADSTART, + EXT_WAD = EXT_LOADSTART, + EXT_KART, + //EXT_PK3, + EXT_SOC, + EXT_LUA, // allowed even if not HAVE_BLUA so that we can yell on load attempt + NUM_EXT, + NUM_EXT_TABLE = NUM_EXT-EXT_START, + EXT_LOADED = 0x80 + /* + obviously there can only be 0x7F supported extensions in + addons menu because we're cramming this into a char out of + laziness/easy memory allocation (what's the difference?) + and have stolen a bit to show whether it's loaded or not + in practice the size of the data type is probably overkill + toast 02/05/17 + */ +} ext_enum; + +typedef enum +{ + DIR_TYPE = 0, + DIR_LEN, + DIR_STRING +} dirname_enum; + +typedef enum +{ + REFRESHDIR_NORMAL = 1, + REFRESHDIR_ADDFILE = 2, + REFRESHDIR_WARNING = 4, + REFRESHDIR_ERROR = 8, + REFRESHDIR_NOTLOADED = 16, + REFRESHDIR_MAX = 32 +} refreshdir_enum; + +void closefilemenu(boolean validsize); +void searchfilemenu(char *tempname); +boolean preparefilemenu(boolean samedepth); + #endif // __FILESRCH_H__ diff --git a/src/m_menu.c b/src/m_menu.c index 82c818c73..2ac2ba7fb 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -33,6 +33,9 @@ #include "s_sound.h" #include "i_system.h" +// Addfile +#include "filesrch.h" + #include "v_video.h" #include "i_video.h" #include "keys.h" @@ -66,6 +69,10 @@ int snprintf(char *str, size_t n, const char *fmt, ...); //int vsnprintf(char *str, size_t n, const char *fmt, va_list ap); #endif +#if defined (__GNUC__) && (__GNUC__ >= 4) +#define FIXUPO0 +#endif + #define SKULLXOFF -32 #define LINEHEIGHT 16 #define STRINGHEIGHT 8 @@ -73,7 +80,6 @@ int snprintf(char *str, size_t n, const char *fmt, ...); #define SMALLLINEHEIGHT 8 #define SLIDER_RANGE 10 #define SLIDER_WIDTH (8*SLIDER_RANGE+6) -#define MAXSTRINGLENGTH 32 #define SERVERS_PER_PAGE 11 typedef enum @@ -203,6 +209,8 @@ menu_t MessageDef; menu_t SPauseDef; +#define lsheadingheight 16 + // Sky Room static void M_CustomLevelSelect(INT32 choice); static void M_CustomWarp(INT32 choice); @@ -296,9 +304,16 @@ menu_t OP_MonitorToggleDef; static void M_ScreenshotOptions(INT32 choice); static void M_EraseData(INT32 choice); +static void M_Addons(INT32 choice); +static void M_AddonsOptions(INT32 choice); +static patch_t *addonsp[NUM_EXT+5]; + +#define numaddonsshown 4 + // Drawing functions static void M_DrawGenericMenu(void); static void M_DrawCenteredMenu(void); +static void M_DrawAddons(void); static void M_DrawSkyRoom(void); static void M_DrawChecklist(void); static void M_DrawEmblemHints(void); @@ -333,6 +348,7 @@ static boolean M_CancelConnect(void); #endif static boolean M_ExitPandorasBox(void); static boolean M_QuitMultiPlayerMenu(void); +static void M_HandleAddons(INT32 choice); static void M_HandleSoundTest(INT32 choice); static void M_HandleImageDef(INT32 choice); static void M_HandleLoadSave(INT32 choice); @@ -440,10 +456,11 @@ static consvar_t cv_dummymares = {"dummymares", "Overall", CV_HIDEN|CV_CALL, dum // --------- static menuitem_t MainMenu[] = { - {IT_CALL |IT_STRING, NULL, "Secrets", M_SecretsMenu, 84}, - {IT_CALL |IT_STRING, NULL, "1 player", M_SinglePlayerMenu, 92}, - {IT_SUBMENU|IT_STRING, NULL, "multiplayer", &MP_MainDef, 100}, - {IT_CALL |IT_STRING, NULL, "options", M_Options, 108}, + {IT_CALL |IT_STRING, NULL, "Secrets", M_SecretsMenu, 76}, + {IT_CALL |IT_STRING, NULL, "1 player", M_SinglePlayerMenu, 84}, + {IT_SUBMENU|IT_STRING, NULL, "multiplayer", &MP_MainDef, 92}, + {IT_CALL |IT_STRING, NULL, "options", M_Options, 100}, + {IT_CALL |IT_STRING, NULL, "Addons", M_Addons, 108}, {IT_CALL |IT_STRING, NULL, "quit game", M_QuitSRB2, 116}, }; @@ -453,9 +470,15 @@ typedef enum singleplr, multiplr, options, + addons, quitdoom } main_e; +static menuitem_t MISC_AddonsMenu[] = +{ + {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleAddons, 0}, // dummy menuitem for the control func +}; + // --------------------------------- // Pause Menu Mode Attacking Edition // --------------------------------- @@ -478,6 +501,7 @@ typedef enum // --------------------- static menuitem_t MPauseMenu[] = { + {IT_STRING | IT_CALL, NULL, "Add-ons...", M_Addons, 8}, {IT_STRING | IT_SUBMENU, NULL, "Scramble Teams...", &MISC_ScrambleTeamDef, 16}, {IT_STRING | IT_CALL, NULL, "Switch Map..." , M_MapChange, 24}, @@ -497,7 +521,8 @@ static menuitem_t MPauseMenu[] = typedef enum { - mpause_scramble = 0, + mpause_addons = 0, + mpause_scramble, mpause_switchmap, mpause_continue, @@ -983,6 +1008,7 @@ static menuitem_t OP_MainMenu[] = {IT_SUBMENU | IT_STRING, NULL, "Game Options...", &OP_GameOptionsDef, 70}, {IT_SUBMENU | IT_STRING, NULL, "Server Options...", &OP_ServerOptionsDef, 80}, + {IT_STRING | IT_CALL, NULL, "Add-on Options...", M_AddonsOptions, 90}, }; static menuitem_t OP_ControlsMenu[] = @@ -1277,6 +1303,24 @@ static menuitem_t OP_EraseDataMenu[] = {IT_STRING | IT_CALL, NULL, "\x85" "Erase ALL Data", M_EraseData, 40}, }; +static menuitem_t OP_AddonsOptionsMenu[] = +{ + {IT_HEADER, NULL, "Menu", NULL, 0}, + {IT_STRING|IT_CVAR, NULL, "Location", &cv_addons_option, 10}, + {IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Custom Folder", &cv_addons_folder, 20}, + {IT_STRING|IT_CVAR, NULL, "Identify add-ons via", &cv_addons_md5, 48}, + {IT_STRING|IT_CVAR, NULL, "Show unsupported file types", &cv_addons_showall, 58}, + + {IT_HEADER, NULL, "Search", NULL, 76}, + {IT_STRING|IT_CVAR, NULL, "Matching", &cv_addons_search_type, 86}, + {IT_STRING|IT_CVAR, NULL, "Case-sensitive", &cv_addons_search_case, 96}, +}; + +enum +{ + op_addons_folder = 2, +}; + static menuitem_t OP_GameOptionsMenu[] = { #ifndef NONET @@ -1308,7 +1352,6 @@ static menuitem_t OP_ServerOptionsMenu[] = #ifndef NONET {IT_STRING | IT_CVAR | IT_CV_STRING, NULL, "Server name", &cv_servername, 50}, -#endif {IT_STRING | IT_CVAR, NULL, "Intermission Timer", &cv_inttime, 80}, {IT_STRING | IT_CVAR, NULL, "Advance to next map", &cv_advancemap, 90}, @@ -1391,6 +1434,18 @@ static menuitem_t OP_MonitorToggleMenu[] = // Main Menu and related menu_t MainDef = CENTERMENUSTYLE(NULL, MainMenu, NULL, 72); +menu_t MISC_AddonsDef = +{ + NULL, + sizeof (MISC_AddonsMenu)/sizeof (menuitem_t), + &MainDef, + MISC_AddonsMenu, + M_DrawAddons, + 50, 28, + 0, + NULL +}; + menu_t MAPauseDef = PAUSEMENUSTYLE(MAPauseMenu, 40, 72); menu_t SPauseDef = PAUSEMENUSTYLE(SPauseMenu, 40, 72); menu_t MPauseDef = PAUSEMENUSTYLE(MPauseMenu, 40, 72); @@ -1736,6 +1791,7 @@ menu_t OP_OpenGLColorDef = #endif menu_t OP_DataOptionsDef = DEFAULTMENUSTYLE("M_DATA", OP_DataOptionsMenu, &OP_MainDef, 60, 30); menu_t OP_ScreenshotOptionsDef = DEFAULTMENUSTYLE("M_DATA", OP_ScreenshotOptionsMenu, &OP_DataOptionsDef, 30, 30); +menu_t OP_AddonsOptionsDef = DEFAULTMENUSTYLE("M_ADDONS", OP_AddonsOptionsMenu, &OP_MainDef, 30, 30); menu_t OP_EraseDataDef = DEFAULTMENUSTYLE("M_DATA", OP_EraseDataMenu, &OP_DataOptionsDef, 60, 30); // ========================================================================== @@ -1961,6 +2017,12 @@ void Moviemode_mode_Onchange(void) OP_ScreenshotOptionsMenu[i].status = IT_STRING|IT_CVAR; } +void Addons_option_Onchange(void) +{ + OP_AddonsOptionsMenu[op_addons_folder].status = + (cv_addons_option.value == 3 ? IT_CVAR|IT_STRING|IT_CV_STRING : IT_DISABLED); +} + // ========================================================================== // END ORGANIZATION STUFF. // ========================================================================== @@ -2565,6 +2627,7 @@ void M_StartControlPanel(void) else // multiplayer { MPauseMenu[mpause_switchmap].status = IT_DISABLED; + MPauseMenu[mpause_addons].status = IT_DISABLED; MPauseMenu[mpause_scramble].status = IT_DISABLED; MPauseMenu[mpause_psetupsplit].status = IT_DISABLED; MPauseMenu[mpause_psetupsplit2].status = IT_DISABLED; @@ -2576,6 +2639,7 @@ void M_StartControlPanel(void) if ((server || adminplayer == consoleplayer)) { MPauseMenu[mpause_switchmap].status = IT_STRING | IT_CALL; + MPauseMenu[mpause_addons].status = IT_STRING | IT_CALL; if (G_GametypeHasTeams()) MPauseMenu[mpause_scramble].status = IT_STRING | IT_SUBMENU; } @@ -3815,6 +3879,547 @@ static void M_HandleImageDef(INT32 choice) // MISC MAIN MENU OPTIONS // ====================== +static void M_AddonsOptions(INT32 choice) +{ + (void)choice; + Addons_option_Onchange(); + + M_SetupNextMenu(&OP_AddonsOptionsDef); +} + +#define LOCATIONSTRING1 "Visit \x83SRB2.ORG/MODS\x80 to get & make add-ons!" +#define LOCATIONSTRING2 "Visit \x88SRB2.ORG/MODS\x80 to get & make add-ons!" + +static void M_Addons(INT32 choice) +{ + const char *pathname = "."; + + (void)choice; + +#if 1 + if (cv_addons_option.value == 0) + pathname = usehome ? srb2home : srb2path; + else if (cv_addons_option.value == 1) + pathname = srb2home; + else if (cv_addons_option.value == 2) + pathname = srb2path; + else +#endif + if (cv_addons_option.value == 3 && *cv_addons_folder.string != '\0') + pathname = cv_addons_folder.string; + + strlcpy(menupath, pathname, 1024); + menupathindex[(menudepthleft = menudepth-1)] = strlen(menupath) + 1; + + if (menupath[menupathindex[menudepthleft]-2] != PATHSEP[0]) + { + menupath[menupathindex[menudepthleft]-1] = PATHSEP[0]; + menupath[menupathindex[menudepthleft]] = 0; + } + else + --menupathindex[menudepthleft]; + + if (!preparefilemenu(false)) + { + M_StartMessage(va("No files/folders found.\n\n%s\n\n(Press a key)\n", (recommendedflags == V_SKYMAP ? LOCATIONSTRING2 : LOCATIONSTRING1)),NULL,MM_NOTHING); + return; + } + else + dir_on[menudepthleft] = 0; + + if (addonsp[0]) // never going to have some provided but not all, saves individually checking + { + size_t i; + for (i = 0; i < NUM_EXT+5; i++) + W_UnlockCachedPatch(addonsp[i]); + } + + addonsp[EXT_FOLDER] = W_CachePatchName("M_FFLDR", PU_STATIC); + addonsp[EXT_UP] = W_CachePatchName("M_FBACK", PU_STATIC); + addonsp[EXT_NORESULTS] = W_CachePatchName("M_FNOPE", PU_STATIC); + addonsp[EXT_TXT] = W_CachePatchName("M_FTXT", PU_STATIC); + addonsp[EXT_CFG] = W_CachePatchName("M_FCFG", PU_STATIC); + addonsp[EXT_WAD] = W_CachePatchName("M_FWAD", PU_STATIC); + addonsp[EXT_KART] = W_CachePatchName("M_FKART", PU_STATIC); + //addonsp[EXT_PK3] = W_CachePatchName("M_FPK3", PU_STATIC); + addonsp[EXT_SOC] = W_CachePatchName("M_FSOC", PU_STATIC); + addonsp[EXT_LUA] = W_CachePatchName("M_FLUA", PU_STATIC); + addonsp[NUM_EXT] = W_CachePatchName("M_FUNKN", PU_STATIC); + addonsp[NUM_EXT+1] = W_CachePatchName("M_FSEL", PU_STATIC); + addonsp[NUM_EXT+2] = W_CachePatchName("M_FLOAD", PU_STATIC); + addonsp[NUM_EXT+3] = W_CachePatchName("M_FSRCH", PU_STATIC); + addonsp[NUM_EXT+4] = W_CachePatchName("M_FSAVE", PU_STATIC); + + MISC_AddonsDef.prevMenu = currentMenu; + M_SetupNextMenu(&MISC_AddonsDef); +} + +#define width 4 +#define vpadding 27 +#define h (BASEVIDHEIGHT-(2*vpadding)) +#define NUMCOLOURS 8 // when toast's coding it's british english hacker fucker +static void M_DrawTemperature(INT32 x, fixed_t t) +{ + INT32 y; + + // bounds check + if (t > FRACUNIT) + t = FRACUNIT; + /*else if (t < 0) -- not needed + t = 0;*/ + + // scale + if (t > 1) + t = (FixedMul(h<>FRACBITS); + + // border + V_DrawFill(x - 1, vpadding, 1, h, 120); + V_DrawFill(x + width, vpadding, 1, h, 120); + V_DrawFill(x - 1, vpadding-1, width+2, 1, 120); + V_DrawFill(x - 1, vpadding+h, width+2, 1, 120); + + // bar itself + y = h; + if (t) + for (t = h - t; y > 0; y--) + { + UINT8 colours[NUMCOLOURS] = {135, 133, 92, 77, 114, 178, 161, 162}; + UINT8 c; + if (y <= t) break; + if (y+vpadding >= BASEVIDHEIGHT/2) + c = 185; + else + c = colours[(NUMCOLOURS*(y-1))/(h/2)]; + V_DrawFill(x, y-1 + vpadding, width, 1, c); + } + + // fill the rest of the backing + if (y) + V_DrawFill(x, vpadding, width, y, 30); +} +#undef width +#undef vpadding +#undef h +#undef NUMCOLOURS + +static char *M_AddonsHeaderPath(void) +{ + UINT32 len; + static char header[1024]; + + strlcpy(header, va("%s folder%s", cv_addons_option.string, menupath+menupathindex[menudepth-1]-1), 1024); + len = strlen(header); + if (len > 34) + { + len = len-34; + header[len] = header[len+1] = header[len+2] = '.'; + } + else + len = 0; + + return header+len; +} + +#define UNEXIST S_StartSound(NULL, sfx_lose);\ + M_SetupNextMenu(MISC_AddonsDef.prevMenu);\ + M_StartMessage(va("\x82%s\x80\nThis folder no longer exists!\nAborting to main menu.\n\n(Press a key)\n", M_AddonsHeaderPath()),NULL,MM_NOTHING) + +#define CLEARNAME Z_Free(refreshdirname);\ + refreshdirname = NULL + +static void M_AddonsClearName(INT32 choice) +{ + CLEARNAME; + M_StopMessage(choice); +} + +// returns whether to do message draw +static boolean M_AddonsRefresh(void) +{ + if ((refreshdirmenu & REFRESHDIR_NORMAL) && !preparefilemenu(true)) + { + UNEXIST; + return true; + } + + if (refreshdirmenu & REFRESHDIR_ADDFILE) + { + char *message = NULL; + + if (refreshdirmenu & REFRESHDIR_NOTLOADED) + { + S_StartSound(NULL, sfx_lose); + if (refreshdirmenu & REFRESHDIR_MAX) + message = va("%c%s\x80\nMaximum number of add-ons reached.\nA file could not be loaded.\nIf you want to play with this add-on, restart the game to clear existing ones.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname); + else + message = va("%c%s\x80\nA file was not loaded.\nCheck the console log for more information.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname); + } + else if (refreshdirmenu & (REFRESHDIR_WARNING|REFRESHDIR_ERROR)) + { + S_StartSound(NULL, sfx_skid); + message = va("%c%s\x80\nA file was loaded with %s.\nCheck the console log for more information.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname, ((refreshdirmenu & REFRESHDIR_ERROR) ? "errors" : "warnings")); + } + + if (message) + { + M_StartMessage(message,M_AddonsClearName,MM_EVENTHANDLER); + return true; + } + + S_StartSound(NULL, sfx_strpst); + CLEARNAME; + } + + return false; +} + +#ifdef FIXUPO0 +#pragma GCC optimize ("0") +#endif + +static void M_DrawAddons(void) +{ + INT32 x, y; + ssize_t i, m; + const UINT8 *flashcol = NULL; + UINT8 hilicol; + + // hack - need to refresh at end of frame to handle addfile... + if (refreshdirmenu & M_AddonsRefresh()) + { + M_DrawMessageMenu(); + return; + } + + if (Playing()) + V_DrawCenteredString(BASEVIDWIDTH/2, 5, warningflags, "Adding files mid-game may cause problems."); + else + V_DrawCenteredString(BASEVIDWIDTH/2, 5, 0, (recommendedflags == V_SKYMAP ? LOCATIONSTRING2 : LOCATIONSTRING1)); + + if (numwadfiles <= mainwads+1) + y = 0; + else if (numwadfiles >= MAX_WADFILES) + y = FRACUNIT; + else + { + x = FixedDiv(((ssize_t)(numwadfiles) - (ssize_t)(mainwads+1))< y) + y = x; + if (y > FRACUNIT) // happens because of how we're shrinkin' it a little + y = FRACUNIT; + } + + M_DrawTemperature(BASEVIDWIDTH - 19 - 5, y); + + // DRAW MENU + x = currentMenu->x; + y = currentMenu->y + 1; + + hilicol = V_GetStringColormap(highlightflags)[120]; + + V_DrawString(x-21, (y - 16) + (lsheadingheight - 12), highlightflags|V_ALLOWLOWERCASE, M_AddonsHeaderPath()); + V_DrawFill(x-21, (y - 16) + (lsheadingheight - 3), MAXSTRINGLENGTH*8+6, 1, hilicol); + V_DrawFill(x-21, (y - 16) + (lsheadingheight - 2), MAXSTRINGLENGTH*8+6, 1, 30); + + m = (BASEVIDHEIGHT - currentMenu->y + 2) - (y - 1); + V_DrawFill(x - 21, y - 1, MAXSTRINGLENGTH*8+6, m, 239); + + // scrollbar! + if (sizedirmenu <= (2*numaddonsshown + 1)) + i = 0; + else + { + ssize_t q = m; + m = ((2*numaddonsshown + 1) * m)/sizedirmenu; + if (dir_on[menudepthleft] <= numaddonsshown) // all the way up + i = 0; + else if (sizedirmenu <= (dir_on[menudepthleft] + numaddonsshown + 1)) // all the way down + i = q-m; + else + i = ((dir_on[menudepthleft] - numaddonsshown) * (q-m))/(sizedirmenu - (2*numaddonsshown + 1)); + } + + V_DrawFill(x + MAXSTRINGLENGTH*8+5 - 21, (y - 1) + i, 1, m, hilicol); + + // get bottom... + m = dir_on[menudepthleft] + numaddonsshown + 1; + if (m > (ssize_t)sizedirmenu) + m = sizedirmenu; + + // then top... + i = m - (2*numaddonsshown + 1); + + // then adjust! + if (i < 0) + { + if ((m -= i) > (ssize_t)sizedirmenu) + m = sizedirmenu; + i = 0; + } + + if (i != 0) + V_DrawString(19, y+4 - (skullAnimCounter/5), highlightflags, "\x1A"); + + if (skullAnimCounter < 4) + flashcol = V_GetStringColormap(highlightflags); + + for (; i < m; i++) + { + UINT32 flags = V_ALLOWLOWERCASE; + if (y > BASEVIDHEIGHT) break; + if (dirmenu[i]) +#define type (UINT8)(dirmenu[i][DIR_TYPE]) + { + if (type & EXT_LOADED) + { + flags |= V_TRANSLUCENT; + V_DrawSmallScaledPatch(x-(16+4), y, V_TRANSLUCENT, addonsp[(type & ~EXT_LOADED)]); + V_DrawSmallScaledPatch(x-(16+4), y, 0, addonsp[NUM_EXT+2]); + } + else + V_DrawSmallScaledPatch(x-(16+4), y, 0, addonsp[(type & ~EXT_LOADED)]); + + if ((size_t)i == dir_on[menudepthleft]) + { + V_DrawFixedPatch((x-(16+4))< (charsonside*2 + 3)) + V_DrawString(x, y+4, flags, va("%.*s...%s", charsonside, dirmenu[i]+DIR_STRING, dirmenu[i]+DIR_STRING+dirmenu[i][DIR_LEN]-(charsonside+1))); +#undef charsonside + else + V_DrawString(x, y+4, flags, dirmenu[i]+DIR_STRING); + } +#undef type + y += 16; + } + + if (m != (ssize_t)sizedirmenu) + V_DrawString(19, y-12 + (skullAnimCounter/5), highlightflags, "\x1B"); + + y = BASEVIDHEIGHT - currentMenu->y + 1; + + M_DrawTextBox(x - (21 + 5), y, MAXSTRINGLENGTH, 1); + if (menusearch[0]) + V_DrawString(x - 18, y + 8, V_ALLOWLOWERCASE, menusearch+1); + else + V_DrawString(x - 18, y + 8, V_ALLOWLOWERCASE|V_TRANSLUCENT, "Type to search..."); + if (skullAnimCounter < 4) + V_DrawCharacter(x - 18 + V_StringWidth(menusearch+1, 0), y + 8, + '_' | 0x80, false); + + x -= (21 + 5 + 16); + V_DrawSmallScaledPatch(x, y + 4, (menusearch[0] ? 0 : V_TRANSLUCENT), addonsp[NUM_EXT+3]); + + x = BASEVIDWIDTH - x - 16; + V_DrawSmallScaledPatch(x, y + 4, ((!modifiedgame || savemoddata) ? 0 : V_TRANSLUCENT), addonsp[NUM_EXT+4]); + + if (modifiedgame) + V_DrawSmallScaledPatch(x, y + 4, 0, addonsp[NUM_EXT+2]); +} + +#ifdef FIXUPO0 +#pragma GCC reset_options +#endif + +static void M_AddonExec(INT32 ch) +{ + if (ch != 'y' && ch != KEY_ENTER) + return; + + S_StartSound(NULL, sfx_zoom); + COM_BufAddText(va("exec \"%s%s\"", menupath, dirmenu[dir_on[menudepthleft]]+DIR_STRING)); +} + +#define len menusearch[0] +static boolean M_ChangeStringAddons(INT32 choice) +{ + if (shiftdown && choice >= 32 && choice <= 127) + choice = shiftxform[choice]; + + switch (choice) + { + case KEY_DEL: + if (len) + { + len = menusearch[1] = 0; + return true; + } + break; + case KEY_BACKSPACE: + if (len) + { + menusearch[1+--len] = 0; + return true; + } + break; + default: + if (choice >= 32 && choice <= 127) + { + if (len < MAXSTRINGLENGTH - 1) + { + menusearch[1+len++] = (char)choice; + menusearch[1+len] = 0; + return true; + } + } + break; + } + return false; +} +#undef len + +static void M_HandleAddons(INT32 choice) +{ + boolean exitmenu = false; // exit to previous menu + + if (M_ChangeStringAddons(choice)) + { + char *tempname = NULL; + if (dirmenu && dirmenu[dir_on[menudepthleft]]) + tempname = Z_StrDup(dirmenu[dir_on[menudepthleft]]+DIR_STRING); // don't need to I_Error if can't make - not important, just QoL +#if 0 // much slower + if (!preparefilemenu(true)) + { + UNEXIST; + return; + } +#else // streamlined + searchfilemenu(tempname); +#endif + } + + switch (choice) + { + case KEY_DOWNARROW: + if (dir_on[menudepthleft] < sizedirmenu-1) + dir_on[menudepthleft]++; + S_StartSound(NULL, sfx_menu1); + break; + case KEY_UPARROW: + if (dir_on[menudepthleft]) + dir_on[menudepthleft]--; + S_StartSound(NULL, sfx_menu1); + break; + case KEY_PGDN: + { + UINT8 i; + for (i = numaddonsshown; i && (dir_on[menudepthleft] < sizedirmenu-1); i--) + dir_on[menudepthleft]++; + } + S_StartSound(NULL, sfx_menu1); + break; + case KEY_PGUP: + { + UINT8 i; + for (i = numaddonsshown; i && (dir_on[menudepthleft]); i--) + dir_on[menudepthleft]--; + } + S_StartSound(NULL, sfx_menu1); + break; + case KEY_ENTER: + { + boolean refresh = true; + if (!dirmenu[dir_on[menudepthleft]]) + S_StartSound(NULL, sfx_lose); + else + { + switch (dirmenu[dir_on[menudepthleft]][DIR_TYPE]) + { + case EXT_FOLDER: + strcpy(&menupath[menupathindex[menudepthleft]],dirmenu[dir_on[menudepthleft]]+DIR_STRING); + if (menudepthleft) + { + menupathindex[--menudepthleft] = strlen(menupath); + menupath[menupathindex[menudepthleft]] = 0; + + if (!preparefilemenu(false)) + { + S_StartSound(NULL, sfx_skid); + M_StartMessage(va("%c%s\x80\nThis folder is empty.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), M_AddonsHeaderPath()),NULL,MM_NOTHING); + menupath[menupathindex[++menudepthleft]] = 0; + + if (!preparefilemenu(true)) + { + UNEXIST; + return; + } + } + else + { + S_StartSound(NULL, sfx_menu1); + dir_on[menudepthleft] = 1; + } + refresh = false; + } + else + { + S_StartSound(NULL, sfx_lose); + M_StartMessage(va("%c%s\x80\nThis folder is too deep to navigate to!\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), M_AddonsHeaderPath()),NULL,MM_NOTHING); + menupath[menupathindex[menudepthleft]] = 0; + } + break; + case EXT_UP: + S_StartSound(NULL, sfx_menu1); + menupath[menupathindex[++menudepthleft]] = 0; + if (!preparefilemenu(false)) + { + UNEXIST; + return; + } + break; + case EXT_TXT: + M_StartMessage(va("%c%s\x80\nThis file may not be a console script.\nAttempt to run anyways? \n\n(Press 'Y' to confirm)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), dirmenu[dir_on[menudepthleft]]+DIR_STRING),M_AddonExec,MM_YESNO); + break; + case EXT_CFG: + M_AddonExec(KEY_ENTER); + break; + case EXT_LUA: +#ifndef HAVE_BLUA + S_StartSound(NULL, sfx_lose); + M_StartMessage(va("%c%s\x80\nThis copy of SRB2 was compiled\nwithout support for .lua files.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), dirmenu[dir_on[menudepthleft]]+DIR_STRING),NULL,MM_NOTHING); + break; +#endif + // else intentional fallthrough + case EXT_SOC: + case EXT_WAD: + case EXT_KART: + //case EXT_PK3: + COM_BufAddText(va("addfile \"%s%s\"", menupath, dirmenu[dir_on[menudepthleft]]+DIR_STRING)); + break; + default: + S_StartSound(NULL, sfx_lose); + } + } + if (refresh) + refreshdirmenu |= REFRESHDIR_NORMAL; + } + break; + + case KEY_ESCAPE: + exitmenu = true; + break; + + default: + break; + } + if (exitmenu) + { + closefilemenu(true); + + // Secret menu! + //MainMenu[secrets].status = (M_AnySecretUnlocked()) ? (IT_STRING | IT_CALL) : (IT_DISABLED); + + if (currentMenu->prevMenu) + M_SetupNextMenu(currentMenu->prevMenu); + else + M_ClearMenus(true); + } +} + static void M_PandorasBox(INT32 choice) { (void)choice; diff --git a/src/m_menu.h b/src/m_menu.h index de76a2710..eb770c194 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -124,6 +124,8 @@ boolean M_CanShowLevelInList(INT32 mapnum, INT32 gt); #define IT_HEADER (IT_SPACE +IT_HEADERTEXT) #define IT_SECRET (IT_SPACE +IT_QUESTIONMARKS) +#define MAXSTRINGLENGTH 32 + typedef union { struct menu_s *submenu; // IT_SUBMENU @@ -223,6 +225,9 @@ void M_CheatActivationResponder(INT32 ch); void Moviemode_mode_Onchange(void); void Screenshot_option_Onchange(void); +// Addons menu updating +void Addons_option_Onchange(void); + // These defines make it a little easier to make menus #define DEFAULTMENUSTYLE(header, source, prev, x, y)\ {\ diff --git a/src/p_setup.c b/src/p_setup.c index 49b98e724..ca8f066e9 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -54,6 +54,8 @@ #include "v_video.h" +#include "filesrch.h" // refreshdirmenu + // wipes #include "f_finale.h" @@ -3005,6 +3007,7 @@ boolean P_AddWadFile(const char *wadfilename, char **firstmapname) if ((numlumps = W_LoadWadFile(wadfilename)) == INT16_MAX) { + refreshdirmenu |= REFRESHDIR_NOTLOADED; CONS_Printf(M_GetText("Errors occurred while loading %s; not added.\n"), wadfilename); return false; } diff --git a/src/v_video.c b/src/v_video.c index 35b848f98..1f05585f3 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -1014,6 +1014,7 @@ void V_DrawFadeConsBack(INT32 plines) // static const UINT8 *V_GetStringColormap(INT32 colorflags) { +#if 0 // perfect switch ((colorflags & V_CHARCOLORMASK) >> V_CHARCOLORSHIFT) { case 1: // 0x81, purple @@ -1033,6 +1034,12 @@ static const UINT8 *V_GetStringColormap(INT32 colorflags) default: // reset return NULL; } +#else // optimised + colorflags = ((colorflags & V_CHARCOLORMASK) >> V_CHARCOLORSHIFT); + if (!colorflags || colorflags > 15) // INT32 is signed, but V_CHARCOLORMASK is a very restrictive mask. + return NULL; + return (purplemap+((colorflags-1)<<8)); +#endif } // Writes a single character (draw WHITE if bit 7 set) diff --git a/src/w_wad.c b/src/w_wad.c index 4cedd3cf4..92509ff7d 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -34,6 +34,8 @@ #include "z_zone.h" #include "fastcmp.h" +#include "filesrch.h" + #include "i_video.h" // rendermode #include "d_netfil.h" #include "dehacked.h" @@ -299,12 +301,22 @@ UINT16 W_LoadWadFile(const char *filename) UINT32 numlumps; size_t i; INT32 compressed = 0; - size_t packetsize = 0; - serverinfo_pak *dummycheck = NULL; + size_t packetsize; UINT8 md5sum[16]; + boolean important; - // Shut the compiler up. - (void)dummycheck; + if (!(refreshdirmenu & REFRESHDIR_ADDFILE)) + refreshdirmenu = REFRESHDIR_NORMAL|REFRESHDIR_ADDFILE; // clean out cons_alerts that happened earlier + + if (refreshdirname) + Z_Free(refreshdirname); + if (dirmenu) + { + refreshdirname = Z_StrDup(filename); + nameonly(refreshdirname); + } + else + refreshdirname = NULL; //CONS_Debug(DBG_SETUP, "Loading %s\n", filename); // @@ -313,6 +325,7 @@ UINT16 W_LoadWadFile(const char *filename) if (numwadfiles >= MAX_WADFILES) { CONS_Alert(CONS_ERROR, M_GetText("Maximum wad files reached\n")); + refreshdirmenu |= REFRESHDIR_MAX; return INT16_MAX; } @@ -322,21 +335,21 @@ UINT16 W_LoadWadFile(const char *filename) // Check if wad files will overflow fileneededbuffer. Only the filename part // is send in the packet; cf. - for (i = 0; i < numwadfiles; i++) + // see PutFileNeeded in d_netfil.c + if ((important = !W_VerifyNMUSlumps(filename))) { - packetsize += nameonlylength(wadfiles[i]->filename); - packetsize += 22; // MD5, etc. - } + packetsize = packetsizetally + nameonlylength(filename) + 22; - packetsize += nameonlylength(filename); - packetsize += 22; + if (packetsize > MAXFILENEEDED*sizeof(UINT8)) + { + CONS_Alert(CONS_ERROR, M_GetText("Maximum wad files reached\n")); + refreshdirmenu |= REFRESHDIR_MAX; + if (handle) + fclose(handle); + return INT16_MAX; + } - if (packetsize > sizeof(dummycheck->fileneeded)) - { - CONS_Alert(CONS_ERROR, M_GetText("Maximum wad files reached\n")); - if (handle) - fclose(handle); - return INT16_MAX; + packetsizetally = packetsize; } // detect dehacked file with the "soc" extension @@ -483,6 +496,7 @@ UINT16 W_LoadWadFile(const char *filename) wadfile->handle = handle; wadfile->numlumps = (UINT16)numlumps; wadfile->lumpinfo = lumpinfo; + wadfile->important = important; fseek(handle, 0, SEEK_END); wadfile->filesize = (unsigned)ftell(handle); @@ -1230,19 +1244,27 @@ static int W_VerifyFile(const char *filename, lumpchecklist_t *checklist, */ int W_VerifyNMUSlumps(const char *filename) { - // MIDI, MOD/S3M/IT/XM/OGG/MP3/WAV, WAVE SFX - // ENDOOM text and palette lumps lumpchecklist_t NMUSlist[] = { - {"D_", 2}, - {"O_", 2}, - {"DS", 2}, - {"ENDOOM", 6}, - {"PLAYPAL", 7}, - {"COLORMAP", 8}, - {"PAL", 3}, - {"CLM", 3}, - {"TRANS", 5}, + {"D_", 2}, // MIDI music + {"O_", 2}, // Digital music + {"DS", 2}, // Sound effects + + {"ENDOOM", 6}, // ENDOOM text lump + {"PLAYPAL", 7}, // Palette + {"COLORMAP", 8}, // Colormap + {"PAL", 3}, // Palette changes + {"CLM", 3}, // Colormap changes + {"TRANS", 5}, // Translucency map + + {"LTFNT", 5}, // Level title font changes + {"STCFN", 5}, // Console font changes + {"TNYFN", 5}, // Tiny console font changes + {"MKFNT", 5}, // Kart font changes + + {"M_", 2}, // Menu changes + {"K_", 2}, // Kart graphic changes + {NULL, 0}, }; return W_VerifyFile(filename, NMUSlist, false); diff --git a/src/w_wad.h b/src/w_wad.h index 320bc3220..62e418767 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -70,6 +70,7 @@ typedef struct wadfile_s FILE *handle; UINT32 filesize; // for network UINT8 md5sum[16]; + boolean important; } wadfile_t; #define WADFILENUM(lumpnum) (UINT16)((lumpnum)>>16) // wad flumpnum>>16) // wad file number in upper word From 0a3b3736bf0f58d791f20e574d513fa552e663f5 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 15 Dec 2018 20:50:33 -0500 Subject: [PATCH 08/71] Handle Kart-specific changes; add PK3 to exttable --- src/filesrch.c | 2 +- src/w_wad.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/filesrch.c b/src/filesrch.c index 98be1f39c..e71b39d91 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -552,7 +552,7 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want char exttable[NUM_EXT_TABLE][7] = { // maximum extension length (currently 4) plus 3 (null terminator, stop, and length including previous two) "\5.txt", "\5.cfg", // exec - "\5.wad", "\6.kart", /*"\5.pk3",*/ "\5.soc", "\5.lua"}; // addfile + "\5.wad", "\6.kart", "\5.pk3", "\5.soc", "\5.lua"}; // addfile char filenamebuf[MAX_WADFILES][MAX_WADPATH]; diff --git a/src/w_wad.c b/src/w_wad.c index 92509ff7d..5eded4265 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -1256,7 +1256,7 @@ int W_VerifyNMUSlumps(const char *filename) {"PAL", 3}, // Palette changes {"CLM", 3}, // Colormap changes {"TRANS", 5}, // Translucency map - +#if 0 {"LTFNT", 5}, // Level title font changes {"STCFN", 5}, // Console font changes {"TNYFN", 5}, // Tiny console font changes @@ -1264,7 +1264,7 @@ int W_VerifyNMUSlumps(const char *filename) {"M_", 2}, // Menu changes {"K_", 2}, // Kart graphic changes - +#endif {NULL, 0}, }; return W_VerifyFile(filename, NMUSlist, false); From f0967520ed5bc7b56a6aa41743efce85cf59de07 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 15 Dec 2018 21:44:39 -0500 Subject: [PATCH 09/71] Compile fixes; enable PK3 support in addons menu * Add missing vars highlightflags, recommendedflags, warningflags from Kart * V_GetStringColormap() use vanilla behavior because Kart behavior glitches for us * V_GetStringColormap() made non-static --- src/d_main.c | 9 ++++----- src/d_netcmd.c | 1 - src/filesrch.h | 2 +- src/m_menu.c | 21 ++++++++++++++++----- src/v_video.c | 9 +-------- src/v_video.h | 2 ++ src/w_wad.c | 1 - 7 files changed, 24 insertions(+), 21 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index 2ee0afae7..702809a15 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -853,11 +853,6 @@ static void IdentifyVersion(void) #if !defined (HAVE_SDL) || defined (HAVE_MIXER) { -#if defined (DC) && 0 - const char *musicfile = "music_dc.dta"; -#else - const char *musicfile = "music.dta"; -#endif #define MUSICTEST(str) \ {\ const char *musicpath = va(pandf,srb2waddir,str);\ @@ -868,7 +863,11 @@ static void IdentifyVersion(void) I_Error("File "str" has been modified with non-music/sound lumps"); \ } +#if defined (DC) && 0 + MUSICTEST("music_dc.dta") +#else MUSICTEST("music.dta") +#endif } #endif } diff --git a/src/d_netcmd.c b/src/d_netcmd.c index a3d3272b5..643daf7a9 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -3243,7 +3243,6 @@ static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum) boolean kick = false; boolean toomany = false; INT32 i,j; - size_t packetsize = 0; serverinfo_pak *dummycheck = NULL; // Shut the compiler up. diff --git a/src/filesrch.h b/src/filesrch.h index 75fd70af7..94c43ffa4 100644 --- a/src/filesrch.h +++ b/src/filesrch.h @@ -56,7 +56,7 @@ typedef enum EXT_LOADSTART, EXT_WAD = EXT_LOADSTART, EXT_KART, - //EXT_PK3, + EXT_PK3, EXT_SOC, EXT_LUA, // allowed even if not HAVE_BLUA so that we can yell on load attempt NUM_EXT, diff --git a/src/m_menu.c b/src/m_menu.c index ea49c0199..99c39ae0c 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1364,6 +1364,7 @@ static menuitem_t OP_ServerOptionsMenu[] = #ifndef NONET {IT_STRING | IT_CVAR | IT_CV_STRING, NULL, "Server name", &cv_servername, 50}, +#endif {IT_STRING | IT_CVAR, NULL, "Intermission Timer", &cv_inttime, 80}, {IT_STRING | IT_CVAR, NULL, "Advance to next map", &cv_advancemap, 90}, @@ -1468,6 +1469,9 @@ menu_t MISC_ChangeTeamDef = DEFAULTMENUSTYLE(NULL, MISC_ChangeTeamMenu, &MPauseD menu_t MISC_ChangeLevelDef = MAPICONMENUSTYLE(NULL, MISC_ChangeLevelMenu, &MPauseDef); menu_t MISC_HelpDef = IMAGEDEF(MISC_HelpMenu); +static INT32 highlightflags, recommendedflags, warningflags; + + // Sky Room menu_t SR_PandoraDef = { @@ -3925,7 +3929,7 @@ static void M_AddonsOptions(INT32 choice) } #define LOCATIONSTRING1 "Visit \x83SRB2.ORG/MODS\x80 to get & make add-ons!" -#define LOCATIONSTRING2 "Visit \x88SRB2.ORG/MODS\x80 to get & make add-ons!" +//#define LOCATIONSTRING2 "Visit \x88SRB2.ORG/MODS\x80 to get & make add-ons!" static void M_Addons(INT32 choice) { @@ -3933,6 +3937,11 @@ static void M_Addons(INT32 choice) (void)choice; + // If M_GetGameypeColor() is ever ported from Kart, then remove this. + highlightflags = V_YELLOWMAP; + recommendedflags = V_GREENMAP; + warningflags = V_REDMAP; + #if 1 if (cv_addons_option.value == 0) pathname = usehome ? srb2home : srb2path; @@ -3958,7 +3967,8 @@ static void M_Addons(INT32 choice) if (!preparefilemenu(false)) { - M_StartMessage(va("No files/folders found.\n\n%s\n\n(Press a key)\n", (recommendedflags == V_SKYMAP ? LOCATIONSTRING2 : LOCATIONSTRING1)),NULL,MM_NOTHING); + M_StartMessage(va("No files/folders found.\n\n%s\n\n(Press a key)\n",LOCATIONSTRING1),NULL,MM_NOTHING); + // (recommendedflags == V_SKYMAP ? LOCATIONSTRING2 : LOCATIONSTRING1)) return; } else @@ -3978,7 +3988,7 @@ static void M_Addons(INT32 choice) addonsp[EXT_CFG] = W_CachePatchName("M_FCFG", PU_STATIC); addonsp[EXT_WAD] = W_CachePatchName("M_FWAD", PU_STATIC); addonsp[EXT_KART] = W_CachePatchName("M_FKART", PU_STATIC); - //addonsp[EXT_PK3] = W_CachePatchName("M_FPK3", PU_STATIC); + addonsp[EXT_PK3] = W_CachePatchName("M_FPK3", PU_STATIC); addonsp[EXT_SOC] = W_CachePatchName("M_FSOC", PU_STATIC); addonsp[EXT_LUA] = W_CachePatchName("M_FLUA", PU_STATIC); addonsp[NUM_EXT] = W_CachePatchName("M_FUNKN", PU_STATIC); @@ -4131,7 +4141,8 @@ static void M_DrawAddons(void) if (Playing()) V_DrawCenteredString(BASEVIDWIDTH/2, 5, warningflags, "Adding files mid-game may cause problems."); else - V_DrawCenteredString(BASEVIDWIDTH/2, 5, 0, (recommendedflags == V_SKYMAP ? LOCATIONSTRING2 : LOCATIONSTRING1)); + V_DrawCenteredString(BASEVIDWIDTH/2, 5, 0, LOCATIONSTRING1); + // (recommendedflags == V_SKYMAP ? LOCATIONSTRING2 : LOCATIONSTRING1) if (numwadfiles <= mainwads+1) y = 0; @@ -4424,7 +4435,7 @@ static void M_HandleAddons(INT32 choice) case EXT_SOC: case EXT_WAD: case EXT_KART: - //case EXT_PK3: + case EXT_PK3: COM_BufAddText(va("addfile \"%s%s\"", menupath, dirmenu[dir_on[menudepthleft]]+DIR_STRING)); break; default: diff --git a/src/v_video.c b/src/v_video.c index 1f05585f3..95558ad24 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -1012,9 +1012,8 @@ void V_DrawFadeConsBack(INT32 plines) // Gets string colormap, used for 0x80 color codes // -static const UINT8 *V_GetStringColormap(INT32 colorflags) +UINT8 *V_GetStringColormap(INT32 colorflags) { -#if 0 // perfect switch ((colorflags & V_CHARCOLORMASK) >> V_CHARCOLORSHIFT) { case 1: // 0x81, purple @@ -1034,12 +1033,6 @@ static const UINT8 *V_GetStringColormap(INT32 colorflags) default: // reset return NULL; } -#else // optimised - colorflags = ((colorflags & V_CHARCOLORMASK) >> V_CHARCOLORSHIFT); - if (!colorflags || colorflags > 15) // INT32 is signed, but V_CHARCOLORMASK is a very restrictive mask. - return NULL; - return (purplemap+((colorflags-1)<<8)); -#endif } // Writes a single character (draw WHITE if bit 7 set) diff --git a/src/v_video.h b/src/v_video.h index a60a08a5b..083be1fb0 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -150,6 +150,8 @@ void V_DrawFadeConsBack(INT32 plines); // draw a single character void V_DrawCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed); +UINT8 *V_GetStringColormap(INT32 colorflags); + void V_DrawLevelTitle(INT32 x, INT32 y, INT32 option, const char *string); // wordwrap a string using the hu_font diff --git a/src/w_wad.c b/src/w_wad.c index dee55c6c8..56629502b 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -649,7 +649,6 @@ UINT16 W_InitFile(const char *filename) restype_t type; UINT16 numlumps = 0; size_t i; - INT32 compressed = 0; size_t packetsize; UINT8 md5sum[16]; boolean important; From c3ff0b6d16ab0b289aa2596d445de5ac91f5366e Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 16 Dec 2018 15:52:01 -0500 Subject: [PATCH 10/71] Uncomment Secrets menu toggle when exiting Addons --- src/m_menu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/m_menu.c b/src/m_menu.c index 99c39ae0c..5aad35896 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -4459,7 +4459,7 @@ static void M_HandleAddons(INT32 choice) closefilemenu(true); // Secret menu! - //MainMenu[secrets].status = (M_AnySecretUnlocked()) ? (IT_STRING | IT_CALL) : (IT_DISABLED); + MainMenu[secrets].status = (M_AnySecretUnlocked()) ? (IT_STRING | IT_CALL) : (IT_DISABLED); if (currentMenu->prevMenu) M_SetupNextMenu(currentMenu->prevMenu); From 6d94568f4b5e6e133dcea77f5af43b7b275e08db Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 16 Dec 2018 16:07:47 -0500 Subject: [PATCH 11/71] Hide kart-specific addons behavior behind USE_KART --- src/doomdef.h | 3 +++ src/filesrch.c | 6 +++++- src/filesrch.h | 2 ++ src/m_menu.c | 4 ++++ 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/doomdef.h b/src/doomdef.h index 796221c91..da5ddb5fe 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -161,6 +161,9 @@ extern FILE *logstream; // Comment or uncomment this as necessary. #define USE_PATCH_DTA +// Use .kart extension addons +//#define USE_KART + // Modification options // If you want to take advantage of the Master Server's ability to force clients to update // to the latest version, fill these out. Otherwise, just comment out UPDATE_ALERT and leave diff --git a/src/filesrch.c b/src/filesrch.c index e71b39d91..0276e1c90 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -552,7 +552,11 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want char exttable[NUM_EXT_TABLE][7] = { // maximum extension length (currently 4) plus 3 (null terminator, stop, and length including previous two) "\5.txt", "\5.cfg", // exec - "\5.wad", "\6.kart", "\5.pk3", "\5.soc", "\5.lua"}; // addfile + "\5.wad", +#ifdef USE_KART + "\6.kart", +#endif + "\5.pk3", "\5.soc", "\5.lua"}; // addfile char filenamebuf[MAX_WADFILES][MAX_WADPATH]; diff --git a/src/filesrch.h b/src/filesrch.h index 94c43ffa4..4186271b0 100644 --- a/src/filesrch.h +++ b/src/filesrch.h @@ -55,7 +55,9 @@ typedef enum EXT_CFG, EXT_LOADSTART, EXT_WAD = EXT_LOADSTART, +#ifdef USE_KART EXT_KART, +#endif EXT_PK3, EXT_SOC, EXT_LUA, // allowed even if not HAVE_BLUA so that we can yell on load attempt diff --git a/src/m_menu.c b/src/m_menu.c index 5aad35896..b5161259c 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -3987,7 +3987,9 @@ static void M_Addons(INT32 choice) addonsp[EXT_TXT] = W_CachePatchName("M_FTXT", PU_STATIC); addonsp[EXT_CFG] = W_CachePatchName("M_FCFG", PU_STATIC); addonsp[EXT_WAD] = W_CachePatchName("M_FWAD", PU_STATIC); +#ifdef USE_KART addonsp[EXT_KART] = W_CachePatchName("M_FKART", PU_STATIC); +#endif addonsp[EXT_PK3] = W_CachePatchName("M_FPK3", PU_STATIC); addonsp[EXT_SOC] = W_CachePatchName("M_FSOC", PU_STATIC); addonsp[EXT_LUA] = W_CachePatchName("M_FLUA", PU_STATIC); @@ -4434,7 +4436,9 @@ static void M_HandleAddons(INT32 choice) // else intentional fallthrough case EXT_SOC: case EXT_WAD: +#ifdef USE_KART case EXT_KART: +#endif case EXT_PK3: COM_BufAddText(va("addfile \"%s%s\"", menupath, dirmenu[dir_on[menudepthleft]]+DIR_STRING)); break; From 046d36a65715ae5da97c80c34ffe0c54cf09ee73 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 16 Dec 2018 16:08:31 -0500 Subject: [PATCH 12/71] Remove Kart entries from NMUSlist --- src/w_wad.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/w_wad.c b/src/w_wad.c index 56629502b..7bb75ef6f 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -1693,10 +1693,8 @@ int W_VerifyNMUSlumps(const char *filename) {"LTFNT", 5}, // Level title font changes {"STCFN", 5}, // Console font changes {"TNYFN", 5}, // Tiny console font changes - {"MKFNT", 5}, // Kart font changes {"M_", 2}, // Menu changes - {"K_", 2}, // Kart graphic changes #endif {NULL, 0}, }; From 899120e475f63771054b88848e988fadd54000fe Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 16 Dec 2018 16:42:57 -0500 Subject: [PATCH 13/71] Revert NMUSlist to original 2.1 --- src/w_wad.c | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/src/w_wad.c b/src/w_wad.c index 7bb75ef6f..88e89974a 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -1677,25 +1677,19 @@ static int W_VerifyFile(const char *filename, lumpchecklist_t *checklist, */ int W_VerifyNMUSlumps(const char *filename) { + // MIDI, MOD/S3M/IT/XM/OGG/MP3/WAV, WAVE SFX + // ENDOOM text and palette lumps lumpchecklist_t NMUSlist[] = { - {"D_", 2}, // MIDI music - {"O_", 2}, // Digital music - {"DS", 2}, // Sound effects - - {"ENDOOM", 6}, // ENDOOM text lump - {"PLAYPAL", 7}, // Palette - {"COLORMAP", 8}, // Colormap - {"PAL", 3}, // Palette changes - {"CLM", 3}, // Colormap changes - {"TRANS", 5}, // Translucency map -#if 0 - {"LTFNT", 5}, // Level title font changes - {"STCFN", 5}, // Console font changes - {"TNYFN", 5}, // Tiny console font changes - - {"M_", 2}, // Menu changes -#endif + {"D_", 2}, + {"O_", 2}, + {"DS", 2}, + {"ENDOOM", 6}, + {"PLAYPAL", 7}, + {"COLORMAP", 8}, + {"PAL", 3}, + {"CLM", 3}, + {"TRANS", 5}, {NULL, 0}, }; return W_VerifyFile(filename, NMUSlist, false); From 296b678d7e039b7bfe328a0b6e2e8eb3d22e999b Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 16 Dec 2018 19:38:46 -0500 Subject: [PATCH 14/71] Wstrict-overflow adjustment --- src/m_menu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/m_menu.c b/src/m_menu.c index b5161259c..a0c509669 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -4203,7 +4203,7 @@ static void M_DrawAddons(void) // then adjust! if (i < 0) { - if ((m -= i) > (ssize_t)sizedirmenu) + if ((m += abs(i)) > (ssize_t)sizedirmenu) m = sizedirmenu; i = 0; } From 2d2bd59099c1fa4d1f22a25401d7e6c8f3973b9a Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 16 Dec 2018 19:39:16 -0500 Subject: [PATCH 15/71] Remove FIXUPO0 GCC pragma --- src/m_menu.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index a0c509669..398e16f44 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -71,10 +71,6 @@ int snprintf(char *str, size_t n, const char *fmt, ...); //int vsnprintf(char *str, size_t n, const char *fmt, va_list ap); #endif -#if defined (__GNUC__) && (__GNUC__ >= 4) -#define FIXUPO0 -#endif - #define SKULLXOFF -32 #define LINEHEIGHT 16 #define STRINGHEIGHT 8 @@ -4122,10 +4118,6 @@ static boolean M_AddonsRefresh(void) return false; } -#ifdef FIXUPO0 -#pragma GCC optimize ("0") -#endif - static void M_DrawAddons(void) { INT32 x, y; @@ -4203,6 +4195,9 @@ static void M_DrawAddons(void) // then adjust! if (i < 0) { + // This line was originally (m -= i), but GCC very helpfully gives us + // a Wstrict-overflow warning during optimization. + // i will always be negative here, so let's just add what would have been a double negative! if ((m += abs(i)) > (ssize_t)sizedirmenu) m = sizedirmenu; i = 0; @@ -4271,10 +4266,6 @@ static void M_DrawAddons(void) V_DrawSmallScaledPatch(x, y + 4, 0, addonsp[NUM_EXT+2]); } -#ifdef FIXUPO0 -#pragma GCC reset_options -#endif - static void M_AddonExec(INT32 ch) { if (ch != 'y' && ch != KEY_ENTER) From 6dbe93099751b7e548568b4f1f6e3f4c928e56ab Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 16 Dec 2018 19:47:02 -0500 Subject: [PATCH 16/71] Use labs for long value --- src/m_menu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/m_menu.c b/src/m_menu.c index 398e16f44..c3977798a 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -4198,7 +4198,7 @@ static void M_DrawAddons(void) // This line was originally (m -= i), but GCC very helpfully gives us // a Wstrict-overflow warning during optimization. // i will always be negative here, so let's just add what would have been a double negative! - if ((m += abs(i)) > (ssize_t)sizedirmenu) + if ((m += labs(i)) > (ssize_t)sizedirmenu) m = sizedirmenu; i = 0; } From b958f00f1781efddedc0de55dc29509198a8fe98 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 17 Dec 2018 10:58:12 -0500 Subject: [PATCH 17/71] Better rewrite for addons draw adjustment --- src/m_menu.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index c3977798a..e6938571e 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -4189,19 +4189,14 @@ static void M_DrawAddons(void) if (m > (ssize_t)sizedirmenu) m = sizedirmenu; - // then top... - i = m - (2*numaddonsshown + 1); - - // then adjust! - if (i < 0) + // then compute top and adjust bottom if needed! + if (m < (2*numaddonsshown + 1)) { - // This line was originally (m -= i), but GCC very helpfully gives us - // a Wstrict-overflow warning during optimization. - // i will always be negative here, so let's just add what would have been a double negative! - if ((m += labs(i)) > (ssize_t)sizedirmenu) - m = sizedirmenu; + m = min(sizedirmenu, 2*numaddonsshown + 1); i = 0; } + else + i = m - (2*numaddonsshown + 1); if (i != 0) V_DrawString(19, y+4 - (skullAnimCounter/5), highlightflags, "\x1A"); From 657e7321f68c3952ca6f783d26f7eb6bd1e0c93d Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 17 Dec 2018 13:38:23 -0500 Subject: [PATCH 18/71] Decouple execversion from MODVERSION; add scheme for MINORMODVERSION --- src/command.c | 12 ++++++++---- src/doomdef.h | 6 ++++++ src/m_misc.c | 8 ++++---- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/command.c b/src/command.c index 47c6d2e5f..3045c1769 100644 --- a/src/command.c +++ b/src/command.c @@ -63,7 +63,7 @@ CV_PossibleValue_t CV_YesNo[] = {{0, "No"}, {1, "Yes"}, {0, NULL}}; CV_PossibleValue_t CV_Unsigned[] = {{0, "MIN"}, {999999999, "MAX"}, {0, NULL}}; CV_PossibleValue_t CV_Natural[] = {{1, "MIN"}, {999999999, "MAX"}, {0, NULL}}; -// Filter consvars by MODVERSION +// Filter consvars by EXECVERSION // First implementation is 26 (2.1.21), so earlier configs default at 25 (2.1.20) // Also set CV_HIDEN during runtime, after config is loaded consvar_t cv_execversion = {"execversion","25",0,CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -1589,7 +1589,7 @@ void CV_InitFilterVar(void) static boolean CV_FilterJoyAxisVars(consvar_t *v, const char *valstr) { // If ALL axis settings are previous defaults, set them to the new defaults - // MODVERSION < 26 (2.1.21) + // EXECVERSION < 26 (2.1.21) if (joyaxis_default) { @@ -1730,6 +1730,11 @@ static boolean CV_FilterJoyAxisVars(consvar_t *v, const char *valstr) static boolean CV_FilterVarByVersion(consvar_t *v, const char *valstr) { + INT32 majorexecversion = abs(cv_execversion.value) & 0xFFFF; +#if 0 // unused for now + INT32 minorexecversion = abs(cv_execversion.value) >> 16; +#endif + // True means allow the CV change, False means block it // We only care about CV_SAVE because this filters the user's config files @@ -1737,8 +1742,7 @@ static boolean CV_FilterVarByVersion(consvar_t *v, const char *valstr) if (!(v->flags & CV_SAVE)) return true; - // We go by MODVERSION here - if (cv_execversion.value < 26) // 26 = 2.1.21 + if (majorexecversion < 26) // 26 = 2.1.21 { // MOUSE SETTINGS // alwaysfreelook split between first and third person (chasefreelook) diff --git a/src/doomdef.h b/src/doomdef.h index 796221c91..0485698d1 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -216,6 +216,12 @@ extern FILE *logstream; // Note that we use this to help keep internal testing in check; this is why v2.1.0 is not version "1". #define MODVERSION 26 +// To version config.cfg, EXECVERSION was originally equal to MODVERSION +// So keep it equal to MODVERSION, and increment MINOREXECVERSION whenever a config change +// is needed that does not correspond to an increment in MODVERSION +#define EXECVERSION 26 +#define MINOREXECVERSION 1 + // ========================================================================= // The maximum number of players, multiplayer/networking. diff --git a/src/m_misc.c b/src/m_misc.c index 1ab5f1fe3..bb25c5405 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -451,7 +451,7 @@ void Command_LoadConfig_f(void) COM_BufInsertText(va("exec \"%s\"\n", configfile)); // don't filter anymore vars and don't let this convsvar be changed - COM_BufInsertText(va("%s \"%d\"\n", cv_execversion.name, MODVERSION)); + COM_BufInsertText(va("%s \"%d\"\n", cv_execversion.name, EXECVERSION)); cv_execversion.flags |= CV_HIDEN; } @@ -503,7 +503,7 @@ void M_FirstLoadConfig(void) // no COM_BufExecute() needed; that does it right away // don't filter anymore vars and don't let this convsvar be changed - COM_BufInsertText(va("%s \"%d\"\n", cv_execversion.name, MODVERSION)); + COM_BufInsertText(va("%s \"%d\"\n", cv_execversion.name, EXECVERSION)); cv_execversion.flags |= CV_HIDEN; // make sure I_Quit() will write back the correct config @@ -562,8 +562,8 @@ void M_SaveConfig(const char *filename) fprintf(f, "// SRB2 configuration file.\n"); // print execversion FIRST, because subsequent consvars need to be filtered - // always print current MODVERSION - fprintf(f, "%s \"%d\"\n", cv_execversion.name, MODVERSION); + // always print current EXECVERSION + fprintf(f, "%s \"%d\"\n", cv_execversion.name, (EXECVERSION + (MINOREXECVERSION << 16))); // FIXME: save key aliases if ever implemented.. From b64dd82034e65e719465b8cd54ad5a223e6a7ecf Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 17 Dec 2018 13:39:24 -0500 Subject: [PATCH 19/71] Attempt to fix cv_execversion being accessible by console --- src/m_misc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/m_misc.c b/src/m_misc.c index bb25c5405..556e56a2e 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -443,7 +443,7 @@ void Command_LoadConfig_f(void) FIL_ForceExtension(configfile, ".cfg"); // temporarily reset execversion to default - cv_execversion.flags &= ~CV_HIDEN; + cv_execversion.flags = 0; COM_BufInsertText(va("%s \"%s\"\n", cv_execversion.name, cv_execversion.defaultvalue)); CV_InitFilterVar(); @@ -452,7 +452,7 @@ void Command_LoadConfig_f(void) // don't filter anymore vars and don't let this convsvar be changed COM_BufInsertText(va("%s \"%d\"\n", cv_execversion.name, EXECVERSION)); - cv_execversion.flags |= CV_HIDEN; + cv_execversion.flags = CV_HIDEN; } /** Saves the current configuration and loads another. @@ -494,7 +494,7 @@ void M_FirstLoadConfig(void) // temporarily reset execversion to default // we shouldn't need to do this, but JUST in case... - cv_execversion.flags &= ~CV_HIDEN; + cv_execversion.flags = 0; COM_BufInsertText(va("%s \"%s\"\n", cv_execversion.name, cv_execversion.defaultvalue)); CV_InitFilterVar(); @@ -504,7 +504,7 @@ void M_FirstLoadConfig(void) // don't filter anymore vars and don't let this convsvar be changed COM_BufInsertText(va("%s \"%d\"\n", cv_execversion.name, EXECVERSION)); - cv_execversion.flags |= CV_HIDEN; + cv_execversion.flags = CV_HIDEN; // make sure I_Quit() will write back the correct config // (do not write back the config if it crash before) From 45aba493c79d4df9e33ff537a77255d44389025b Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Mon, 17 Dec 2018 20:43:59 +0100 Subject: [PATCH 20/71] 2.1.21 and all of the kart additions. Woo. --- src/console.c | 55 ++-- src/d_main.c | 1 + src/g_game.c | 8 +- src/hu_stuff.c | 736 ++++++++++++++++++++++++++-------------------- src/hu_stuff.h | 26 +- src/lua_baselib.c | 28 +- src/lua_hook.h | 2 +- src/lua_hooklib.c | 20 +- src/m_menu.c | 4 +- src/v_video.c | 73 ++--- src/v_video.h | 1 + 11 files changed, 534 insertions(+), 420 deletions(-) diff --git a/src/console.c b/src/console.c index b7ef60444..660a57e45 100644 --- a/src/console.c +++ b/src/console.c @@ -131,11 +131,16 @@ static CV_PossibleValue_t backpic_cons_t[] = {{0, "translucent"}, {1, "picture"} // whether to use console background picture, or translucent mode static consvar_t cons_backpic = {"con_backpic", "translucent", CV_SAVE, backpic_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -static CV_PossibleValue_t backcolor_cons_t[] = {{0, "White"}, {1, "Gray"}, {2, "Brown"}, - {3, "Red"}, {4, "Orange"}, {5, "Yellow"}, - {6, "Green"}, {7, "Blue"}, {8, "Cyan"}, +static CV_PossibleValue_t backcolor_cons_t[] = {{0, "White"}, {1, "Black"}, {2, "Sepia"}, + {3, "Brown"}, {4, "Pink"}, {5, "Raspberry"}, + {6, "Red"}, {7, "Creamsicle"}, {8, "Orange"}, + {9, "Gold"}, {10,"Yellow"}, {11,"Emerald"}, + {12,"Green"}, {13,"Cyan"}, {14,"Steel"}, + {15,"Periwinkle"}, {16,"Blue"}, {17,"Purple"}, + {18,"Lavender"}, {0, NULL}}; -consvar_t cons_backcolor = {"con_backcolor", "Green", CV_CALL|CV_SAVE, backcolor_cons_t, CONS_backcolor_Change, 0, NULL, NULL, 0, 0, NULL}; + +consvar_t cons_backcolor = {"con_backcolor", "Black", CV_CALL|CV_SAVE, backcolor_cons_t, CONS_backcolor_Change, 0, NULL, NULL, 0, 0, NULL}; static void CON_Print(char *msg); @@ -241,29 +246,41 @@ void CON_SetupBackColormap(void) UINT16 i, palsum; UINT8 j, palindex; UINT8 *pal = W_CacheLumpName(GetPalette(), PU_CACHE); + INT32 shift = 6; if (!consolebgmap) consolebgmap = (UINT8 *)Z_Malloc(256, PU_STATIC, NULL); switch (cons_backcolor.value) { - case 0: palindex = 15; break; // White - case 1: palindex = 31; break; // Gray - case 2: palindex = 63; break; // Brown - case 3: palindex = 143; break; // Red - case 4: palindex = 95; break; // Orange - case 5: palindex = 111; break; // Yellow - case 6: palindex = 175; break; // Green - case 7: palindex = 239; break; // Blue - case 8: palindex = 219; break; // Cyan + case 0: palindex = 15; break; // White + case 1: palindex = 31; break; // Gray + case 2: palindex = 47; break; // Sepia + case 3: palindex = 63; break; // Brown + case 4: palindex = 150; shift = 7; break; // Pink + case 5: palindex = 127; shift = 7; break; // Raspberry + case 6: palindex = 143; break; // Red + case 7: palindex = 86; shift = 7; break; // Creamsicle + case 8: palindex = 95; break; // Orange + case 9: palindex = 119; shift = 7; break; // Gold + case 10: palindex = 111; break; // Yellow + case 11: palindex = 191; shift = 7; break; // Emerald + case 12: palindex = 175; break; // Green + case 13: palindex = 219; break; // Cyan + case 14: palindex = 207; shift = 7; break; // Steel + case 15: palindex = 230; shift = 7; break; // Periwinkle + case 16: palindex = 239; break; // Blue + case 17: palindex = 199; shift = 7; break; // Purple + case 18: palindex = 255; shift = 7; break; // Lavender // Default green default: palindex = 175; break; + } // setup background colormap for (i = 0, j = 0; i < 768; i += 3, j++) { - palsum = (pal[i] + pal[i+1] + pal[i+2]) >> 6; + palsum = (pal[i] + pal[i+1] + pal[i+2]) >> shift; consolebgmap[j] = (UINT8)(palindex - palsum); } } @@ -1035,17 +1052,17 @@ boolean CON_Responder(event_t *ev) } else if (key == KEY_KPADSLASH) key = '/'; - + // capslock if (key == KEY_CAPSLOCK) // it's a toggle. - { + { if (capslock) capslock = false; - else + else capslock = true; return true; - } - + } + if (key >= 'a' && key <= 'z') { if (capslock ^ shiftdown) diff --git a/src/d_main.c b/src/d_main.c index 23835136a..906906e52 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -178,6 +178,7 @@ void D_PostEvent_end(void) {}; UINT8 shiftdown = 0; // 0x1 left, 0x2 right UINT8 ctrldown = 0; // 0x1 left, 0x2 right UINT8 altdown = 0; // 0x1 left, 0x2 right +boolean capslock = 0; // gee i wonder what this does. // // D_ModifierKeyResponder // Sets global shift/ctrl/alt variables, never actually eats events diff --git a/src/g_game.c b/src/g_game.c index 1da546d28..1c37b3b71 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -371,10 +371,12 @@ consvar_t cv_chatnotifications= {"chatnotifications", "On", CV_SAVE, CV_OnOff, N consvar_t cv_chatspamprotection= {"chatspamprotection", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; // minichat text background -consvar_t cv_chatbacktint = {"chatbacktint", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_chatbacktint = {"chatbacktint", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; // old shit console chat. (mostly exists for stuff like terminal, not because I cared if anyone liked the old chat.) -consvar_t cv_consolechat= {"consolechat", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +static CV_PossibleValue_t consolechat_cons_t[] = {{0, "Window"}, {1, "Console"}, {2, "Window (Hidden)"}, {0, NULL}}; +consvar_t cv_consolechat = {"chatmode", "Window", CV_SAVE, consolechat_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; + consvar_t cv_crosshair = {"crosshair", "Cross", CV_SAVE, crosshair_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_crosshair2 = {"crosshair2", "Cross", CV_SAVE, crosshair_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -1583,7 +1585,7 @@ void G_BuildTiccmd2(ticcmd_t *cmd, INT32 realtics) { localangle2 += (cmd->angleturn<<16); cmd->angleturn = (INT16)(localangle2 >> 16); - } + } } // User has designated that they want diff --git a/src/hu_stuff.c b/src/hu_stuff.c index a8f48051e..0bf4fcd89 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -325,10 +325,10 @@ void HU_Start(void) static UINT32 chat_nummsg_log = 0; static UINT32 chat_nummsg_min = 0; -static UINT32 chat_scroll = 0; +static UINT32 chat_scroll = 0; static tic_t chat_scrolltime = 0; -static INT32 chat_maxscroll = 0; // how far can we scroll? +static INT32 chat_maxscroll = 0; // how far can we scroll? //static chatmsg_t chat_mini[CHAT_BUFSIZE]; // Display the last few messages sent. //static chatmsg_t chat_log[CHAT_BUFSIZE]; // Keep every message sent to us in memory so we can scroll n shit, it's cool. @@ -341,7 +341,7 @@ static boolean chat_scrollmedown = false; // force instant scroll down on the ch // remove text from minichat table -static INT16 addy = 0; // use this to make the messages scroll smoothly when one fades away +static INT16 addy = 0; // use this to make the messages scroll smoothly when one fades away static void HU_removeChatText_Mini(void) { @@ -368,25 +368,32 @@ static void HU_removeChatText_Log(void) } chat_nummsg_log--; // lost 1 msg. } - -void HU_AddChatText(const char *text) + +void HU_AddChatText(const char *text, boolean playsound) { - - // TODO: check if we're oversaturating the log (we can only log CHAT_BUFSIZE messages.) - - if (chat_nummsg_log >= CHAT_BUFSIZE) + if (playsound && cv_consolechat.value != 2) // Don't play the sound if we're using hidden chat. + S_StartSound(NULL, sfx_radio); + // reguardless of our preferences, put all of this in the chat buffer in case we decide to change from oldchat mid-game. + + if (chat_nummsg_log >= CHAT_BUFSIZE) // too many messages! HU_removeChatText_Log(); - + strcpy(chat_log[chat_nummsg_log], text); chat_nummsg_log++; - + if (chat_nummsg_min >= 8) HU_removeChatText_Mini(); - + strcpy(chat_mini[chat_nummsg_min], text); chat_timers[chat_nummsg_min] = TICRATE*cv_chattime.value; chat_nummsg_min++; -} + + if (OLDCHAT) // if we're using oldchat, print directly in console + CONS_Printf("%s\n", text); + else // if we aren't, still save the message to log.txt + CON_LogMessage(va("%s\n", text)); +} + /** Runs a say command, sending an ::XD_SAY message. * A say command consists of a signed 8-bit integer for the target, an @@ -406,8 +413,8 @@ void HU_AddChatText(const char *text) * \sa Command_Say_f, Command_Sayteam_f, Command_Sayto_f, Got_Saycmd * \author Graue */ - - + + static void DoSayCommand(SINT8 target, size_t usedargs, UINT8 flags) { XBOXSTATIC char buf[254]; @@ -418,18 +425,14 @@ static void DoSayCommand(SINT8 target, size_t usedargs, UINT8 flags) numwords = COM_Argc() - usedargs; I_Assert(numwords > 0); -<<<<<<< HEAD - if (cv_mute.value && !(server || adminplayer == consoleplayer)) // TODO: Per Player mute. -======= - if (cv_mute.value && !(server || IsPlayerAdmin(consoleplayer))) ->>>>>>> master + if (CHAT_MUTE) // TODO: Per Player mute. { - HU_AddChatText(va("%s>ERROR: The chat is muted. You can't say anything.", "\x85")); + HU_AddChatText(va("%s>ERROR: The chat is muted. You can't say anything.", "\x85"), false); return; } // Only servers/admins can CSAY. - if(!server && IsPlayerAdmin(consoleplayer)) + if(!server && !(IsPlayerAdmin(consoleplayer))) flags &= ~HU_CSAY; // We handle HU_SERVER_SAY, not the caller. @@ -447,51 +450,52 @@ static void DoSayCommand(SINT8 target, size_t usedargs, UINT8 flags) strlcat(msg, " ", msgspace); strlcat(msg, COM_Argv(ix + usedargs), msgspace); } - + if (strlen(msg) > 4 && strnicmp(msg, "/pm", 3) == 0) // used /pm { // what we're gonna do now is check if the node exists // with that logic, characters 4 and 5 are our numbers: + const char *newmsg; int spc = 1; // used if nodenum[1] is a space. char *nodenum = (char*) malloc(3); strncpy(nodenum, msg+3, 5); // check for undesirable characters in our "number" if (((nodenum[0] < '0') || (nodenum[0] > '9')) || ((nodenum[1] < '0') || (nodenum[1] > '9'))) - { + { // check if nodenum[1] is a space if (nodenum[1] == ' ') spc = 0; // let it slide else - { - HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm \'."); + { + HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm \'.", false); return; - } + } } // I'm very bad at C, I swear I am, additional checks eww! if (spc != 0) - { + { if (msg[5] != ' ') { - HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm \'."); + HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm \'.", false); return; } } - + target = atoi((const char*) nodenum); // turn that into a number //CONS_Printf("%d\n", target); - + // check for target player, if it doesn't exist then we can't send the message! if (playeringame[target]) // player exists target++; // even though playernums are from 0 to 31, target is 1 to 32, so up that by 1 to have it work! else { - HU_AddChatText(va("\x82NOTICE: \x80Player %d does not exist.", target)); // same + HU_AddChatText(va("\x82NOTICE: \x80Player %d does not exist.", target), false); // same return; } buf[0] = target; - const char *newmsg = msg+5+spc; - memcpy(msg, newmsg, 255); + newmsg = msg+5+spc; + memcpy(msg, newmsg, 252); } SendNetXCmd(XD_SAY, buf, strlen(msg) + 1 + msg-buf); @@ -577,7 +581,6 @@ static void Command_CSay_f(void) DoSayCommand(0, 1, HU_CSAY); } - static tic_t stop_spamming_you_cunt[MAXPLAYERS]; /** Receives a message, processing an ::XD_SAY command. @@ -592,7 +595,8 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) char *msg; boolean action = false; char *ptr; - + int spam_eatmsg = 0; + CONS_Debug(DBG_NETPLAY,"Received SAY cmd from Player %d (%s)\n", playernum+1, player_names[playernum]); target = READSINT8(*p); @@ -600,7 +604,7 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) msg = (char *)*p; SKIPSTRING(*p); - if ((cv_mute.value || flags & (HU_CSAY|HU_SERVER_SAY)) && playernum != serverplayer && !IsPlayerAdmin(playernum)) + if ((cv_mute.value || flags & (HU_CSAY|HU_SERVER_SAY)) && playernum != serverplayer && !(IsPlayerAdmin(playernum))) { CONS_Alert(CONS_WARNING, cv_mute.value ? M_GetText("Illegal say command received from %s while muted\n") : M_GetText("Illegal csay command received from non-admin %s\n"), @@ -637,32 +641,29 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) } } } - - int spam_eatmsg = 0; - + // before we do anything, let's verify the guy isn't spamming, get this easier on us. - + //if (stop_spamming_you_cunt[playernum] != 0 && cv_chatspamprotection.value && !(flags & HU_CSAY)) if (stop_spamming_you_cunt[playernum] != 0 && consoleplayer != playernum && cv_chatspamprotection.value && !(flags & HU_CSAY)) - { + { CONS_Debug(DBG_NETPLAY,"Received SAY cmd too quickly from Player %d (%s), assuming as spam and blocking message.\n", playernum+1, player_names[playernum]); stop_spamming_you_cunt[playernum] = 4; spam_eatmsg = 1; } else stop_spamming_you_cunt[playernum] = 4; // you can hold off for 4 tics, can you? - + // run the lua hook even if we were supposed to eat the msg, netgame consistency goes first. - -/*#ifdef HAVE_BLUA + +#ifdef HAVE_BLUA if (LUAh_PlayerMsg(playernum, target, flags, msg, spam_eatmsg)) return; -#endif*/ - // Kill PlayerMsg for now, it breaks the purpose of this EXE. - +#endif + if (spam_eatmsg) return; // don't proceed if we were supposed to eat the message. - + // If it's a CSAY, just CECHO and be done with it. if (flags & HU_CSAY) { @@ -702,23 +703,55 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) || target == 0 // To everyone || consoleplayer == target-1) // To you { - const char *prefix = "", *cstart = "", *cend = "", *adminchar = "\x82~\x83", *remotechar = "\x82@\x83", *fmt, *fmt2; + const char *prefix = "", *cstart = "", *cend = "", *adminchar = "\x82~\x83", *remotechar = "\x82@\x83", *fmt2, *textcolor = "\x80"; char *tempchar = NULL; - - // In CTF and team match, color the player's name. - if (G_GametypeHasTeams()) - { - cend = ""; - if (players[playernum].ctfteam == 1) // red - cstart = "\x85"; - else if (players[playernum].ctfteam == 2) // blue - cstart = "\x84"; - - } - + // player is a spectator? - if (players[playernum].spectator) - cstart = "\x86"; // grey name + if (players[playernum].spectator) + { + cstart = "\x86"; // grey name + textcolor = "\x86"; + } + else if (target == -1) // say team + { + if (players[playernum].ctfteam == 1) // red + { + cstart = "\x85"; + textcolor = "\x85"; + } + else // blue + { + cstart = "\x84"; + textcolor = "\x84"; + } + } + else + { + + cstart = "\x83"; + const UINT8 color = players[playernum].skincolor; + if (color <= SKINCOLOR_SILVER) + cstart = "\x80"; // White + else if (color <= SKINCOLOR_BLACK) + cstart = "\x86"; // Grey + else if (color <= SKINCOLOR_BLUE) + cstart = "\x84"; // Blue + else if (color <= SKINCOLOR_PEACH) + cstart = "\x87"; //... Orange??? + else if (color == SKINCOLOR_PINK) + cstart = "\x85"; // Red. + else if (color <= SKINCOLOR_PURPLE) + cstart = "\x81"; // Purple + else if (color <= SKINCOLOR_ROSEWOOD) + cstart = "\x87"; // Orange + else if (color <= SKINCOLOR_DARKRED) + cstart = "\x85"; // Red + else if (color <= SKINCOLOR_OLIVE) + cstart = "\x83"; // green + else if (color <= SKINCOLOR_GOLD) + cstart = "\x82"; // Yellow + } + prefix = cstart; // Give admins and remote admins their symbols. if (playernum == serverplayer) @@ -740,61 +773,39 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) // name, color end, and the message itself. // '\4' makes the message yellow and beeps; '\3' just beeps. if (action) - { - fmt = "\3* %s%s%s%s \x82%s\n"; // don't make /me yellow, yellow will be for mentions and PMs! - fmt2 = "* %s%s%s%s \x82%s"; - } - else if (target == 0) // To everyone - { - fmt = "\3%s\x83<%s%s%s\x83>\x80 %s\n"; - fmt2 = "%s\x83<%s%s%s\x83>\x80 %s"; - } + fmt2 = "* %s%s%s%s \x82%s%s"; else if (target-1 == consoleplayer) // To you { prefix = "\x82[PM]"; cstart = "\x82"; - fmt = "\4%s<%s%s>%s\x80 %s\n"; // make this yellow, however. - fmt2 = "%s<%s%s>%s\x80 %s"; + textcolor = "\x82"; + fmt2 = "%s<%s%s>%s\x80 %s%s"; } else if (target > 0) // By you, to another player { // Use target's name. dispname = player_names[target-1]; - /*fmt = "\3\x82[TO]\x80%s%s%s* %s\n"; - fmt2 = "\x82[TO]\x80%s%s%s* %s";*/ prefix = "\x82[TO]"; cstart = "\x82"; - fmt = "\4%s<%s%s>%s\x80 %s\n"; // make this yellow, however. - fmt2 = "%s<%s%s>%s\x80 %s"; - + fmt2 = "%s<%s%s>%s\x80 %s%s"; + } + else if (target == 0) // To everyone + fmt2 = "%s<%s%s%s>\x80 %s%s"; else // To your team { - if (players[playernum].ctfteam == 1) // red - prefix = "\x85[TEAM]"; + if (players[playernum].ctfteam == 1) // red + prefix = "\x85[TEAM]"; else if (players[playernum].ctfteam == 2) // blue prefix = "\x84[TEAM]"; else prefix = "\x83"; // makes sure this doesn't implode if you sayteam on non-team gamemodes - - fmt = "\3%s<%s%s>\x80%s %s\n"; - fmt2 = "%s<%s%s>\x80%s %s"; - - } - - if OLDCHAT - { - CONS_Printf(fmt, prefix, cstart, dispname, cend, msg); - HU_AddChatText(va(fmt2, prefix, cstart, dispname, cend, msg)); // add it reguardless, in case we decide to change our mind about our chat type. - } - else - { - HU_AddChatText(va(fmt2, prefix, cstart, dispname, cend, msg)); - CON_LogMessage(va(fmt, prefix, cstart, dispname, cend, msg)); // save to log.txt - if (cv_chatnotifications.value) - S_StartSound(NULL, sfx_radio); - } - + + fmt2 = "%s<%s%s>\x80%s %s%s"; + } + + HU_AddChatText(va(fmt2, prefix, cstart, dispname, cend, textcolor, msg), cv_chatnotifications.value); // add to chat + if (tempchar) Z_Free(tempchar); } @@ -825,10 +836,10 @@ static inline boolean HU_keyInChatString(char *s, char ch) { s[l++] = ch; s[l]=0; - } + } else - { - + { + // move everything past c_input for new characters: INT32 m = HU_MAXMSGLEN-1; for (;(m>=c_input);m--) @@ -850,16 +861,16 @@ static inline boolean HU_keyInChatString(char *s, char ch) size_t i = c_input; if (!s[i-1]) return false; - + if (i >= strlen(s)-1) - { + { s[strlen(s)-1] = 0; c_input--; return false; - } - + } + for (; (i < HU_MAXMSGLEN); i++) - { + { s[i-1] = s[i]; } c_input--; @@ -909,78 +920,78 @@ static void HU_queueChatChar(char c) size_t i = 0; for (;(iERROR: The chat is muted. You can't say anything.", "\x85")); + HU_AddChatText(va("%s>ERROR: The chat is muted. You can't say anything.", "\x85"), false); return; } - + INT32 target = 0; - + if (strlen(msg) > 4 && strnicmp(msg, "/pm", 3) == 0) // used /pm { // what we're gonna do now is check if the node exists // with that logic, characters 4 and 5 are our numbers: - + // teamtalk can't send PMs, just don't send it, else everyone would be able to see it, and no one wants to see your sex RP sicko. if (teamtalk) { - HU_AddChatText(va("%sCannot send sayto in Say-Team.", "\x85")); + HU_AddChatText(va("%sCannot send sayto in Say-Team.", "\x85"), false); return; - } - + } + int spc = 1; // used if nodenum[1] is a space. char *nodenum = (char*) malloc(3); strncpy(nodenum, msg+3, 5); // check for undesirable characters in our "number" if (((nodenum[0] < '0') || (nodenum[0] > '9')) || ((nodenum[1] < '0') || (nodenum[1] > '9'))) - { + { // check if nodenum[1] is a space if (nodenum[1] == ' ') spc = 0; // let it slide else - { - HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm \'."); - return; - } - } - // I'm very bad at C, I swear I am, additional checks eww! - if (spc != 0) - { - if (msg[5] != ' ') { - HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm \'."); + HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm \'.", false); return; } } - + // I'm very bad at C, I swear I am, additional checks eww! + if (spc != 0) + { + if (msg[5] != ' ') + { + HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm \'.", false); + return; + } + } + target = atoi((const char*) nodenum); // turn that into a number //CONS_Printf("%d\n", target); - + // check for target player, if it doesn't exist then we can't send the message! if (playeringame[target]) // player exists target++; // even though playernums are from 0 to 31, target is 1 to 32, so up that by 1 to have it work! else { - HU_AddChatText(va("\x82NOTICE: \x80Player %d does not exist.", target)); // same + HU_AddChatText(va("\x82NOTICE: \x80Player %d does not exist.", target), false); // same return; } // we need to get rid of the /pm const char *newmsg = msg+5+spc; memcpy(msg, newmsg, 255); - } + } if (ci > 3) // don't send target+flags+empty message. { if (teamtalk) buf[0] = -1; // target else buf[0] = target; - + buf[1] = 0; // flags SendNetXCmd(XD_SAY, buf, 2 + strlen(&buf[2]) + 1); } @@ -999,53 +1010,81 @@ void HU_clearChatChars(void) static boolean justscrolleddown; static boolean justscrolledup; +static INT16 typelines = 1; // number of drawfill lines we need when drawing the chat. it's some weird hack and might be one frame off but I'm lazy to make another loop. +// It's up here since it has to be reset when we open the chat. + // // Returns true if key eaten // boolean HU_Responder(event_t *ev) { - UINT8 c=0; - + INT32 c=0; + if (ev->type != ev_keydown) return false; // only KeyDown events now... - + + /*// Shoot, to prevent P1 chatting from ruining the game for everyone else, it's either: + // A. completely disallow opening chat entirely in online splitscreen + // or B. iterate through all controls to make sure it's bound to player 1 before eating + // You can see which one I chose. + // (Unless if you're sharing a keyboard, since you probably establish when you start chatting that you have dibs on it...) + // (Ahhh, the good ol days when I was a kid who couldn't afford an extra USB controller...) + + if (ev->data1 >= KEY_MOUSE1) + { + INT32 i; + for (i = 0; i < num_gamecontrols; i++) + { + if (gamecontrol[i][0] == ev->data1 || gamecontrol[i][1] == ev->data1) + break; + } + + if (i == num_gamecontrols) + return false; + }*/ //We don't actually care about that unless we get splitscreen netgames. :V + + c = (INT32)ev->data1; + + // capslock (now handled outside of chat on so that it works everytime......) + if (c && c == KEY_CAPSLOCK) // it's a toggle. + { + if (capslock) + capslock = false; + else + capslock = true; + return true; + } + if (!chat_on) { // enter chat mode if ((ev->data1 == gamecontrol[gc_talkkey][0] || ev->data1 == gamecontrol[gc_talkkey][1]) - && netgame && (!cv_mute.value || server || IsPlayerAdmin(consoleplayer))) + && netgame && !OLD_MUTE) // check for old chat mute, still let the players open the chat incase they want to scroll otherwise. { - if (cv_mute.value && !(server || IsPlayerAdmin(consoleplayer))) - return false; chat_on = true; w_chat[0] = 0; teamtalk = false; chat_scrollmedown = true; + typelines = 1; return true; } if ((ev->data1 == gamecontrol[gc_teamkey][0] || ev->data1 == gamecontrol[gc_teamkey][1]) - && netgame && (!cv_mute.value || server || (IsPlayerAdmin(consoleplayer)))) + && netgame && !OLD_MUTE) { -<<<<<<< HEAD - if (cv_mute.value && !(server || adminplayer == consoleplayer)) -======= - if (cv_mute.value && !(server || IsPlayerAdmin(consoleplayer))) ->>>>>>> master - return false; chat_on = true; w_chat[0] = 0; - teamtalk = true; -<<<<<<< HEAD + teamtalk = G_GametypeHasTeams(); // Don't teamtalk if we don't have teams. chat_scrollmedown = true; + typelines = 1; return true; } } else // if chat_on { - + // Ignore modifier keys // Note that we do this here so users can still set // their chat keys to one of these, if they so desire. @@ -1054,43 +1093,38 @@ boolean HU_Responder(event_t *ev) || ev->data1 == KEY_LALT || ev->data1 == KEY_RALT) return true; - c = (UINT8)ev->data1; - - // capslock - if (c && c == KEY_CAPSLOCK) // it's a toggle. - { - if (capslock) - capslock = false; - else - capslock = true; - return true; - } - - // use console translations + c = (INT32)ev->data1; - if (c >= 'a' && c <= 'z') + // I know this looks very messy but this works. If it ain't broke, don't fix it! + // shift LETTERS to uppercase if we have capslock or are holding shift + if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { - if (capslock ^ shiftdown) + if (shiftdown ^ capslock) c = shiftxform[c]; } - else if (shiftdown) - c = shiftxform[c]; - + else // if we're holding shift we should still shift non letter symbols + { + if (shiftdown) + c = shiftxform[c]; + } + // pasting. pasting is cool. chat is a bit limited, though :( - if ((c == 'v' || c == 'V') && ctrldown) + if (((c == 'v' || c == 'V') && ctrldown) && !CHAT_MUTE) { const char *paste = I_ClipboardPaste(); - + size_t chatlen; + size_t pastelen; + // create a dummy string real quickly - + if (paste == NULL) return true; - - size_t chatlen = strlen(w_chat); - size_t pastelen = strlen(paste); + + chatlen = strlen(w_chat); + pastelen = strlen(paste); if (chatlen+pastelen > HU_MAXMSGLEN) return true; // we can't paste this!! - + if (c_input >= strlen(w_chat)) // add it at the end of the string. { memcpy(&w_chat[chatlen], paste, pastelen); // copy all of that. @@ -1103,85 +1137,64 @@ boolean HU_Responder(event_t *ev) return true; } else // otherwise, we need to shift everything and make space, etc etc - { + { size_t i = HU_MAXMSGLEN-1; for (; i>=c_input;i--) { if (w_chat[i]) w_chat[i+pastelen] = w_chat[i]; - + } memcpy(&w_chat[c_input], paste, pastelen); // copy all of that. c_input += pastelen; return true; } } - - if (HU_keyInChatString(w_chat,c)) - { + + if (!CHAT_MUTE && HU_keyInChatString(w_chat,c)) + { HU_queueChatChar(c); - } + } if (c == KEY_ENTER) - { + { chat_on = false; c_input = 0; // reset input cursor chat_scrollmedown = true; // you hit enter, so you might wanna autoscroll to see what you just sent. :) - } - else if (c == KEY_ESCAPE) - { + } + else if (c == KEY_ESCAPE + || ((c == gamecontrol[gc_talkkey][0] || c == gamecontrol[gc_talkkey][1] + || c == gamecontrol[gc_teamkey][0] || c == gamecontrol[gc_teamkey][1]) + && c >= KEY_MOUSE1)) // If it's not a keyboard key, then the chat button is used as a toggle. + { chat_on = false; c_input = 0; // reset input cursor - } - else if ((c == KEY_UPARROW || c == KEY_MOUSEWHEELUP) && chat_scroll > 0) // CHAT SCROLLING YAYS! + } + else if ((c == KEY_UPARROW || c == KEY_MOUSEWHEELUP) && chat_scroll > 0 && !OLDCHAT) // CHAT SCROLLING YAYS! { chat_scroll--; justscrolledup = true; chat_scrolltime = 4; - } - else if ((c == KEY_DOWNARROW || c == KEY_MOUSEWHEELDOWN) && chat_scroll < chat_maxscroll && chat_maxscroll > 0) - { + } + else if ((c == KEY_DOWNARROW || c == KEY_MOUSEWHEELDOWN) && chat_scroll < chat_maxscroll && chat_maxscroll > 0 && !OLDCHAT) + { chat_scroll++; justscrolleddown = true; chat_scrolltime = 4; } - else if (c == KEY_LEFTARROW && c_input != 0) // i said go back + else if (c == KEY_LEFTARROW && c_input != 0 && !OLDCHAT) // i said go back c_input--; - else if (c == KEY_RIGHTARROW && c_input < strlen(w_chat)) - c_input++; + else if (c == KEY_RIGHTARROW && c_input < strlen(w_chat) && !OLDCHAT) // don't need to check for admin or w/e here since the chat won't ever contain anything if it's muted. + c_input++; return true; } return false; } + //====================================================================== // HEADS UP DRAWING //====================================================================== -// Gets string colormap, used for 0x80 color codes -// -static UINT8 *CHAT_GetStringColormap(INT32 colorflags) // pasted from video.c, sorry for the mess. -{ - switch ((colorflags & V_CHARCOLORMASK) >> V_CHARCOLORSHIFT) - { - case 1: // 0x81, purple - return purplemap; - case 2: // 0x82, yellow - return yellowmap; - case 3: // 0x83, lgreen - return lgreenmap; - case 4: // 0x84, blue - return bluemap; - case 5: // 0x85, red - return redmap; - case 6: // 0x86, gray - return graymap; - case 7: // 0x87, orange - return orangemap; - default: // reset - return NULL; - } -} - // Precompile a wordwrapped string to any given width. // This is a muuuch better method than V_WORDWRAP. // again stolen and modified a bit from video.c, don't mind me, will need to rearrange this one day. @@ -1190,7 +1203,7 @@ char *CHAT_WordWrap(INT32 x, INT32 w, INT32 option, const char *string) { int c; size_t chw, i, lastusablespace = 0; - size_t slen; + size_t slen; char *newstring = Z_StrDup(string); INT32 spacewidth = (vid.width < 640) ? 8 : 4, charwidth = (vid.width < 640) ? 8 : 4; @@ -1228,7 +1241,7 @@ char *CHAT_WordWrap(INT32 x, INT32 w, INT32 option, const char *string) { //CONS_Printf("Wrap at index %d\n", i); newstring[lastusablespace] = '\n'; - i = lastusablespace+1; + i = lastusablespace+1; lastusablespace = 0; x = 0; } @@ -1247,21 +1260,26 @@ INT16 chatx = 13, chaty = 169; // let's use this as our coordinates, shh static void HU_drawMiniChat(void) { - if (!chat_nummsg_min) - return; // needless to say it's useless to do anything if we don't have anything to draw. - INT32 x = chatx+2; INT32 charwidth = 4, charheight = 6; + INT32 boxw = cv_chatwidth.value; INT32 dx = 0, dy = 0; size_t i = chat_nummsg_min; boolean prev_linereturn = false; // a hack to prevent double \n while I have no idea why they happen in the first place. INT32 msglines = 0; // process all messages once without rendering anything or doing anything fancy so that we know how many lines each message has... + INT32 y; + + if (!chat_nummsg_min) + return; // needless to say it's useless to do anything if we don't have anything to draw. + + /*if (splitscreen > 1) + boxw = max(64, boxw/2);*/ for (; i>0; i--) { - const char *msg = CHAT_WordWrap(x+2, cv_chatwidth.value-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_mini[i-1]); + const char *msg = CHAT_WordWrap(x+2, boxw-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_mini[i-1]); size_t j = 0; INT32 linescount = 0; @@ -1273,10 +1291,10 @@ static void HU_drawMiniChat(void) { ++j; if (!prev_linereturn) - { + { linescount += 1; dx = 0; - } + } prev_linereturn = true; continue; } @@ -1294,7 +1312,7 @@ static void HU_drawMiniChat(void) } prev_linereturn = false; dx += charwidth; - if (dx >= cv_chatwidth.value) + if (dx >= boxw) { dx = 0; linescount += 1; @@ -1305,7 +1323,17 @@ static void HU_drawMiniChat(void) msglines += linescount+1; } - INT32 y = chaty - charheight*(msglines+1); + y = chaty - charheight*(msglines+1); + + if (splitscreen) + { + y -= BASEVIDHEIGHT/2; + if (splitscreen > 1) + y += 16; + } + /*else + y -= (cv_kartspeedometer.value ? 16 : 0);*/ + dx = 0; dy = 0; i = 0; @@ -1317,7 +1345,8 @@ static void HU_drawMiniChat(void) INT32 timer = ((cv_chattime.value*TICRATE)-chat_timers[i]) - cv_chattime.value*TICRATE+9; // see below... INT32 transflag = (timer >= 0 && timer <= 9) ? (timer*V_10TRANS) : 0; // you can make bad jokes out of this one. size_t j = 0; - const char *msg = CHAT_WordWrap(x+2, cv_chatwidth.value-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_mini[i]); // get the current message, and word wrap it. + const char *msg = CHAT_WordWrap(x+2, boxw-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_mini[i]); // get the current message, and word wrap it. + UINT8 *colormap = NULL; while(msg[j]) // iterate through msg { @@ -1327,16 +1356,17 @@ static void HU_drawMiniChat(void) { ++j; if (!prev_linereturn) - { + { dy += charheight; dx = 0; - } + } prev_linereturn = true; continue; } else if (msg[j] & 0x80) // stolen from video.c, nice. { clrflag = ((msg[j] & 0x7f) << V_CHARCOLORSHIFT) & V_CHARCOLORMASK; + colormap = V_GetStringColormap(clrflag); ++j; continue; } @@ -1345,8 +1375,6 @@ static void HU_drawMiniChat(void) } else { - UINT8 *colormap = CHAT_GetStringColormap(clrflag); - if (cv_chatbacktint.value) // on request of wolfy V_DrawFillConsoleMap(x + dx + 2, y+dy, charwidth, charheight, 239|V_SNAPTOBOTTOM|V_SNAPTOLEFT); @@ -1355,7 +1383,7 @@ static void HU_drawMiniChat(void) dx += charwidth; prev_linereturn = false; - if (dx >= cv_chatwidth.value) + if (dx >= boxw) { dx = 0; dy += charheight; @@ -1370,6 +1398,7 @@ static void HU_drawMiniChat(void) } + // HU_DrawUpArrow // You see, we don't have arrow graphics in 2.1 and I'm too lazy to include a 2 bytes file for it. @@ -1379,7 +1408,7 @@ static void HU_DrawUpArrow(INT32 x, INT32 y, INT32 options) V_DrawFill(x+2, y, 1, 1, 103|options); V_DrawFill(x+1, y+1, 3, 1, 103|options); V_DrawFill(x, y+2, 5, 1, 103|options); // that's the yellow part, I swear - + V_DrawFill(x+3, y, 1, 1, 26|options); V_DrawFill(x+4, y+1, 1, 1, 26|options); V_DrawFill(x+5, y+2, 1, 1, 26|options); @@ -1396,36 +1425,61 @@ static void HU_DrawDownArrow(INT32 x, INT32 y, INT32 options) V_DrawFill(x, y+1, 5, 1, 26|options); V_DrawFill(x+1, y+2, 3, 1, 26|options); V_DrawFill(x+2, y+3, 1, 1, 26|options); // that's the black part. no racism intended. i swear. - + V_DrawFill(x, y, 5, 1, 103|options); V_DrawFill(x+1, y+1, 3, 1, 103|options); V_DrawFill(x+2, y+2, 1, 1, 103|options); // that's the yellow part, I swear -} +} // HU_DrawChatLog -// TODO: fix dumb word wrapping issues static void HU_drawChatLog(INT32 offset) { + INT32 charwidth = 4, charheight = 6; + INT32 boxw = cv_chatwidth.value, boxh = cv_chatheight.value; + INT32 x = chatx+2, y, dx = 0, dy = 0; + UINT32 i = 0; + INT32 chat_topy, chat_bottomy; + boolean atbottom = false; - // before we do anything, make sure that our scroll position isn't "illegal"; + // make sure that our scroll position isn't "illegal"; if (chat_scroll > chat_maxscroll) chat_scroll = chat_maxscroll; - INT32 charwidth = 4, charheight = 6; - INT32 x = chatx+2, y = chaty - offset*charheight - (chat_scroll*charheight) - cv_chatheight.value*charheight - 12, dx = 0, dy = 0; - UINT32 i = 0; - INT32 chat_topy = y + chat_scroll*charheight; - INT32 chat_bottomy = chat_topy + cv_chatheight.value*charheight; - boolean atbottom = false; + /*if (splitscreen) + { + boxh = max(6, boxh/2); + if (splitscreen > 1) + boxw = max(64, boxw/2); + }*/ - V_DrawFillConsoleMap(chatx, chat_topy, cv_chatwidth.value, cv_chatheight.value*charheight +2, 239|V_SNAPTOBOTTOM|V_SNAPTOLEFT); // log box + // Unused SRB2KART splitscreen stuff. I'll leave it here in case it ever happens in Vanilla? + + y = chaty - offset*charheight - (chat_scroll*charheight) - boxh*charheight - 12; + + /*if (splitscreen) + { + y -= BASEVIDHEIGHT/2; + if (splitscreen > 1) + y += 16; + } + else + y -= (cv_kartspeedometer.value ? 16 : 0);*/ + + // Unused SRB2KART splitscreen stuff. I'll leave it here in case it ever happens in Vanilla? (x2) + + + chat_topy = y + chat_scroll*charheight; + chat_bottomy = chat_topy + boxh*charheight; + + V_DrawFillConsoleMap(chatx, chat_topy, boxw, boxh*charheight +2, 239|V_SNAPTOBOTTOM|V_SNAPTOLEFT); // log box for (i=0; i= chat_topy) && (y+dy < (chat_bottomy))) - { - UINT8 *colormap = CHAT_GetStringColormap(clrflag); V_DrawChatCharacter(x + dx + 2, y+dy+2, msg[j++] |V_SNAPTOBOTTOM|V_SNAPTOLEFT, !cv_allcaps.value, colormap); - } else j++; // don't forget to increment this or we'll get stuck in the limbo. } dx += charwidth; - if (dx >= cv_chatwidth.value-charwidth-2 && i= HU_FONTSTART) // end of message shouldn't count, nor should invisible characters!!!! + if (dx >= boxw-charwidth-2 && i= HU_FONTSTART) // end of message shouldn't count, nor should invisible characters!!!! { dx = 0; dy += charheight; @@ -1468,6 +1520,7 @@ static void HU_drawChatLog(INT32 offset) dx = 0; } + if (((chat_scroll >= chat_maxscroll) || (chat_scrollmedown)) && !(justscrolleddown || justscrolledup || chat_scrolltime)) // was already at the bottom of the page before new maxscroll calculation and was NOT scrolling. { atbottom = true; // we should scroll @@ -1502,14 +1555,30 @@ static void HU_drawChatLog(INT32 offset) // Draw chat input // -static INT16 typelines = 1; // number of drawfill lines we need. it's some weird hack and might be one frame off but I'm lazy to make another loop. static void HU_DrawChat(void) { INT32 charwidth = 4, charheight = 6; + INT32 boxw = cv_chatwidth.value; INT32 t = 0, c = 0, y = chaty - (typelines*charheight); - UINT32 i = 0; + UINT32 i = 0, saylen = strlen(w_chat); // You learn new things everyday! + INT32 cflag = 0; const char *ntalk = "Say: ", *ttalk = "Team: "; const char *talk = ntalk; + const char *mute = "Chat has been muted."; + + /*if (splitscreen) + { + y -= BASEVIDHEIGHT/2; + if (splitscreen > 1) + { + y += 16; + boxw = max(64, boxw/2); + } + } + else + y -= (cv_kartspeedometer.value ? 16 : 0);*/ + + // More unused SRB2KART stuff. if (teamtalk) { @@ -1522,18 +1591,35 @@ static void HU_DrawChat(void) #endif } - V_DrawFillConsoleMap(chatx, y-1, cv_chatwidth.value, (typelines*charheight), 239 | V_SNAPTOBOTTOM | V_SNAPTOLEFT); + if (CHAT_MUTE) + { + talk = mute; + typelines = 1; + cflag = V_GRAYMAP; // set text in gray if chat is muted. + } + + V_DrawFillConsoleMap(chatx, y-1, boxw, (typelines*charheight), 239 | V_SNAPTOBOTTOM | V_SNAPTOLEFT); while (talk[i]) { if (talk[i] < HU_FONTSTART) ++i; else - V_DrawChatCharacter(chatx + c + 2, y, talk[i++] |V_SNAPTOBOTTOM|V_SNAPTOLEFT, !cv_allcaps.value, NULL); + { + V_DrawChatCharacter(chatx + c + 2, y, talk[i] |V_SNAPTOBOTTOM|V_SNAPTOLEFT|cflag, !cv_allcaps.value, V_GetStringColormap(talk[i]|cflag)); + i++; + } c += charwidth; } + // if chat is muted, just draw the log and get it over with, no need to draw anything else. + if (CHAT_MUTE) + { + HU_drawChatLog(0); + return; + } + i = 0; typelines = 1; @@ -1545,12 +1631,12 @@ static void HU_DrawChat(void) boolean skippedline = false; if (c_input == (i+1)) { - int cursorx = (c+charwidth < cv_chatwidth.value-charwidth) ? (chatx + 2 + c+charwidth) : (chatx+1); // we may have to go down. + int cursorx = (c+charwidth < boxw-charwidth) ? (chatx + 2 + c+charwidth) : (chatx+1); // we may have to go down. int cursory = (cursorx != chatx+1) ? (y) : (y+charheight); if (hu_tick < 4) V_DrawChatCharacter(cursorx, cursory+1, '_' |V_SNAPTOBOTTOM|V_SNAPTOLEFT|t, !cv_allcaps.value, NULL); - if (cursorx == chatx+1) // a weirdo hack + if (cursorx == chatx+1 && saylen == i) // a weirdo hack { typelines += 1; skippedline = true; @@ -1565,38 +1651,47 @@ static void HU_DrawChat(void) V_DrawChatCharacter(chatx + c + 2, y, w_chat[i++] | V_SNAPTOBOTTOM|V_SNAPTOLEFT | t, !cv_allcaps.value, NULL); c += charwidth; - if (c > cv_chatwidth.value-(charwidth*2) && !skippedline) + if (c > boxw-(charwidth*2) && !skippedline) { c = 0; y += charheight; typelines += 1; -======= - return true; ->>>>>>> master } } - // handle /pm list. + // handle /pm list. It's messy, horrible and I don't care. if (strnicmp(w_chat, "/pm", 3) == 0 && vid.width >= 400 && !teamtalk) // 320x200 unsupported kthxbai { - i = 0; INT32 count = 0; INT32 p_dispy = chaty - charheight -1; + /*if (splitscreen) + { + p_dispy -= BASEVIDHEIGHT/2; + if (splitscreen > 1) + p_dispy += 16; + } + else + p_dispy -= (cv_kartspeedometer.value ? 16 : 0);*/ + + // more kart leftovers. + + i = 0; for(i=0; (i '9'))) || ((w_chat[4] != 0) && (((w_chat[4] < '0') || (w_chat[4] > '9'))))) && (w_chat[4] != ' ')) break; - char *nodenum = (char*) malloc(3); + nodenum = (char*) malloc(3); strncpy(nodenum, w_chat+3, 4); - UINT32 n = atoi((const char*) nodenum); // turn that into a number + n = atoi((const char*) nodenum); // turn that into a number // special cases: if ((n == 0) && !(w_chat[4] == '0')) @@ -1630,8 +1725,8 @@ static void HU_DrawChat(void) { char name[MAXPLAYERNAME+1]; strlcpy(name, player_names[i], 7); // shorten name to 7 characters. - V_DrawFillConsoleMap(chatx+ cv_chatwidth.value + 2, p_dispy- (6*count), 48, 6, 239 | V_SNAPTOBOTTOM | V_SNAPTOLEFT); // fill it like the chat so the text doesn't become hard to read because of the hud. - V_DrawSmallString(chatx+ cv_chatwidth.value + 4, p_dispy- (6*count), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, va("\x82%d\x80 - %s", i, name)); + V_DrawFillConsoleMap(chatx+ boxw + 2, p_dispy- (6*count), 48, 6, 239 | V_SNAPTOBOTTOM | V_SNAPTOLEFT); // fill it like the chat so the text doesn't become hard to read because of the hud. + V_DrawSmallString(chatx+ boxw + 4, p_dispy- (6*count), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, va("\x82%d\x80 - %s", i, name)); count++; } } @@ -1646,7 +1741,8 @@ static void HU_DrawChat(void) } -// why the fuck would you use this... + +// For anyone who, for some godforsaken reason, likes oldchat. static void HU_DrawChat_Old(void) { @@ -1681,21 +1777,21 @@ static void HU_DrawChat_Old(void) } c += charwidth; } - + if ((strlen(w_chat) == 0 || c_input == 0) && hu_tick < 4) V_DrawCharacter(HU_INPUTX+c, y+2*con_scalefactor, '_' |cv_constextsize.value | V_NOSCALESTART|t, !cv_allcaps.value); - + i = 0; while (w_chat[i]) { - + if (c_input == (i+1) && hu_tick < 4) { int cursorx = (HU_INPUTX+c+charwidth < vid.width) ? (HU_INPUTX + c + charwidth) : (HU_INPUTX); // we may have to go down. int cursory = (cursorx != HU_INPUTX) ? (y) : (y+charheight); - V_DrawCharacter(cursorx, cursory+2*con_scalefactor, '_' |cv_constextsize.value | V_NOSCALESTART|t, !cv_allcaps.value); - } - + V_DrawCharacter(cursorx, cursory+2*con_scalefactor, '_' |cv_constextsize.value | V_NOSCALESTART|t, !cv_allcaps.value); + } + //Hurdler: isn't it better like that? if (w_chat[i] < HU_FONTSTART) { @@ -1887,8 +1983,8 @@ void HU_Drawer(void) { // draw chat string plus cursor if (chat_on) - { - // count down the scroll timer. + { + // count down the scroll timer. if (chat_scrolltime > 0) chat_scrolltime--; if (!OLDCHAT) @@ -1898,28 +1994,26 @@ void HU_Drawer(void) } else { - if (!OLDCHAT) - { + typelines = 1; + chat_scrolltime = 0; + if (!OLDCHAT && cv_consolechat.value < 2) // Don't display minimized chat if you set the mode to Window (Hidden) HU_drawMiniChat(); // draw messages in a cool fashion. - chat_scrolltime = 0; // do scroll anyway. - typelines = 0; // make sure that the chat doesn't have a weird blinking huge ass square if we typed a lot last time. - } } if (netgame) // would handle that in hu_drawminichat, but it's actually kinda awkward when you're typing a lot of messages. (only handle that in netgames duh) { size_t i = 0; - + // handle spam while we're at it: for(; (i 0) stop_spamming_you_cunt[i]--; - } - + } + // handle chat timers for (i=0; (i 0) chat_timers[i]--; else @@ -2069,29 +2163,29 @@ void HU_drawPing(INT32 x, INT32 y, INT32 ping, boolean notext) SINT8 i = 0; SINT8 yoffset = 6; if (ping < 128) - { + { numbars = 3; barcolor = 184; - } + } else if (ping < 256) - { + { numbars = 2; // Apparently ternaries w/ multiple statements don't look good in C so I decided against it. barcolor = 103; - } - + } + INT32 dx = x+1 - (V_SmallStringWidth(va("%dms", ping), V_ALLOWLOWERCASE)/2); if (!notext || vid.width >= 640) // how sad, we're using a shit resolution. V_DrawSmallString(dx, y+4, V_ALLOWLOWERCASE, va("%dms", ping)); - + for (i=0; (i<3); i++) // Draw the ping bar - { + { V_DrawFill(x+2 *(i-1), y+yoffset-4, 2, 8-yoffset, 31); if (i < numbars) V_DrawFill(x+2 *(i-1), y+yoffset-3, 1, 8-yoffset-1, barcolor); - + yoffset -= 2; } -} +} // // HU_DrawTabRankings @@ -2110,15 +2204,15 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I { if (players[tab[i].num].spectator) continue; //ignore them. - + if (!splitscreen) // don't draw it on splitscreen, { if (!(tab[i].num == serverplayer)) HU_drawPing(x+ 253, y+2, playerpingtable[tab[i].num], false); //else - // V_DrawSmallString(x+ 246, y+4, V_YELLOWMAP, "SERVER"); - } - + // V_DrawSmallString(x+ 246, y+4, V_YELLOWMAP, "SERVER"); + } + V_DrawString(x + 20, y, ((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0) | ((players[tab[i].num].health > 0) ? 0 : V_60TRANS) @@ -2236,7 +2330,7 @@ static void HU_Draw32TeamTabRankings(playersort_t *tab, INT32 whiteplayer) V_DrawFill(160, 26, 1, 154, 0); //Draw a vertical line to separate the two teams. V_DrawFill(1, 26, 318, 1, 0); //And a horizontal line to make a T. V_DrawFill(1, 180, 318, 1, 0); //And a horizontal line near the bottom. - + for (i = 0; i < MAXPLAYERS; i++) { if (players[tab[i].num].spectator) @@ -2293,11 +2387,11 @@ static void HU_Draw32TeamTabRankings(playersort_t *tab, INT32 whiteplayer) } V_DrawRightAlignedThinString(x+128, y, ((players[tab[i].num].health > 0) ? 0 : V_TRANSLUCENT), va("%u", tab[i].count)); if (!splitscreen) - { + { if (!(tab[i].num == serverplayer)) HU_drawPing(x+ 135, y+3, playerpingtable[tab[i].num], true); //else - //V_DrawSmallString(x+ 129, y+4, V_YELLOWMAP, "HOST"); + //V_DrawSmallString(x+ 129, y+4, V_YELLOWMAP, "HOST"); } } } @@ -2323,37 +2417,37 @@ void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer) { smol = true; break; // don't make more loops than we need to. - } + } } else if (tab[i].color == skincolor_blueteam) //blue { if (blueplayers++ > 8) - { + { smol = true; break; - } + } } else //er? not on red or blue, so ignore them continue; - + } - + // I'll be blunt with you, this may add more lines, but I'm not adding weird cases for this, so we're executing a separate function. if (smol == true || cv_compactscoreboard.value) - { + { HU_Draw32TeamTabRankings(tab, whiteplayer); return; - } - + } + V_DrawFill(160, 26, 1, 154, 0); //Draw a vertical line to separate the two teams. V_DrawFill(1, 26, 318, 1, 0); //And a horizontal line to make a T. V_DrawFill(1, 180, 318, 1, 0); //And a horizontal line near the bottom. - + const UINT8 *colormap; char name[MAXPLAYERNAME+1]; - + i=0, redplayers=0, blueplayers=0; - + for (i = 0; i < MAXPLAYERS; i++) { if (players[tab[i].num].spectator) @@ -2412,11 +2506,11 @@ void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer) } V_DrawRightAlignedThinString(x+100, y, ((players[tab[i].num].health > 0) ? 0 : V_TRANSLUCENT), va("%u", tab[i].count)); if (!splitscreen) - { + { if (!(tab[i].num == serverplayer)) HU_drawPing(x+ 113, y+2, playerpingtable[tab[i].num], false); //else - // V_DrawSmallString(x+ 94, y+4, V_YELLOWMAP, "SERVER"); + // V_DrawSmallString(x+ 94, y+4, V_YELLOWMAP, "SERVER"); } } } @@ -2443,8 +2537,8 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline if (!(tab[i].num == serverplayer)) HU_drawPing(x+ 113, y+2, playerpingtable[tab[i].num], false); //else - // V_DrawSmallString(x+ 94, y+4, V_YELLOWMAP, "SERVER"); - + // V_DrawSmallString(x+ 94, y+4, V_YELLOWMAP, "SERVER"); + V_DrawString(x + 20, y, ((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0) | ((players[tab[i].num].health > 0) ? 0 : V_TRANSLUCENT) @@ -2542,9 +2636,9 @@ void HU_Draw32TabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, if (!(tab[i].num == serverplayer)) HU_drawPing(x+ 135, y+3, playerpingtable[tab[i].num], true); //else - // V_DrawSmallString(x+ 129, y+4, V_YELLOWMAP, "HOST"); + // V_DrawSmallString(x+ 129, y+4, V_YELLOWMAP, "HOST"); } - + V_DrawString(x + 10, y, ((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0) | ((players[tab[i].num].health > 0) ? 0 : V_TRANSLUCENT) diff --git a/src/hu_stuff.h b/src/hu_stuff.h index f61ecfbd8..ba2b02700 100644 --- a/src/hu_stuff.h +++ b/src/hu_stuff.h @@ -57,6 +57,16 @@ typedef struct // chat stuff //------------------------------------ #define HU_MAXMSGLEN 224 +#define CHAT_BUFSIZE 64 // that's enough messages, right? We'll delete the older ones when that gets out of hand. +#define OLDCHAT (cv_consolechat.value == 1 || dedicated || vid.width < 640) +#define CHAT_MUTE (cv_mute.value && !(server || IsPlayerAdmin(consoleplayer))) // this still allows to open the chat but not to type. That's used for scrolling and whatnot. +#define OLD_MUTE (OLDCHAT && cv_mute.value && !(server || IsPlayerAdmin(consoleplayer))) // this is used to prevent oldchat from opening when muted. + +// some functions +void HU_AddChatText(const char *text, boolean playsound); + +// set true when entering a chat message +extern boolean chat_on; extern patch_t *hu_font[HU_FONTSIZE], *tny_font[HU_FONTSIZE]; extern patch_t *tallnum[10]; @@ -72,22 +82,6 @@ extern patch_t *bmatcico; extern patch_t *tagico; extern patch_t *tallminus; -/*typedef struct -{ - const char *msg; // The final message we display on the HUD - tic_t time; // how much time do we still keep the message around for in the mini chat? - boolean hasmention; // make the message yellow if it has a mention because that's pretty cool. -} chatmsg_t;*/ - -#define CHAT_BUFSIZE 64 // that's enough messages, right? We'll delete the older ones when that gets out of hand. -#define OLDCHAT (cv_consolechat.value || dedicated || !netgame || vid.width < 640) - -// some functions -void HU_AddChatText(const char *text); - -// set true when entering a chat message -extern boolean chat_on; - // set true whenever the tab rankings are being shown for any reason extern boolean hu_showscores; diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 41bc55ac0..d8b8d24eb 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -23,13 +23,9 @@ #include "m_random.h" #include "s_sound.h" #include "g_game.h" -<<<<<<< HEAD #include "hu_stuff.h" // HU_AddChatText -======= -#include "hu_stuff.h" #include "console.h" #include "d_netcmd.h" // IsPlayerAdmin ->>>>>>> master #include "lua_script.h" #include "lua_libs.h" @@ -99,16 +95,14 @@ static int lib_print(lua_State *L) static int lib_chatprint(lua_State *L) { const char *str = luaL_checkstring(L, 1); // retrieve string + boolean sound = luaL_checkboolean(L, 2); // retrieve sound boolean if (str == NULL) // error if we don't have a string! return luaL_error(L, LUA_QL("tostring") " must return a string to " LUA_QL("chatprint")); int len = strlen(str); if (len > 255) // string is too long!!! return luaL_error(L, "String exceeds the 255 characters limit of the chat buffer."); - - if (OLDCHAT) - CONS_Printf("%s\n", str); - else - HU_AddChatText(str); + + HU_AddChatText(str, sound); return 0; } @@ -119,24 +113,22 @@ static int lib_chatprintf(lua_State *L) player_t *plr; if (n < 2) return luaL_error(L, "chatprintf requires at least two arguments: player and text."); - + plr = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); // retrieve player if (!plr) return LUA_ErrInvalid(L, "player_t"); if (plr != &players[consoleplayer]) return 0; - + const char *str = luaL_checkstring(L, 2); // retrieve string + boolean sound = luaL_checkboolean(L, 3); // sound? if (str == NULL) // error if we don't have a string! return luaL_error(L, LUA_QL("tostring") " must return a string to " LUA_QL("chatprintf")); int len = strlen(str); if (len > 255) // string is too long!!! return luaL_error(L, "String exceeds the 255 characters limit of the chat buffer."); - - if (OLDCHAT) - CONS_Printf("%s\n", str); - else - HU_AddChatText(str); + + HU_AddChatText(str, sound); return 0; } @@ -1758,9 +1750,9 @@ static int lib_sStartSound(lua_State *L) { if (hud_running) origin = NULL; // HUD rendering startsound shouldn't have an origin, just remove it instead of having a retarded error. - + S_StartSound(origin, sound_id); - } + } return 0; } diff --git a/src/lua_hook.h b/src/lua_hook.h index 252960edf..324babdb5 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -75,7 +75,7 @@ boolean LUAh_MobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source); // Ho boolean LUAh_BotTiccmd(player_t *bot, ticcmd_t *cmd); // Hook for B_BuildTiccmd boolean LUAh_BotAI(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd); // Hook for B_BuildTailsTiccmd by skin name boolean LUAh_LinedefExecute(line_t *line, mobj_t *mo, sector_t *sector); // Hook for linedef executors -boolean LUAh_PlayerMsg(int source, int target, int flags, char *msg); // Hook for chat messages +boolean LUAh_PlayerMsg(int source, int target, int flags, char *msg, int mute); // Hook for chat messages boolean LUAh_HurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source); // Hook for hurt messages #define LUAh_PlayerSpawn(player) LUAh_PlayerHook(player, hook_PlayerSpawn) // Hook for G_SpawnPlayer void LUAh_PlayerQuit(player_t *plr, int reason); // Hook for player quitting diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 7e544ae99..697552ec3 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -953,7 +953,9 @@ boolean LUAh_LinedefExecute(line_t *line, mobj_t *mo, sector_t *sector) } // Hook for player chat -boolean LUAh_PlayerMsg(int source, int target, int flags, char *msg) +// Added the "mute" field. It's set to true if the message was supposed to be eaten by spam protection. +// But for netgame consistency purposes, this hook is ran first reguardless, so this boolean allows for modders to adapt if they so desire. +boolean LUAh_PlayerMsg(int source, int target, int flags, char *msg, int mute) { hook_p hookp; boolean hooked = false; @@ -982,14 +984,19 @@ boolean LUAh_PlayerMsg(int source, int target, int flags, char *msg) LUA_PushUserdata(gL, &players[target-1], META_PLAYER); // target } lua_pushstring(gL, msg); // msg + if (mute) + lua_pushboolean(gL, true); // the message was supposed to be eaten by spamprotecc. + else + lua_pushboolean(gL, false); } lua_pushfstring(gL, FMT_HOOKID, hookp->id); lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - if (lua_pcall(gL, 4, 1, 0)) { + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + if (lua_pcall(gL, 5, 1, 0)) { if (!hookp->error || cv_debug & DBG_LUA) CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); lua_pop(gL, 1); @@ -1005,6 +1012,7 @@ boolean LUAh_PlayerMsg(int source, int target, int flags, char *msg) return hooked; } + // Hook for hurt messages boolean LUAh_HurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source) { diff --git a/src/m_menu.c b/src/m_menu.c index 8fedbbbe8..7647d72fc 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1321,7 +1321,7 @@ static menuitem_t OP_ChatOptionsMenu[] = {IT_STRING | IT_CVAR, NULL, "Chat Notifications", &cv_chatnotifications, 40}, {IT_STRING | IT_CVAR, NULL, "Spam Protection", &cv_chatspamprotection, 50}, {IT_STRING | IT_CVAR, NULL, "Chat background tint", &cv_chatbacktint, 60}, - {IT_STRING | IT_CVAR, NULL, "Old Console Chat", &cv_consolechat, 70}, + {IT_STRING | IT_CVAR, NULL, "Chat Mode", &cv_consolechat, 70}, }; static menuitem_t OP_ServerOptionsMenu[] = @@ -2744,7 +2744,7 @@ void M_Init(void) CV_RegisterVar(&cv_newgametype); CV_RegisterVar(&cv_chooseskin); CV_RegisterVar(&cv_autorecord); - + if (dedicated) return; diff --git a/src/v_video.c b/src/v_video.c index 438832489..651418e68 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -841,12 +841,45 @@ void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c) memset(dest, c, w * vid.bpp); } +#ifdef HWRENDER +// This is now a function since it's otherwise repeated 2 times and honestly looks retarded: +static UINT32 V_GetHWConsBackColor(void) +{ + UINT32 hwcolor; + switch (cons_backcolor.value) + { + case 0: hwcolor = 0xffffff00; break; // White + case 1: hwcolor = 0x80808000; break; // Gray + case 2: hwcolor = 0xdeb88700; break; // Sepia + case 3: hwcolor = 0x40201000; break; // Brown + case 4: hwcolor = 0xfa807200; break; // Pink + case 5: hwcolor = 0xff69b400; break; // Raspberry + case 6: hwcolor = 0xff000000; break; // Red + case 7: hwcolor = 0xffd68300; break; // Creamsicle + case 8: hwcolor = 0xff800000; break; // Orange + case 9: hwcolor = 0xdaa52000; break; // Gold + case 10: hwcolor = 0x80800000; break; // Yellow + case 11: hwcolor = 0x00ff0000; break; // Emerald + case 12: hwcolor = 0x00800000; break; // Green + case 13: hwcolor = 0x4080ff00; break; // Cyan + case 14: hwcolor = 0x4682b400; break; // Steel + case 15: hwcolor = 0x1e90ff00; break; // Periwinkle + case 16: hwcolor = 0x0000ff00; break; // Blue + case 17: hwcolor = 0xff00ff00; break; // Purple + case 18: hwcolor = 0xee82ee00; break; // Lavender + // Default green + default: hwcolor = 0x00800000; break; + } + return hwcolor; +} +#endif + + // THANK YOU MPC!!! void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c) { UINT8 *dest; - const UINT8 *deststop; INT32 u, v; UINT32 alphalevel = 0; @@ -856,21 +889,7 @@ void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c) #ifdef HWRENDER if (rendermode != render_soft && rendermode != render_none) { - UINT32 hwcolor; - switch (cons_backcolor.value) - { - case 0: hwcolor = 0xffffff00; break; // White - case 1: hwcolor = 0x80808000; break; // Gray - case 2: hwcolor = 0x40201000; break; // Brown - case 3: hwcolor = 0xff000000; break; // Red - case 4: hwcolor = 0xff800000; break; // Orange - case 5: hwcolor = 0x80800000; break; // Yellow - case 6: hwcolor = 0x00800000; break; // Green - case 7: hwcolor = 0x0000ff00; break; // Blue - case 8: hwcolor = 0x4080ff00; break; // Cyan - // Default green - default: hwcolor = 0x00800000; break; - } + UINT32 hwcolor = V_GetHWConsBackColor(); HWR_DrawConsoleFill(x, y, w, h, hwcolor, c); // we still use the regular color stuff but only for flags. actual draw color is "hwcolor" for this. return; } @@ -1107,21 +1126,7 @@ void V_DrawFadeConsBack(INT32 plines) #ifdef HWRENDER // not win32 only 19990829 by Kin if (rendermode != render_soft && rendermode != render_none) { - UINT32 hwcolor; - switch (cons_backcolor.value) - { - case 0: hwcolor = 0xffffff00; break; // White - case 1: hwcolor = 0x80808000; break; // Gray - case 2: hwcolor = 0x40201000; break; // Brown - case 3: hwcolor = 0xff000000; break; // Red - case 4: hwcolor = 0xff800000; break; // Orange - case 5: hwcolor = 0x80800000; break; // Yellow - case 6: hwcolor = 0x00800000; break; // Green - case 7: hwcolor = 0x0000ff00; break; // Blue - case 8: hwcolor = 0x4080ff00; break; // Cyan - // Default green - default: hwcolor = 0x00800000; break; - } + UINT32 hwcolor = V_GetHWConsBackColor(); HWR_DrawConsoleBack(hwcolor, plines); return; } @@ -1136,7 +1141,7 @@ void V_DrawFadeConsBack(INT32 plines) // Gets string colormap, used for 0x80 color codes // -static const UINT8 *V_GetStringColormap(INT32 colorflags) +UINT8 *V_GetStringColormap(INT32 colorflags) { switch ((colorflags & V_CHARCOLORMASK) >> V_CHARCOLORSHIFT) { @@ -1205,10 +1210,10 @@ void V_DrawChatCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed, UI w = (vid.width < 640 ) ? (SHORT(hu_font[c]->width)/2) : (SHORT(hu_font[c]->width)); // use normal sized characters if we're using a terribly low resolution. if (x + w > vid.width) return; - + V_DrawFixedPatch(x*FRACUNIT, y*FRACUNIT, (vid.width < 640) ? (FRACUNIT) : (FRACUNIT/2), flags, hu_font[c], colormap); - + } // Precompile a wordwrapped string to any given width. diff --git a/src/v_video.h b/src/v_video.h index 430b7fd47..6bec258a4 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -157,6 +157,7 @@ void V_DrawLevelTitle(INT32 x, INT32 y, INT32 option, const char *string); // wordwrap a string using the hu_font char *V_WordWrap(INT32 x, INT32 w, INT32 option, const char *string); +UINT8 *V_GetStringColormap(INT32 colorflags); // draw a string using the hu_font void V_DrawString(INT32 x, INT32 y, INT32 option, const char *string); From ff957baae377fb0760c0dad893e68f08371dfec8 Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Mon, 17 Dec 2018 21:31:31 +0100 Subject: [PATCH 21/71] Don't overlap ringslinger HUD --- src/hu_stuff.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 0bf4fcd89..b93116016 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -1325,14 +1325,13 @@ static void HU_drawMiniChat(void) y = chaty - charheight*(msglines+1); - if (splitscreen) + /*if (splitscreen) { y -= BASEVIDHEIGHT/2; if (splitscreen > 1) y += 16; - } - /*else - y -= (cv_kartspeedometer.value ? 16 : 0);*/ + }*/ + y -= (G_RingSlingerGametype() ? 16 : 0); dx = 0; dy = 0; @@ -1462,9 +1461,8 @@ static void HU_drawChatLog(INT32 offset) y -= BASEVIDHEIGHT/2; if (splitscreen > 1) y += 16; - } - else - y -= (cv_kartspeedometer.value ? 16 : 0);*/ + }*/ + y -= (G_RingSlingerGametype() ? 16 : 0); // Unused SRB2KART splitscreen stuff. I'll leave it here in case it ever happens in Vanilla? (x2) @@ -1574,9 +1572,8 @@ static void HU_DrawChat(void) y += 16; boxw = max(64, boxw/2); } - } - else - y -= (cv_kartspeedometer.value ? 16 : 0);*/ + }*/ + y -= (G_RingSlingerGametype() ? 16 : 0); // More unused SRB2KART stuff. @@ -1669,9 +1666,8 @@ static void HU_DrawChat(void) p_dispy -= BASEVIDHEIGHT/2; if (splitscreen > 1) p_dispy += 16; - } - else - p_dispy -= (cv_kartspeedometer.value ? 16 : 0);*/ + }*/ + y -= (G_RingSlingerGametype() ? 16 : 0); // more kart leftovers. From 2fdf27c5077a20bf12359188a5fdf9c1761041df Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Mon, 17 Dec 2018 21:39:49 +0100 Subject: [PATCH 22/71] make sure to change p_dispy and not y for /pm list. Also make MPC happy. --- src/hu_stuff.c | 2 +- src/v_video.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index b93116016..27144e503 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -1667,7 +1667,7 @@ static void HU_DrawChat(void) if (splitscreen > 1) p_dispy += 16; }*/ - y -= (G_RingSlingerGametype() ? 16 : 0); + p_dispy -= (G_RingSlingerGametype() ? 16 : 0); // more kart leftovers. diff --git a/src/v_video.c b/src/v_video.c index 651418e68..796e6465f 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -880,7 +880,7 @@ static UINT32 V_GetHWConsBackColor(void) void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c) { UINT8 *dest; - INT32 u, v; + INT32 u, v; UINT32 alphalevel = 0; if (rendermode == render_none) From 82601e881b8296a0cb4ed6ae44c99976a5c30fda Mon Sep 17 00:00:00 2001 From: MPC Date: Mon, 17 Dec 2018 17:57:53 -0300 Subject: [PATCH 23/71] fix my fucking code --- src/v_video.c | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/src/v_video.c b/src/v_video.c index 796e6465f..2a5eca9d0 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -881,6 +881,7 @@ void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c) { UINT8 *dest; INT32 u, v; + UINT8 *fadetable; UINT32 alphalevel = 0; if (rendermode == render_none) @@ -965,23 +966,20 @@ void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c) c &= 255; - if (!alphalevel) { - for (v = 0; v < h; v++, dest += vid.width) { - for (u = 0; u < w; u++) { - dest[u] = consolebgmap[dest[u]]; - } - } - } else { // mpc 12-04-2018 - const UINT8 *fadetable = ((UINT8 *)transtables + ((alphalevel-1)<y) ? y : x - w = clip(w,vid.width); - h = clip(h,vid.height); - for (v = 0; v < h; v++, dest += vid.width) { - for (u = 0; u < w; u++) { - dest[u] = fadetable[consolebgmap[dest[u]]]; - } - } - } + // Jimita (12-04-2018) + w = min(w, vid.width); + h = min(h, vid.height); + if (alphalevel) // Use fadetable + fadetable = ((UINT8 *)transtables + ((alphalevel-1)< Date: Mon, 17 Dec 2018 18:09:29 -0300 Subject: [PATCH 24/71] fix the fucking warning --- src/v_video.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/v_video.c b/src/v_video.c index 2a5eca9d0..cfe7d0360 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -969,9 +969,7 @@ void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c) // Jimita (12-04-2018) w = min(w, vid.width); h = min(h, vid.height); - if (alphalevel) // Use fadetable - fadetable = ((UINT8 *)transtables + ((alphalevel-1)< Date: Mon, 17 Dec 2018 18:55:21 -0500 Subject: [PATCH 25/71] Fix compile errors --- src/hu_stuff.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 27144e503..d99fe07a5 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -73,7 +73,7 @@ patch_t *cred_font[CRED_FONTSIZE]; static player_t *plr; boolean chat_on; // entering a chat message? static char w_chat[HU_MAXMSGLEN]; -static INT32 c_input = 0; // let's try to make the chat input less shitty. +static size_t c_input = 0; // let's try to make the chat input less shitty. static boolean headsupactive = false; boolean hu_showscores; // draw rankings static char hu_tick; @@ -328,7 +328,7 @@ static UINT32 chat_nummsg_min = 0; static UINT32 chat_scroll = 0; static tic_t chat_scrolltime = 0; -static INT32 chat_maxscroll = 0; // how far can we scroll? +static UINT32 chat_maxscroll = 0; // how far can we scroll? //static chatmsg_t chat_mini[CHAT_BUFSIZE]; // Display the last few messages sent. //static chatmsg_t chat_log[CHAT_BUFSIZE]; // Keep every message sent to us in memory so we can scroll n shit, it's cool. @@ -346,7 +346,7 @@ static INT16 addy = 0; // use this to make the messages scroll smoothly when one static void HU_removeChatText_Mini(void) { // MPC: Don't create new arrays, just iterate through an existing one - int i; + size_t i; for(i=0;i=c_input);m--) { if (s[m]) @@ -1199,7 +1199,7 @@ boolean HU_Responder(event_t *ev) // This is a muuuch better method than V_WORDWRAP. // again stolen and modified a bit from video.c, don't mind me, will need to rearrange this one day. // this one is simplified for the chat drawer. -char *CHAT_WordWrap(INT32 x, INT32 w, INT32 option, const char *string) +static char *CHAT_WordWrap(INT32 x, INT32 w, INT32 option, const char *string) { int c; size_t chw, i, lastusablespace = 0; @@ -2611,7 +2611,7 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline // // HU_Draw32TabRankings // -void HU_Draw32TabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, INT32 whiteplayer) +static void HU_Draw32TabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, INT32 whiteplayer) { INT32 i; const UINT8 *colormap; From 7a92c9d3d04b4dee842dda8b9b149ddda75b7812 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 17 Dec 2018 19:02:22 -0500 Subject: [PATCH 26/71] Mixed D&C fixes; replace a couple int's with INT32 --- src/hu_stuff.c | 27 +++++++++++++++++---------- src/lua_baselib.c | 12 ++++++++---- src/m_menu.c | 15 ++++++++------- 3 files changed, 33 insertions(+), 21 deletions(-) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index d99fe07a5..22e3aa3d6 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -727,9 +727,10 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) } else { + const UINT8 color = players[playernum].skincolor; cstart = "\x83"; - const UINT8 color = players[playernum].skincolor; + if (color <= SKINCOLOR_SILVER) cstart = "\x80"; // White else if (color <= SKINCOLOR_BLACK) @@ -856,9 +857,11 @@ static inline boolean HU_keyInChatString(char *s, char ch) } else if (ch == KEY_BACKSPACE) { + size_t i = c_input; + if (c_input <= 0) return false; - size_t i = c_input; + if (!s[i-1]) return false; @@ -910,14 +913,17 @@ static void HU_queueChatChar(char c) if (c == KEY_ENTER) { char buf[2+256]; - size_t ci = 2; char *msg = &buf[2]; + size_t i = 0; + size_t ci = 2; + INT32 target = 0; + do { c = w_chat[-2+ci++]; if (!c || (c >= ' ' && !(c & 0x80))) // copy printable characters and terminating '\0' only. buf[ci-1]=c; } while (c); - size_t i = 0; + for (;(i 4 && strnicmp(msg, "/pm", 3) == 0) // used /pm { + INT32 spc = 1; // used if nodenum[1] is a space. + char *nodenum = (char*) malloc(3); + const char *newmsg = msg+5+spc; + // what we're gonna do now is check if the node exists // with that logic, characters 4 and 5 are our numbers: @@ -944,8 +952,6 @@ static void HU_queueChatChar(char c) return; } - int spc = 1; // used if nodenum[1] is a space. - char *nodenum = (char*) malloc(3); strncpy(nodenum, msg+3, 5); // check for undesirable characters in our "number" if (((nodenum[0] < '0') || (nodenum[0] > '9')) || ((nodenum[1] < '0') || (nodenum[1] > '9'))) @@ -981,8 +987,8 @@ static void HU_queueChatChar(char c) HU_AddChatText(va("\x82NOTICE: \x80Player %d does not exist.", target), false); // same return; } + // we need to get rid of the /pm - const char *newmsg = msg+5+spc; memcpy(msg, newmsg, 255); } if (ci > 3) // don't send target+flags+empty message. @@ -2158,6 +2164,8 @@ void HU_drawPing(INT32 x, INT32 y, INT32 ping, boolean notext) UINT8 barcolor = 128; // color we use for the bars (green, yellow or red) SINT8 i = 0; SINT8 yoffset = 6; + INT32 dx = x+1 - (V_SmallStringWidth(va("%dms", ping), V_ALLOWLOWERCASE)/2); + if (ping < 128) { numbars = 3; @@ -2169,7 +2177,6 @@ void HU_drawPing(INT32 x, INT32 y, INT32 ping, boolean notext) barcolor = 103; } - INT32 dx = x+1 - (V_SmallStringWidth(va("%dms", ping), V_ALLOWLOWERCASE)/2); if (!notext || vid.width >= 640) // how sad, we're using a shit resolution. V_DrawSmallString(dx, y+4, V_ALLOWLOWERCASE, va("%dms", ping)); diff --git a/src/lua_baselib.c b/src/lua_baselib.c index d8b8d24eb..6b1456e9a 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -96,9 +96,11 @@ static int lib_chatprint(lua_State *L) { const char *str = luaL_checkstring(L, 1); // retrieve string boolean sound = luaL_checkboolean(L, 2); // retrieve sound boolean + int len = strlen(str); + if (str == NULL) // error if we don't have a string! return luaL_error(L, LUA_QL("tostring") " must return a string to " LUA_QL("chatprint")); - int len = strlen(str); + if (len > 255) // string is too long!!! return luaL_error(L, "String exceeds the 255 characters limit of the chat buffer."); @@ -110,7 +112,11 @@ static int lib_chatprint(lua_State *L) static int lib_chatprintf(lua_State *L) { int n = lua_gettop(L); /* number of arguments */ + const char *str = luaL_checkstring(L, 2); // retrieve string + boolean sound = luaL_checkboolean(L, 3); // sound? + int len = strlen(str); player_t *plr; + if (n < 2) return luaL_error(L, "chatprintf requires at least two arguments: player and text."); @@ -120,11 +126,9 @@ static int lib_chatprintf(lua_State *L) if (plr != &players[consoleplayer]) return 0; - const char *str = luaL_checkstring(L, 2); // retrieve string - boolean sound = luaL_checkboolean(L, 3); // sound? if (str == NULL) // error if we don't have a string! return luaL_error(L, LUA_QL("tostring") " must return a string to " LUA_QL("chatprintf")); - int len = strlen(str); + if (len > 255) // string is too long!!! return luaL_error(L, "String exceeds the 255 characters limit of the chat buffer."); diff --git a/src/m_menu.c b/src/m_menu.c index 7647d72fc..380ba266b 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1315,13 +1315,14 @@ static menuitem_t OP_GameOptionsMenu[] = static menuitem_t OP_ChatOptionsMenu[] = { - {IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Chat Box Width", &cv_chatwidth, 10}, - {IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Chat Box Height", &cv_chatheight, 20}, - {IT_STRING | IT_CVAR, NULL, "Message Fadeout Time", &cv_chattime, 30}, - {IT_STRING | IT_CVAR, NULL, "Chat Notifications", &cv_chatnotifications, 40}, - {IT_STRING | IT_CVAR, NULL, "Spam Protection", &cv_chatspamprotection, 50}, - {IT_STRING | IT_CVAR, NULL, "Chat background tint", &cv_chatbacktint, 60}, - {IT_STRING | IT_CVAR, NULL, "Chat Mode", &cv_consolechat, 70}, + {IT_STRING | IT_CVAR, NULL, "Chat Mode", &cv_consolechat, 10}, + + {IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Chat Box Width", &cv_chatwidth, 30}, + {IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Chat Box Height", &cv_chatheight, 40}, + {IT_STRING | IT_CVAR, NULL, "Message Fadeout Time", &cv_chattime, 50}, + {IT_STRING | IT_CVAR, NULL, "Chat Notifications", &cv_chatnotifications, 60}, + {IT_STRING | IT_CVAR, NULL, "Spam Protection", &cv_chatspamprotection, 70}, + {IT_STRING | IT_CVAR, NULL, "Chat background tint", &cv_chatbacktint, 80}, }; static menuitem_t OP_ServerOptionsMenu[] = From bf21b7c483a207412577e0786c98698cfcefd4b0 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 17 Dec 2018 19:03:09 -0500 Subject: [PATCH 27/71] Mixed D&C fixes for HU_DrawTeamTabRankings --- src/hu_stuff.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 22e3aa3d6..b924cf789 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -2407,6 +2407,8 @@ void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer) INT32 i,x,y; INT32 redplayers = 0, blueplayers = 0; boolean smol = false; + const UINT8 *colormap; + char name[MAXPLAYERNAME+1]; // before we draw, we must count how many players are in each team. It makes an additional loop, but we need to know if we have to draw a big or a small ranking. for (i = 0; i < MAXPLAYERS; i++) @@ -2446,9 +2448,6 @@ void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer) V_DrawFill(1, 26, 318, 1, 0); //And a horizontal line to make a T. V_DrawFill(1, 180, 318, 1, 0); //And a horizontal line near the bottom. - const UINT8 *colormap; - char name[MAXPLAYERNAME+1]; - i=0, redplayers=0, blueplayers=0; for (i = 0; i < MAXPLAYERS; i++) From 876ddd48f11a4e92c8d32b551819cf815ebecdb4 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 17 Dec 2018 19:09:05 -0500 Subject: [PATCH 28/71] Change int to INT32 --- src/hu_stuff.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index b924cf789..6d5fbfca6 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -456,8 +456,9 @@ static void DoSayCommand(SINT8 target, size_t usedargs, UINT8 flags) // what we're gonna do now is check if the node exists // with that logic, characters 4 and 5 are our numbers: const char *newmsg; - int spc = 1; // used if nodenum[1] is a space. char *nodenum = (char*) malloc(3); + INT32 spc = 1; // used if nodenum[1] is a space. + strncpy(nodenum, msg+3, 5); // check for undesirable characters in our "number" if (((nodenum[0] < '0') || (nodenum[0] > '9')) || ((nodenum[1] < '0') || (nodenum[1] > '9'))) @@ -595,7 +596,7 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) char *msg; boolean action = false; char *ptr; - int spam_eatmsg = 0; + INT32 spam_eatmsg = 0; CONS_Debug(DBG_NETPLAY,"Received SAY cmd from Player %d (%s)\n", playernum+1, player_names[playernum]); @@ -1207,7 +1208,7 @@ boolean HU_Responder(event_t *ev) // this one is simplified for the chat drawer. static char *CHAT_WordWrap(INT32 x, INT32 w, INT32 option, const char *string) { - int c; + INT32 c; size_t chw, i, lastusablespace = 0; size_t slen; char *newstring = Z_StrDup(string); @@ -1634,8 +1635,8 @@ static void HU_DrawChat(void) boolean skippedline = false; if (c_input == (i+1)) { - int cursorx = (c+charwidth < boxw-charwidth) ? (chatx + 2 + c+charwidth) : (chatx+1); // we may have to go down. - int cursory = (cursorx != chatx+1) ? (y) : (y+charheight); + INT32 cursorx = (c+charwidth < boxw-charwidth) ? (chatx + 2 + c+charwidth) : (chatx+1); // we may have to go down. + INT32 cursory = (cursorx != chatx+1) ? (y) : (y+charheight); if (hu_tick < 4) V_DrawChatCharacter(cursorx, cursory+1, '_' |V_SNAPTOBOTTOM|V_SNAPTOLEFT|t, !cv_allcaps.value, NULL); @@ -1644,7 +1645,6 @@ static void HU_DrawChat(void) typelines += 1; skippedline = true; } - } //Hurdler: isn't it better like that? @@ -1789,8 +1789,8 @@ static void HU_DrawChat_Old(void) if (c_input == (i+1) && hu_tick < 4) { - int cursorx = (HU_INPUTX+c+charwidth < vid.width) ? (HU_INPUTX + c + charwidth) : (HU_INPUTX); // we may have to go down. - int cursory = (cursorx != HU_INPUTX) ? (y) : (y+charheight); + INT32 cursorx = (HU_INPUTX+c+charwidth < vid.width) ? (HU_INPUTX + c + charwidth) : (HU_INPUTX); // we may have to go down. + INT32 cursory = (cursorx != HU_INPUTX) ? (y) : (y+charheight); V_DrawCharacter(cursorx, cursory+2*con_scalefactor, '_' |cv_constextsize.value | V_NOSCALESTART|t, !cv_allcaps.value); } From 1fcf607b41ef3578efc4fb32e30f0cde7fb7dd55 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 17 Dec 2018 21:31:00 -0500 Subject: [PATCH 29/71] Fix strncpy nodenum length overflow --- src/hu_stuff.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 6d5fbfca6..5941c68dc 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -459,7 +459,7 @@ static void DoSayCommand(SINT8 target, size_t usedargs, UINT8 flags) char *nodenum = (char*) malloc(3); INT32 spc = 1; // used if nodenum[1] is a space. - strncpy(nodenum, msg+3, 5); + strncpy(nodenum, msg+3, 3); // check for undesirable characters in our "number" if (((nodenum[0] < '0') || (nodenum[0] > '9')) || ((nodenum[1] < '0') || (nodenum[1] > '9'))) { @@ -953,7 +953,7 @@ static void HU_queueChatChar(char c) return; } - strncpy(nodenum, msg+3, 5); + strncpy(nodenum, msg+3, 3); // check for undesirable characters in our "number" if (((nodenum[0] < '0') || (nodenum[0] > '9')) || ((nodenum[1] < '0') || (nodenum[1] > '9'))) { @@ -1692,7 +1692,7 @@ static void HU_DrawChat(void) nodenum = (char*) malloc(3); - strncpy(nodenum, w_chat+3, 4); + strncpy(nodenum, w_chat+3, 3); n = atoi((const char*) nodenum); // turn that into a number // special cases: From a31b85e1244d836ace7d2287333e2ebba262dc8d Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Wed, 19 Dec 2018 16:44:57 +0100 Subject: [PATCH 30/71] Some messages relevant to discussions now go in the chat. --- src/d_clisrv.c | 30 ++++++++++++++++++------------ src/d_netcmd.c | 4 ++-- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index cd8367af8..8477aac3e 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2779,17 +2779,17 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) switch (msg) { case KICK_MSG_GO_AWAY: - CONS_Printf(M_GetText("has been kicked (Go away)\n")); + HU_AddChatText(va("\x82*%s has been kicked (Go away)", player_names[pnum]), false); kickreason = KR_KICK; break; #ifdef NEWPING case KICK_MSG_PING_HIGH: - CONS_Printf(M_GetText("left the game (Broke ping limit)\n")); + HU_AddChatText(va("\x82*%s left the game (Broke ping limit)", player_names[pnum]), false); kickreason = KR_PINGLIMIT; break; #endif case KICK_MSG_CON_FAIL: - CONS_Printf(M_GetText("left the game (Synch failure)\n")); + HU_AddChatText(va("\x82*%s left the game (Synch Failure)", player_names[pnum]), false); kickreason = KR_SYNCH; if (M_CheckParm("-consisdump")) // Helps debugging some problems @@ -2826,26 +2826,26 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) } break; case KICK_MSG_TIMEOUT: - CONS_Printf(M_GetText("left the game (Connection timeout)\n")); + HU_AddChatText(va("\x82*%s left the game (Connection timeout)", player_names[pnum]), false); kickreason = KR_TIMEOUT; break; case KICK_MSG_PLAYER_QUIT: if (netgame) // not splitscreen/bots - CONS_Printf(M_GetText("left the game\n")); + HU_AddChatText(va("\x82*%s left the game", player_names[pnum]), false); kickreason = KR_LEAVE; break; case KICK_MSG_BANNED: - CONS_Printf(M_GetText("has been banned (Don't come back)\n")); + HU_AddChatText(va("\x82*%s has been banned (Don't come back)", player_names[pnum]), false); kickreason = KR_BAN; break; case KICK_MSG_CUSTOM_KICK: READSTRINGN(*p, reason, MAX_REASONLENGTH+1); - CONS_Printf(M_GetText("has been kicked (%s)\n"), reason); + HU_AddChatText(va("\x82*%s has been kicked (%s)", player_names[pnum], reason), false); kickreason = KR_KICK; break; case KICK_MSG_CUSTOM_BAN: READSTRINGN(*p, reason, MAX_REASONLENGTH+1); - CONS_Printf(M_GetText("has been banned (%s)\n"), reason); + HU_AddChatText(va("\x82*%s has been banned (%s)", player_names[pnum], reason), false); kickreason = KR_BAN; break; } @@ -3143,11 +3143,17 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum) D_SendPlayerConfig(); addedtogame = true; } - else if (server && netgame && cv_showjoinaddress.value) + + if (netgame) { - const char *address; - if (I_GetNodeAddress && (address = I_GetNodeAddress(node)) != NULL) - CONS_Printf(M_GetText("Player Address is %s\n"), address); + if (server && cv_showjoinaddress.value) + { + const char *address; + if (I_GetNodeAddress && (address = I_GetNodeAddress(node)) != NULL) + HU_AddChatText(va("\x82*Player %d has joined the game (node %d) (%s)", newplayernum+1, node, address), false); // merge join notification + IP to avoid clogging console/chat. + } + else + HU_AddChatText(va("\x82*Player %d has joined the game (node %d)", newplayernum+1, node), false); // if you don't wanna see the join address. } if (server && multiplayer && motd[0] != '\0') diff --git a/src/d_netcmd.c b/src/d_netcmd.c index a371be320..3ed50e0b0 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -995,8 +995,8 @@ static void SetPlayerName(INT32 playernum, char *newname) if (strcasecmp(newname, player_names[playernum]) != 0) { if (netgame) - CONS_Printf(M_GetText("%s renamed to %s\n"), - player_names[playernum], newname); + HU_AddChatText(va("\x82*%s renamed to %s", player_names[playernum], newname), false); + strcpy(player_names[playernum], newname); } } From 969960a1ebbcd0c4907a9fa110d1b6cf5da2c5b3 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 20 Dec 2018 02:14:41 -0500 Subject: [PATCH 31/71] Adjust EXECVERSION define scheme* MAJOREXECVERSION and MINOREXECVERSION* GETEXECVERSION(major, minor) macro --- src/doomdef.h | 16 ++++++++++++---- src/m_misc.c | 2 +- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/doomdef.h b/src/doomdef.h index 0485698d1..0e059cd11 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -216,11 +216,19 @@ extern FILE *logstream; // Note that we use this to help keep internal testing in check; this is why v2.1.0 is not version "1". #define MODVERSION 26 -// To version config.cfg, EXECVERSION was originally equal to MODVERSION -// So keep it equal to MODVERSION, and increment MINOREXECVERSION whenever a config change -// is needed that does not correspond to an increment in MODVERSION -#define EXECVERSION 26 +// To version config.cfg, set MAJOREXECVERSION equal to MODVERSION +// and increment SUBEXECVERSION whenever a config change is needed +// that does not correspond to an increment in MODVERSION. +// If MAJOREXECVERSION increases, set MINOREXECVERSION to 0. +#define MAJOREXECVERSION 26 #define MINOREXECVERSION 1 +// (It would have been nice to use VERSION and SUBVERSION but those are different for DEVELOP builds) + +// Macros +#define GETMAJOREXECVERSION(v) (v & 0xFFFF) +#define GETMINOREXECVERSION(v) (v >> 16) +#define GETEXECVERSION(major,minor) (major + (minor << 16)) +#define EXECVERSION GETEXECVERSION(MAJOREXECVERSION, MINOREXECVERSION) // ========================================================================= diff --git a/src/m_misc.c b/src/m_misc.c index 556e56a2e..1b92a8c4f 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -563,7 +563,7 @@ void M_SaveConfig(const char *filename) // print execversion FIRST, because subsequent consvars need to be filtered // always print current EXECVERSION - fprintf(f, "%s \"%d\"\n", cv_execversion.name, (EXECVERSION + (MINOREXECVERSION << 16))); + fprintf(f, "%s \"%d\"\n", cv_execversion.name, EXECVERSION); // FIXME: save key aliases if ever implemented.. From 60bcf925253a1e24eebd221a02d284e48f19e58d Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 20 Dec 2018 02:18:59 -0500 Subject: [PATCH 32/71] Adjust execversion retrieval in CV_FilterVarByVersion --- src/command.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/command.c b/src/command.c index 3045c1769..3bd80e1ee 100644 --- a/src/command.c +++ b/src/command.c @@ -1730,11 +1730,6 @@ static boolean CV_FilterJoyAxisVars(consvar_t *v, const char *valstr) static boolean CV_FilterVarByVersion(consvar_t *v, const char *valstr) { - INT32 majorexecversion = abs(cv_execversion.value) & 0xFFFF; -#if 0 // unused for now - INT32 minorexecversion = abs(cv_execversion.value) >> 16; -#endif - // True means allow the CV change, False means block it // We only care about CV_SAVE because this filters the user's config files @@ -1742,7 +1737,7 @@ static boolean CV_FilterVarByVersion(consvar_t *v, const char *valstr) if (!(v->flags & CV_SAVE)) return true; - if (majorexecversion < 26) // 26 = 2.1.21 + if (GETMAJOREXECVERSION(cv_execversion.value) < 26) // 26 = 2.1.21 { // MOUSE SETTINGS // alwaysfreelook split between first and third person (chasefreelook) From 9d212b340b955c92800fb283114ae202e940ef5e Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 20 Dec 2018 02:35:27 -0500 Subject: [PATCH 33/71] Update code versions to 2.1.22 --- CMakeLists.txt | 2 +- appveyor.yml | 2 +- debian/changelog | 4 ++-- debian/control | 4 ++-- src/doomdef.h | 8 ++++---- src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj | 4 ++-- src/sdl12/macosx/Srb2mac.xcodeproj/project.pbxproj | 4 ++-- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ec96b7030..f2c43d02c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.0) project(SRB2 - VERSION 2.1.21 + VERSION 2.1.22 LANGUAGES C) if(${PROJECT_SOURCE_DIR} MATCHES ${PROJECT_BINARY_DIR}) diff --git a/appveyor.yml b/appveyor.yml index 061613c4d..501aee5b0 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 2.1.21.{branch}-{build} +version: 2.1.22.{branch}-{build} os: MinGW environment: diff --git a/debian/changelog b/debian/changelog index 855c1c1b3..49f4c8b6b 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,6 +1,6 @@ -srb2 (2.1.21~9) trusty; urgency=high +srb2 (2.1.22~9) trusty; urgency=high - * SRB2 v2.1.21 release + * SRB2 v2.1.22 release -- Marco Zafra Mon, 27 Nov 2018 16:45:00 -0500 diff --git a/debian/control b/debian/control index ce3b33fbd..64b96d6b9 100644 --- a/debian/control +++ b/debian/control @@ -18,7 +18,7 @@ Homepage: http://www.srb2.org Package: srb2 Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends}, srb2-data (>= 2.1.15), srb2-data (<= 2.1.21) +Depends: ${shlibs:Depends}, ${misc:Depends}, srb2-data (>= 2.1.15), srb2-data (<= 2.1.22) Description: A cross-platform 3D Sonic fangame Sonic Robo Blast 2 is a 3D open-source Sonic the Hedgehog fangame built using a modified version of the Doom Legacy @@ -31,7 +31,7 @@ Description: A cross-platform 3D Sonic fangame Package: srb2-dbg Architecture: any # FIXME: should be Depends: ${shlibs:Depends}, ${misc:Depends}, srb2-data (= 2.1.14), srb2 but dh_shlibdeps is being an asshat -Depends: libc6, ${misc:Depends}, srb2-data (>= 2.1.15), srb2-data (<= 2.1.21), srb2 +Depends: libc6, ${misc:Depends}, srb2-data (>= 2.1.15), srb2-data (<= 2.1.22), srb2 Description: A cross-platform 3D Sonic fangame Sonic Robo Blast 2 is a 3D open-source Sonic the Hedgehog fangame built using a modified version of the Doom Legacy diff --git a/src/doomdef.h b/src/doomdef.h index 796221c91..a65d7d484 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -150,9 +150,9 @@ extern FILE *logstream; // we use comprevision and compbranch instead. #else #define VERSION 201 // Game version -#define SUBVERSION 21 // more precise version number -#define VERSIONSTRING "v2.1.21" -#define VERSIONSTRINGW L"v2.1.21" +#define SUBVERSION 22 // more precise version number +#define VERSIONSTRING "v2.1.22" +#define VERSIONSTRINGW L"v2.1.22" // Hey! If you change this, add 1 to the MODVERSION below! // Otherwise we can't force updates! #endif @@ -214,7 +214,7 @@ extern FILE *logstream; // it's only for detection of the version the player is using so the MS can alert them of an update. // Only set it higher, not lower, obviously. // Note that we use this to help keep internal testing in check; this is why v2.1.0 is not version "1". -#define MODVERSION 26 +#define MODVERSION 27 // ========================================================================= diff --git a/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj b/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj index 6eabee56b..6242e0a05 100644 --- a/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj +++ b/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj @@ -1214,7 +1214,7 @@ C01FCF4B08A954540054247B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - CURRENT_PROJECT_VERSION = 2.1.21; + CURRENT_PROJECT_VERSION = 2.1.22; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", NORMALSRB2, @@ -1226,7 +1226,7 @@ C01FCF4C08A954540054247B /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - CURRENT_PROJECT_VERSION = 2.1.21; + CURRENT_PROJECT_VERSION = 2.1.22; GCC_ENABLE_FIX_AND_CONTINUE = NO; GCC_GENERATE_DEBUGGING_SYMBOLS = NO; GCC_PREPROCESSOR_DEFINITIONS = ( diff --git a/src/sdl12/macosx/Srb2mac.xcodeproj/project.pbxproj b/src/sdl12/macosx/Srb2mac.xcodeproj/project.pbxproj index 93f63309c..081d04603 100644 --- a/src/sdl12/macosx/Srb2mac.xcodeproj/project.pbxproj +++ b/src/sdl12/macosx/Srb2mac.xcodeproj/project.pbxproj @@ -1214,7 +1214,7 @@ C01FCF4B08A954540054247B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - CURRENT_PROJECT_VERSION = 2.1.21; + CURRENT_PROJECT_VERSION = 2.1.22; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", NORMALSRB2, @@ -1226,7 +1226,7 @@ C01FCF4C08A954540054247B /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - CURRENT_PROJECT_VERSION = 2.1.21; + CURRENT_PROJECT_VERSION = 2.1.22; GCC_ENABLE_FIX_AND_CONTINUE = NO; GCC_GENERATE_DEBUGGING_SYMBOLS = NO; GCC_PREPROCESSOR_DEFINITIONS = ( From 04916edc07396a1ba8605a871afad3e6ec818b5c Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 20 Dec 2018 04:03:35 -0500 Subject: [PATCH 34/71] Update EXECVERSION to MODVERSION 27 --- src/doomdef.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/doomdef.h b/src/doomdef.h index 0e059cd11..03f38098f 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -214,14 +214,14 @@ extern FILE *logstream; // it's only for detection of the version the player is using so the MS can alert them of an update. // Only set it higher, not lower, obviously. // Note that we use this to help keep internal testing in check; this is why v2.1.0 is not version "1". -#define MODVERSION 26 +#define MODVERSION 27 // To version config.cfg, set MAJOREXECVERSION equal to MODVERSION // and increment SUBEXECVERSION whenever a config change is needed // that does not correspond to an increment in MODVERSION. // If MAJOREXECVERSION increases, set MINOREXECVERSION to 0. -#define MAJOREXECVERSION 26 -#define MINOREXECVERSION 1 +#define MAJOREXECVERSION 27 +#define MINOREXECVERSION 0 // (It would have been nice to use VERSION and SUBVERSION but those are different for DEVELOP builds) // Macros From 6f8b12658690834b64499f40d6bd34a3a6585752 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 20 Dec 2018 04:04:49 -0500 Subject: [PATCH 35/71] Add G_FilterKeyByVersion() to setcontrol --- src/g_input.c | 169 +++++++++++++++++++++++++++++++++++++++++++------- src/g_input.h | 2 +- src/m_menu.c | 2 +- 3 files changed, 147 insertions(+), 26 deletions(-) diff --git a/src/g_input.c b/src/g_input.c index 44d9f2b28..954a2a58c 100644 --- a/src/g_input.c +++ b/src/g_input.c @@ -1300,30 +1300,152 @@ void G_SaveKeySetting(FILE *f) } } -void G_CheckDoubleUsage(INT32 keynum) +INT32 G_CheckDoubleUsage(INT32 keynum, boolean modify) { + INT32 result = gc_null; if (cv_controlperkey.value == 1) { INT32 i; for (i = 0; i < num_gamecontrols; i++) { if (gamecontrol[i][0] == keynum) - gamecontrol[i][0] = KEY_NULL; + { + result = i; + if (modify) gamecontrol[i][0] = KEY_NULL; + } if (gamecontrol[i][1] == keynum) - gamecontrol[i][1] = KEY_NULL; + { + result = i; + if (modify) gamecontrol[i][1] = KEY_NULL; + } if (gamecontrolbis[i][0] == keynum) - gamecontrolbis[i][0] = KEY_NULL; + { + result = i; + if (modify) gamecontrolbis[i][0] = KEY_NULL; + } if (gamecontrolbis[i][1] == keynum) - gamecontrolbis[i][1] = KEY_NULL; + { + result = i; + if (modify) gamecontrolbis[i][1] = KEY_NULL; + } + if (result && !modify) + return result; } } + return result; } -static void setcontrol(INT32 (*gc)[2], INT32 na) +static INT32 G_FilterKeyByVersion(INT32 numctrl, INT32 keyidx, INT32 player, INT32 *keynum1, INT32 *keynum2) +{ + // Special case: ignore KEY_PAUSE because it's hardcoded + if (keyidx == 0 && *keynum1 == KEY_PAUSE) + { + if (*keynum2 != KEY_PAUSE) + { + *keynum1 = *keynum2; // shift down keynum2 and continue + *keynum2 = 0; + } + else + return 0; + } + else if (keyidx == 1 && *keynum2 == KEY_PAUSE) + return 0; + +#if !defined (DC) && !defined (_PSP) && !defined (GP2X) && !defined (_NDS) && !defined(WMINPUT) && !defined(_WII) + if (GETMAJOREXECVERSION(cv_execversion.value) < 27 && ( // v2.1.22 + numctrl == gc_weaponnext || numctrl == gc_weaponprev || numctrl == gc_tossflag || + numctrl == gc_use || numctrl == gc_camreset || numctrl == gc_jump || + numctrl == gc_pause || numctrl == gc_systemmenu || numctrl == gc_camtoggle || + numctrl == gc_screenshot || numctrl == gc_talkkey || numctrl == gc_scores + )) + { + INT32 keynum = 0, existingctrl = 0; + INT32 defaultkey; + boolean defaultoverride = false; + + // get the default gamecontrol + if (player == 0 && numctrl == gc_systemmenu) + defaultkey = gamecontrol[numctrl][0]; + else + defaultkey = (player == 1 ? gamecontrolbis[numctrl][0] : gamecontrol[numctrl][1]); + + // Assign joypad button defaults if there is an open slot. + // At this point, gamecontrol/bis should have the default controls + // (unless LOADCONFIG is being run) + // + // If the player runs SETCONTROL in-game, this block should not be reached + // because EXECVERSION is locked onto the latest version. + if (keyidx == 0 && !*keynum1) + { + if (*keynum2) // push keynum2 down; this is an edge case + { + *keynum1 = *keynum2; + *keynum2 = 0; + keynum = *keynum1; + } + else + { + keynum = defaultkey; + defaultoverride = true; + } + } + else if (keyidx == 1 && (!*keynum2 || (!*keynum1 && *keynum2))) // last one is the same edge case as above + { + keynum = defaultkey; + defaultoverride = true; + } + else // default to the specified keynum + keynum = (keyidx == 1 ? *keynum2 : *keynum1); + + // Fill keynum2 with the default control + if (keyidx == 0 && !*keynum2) + { + *keynum2 = defaultkey; + + // if keynum2 already matches keynum1, we probably recursed + // so unset it + if (*keynum1 == *keynum2) + *keynum2 = 0; + } + + // check if the key is being used somewhere else before passing it + // pass it through if it's the same numctrl. This is an edge case -- when using + // LOADCONFIG, gamecontrol is not reset with default. + // + // Also, only check if we're actually overriding, to preserve behavior where + // config'd keys overwrite default keys. + if (defaultoverride) + existingctrl = G_CheckDoubleUsage(keynum, false); + + if (keynum && (!existingctrl || existingctrl == numctrl)) + return keynum; + else if (keyidx == 0 && *keynum2) + { + // try it again and push down keynum2 + *keynum1 = *keynum2; + *keynum2 = 0; + return G_FilterKeyByVersion(numctrl, keyidx, player, keynum1, keynum2); + // recursion *should* be safe because we only assign keynum2 to a joy default + // and then clear it if we find that keynum1 already has the joy default. + } + else + return 0; + } +#endif + + // All's good, so pass the keynum as-is + if (keyidx == 1) + return *keynum2; + else //if (keyidx == 0) + return *keynum1; +} + +static void setcontrol(INT32 (*gc)[2]) { INT32 numctrl; const char *namectrl; - INT32 keynum; + INT32 keynum, keynum1, keynum2; + INT32 player = ((void*)gc == (void*)&gamecontrolbis ? 1 : 0); namectrl = COM_Argv(1); for (numctrl = 0; numctrl < num_gamecontrols && stricmp(namectrl, gamecontrolname[numctrl]); @@ -1334,28 +1456,27 @@ static void setcontrol(INT32 (*gc)[2], INT32 na) CONS_Printf(M_GetText("Control '%s' unknown\n"), namectrl); return; } - keynum = G_KeyStringtoNum(COM_Argv(2)); + keynum1 = G_KeyStringtoNum(COM_Argv(2)); + keynum2 = G_KeyStringtoNum(COM_Argv(3)); + keynum = G_FilterKeyByVersion(numctrl, 0, player, &keynum1, &keynum2); - if (keynum == KEY_PAUSE) // fail silently; pause is hardcoded + (void)G_CheckDoubleUsage(keynum, true); + + // if keynum was rejected, try it again with keynum2 + if (!keynum && keynum2) { - if (na == 4) - { - na--; - keynum = G_KeyStringtoNum(COM_Argv(3)); - if (keynum == KEY_PAUSE) - return; - } - else - return; + keynum1 = keynum2; // push down keynum2 + keynum2 = 0; + keynum = G_FilterKeyByVersion(numctrl, 0, player, &keynum1, &keynum2); + (void)G_CheckDoubleUsage(keynum, true); } - G_CheckDoubleUsage(keynum); gc[numctrl][0] = keynum; - if (na == 4) + if (keynum2) { - keynum = G_KeyStringtoNum(COM_Argv(3)); - if (keynum != KEY_PAUSE) + keynum = G_FilterKeyByVersion(numctrl, 1, player, &keynum1, &keynum2); + if (keynum != gc[numctrl][0]) gc[numctrl][1] = keynum; else gc[numctrl][1] = 0; @@ -1376,7 +1497,7 @@ void Command_Setcontrol_f(void) return; } - setcontrol(gamecontrol, na); + setcontrol(gamecontrol); } void Command_Setcontrol2_f(void) @@ -1391,5 +1512,5 @@ void Command_Setcontrol2_f(void) return; } - setcontrol(gamecontrolbis, na); + setcontrol(gamecontrolbis); } diff --git a/src/g_input.h b/src/g_input.h index 557fb3bf3..1fe5a6c10 100644 --- a/src/g_input.h +++ b/src/g_input.h @@ -164,6 +164,6 @@ void Command_Setcontrol_f(void); void Command_Setcontrol2_f(void); void G_Controldefault(void); void G_SaveKeySetting(FILE *f); -void G_CheckDoubleUsage(INT32 keynum); +INT32 G_CheckDoubleUsage(INT32 keynum, boolean modify); #endif diff --git a/src/m_menu.c b/src/m_menu.c index 1e1b1e696..3403f934c 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -6955,7 +6955,7 @@ static void M_ChangecontrolResponse(event_t *ev) found = 0; setupcontrols[control][1] = KEY_NULL; //replace key 1,clear key2 } - G_CheckDoubleUsage(ch); + (void)G_CheckDoubleUsage(ch, true); setupcontrols[control][found] = ch; } S_StartSound(NULL, sfx_strpst); From 9be1ee4ac71c9292bd5a3e9e06db91ccbc2a2055 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 20 Dec 2018 17:16:04 -0500 Subject: [PATCH 36/71] Hardcode define MAJOREXECVERSION to MODVERSION --- src/doomdef.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/doomdef.h b/src/doomdef.h index 2b5c1ce3a..02b156d60 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -216,13 +216,13 @@ extern FILE *logstream; // Note that we use this to help keep internal testing in check; this is why v2.1.0 is not version "1". #define MODVERSION 27 -// To version config.cfg, set MAJOREXECVERSION equal to MODVERSION -// and increment SUBEXECVERSION whenever a config change is needed +// To version config.cfg, MAJOREXECVERSION is set equal to MODVERSION automatically. +// Increment SUBEXECVERSION whenever a config change is needed // that does not correspond to an increment in MODVERSION. // If MAJOREXECVERSION increases, set MINOREXECVERSION to 0. -#define MAJOREXECVERSION 27 +#define MAJOREXECVERSION MODVERSION #define MINOREXECVERSION 0 -// (It would have been nice to use VERSION and SUBVERSION but those are different for DEVELOP builds) +// (It would have been nice to use VERSION and SUBVERSION but those are zero'd out for DEVELOP builds) // Macros #define GETMAJOREXECVERSION(v) (v & 0xFFFF) From f1fea30045845df5092e12b2d20bdf4b1fa93f08 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 20 Dec 2018 17:56:51 -0500 Subject: [PATCH 37/71] Properly restrict EXECVERSION from cvar updates --- src/command.c | 15 ++++++++++++++- src/command.h | 1 + src/doomdef.h | 6 +++--- src/m_misc.c | 8 ++++---- 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/command.c b/src/command.c index 3bd80e1ee..c7ce2bd3c 100644 --- a/src/command.c +++ b/src/command.c @@ -49,6 +49,7 @@ static void COM_Wait_f(void); static void COM_Help_f(void); static void COM_Toggle_f(void); +static void CV_EnforceExecVersion(void); static boolean CV_FilterVarByVersion(consvar_t *v, const char *valstr); static boolean CV_Command(void); static consvar_t *CV_FindVar(const char *name); @@ -66,7 +67,8 @@ CV_PossibleValue_t CV_Natural[] = {{1, "MIN"}, {999999999, "MAX"}, {0, NULL}}; // Filter consvars by EXECVERSION // First implementation is 26 (2.1.21), so earlier configs default at 25 (2.1.20) // Also set CV_HIDEN during runtime, after config is loaded -consvar_t cv_execversion = {"execversion","25",0,CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL}; +static boolean execversion_enabled = false; +consvar_t cv_execversion = {"execversion","25",CV_CALL,CV_Unsigned, CV_EnforceExecVersion, 0, NULL, NULL, 0, 0, NULL}; // for default joyaxis detection static boolean joyaxis_default = false; @@ -1586,6 +1588,17 @@ void CV_InitFilterVar(void) joyaxis_count = joyaxis2_count = 0; } +void CV_ToggleExecVersion(boolean enable) +{ + execversion_enabled = enable; +} + +static void CV_EnforceExecVersion(void) +{ + if (!execversion_enabled) + CV_StealthSetValue(&cv_execversion, EXECVERSION); +} + static boolean CV_FilterJoyAxisVars(consvar_t *v, const char *valstr) { // If ALL axis settings are previous defaults, set them to the new defaults diff --git a/src/command.h b/src/command.h index 8dee1174c..e6767825c 100644 --- a/src/command.h +++ b/src/command.h @@ -130,6 +130,7 @@ extern CV_PossibleValue_t CV_Natural[]; extern consvar_t cv_execversion; void CV_InitFilterVar(void); +void CV_ToggleExecVersion(boolean enable); // register a variable for use at the console void CV_RegisterVar(consvar_t *variable); diff --git a/src/doomdef.h b/src/doomdef.h index 02b156d60..1cbe97f2a 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -217,9 +217,9 @@ extern FILE *logstream; #define MODVERSION 27 // To version config.cfg, MAJOREXECVERSION is set equal to MODVERSION automatically. -// Increment SUBEXECVERSION whenever a config change is needed -// that does not correspond to an increment in MODVERSION. -// If MAJOREXECVERSION increases, set MINOREXECVERSION to 0. +// Increment MINOREXECVERSION whenever a config change is needed that does not correspond +// to an increment in MODVERSION. This might never happen in practice. +// If MODVERSION increases, set MINOREXECVERSION to 0. #define MAJOREXECVERSION MODVERSION #define MINOREXECVERSION 0 // (It would have been nice to use VERSION and SUBVERSION but those are zero'd out for DEVELOP builds) diff --git a/src/m_misc.c b/src/m_misc.c index 1b92a8c4f..1ef74dc7b 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -443,7 +443,7 @@ void Command_LoadConfig_f(void) FIL_ForceExtension(configfile, ".cfg"); // temporarily reset execversion to default - cv_execversion.flags = 0; + CV_ToggleExecVersion(true); COM_BufInsertText(va("%s \"%s\"\n", cv_execversion.name, cv_execversion.defaultvalue)); CV_InitFilterVar(); @@ -452,7 +452,7 @@ void Command_LoadConfig_f(void) // don't filter anymore vars and don't let this convsvar be changed COM_BufInsertText(va("%s \"%d\"\n", cv_execversion.name, EXECVERSION)); - cv_execversion.flags = CV_HIDEN; + CV_ToggleExecVersion(false); } /** Saves the current configuration and loads another. @@ -494,7 +494,7 @@ void M_FirstLoadConfig(void) // temporarily reset execversion to default // we shouldn't need to do this, but JUST in case... - cv_execversion.flags = 0; + CV_ToggleExecVersion(true); COM_BufInsertText(va("%s \"%s\"\n", cv_execversion.name, cv_execversion.defaultvalue)); CV_InitFilterVar(); @@ -504,7 +504,7 @@ void M_FirstLoadConfig(void) // don't filter anymore vars and don't let this convsvar be changed COM_BufInsertText(va("%s \"%d\"\n", cv_execversion.name, EXECVERSION)); - cv_execversion.flags = CV_HIDEN; + CV_ToggleExecVersion(false); // make sure I_Quit() will write back the correct config // (do not write back the config if it crash before) From e20c70d5fb3c521f4deabac3525aa1126ffd771e Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 20 Dec 2018 18:27:44 -0500 Subject: [PATCH 38/71] Skip setting control if keynum is -1 (for KEY_PAUSE) handling --- src/g_input.c | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/src/g_input.c b/src/g_input.c index 954a2a58c..62a4f5aae 100644 --- a/src/g_input.c +++ b/src/g_input.c @@ -1346,10 +1346,10 @@ static INT32 G_FilterKeyByVersion(INT32 numctrl, INT32 keyidx, INT32 player, INT *keynum2 = 0; } else - return 0; + return -1; // skip setting control } else if (keyidx == 1 && *keynum2 == KEY_PAUSE) - return 0; + return -1; // skip setting control #if !defined (DC) && !defined (_PSP) && !defined (GP2X) && !defined (_NDS) && !defined(WMINPUT) && !defined(_WII) if (GETMAJOREXECVERSION(cv_execversion.value) < 27 && ( // v2.1.22 @@ -1460,26 +1460,34 @@ static void setcontrol(INT32 (*gc)[2]) keynum2 = G_KeyStringtoNum(COM_Argv(3)); keynum = G_FilterKeyByVersion(numctrl, 0, player, &keynum1, &keynum2); - (void)G_CheckDoubleUsage(keynum, true); - - // if keynum was rejected, try it again with keynum2 - if (!keynum && keynum2) + if (keynum >= 0) { - keynum1 = keynum2; // push down keynum2 - keynum2 = 0; - keynum = G_FilterKeyByVersion(numctrl, 0, player, &keynum1, &keynum2); (void)G_CheckDoubleUsage(keynum, true); + + // if keynum was rejected, try it again with keynum2 + if (!keynum && keynum2) + { + keynum1 = keynum2; // push down keynum2 + keynum2 = 0; + keynum = G_FilterKeyByVersion(numctrl, 0, player, &keynum1, &keynum2); + if (keynum >= 0) + (void)G_CheckDoubleUsage(keynum, true); + } } - gc[numctrl][0] = keynum; + if (keynum >= 0) + gc[numctrl][0] = keynum; if (keynum2) { keynum = G_FilterKeyByVersion(numctrl, 1, player, &keynum1, &keynum2); - if (keynum != gc[numctrl][0]) - gc[numctrl][1] = keynum; - else - gc[numctrl][1] = 0; + if (keynum >= 0) + { + if (keynum != gc[numctrl][0]) + gc[numctrl][1] = keynum; + else + gc[numctrl][1] = 0; + } } else gc[numctrl][1] = 0; From 06ff171e19f88db55f793e8acfb77f38d9369e3f Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 21 Dec 2018 09:38:28 -0500 Subject: [PATCH 39/71] Adjust vid.width floating point comparson for CHAT --- src/hardware/hw_draw.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index 8aa927524..d3d237c43 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -845,14 +845,14 @@ void HWR_DrawConsoleFill(INT32 x, INT32 y, INT32 w, INT32 h, UINT32 color, INT32 fw *= dupx; fh *= dupy; - if (vid.width != BASEVIDWIDTH * vid.dupx) + if (fabsf((float)vid.width - ((float)BASEVIDWIDTH * dupx)) > 1.0E-36f) { if (options & V_SNAPTORIGHT) fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)); else if (!(options & V_SNAPTOLEFT)) fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 2; } - if (vid.height != BASEVIDHEIGHT * dupy) + if (fabsf((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) > 1.0E-36f) { // same thing here if (options & V_SNAPTOBOTTOM) @@ -900,7 +900,7 @@ void HWR_DrawConsoleFill(INT32 x, INT32 y, INT32 w, INT32 h, UINT32 color, INT32 v[2].sow = v[1].sow = 1.0f; v[0].tow = v[1].tow = 0.0f; v[2].tow = v[3].tow = 1.0f; - + Surf.FlatColor.rgba = UINT2RGBA(color); Surf.FlatColor.s.alpha = 0x80; From 10521d161ce10f35ae1962b70e888580ea64ad4f Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Fri, 21 Dec 2018 22:28:28 -0500 Subject: [PATCH 40/71] Fix various bugs with the chat. --- src/d_clisrv.c | 5 +---- src/hu_stuff.c | 3 ++- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 8477aac3e..2529b05d0 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2762,7 +2762,7 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) msg = KICK_MSG_CON_FAIL; } - CONS_Printf("\x82%s ", player_names[pnum]); + //CONS_Printf("\x82%s ", player_names[pnum]); // If a verified admin banned someone, the server needs to know about it. // If the playernum isn't zero (the server) then the server needs to record the ban. @@ -3119,9 +3119,6 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum) if (newplayernum+1 > doomcom->numslots) doomcom->numslots = (INT16)(newplayernum+1); - if (netgame) - CONS_Printf(M_GetText("Player %d has joined the game (node %d)\n"), newplayernum+1, node); - // the server is creating my player if (node == mynode) { diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 5941c68dc..771628efb 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -941,7 +941,7 @@ static void HU_queueChatChar(char c) { INT32 spc = 1; // used if nodenum[1] is a space. char *nodenum = (char*) malloc(3); - const char *newmsg = msg+5+spc; + const char *newmsg; // what we're gonna do now is check if the node exists // with that logic, characters 4 and 5 are our numbers: @@ -990,6 +990,7 @@ static void HU_queueChatChar(char c) } // we need to get rid of the /pm + newmsg = msg+5+spc; memcpy(msg, newmsg, 255); } if (ci > 3) // don't send target+flags+empty message. From 619dd9d08aa285dd59ae87bb04208070e6e2cde3 Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Sat, 22 Dec 2018 12:34:17 +0100 Subject: [PATCH 41/71] Fixed various issues: added some free()s, lua_optboolean, other things, and also made sure chat can't send empty messages. --- src/g_game.c | 3 ++- src/hu_stuff.c | 40 ++++++++++++++++++++++++++++++++++++++-- src/lua_baselib.c | 4 ++-- src/m_menu.c | 4 ++++ 4 files changed, 46 insertions(+), 5 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 1c37b3b71..2f2ac043a 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3661,7 +3661,8 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean unlocktriggers = 0; // clear itemfinder, just in case - CV_StealthSetValue(&cv_itemfinder, 0); + if (!dedicated) // except in dedicated servers, where it is not registered and can actually I_Error debug builds + CV_StealthSetValue(&cv_itemfinder, 0); } // internal game map diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 771628efb..8d51bf3fa 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -465,11 +465,15 @@ static void DoSayCommand(SINT8 target, size_t usedargs, UINT8 flags) { // check if nodenum[1] is a space if (nodenum[1] == ' ') + { spc = 0; + free(nodenum); // don't need this anymore. // let it slide + } else { HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm \'.", false); + free(nodenum); return; } } @@ -479,11 +483,13 @@ static void DoSayCommand(SINT8 target, size_t usedargs, UINT8 flags) if (msg[5] != ' ') { HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm \'.", false); + free(nodenum); return; } } target = atoi((const char*) nodenum); // turn that into a number + free(nodenum); //CONS_Printf("%d\n", target); // check for target player, if it doesn't exist then we can't send the message! @@ -906,6 +912,27 @@ static boolean teamtalk = false; static INT32 head = 0, tail = 0;*/ // WHY DO YOU OVERCOMPLICATE EVERYTHING????????? +// Clear spaces so we don't end up with messages only made out of emptiness +static boolean HU_clearChatSpaces() +{ + size_t i = 0; // Used to just check our message + char c; // current character we're iterating. + boolean nothingbutspaces = true; + + for (; i < strlen(w_chat); i++) // iterate through message and eradicate all spaces that don't belong. + { + c = w_chat[i]; + if (!c) + break; // if there's nothing, it's safe to assume our message has ended, so let's not waste any more time here. + + if (c != ' ') // Isn't a space + { + nothingbutspaces = false; + } + } + return nothingbutspaces; +} + // // static void HU_queueChatChar(char c) @@ -919,6 +946,9 @@ static void HU_queueChatChar(char c) size_t ci = 2; INT32 target = 0; + if (HU_clearChatSpaces()) // Avoids being able to send empty messages, or something. + return; // If this returns true, that means our message was NOTHING but spaces, so don't send it period. + do { c = w_chat[-2+ci++]; if (!c || (c >= ' ' && !(c & 0x80))) // copy printable characters and terminating '\0' only. @@ -959,11 +989,15 @@ static void HU_queueChatChar(char c) { // check if nodenum[1] is a space if (nodenum[1] == ' ') + { spc = 0; + free(nodenum); // let it slide + } else { HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm \'.", false); + free(nodenum); return; } } @@ -973,11 +1007,13 @@ static void HU_queueChatChar(char c) if (msg[5] != ' ') { HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm \'.", false); + free(nodenum); return; } } target = atoi((const char*) nodenum); // turn that into a number + free(nodenum); //CONS_Printf("%d\n", target); // check for target player, if it doesn't exist then we can't send the message! @@ -1735,8 +1771,8 @@ static void HU_DrawChat(void) } if (count == 0) // no results. { - V_DrawFillConsoleMap(chatx-50, p_dispy- (6*count), 48, 6, 239 | V_SNAPTOBOTTOM | V_SNAPTOLEFT); // fill it like the chat so the text doesn't become hard to read because of the hud. - V_DrawSmallString(chatx-48, p_dispy- (6*count), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, "NO RESULT."); + V_DrawFillConsoleMap(chatx+boxw+2, p_dispy- (6*count), 48, 6, 239 | V_SNAPTOBOTTOM | V_SNAPTOLEFT); // fill it like the chat so the text doesn't become hard to read because of the hud. + V_DrawSmallString(chatx+boxw+4, p_dispy- (6*count), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, "NO RESULT."); } } diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 6b1456e9a..6ae4ad8cf 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -95,7 +95,7 @@ static int lib_print(lua_State *L) static int lib_chatprint(lua_State *L) { const char *str = luaL_checkstring(L, 1); // retrieve string - boolean sound = luaL_checkboolean(L, 2); // retrieve sound boolean + boolean sound = lua_optboolean(L, 2); // retrieve sound boolean int len = strlen(str); if (str == NULL) // error if we don't have a string! @@ -113,7 +113,7 @@ static int lib_chatprintf(lua_State *L) { int n = lua_gettop(L); /* number of arguments */ const char *str = luaL_checkstring(L, 2); // retrieve string - boolean sound = luaL_checkboolean(L, 3); // sound? + boolean sound = lua_optboolean(L, 3); // sound? int len = strlen(str); player_t *plr; diff --git a/src/m_menu.c b/src/m_menu.c index 380ba266b..8f71c97a2 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -6344,6 +6344,10 @@ static void M_DrawConnectIPMenu(void) static void M_ConnectIP(INT32 choice) { (void)choice; + + if (*setupm_ip == 0) + return; + COM_BufAddText(va("connect \"%s\"\n", setupm_ip)); // A little "please wait" message. From c7060aa5ad99eeaade268918fa22d6d659c92ea1 Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Sat, 22 Dec 2018 16:44:58 +0100 Subject: [PATCH 42/71] Remove mute boolean from playermsg hook, fix username stuff still being there, potential memory leaks, and added back the ip message. --- src/d_netcmd.c | 3 --- src/hu_stuff.c | 8 +------- src/lua_hook.h | 2 +- src/lua_hooklib.c | 21 +++++++-------------- src/m_menu.c | 3 +++ 5 files changed, 12 insertions(+), 25 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 3ed50e0b0..6d605ad4c 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -582,7 +582,6 @@ void D_RegisterServerCommands(void) */ void D_RegisterClientCommands(void) { - const char *username; INT32 i; for (i = 0; i < MAXSKINCOLORS; i++) @@ -639,8 +638,6 @@ void D_RegisterClientCommands(void) #endif // register these so it is saved to config - if ((username = I_GetUserName())) - cv_playername.defaultvalue = username; CV_RegisterVar(&cv_playername); CV_RegisterVar(&cv_playercolor); CV_RegisterVar(&cv_skin); // r_things.c (skin NAME) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 8d51bf3fa..fc5ae657c 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -465,11 +465,8 @@ static void DoSayCommand(SINT8 target, size_t usedargs, UINT8 flags) { // check if nodenum[1] is a space if (nodenum[1] == ' ') - { spc = 0; - free(nodenum); // don't need this anymore. // let it slide - } else { HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm \'.", false); @@ -664,7 +661,7 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) // run the lua hook even if we were supposed to eat the msg, netgame consistency goes first. #ifdef HAVE_BLUA - if (LUAh_PlayerMsg(playernum, target, flags, msg, spam_eatmsg)) + if (LUAh_PlayerMsg(playernum, target, flags, msg)) return; #endif @@ -989,11 +986,8 @@ static void HU_queueChatChar(char c) { // check if nodenum[1] is a space if (nodenum[1] == ' ') - { spc = 0; - free(nodenum); // let it slide - } else { HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm \'.", false); diff --git a/src/lua_hook.h b/src/lua_hook.h index 324babdb5..252960edf 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -75,7 +75,7 @@ boolean LUAh_MobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source); // Ho boolean LUAh_BotTiccmd(player_t *bot, ticcmd_t *cmd); // Hook for B_BuildTiccmd boolean LUAh_BotAI(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd); // Hook for B_BuildTailsTiccmd by skin name boolean LUAh_LinedefExecute(line_t *line, mobj_t *mo, sector_t *sector); // Hook for linedef executors -boolean LUAh_PlayerMsg(int source, int target, int flags, char *msg, int mute); // Hook for chat messages +boolean LUAh_PlayerMsg(int source, int target, int flags, char *msg); // Hook for chat messages boolean LUAh_HurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source); // Hook for hurt messages #define LUAh_PlayerSpawn(player) LUAh_PlayerHook(player, hook_PlayerSpawn) // Hook for G_SpawnPlayer void LUAh_PlayerQuit(player_t *plr, int reason); // Hook for player quitting diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 697552ec3..948eca84c 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -952,10 +952,8 @@ boolean LUAh_LinedefExecute(line_t *line, mobj_t *mo, sector_t *sector) return hooked; } -// Hook for player chat -// Added the "mute" field. It's set to true if the message was supposed to be eaten by spam protection. -// But for netgame consistency purposes, this hook is ran first reguardless, so this boolean allows for modders to adapt if they so desire. -boolean LUAh_PlayerMsg(int source, int target, int flags, char *msg, int mute) + +boolean LUAh_PlayerMsg(int source, int target, int flags, char *msg) { hook_p hookp; boolean hooked = false; @@ -984,19 +982,14 @@ boolean LUAh_PlayerMsg(int source, int target, int flags, char *msg, int mute) LUA_PushUserdata(gL, &players[target-1], META_PLAYER); // target } lua_pushstring(gL, msg); // msg - if (mute) - lua_pushboolean(gL, true); // the message was supposed to be eaten by spamprotecc. - else - lua_pushboolean(gL, false); } lua_pushfstring(gL, FMT_HOOKID, hookp->id); lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - if (lua_pcall(gL, 5, 1, 0)) { + lua_pushvalue(gL, -5); + lua_pushvalue(gL, -5); + lua_pushvalue(gL, -5); + lua_pushvalue(gL, -5); + if (lua_pcall(gL, 4, 1, 0)) { if (!hookp->error || cv_debug & DBG_LUA) CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); lua_pop(gL, 1); diff --git a/src/m_menu.c b/src/m_menu.c index 8f71c97a2..ba9e08f39 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -6346,7 +6346,10 @@ static void M_ConnectIP(INT32 choice) (void)choice; if (*setupm_ip == 0) + { + M_StartMessage("You must specify an IP address.\n", NULL, MM_NOTHING); return; + } COM_BufAddText(va("connect \"%s\"\n", setupm_ip)); From 5badc11159e6d754803aefaeff29cdf50e01ebc4 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 22 Dec 2018 20:17:50 -0500 Subject: [PATCH 43/71] Fix integer overflow on for loop decrements --- src/hu_stuff.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index fc5ae657c..984d1016d 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -847,10 +847,13 @@ static inline boolean HU_keyInChatString(char *s, char ch) // move everything past c_input for new characters: size_t m = HU_MAXMSGLEN-1; - for (;(m>=c_input);m--) + while (m>=c_input) { if (s[m]) s[m+1] = (s[m]); + if (m == 0) // prevent overflow + break; + m--; } s[c_input] = ch; // and replace this. } @@ -1177,11 +1180,13 @@ boolean HU_Responder(event_t *ev) else // otherwise, we need to shift everything and make space, etc etc { size_t i = HU_MAXMSGLEN-1; - for (; i>=c_input;i--) + while (i >= c_input) { if (w_chat[i]) w_chat[i+pastelen] = w_chat[i]; - + if (i == 0) // prevent overflow + break; + i--; } memcpy(&w_chat[c_input], paste, pastelen); // copy all of that. c_input += pastelen; From 0f0e30924f3d32571efc30595f42a83003581ffd Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 22 Dec 2018 20:35:12 -0500 Subject: [PATCH 44/71] One more free(nodenum) --- src/hu_stuff.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 984d1016d..094db29e7 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -1730,6 +1730,7 @@ static void HU_DrawChat(void) nodenum = (char*) malloc(3); strncpy(nodenum, w_chat+3, 3); n = atoi((const char*) nodenum); // turn that into a number + free(nodenum); // special cases: if ((n == 0) && !(w_chat[4] == '0')) From fb3722a6f37e1e0182762e3fbee001b3a4c37ea5 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 22 Dec 2018 20:52:32 -0500 Subject: [PATCH 45/71] Accommodate Kart splitscreen code for CHAT via #define NETSPLITSCREEN --- src/d_net.h | 1 + src/hu_stuff.c | 32 ++++++++++++++++---------------- src/hu_stuff.h | 4 ++++ 3 files changed, 21 insertions(+), 16 deletions(-) diff --git a/src/d_net.h b/src/d_net.h index 55ea308b3..61c669dbb 100644 --- a/src/d_net.h +++ b/src/d_net.h @@ -22,6 +22,7 @@ #define MAXNETNODES 32 #define BROADCASTADDR MAXNETNODES #define MAXSPLITSCREENPLAYERS 2 // Max number of players on a single computer +//#define NETSPLITSCREEN // Kart's splitscreen netgame feature #define STATLENGTH (TICRATE*2) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 094db29e7..1f474d226 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -1488,27 +1488,27 @@ static void HU_drawChatLog(INT32 offset) if (chat_scroll > chat_maxscroll) chat_scroll = chat_maxscroll; - /*if (splitscreen) +#ifdef NETSPLITSCREEN + if (splitscreen) { boxh = max(6, boxh/2); if (splitscreen > 1) boxw = max(64, boxw/2); - }*/ - - // Unused SRB2KART splitscreen stuff. I'll leave it here in case it ever happens in Vanilla? + } +#endif y = chaty - offset*charheight - (chat_scroll*charheight) - boxh*charheight - 12; - /*if (splitscreen) +#ifdef NETSPLITSCREEN + if (splitscreen) { y -= BASEVIDHEIGHT/2; if (splitscreen > 1) y += 16; - }*/ + } +#endif y -= (G_RingSlingerGametype() ? 16 : 0); - // Unused SRB2KART splitscreen stuff. I'll leave it here in case it ever happens in Vanilla? (x2) - chat_topy = y + chat_scroll*charheight; chat_bottomy = chat_topy + boxh*charheight; @@ -1607,7 +1607,8 @@ static void HU_DrawChat(void) const char *talk = ntalk; const char *mute = "Chat has been muted."; - /*if (splitscreen) +#ifdef NETSPLITSCREEN + if (splitscreen) { y -= BASEVIDHEIGHT/2; if (splitscreen > 1) @@ -1615,11 +1616,10 @@ static void HU_DrawChat(void) y += 16; boxw = max(64, boxw/2); } - }*/ + } +#endif y -= (G_RingSlingerGametype() ? 16 : 0); - // More unused SRB2KART stuff. - if (teamtalk) { talk = ttalk; @@ -1703,16 +1703,16 @@ static void HU_DrawChat(void) { INT32 count = 0; INT32 p_dispy = chaty - charheight -1; - /*if (splitscreen) +#ifdef NETSPLITSCREEN + if (splitscreen) { p_dispy -= BASEVIDHEIGHT/2; if (splitscreen > 1) p_dispy += 16; - }*/ + } +#endif p_dispy -= (G_RingSlingerGametype() ? 16 : 0); - // more kart leftovers. - i = 0; for(i=0; (i Date: Sat, 22 Dec 2018 20:57:53 -0500 Subject: [PATCH 46/71] Draw up and down arrows by string --- src/hu_stuff.c | 38 ++------------------------------------ 1 file changed, 2 insertions(+), 36 deletions(-) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 1f474d226..40c065382 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -1440,39 +1440,6 @@ static void HU_drawMiniChat(void) } - -// HU_DrawUpArrow -// You see, we don't have arrow graphics in 2.1 and I'm too lazy to include a 2 bytes file for it. - -static void HU_DrawUpArrow(INT32 x, INT32 y, INT32 options) -{ - // Ok I'm super lazy so let's make this as the worst draw function: - V_DrawFill(x+2, y, 1, 1, 103|options); - V_DrawFill(x+1, y+1, 3, 1, 103|options); - V_DrawFill(x, y+2, 5, 1, 103|options); // that's the yellow part, I swear - - V_DrawFill(x+3, y, 1, 1, 26|options); - V_DrawFill(x+4, y+1, 1, 1, 26|options); - V_DrawFill(x+5, y+2, 1, 1, 26|options); - V_DrawFill(x, y+3, 6, 1, 26|options); // that's the black part. no racism intended. i swear. -} - -// HU_DrawDownArrow -// Should we talk about anime waifus to pass the time? This feels retarded. - -static void HU_DrawDownArrow(INT32 x, INT32 y, INT32 options) -{ - // Ok I'm super lazy so let's make this as the worst draw function: - V_DrawFill(x, y, 6, 1, 26|options); - V_DrawFill(x, y+1, 5, 1, 26|options); - V_DrawFill(x+1, y+2, 3, 1, 26|options); - V_DrawFill(x+2, y+3, 1, 1, 26|options); // that's the black part. no racism intended. i swear. - - V_DrawFill(x, y, 5, 1, 103|options); - V_DrawFill(x+1, y+1, 3, 1, 103|options); - V_DrawFill(x+2, y+2, 1, 1, 103|options); // that's the yellow part, I swear -} - // HU_DrawChatLog static void HU_drawChatLog(INT32 offset) @@ -1580,11 +1547,10 @@ static void HU_drawChatLog(INT32 offset) chat_scroll = chat_maxscroll; // draw arrows to indicate that we can (or not) scroll. - if (chat_scroll > 0) - HU_DrawUpArrow(chatx-8, ((justscrolledup) ? (chat_topy-1) : (chat_topy)), V_SNAPTOBOTTOM | V_SNAPTOLEFT); + V_DrawString(chatx-8, ((justscrolledup) ? (chat_topy-1) : (chat_topy)), V_SNAPTOBOTTOM | V_SNAPTOLEFT | V_YELLOWMAP, "\x1A"); // up arrow if (chat_scroll < chat_maxscroll) - HU_DrawDownArrow(chatx-8, chat_bottomy-((justscrolleddown) ? 3 : 4), V_SNAPTOBOTTOM | V_SNAPTOLEFT); + V_DrawString(chatx-8, chat_bottomy-((justscrolleddown) ? 3 : 4), V_SNAPTOBOTTOM | V_SNAPTOLEFT | V_YELLOWMAP, "\x1B"); // down arrow justscrolleddown = false; justscrolledup = false; From 7e9411f320b75f7f90cc9f16a501d7aed7e88ae4 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 22 Dec 2018 21:17:01 -0500 Subject: [PATCH 47/71] Minor code cleanup, CHAT --- src/hu_stuff.c | 238 ++++++++++++++++++++++++------------------------- 1 file changed, 119 insertions(+), 119 deletions(-) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 40c065382..1fea28f04 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -73,7 +73,7 @@ patch_t *cred_font[CRED_FONTSIZE]; static player_t *plr; boolean chat_on; // entering a chat message? static char w_chat[HU_MAXMSGLEN]; -static size_t c_input = 0; // let's try to make the chat input less shitty. +static size_t c_input = 0; // let's try to make the chat input less shitty. static boolean headsupactive = false; boolean hu_showscores; // draw rankings static char hu_tick; @@ -328,20 +328,20 @@ static UINT32 chat_nummsg_min = 0; static UINT32 chat_scroll = 0; static tic_t chat_scrolltime = 0; -static UINT32 chat_maxscroll = 0; // how far can we scroll? +static UINT32 chat_maxscroll = 0; // how far can we scroll? -//static chatmsg_t chat_mini[CHAT_BUFSIZE]; // Display the last few messages sent. -//static chatmsg_t chat_log[CHAT_BUFSIZE]; // Keep every message sent to us in memory so we can scroll n shit, it's cool. +//static chatmsg_t chat_mini[CHAT_BUFSIZE]; // Display the last few messages sent. +//static chatmsg_t chat_log[CHAT_BUFSIZE]; // Keep every message sent to us in memory so we can scroll n shit, it's cool. -static char chat_log[CHAT_BUFSIZE][255]; // hold the last 48 or so messages in that log. -static char chat_mini[8][255]; // display up to 8 messages that will fade away / get overwritten +static char chat_log[CHAT_BUFSIZE][255]; // hold the last 48 or so messages in that log. +static char chat_mini[8][255]; // display up to 8 messages that will fade away / get overwritten static tic_t chat_timers[8]; -static boolean chat_scrollmedown = false; // force instant scroll down on the chat log. Happens when you open it / send a message. +static boolean chat_scrollmedown = false; // force instant scroll down on the chat log. Happens when you open it / send a message. // remove text from minichat table -static INT16 addy = 0; // use this to make the messages scroll smoothly when one fades away +static INT16 addy = 0; // use this to make the messages scroll smoothly when one fades away static void HU_removeChatText_Mini(void) { @@ -351,7 +351,7 @@ static void HU_removeChatText_Mini(void) strcpy(chat_mini[i], chat_mini[i+1]); chat_timers[i] = chat_timers[i+1]; } - chat_nummsg_min--; // lost 1 msg. + chat_nummsg_min--; // lost 1 msg. // use addy and make shit slide smoothly af. addy += (vid.width < 640) ? 8 : 6; @@ -366,16 +366,16 @@ static void HU_removeChatText_Log(void) for(i=0;i