From 773d564d6adb336808c119b23ce8f2e2a43bb529 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Mon, 30 Dec 2019 00:22:27 -0300 Subject: [PATCH 01/83] MUSICDEF parser changes. --- src/s_sound.c | 91 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 70 insertions(+), 21 deletions(-) diff --git a/src/s_sound.c b/src/s_sound.c index a49499040..1b7c7c8c5 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1469,6 +1469,7 @@ void S_LoadMusicDefs(UINT16 wadnum) char *buf2; char *stoken; char *value; + char *textline; size_t size; INT32 i; musicdef_t *def = NULL; @@ -1560,9 +1561,63 @@ skip_lump: } else { - value = strtok(NULL, "\r\n= "); + // If this is set true, the line was invalid. + boolean brokenline = false; + // Delimit only by line break. + value = strtok(NULL, "\r\n"); + + // Find the equals sign. + value = strchr(value, '='); + + // It's not there?! if (!value) + brokenline = true; + else + { + // Skip the equals sign. + value++; + + // Now skip funny whitespace. + for (;;) + { + char c = value[0]; + if (c == '\0') // :NOTHING: + { + brokenline = true; + break; + } + else if (c == ' ' || c == '\t') + value++; + else + break; + } + } + + // If the line is valid, copy the text line from the lump data. + if (!brokenline) + { + // strtok returns memory that already belongs to the input string. + value = buf + (value - buf2); + + // Find the length of the line. + size = 0; + for (;;) + { + char c = value[size]; + if (c == '\n' || c == '\r' || c == '\0') + break; + size++; + } + + // Copy the line. + textline = malloc(size+1); + if (!textline) + I_Error("S_LoadMusicDefs: No more free memory for text line\n"); + M_Memcpy(textline, value, size); + textline[size] = '\0'; + } + else { CONS_Alert(CONS_WARNING, "MUSICDEF: Field '%s' is missing value. (file %s, line %d)\n", stoken, wadfiles[wadnum]->filename, line); stoken = strtok(NULL, "\r\n"); // skip end of line @@ -1572,53 +1627,44 @@ skip_lump: if (!def) { CONS_Alert(CONS_ERROR, "MUSICDEF: No music definition before field '%s'. (file %s, line %d)\n", stoken, wadfiles[wadnum]->filename, line); + free(textline); free(buf2); return; } - i = atoi(value); + i = atoi(textline); if (!stricmp(stoken, "usage")) { #if 0 // Ignore for now - STRBUFCPY(def->usage, value); - for (value = def->usage; *value; value++) - if (*value == '_') *value = ' '; // turn _ into spaces. + STRBUFCPY(def->usage, textline); //CONS_Printf("S_LoadMusicDefs: Set usage to '%s'\n", def->usage); #endif } else if (!stricmp(stoken, "source")) { #if 0 // Ignore for now - STRBUFCPY(def->source, value); - for (value = def->source; *value; value++) - if (*value == '_') *value = ' '; // turn _ into spaces. + STRBUFCPY(def->source, textline); //CONS_Printf("S_LoadMusicDefs: Set source to '%s'\n", def->usage); #endif } else if (!stricmp(stoken, "title")) { - STRBUFCPY(def->title, value); - for (value = def->title; *value; value++) - if (*value == '_') *value = ' '; // turn _ into spaces. + STRBUFCPY(def->title, textline); //CONS_Printf("S_LoadMusicDefs: Set title to '%s'\n", def->source); } else if (!stricmp(stoken, "alttitle")) { - STRBUFCPY(def->alttitle, value); - for (value = def->alttitle; *value; value++) - if (*value == '_') *value = ' '; // turn _ into spaces. + STRBUFCPY(def->alttitle, textline); //CONS_Printf("S_LoadMusicDefs: Set alttitle to '%s'\n", def->source); } else if (!stricmp(stoken, "authors")) { - STRBUFCPY(def->authors, value); - for (value = def->authors; *value; value++) - if (*value == '_') *value = ' '; // turn _ into spaces. + STRBUFCPY(def->authors, textline); //CONS_Printf("S_LoadMusicDefs: Set authors to '%s'\n", def->source); } else if (!stricmp(stoken, "soundtestpage")) { def->soundtestpage = (UINT8)i; } else if (!stricmp(stoken, "soundtestcond")) { // Convert to map number - if (value[0] >= 'A' && value[0] <= 'Z' && value[2] == '\0') - i = M_MapNumber(value[0], value[1]); + if (textline[0] >= 'A' && textline[0] <= 'Z' && textline[2] == '\0') + i = M_MapNumber(textline[0], textline[1]); def->soundtestcond = (INT16)i; } else if (!stricmp(stoken, "stoppingtime")) { - double stoppingtime = atof(value)*TICRATE; + double stoppingtime = atof(textline)*TICRATE; def->stoppingtics = (tic_t)stoppingtime; } else if (!stricmp(stoken, "bpm")) { - double bpm = atof(value); + double bpm = atof(textline); fixed_t bpmf = FLOAT_TO_FIXED(bpm); if (bpmf > 0) def->bpm = FixedDiv((60*TICRATE)<filename, line); } + // Free the temporary line from memory. + free(textline); + skip_field: stoken = strtok(NULL, "\r\n= "); line++; From c303b1a435c61ea46e98a4ceee8c002921b00e3b Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Mon, 30 Dec 2019 01:39:34 -0300 Subject: [PATCH 02/83] Use strspn here. --- src/s_sound.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/src/s_sound.c b/src/s_sound.c index 1b7c7c8c5..11774b5ba 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1579,19 +1579,10 @@ skip_lump: value++; // Now skip funny whitespace. - for (;;) - { - char c = value[0]; - if (c == '\0') // :NOTHING: - { - brokenline = true; - break; - } - else if (c == ' ' || c == '\t') - value++; - else - break; - } + if (value[0] == '\0') // :NOTHING: + brokenline = true; + else + value += strspn(value, "\t "); } // If the line is valid, copy the text line from the lump data. From 757480f21940e9acfe3759d68d01c69404c12de0 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Mon, 30 Dec 2019 02:07:39 -0300 Subject: [PATCH 03/83] Some cleanup in general. --- src/s_sound.c | 51 ++++++++++++++++++++++++++------------------------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/src/s_sound.c b/src/s_sound.c index 11774b5ba..b1d80f43b 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1464,9 +1464,9 @@ static UINT16 W_CheckForMusicDefInPwad(UINT16 wadid) void S_LoadMusicDefs(UINT16 wadnum) { - UINT16 lump; - char *buf; - char *buf2; + UINT16 lumpnum; + char *lump, *buf; + char *musdeftext; char *stoken; char *value; char *textline; @@ -1475,21 +1475,27 @@ void S_LoadMusicDefs(UINT16 wadnum) musicdef_t *def = NULL; UINT16 line = 1; // for better error msgs - lump = W_CheckForMusicDefInPwad(wadnum); - if (lump == INT16_MAX) + lumpnum = W_CheckForMusicDefInPwad(wadnum); + if (lumpnum == INT16_MAX) return; - buf = W_CacheLumpNumPwad(wadnum, lump, PU_CACHE); - size = W_LumpLengthPwad(wadnum, lump); + lump = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); + size = W_LumpLengthPwad(wadnum, lumpnum); + + // Null-terminated MUSICDEF lump. + musdeftext = malloc(size+1); + if (!musdeftext) + I_Error("S_LoadMusicDefs: No more free memory for the parser\n"); + M_Memcpy(musdeftext, lump, size); + musdeftext[size] = '\0'; // for strtok - buf2 = malloc(size+1); - if (!buf2) - I_Error("S_LoadMusicDefs: No more free memory\n"); - M_Memcpy(buf2,buf,size); - buf2[size] = '\0'; + buf = malloc(size+1); + if (!buf) + I_Error("S_LoadMusicDefs: No more free memory for the parser\n"); + M_Memcpy(buf, musdeftext, size+1); - stoken = strtok (buf2, "\r\n "); + stoken = strtok(buf, "\r\n "); // Find music def while (stoken) { @@ -1589,17 +1595,10 @@ skip_lump: if (!brokenline) { // strtok returns memory that already belongs to the input string. - value = buf + (value - buf2); + value = musdeftext + (value - buf); // Find the length of the line. - size = 0; - for (;;) - { - char c = value[size]; - if (c == '\n' || c == '\r' || c == '\0') - break; - size++; - } + size = strcspn(value, "\r\n"); // Copy the line. textline = malloc(size+1); @@ -1619,7 +1618,8 @@ skip_lump: { CONS_Alert(CONS_ERROR, "MUSICDEF: No music definition before field '%s'. (file %s, line %d)\n", stoken, wadfiles[wadnum]->filename, line); free(textline); - free(buf2); + free(buf); + free(musdeftext); return; } @@ -1663,7 +1663,7 @@ skip_lump: CONS_Alert(CONS_WARNING, "MUSICDEF: Invalid field '%s'. (file %s, line %d)\n", stoken, wadfiles[wadnum]->filename, line); } - // Free the temporary line from memory. + // Free the temporary text line from memory. free(textline); skip_field: @@ -1672,7 +1672,8 @@ skip_field: } } - free(buf2); + free(buf); + free(musdeftext); return; } From da226139f11bfc1e588ccd379c87d01db301ad1c Mon Sep 17 00:00:00 2001 From: lachwright Date: Fri, 3 Jan 2020 13:12:18 +0800 Subject: [PATCH 04/83] Add generic signpost sprite for skins that don't have one --- src/dehacked.c | 1 + src/info.c | 27 ++++++++++++++------------- src/info.h | 1 + src/p_enemy.c | 22 ++++++++++++++++++---- 4 files changed, 34 insertions(+), 17 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 4b6d76a6a..b412fa0b2 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -6009,6 +6009,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_SIGNSTOP", "S_SIGNBOARD", "S_EGGMANSIGN", + "S_CLEARSIGN", // Spike Ball "S_SPIKEBALL1", diff --git a/src/info.c b/src/info.c index 30f3e96d0..4e9cbbb10 100644 --- a/src/info.c +++ b/src/info.c @@ -1849,18 +1849,19 @@ state_t states[NUMSTATES] = {SPR_BBLS, 3, 8, {A_BubbleCheck}, 0, 0, S_BUBBLES1}, // S_BUBBLES4 // Level End Sign - {SPR_SIGN, 0, -1, {A_SignPlayer}, -3, 0, S_NULL}, // S_SIGN - {SPR_SIGN, 0, 1, {A_SignSpin}, 30, 0, S_SIGNSPIN2}, // S_SIGNSPIN1 - {SPR_SIGN, 0, 0, {A_Repeat}, 4, S_SIGNSPIN1, S_SIGNSPIN3}, // S_SIGNSPIN2 - {SPR_SIGN, 0, 0, {A_SignPlayer}, -2, 0, S_SIGNSPIN4}, // S_SIGNSPIN3 - {SPR_SIGN, 0, 1, {A_SignSpin}, 30, 0, S_SIGNSPIN5}, // S_SIGNSPIN4 - {SPR_SIGN, 0, 0, {A_Repeat}, 4, S_SIGNSPIN4, S_SIGNSPIN6}, // S_SIGNSPIN5 - {SPR_SIGN, 0, 0, {A_SignPlayer}, -3, 0, S_SIGNSPIN1}, // S_SIGNSPIN6 - {SPR_SIGN, 0, 1, {A_SignPlayer}, -1, 0, S_SIGNSLOW}, // S_SIGNPLAYER - {SPR_SIGN, 0, 1, {A_SignSpin}, 30, 0, S_SIGNSLOW}, // S_SIGNSLOW - {SPR_SIGN, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SIGNSTOP - {SPR_SIGN, FF_PAPERSPRITE|2, -1, {NULL}, 0, 0, S_NULL}, // S_SIGNBOARD - {SPR_SIGN, FF_PAPERSPRITE|1, -1, {NULL}, 0, 29, S_NULL}, // S_EGGMANSIGN + {SPR_SIGN, 0, -1, {A_SignPlayer}, -3, 0, S_NULL}, // S_SIGN + {SPR_SIGN, 0, 1, {A_SignSpin}, 30, 0, S_SIGNSPIN2}, // S_SIGNSPIN1 + {SPR_SIGN, 0, 0, {A_Repeat}, 4, S_SIGNSPIN1, S_SIGNSPIN3}, // S_SIGNSPIN2 + {SPR_SIGN, 0, 0, {A_SignPlayer}, -2, 0, S_SIGNSPIN4}, // S_SIGNSPIN3 + {SPR_SIGN, 0, 1, {A_SignSpin}, 30, 0, S_SIGNSPIN5}, // S_SIGNSPIN4 + {SPR_SIGN, 0, 0, {A_Repeat}, 4, S_SIGNSPIN4, S_SIGNSPIN6}, // S_SIGNSPIN5 + {SPR_SIGN, 0, 0, {A_SignPlayer}, -3, 0, S_SIGNSPIN1}, // S_SIGNSPIN6 + {SPR_SIGN, 0, 1, {A_SignPlayer}, -1, 0, S_SIGNSLOW}, // S_SIGNPLAYER + {SPR_SIGN, 0, 1, {A_SignSpin}, 30, 0, S_SIGNSLOW}, // S_SIGNSLOW + {SPR_SIGN, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SIGNSTOP + {SPR_SIGN, FF_PAPERSPRITE| 2, -1, {NULL}, 0, 0, S_NULL}, // S_SIGNBOARD + {SPR_SIGN, FF_PAPERSPRITE| 1, -1, {NULL}, 0, 29, S_NULL}, // S_EGGMANSIGN + {SPR_SIGN, FF_PAPERSPRITE|18, -1, {NULL}, 0, 29, S_NULL}, // S_CLEARSIGN // Spike Ball {SPR_SPIK, 0, 1, {NULL}, 0, 0, S_SPIKEBALL2}, // S_SPIKEBALL1 @@ -7850,7 +7851,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = MT_SPARK, // painchance sfx_s3kb8, // painsound S_EGGMANSIGN, // meleestate - S_NULL, // missilestate + S_CLEARSIGN, // missilestate S_SIGNSTOP, // deathstate S_NULL, // xdeathstate sfx_s3k64, // deathsound diff --git a/src/info.h b/src/info.h index 261abbac5..de766503a 100644 --- a/src/info.h +++ b/src/info.h @@ -2021,6 +2021,7 @@ typedef enum state S_SIGNSTOP, S_SIGNBOARD, S_EGGMANSIGN, + S_CLEARSIGN, // Spike Ball S_SPIKEBALL1, diff --git a/src/p_enemy.c b/src/p_enemy.c index ce201844f..c8edf293a 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -5177,6 +5177,8 @@ void A_SignPlayer(mobj_t *actor) if (signcolor) ; + else if (!skin->sprites[SPR2_SIGN].numframes) + signcolor = facecolor; else if ((actor->target->player->skincolor == skin->prefcolor) && (skin->prefoppositecolor)) // Set it as the skin's preferred oppositecolor? signcolor = skin->prefoppositecolor; else if (actor->target->player->skincolor) // Set the sign to be an appropriate background color for this player's skincolor. @@ -5221,21 +5223,33 @@ void A_SignPlayer(mobj_t *actor) facecolor = skin->prefcolor; if (signcolor) ; + else if (!skin->sprites[SPR2_SIGN].numframes) + signcolor = facecolor; else if (skin->prefoppositecolor) signcolor = skin->prefoppositecolor; else if (facecolor) signcolor = Color_Opposite[facecolor - 1][0]; } - if (skin && skin->sprites[SPR2_SIGN].numframes) // player face + if (skin) { - ov->color = facecolor; - ov->skin = skin; - P_SetMobjState(ov, actor->info->seestate); // S_PLAY_SIGN + if (skin->sprites[SPR2_SIGN].numframes) // player face + { + ov->color = facecolor; + ov->skin = skin; + P_SetMobjState(ov, actor->info->seestate); // S_PLAY_SIGN + } + else // CLEAR! sign + { + ov->color = SKINCOLOR_NONE; + ov->skin = NULL; // needs to be NULL in the case of SF_HIRES characters + P_SetMobjState(ov, actor->info->missilestate); // S_CLEARSIGN + } } else // Eggman face { ov->color = SKINCOLOR_NONE; + ov->skin = NULL; P_SetMobjState(ov, actor->info->meleestate); // S_EGGMANSIGN if (!signcolor) signcolor = SKINCOLOR_CARBON; From 6f5833f8b3c9324a64cb237135177c0581a0c2ee Mon Sep 17 00:00:00 2001 From: lachwright Date: Sat, 4 Jan 2020 14:49:44 +0800 Subject: [PATCH 05/83] Randomize skin during signpost roulette --- src/p_enemy.c | 34 +++++++++++++--------------------- 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index c8edf293a..74faa76f4 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -5189,33 +5189,25 @@ void A_SignPlayer(mobj_t *actor) else if (locvar1 != -3) // set to a defined skin { // I turned this function into a fucking mess. I'm so sorry. -Lach - if (locvar1 == -2) // next skin + if (locvar1 == -2) // random skin { +#define skincheck(num) (player ? !R_SkinUsable(player-players, num) : skins[num].availability > 0) player_t *player = actor->target ? actor->target->player : NULL; UINT8 skinnum; -#define skincheck(num) (player ? !R_SkinUsable(player-players, num) : skins[num].availability > 0) - if (ov->skin == NULL) // pick a random skin to start with! + UINT8 skincount = 0; + for (skincount = 0; skincount < numskins; skincount++) + if (!skincheck(skincount)) + skincount++; + skinnum = P_RandomKey(skincount); + for (skincount = 0; skincount < numskins; skincount++) { - UINT8 skincount = 0; - for (skincount = 0; skincount < numskins; skincount++) - if (!skincheck(skincount)) - skincount++; - skinnum = P_RandomKey(skincount); - for (skincount = 0; skincount < numskins; skincount++) - { - if (skincount > skinnum) - break; - if (skincheck(skincount)) - skinnum++; - } + if (skincount > skinnum) + break; + if (skincheck(skincount)) + skinnum++; } - else // otherwise, advance 1 skin - { - skinnum = (skin_t*)ov->skin-skins; - while ((skinnum = (skinnum + 1) % numskins) && skincheck(skinnum)); - } -#undef skincheck skin = &skins[skinnum]; +#undef skincheck } else // specific skin skin = &skins[locvar1]; From 9e703f935a605455920736141adc35f87b4f91e9 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 8 Jan 2020 01:03:44 -0800 Subject: [PATCH 06/83] Right word jump --- src/console.c | 60 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 43 insertions(+), 17 deletions(-) diff --git a/src/console.c b/src/console.c index 01d1ddaa2..a726d8628 100644 --- a/src/console.c +++ b/src/console.c @@ -41,6 +41,8 @@ #include "hardware/hw_main.h" #endif +#define PUNCTUATION "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~" + #define MAXHUDLINES 20 static boolean con_started = false; // console has been initialised @@ -815,6 +817,47 @@ boolean CON_Responder(event_t *ev) || key == KEY_LALT || key == KEY_RALT) return true; + if (key == KEY_LEFTARROW) + { + if (input_cur != 0) + --input_cur; + if (!shiftdown) + input_sel = input_cur; + return true; + } + else if (key == KEY_RIGHTARROW) + { + if (ctrldown) + { + char *line; + int c; + + line = &inputlines[inputline][input_cur]; + c = line[0]; + + if (isspace(c)) + input_cur += strspn(line, " "); + else if (ispunct(c)) + input_cur += strspn(line, PUNCTUATION); + else + { + if (isspace(line[1])) + input_cur += 1 + strspn(&line[1], " "); + else + input_cur += strcspn(line, " "PUNCTUATION); + } + } + else + { + if (input_cur < input_len) + ++input_cur; + } + + if (!shiftdown) + input_sel = input_cur; + return true; + } + // ctrl modifier -- changes behavior, adds shortcuts if (ctrldown) { @@ -967,23 +1010,6 @@ boolean CON_Responder(event_t *ev) con_scrollup--; return true; } - - if (key == KEY_LEFTARROW) - { - if (input_cur != 0) - --input_cur; - if (!shiftdown) - input_sel = input_cur; - return true; - } - else if (key == KEY_RIGHTARROW) - { - if (input_cur < input_len) - ++input_cur; - if (!shiftdown) - input_sel = input_cur; - return true; - } else if (key == KEY_HOME) { input_cur = 0; From 0d3c03ccd658ee1f0d321a38bddf967d70b071bf Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 8 Jan 2020 02:54:17 -0800 Subject: [PATCH 07/83] Left word jump (whoo that took long) --- src/console.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/console.c b/src/console.c index a726d8628..f77d9b085 100644 --- a/src/console.c +++ b/src/console.c @@ -820,7 +820,31 @@ boolean CON_Responder(event_t *ev) if (key == KEY_LEFTARROW) { if (input_cur != 0) - --input_cur; + { + if (ctrldown) + { + int (*is)(int); + char *line; + int c; + line = inputlines[inputline]; + c = line[--input_cur]; + if (isspace(c)) + is = isspace; + else if (ispunct(c)) + is = ispunct; + else + is = isalnum; + c = (*is)(line[input_cur]); + while (input_cur > 0 && + (*is)(line[input_cur - 1]) == c) + input_cur--; + } + else + { + --input_cur; + } + } + if (!shiftdown) input_sel = input_cur; return true; From 702b23ec3f7db75c94bcff065b45d0a367644b56 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 8 Jan 2020 12:58:19 -0800 Subject: [PATCH 08/83] Put the word jumping code in functions --- src/console.c | 49 +++++-------------------------------------------- src/doomdef.h | 2 ++ src/m_misc.c | 37 +++++++++++++++++++++++++++++++++++++ src/m_misc.h | 8 ++++++++ 4 files changed, 52 insertions(+), 44 deletions(-) diff --git a/src/console.c b/src/console.c index f77d9b085..786eb8c2b 100644 --- a/src/console.c +++ b/src/console.c @@ -32,6 +32,7 @@ #include "d_main.h" #include "m_menu.h" #include "filesrch.h" +#include "m_misc.h" #ifdef _WINDOWS #include "win32/win_main.h" @@ -41,8 +42,6 @@ #include "hardware/hw_main.h" #endif -#define PUNCTUATION "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~" - #define MAXHUDLINES 20 static boolean con_started = false; // console has been initialised @@ -822,61 +821,23 @@ boolean CON_Responder(event_t *ev) if (input_cur != 0) { if (ctrldown) - { - int (*is)(int); - char *line; - int c; - line = inputlines[inputline]; - c = line[--input_cur]; - if (isspace(c)) - is = isspace; - else if (ispunct(c)) - is = ispunct; - else - is = isalnum; - c = (*is)(line[input_cur]); - while (input_cur > 0 && - (*is)(line[input_cur - 1]) == c) - input_cur--; - } + input_cur = M_JumpWordReverse(inputlines[inputline], input_cur); else - { --input_cur; - } } - if (!shiftdown) input_sel = input_cur; return true; } else if (key == KEY_RIGHTARROW) { - if (ctrldown) + if (input_cur < input_len) { - char *line; - int c; - - line = &inputlines[inputline][input_cur]; - c = line[0]; - - if (isspace(c)) - input_cur += strspn(line, " "); - else if (ispunct(c)) - input_cur += strspn(line, PUNCTUATION); + if (ctrldown) + input_cur += M_JumpWord(&inputlines[inputline][input_cur]); else - { - if (isspace(line[1])) - input_cur += 1 + strspn(&line[1], " "); - else - input_cur += strcspn(line, " "PUNCTUATION); - } - } - else - { - if (input_cur < input_len) ++input_cur; } - if (!shiftdown) input_sel = input_cur; return true; diff --git a/src/doomdef.h b/src/doomdef.h index 55ad8abed..7b4f6343f 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -541,6 +541,8 @@ INT32 I_GetKey(void); #define PATHSEP "/" #endif +#define PUNCTUATION "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~" + // Compile date and time and revision. extern const char *compdate, *comptime, *comprevision, *compbranch; diff --git a/src/m_misc.c b/src/m_misc.c index 83c0c7bec..91447b415 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -2540,3 +2540,40 @@ void M_MkdirEach(const char *path, int start, int mode) { M_MkdirEachUntil(path, start, -1, mode); } + +int M_JumpWord(const char *line) +{ + int c; + + c = line[0]; + + if (isspace(c)) + return strspn(line, " "); + else if (ispunct(c)) + return strspn(line, PUNCTUATION); + else + { + if (isspace(line[1])) + return 1 + strspn(&line[1], " "); + else + return strcspn(line, " "PUNCTUATION); + } +} + +int M_JumpWordReverse(const char *line, int offset) +{ + int (*is)(int); + int c; + c = line[--offset]; + if (isspace(c)) + is = isspace; + else if (ispunct(c)) + is = ispunct; + else + is = isalnum; + c = (*is)(line[offset]); + while (offset > 0 && + (*is)(line[offset - 1]) == c) + offset--; + return offset; +} diff --git a/src/m_misc.h b/src/m_misc.h index e0a73e0b7..3fb9f031a 100644 --- a/src/m_misc.h +++ b/src/m_misc.h @@ -101,6 +101,14 @@ boolean M_IsPathAbsolute (const char *path); void M_MkdirEach (const char *path, int start, int mode); void M_MkdirEachUntil (const char *path, int start, int end, int mode); +/* Return offset to the first word in a string. */ +/* E.g. cursor += M_JumpWord(line + cursor); */ +int M_JumpWord (const char *s); + +/* Return index of the last word behind offset bytes in a string. */ +/* E.g. cursor = M_JumpWordReverse(line, cursor); */ +int M_JumpWordReverse (const char *line, int offset); + // counting bits, for weapon ammo code, usually FUNCMATH UINT8 M_CountBits(UINT32 num, UINT8 size); From 8bc7b4c72d3a0dd94e29d0cab806037836958a28 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 8 Jan 2020 12:58:34 -0800 Subject: [PATCH 09/83] Give chat word jumping --- src/hu_stuff.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 772d1cd58..d75b478ab 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -17,6 +17,7 @@ #include "m_menu.h" // gametype_cons_t #include "m_cond.h" // emblems +#include "m_misc.h" // word jumping #include "d_clisrv.h" @@ -1349,9 +1350,19 @@ boolean HU_Responder(event_t *ev) chat_scrolltime = 4; } else if (c == KEY_LEFTARROW && c_input != 0 && !OLDCHAT) // i said go back - c_input--; + { + if (ctrldown) + c_input = M_JumpWordReverse(w_chat, c_input); + else + 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++; + { + if (ctrldown) + c_input += M_JumpWord(&w_chat[c_input]); + else + c_input++; + } return true; } #endif From 74364b84f9d0563eae4fba2cd111ca52bed9e6b5 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 8 Jan 2020 14:26:47 -0800 Subject: [PATCH 10/83] Revert "Oh right, the keywords..." This reverts commit a00dfcf4205f88cd6149daf73fec4831a7d7c2e5. --- src/dehacked.c | 5 +++++ src/doomstat.h | 1 + src/g_game.c | 3 +++ src/lua_maplib.c | 2 ++ src/p_setup.c | 1 + 5 files changed, 12 insertions(+) diff --git a/src/dehacked.c b/src/dehacked.c index 8220f5aa3..8b4b92494 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1629,6 +1629,11 @@ static void readlevelheader(MYFILE *f, INT32 num) mapheaderinfo[num-1]->typeoflevel = tol; } } + else if (fastcmp(word, "KEYWORD")) + { + deh_strlcpy(mapheaderinfo[num-1]->keyword, word2, + sizeof(mapheaderinfo[num-1]->keyword), va("Level header %d: keyword", num)); + } else if (fastcmp(word, "MUSIC")) { if (fastcmp(word2, "NONE")) diff --git a/src/doomstat.h b/src/doomstat.h index 7e961677f..0fad811d9 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -289,6 +289,7 @@ typedef struct UINT8 actnum; ///< Act number or 0 for none. UINT32 typeoflevel; ///< Combination of typeoflevel flags. INT16 nextlevel; ///< Map number of next level, or 1100-1102 to end. + char keyword[33]; ///< Keywords separated by space to search for. 32 characters. char musname[7]; ///< Music track to play. "" for no music. UINT16 mustrack; ///< Subsong to play. Only really relevant for music modules and specific formats supported by GME. 0 to ignore. UINT32 muspos; ///< Music position to jump to. diff --git a/src/g_game.c b/src/g_game.c index f7778df8f..45730adac 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -4761,6 +4761,9 @@ INT32 G_FindMap(const char *mapname, char **foundmapnamep, measurekeywords(&freq[freqc], &freq[freqc].matchd, &freq[freqc].matchc, realmapname, mapname, wanttable); + measurekeywords(&freq[freqc], + &freq[freqc].keywhd, &freq[freqc].keywhc, + mapheaderinfo[i]->keyword, mapname, wanttable); if (freq[freqc].total) freqc++; } diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 309ba86a1..64e60c99a 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -2014,6 +2014,8 @@ static int mapheaderinfo_get(lua_State *L) lua_pushinteger(L, header->typeoflevel); else if (fastcmp(field,"nextlevel")) lua_pushinteger(L, header->nextlevel); + else if (fastcmp(field,"keyword")) + lua_pushstring(L, header->keyword); else if (fastcmp(field,"musname")) lua_pushstring(L, header->musname); else if (fastcmp(field,"mustrack")) diff --git a/src/p_setup.c b/src/p_setup.c index 104b4e5a0..a9585d0c2 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -222,6 +222,7 @@ static void P_ClearSingleMapHeaderInfo(INT16 i) mapheaderinfo[num]->typeoflevel = 0; mapheaderinfo[num]->nextlevel = (INT16)(i + 1); mapheaderinfo[num]->startrings = 0; + mapheaderinfo[num]->keyword[0] = '\0'; snprintf(mapheaderinfo[num]->musname, 7, "%sM", G_BuildMapName(i)); mapheaderinfo[num]->musname[6] = 0; mapheaderinfo[num]->mustrack = 0; From 735289502c0fb9e91615f06dec94bf7b799fd560 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 8 Jan 2020 14:41:38 -0800 Subject: [PATCH 11/83] Call it KEYWORDS --- src/dehacked.c | 6 +++--- src/doomstat.h | 2 +- src/g_game.c | 2 +- src/lua_maplib.c | 4 ++-- src/p_setup.c | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 8b4b92494..91d67c63f 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1629,10 +1629,10 @@ static void readlevelheader(MYFILE *f, INT32 num) mapheaderinfo[num-1]->typeoflevel = tol; } } - else if (fastcmp(word, "KEYWORD")) + else if (fastcmp(word, "KEYWORDS")) { - deh_strlcpy(mapheaderinfo[num-1]->keyword, word2, - sizeof(mapheaderinfo[num-1]->keyword), va("Level header %d: keyword", num)); + deh_strlcpy(mapheaderinfo[num-1]->keywords, word2, + sizeof(mapheaderinfo[num-1]->keywords), va("Level header %d: keywords", num)); } else if (fastcmp(word, "MUSIC")) { diff --git a/src/doomstat.h b/src/doomstat.h index 0fad811d9..c7c12632a 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -289,7 +289,7 @@ typedef struct UINT8 actnum; ///< Act number or 0 for none. UINT32 typeoflevel; ///< Combination of typeoflevel flags. INT16 nextlevel; ///< Map number of next level, or 1100-1102 to end. - char keyword[33]; ///< Keywords separated by space to search for. 32 characters. + char keywords[33]; ///< Keywords separated by space to search for. 32 characters. char musname[7]; ///< Music track to play. "" for no music. UINT16 mustrack; ///< Subsong to play. Only really relevant for music modules and specific formats supported by GME. 0 to ignore. UINT32 muspos; ///< Music position to jump to. diff --git a/src/g_game.c b/src/g_game.c index 45730adac..dd7540ae8 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -4763,7 +4763,7 @@ INT32 G_FindMap(const char *mapname, char **foundmapnamep, realmapname, mapname, wanttable); measurekeywords(&freq[freqc], &freq[freqc].keywhd, &freq[freqc].keywhc, - mapheaderinfo[i]->keyword, mapname, wanttable); + mapheaderinfo[i]->keywords, mapname, wanttable); if (freq[freqc].total) freqc++; } diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 64e60c99a..3d98bee33 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -2014,8 +2014,8 @@ static int mapheaderinfo_get(lua_State *L) lua_pushinteger(L, header->typeoflevel); else if (fastcmp(field,"nextlevel")) lua_pushinteger(L, header->nextlevel); - else if (fastcmp(field,"keyword")) - lua_pushstring(L, header->keyword); + else if (fastcmp(field,"keywords")) + lua_pushstring(L, header->keywords); else if (fastcmp(field,"musname")) lua_pushstring(L, header->musname); else if (fastcmp(field,"mustrack")) diff --git a/src/p_setup.c b/src/p_setup.c index a9585d0c2..14bdca2e3 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -222,7 +222,7 @@ static void P_ClearSingleMapHeaderInfo(INT16 i) mapheaderinfo[num]->typeoflevel = 0; mapheaderinfo[num]->nextlevel = (INT16)(i + 1); mapheaderinfo[num]->startrings = 0; - mapheaderinfo[num]->keyword[0] = '\0'; + mapheaderinfo[num]->keywords[0] = '\0'; snprintf(mapheaderinfo[num]->musname, 7, "%sM", G_BuildMapName(i)); mapheaderinfo[num]->musname[6] = 0; mapheaderinfo[num]->mustrack = 0; From 48c1ce3ac3c0869a9272d3685da9ddaa3c1b014b Mon Sep 17 00:00:00 2001 From: fickleheart Date: Fri, 27 Dec 2019 15:31:20 -0600 Subject: [PATCH 12/83] Add render-based drop shadows to some objects Uses a hardcoded list for now. I was experiencing some crashes with this, but the shadowyscale check seems to have suppressed them. --- src/r_things.c | 133 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 132 insertions(+), 1 deletion(-) diff --git a/src/r_things.c b/src/r_things.c index c9fe795fb..558ea280e 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1094,6 +1094,124 @@ static void R_SplitSprite(vissprite_t *sprite) } } +static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t tx, fixed_t tz) +{ + vissprite_t *shadow; + patch_t *patch; + fixed_t xscale, yscale, shadowxscale, shadowyscale, x1, x2; + INT32 light = 0; + fixed_t scalemul; UINT8 trans; + fixed_t floordiff; + fixed_t floorz; + + // Get floorz as the first floor below the object that's visible + floorz = (vis->heightsec != -1) ? sectors[vis->heightsec].floorheight : thing->floorz; + if (vis->sector->ffloors) + { + ffloor_t *rover = vis->sector->ffloors; + fixed_t z; + + for (; rover; rover = rover->next) + { + if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERPLANES) || (rover->alpha < 90 && !(rover->flags & FF_SWIMMABLE))) + continue; + + z = *rover->t_slope ? P_GetZAt(*rover->t_slope, thing->x, thing->y) : *rover->topheight; + if (z < thing->z+thing->height/3 && z > floorz) + floorz = z; + } + } + + floordiff = abs(thing->z - floorz); + + trans = floordiff / (100*FRACUNIT) + 3; + if (trans >= 9) return; + + scalemul = FRACUNIT - floordiff/640; + + patch = W_CachePatchNum(sprites[SPR_THOK].spriteframes[0].lumppat[0], PU_CACHE); + xscale = FixedDiv(projection, tz); + yscale = FixedDiv(projectiony, tz); + shadowxscale = FixedMul(thing->radius*2, scalemul) / patch->width; + shadowyscale = FixedMul(FixedMul(thing->radius*2 / patch->height, scalemul), FixedDiv(abs(floorz - viewz), tz)); + + tx -= patch->width * shadowxscale/2; + x1 = (centerxfrac + FixedMul(tx,xscale))>>FRACBITS; + if (x1 >= viewwidth) return; + + tx += patch->width * shadowxscale; + x2 = ((centerxfrac + FixedMul(tx,xscale))>>FRACBITS); x2--; + if (x2 < 0 || x2 <= x1) return; + + if (shadowyscale < FRACUNIT/patch->height) return; // fix some crashes? + + shadow = R_NewVisSprite(); + shadow->patch = patch; + shadow->heightsec = vis->heightsec; + + shadow->thingheight = FRACUNIT; + shadow->pz = floorz; + shadow->pzt = shadow->pz + shadow->thingheight; + + shadow->mobjflags = 0; + shadow->sortscale = vis->sortscale; + shadow->dispoffset = vis->dispoffset - 5; + shadow->gx = thing->x; + shadow->gy = thing->y; + shadow->gzt = shadow->pz + shadow->patch->height * shadowyscale / 2; + shadow->gz = shadow->gzt - shadow->patch->height * shadowyscale; + shadow->texturemid = FixedDiv(shadow->gzt - viewz, shadowyscale); + shadow->scalestep = 0; + + shadow->mobj = thing; // Easy access! Tails 06-07-2002 + + shadow->x1 = x1 < 0 ? 0 : x1; + shadow->x2 = x2 >= viewwidth ? viewwidth-1 : x2; + + shadow->xscale = FixedMul(xscale, shadowxscale); //SoM: 4/17/2000 + shadow->scale = FixedMul(yscale, shadowyscale); + shadow->sector = vis->sector; + shadow->szt = (INT16)((centeryfrac - FixedMul(shadow->gzt - viewz, yscale))>>FRACBITS); + shadow->sz = (INT16)((centeryfrac - FixedMul(shadow->gz - viewz, yscale))>>FRACBITS); + shadow->cut = SC_ISSCALED; //check this + + + shadow->startfrac = 0; + shadow->xiscale = 0x7fffff00 / (shadow->xscale/2); + + if (shadow->x1 > x1) + shadow->startfrac += shadow->xiscale*(vis->x1-x1); + + if (thing->subsector->sector->numlights) + { + INT32 lightnum; +#ifdef ESLOPE // R_GetPlaneLight won't work on sloped lights! + light = thing->subsector->sector->numlights - 1; + + for (lightnum = 1; lightnum < thing->subsector->sector->numlights; lightnum++) { + fixed_t h = thing->subsector->sector->lightlist[lightnum].slope ? P_GetZAt(thing->subsector->sector->lightlist[lightnum].slope, thing->x, thing->y) + : thing->subsector->sector->lightlist[lightnum].height; + if (h <= shadow->gzt) { + light = lightnum - 1; + break; + } + } +#else + light = R_GetPlaneLight(thing->subsector->sector, shadow->gzt, false); +#endif + } + + if (thing->subsector->sector->numlights) + shadow->extra_colormap = *thing->subsector->sector->lightlist[light].extra_colormap; + else + shadow->extra_colormap = thing->subsector->sector->extra_colormap; + + shadow->transmap = transtables + (trans<colormap = scalelight[0][0]; // full dark! + + objectsdrawn++; +} + // // R_ProjectSprite // Generates a vissprite for a thing @@ -1131,6 +1249,8 @@ static void R_ProjectSprite(mobj_t *thing) fixed_t scalestep; fixed_t offset, offset2; + fixed_t basetx; // drop shadows + boolean papersprite = !!(thing->frame & FF_PAPERSPRITE); fixed_t paperoffset = 0, paperdistance = 0; angle_t centerangle = 0; @@ -1166,7 +1286,7 @@ static void R_ProjectSprite(mobj_t *thing) gxt = -FixedMul(tr_x, viewsin); gyt = FixedMul(tr_y, viewcos); - tx = -(gyt + gxt); + basetx = tx = -(gyt + gxt); // too far off the side? if (!papersprite && abs(tx) > tz<<2) // papersprite clipping is handled later @@ -1623,6 +1743,17 @@ static void R_ProjectSprite(mobj_t *thing) if (thing->subsector->sector->numlights) R_SplitSprite(vis); + // temporary: whitelist. eventually: MF/2/E flag? + if (( + oldthing->type == MT_PLAYER || + (oldthing->state - states) == S_RING || + oldthing->type == MT_ROLLOUTROCK || + oldthing->flags & MF_ENEMY || + oldthing->type == MT_EGGMOBILE4_MACE || + (oldthing->type >= MT_SMALLMACE && oldthing->type <= MT_REDSPRINGBALL) // .W. + ) && !papersprite) + R_ProjectDropShadow(oldthing, vis, basetx, tz); + // Debug ++objectsdrawn; } From c46c92d605efa401fbb24193eef170b64ecb99ca Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 29 Dec 2019 18:30:29 -0600 Subject: [PATCH 13/83] Prevent linkdraw sprites from connecting to shadows --- src/r_things.c | 11 ++++++++++- src/r_things.h | 3 ++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index 558ea280e..953952c56 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1122,6 +1122,8 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t tx, fix } } + if (abs(floorz-viewz)/tz > 4) return; // Prevent stretchy shadows and possible crashes + floordiff = abs(thing->z - floorz); trans = floordiff / (100*FRACUNIT) + 3; @@ -1173,7 +1175,7 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t tx, fix shadow->sector = vis->sector; shadow->szt = (INT16)((centeryfrac - FixedMul(shadow->gzt - viewz, yscale))>>FRACBITS); shadow->sz = (INT16)((centeryfrac - FixedMul(shadow->gz - viewz, yscale))>>FRACBITS); - shadow->cut = SC_ISSCALED; //check this + shadow->cut = SC_ISSCALED|SC_SHADOW; //check this shadow->startfrac = 0; @@ -2069,6 +2071,9 @@ static void R_SortVisSprites(vissprite_t* vsprsortedhead, UINT32 start, UINT32 e if (!(ds->cut & SC_LINKDRAW)) continue; + if (ds->cut & SC_SHADOW) + continue; + // reuse dsfirst... for (dsfirst = unsorted.prev; dsfirst != &unsorted; dsfirst = dsfirst->prev) { @@ -2076,6 +2081,10 @@ static void R_SortVisSprites(vissprite_t* vsprsortedhead, UINT32 start, UINT32 e if (dsfirst->cut & SC_LINKDRAW) continue; + // don't connect to your shadow! + if (dsfirst->cut & SC_SHADOW) + continue; + // don't connect if it's not the tracer if (dsfirst->mobj != ds->mobj) continue; diff --git a/src/r_things.h b/src/r_things.h index 1b74dd74e..a6ef92802 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -153,7 +153,8 @@ typedef enum SC_LINKDRAW = 1<<3, SC_FULLBRIGHT = 1<<4, SC_VFLIP = 1<<5, - SC_ISSCALED = 1>>6, + SC_ISSCALED = 1<<6, + SC_SHADOW = 1<<7, // masks SC_CUTMASK = SC_TOP|SC_BOTTOM, SC_FLAGMASK = ~SC_CUTMASK From 5929b4797e33f3869131be37b2ff52daf30d469e Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 29 Dec 2019 19:19:26 -0600 Subject: [PATCH 14/83] This acursed crash-inducing typo spat in my face and called me a bitch --- src/r_things.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index 953952c56..174ada10a 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1177,12 +1177,11 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t tx, fix shadow->sz = (INT16)((centeryfrac - FixedMul(shadow->gz - viewz, yscale))>>FRACBITS); shadow->cut = SC_ISSCALED|SC_SHADOW; //check this - shadow->startfrac = 0; - shadow->xiscale = 0x7fffff00 / (shadow->xscale/2); + shadow->xiscale = 0x7ffffff0 / (shadow->xscale/2); if (shadow->x1 > x1) - shadow->startfrac += shadow->xiscale*(vis->x1-x1); + shadow->startfrac += shadow->xiscale*(shadow->x1-x1); if (thing->subsector->sector->numlights) { From 9c49e020c3abd7d748ea93e37c1b2eb67a4f90ea Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 29 Dec 2019 20:19:27 -0600 Subject: [PATCH 15/83] FUCK IT, SLOPED SHADOWS NOW --- src/r_things.c | 76 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 67 insertions(+), 9 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index 174ada10a..628239957 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -876,6 +876,7 @@ static void R_DrawVisSprite(vissprite_t *vis) if (!(vis->scalestep)) { sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale); + sprtopscreen += vis->paperdistance * vis->paperoffset; dc_iscale = FixedDiv(FRACUNIT, vis->scale); } @@ -921,7 +922,7 @@ static void R_DrawVisSprite(vissprite_t *vis) else { // Non-paper drawing loop - for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale) + for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale, sprtopscreen += vis->paperdistance) { #ifdef RANGECHECK texturecolumn = frac>>FRACBITS; @@ -1098,30 +1099,59 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t tx, fix { vissprite_t *shadow; patch_t *patch; - fixed_t xscale, yscale, shadowxscale, shadowyscale, x1, x2; + fixed_t xscale, yscale, shadowxscale, shadowyscale, shadowskew, x1, x2; INT32 light = 0; fixed_t scalemul; UINT8 trans; fixed_t floordiff; fixed_t floorz; + pslope_t *floorslope; // Get floorz as the first floor below the object that's visible floorz = (vis->heightsec != -1) ? sectors[vis->heightsec].floorheight : thing->floorz; - if (vis->sector->ffloors) + floorslope = (vis->heightsec != -1) ? NULL : thing->standingslope; + { - ffloor_t *rover = vis->sector->ffloors; + boolean original = true; fixed_t z; - for (; rover; rover = rover->next) + if (vis->sector->ffloors) { - if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERPLANES) || (rover->alpha < 90 && !(rover->flags & FF_SWIMMABLE))) - continue; + ffloor_t *rover = vis->sector->ffloors; - z = *rover->t_slope ? P_GetZAt(*rover->t_slope, thing->x, thing->y) : *rover->topheight; - if (z < thing->z+thing->height/3 && z > floorz) + for (; rover; rover = rover->next) + { + if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERPLANES) || (rover->alpha < 90 && !(rover->flags & FF_SWIMMABLE))) + continue; + + z = *rover->t_slope ? P_GetZAt(*rover->t_slope, thing->x, thing->y) : *rover->topheight; + if (z < thing->z+thing->height/3 && z > floorz) + { + floorz = z; + floorslope = *rover->t_slope; + original = false; + } + else if (original && (*rover->t_slope) && z < thing->z+thing->height/3 && z > floorz - FixedMul(abs((*rover->t_slope)->zdelta), thing->radius*2)) + { + // Guesstimated to be a usable floor. This is here to handle floorslope of non-grounded things, I guess. + floorz = z; + floorslope = *rover->t_slope; + original = false; + } + } + } + + if (original && vis->sector->f_slope) + { + z = P_GetZAt(vis->sector->f_slope, thing->x, thing->y); + if (z < thing->z+thing->height/3 && z > floorz - FixedMul(abs(vis->sector->f_slope->zdelta), thing->radius*2)) + { floorz = z; + floorslope = vis->sector->f_slope; + } } } + if (abs(floorz-viewz)/tz > 4) return; // Prevent stretchy shadows and possible crashes floordiff = abs(thing->z - floorz); @@ -1136,6 +1166,28 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t tx, fix yscale = FixedDiv(projectiony, tz); shadowxscale = FixedMul(thing->radius*2, scalemul) / patch->width; shadowyscale = FixedMul(FixedMul(thing->radius*2 / patch->height, scalemul), FixedDiv(abs(floorz - viewz), tz)); + shadowskew = 0; + + if (floorslope) + { + // haha let's try some dumb stuff + fixed_t xslope, zslope; + angle_t sloperelang = (R_PointToAngle(thing->x, thing->y) - floorslope->xydirection) >> ANGLETOFINESHIFT; + + xslope = FixedMul(FINESINE(sloperelang), floorslope->zdelta); + zslope = FixedMul(FINECOSINE(sloperelang), floorslope->zdelta); + + //CONS_Printf("Shadow is sloped by %d %d\n", xslope, zslope); + + if (viewz < floorz) + shadowyscale += FixedMul(FixedMul(thing->radius*2 / patch->height, scalemul), zslope); + else + shadowyscale -= FixedMul(FixedMul(thing->radius*2 / patch->height, scalemul), zslope); + + shadowyscale = abs(shadowyscale); + + shadowskew = xslope; + } tx -= patch->width * shadowxscale/2; x1 = (centerxfrac + FixedMul(tx,xscale))>>FRACBITS; @@ -1164,6 +1216,7 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t tx, fix shadow->gz = shadow->gzt - shadow->patch->height * shadowyscale; shadow->texturemid = FixedDiv(shadow->gzt - viewz, shadowyscale); shadow->scalestep = 0; + shadow->paperdistance = shadowskew; // repurposed variable shadow->mobj = thing; // Easy access! Tails 06-07-2002 @@ -1183,6 +1236,10 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t tx, fix if (shadow->x1 > x1) shadow->startfrac += shadow->xiscale*(shadow->x1-x1); + // reusing x1 variable + x1 += (x2-x1)/2; + shadow->paperoffset = (vis->x1-x1)/2; + if (thing->subsector->sector->numlights) { INT32 lightnum; @@ -1878,6 +1935,7 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing) vis->pzt = vis->pz + vis->thingheight; vis->texturemid = vis->gzt - viewz; vis->scalestep = 0; + vis->paperdistance = 0; vis->x1 = x1 < 0 ? 0 : x1; vis->x2 = x2 >= viewwidth ? viewwidth-1 : x2; From c078ab630d83b5bc18d4e0ba4c5db3571be8706a Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 29 Dec 2019 20:45:07 -0600 Subject: [PATCH 16/83] Fix more shadow crashes and save my sanity --- src/r_things.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/r_things.c b/src/r_things.c index 628239957..4db6cae58 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1231,7 +1231,8 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t tx, fix shadow->cut = SC_ISSCALED|SC_SHADOW; //check this shadow->startfrac = 0; - shadow->xiscale = 0x7ffffff0 / (shadow->xscale/2); + //shadow->xiscale = 0x7ffffff0 / (shadow->xscale/2); + shadow->xiscale = (patch->width<x1 > x1) shadow->startfrac += shadow->xiscale*(shadow->x1-x1); From 8757194d7347ba15fa7b25a7c66a509e123e19d0 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 29 Dec 2019 20:53:28 -0600 Subject: [PATCH 17/83] Make ring shadows smaller and fix scale bug --- src/r_things.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/r_things.c b/src/r_things.c index 4db6cae58..e6d0d53e6 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1161,6 +1161,10 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t tx, fix scalemul = FRACUNIT - floordiff/640; + //@TODO make this configurable instead of hardcoding to the ring + if (thing->type == MT_RING) + scalemul = scalemul*2/3; + patch = W_CachePatchNum(sprites[SPR_THOK].spriteframes[0].lumppat[0], PU_CACHE); xscale = FixedDiv(projection, tz); yscale = FixedDiv(projectiony, tz); @@ -1214,7 +1218,7 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t tx, fix shadow->gy = thing->y; shadow->gzt = shadow->pz + shadow->patch->height * shadowyscale / 2; shadow->gz = shadow->gzt - shadow->patch->height * shadowyscale; - shadow->texturemid = FixedDiv(shadow->gzt - viewz, shadowyscale); + shadow->texturemid = FixedMul(thing->scale, FixedDiv(shadow->gzt - viewz, shadowyscale)); shadow->scalestep = 0; shadow->paperdistance = shadowskew; // repurposed variable From ef4974ab4dfd1d6551079cb6d157cbe4fdfd301f Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 29 Dec 2019 22:15:01 -0600 Subject: [PATCH 18/83] Apply portal clipping to drop shadows too --- src/r_things.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/r_things.c b/src/r_things.c index e6d0d53e6..1f48bcb52 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1227,6 +1227,15 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t tx, fix shadow->x1 = x1 < 0 ? 0 : x1; shadow->x2 = x2 >= viewwidth ? viewwidth-1 : x2; + // PORTAL SEMI-CLIPPING + if (portalrender) + { + if (shadow->x1 < portalclipstart) + shadow->x1 = portalclipstart; + if (shadow->x2 >= portalclipend) + shadow->x2 = portalclipend-1; + } + shadow->xscale = FixedMul(xscale, shadowxscale); //SoM: 4/17/2000 shadow->scale = FixedMul(yscale, shadowyscale); shadow->sector = vis->sector; From a7edf51cb9fbfaa36bd6208dfbc2b5783a5c120b Mon Sep 17 00:00:00 2001 From: fickleheart Date: Wed, 8 Jan 2020 21:52:10 -0600 Subject: [PATCH 19/83] Stop misusing papersprite vars for sprite skew --- src/r_things.c | 12 ++++++++---- src/r_things.h | 5 +++++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index 1f48bcb52..ca3993322 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -876,7 +876,7 @@ static void R_DrawVisSprite(vissprite_t *vis) if (!(vis->scalestep)) { sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale); - sprtopscreen += vis->paperdistance * vis->paperoffset; + sprtopscreen += vis->shear.tan * vis->shear.offset; dc_iscale = FixedDiv(FRACUNIT, vis->scale); } @@ -922,7 +922,7 @@ static void R_DrawVisSprite(vissprite_t *vis) else { // Non-paper drawing loop - for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale, sprtopscreen += vis->paperdistance) + for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale, sprtopscreen += vis->shear.tan) { #ifdef RANGECHECK texturecolumn = frac>>FRACBITS; @@ -1220,7 +1220,7 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t tx, fix shadow->gz = shadow->gzt - shadow->patch->height * shadowyscale; shadow->texturemid = FixedMul(thing->scale, FixedDiv(shadow->gzt - viewz, shadowyscale)); shadow->scalestep = 0; - shadow->paperdistance = shadowskew; // repurposed variable + shadow->shear.tan = shadowskew; // repurposed variable shadow->mobj = thing; // Easy access! Tails 06-07-2002 @@ -1252,7 +1252,7 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t tx, fix // reusing x1 variable x1 += (x2-x1)/2; - shadow->paperoffset = (vis->x1-x1)/2; + shadow->shear.offset = (vis->x1-x1)/2; if (thing->subsector->sector->numlights) { @@ -1723,6 +1723,8 @@ static void R_ProjectSprite(mobj_t *thing) vis->paperoffset = paperoffset; vis->paperdistance = paperdistance; vis->centerangle = centerangle; + vis->shear.tan = 0; + vis->shear.offset = 0; vis->mobj = thing; // Easy access! Tails 06-07-2002 @@ -1950,6 +1952,8 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing) vis->texturemid = vis->gzt - viewz; vis->scalestep = 0; vis->paperdistance = 0; + vis->shear.tan = 0; + vis->shear.offset = 0; vis->x1 = x1 < 0 ? 0 : x1; vis->x2 = x2 >= viewwidth ? viewwidth-1 : x2; diff --git a/src/r_things.h b/src/r_things.h index a6ef92802..12f0008eb 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -187,6 +187,11 @@ typedef struct vissprite_s angle_t centerangle; // for paper sprites + struct { + fixed_t tan; // The amount to shear the sprite vertically per row + INT32 offset; // The center of the shearing location offset from x1 + } shear; + fixed_t texturemid; patch_t *patch; From fa4b49d52cb75abd06cee204a1ac0678c919afc8 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Wed, 8 Jan 2020 23:19:52 -0600 Subject: [PATCH 20/83] Refactor shadow floor finding code a bit I tried to fix ring shadows on polyobjects and got this in return: https://media.discordapp.net/attachments/629477786943356938/664695818913185822/srb20156.png --- src/r_things.c | 160 +++++++++++++++++++++++++++++++++++-------------- src/r_things.h | 2 + 2 files changed, 117 insertions(+), 45 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index ca3993322..018f5d37f 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1095,6 +1095,120 @@ static void R_SplitSprite(vissprite_t *sprite) } } +// +// R_GetShadowZ(thing, shadowslope) +// Get the first visible floor below the object for shadows +// shadowslope is filled with the floor's slope, if provided +// +fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope) +{ + fixed_t z, floorz = INT32_MIN; + pslope_t *slope, *floorslope = NULL; + msecnode_t *node; + sector_t *sector; + ffloor_t *rover; + + for (node = thing->touching_sectorlist; node; node = node->m_sectorlist_next) + { + sector = node->m_sector; + + slope = (sector->heightsec != -1) ? NULL : sector->f_slope; + z = slope ? P_GetZAt(slope, thing->x, thing->y) : ( + (sector->heightsec != -1) ? sectors[sector->heightsec].floorheight : sector->floorheight + ); + + if (z < thing->z+thing->height/2 && z > floorz) + { + floorz = z; + floorslope = slope; + } + + if (sector->ffloors) + for (rover = sector->ffloors; rover; rover = rover->next) + { + if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERPLANES) || (rover->alpha < 90 && !(rover->flags & FF_SWIMMABLE))) + continue; + + z = *rover->t_slope ? P_GetZAt(*rover->t_slope, thing->x, thing->y) : *rover->topheight; + if (z < thing->z+thing->height/2 && z > floorz) + { + floorz = z; + floorslope = *rover->t_slope; + } + } + } + + if (thing->floorz > floorz + (!floorslope ? 0 : FixedMul(abs(floorslope->zdelta), thing->radius*3/2))) + { + floorz = thing->floorz; + floorslope = NULL; + } + +#if 0 // Unfortunately, this drops CEZ2 down to sub-17 FPS on my i7. +//#ifdef POLYOBJECTS + // Check polyobjects and see if floorz needs to be altered, for rings only because they don't update floorz + if (thing->type == MT_RING) + { + INT32 xl, xh, yl, yh, bx, by; + + xl = (unsigned)(thing->x - thing->radius - bmaporgx)>>MAPBLOCKSHIFT; + xh = (unsigned)(thing->x + thing->radius - bmaporgx)>>MAPBLOCKSHIFT; + yl = (unsigned)(thing->y - thing->radius - bmaporgy)>>MAPBLOCKSHIFT; + yh = (unsigned)(thing->y + thing->radius - bmaporgy)>>MAPBLOCKSHIFT; + + BMBOUNDFIX(xl, xh, yl, yh); + + validcount++; + + for (by = yl; by <= yh; by++) + for (bx = xl; bx <= xh; bx++) + { + INT32 offset; + polymaplink_t *plink; // haleyjd 02/22/06 + + if (bx < 0 || by < 0 || bx >= bmapwidth || by >= bmapheight) + continue; + + offset = by*bmapwidth + bx; + + // haleyjd 02/22/06: consider polyobject lines + plink = polyblocklinks[offset]; + + while (plink) + { + polyobj_t *po = plink->po; + + if (po->validcount != validcount) // if polyobj hasn't been checked + { + po->validcount = validcount; + + if (!P_MobjInsidePolyobj(po, thing) || !(po->flags & POF_RENDERPLANES)) + { + plink = (polymaplink_t *)(plink->link.next); + continue; + } + + // We're inside it! Yess... + z = po->lines[0]->backsector->ceilingheight; + + if (z < thing->z+thing->height/2 && z > floorz) + { + floorz = z; + floorslope = NULL; + } + } + plink = (polymaplink_t *)(plink->link.next); + } + } + } +#endif + + if (shadowslope != NULL) + *shadowslope = floorslope; + + return floorz; +} + static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t tx, fixed_t tz) { vissprite_t *shadow; @@ -1106,51 +1220,7 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t tx, fix fixed_t floorz; pslope_t *floorslope; - // Get floorz as the first floor below the object that's visible - floorz = (vis->heightsec != -1) ? sectors[vis->heightsec].floorheight : thing->floorz; - floorslope = (vis->heightsec != -1) ? NULL : thing->standingslope; - - { - boolean original = true; - fixed_t z; - - if (vis->sector->ffloors) - { - ffloor_t *rover = vis->sector->ffloors; - - for (; rover; rover = rover->next) - { - if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERPLANES) || (rover->alpha < 90 && !(rover->flags & FF_SWIMMABLE))) - continue; - - z = *rover->t_slope ? P_GetZAt(*rover->t_slope, thing->x, thing->y) : *rover->topheight; - if (z < thing->z+thing->height/3 && z > floorz) - { - floorz = z; - floorslope = *rover->t_slope; - original = false; - } - else if (original && (*rover->t_slope) && z < thing->z+thing->height/3 && z > floorz - FixedMul(abs((*rover->t_slope)->zdelta), thing->radius*2)) - { - // Guesstimated to be a usable floor. This is here to handle floorslope of non-grounded things, I guess. - floorz = z; - floorslope = *rover->t_slope; - original = false; - } - } - } - - if (original && vis->sector->f_slope) - { - z = P_GetZAt(vis->sector->f_slope, thing->x, thing->y); - if (z < thing->z+thing->height/3 && z > floorz - FixedMul(abs(vis->sector->f_slope->zdelta), thing->radius*2)) - { - floorz = z; - floorslope = vis->sector->f_slope; - } - } - } - + floorz = R_GetShadowZ(thing, &floorslope); if (abs(floorz-viewz)/tz > 4) return; // Prevent stretchy shadows and possible crashes diff --git a/src/r_things.h b/src/r_things.h index 12f0008eb..5649b226b 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -55,6 +55,8 @@ void R_DrawFlippedMaskedColumn(column_t *column, INT32 texheight); // (only sprites from namelist are added or replaced) void R_AddSpriteDefs(UINT16 wadnum); +fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope); + //SoM: 6/5/2000: Light sprites correctly! void R_AddSprites(sector_t *sec, INT32 lightlevel); void R_InitSprites(void); From 9e8d20504e6f25b5d10b1c44731a2ef696dc4554 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Wed, 8 Jan 2020 23:24:31 -0600 Subject: [PATCH 21/83] Refactor shadow scale into an argument --- src/r_things.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index 018f5d37f..f2b205429 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1209,7 +1209,7 @@ fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope) return floorz; } -static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t tx, fixed_t tz) +static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, fixed_t tx, fixed_t tz) { vissprite_t *shadow; patch_t *patch; @@ -1229,11 +1229,7 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t tx, fix trans = floordiff / (100*FRACUNIT) + 3; if (trans >= 9) return; - scalemul = FRACUNIT - floordiff/640; - - //@TODO make this configurable instead of hardcoding to the ring - if (thing->type == MT_RING) - scalemul = scalemul*2/3; + scalemul = FixedMul(FRACUNIT - floordiff/640, scale); patch = W_CachePatchNum(sprites[SPR_THOK].spriteframes[0].lumppat[0], PU_CACHE); xscale = FixedDiv(projection, tz); @@ -1887,7 +1883,7 @@ static void R_ProjectSprite(mobj_t *thing) if (thing->subsector->sector->numlights) R_SplitSprite(vis); - // temporary: whitelist. eventually: MF/2/E flag? + ///@TODO temporary: whitelist. eventually: MF/2/E flag? if (( oldthing->type == MT_PLAYER || (oldthing->state - states) == S_RING || @@ -1896,7 +1892,10 @@ static void R_ProjectSprite(mobj_t *thing) oldthing->type == MT_EGGMOBILE4_MACE || (oldthing->type >= MT_SMALLMACE && oldthing->type <= MT_REDSPRINGBALL) // .W. ) && !papersprite) - R_ProjectDropShadow(oldthing, vis, basetx, tz); + R_ProjectDropShadow(oldthing, vis, + ///@TODO make this scale configurable! + ((oldthing->state - states) == S_RING) ? 2*FRACUNIT/3 : FRACUNIT, + basetx, tz); // Debug ++objectsdrawn; From 7d2402ac62d5c4a8871aa2f89af5b60f8d5c8d45 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Wed, 8 Jan 2020 23:33:43 -0600 Subject: [PATCH 22/83] Fix shadows under hiresscale characters --- src/r_things.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/r_things.c b/src/r_things.c index f2b205429..73c598549 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1285,6 +1285,8 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, shadow->gzt = shadow->pz + shadow->patch->height * shadowyscale / 2; shadow->gz = shadow->gzt - shadow->patch->height * shadowyscale; shadow->texturemid = FixedMul(thing->scale, FixedDiv(shadow->gzt - viewz, shadowyscale)); + if (thing->skin && ((skin_t *)thing->skin)->flags & SF_HIRES) + shadow->texturemid = FixedMul(shadow->texturemid, ((skin_t *)thing->skin)->highresscale); shadow->scalestep = 0; shadow->shear.tan = shadowskew; // repurposed variable From 1113a13621a549fa180910f0767592e51a5f43a8 Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 10 Jan 2020 12:55:03 -0800 Subject: [PATCH 23/83] 1upsound always plays a sound instead of jingle --- src/p_user.c | 7 +++++++ src/s_sound.c | 9 +++++++++ src/s_sound.h | 2 ++ 3 files changed, 18 insertions(+) diff --git a/src/p_user.c b/src/p_user.c index a97e62052..f56b321e1 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1463,6 +1463,13 @@ void P_PlayLivesJingle(player_t *player) S_StartSound(NULL, sfx_oneup); else if (mariomode) S_StartSound(NULL, sfx_marioa); + else if (cv_1upsound.value) + { + if (S_sfx[sfx_oneup].lumpnum != LUMPERROR) + S_StartSound(NULL, sfx_oneup); + else + S_StartSound(NULL, sfx_chchng);/* at least play something! */ + } else { P_PlayJingle(player, JT_1UP); diff --git a/src/s_sound.c b/src/s_sound.c index 0235d8376..019f5c765 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -117,6 +117,14 @@ static consvar_t surround = {"surround", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL consvar_t cv_resetmusic = {"resetmusic", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_resetmusicbyheader = {"resetmusicbyheader", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; +static CV_PossibleValue_t cons_1upsound_t[] = { + {0, "Jingle"}, + {1, "Sound"}, + + {0} +}; +consvar_t cv_1upsound = {"1upsound", "Jingle", CV_SAVE, cons_1upsound_t, NULL, 0, NULL, NULL, 0, 0, NULL}; + // Sound system toggles, saved into the config consvar_t cv_gamedigimusic = {"digimusic", "On", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, GameDigiMusic_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_gamemidimusic = {"midimusic", "On", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, GameMIDIMusic_OnChange, 0, NULL, NULL, 0, 0, NULL}; @@ -287,6 +295,7 @@ void S_RegisterSoundStuff(void) CV_RegisterVar(&cv_samplerate); CV_RegisterVar(&cv_resetmusic); CV_RegisterVar(&cv_resetmusicbyheader); + CV_RegisterVar(&cv_1upsound); CV_RegisterVar(&cv_playsoundsifunfocused); CV_RegisterVar(&cv_playmusicifunfocused); CV_RegisterVar(&cv_gamesounds); diff --git a/src/s_sound.h b/src/s_sound.h index 18f2d3743..9a4cbe48b 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -35,6 +35,8 @@ extern consvar_t cv_numChannels; extern consvar_t cv_resetmusic; extern consvar_t cv_resetmusicbyheader; +extern consvar_t cv_1upsound; + #define RESETMUSIC (!modeattacking && \ (cv_resetmusicbyheader.value ? \ (mapheaderinfo[gamemap-1]->musforcereset != -1 ? mapheaderinfo[gamemap-1]->musforcereset : cv_resetmusic.value) \ From 134d1831e3d7d4abfce8a562c11f7a202bd2bd1f Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 10 Jan 2020 12:55:22 -0800 Subject: [PATCH 24/83] Menu option for 1upsound --- src/m_menu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/m_menu.c b/src/m_menu.c index 5e6b6f8ba..0d19a6a43 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1375,8 +1375,9 @@ static menuitem_t OP_SoundOptionsMenu[] = {IT_HEADER, NULL, "Miscellaneous", NULL, 102}, {IT_STRING | IT_CVAR, NULL, "Closed Captioning", &cv_closedcaptioning, 114}, {IT_STRING | IT_CVAR, NULL, "Reset Music Upon Dying", &cv_resetmusic, 124}, + {IT_STRING | IT_CVAR, NULL, "Default 1-Up sound", &cv_1upsound, 134}, - {IT_STRING | IT_SUBMENU, NULL, "Advanced Settings...", &OP_SoundAdvancedDef, 144}, + {IT_STRING | IT_SUBMENU, NULL, "Advanced Settings...", &OP_SoundAdvancedDef, 154}, }; #ifdef HAVE_OPENMPT From 9c8988ab57c872193a84a3505bb48de6b4654913 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sat, 11 Jan 2020 18:48:47 +0000 Subject: [PATCH 25/83] Don't make locale code dependent on GETTEXT, save that for the actual gettext related stuff! --- src/d_main.c | 2 -- src/doomdef.h | 2 +- src/m_misc.c | 18 +++++++++++------- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index e55c65bbb..1001e99a9 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1046,10 +1046,8 @@ void D_SRB2Main(void) I_OutputMsg("setvbuf didnt work\n"); #endif -#ifdef GETTEXT // initialise locale code M_StartupLocale(); -#endif // get parameters from a response file (eg: srb2 @parms.txt) M_FindResponseFile(); diff --git a/src/doomdef.h b/src/doomdef.h index 55ad8abed..1c4e9dc89 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -98,8 +98,8 @@ #ifdef GETTEXT #include -#include #endif +#include // locale should not be dependent on GETTEXT -- 11/01/20 Monster Iestyn #include #include diff --git a/src/m_misc.c b/src/m_misc.c index 83c0c7bec..5ee7b0ac9 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -1594,16 +1594,19 @@ boolean M_ScreenshotResponder(event_t *ev) // M_StartupLocale. // Sets up gettext to translate SRB2's strings. #ifdef GETTEXT -#if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON) -#define GETTEXTDOMAIN1 "/usr/share/locale" -#define GETTEXTDOMAIN2 "/usr/local/share/locale" -#elif defined (_WIN32) -#define GETTEXTDOMAIN1 "." -#endif + #if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON) + #define GETTEXTDOMAIN1 "/usr/share/locale" + #define GETTEXTDOMAIN2 "/usr/local/share/locale" + #elif defined (_WIN32) + #define GETTEXTDOMAIN1 "." + #endif +#endif // GETTEXT void M_StartupLocale(void) { +#ifdef GETTEXT char *textdomhandle = NULL; +#endif //GETTEXT CONS_Printf("M_StartupLocale...\n"); @@ -1612,6 +1615,7 @@ void M_StartupLocale(void) // Do not set numeric locale as that affects atof setlocale(LC_NUMERIC, "C"); +#ifdef GETTEXT // FIXME: global name define anywhere? #ifdef GETTEXTDOMAIN1 textdomhandle = bindtextdomain("srb2", GETTEXTDOMAIN1); @@ -1632,8 +1636,8 @@ void M_StartupLocale(void) textdomain("srb2"); else CONS_Printf("Could not find locale text domain!\n"); +#endif //GETTEXT } -#endif // ========================================================================== // MISC STRING FUNCTIONS From 1643e6623df1eeed9d02e399bfc9444f3bfa1a95 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sat, 11 Jan 2020 20:24:43 +0000 Subject: [PATCH 26/83] whoops, forgot to do this --- src/doomdef.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doomdef.h b/src/doomdef.h index 1c4e9dc89..696071597 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -451,12 +451,12 @@ char savegamename[256]; // m_misc.h #ifdef GETTEXT #define M_GetText(String) gettext(String) -void M_StartupLocale(void); #else // If no translations are to be used, make a stub // M_GetText function that just returns the string. #define M_GetText(x) (x) #endif +void M_StartupLocale(void); extern void *(*M_Memcpy)(void* dest, const void* src, size_t n) FUNCNONNULL; char *va(const char *format, ...) FUNCPRINTF; char *M_GetToken(const char *inputString); From 4e5f49c60d11382bd054f2bb84b80da7e692d0ee Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 11 Jan 2020 17:39:53 -0600 Subject: [PATCH 27/83] Fix player shadows while on rope hangs etc --- src/p_mobj.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/p_mobj.c b/src/p_mobj.c index a4231fa74..50f6106d1 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -3902,11 +3902,15 @@ static void P_PlayerMobjThinker(mobj_t *mobj) mobj->z += mobj->momz; P_SetThingPosition(mobj); P_CheckPosition(mobj, mobj->x, mobj->y); + mobj->floorz = tmfloorz; + mobj->ceilingz = tmceilingz; goto animonly; } else if (mobj->player->powers[pw_carry] == CR_MACESPIN) { P_CheckPosition(mobj, mobj->x, mobj->y); + mobj->floorz = tmfloorz; + mobj->ceilingz = tmceilingz; goto animonly; } } From 1b0a3d0fe3bb6f5af5cb7177b2e6d3ade4e137c0 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 11 Jan 2020 17:56:49 -0600 Subject: [PATCH 28/83] Use dedicated shadow graphic --- src/r_things.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_things.c b/src/r_things.c index 6cedced1c..ff9993525 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1244,7 +1244,7 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, scalemul = FixedMul(FRACUNIT - floordiff/640, scale); - patch = W_CachePatchNum(sprites[SPR_THOK].spriteframes[0].lumppat[0], PU_CACHE); + patch = W_CachePatchName("DSHADOW", PU_CACHE); xscale = FixedDiv(projection, tz); yscale = FixedDiv(projectiony, tz); shadowxscale = FixedMul(thing->radius*2, scalemul) / patch->width; From ba8ff3d502b2d8e06d1159f5f27062ae8f3cc49e Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 11 Jan 2020 18:24:08 -0600 Subject: [PATCH 29/83] Add mobj shadowscale property --- src/p_inter.c | 1 + src/p_mobj.c | 16 ++++++++++++++++ src/p_mobj.h | 1 + src/r_things.c | 15 ++------------- 4 files changed, 20 insertions(+), 13 deletions(-) diff --git a/src/p_inter.c b/src/p_inter.c index 71740822e..b2d158062 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1869,6 +1869,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) S_StartSound(toucher, special->info->deathsound); // was NULL, but changed to player so you could hear others pick up rings P_KillMobj(special, NULL, toucher, 0); + special->shadowscale = 0; } /** Prints death messages relating to a dying or hit player. diff --git a/src/p_mobj.c b/src/p_mobj.c index 50f6106d1..e4de59031 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10557,6 +10557,22 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) else mobj->z = z; + // Set shadowscale here, before spawn hook so that Lua can change it + if ( + type == MT_PLAYER || + type == MT_ROLLOUTROCK || + type == MT_EGGMOBILE4_MACE || + (type >= MT_SMALLMACE && type <= MT_REDSPRINGBALL) || + (mobj->flags & MF_ENEMY) + ) + mobj->shadowscale = FRACUNIT; + else if ( + type >= MT_RING && type <= MT_FLINGEMERALD && type != MT_EMERALDSPAWN + ) + mobj->shadowscale = 2*FRACUNIT/3; + else + mobj->shadowscale = 0; + #ifdef HAVE_BLUA // DANGER! This can cause P_SpawnMobj to return NULL! // Avoid using P_RemoveMobj on the newly created mobj in "MobjSpawn" Lua hooks! diff --git a/src/p_mobj.h b/src/p_mobj.h index 92160d9e2..fd0c95a56 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -375,6 +375,7 @@ typedef struct mobj_s #endif boolean colorized; // Whether the mobj uses the rainbow colormap + fixed_t shadowscale; // If this object casts a shadow, and the size relative to radius // WARNING: New fields must be added separately to savegame and Lua. } mobj_t; diff --git a/src/r_things.c b/src/r_things.c index ff9993525..0fc806071 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1902,19 +1902,8 @@ static void R_ProjectSprite(mobj_t *thing) if (thing->subsector->sector->numlights) R_SplitSprite(vis); - ///@TODO temporary: whitelist. eventually: MF/2/E flag? - if (( - oldthing->type == MT_PLAYER || - (oldthing->state - states) == S_RING || - oldthing->type == MT_ROLLOUTROCK || - oldthing->flags & MF_ENEMY || - oldthing->type == MT_EGGMOBILE4_MACE || - (oldthing->type >= MT_SMALLMACE && oldthing->type <= MT_REDSPRINGBALL) // .W. - ) && !papersprite) - R_ProjectDropShadow(oldthing, vis, - ///@TODO make this scale configurable! - ((oldthing->state - states) == S_RING) ? 2*FRACUNIT/3 : FRACUNIT, - basetx, tz); + if (oldthing->shadowscale && !papersprite) + R_ProjectDropShadow(oldthing, vis, oldthing->shadowscale, basetx, tz); // Debug ++objectsdrawn; From cfb9b3c234ef55dd719174aa50176c41eb45a206 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sat, 11 Jan 2020 18:28:15 -0600 Subject: [PATCH 30/83] Expose mobj->shadowscale to Lua --- src/lua_mobjlib.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index 222487751..fd32b2134 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -88,7 +88,8 @@ enum mobj_e { #ifdef ESLOPE mobj_standingslope, #endif - mobj_colorized + mobj_colorized, + mobj_shadowscale }; static const char *const mobj_opt[] = { @@ -156,6 +157,7 @@ static const char *const mobj_opt[] = { "standingslope", #endif "colorized", + "shadowscale", NULL}; #define UNIMPLEMENTED luaL_error(L, LUA_QL("mobj_t") " field " LUA_QS " is not implemented for Lua and cannot be accessed.", mobj_opt[field]) @@ -390,6 +392,9 @@ static int mobj_get(lua_State *L) case mobj_colorized: lua_pushboolean(L, mo->colorized); break; + case mobj_shadowscale: + lua_pushfixed(L, mo->shadowscale); + break; default: // extra custom variables in Lua memory lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS); I_Assert(lua_istable(L, -1)); @@ -719,6 +724,8 @@ static int mobj_set(lua_State *L) case mobj_colorized: mo->colorized = luaL_checkboolean(L, 3); break; + case mobj_shadowscale: + mo->shadowscale = luaL_checkfixed(L, 3); default: lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS); I_Assert(lua_istable(L, -1)); From 9e101fc2bb8d86cbc0e8317368f1e21fd9fed42b Mon Sep 17 00:00:00 2001 From: fickleheart Date: Sun, 12 Jan 2020 09:10:09 -0600 Subject: [PATCH 31/83] Limit shadow Y scale to prevent graphical bugs --- src/r_things.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index 0fc806071..41fb103e3 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1247,8 +1247,10 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, patch = W_CachePatchName("DSHADOW", PU_CACHE); xscale = FixedDiv(projection, tz); yscale = FixedDiv(projectiony, tz); - shadowxscale = FixedMul(thing->radius*2, scalemul) / patch->width; - shadowyscale = FixedMul(FixedMul(thing->radius*2 / patch->height, scalemul), FixedDiv(abs(floorz - viewz), tz)); + shadowxscale = FixedMul(thing->radius*2, scalemul); + shadowyscale = FixedMul(FixedMul(thing->radius*2, scalemul), FixedDiv(abs(floorz - viewz), tz)); + shadowyscale = min(shadowyscale, shadowxscale) / patch->height; + shadowxscale /= patch->width; shadowskew = 0; if (floorslope) From f6244ec9a443cab3c86e95b65c592c28c1b47254 Mon Sep 17 00:00:00 2001 From: Louis-Antoine Date: Sun, 12 Jan 2020 20:08:41 +0100 Subject: [PATCH 32/83] Disable title map when entering a netgame --- src/d_clisrv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 586e3077c..2c7493cbe 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1622,6 +1622,7 @@ static void CL_LoadReceivedSavegame(void) paused = false; demoplayback = false; + titlemapinaction = TITLEMAP_OFF; titledemo = false; automapactive = false; From 0d6b6efe0ffd458d24d9f0218c244d306524f88e Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 13 Jan 2020 15:20:50 -0800 Subject: [PATCH 33/83] Refactor R_LoadTextures into something manageable (no goto!!) --- src/r_data.c | 496 ++++++++++++++++++++++++++------------------------- 1 file changed, 256 insertions(+), 240 deletions(-) diff --git a/src/r_data.c b/src/r_data.c index d35777664..ebb73cd42 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -699,254 +699,29 @@ void R_FlushTextureCache(void) int R_CountTexturesInTEXTURESLump(UINT16 wadNum, UINT16 lumpNum); void R_ParseTEXTURESLump(UINT16 wadNum, UINT16 lumpNum, INT32 *index); -// -// R_LoadTextures -// Initializes the texture list with the textures from the world map. -// -#define TX_START "TX_START" -#define TX_END "TX_END" -void R_LoadTextures(void) +#ifdef WALLFLATS +static INT32 +Rloadflats (INT32 i, INT32 w) { - INT32 i, w; UINT16 j; - UINT16 texstart, texend, texturesLumpPos; - patch_t *patchlump; - texpatch_t *patch; + UINT16 texstart, texend; texture_t *texture; + texpatch_t *patch; - // Free previous memory before numtextures change. - if (numtextures) + // Yes + if (wadfiles[w]->type == RET_PK3) { - for (i = 0; i < numtextures; i++) - { - Z_Free(textures[i]); - Z_Free(texturecache[i]); - } - Z_Free(texturetranslation); - Z_Free(textures); - Z_Free(texflats); + texstart = W_CheckNumForFolderStartPK3("flats/", (UINT16)w, 0); + texend = W_CheckNumForFolderEndPK3("flats/", (UINT16)w, texstart); + } + else + { + texstart = W_CheckNumForNamePwad("F_START", (UINT16)w, 0); + texend = W_CheckNumForNamePwad("F_END", (UINT16)w, texstart); } - // Load patches and textures. - - // Get the number of textures to check. - // NOTE: Make SURE the system does not process - // the markers. - // This system will allocate memory for all duplicate/patched textures even if it never uses them, - // but the alternative is to spend a ton of time checking and re-checking all previous entries just to skip any potentially patched textures. - for (w = 0, numtextures = 0; w < numwadfiles; w++) + if (!( texstart == INT16_MAX || texend == INT16_MAX )) { - // Count the textures from TEXTURES lumps - texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0); - while (texturesLumpPos != INT16_MAX) - { - numtextures += R_CountTexturesInTEXTURESLump((UINT16)w, (UINT16)texturesLumpPos); - texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, texturesLumpPos + 1); - } - - // Count single-patch textures - if (wadfiles[w]->type == RET_PK3) - { - texstart = W_CheckNumForFolderStartPK3("textures/", (UINT16)w, 0); - texend = W_CheckNumForFolderEndPK3("textures/", (UINT16)w, texstart); - } - else - { - texstart = W_CheckNumForNamePwad(TX_START, (UINT16)w, 0); - texend = W_CheckNumForNamePwad(TX_END, (UINT16)w, 0); - } - - if (texstart == INT16_MAX || texend == INT16_MAX) -#ifdef WALLFLATS - goto countflats; -#else - continue; -#endif - - texstart++; // Do not count the first marker - - // PK3s have subfolders, so we can't just make a simple sum - if (wadfiles[w]->type == RET_PK3) - { - for (j = texstart; j < texend; j++) - { - if (!W_IsLumpFolder((UINT16)w, j)) // Check if lump is a folder; if not, then count it - numtextures++; - } - } - else // Add all the textures between TX_START and TX_END - { - numtextures += (UINT32)(texend - texstart); - } - -#ifdef WALLFLATS -countflats: - // Count flats - if (wadfiles[w]->type == RET_PK3) - { - texstart = W_CheckNumForFolderStartPK3("flats/", (UINT16)w, 0); - texend = W_CheckNumForFolderEndPK3("flats/", (UINT16)w, texstart); - } - else - { - texstart = W_CheckNumForNamePwad("F_START", (UINT16)w, 0); - texend = W_CheckNumForNamePwad("F_END", (UINT16)w, texstart); - } - - if (texstart == INT16_MAX || texend == INT16_MAX) - continue; - - texstart++; // Do not count the first marker - - // PK3s have subfolders, so we can't just make a simple sum - if (wadfiles[w]->type == RET_PK3) - { - for (j = texstart; j < texend; j++) - { - if (!W_IsLumpFolder((UINT16)w, j)) // Check if lump is a folder; if not, then count it - numtextures++; - } - } - else // Add all the textures between F_START and F_END - { - numtextures += (UINT32)(texend - texstart); - } -#endif - } - - // If no textures found by this point, bomb out - if (!numtextures) - I_Error("No textures detected in any WADs!\n"); - - // Allocate memory and initialize to 0 for all the textures we are initialising. - // There are actually 5 buffers allocated in one for convenience. - textures = Z_Calloc((numtextures * sizeof(void *)) * 5, PU_STATIC, NULL); - texflats = Z_Calloc((numtextures * sizeof(*texflats)), PU_STATIC, NULL); - - // Allocate texture column offset table. - texturecolumnofs = (void *)((UINT8 *)textures + (numtextures * sizeof(void *))); - // Allocate texture referencing cache. - texturecache = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 2)); - // Allocate texture width table. - texturewidth = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 3)); - // Allocate texture height table. - textureheight = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 4)); - // Create translation table for global animation. - texturetranslation = Z_Malloc((numtextures + 1) * sizeof(*texturetranslation), PU_STATIC, NULL); - - for (i = 0; i < numtextures; i++) - texturetranslation[i] = i; - - for (i = 0, w = 0; w < numwadfiles; w++) - { - // Get the lump numbers for the markers in the WAD, if they exist. - if (wadfiles[w]->type == RET_PK3) - { - texstart = W_CheckNumForFolderStartPK3("textures/", (UINT16)w, 0); - texend = W_CheckNumForFolderEndPK3("textures/", (UINT16)w, texstart); - texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0); - while (texturesLumpPos != INT16_MAX) - { - R_ParseTEXTURESLump(w, texturesLumpPos, &i); - texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, texturesLumpPos + 1); - } - } - else - { - texstart = W_CheckNumForNamePwad(TX_START, (UINT16)w, 0); - texend = W_CheckNumForNamePwad(TX_END, (UINT16)w, 0); - texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0); - if (texturesLumpPos != INT16_MAX) - R_ParseTEXTURESLump(w, texturesLumpPos, &i); - } - - if (texstart == INT16_MAX || texend == INT16_MAX) -#ifdef WALLFLATS - goto checkflats; -#else - continue; -#endif - - texstart++; // Do not count the first marker - - // Work through each lump between the markers in the WAD. - for (j = 0; j < (texend - texstart); j++) - { - UINT16 wadnum = (UINT16)w; - lumpnum_t lumpnum = texstart + j; -#ifndef NO_PNG_LUMPS - size_t lumplength; -#endif - - if (wadfiles[w]->type == RET_PK3) - { - if (W_IsLumpFolder(wadnum, lumpnum)) // Check if lump is a folder - continue; // If it is then SKIP IT - } - - patchlump = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); -#ifndef NO_PNG_LUMPS - lumplength = W_LumpLengthPwad(wadnum, lumpnum); -#endif - - //CONS_Printf("\n\"%s\" is a single patch, dimensions %d x %d",W_CheckNameForNumPwad((UINT16)w,texstart+j),patchlump->width, patchlump->height); - texture = textures[i] = Z_Calloc(sizeof(texture_t) + sizeof(texpatch_t), PU_STATIC, NULL); - - // Set texture properties. - M_Memcpy(texture->name, W_CheckNameForNumPwad(wadnum, lumpnum), sizeof(texture->name)); - -#ifndef NO_PNG_LUMPS - if (R_IsLumpPNG((UINT8 *)patchlump, lumplength)) - { - INT16 width, height; - R_PNGDimensions((UINT8 *)patchlump, &width, &height, lumplength); - texture->width = width; - texture->height = height; - } - else -#endif - { - texture->width = SHORT(patchlump->width); - texture->height = SHORT(patchlump->height); - } - - texture->type = TEXTURETYPE_SINGLEPATCH; - texture->patchcount = 1; - texture->holes = false; - texture->flip = 0; - - // Allocate information for the texture's patches. - patch = &texture->patches[0]; - - patch->originx = patch->originy = 0; - patch->wad = (UINT16)w; - patch->lump = texstart + j; - patch->flip = 0; - - Z_Unlock(patchlump); - - texturewidth[i] = texture->width; - textureheight[i] = texture->height << FRACBITS; - i++; - } - -#ifdef WALLFLATS -checkflats: - // Yes - if (wadfiles[w]->type == RET_PK3) - { - texstart = W_CheckNumForFolderStartPK3("flats/", (UINT16)w, 0); - texend = W_CheckNumForFolderEndPK3("flats/", (UINT16)w, texstart); - } - else - { - texstart = W_CheckNumForNamePwad("F_START", (UINT16)w, 0); - texend = W_CheckNumForNamePwad("F_END", (UINT16)w, texstart); - } - - if (texstart == INT16_MAX || texend == INT16_MAX) - continue; - texstart++; // Do not count the first marker // Work through each lump between the markers in the WAD. @@ -1029,6 +804,247 @@ checkflats: textureheight[i] = texture->height << FRACBITS; i++; } + } + + return i; +} +#endif/*WALLFLATS*/ + +#define TX_START "TX_START" +#define TX_END "TX_END" + +static INT32 +Rloadtextures (INT32 i, INT32 w) +{ + UINT16 j; + UINT16 texstart, texend, texturesLumpPos; + texture_t *texture; + patch_t *patchlump; + texpatch_t *patch; + + // Get the lump numbers for the markers in the WAD, if they exist. + if (wadfiles[w]->type == RET_PK3) + { + texstart = W_CheckNumForFolderStartPK3("textures/", (UINT16)w, 0); + texend = W_CheckNumForFolderEndPK3("textures/", (UINT16)w, texstart); + texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0); + while (texturesLumpPos != INT16_MAX) + { + R_ParseTEXTURESLump(w, texturesLumpPos, &i); + texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, texturesLumpPos + 1); + } + } + else + { + texstart = W_CheckNumForNamePwad(TX_START, (UINT16)w, 0); + texend = W_CheckNumForNamePwad(TX_END, (UINT16)w, 0); + texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0); + if (texturesLumpPos != INT16_MAX) + R_ParseTEXTURESLump(w, texturesLumpPos, &i); + } + + if (!( texstart == INT16_MAX || texend == INT16_MAX )) + { + texstart++; // Do not count the first marker + + // Work through each lump between the markers in the WAD. + for (j = 0; j < (texend - texstart); j++) + { + UINT16 wadnum = (UINT16)w; + lumpnum_t lumpnum = texstart + j; +#ifndef NO_PNG_LUMPS + size_t lumplength; +#endif + + if (wadfiles[w]->type == RET_PK3) + { + if (W_IsLumpFolder(wadnum, lumpnum)) // Check if lump is a folder + continue; // If it is then SKIP IT + } + + patchlump = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); +#ifndef NO_PNG_LUMPS + lumplength = W_LumpLengthPwad(wadnum, lumpnum); +#endif + + //CONS_Printf("\n\"%s\" is a single patch, dimensions %d x %d",W_CheckNameForNumPwad((UINT16)w,texstart+j),patchlump->width, patchlump->height); + texture = textures[i] = Z_Calloc(sizeof(texture_t) + sizeof(texpatch_t), PU_STATIC, NULL); + + // Set texture properties. + M_Memcpy(texture->name, W_CheckNameForNumPwad(wadnum, lumpnum), sizeof(texture->name)); + +#ifndef NO_PNG_LUMPS + if (R_IsLumpPNG((UINT8 *)patchlump, lumplength)) + { + INT16 width, height; + R_PNGDimensions((UINT8 *)patchlump, &width, &height, lumplength); + texture->width = width; + texture->height = height; + } + else +#endif + { + texture->width = SHORT(patchlump->width); + texture->height = SHORT(patchlump->height); + } + + texture->type = TEXTURETYPE_SINGLEPATCH; + texture->patchcount = 1; + texture->holes = false; + texture->flip = 0; + + // Allocate information for the texture's patches. + patch = &texture->patches[0]; + + patch->originx = patch->originy = 0; + patch->wad = (UINT16)w; + patch->lump = texstart + j; + patch->flip = 0; + + Z_Unlock(patchlump); + + texturewidth[i] = texture->width; + textureheight[i] = texture->height << FRACBITS; + i++; + } + } + + return i; +} + +// +// R_LoadTextures +// Initializes the texture list with the textures from the world map. +// +void R_LoadTextures(void) +{ + INT32 i, w; + UINT16 j; + UINT16 texstart, texend, texturesLumpPos; + + // Free previous memory before numtextures change. + if (numtextures) + { + for (i = 0; i < numtextures; i++) + { + Z_Free(textures[i]); + Z_Free(texturecache[i]); + } + Z_Free(texturetranslation); + Z_Free(textures); + Z_Free(texflats); + } + + // Load patches and textures. + + // Get the number of textures to check. + // NOTE: Make SURE the system does not process + // the markers. + // This system will allocate memory for all duplicate/patched textures even if it never uses them, + // but the alternative is to spend a ton of time checking and re-checking all previous entries just to skip any potentially patched textures. + for (w = 0, numtextures = 0; w < numwadfiles; w++) + { +#ifdef WALLFLATS + // Count flats + if (wadfiles[w]->type == RET_PK3) + { + texstart = W_CheckNumForFolderStartPK3("flats/", (UINT16)w, 0); + texend = W_CheckNumForFolderEndPK3("flats/", (UINT16)w, texstart); + } + else + { + texstart = W_CheckNumForNamePwad("F_START", (UINT16)w, 0); + texend = W_CheckNumForNamePwad("F_END", (UINT16)w, texstart); + } + + if (!( texstart == INT16_MAX || texend == INT16_MAX )) + { + texstart++; // Do not count the first marker + + // PK3s have subfolders, so we can't just make a simple sum + if (wadfiles[w]->type == RET_PK3) + { + for (j = texstart; j < texend; j++) + { + if (!W_IsLumpFolder((UINT16)w, j)) // Check if lump is a folder; if not, then count it + numtextures++; + } + } + else // Add all the textures between F_START and F_END + { + numtextures += (UINT32)(texend - texstart); + } + } +#endif/*WALLFLATS*/ + + // Count the textures from TEXTURES lumps + texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0); + while (texturesLumpPos != INT16_MAX) + { + numtextures += R_CountTexturesInTEXTURESLump((UINT16)w, (UINT16)texturesLumpPos); + texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, texturesLumpPos + 1); + } + + // Count single-patch textures + if (wadfiles[w]->type == RET_PK3) + { + texstart = W_CheckNumForFolderStartPK3("textures/", (UINT16)w, 0); + texend = W_CheckNumForFolderEndPK3("textures/", (UINT16)w, texstart); + } + else + { + texstart = W_CheckNumForNamePwad(TX_START, (UINT16)w, 0); + texend = W_CheckNumForNamePwad(TX_END, (UINT16)w, 0); + } + + if (texstart == INT16_MAX || texend == INT16_MAX) + continue; + + texstart++; // Do not count the first marker + + // PK3s have subfolders, so we can't just make a simple sum + if (wadfiles[w]->type == RET_PK3) + { + for (j = texstart; j < texend; j++) + { + if (!W_IsLumpFolder((UINT16)w, j)) // Check if lump is a folder; if not, then count it + numtextures++; + } + } + else // Add all the textures between TX_START and TX_END + { + numtextures += (UINT32)(texend - texstart); + } + } + + // If no textures found by this point, bomb out + if (!numtextures) + I_Error("No textures detected in any WADs!\n"); + + // Allocate memory and initialize to 0 for all the textures we are initialising. + // There are actually 5 buffers allocated in one for convenience. + textures = Z_Calloc((numtextures * sizeof(void *)) * 5, PU_STATIC, NULL); + texflats = Z_Calloc((numtextures * sizeof(*texflats)), PU_STATIC, NULL); + + // Allocate texture column offset table. + texturecolumnofs = (void *)((UINT8 *)textures + (numtextures * sizeof(void *))); + // Allocate texture referencing cache. + texturecache = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 2)); + // Allocate texture width table. + texturewidth = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 3)); + // Allocate texture height table. + textureheight = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 4)); + // Create translation table for global animation. + texturetranslation = Z_Malloc((numtextures + 1) * sizeof(*texturetranslation), PU_STATIC, NULL); + + for (i = 0; i < numtextures; i++) + texturetranslation[i] = i; + + for (i = 0, w = 0; w < numwadfiles; w++) + { + i = Rloadtextures(i, w); +#ifdef WALLFLATS + i = Rloadflats(i, w); #endif } From 68b78f44d8e72664fbac0a8676e2ad656b137edd Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 13 Jan 2020 15:21:35 -0800 Subject: [PATCH 34/83] Load flats first so textures with the same name are prefered on walls --- src/r_data.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_data.c b/src/r_data.c index ebb73cd42..9f80e257b 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1042,10 +1042,10 @@ void R_LoadTextures(void) for (i = 0, w = 0; w < numwadfiles; w++) { - i = Rloadtextures(i, w); #ifdef WALLFLATS i = Rloadflats(i, w); #endif + i = Rloadtextures(i, w); } #ifdef HWRENDER From af2d3cfd16a59c385f25cb06f6717502ccbc9b2e Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 3 Aug 2019 13:27:57 -0700 Subject: [PATCH 35/83] Let MS_Connect use -bindaddr And so now you really can host from multiple IP addresses. (cherry picked from commit e56bf12537700af7b7fcd0d3b0e8586e41edddd1) --- src/mserv.c | 94 ++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 67 insertions(+), 27 deletions(-) diff --git a/src/mserv.c b/src/mserv.c index ddabdb6c0..1052de80c 100644 --- a/src/mserv.c +++ b/src/mserv.c @@ -323,7 +323,7 @@ static INT32 GetServersList(void) // // MS_Connect() // -static INT32 MS_Connect(const char *ip_addr, const char *str_port, INT32 async) +static INT32 MS_SubConnect(const char *ip_addr, const char *str_port, INT32 async, struct sockaddr *bindaddr, socklen_t bindaddrlen) { #ifdef NONET (void)ip_addr; @@ -356,44 +356,48 @@ static INT32 MS_Connect(const char *ip_addr, const char *str_port, INT32 async) socket_fd = socket(runp->ai_family, runp->ai_socktype, runp->ai_protocol); if (socket_fd != (SOCKET_TYPE)ERRSOCKET) { - if (async) // do asynchronous connection + if (!bindaddr || bind(socket_fd, bindaddr, bindaddrlen) == 0) { + if (async) // do asynchronous connection + { #ifdef FIONBIO #ifdef WATTCP - char res = 1; + char res = 1; #else - unsigned long res = 1; + unsigned long res = 1; #endif - ioctl(socket_fd, FIONBIO, &res); + ioctl(socket_fd, FIONBIO, &res); #endif - if (connect(socket_fd, runp->ai_addr, (socklen_t)runp->ai_addrlen) == ERRSOCKET) - { -#ifdef _WIN32 // humm, on win32/win64 it doesn't work with EINPROGRESS (stupid windows) - if (WSAGetLastError() != WSAEWOULDBLOCK) -#else - if (errno != EINPROGRESS) -#endif + if (connect(socket_fd, runp->ai_addr, (socklen_t)runp->ai_addrlen) == ERRSOCKET) { - con_state = MSCS_FAILED; - CloseConnection(); - I_freeaddrinfo(ai); - return MS_CONNECT_ERROR; +#ifdef _WIN32 // humm, on win32/win64 it doesn't work with EINPROGRESS (stupid windows) + if (WSAGetLastError() != WSAEWOULDBLOCK) +#else + if (errno != EINPROGRESS) +#endif + { + con_state = MSCS_FAILED; + CloseConnection(); + I_freeaddrinfo(ai); + return MS_CONNECT_ERROR; + } } + con_state = MSCS_WAITING; + FD_ZERO(&wset); + FD_SET(socket_fd, &wset); + select_timeout.tv_sec = 0, select_timeout.tv_usec = 0; + I_freeaddrinfo(ai); + return 0; + } + else if (connect(socket_fd, runp->ai_addr, (socklen_t)runp->ai_addrlen) != ERRSOCKET) + { + I_freeaddrinfo(ai); + return 0; } - con_state = MSCS_WAITING; - FD_ZERO(&wset); - FD_SET(socket_fd, &wset); - select_timeout.tv_sec = 0, select_timeout.tv_usec = 0; - I_freeaddrinfo(ai); - return 0; - } - else if (connect(socket_fd, runp->ai_addr, (socklen_t)runp->ai_addrlen) != ERRSOCKET) - { - I_freeaddrinfo(ai); - return 0; } + close(socket_fd); } runp = runp->ai_next; } @@ -402,6 +406,42 @@ static INT32 MS_Connect(const char *ip_addr, const char *str_port, INT32 async) return MS_CONNECT_ERROR; } +static INT32 MS_Connect(const char *ip_addr, const char *str_port, INT32 async) +{ + const char *lhost; + struct my_addrinfo hints; + struct my_addrinfo *ai, *aip; + int c; + if (M_CheckParm("-bindaddr") && ( lhost = M_GetNextParm() )) + { + memset (&hints, 0x00, sizeof(hints)); +#ifdef AI_ADDRCONFIG + hints.ai_flags = AI_ADDRCONFIG; +#endif + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + if (( c = I_getaddrinfo(lhost, 0, &hints, &ai) ) != 0) + { + CONS_Printf( + "mserv.c: bind to %s: %s\n", + lhost, + gai_strerror(c)); + return MS_GETHOSTBYNAME_ERROR; + } + for (aip = ai; aip; aip = aip->ai_next) + { + c = MS_SubConnect(ip_addr, str_port, async, aip->ai_addr, aip->ai_addrlen); + if (c == 0) + return 0; + } + I_freeaddrinfo(ai); + return c; + } + else + return MS_SubConnect(ip_addr, str_port, async, 0, 0); +} + #define NUM_LIST_SERVER MAXSERVERLIST const msg_server_t *GetShortServersList(INT32 room) { From 619efb3d4ecf89b242784d17bbec70a8f7ef6ed6 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 3 Aug 2019 13:30:22 -0700 Subject: [PATCH 36/83] And free addrinfo (cherry picked from commit 986c80fb13e7ae6900792de5b4b43327af7ca76c) --- src/mserv.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/mserv.c b/src/mserv.c index 1052de80c..a842e92e9 100644 --- a/src/mserv.c +++ b/src/mserv.c @@ -433,7 +433,10 @@ static INT32 MS_Connect(const char *ip_addr, const char *str_port, INT32 async) { c = MS_SubConnect(ip_addr, str_port, async, aip->ai_addr, aip->ai_addrlen); if (c == 0) + { + I_freeaddrinfo(ai); return 0; + } } I_freeaddrinfo(ai); return c; From 708ab6ff907cb77bdd05813eefde1f6d81d41a5e Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 14 Jan 2020 21:40:58 -0800 Subject: [PATCH 37/83] Update buffer for SendNameAndColor --- src/d_netcmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 723748448..23ec00b2e 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1174,7 +1174,7 @@ static INT32 snacpending = 0, snac2pending = 0, chmappending = 0; // static void SendNameAndColor(void) { - char buf[MAXPLAYERNAME+2]; + char buf[MAXPLAYERNAME+6]; char *p; p = buf; From 1489b4bcdd1cbd6346db24ab3f14785ca6297d90 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 15 Jan 2020 02:14:20 -0800 Subject: [PATCH 38/83] It's FALLTHRU not fallthru It took a week and me staying up until 2AM to look at the damn manpage and figure out THIS is why I was getting an error about 'if (tutorialmode)' falling through. But I still don't know why it didn't trigger on the MT_TNTBARREL case. Oh well. --- src/p_user.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index 0c4d25554..cd308d932 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -9185,7 +9185,7 @@ mobj_t *P_LookForFocusTarget(player_t *player, mobj_t *exclude, SINT8 direction, case MT_TNTBARREL: if (lockonflags & LOCK_INTERESTS) break; - /*fallthru*/ + /*FALLTHRU*/ case MT_PLAYER: // Don't chase other players! case MT_DETON: continue; // Don't be STUPID, Sonic! @@ -9203,7 +9203,7 @@ mobj_t *P_LookForFocusTarget(player_t *player, mobj_t *exclude, SINT8 direction, case MT_EGGSTATUE: if (tutorialmode) break; // Always focus egg statue in the tutorial - /*fallthru*/ + /*FALLTHRU*/ default: if ((lockonflags & LOCK_BOSS) && ((mo->flags & (MF_BOSS|MF_SHOOTABLE)) == (MF_BOSS|MF_SHOOTABLE))) // allows if it has the flags desired XOR it has the invert aimable flag From 9504ba96da07ec9ec6f4eb4d41bde87024130fd0 Mon Sep 17 00:00:00 2001 From: Louis-Antoine Date: Wed, 15 Jan 2020 15:36:11 +0100 Subject: [PATCH 39/83] Increase maximum and default chat width --- src/g_game.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index eba53627d..a80d0f40a 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -352,8 +352,8 @@ static CV_PossibleValue_t chattime_cons_t[] = {{5, "MIN"}, {999, "MAX"}, {0, NUL 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", "128", CV_SAVE, chatwidth_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +static CV_PossibleValue_t chatwidth_cons_t[] = {{64, "MIN"}, {300, "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}}; From ec5db89e550e842ab7a0ebb24415f39c4e31ab15 Mon Sep 17 00:00:00 2001 From: Louis-Antoine Date: Wed, 15 Jan 2020 15:48:03 +0100 Subject: [PATCH 40/83] Cleanup chat code a little --- src/hu_stuff.c | 54 ++++++++++++++++---------------------------------- 1 file changed, 17 insertions(+), 37 deletions(-) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 14cb481b0..9e708e1cf 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -501,37 +501,31 @@ static void DoSayCommand(SINT8 target, size_t usedargs, UINT8 flags) // what we're gonna do now is check if the player exists // with that logic, characters 4 and 5 are our numbers: const char *newmsg; - char *playernum = (char*) malloc(3); + char playernum[3]; INT32 spc = 1; // used if playernum[1] is a space. strncpy(playernum, msg+3, 3); // check for undesirable characters in our "number" - if (((playernum[0] < '0') || (playernum[0] > '9')) || ((playernum[1] < '0') || (playernum[1] > '9'))) + if (((playernum[0] < '0') || (playernum[0] > '9')) || ((playernum[1] < '0') || (playernum[1] > '9'))) { // check if playernum[1] is a space if (playernum[1] == ' ') spc = 0; - // let it slide + // let it slide else { HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm \'.", false); - free(playernum); 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); - free(playernum); - return; - } - } + if (spc != 0 && msg[5] != ' ') + { + HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm \'.", false); + return; + } - target = atoi((const char*) playernum); // turn that into a number - free(playernum); + target = atoi(playernum); // 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! @@ -1021,9 +1015,6 @@ void HU_Ticker(void) #ifndef NONET static boolean teamtalk = false; -/*static char chatchars[QUEUESIZE]; -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(void) @@ -1083,7 +1074,7 @@ static void HU_queueChatChar(char c) if (strlen(msg) > 4 && strnicmp(msg, "/pm", 3) == 0) // used /pm { INT32 spc = 1; // used if nodenum[1] is a space. - char *nodenum = (char*) malloc(3); + char nodenum[3]; const char *newmsg; // what we're gonna do now is check if the node exists @@ -1098,7 +1089,7 @@ static void HU_queueChatChar(char c) 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'))) + if (((nodenum[0] < '0') || (nodenum[0] > '9')) || ((nodenum[1] < '0') || (nodenum[1] > '9'))) { // check if nodenum[1] is a space if (nodenum[1] == ' ') @@ -1107,7 +1098,6 @@ static void HU_queueChatChar(char c) else { HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm \'.", false); - free(nodenum); return; } } @@ -1117,13 +1107,11 @@ 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); + target = atoi(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! @@ -1648,12 +1636,9 @@ static void HU_drawChatLog(INT32 offset) } 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); // 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; + // 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 = max(dy / charheight - cv_chatheight.value, 0); // if we're not bound by the time, autoscroll for next frame: if (atbottom) @@ -1794,21 +1779,17 @@ static void HU_DrawChat(void) i = 0; for(i=0; (i '9'))) || ((w_chat[4] != 0) && (((w_chat[4] < '0') || (w_chat[4] > '9'))))) && (w_chat[4] != ' ')) break; - - nodenum = (char*) malloc(3); strncpy(nodenum, w_chat+3, 3); - n = atoi((const char*) nodenum); // turn that into a number - free(nodenum); + n = atoi(nodenum); // turn that into a number // special cases: if ((n == 0) && !(w_chat[4] == '0')) @@ -1855,7 +1836,6 @@ static void HU_DrawChat(void) } 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. - } From 0197a83db7f80dc8a412ee41200989322fca1c5b Mon Sep 17 00:00:00 2001 From: Louis-Antoine Date: Wed, 15 Jan 2020 15:57:38 +0100 Subject: [PATCH 41/83] bruh --- src/hu_stuff.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 9e708e1cf..87e888eeb 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -1073,11 +1073,11 @@ static void HU_queueChatChar(char c) if (strlen(msg) > 4 && strnicmp(msg, "/pm", 3) == 0) // used /pm { - INT32 spc = 1; // used if nodenum[1] is a space. - char nodenum[3]; + INT32 spc = 1; // used if playernum[1] is a space. + char playernum[3]; const char *newmsg; - // what we're gonna do now is check if the node exists + // what we're gonna do now is check if the player 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. @@ -1087,17 +1087,17 @@ static void HU_queueChatChar(char c) return; } - strncpy(nodenum, msg+3, 3); + strncpy(playernum, msg+3, 3); // check for undesirable characters in our "number" - if (((nodenum[0] < '0') || (nodenum[0] > '9')) || ((nodenum[1] < '0') || (nodenum[1] > '9'))) + if (((playernum[0] < '0') || (playernum[0] > '9')) || ((playernum[1] < '0') || (playernum[1] > '9'))) { - // check if nodenum[1] is a space - if (nodenum[1] == ' ') + // check if playernum[1] is a space + if (playernum[1] == ' ') spc = 0; // let it slide else { - HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm \'.", false); + HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm \'.", false); return; } } @@ -1106,12 +1106,12 @@ static void HU_queueChatChar(char c) { if (msg[5] != ' ') { - HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm \'.", false); + HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm \'.", false); return; } } - target = atoi(nodenum); // turn that into a number + target = atoi(playernum); // 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! @@ -1123,7 +1123,7 @@ static void HU_queueChatChar(char c) return; } - // we need to get rid of the /pm + // we need to get rid of the /pm newmsg = msg+5+spc; strlcpy(msg, newmsg, 255); } @@ -1782,14 +1782,14 @@ static void HU_DrawChat(void) // filter: (code needs optimization pls help I'm bad with C) if (w_chat[3]) { - char nodenum[3]; + char playernum[3]; UINT32 n; // right, that's half important: (w_chat[4] may be a space since /pm0 msg is perfectly acceptable!) if ( ( ((w_chat[3] != 0) && ((w_chat[3] < '0') || (w_chat[3] > '9'))) || ((w_chat[4] != 0) && (((w_chat[4] < '0') || (w_chat[4] > '9'))))) && (w_chat[4] != ' ')) break; - strncpy(nodenum, w_chat+3, 3); - n = atoi(nodenum); // turn that into a number + strncpy(playernum, w_chat+3, 3); + n = atoi(playernum); // turn that into a number // special cases: if ((n == 0) && !(w_chat[4] == '0')) From 0134be8b78ecc04b92d5f4e3fd781f937cc46285 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Thu, 16 Jan 2020 12:05:21 -0500 Subject: [PATCH 42/83] please stop breaking clang --- src/s_sound.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/s_sound.c b/src/s_sound.c index 019f5c765..606cde597 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -120,8 +120,7 @@ consvar_t cv_resetmusicbyheader = {"resetmusicbyheader", "Yes", CV_SAVE, CV_YesN static CV_PossibleValue_t cons_1upsound_t[] = { {0, "Jingle"}, {1, "Sound"}, - - {0} + {0, NULL} }; consvar_t cv_1upsound = {"1upsound", "Jingle", CV_SAVE, cons_1upsound_t, NULL, 0, NULL, NULL, 0, 0, NULL}; From 4e481340ce70c82c1c66400e3e85d47b2071190c Mon Sep 17 00:00:00 2001 From: Sally Cochenour Date: Thu, 16 Jan 2020 12:37:32 -0500 Subject: [PATCH 43/83] OpenGL shadows --- src/hardware/hw_main.c | 280 ++++++++++++----------------------------- src/r_main.c | 12 -- src/r_main.h | 6 - 3 files changed, 81 insertions(+), 217 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 74be53db5..14121518b 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -41,6 +41,7 @@ #include "../i_system.h" #include "../m_cheat.h" #include "../f_finale.h" +#include "../r_things.h" // R_GetShadowZ #ifdef ESLOPE #include "../p_slopes.h" #endif @@ -4050,39 +4051,6 @@ static gr_vissprite_t *HWR_NewVisSprite(void) return HWR_GetVisSprite(gr_visspritecount++); } -#ifdef GLBADSHADOWS -// Finds a floor through which light does not pass. -static fixed_t HWR_OpaqueFloorAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height) -{ - const sector_t *sec = R_PointInSubsector(x, y)->sector; - fixed_t floorz = sec->floorheight; - - if (sec->ffloors) - { - ffloor_t *rover; - fixed_t delta1, delta2; - const fixed_t thingtop = z + height; - - for (rover = sec->ffloors; rover; rover = rover->next) - { - if (!(rover->flags & FF_EXISTS) - || !(rover->flags & FF_RENDERPLANES) - || rover->flags & FF_TRANSLUCENT - || rover->flags & FF_FOG - || rover->flags & FF_INVERTPLANES) - continue; - - delta1 = z - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2)); - delta2 = thingtop - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2)); - if (*rover->topheight > floorz && abs(delta1) < abs(delta2)) - floorz = *rover->topheight; - } - } - - return floorz; -} -#endif //#ifdef GLBADSHADOWS - // // HWR_DoCulling // Hardware version of R_DoCulling @@ -4123,180 +4091,123 @@ static boolean HWR_DoCulling(line_t *cullheight, line_t *viewcullheight, float v return false; } -#ifdef GLBADSHADOWS -static void HWR_DrawSpriteShadow(gr_vissprite_t *spr, GLPatch_t *gpatch, float this_scale) +static void HWR_DrawDropShadow(mobj_t *thing, gr_vissprite_t *spr, fixed_t scale) { - FOutVector swallVerts[4]; + GLPatch_t *gpatch; + FOutVector shadowVerts[4]; FSurfaceInfo sSurf; - fixed_t floorheight, mobjfloor; - float offset = 0; + float fscale; float fx; float fy; float offset; + UINT8 lightlevel = 255; + extracolormap_t *colormap = NULL; + UINT8 i; - mobjfloor = HWR_OpaqueFloorAtPos( - spr->mobj->x, spr->mobj->y, - spr->mobj->z, spr->mobj->height); - if (cv_shadowoffs.value) - { - angle_t shadowdir; + INT32 light; + fixed_t scalemul; + UINT16 alpha; + fixed_t floordiff; + fixed_t floorz; + fixed_t slopez; + pslope_t *floorslope; - // Set direction - if (splitscreen && stplyr == &players[secondarydisplayplayer]) - shadowdir = localangle2 + FixedAngle(cv_cam2_rotate.value); - else - shadowdir = localangle + FixedAngle(cv_cam_rotate.value); + floorz = R_GetShadowZ(thing, &floorslope); - // Find floorheight - floorheight = HWR_OpaqueFloorAtPos( - spr->mobj->x + P_ReturnThrustX(spr->mobj, shadowdir, spr->mobj->z - mobjfloor), - spr->mobj->y + P_ReturnThrustY(spr->mobj, shadowdir, spr->mobj->z - mobjfloor), - spr->mobj->z, spr->mobj->height); + //if (abs(floorz - gr_viewz) / tz > 4) return; // Prevent stretchy shadows and possible crashes - // The shadow is falling ABOVE it's mobj? - // Don't draw it, then! - if (spr->mobj->z < floorheight) - return; - else - { - fixed_t floorz; - floorz = HWR_OpaqueFloorAtPos( - spr->mobj->x + P_ReturnThrustX(spr->mobj, shadowdir, spr->mobj->z - floorheight), - spr->mobj->y + P_ReturnThrustY(spr->mobj, shadowdir, spr->mobj->z - floorheight), - spr->mobj->z, spr->mobj->height); - // The shadow would be falling on a wall? Don't draw it, then. - // Would draw midair otherwise. - if (floorz < floorheight) - return; - } + floordiff = abs(thing->z - floorz); - floorheight = FixedInt(spr->mobj->z - floorheight); + alpha = floordiff / (4*FRACUNIT) + 75; + if (alpha >= 255) return; + alpha = 255 - alpha; - offset = floorheight; - } - else - floorheight = FixedInt(spr->mobj->z - mobjfloor); + gpatch = (GLPatch_t *)W_CachePatchName("DSHADOW", PU_CACHE); + if (!(gpatch && gpatch->mipmap->grInfo.format)) return; + HWR_GetPatch(gpatch); + + scalemul = FixedMul(FRACUNIT - floordiff/640, scale); + scalemul = FixedMul(scalemul, (thing->radius*2) / gpatch->height); + + fscale = FIXED_TO_FLOAT(scalemul); + fx = FIXED_TO_FLOAT(thing->x); + fy = FIXED_TO_FLOAT(thing->y); - // create the sprite billboard - // // 3--2 // | /| // |/ | // 0--1 - // x1/x2 were already scaled in HWR_ProjectSprite - // First match the normal sprite - swallVerts[0].x = swallVerts[3].x = spr->x1; - swallVerts[2].x = swallVerts[1].x = spr->x2; - swallVerts[0].z = swallVerts[3].z = spr->z1; - swallVerts[2].z = swallVerts[1].z = spr->z2; + if (thing && fabsf(fscale - 1.0f) > 1.0E-36f) + offset = (gpatch->height/2) * fscale; + else + offset = (float)(gpatch->height/2); - if (spr->mobj && fabsf(this_scale - 1.0f) > 1.0E-36f) + shadowVerts[0].x = shadowVerts[3].x = fx - offset; + shadowVerts[2].x = shadowVerts[1].x = fx + offset; + shadowVerts[0].z = shadowVerts[1].z = fy - offset; + shadowVerts[3].z = shadowVerts[2].z = fy + offset; + + if (floorslope) { - // Always a pixel above the floor, perfectly flat. - swallVerts[0].y = swallVerts[1].y = swallVerts[2].y = swallVerts[3].y = spr->ty - gpatch->topoffset * this_scale - (floorheight+3); - - // Now transform the TOP vertices along the floor in the direction of the camera - swallVerts[3].x = spr->x1 + ((gpatch->height * this_scale) + offset) * gr_viewcos; - swallVerts[2].x = spr->x2 + ((gpatch->height * this_scale) + offset) * gr_viewcos; - swallVerts[3].z = spr->z1 + ((gpatch->height * this_scale) + offset) * gr_viewsin; - swallVerts[2].z = spr->z2 + ((gpatch->height * this_scale) + offset) * gr_viewsin; + for (i = 0; i < 4; i++) + { + slopez = P_GetZAt(floorslope, FLOAT_TO_FIXED(shadowVerts[i].x), FLOAT_TO_FIXED(shadowVerts[i].z)); + shadowVerts[i].y = FIXED_TO_FLOAT(slopez) + 0.05f; + } } else { - // Always a pixel above the floor, perfectly flat. - swallVerts[0].y = swallVerts[1].y = swallVerts[2].y = swallVerts[3].y = spr->ty - gpatch->topoffset - (floorheight+3); - - // Now transform the TOP vertices along the floor in the direction of the camera - swallVerts[3].x = spr->x1 + (gpatch->height + offset) * gr_viewcos; - swallVerts[2].x = spr->x2 + (gpatch->height + offset) * gr_viewcos; - swallVerts[3].z = spr->z1 + (gpatch->height + offset) * gr_viewsin; - swallVerts[2].z = spr->z2 + (gpatch->height + offset) * gr_viewsin; - } - - // We also need to move the bottom ones away when shadowoffs is on - if (cv_shadowoffs.value) - { - swallVerts[0].x = spr->x1 + offset * gr_viewcos; - swallVerts[1].x = spr->x2 + offset * gr_viewcos; - swallVerts[0].z = spr->z1 + offset * gr_viewsin; - swallVerts[1].z = spr->z2 + offset * gr_viewsin; + for (i = 0; i < 4; i++) + shadowVerts[i].y = FIXED_TO_FLOAT(floorz) + 0.05f; } if (spr->flip) { - swallVerts[0].sow = swallVerts[3].sow = gpatch->max_s; - swallVerts[2].sow = swallVerts[1].sow = 0; + shadowVerts[0].sow = shadowVerts[3].sow = gpatch->max_s; + shadowVerts[2].sow = shadowVerts[1].sow = 0; } else { - swallVerts[0].sow = swallVerts[3].sow = 0; - swallVerts[2].sow = swallVerts[1].sow = gpatch->max_s; + shadowVerts[0].sow = shadowVerts[3].sow = 0; + shadowVerts[2].sow = shadowVerts[1].sow = gpatch->max_s; } // flip the texture coords (look familiar?) if (spr->vflip) { - swallVerts[3].tow = swallVerts[2].tow = gpatch->max_t; - swallVerts[0].tow = swallVerts[1].tow = 0; + shadowVerts[3].tow = shadowVerts[2].tow = gpatch->max_t; + shadowVerts[0].tow = shadowVerts[1].tow = 0; } else { - swallVerts[3].tow = swallVerts[2].tow = 0; - swallVerts[0].tow = swallVerts[1].tow = gpatch->max_t; + shadowVerts[3].tow = shadowVerts[2].tow = 0; + shadowVerts[0].tow = shadowVerts[1].tow = gpatch->max_t; } - sSurf.FlatColor.s.red = 0x00; - sSurf.FlatColor.s.blue = 0x00; - sSurf.FlatColor.s.green = 0x00; - - /*if (spr->mobj->frame & FF_TRANSMASK || spr->mobj->flags2 & MF2_SHADOW) + if (thing->subsector->sector->numlights) { - sector_t *sector = spr->mobj->subsector->sector; - UINT8 lightlevel = 255; - extracolormap_t *colormap = sector->extra_colormap; + light = R_GetPlaneLight(thing->subsector->sector, floorz, false); // Always use the light at the top instead of whatever I was doing before - if (sector->numlights) - { - INT32 light = R_GetPlaneLight(sector, spr->mobj->floorz, false); + lightlevel = *thing->subsector->sector->lightlist[light].lightlevel; - if (!(spr->mobj->frame & FF_FULLBRIGHT)) - lightlevel = *sector->lightlist[light].lightlevel; - - if (*sector->lightlist[light].extra_colormap) - colormap = *sector->lightlist[light].extra_colormap; - } - else - { - lightlevel = sector->lightlevel; - - if (sector->extra_colormap) - colormap = sector->extra_colormap; - } - - if (colormap) - sSurf.FlatColor.rgba = HWR_Lighting(lightlevel/2, colormap->rgba, colormap->fadergba, false, true); - else - sSurf.FlatColor.rgba = HWR_Lighting(lightlevel/2, NORMALFOG, FADEFOG, false, true); - }*/ - - // shadow is always half as translucent as the sprite itself - if (!cv_translucency.value) // use default translucency (main sprite won't have any translucency) - sSurf.FlatColor.s.alpha = 0x80; // default - else if (spr->mobj->flags2 & MF2_SHADOW) - sSurf.FlatColor.s.alpha = 0x20; - else if (spr->mobj->frame & FF_TRANSMASK) - { - HWR_TranstableToAlpha((spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &sSurf); - sSurf.FlatColor.s.alpha /= 2; //cut alpha in half! + if (*thing->subsector->sector->lightlist[light].extra_colormap) + colormap = *thing->subsector->sector->lightlist[light].extra_colormap; } else - sSurf.FlatColor.s.alpha = 0x80; // default - - if (sSurf.FlatColor.s.alpha > floorheight/4) { - sSurf.FlatColor.s.alpha = (UINT8)(sSurf.FlatColor.s.alpha - floorheight/4); - HWD.pfnDrawPolygon(&sSurf, swallVerts, 4, PF_Translucent|PF_Modulated|PF_Clip); + lightlevel = thing->subsector->sector->lightlevel; + + if (thing->subsector->sector->extra_colormap) + colormap = thing->subsector->sector->extra_colormap; } + + if (colormap) + sSurf.FlatColor.rgba = HWR_Lighting(lightlevel, colormap->rgba, colormap->fadergba, false, false); + else + sSurf.FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, false, false); + + sSurf.FlatColor.s.alpha = alpha; + + HWD.pfnDrawPolygon(&sSurf, shadowVerts, 4, PF_Translucent|PF_Modulated|PF_Clip); } -#endif //#ifdef GLBADSHADOWS // This is expecting a pointer to an array containing 4 wallVerts for a sprite static void HWR_RotateSpritePolyToAim(gr_vissprite_t *spr, FOutVector *wallVerts) @@ -4372,24 +4283,6 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) //Hurdler: 25/04/2000: now support colormap in hardware mode HWR_GetMappedPatch(gpatch, spr->colormap); -#ifdef GLBADSHADOWS - // Draw shadow BEFORE sprite - if (cv_shadow.value // Shadows enabled - && (spr->mobj->flags & (MF_SCENERY|MF_SPAWNCEILING|MF_NOGRAVITY)) != (MF_SCENERY|MF_SPAWNCEILING|MF_NOGRAVITY) // Ceiling scenery have no shadow. - && !(spr->mobj->flags2 & MF2_DEBRIS) // Debris have no corona or shadow. -#ifdef ALAM_LIGHTING - && !(t_lspr[spr->mobj->sprite]->type // Things with dynamic lights have no shadow. - && (!spr->mobj->player || spr->mobj->player->powers[pw_super])) // Except for non-super players. -#endif - && (spr->mobj->z >= spr->mobj->floorz)) // Without this, your shadow shows on the floor, even after you die and fall through the ground. - { - //////////////////// - // SHADOW SPRITE! // - //////////////////// - HWR_DrawSpriteShadow(spr, gpatch, this_scale); - } -#endif //#ifdef GLBADSHADOWS - baseWallVerts[0].x = baseWallVerts[3].x = spr->x1; baseWallVerts[2].x = baseWallVerts[1].x = spr->x2; baseWallVerts[0].z = baseWallVerts[3].z = spr->z1; @@ -4776,24 +4669,6 @@ static void HWR_DrawSprite(gr_vissprite_t *spr) //Hurdler: 25/04/2000: now support colormap in hardware mode HWR_GetMappedPatch(gpatch, spr->colormap); -#ifdef GLBADSHADOWS - // Draw shadow BEFORE sprite - if (cv_shadow.value // Shadows enabled - && (spr->mobj->flags & (MF_SCENERY|MF_SPAWNCEILING|MF_NOGRAVITY)) != (MF_SCENERY|MF_SPAWNCEILING|MF_NOGRAVITY) // Ceiling scenery have no shadow. - && !(spr->mobj->flags2 & MF2_DEBRIS) // Debris have no corona or shadow. -#ifdef ALAM_LIGHTING - && !(t_lspr[spr->mobj->sprite]->type // Things with dynamic lights have no shadow. - && (!spr->mobj->player || spr->mobj->player->powers[pw_super])) // Except for non-super players. -#endif - && (spr->mobj->z >= spr->mobj->floorz)) // Without this, your shadow shows on the floor, even after you die and fall through the ground. - { - //////////////////// - // SHADOW SPRITE! // - //////////////////// - HWR_DrawSpriteShadow(spr, gpatch, this_scale); - } -#endif //#ifdef GLBADSHADOWS - // if it has a dispoffset, push it a little towards the camera if (spr->dispoffset) { float co = -gr_viewcos*(0.05f*spr->dispoffset); @@ -5407,6 +5282,12 @@ static void HWR_DrawSprites(void) HWR_DrawPrecipitationSprite(spr); else #endif + { + if (spr->mobj && spr->mobj->shadowscale && !(spr->mobj->frame & FF_PAPERSPRITE)) + { + HWR_DrawDropShadow(spr->mobj, spr, spr->mobj->shadowscale); + } + if (spr->mobj && spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) { if (!cv_grmodels.value || md2_playermodels[(skin_t*)spr->mobj->skin-skins].notfound || md2_playermodels[(skin_t*)spr->mobj->skin-skins].scale < 0.0f) @@ -5427,6 +5308,7 @@ static void HWR_DrawSprites(void) HWR_DrawSprite(spr); } } + } } } } diff --git a/src/r_main.c b/src/r_main.c index 3c6aaf6a6..49d7594e9 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -128,12 +128,6 @@ consvar_t cv_chasecam2 = {"chasecam2", "On", CV_CALL, CV_OnOff, ChaseCam2_OnChan consvar_t cv_flipcam = {"flipcam", "No", CV_SAVE|CV_CALL|CV_NOINIT, CV_YesNo, FlipCam_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_flipcam2 = {"flipcam2", "No", CV_SAVE|CV_CALL|CV_NOINIT, CV_YesNo, FlipCam2_OnChange, 0, NULL, NULL, 0, 0, NULL}; -#if defined(FLOORSPLATS) || defined(GLBADSHADOWS) -consvar_t cv_shadow = {"shadow", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -#endif //#if defined(FLOORSPLATS) || defined(GLBADSHADOWS) -#ifdef GLBADSHADOWS -consvar_t cv_shadowoffs = {"offsetshadows", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -#endif //#ifdef GLBADSHADOWS consvar_t cv_skybox = {"skybox", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_allowmlook = {"allowmlook", "Yes", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_showhud = {"showhud", "Yes", CV_CALL, CV_YesNo, R_SetViewSize, 0, NULL, NULL, 0, 0, NULL}; @@ -1223,12 +1217,6 @@ void R_RegisterEngineStuff(void) CV_RegisterVar(&cv_chasecam); CV_RegisterVar(&cv_chasecam2); -#if defined(FLOORSPLATS) || defined(GLBADSHADOWS) - CV_RegisterVar(&cv_shadow); -#endif //#if defined(FLOORSPLATS) || defined(GLBADSHADOWS) -#ifdef GLBADSHADOWS - CV_RegisterVar(&cv_shadowoffs); -#endif //#ifdef GLBADSHADOWS CV_RegisterVar(&cv_skybox); CV_RegisterVar(&cv_cam_dist); diff --git a/src/r_main.h b/src/r_main.h index 998bb50ef..4654f4d72 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -76,12 +76,6 @@ extern consvar_t cv_showhud, cv_translucenthud; extern consvar_t cv_homremoval; extern consvar_t cv_chasecam, cv_chasecam2; extern consvar_t cv_flipcam, cv_flipcam2; -#if defined(FLOORSPLATS) || defined(GLBADSHADOWS) -extern consvar_t cv_shadow; -#endif -#ifdef GLBADSHADOWS -extern conscar_t cv_shadowoffs; -#endif //#ifdef GLBADSHADOWS extern consvar_t cv_translucency; extern consvar_t cv_drawdist, cv_drawdist_nights, cv_drawdist_precip; extern consvar_t cv_fov; From 36511afda9a9e6485cfe752cba3455753bb6c637 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Thu, 16 Jan 2020 14:28:03 -0500 Subject: [PATCH 44/83] Add missing name to the credits --- src/f_finale.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/f_finale.c b/src/f_finale.c index bbee48bdc..8f6eb51fc 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1233,6 +1233,7 @@ static const char *credits[] = { "Thomas \"Shadow Hog\" Igoe", "Alexander \"DrTapeworm\" Moench-Ford", "\"Kaito Sinclaire\"", + "\"QueenDelta\"", "Wessel \"sphere\" Smit", "\"Spazzo\"", "\"SSNTails\"", @@ -1240,7 +1241,7 @@ static const char *credits[] = { "\"Torgo\"", "Jarrett \"JEV3\" Voight", "Johnny \"Sonikku\" Wallbank", - "Marco \"mazmazz\" Zafra", + "Marco \"mazmazz\" Zafra" "", "\1Boss Design", "Ben \"Mystic\" Geyer", From 4c6edd87dfb195a0f141bc101888b354677c3374 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Thu, 16 Jan 2020 14:31:36 -0500 Subject: [PATCH 45/83] Restore this that got removed shomehow --- src/f_finale.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/f_finale.c b/src/f_finale.c index 8f6eb51fc..87e41df78 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1241,7 +1241,7 @@ static const char *credits[] = { "\"Torgo\"", "Jarrett \"JEV3\" Voight", "Johnny \"Sonikku\" Wallbank", - "Marco \"mazmazz\" Zafra" + "Marco \"mazmazz\" Zafra", "", "\1Boss Design", "Ben \"Mystic\" Geyer", From 32c65ae8444a30fa846daba2f7de6e0a608565b6 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Thu, 16 Jan 2020 18:59:39 -0500 Subject: [PATCH 46/83] Move to the end of the list --- src/f_finale.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/f_finale.c b/src/f_finale.c index 87e41df78..1d97038b8 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1233,7 +1233,6 @@ static const char *credits[] = { "Thomas \"Shadow Hog\" Igoe", "Alexander \"DrTapeworm\" Moench-Ford", "\"Kaito Sinclaire\"", - "\"QueenDelta\"", "Wessel \"sphere\" Smit", "\"Spazzo\"", "\"SSNTails\"", @@ -1242,6 +1241,7 @@ static const char *credits[] = { "Jarrett \"JEV3\" Voight", "Johnny \"Sonikku\" Wallbank", "Marco \"mazmazz\" Zafra", + "\"QueenDelta\"", "", "\1Boss Design", "Ben \"Mystic\" Geyer", From 54ec64062c4f8d84c9b8569bfef3edf5ac0c9948 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Thu, 16 Jan 2020 19:20:05 -0500 Subject: [PATCH 47/83] Revert "Move to the end of the list" This reverts commit 32c65ae8444a30fa846daba2f7de6e0a608565b6. --- src/f_finale.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/f_finale.c b/src/f_finale.c index 1d97038b8..87e41df78 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1233,6 +1233,7 @@ static const char *credits[] = { "Thomas \"Shadow Hog\" Igoe", "Alexander \"DrTapeworm\" Moench-Ford", "\"Kaito Sinclaire\"", + "\"QueenDelta\"", "Wessel \"sphere\" Smit", "\"Spazzo\"", "\"SSNTails\"", @@ -1241,7 +1242,6 @@ static const char *credits[] = { "Jarrett \"JEV3\" Voight", "Johnny \"Sonikku\" Wallbank", "Marco \"mazmazz\" Zafra", - "\"QueenDelta\"", "", "\1Boss Design", "Ben \"Mystic\" Geyer", From f9dd5056c6283344a5e2bac724e4a6ab5cba7676 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 16 Jan 2020 16:36:10 -0800 Subject: [PATCH 48/83] musicdef-2.2.1 for converting 2.2.0 MUSICDEF to new format --- tools/musicdef-2.2.1/Makefile | 1 + tools/musicdef-2.2.1/musicdef-2.2.1.c | 76 +++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 tools/musicdef-2.2.1/Makefile create mode 100644 tools/musicdef-2.2.1/musicdef-2.2.1.c diff --git a/tools/musicdef-2.2.1/Makefile b/tools/musicdef-2.2.1/Makefile new file mode 100644 index 000000000..403d27b04 --- /dev/null +++ b/tools/musicdef-2.2.1/Makefile @@ -0,0 +1 @@ +musicdef-2.2.1: diff --git a/tools/musicdef-2.2.1/musicdef-2.2.1.c b/tools/musicdef-2.2.1/musicdef-2.2.1.c new file mode 100644 index 000000000..d73f16efc --- /dev/null +++ b/tools/musicdef-2.2.1/musicdef-2.2.1.c @@ -0,0 +1,76 @@ +/* +Copyright 2019 James R. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include + +#ifdef _WIN32 +#define strcasecmp _stricmp +#else +#include +#endif + +int +main (int ac, char **av) +{ + char line[256]; + char buf[256]; + char *var; + char *val; + char *p; + int n; + (void)ac; + (void)av; + fputs( + "Copyright 2019 James R.\n" + "All rights reserved.\n" + "\n" + "Usage: musicdef-2.2.1 < old-MUSICDEF > new-MUSICDEF\n" + "\n" + ,stderr); + while (fgets(line, sizeof line, stdin)) + { + memcpy(buf, line, sizeof buf); + if (( var = strtok(buf, " =") )) + { + if (!( + strcasecmp(var, "TITLE") && + strcasecmp(var, "AUTHORS") + )){ + if (( val = strtok(0, "") )) + { + for (p = val; ( p = strchr(p, '_') ); ) + { + n = strspn(p, "_"); + memset(p, ' ', n); + p += n; + } + printf("%s %s", var, val); + continue; + } + } + } + fputs(line, stdout); + } + return 0; +} From 90c9a467f31215946f55fcffdd855a04e88a9139 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 16 Jan 2020 16:45:52 -0800 Subject: [PATCH 49/83] Bah it's a new year! --- tools/musicdef-2.2.1/musicdef-2.2.1.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/musicdef-2.2.1/musicdef-2.2.1.c b/tools/musicdef-2.2.1/musicdef-2.2.1.c index d73f16efc..585bc6bb0 100644 --- a/tools/musicdef-2.2.1/musicdef-2.2.1.c +++ b/tools/musicdef-2.2.1/musicdef-2.2.1.c @@ -1,5 +1,5 @@ /* -Copyright 2019 James R. +Copyright 2020 James R. All rights reserved. Redistribution and use in source and binary forms, with or without @@ -42,7 +42,7 @@ main (int ac, char **av) (void)ac; (void)av; fputs( - "Copyright 2019 James R.\n" + "Copyright 2020 James R.\n" "All rights reserved.\n" "\n" "Usage: musicdef-2.2.1 < old-MUSICDEF > new-MUSICDEF\n" From 51f1f4f2b155999f696be93fc8422360ad7aa8c4 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 16 Jan 2020 16:46:31 -0800 Subject: [PATCH 50/83] Also check ALTTITLE --- tools/musicdef-2.2.1/musicdef-2.2.1.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/musicdef-2.2.1/musicdef-2.2.1.c b/tools/musicdef-2.2.1/musicdef-2.2.1.c index 585bc6bb0..65d434c8a 100644 --- a/tools/musicdef-2.2.1/musicdef-2.2.1.c +++ b/tools/musicdef-2.2.1/musicdef-2.2.1.c @@ -55,6 +55,7 @@ main (int ac, char **av) { if (!( strcasecmp(var, "TITLE") && + strcasecmp(var, "ALTTITLE") && strcasecmp(var, "AUTHORS") )){ if (( val = strtok(0, "") )) From e4f0fa46f58c4a2236d48f9774ba5eeb65d021e4 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 16 Jan 2020 18:07:28 -0800 Subject: [PATCH 51/83] Dumbass NONET stuff... --- src/mserv.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/mserv.c b/src/mserv.c index a842e92e9..4ddab05b9 100644 --- a/src/mserv.c +++ b/src/mserv.c @@ -323,13 +323,9 @@ static INT32 GetServersList(void) // // MS_Connect() // +#ifndef NONET static INT32 MS_SubConnect(const char *ip_addr, const char *str_port, INT32 async, struct sockaddr *bindaddr, socklen_t bindaddrlen) { -#ifdef NONET - (void)ip_addr; - (void)str_port; - (void)async; -#else struct my_addrinfo *ai, *runp, hints; int gaie; @@ -402,12 +398,18 @@ static INT32 MS_SubConnect(const char *ip_addr, const char *str_port, INT32 asyn runp = runp->ai_next; } I_freeaddrinfo(ai); -#endif return MS_CONNECT_ERROR; } +#endif/*NONET xd*/ static INT32 MS_Connect(const char *ip_addr, const char *str_port, INT32 async) { +#ifdef NONET + (void)ip_addr; + (void)str_port; + (void)async; + return MS_CONNECT_ERROR; +#else const char *lhost; struct my_addrinfo hints; struct my_addrinfo *ai, *aip; @@ -443,6 +445,7 @@ static INT32 MS_Connect(const char *ip_addr, const char *str_port, INT32 async) } else return MS_SubConnect(ip_addr, str_port, async, 0, 0); +#endif/*NONET xd*/ } #define NUM_LIST_SERVER MAXSERVERLIST From 7adc108a2af8bbd621d3293ba38161b8b5a96f19 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Fri, 17 Jan 2020 00:34:31 -0300 Subject: [PATCH 52/83] typoe --- src/dehacked.c | 2 +- src/p_maputl.c | 8 ++++---- src/p_spec.c | 2 +- src/r_defs.h | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index e6e2a29b2..082adda24 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -9670,7 +9670,7 @@ struct { {"FF_QUICKSAND",FF_QUICKSAND}, ///< Quicksand! {"FF_PLATFORM",FF_PLATFORM}, ///< You can jump up through this to the top. {"FF_REVERSEPLATFORM",FF_REVERSEPLATFORM}, ///< A fall-through floor in normal gravity, a platform in reverse gravity. - {"FF_INTANGABLEFLATS",FF_INTANGABLEFLATS}, ///< Both flats are intangable, but the sides are still solid. + {"FF_INTANGIBLEFLATS",FF_INTANGIBLEFLATS}, ///< Both flats are intangible, but the sides are still solid. {"FF_SHATTER",FF_SHATTER}, ///< Used with ::FF_BUSTUP. Bustable on mere touch. {"FF_SPINBUST",FF_SPINBUST}, ///< Used with ::FF_BUSTUP. Also bustable if you're in your spinning frames. {"FF_STRONGBUST",FF_STRONGBUST }, ///< Used with ::FF_BUSTUP. Only bustable by "strong" characters (Knuckles) and abilities (bouncing, twinspin, melee). diff --git a/src/p_maputl.c b/src/p_maputl.c index afa020504..b4043d643 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -643,7 +643,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) delta1 = abs(mobj->z - (bottomheight + ((topheight - bottomheight)/2))); delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2))); - if (delta1 >= delta2 && (rover->flags & FF_INTANGABLEFLATS) != FF_PLATFORM) // thing is below FOF + if (delta1 >= delta2 && (rover->flags & FF_INTANGIBLEFLATS) != FF_PLATFORM) // thing is below FOF { if (bottomheight < opentop) { opentop = bottomheight; @@ -656,7 +656,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) highceiling = bottomheight; } - if (delta1 < delta2 && (rover->flags & FF_INTANGABLEFLATS) != FF_REVERSEPLATFORM) // thing is above FOF + if (delta1 < delta2 && (rover->flags & FF_INTANGIBLEFLATS) != FF_REVERSEPLATFORM) // thing is above FOF { if (topheight > openbottom) { openbottom = topheight; @@ -689,7 +689,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) delta1 = abs(mobj->z - (bottomheight + ((topheight - bottomheight)/2))); delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2))); - if (delta1 >= delta2 && (rover->flags & FF_INTANGABLEFLATS) != FF_PLATFORM) // thing is below FOF + if (delta1 >= delta2 && (rover->flags & FF_INTANGIBLEFLATS) != FF_PLATFORM) // thing is below FOF { if (bottomheight < opentop) { opentop = bottomheight; @@ -702,7 +702,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) highceiling = bottomheight; } - if (delta1 < delta2 && (rover->flags & FF_INTANGABLEFLATS) != FF_REVERSEPLATFORM) // thing is above FOF + if (delta1 < delta2 && (rover->flags & FF_INTANGIBLEFLATS) != FF_REVERSEPLATFORM) // thing is above FOF { if (topheight > openbottom) { openbottom = topheight; diff --git a/src/p_spec.c b/src/p_spec.c index 9defc33a0..e5b026a3d 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6931,7 +6931,7 @@ void P_SpawnSpecials(boolean fromnetsave) break; case 146: // Intangible floor/ceiling with solid sides (fences/hoops maybe?) - P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERSIDES|FF_ALLSIDES|FF_INTANGABLEFLATS, secthinkers); + P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERSIDES|FF_ALLSIDES|FF_INTANGIBLEFLATS, secthinkers); break; case 150: // Air bobbing platform diff --git a/src/r_defs.h b/src/r_defs.h index eade61db5..88d418fc9 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -144,7 +144,7 @@ typedef enum FF_QUICKSAND = 0x1000000, ///< Quicksand! FF_PLATFORM = 0x2000000, ///< You can jump up through this to the top. FF_REVERSEPLATFORM = 0x4000000, ///< A fall-through floor in normal gravity, a platform in reverse gravity. - FF_INTANGABLEFLATS = 0x6000000, ///< Both flats are intangable, but the sides are still solid. + FF_INTANGIBLEFLATS = 0x6000000, ///< Both flats are intangible, but the sides are still solid. FF_SHATTER = 0x8000000, ///< Used with ::FF_BUSTUP. Bustable on mere touch. FF_SPINBUST = 0x10000000, ///< Used with ::FF_BUSTUP. Also bustable if you're in your spinning frames. FF_STRONGBUST = 0x20000000, ///< Used with ::FF_BUSTUP. Only bustable by "strong" characters (Knuckles) and abilities (bouncing, twinspin, melee). From 8bfdb52231b0cdff953410c0c150c8a28ea9b465 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Fri, 17 Jan 2020 00:49:43 -0300 Subject: [PATCH 53/83] add R_IsPointInSubsector to lua baselib --- src/lua_baselib.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 2a82ec512..7a16f3c69 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -2193,6 +2193,20 @@ static int lib_rPointInSubsector(lua_State *L) return 1; } +static int lib_rIsPointInSubsector(lua_State *L) +{ + fixed_t x = luaL_checkfixed(L, 1); + fixed_t y = luaL_checkfixed(L, 2); + subsector_t *sub = R_IsPointInSubsector(x, y); + //HUDSAFE + INLEVEL + if (sub) + LUA_PushUserdata(L, sub, META_SUBSECTOR); + else + lua_pushnil(L); + return 1; +} + // R_THINGS //////////// @@ -3127,6 +3141,7 @@ static luaL_Reg lib[] = { {"R_PointToDist",lib_rPointToDist}, {"R_PointToDist2",lib_rPointToDist2}, {"R_PointInSubsector",lib_rPointInSubsector}, + {"R_IsPointInSubsector",lib_rIsPointInSubsector}, // r_things (sprite) {"R_Char2Frame",lib_rChar2Frame}, From f0843cba132c8da35e76d23f59d8ce6ffa542232 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Fri, 17 Jan 2020 00:13:05 -0600 Subject: [PATCH 54/83] Let vissprites have shadows too fuck it, hopefully it works --- src/r_things.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_things.c b/src/r_things.c index 41fb103e3..85452b745 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1904,7 +1904,7 @@ static void R_ProjectSprite(mobj_t *thing) if (thing->subsector->sector->numlights) R_SplitSprite(vis); - if (oldthing->shadowscale && !papersprite) + if (oldthing->shadowscale) R_ProjectDropShadow(oldthing, vis, oldthing->shadowscale, basetx, tz); // Debug From 9a4ad2094743a520c9a09222465abed02f1d0197 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Fri, 17 Jan 2020 00:13:13 -0600 Subject: [PATCH 55/83] DAMNIT --- src/r_things.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_things.c b/src/r_things.c index 85452b745..430542a20 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1335,7 +1335,7 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, // reusing x1 variable x1 += (x2-x1)/2; - shadow->shear.offset = (vis->x1-x1)/2; + shadow->shear.offset = (shadow->x1-x1)/2; if (thing->subsector->sector->numlights) { From 4ca44f2d578bf7d708196388b3883fdb6d0a4808 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Fri, 17 Jan 2020 00:16:15 -0600 Subject: [PATCH 56/83] Bosses need dropshadows too --- src/p_mobj.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index e4de59031..a8599ceb5 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10563,7 +10563,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) type == MT_ROLLOUTROCK || type == MT_EGGMOBILE4_MACE || (type >= MT_SMALLMACE && type <= MT_REDSPRINGBALL) || - (mobj->flags & MF_ENEMY) + (mobj->flags & (MF_ENEMY|MF_BOSS)) ) mobj->shadowscale = FRACUNIT; else if ( From 919661ff8f149878c18c8628484d626b2ffb77ec Mon Sep 17 00:00:00 2001 From: fickleheart Date: Fri, 17 Jan 2020 00:18:00 -0600 Subject: [PATCH 57/83] Give me a break --- src/lua_mobjlib.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index fd32b2134..90733b2c6 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -726,6 +726,7 @@ static int mobj_set(lua_State *L) break; case mobj_shadowscale: mo->shadowscale = luaL_checkfixed(L, 3); + break; default: lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS); I_Assert(lua_istable(L, -1)); From d39d8506caeeb2530d9b02ac94ac48e8f5eff63a Mon Sep 17 00:00:00 2001 From: fickleheart Date: Fri, 17 Jan 2020 00:20:10 -0600 Subject: [PATCH 58/83] Let nerds turn off shadows --- src/r_main.c | 6 +----- src/r_main.h | 2 -- src/r_things.c | 2 +- 3 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/r_main.c b/src/r_main.c index 3c6aaf6a6..4b044c6cc 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -128,9 +128,7 @@ consvar_t cv_chasecam2 = {"chasecam2", "On", CV_CALL, CV_OnOff, ChaseCam2_OnChan consvar_t cv_flipcam = {"flipcam", "No", CV_SAVE|CV_CALL|CV_NOINIT, CV_YesNo, FlipCam_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_flipcam2 = {"flipcam2", "No", CV_SAVE|CV_CALL|CV_NOINIT, CV_YesNo, FlipCam2_OnChange, 0, NULL, NULL, 0, 0, NULL}; -#if defined(FLOORSPLATS) || defined(GLBADSHADOWS) -consvar_t cv_shadow = {"shadow", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -#endif //#if defined(FLOORSPLATS) || defined(GLBADSHADOWS) +consvar_t cv_shadow = {"shadow", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; #ifdef GLBADSHADOWS consvar_t cv_shadowoffs = {"offsetshadows", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; #endif //#ifdef GLBADSHADOWS @@ -1223,9 +1221,7 @@ void R_RegisterEngineStuff(void) CV_RegisterVar(&cv_chasecam); CV_RegisterVar(&cv_chasecam2); -#if defined(FLOORSPLATS) || defined(GLBADSHADOWS) CV_RegisterVar(&cv_shadow); -#endif //#if defined(FLOORSPLATS) || defined(GLBADSHADOWS) #ifdef GLBADSHADOWS CV_RegisterVar(&cv_shadowoffs); #endif //#ifdef GLBADSHADOWS diff --git a/src/r_main.h b/src/r_main.h index 998bb50ef..0764c40d2 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -76,9 +76,7 @@ extern consvar_t cv_showhud, cv_translucenthud; extern consvar_t cv_homremoval; extern consvar_t cv_chasecam, cv_chasecam2; extern consvar_t cv_flipcam, cv_flipcam2; -#if defined(FLOORSPLATS) || defined(GLBADSHADOWS) extern consvar_t cv_shadow; -#endif #ifdef GLBADSHADOWS extern conscar_t cv_shadowoffs; #endif //#ifdef GLBADSHADOWS diff --git a/src/r_things.c b/src/r_things.c index 430542a20..680ae4d4f 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1904,7 +1904,7 @@ static void R_ProjectSprite(mobj_t *thing) if (thing->subsector->sector->numlights) R_SplitSprite(vis); - if (oldthing->shadowscale) + if (oldthing->shadowscale && cv_shadow.value) R_ProjectDropShadow(oldthing, vis, oldthing->shadowscale, basetx, tz); // Debug From f59ed6b2f48fab3350f6bebe9373128042c49b1d Mon Sep 17 00:00:00 2001 From: fickleheart Date: Fri, 17 Jan 2020 00:34:57 -0600 Subject: [PATCH 59/83] DOUBLE DAMNIT --- src/r_things.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_things.c b/src/r_things.c index 680ae4d4f..8fa0f2d0e 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1335,7 +1335,7 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, // reusing x1 variable x1 += (x2-x1)/2; - shadow->shear.offset = (shadow->x1-x1)/2; + shadow->shear.offset = shadow->x1-x1; if (thing->subsector->sector->numlights) { From 999094f2f6f395c2a63db0789c8e1545e47e13df Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Fri, 17 Jan 2020 16:11:17 -0300 Subject: [PATCH 60/83] backwards compat --- src/dehacked.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 082adda24..0dbfe3318 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -9427,7 +9427,7 @@ struct { {"SH_FORCE",SH_FORCE}, {"SH_FORCEHP",SH_FORCEHP}, // to be used as a bitmask only // Mostly for use with Mario mode. - {"SH_FIREFLOWER", SH_FIREFLOWER}, + {"SH_FIREFLOWER",SH_FIREFLOWER}, {"SH_STACK",SH_STACK}, {"SH_NOSTACK",SH_NOSTACK}, @@ -9442,7 +9442,7 @@ struct { {"CR_ROPEHANG",CR_ROPEHANG}, {"CR_MACESPIN",CR_MACESPIN}, {"CR_MINECART",CR_MINECART}, - {"CR_ROLLOUT", CR_ROLLOUT}, + {"CR_ROLLOUT",CR_ROLLOUT}, {"CR_PTERABYTE",CR_PTERABYTE}, // Ring weapons (ringweapons_t) @@ -9609,7 +9609,7 @@ struct { {"NUM_WEAPONS",NUM_WEAPONS}, // Value for infinite lives - {"INFLIVES", INFLIVES}, + {"INFLIVES",INFLIVES}, // Got Flags, for player->gotflag! // Used to be MF_ for some stupid reason, now they're GF_ to stop them looking like mobjflags @@ -9671,9 +9671,10 @@ struct { {"FF_PLATFORM",FF_PLATFORM}, ///< You can jump up through this to the top. {"FF_REVERSEPLATFORM",FF_REVERSEPLATFORM}, ///< A fall-through floor in normal gravity, a platform in reverse gravity. {"FF_INTANGIBLEFLATS",FF_INTANGIBLEFLATS}, ///< Both flats are intangible, but the sides are still solid. + {"FF_INTANGABLEFLATS",FF_INTANGIBLEFLATS}, ///< Both flats are intangable, but the sides are still solid. {"FF_SHATTER",FF_SHATTER}, ///< Used with ::FF_BUSTUP. Bustable on mere touch. {"FF_SPINBUST",FF_SPINBUST}, ///< Used with ::FF_BUSTUP. Also bustable if you're in your spinning frames. - {"FF_STRONGBUST",FF_STRONGBUST }, ///< Used with ::FF_BUSTUP. Only bustable by "strong" characters (Knuckles) and abilities (bouncing, twinspin, melee). + {"FF_STRONGBUST",FF_STRONGBUST}, ///< Used with ::FF_BUSTUP. Only bustable by "strong" characters (Knuckles) and abilities (bouncing, twinspin, melee). {"FF_RIPPLE",FF_RIPPLE}, ///< Ripple the flats {"FF_COLORMAPONLY",FF_COLORMAPONLY}, ///< Only copy the colormap, not the lightlevel {"FF_GOOWATER",FF_GOOWATER}, ///< Used with ::FF_SWIMMABLE. Makes thick bouncey goop. From 43828f265c58afab1b9e3ec0193e33d13f9ac0b4 Mon Sep 17 00:00:00 2001 From: Sally Cochenour Date: Fri, 17 Jan 2020 22:20:04 -0500 Subject: [PATCH 61/83] Use shadow cvar --- src/hardware/hw_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 14121518b..2a5eae9f1 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5283,7 +5283,7 @@ static void HWR_DrawSprites(void) else #endif { - if (spr->mobj && spr->mobj->shadowscale && !(spr->mobj->frame & FF_PAPERSPRITE)) + if (spr->mobj && spr->mobj->shadowscale && cv_shadow.value) { HWR_DrawDropShadow(spr->mobj, spr, spr->mobj->shadowscale); } From 0c7c5742a80b1fd849cf4aaa4f8f12045d4ba44b Mon Sep 17 00:00:00 2001 From: Tatsuru <44866610+Ikkarin@users.noreply.github.com> Date: Sat, 18 Jan 2020 12:06:04 -0300 Subject: [PATCH 62/83] Put cv_exitmove in the menus --- src/m_menu.c | 47 ++++++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index ec4e51c9c..8d62028e4 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1584,32 +1584,33 @@ static menuitem_t OP_ServerOptionsMenu[] = {IT_STRING | IT_CVAR, NULL, "Players required for exit", &cv_playersforexit, 96}, {IT_STRING | IT_CVAR, NULL, "Starposts", &cv_coopstarposts, 101}, {IT_STRING | IT_CVAR, NULL, "Life sharing", &cv_cooplives, 106}, + {IT_STRING | IT_CVAR, NULL, "Post goal free roaming", &cv_exitmove, 111}, - {IT_HEADER, NULL, "Race, Competition", NULL, 115}, - {IT_STRING | IT_CVAR, NULL, "Level completion countdown", &cv_countdowntime, 121}, - {IT_STRING | IT_CVAR, NULL, "Item Monitors", &cv_competitionboxes, 126}, + {IT_HEADER, NULL, "Race, Competition", NULL, 120}, + {IT_STRING | IT_CVAR, NULL, "Level completion countdown", &cv_countdowntime, 126}, + {IT_STRING | IT_CVAR, NULL, "Item Monitors", &cv_competitionboxes, 131}, - {IT_HEADER, NULL, "Ringslinger (Match, CTF, Tag, H&S)", NULL, 135}, - {IT_STRING | IT_CVAR, NULL, "Time Limit", &cv_timelimit, 141}, - {IT_STRING | IT_CVAR, NULL, "Score Limit", &cv_pointlimit, 146}, - {IT_STRING | IT_CVAR, NULL, "Overtime on Tie", &cv_overtime, 151}, - {IT_STRING | IT_CVAR, NULL, "Player respawn delay", &cv_respawntime, 156}, + {IT_HEADER, NULL, "Ringslinger (Match, CTF, Tag, H&S)", NULL, 140}, + {IT_STRING | IT_CVAR, NULL, "Time Limit", &cv_timelimit, 146}, + {IT_STRING | IT_CVAR, NULL, "Score Limit", &cv_pointlimit, 151}, + {IT_STRING | IT_CVAR, NULL, "Overtime on Tie", &cv_overtime, 156}, + {IT_STRING | IT_CVAR, NULL, "Player respawn delay", &cv_respawntime, 161}, - {IT_STRING | IT_CVAR, NULL, "Item Monitors", &cv_matchboxes, 166}, - {IT_STRING | IT_CVAR, NULL, "Weapon Rings", &cv_specialrings, 171}, - {IT_STRING | IT_CVAR, NULL, "Power Stones", &cv_powerstones, 176}, + {IT_STRING | IT_CVAR, NULL, "Item Monitors", &cv_matchboxes, 171}, + {IT_STRING | IT_CVAR, NULL, "Weapon Rings", &cv_specialrings, 176}, + {IT_STRING | IT_CVAR, NULL, "Power Stones", &cv_powerstones, 181}, - {IT_STRING | IT_CVAR, NULL, "Flag respawn delay", &cv_flagtime, 186}, - {IT_STRING | IT_CVAR, NULL, "Hiding time", &cv_hidetime, 191}, + {IT_STRING | IT_CVAR, NULL, "Flag respawn delay", &cv_flagtime, 191}, + {IT_STRING | IT_CVAR, NULL, "Hiding time", &cv_hidetime, 196}, - {IT_HEADER, NULL, "Teams", NULL, 200}, - {IT_STRING | IT_CVAR, NULL, "Autobalance sizes", &cv_autobalance, 206}, - {IT_STRING | IT_CVAR, NULL, "Scramble on Map Change", &cv_scrambleonchange, 211}, + {IT_HEADER, NULL, "Teams", NULL, 205}, + {IT_STRING | IT_CVAR, NULL, "Autobalance sizes", &cv_autobalance, 211}, + {IT_STRING | IT_CVAR, NULL, "Scramble on Map Change", &cv_scrambleonchange, 216}, #ifndef NONET - {IT_HEADER, NULL, "Advanced", NULL, 220}, - {IT_STRING | IT_CVAR | IT_CV_STRING, NULL, "Master server", &cv_masterserver, 226}, - {IT_STRING | IT_CVAR, NULL, "Attempts to resynchronise", &cv_resynchattempts, 240}, + {IT_HEADER, NULL, "Advanced", NULL, 225}, + {IT_STRING | IT_CVAR | IT_CV_STRING, NULL, "Master server", &cv_masterserver, 231}, + {IT_STRING | IT_CVAR, NULL, "Attempts to resynchronise", &cv_resynchattempts, 245}, #endif }; @@ -10632,8 +10633,8 @@ static void M_ServerOptions(INT32 choice) OP_ServerOptionsMenu[ 2].status = IT_GRAYEDOUT; // Max players OP_ServerOptionsMenu[ 3].status = IT_GRAYEDOUT; // Allow add-on downloading OP_ServerOptionsMenu[ 4].status = IT_GRAYEDOUT; // Allow players to join - OP_ServerOptionsMenu[34].status = IT_GRAYEDOUT; // Master server - OP_ServerOptionsMenu[35].status = IT_GRAYEDOUT; // Attempts to resynchronise + OP_ServerOptionsMenu[35].status = IT_GRAYEDOUT; // Master server + OP_ServerOptionsMenu[36].status = IT_GRAYEDOUT; // Attempts to resynchronise } else { @@ -10641,10 +10642,10 @@ static void M_ServerOptions(INT32 choice) OP_ServerOptionsMenu[ 2].status = IT_STRING | IT_CVAR; OP_ServerOptionsMenu[ 3].status = IT_STRING | IT_CVAR; OP_ServerOptionsMenu[ 4].status = IT_STRING | IT_CVAR; - OP_ServerOptionsMenu[34].status = (netgame + OP_ServerOptionsMenu[35].status = (netgame ? IT_GRAYEDOUT : (IT_STRING | IT_CVAR | IT_CV_STRING)); - OP_ServerOptionsMenu[35].status = IT_STRING | IT_CVAR; + OP_ServerOptionsMenu[36].status = IT_STRING | IT_CVAR; } #endif From cdc3386d48a5571205dacdf981a95494c3499b36 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Sat, 18 Jan 2020 12:10:48 -0300 Subject: [PATCH 63/83] Fix missing constant --- src/dehacked.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dehacked.c b/src/dehacked.c index 0dbfe3318..4c36639a2 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8847,7 +8847,7 @@ static const char *const MOBJEFLAG_LIST[] = { #ifdef HAVE_BLUA static const char *const MAPTHINGFLAG_LIST[4] = { - NULL, + "EXTRA", // Extra flag for objects. "OBJECTFLIP", // Reverse gravity flag for objects. "OBJECTSPECIAL", // Special flag used with certain objects. "AMBUSH" // Deaf monsters/do not react to sound. From 8348123a70474869d3dc9bae127e421f76fa2080 Mon Sep 17 00:00:00 2001 From: Tatsuru <44866610+Ikkarin@users.noreply.github.com> Date: Sat, 18 Jan 2020 13:15:24 -0300 Subject: [PATCH 64/83] Goal posts --- 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 8d62028e4..62bea7ae0 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1584,7 +1584,7 @@ static menuitem_t OP_ServerOptionsMenu[] = {IT_STRING | IT_CVAR, NULL, "Players required for exit", &cv_playersforexit, 96}, {IT_STRING | IT_CVAR, NULL, "Starposts", &cv_coopstarposts, 101}, {IT_STRING | IT_CVAR, NULL, "Life sharing", &cv_cooplives, 106}, - {IT_STRING | IT_CVAR, NULL, "Post goal free roaming", &cv_exitmove, 111}, + {IT_STRING | IT_CVAR, NULL, "Post-goal free roaming", &cv_exitmove, 111}, {IT_HEADER, NULL, "Race, Competition", NULL, 120}, {IT_STRING | IT_CVAR, NULL, "Level completion countdown", &cv_countdowntime, 126}, From 1317dba3e42a6f700e38f930d296f6f4128e97bf Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 18 Jan 2020 22:13:34 -0800 Subject: [PATCH 65/83] Refactor MUSICDEF parsing, actually count lines If you use strtok for (CR)LF, it'll skip the empty lines bruh. --- src/s_sound.c | 305 ++++++++++++++++++++++++-------------------------- 1 file changed, 147 insertions(+), 158 deletions(-) diff --git a/src/s_sound.c b/src/s_sound.c index c4c92ebf5..848fd671a 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1472,188 +1472,112 @@ static UINT16 W_CheckForMusicDefInPwad(UINT16 wadid) return INT16_MAX; // not found } -void S_LoadMusicDefs(UINT16 wadnum) +static boolean +ReadMusicDefFields (UINT16 wadnum, int line, char *stoken, musicdef_t **defp) { - UINT16 lumpnum; - char *lump, *buf; - char *musdeftext; - char *stoken; + musicdef_t *def; + char *value; char *textline; - size_t size; - INT32 i; - musicdef_t *def = NULL; - UINT16 line = 1; // for better error msgs + int i; - lumpnum = W_CheckForMusicDefInPwad(wadnum); - if (lumpnum == INT16_MAX) - return; - - lump = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); - size = W_LumpLengthPwad(wadnum, lumpnum); - - // Null-terminated MUSICDEF lump. - musdeftext = malloc(size+1); - if (!musdeftext) - I_Error("S_LoadMusicDefs: No more free memory for the parser\n"); - M_Memcpy(musdeftext, lump, size); - musdeftext[size] = '\0'; - - // for strtok - buf = malloc(size+1); - if (!buf) - I_Error("S_LoadMusicDefs: No more free memory for the parser\n"); - M_Memcpy(buf, musdeftext, size+1); - - stoken = strtok(buf, "\r\n "); - // Find music def - while (stoken) + if (!stricmp(stoken, "lump")) { - /*if ((stoken[0] == '/' && stoken[1] == '/') - || (stoken[0] == '#')) // skip comments + value = strtok(NULL, " "); + if (!value) { - stoken = strtok(NULL, "\r\n"); // skip end of line - if (def) - stoken = strtok(NULL, "\r\n= "); - else - stoken = strtok(NULL, "\r\n "); - line++; - } - else*/ if (!stricmp(stoken, "lump")) - { - value = strtok(NULL, "\r\n "); - - if (!value) - { - CONS_Alert(CONS_WARNING, "MUSICDEF: Lump '%s' is missing name. (file %s, line %d)\n", stoken, wadfiles[wadnum]->filename, line); - stoken = strtok(NULL, "\r\n"); // skip end of line - goto skip_lump; - } - - // No existing musicdefs - /*if (!musicdefstart) - { - musicdefstart = Z_Calloc(sizeof (musicdef_t), PU_STATIC, NULL); - STRBUFCPY(musicdefstart->name, value); - strlwr(musicdefstart->name); - def = musicdefstart; - //CONS_Printf("S_LoadMusicDefs: Initialized musicdef w/ song '%s'\n", def->name); - } - else*/ - { - musicdef_t *prev = NULL; - def = musicdefstart; - - // Search if this is a replacement - //CONS_Printf("S_LoadMusicDefs: Searching for song replacement...\n"); - while (def) - { - if (!stricmp(def->name, value)) - { - //CONS_Printf("S_LoadMusicDefs: Found song replacement '%s'\n", def->name); - break; - } - - prev = def; - def = def->next; - } - - // Nothing found, add to the end. - if (!def) - { - def = Z_Calloc(sizeof (musicdef_t), PU_STATIC, NULL); - STRBUFCPY(def->name, value); - strlwr(def->name); - def->bpm = TICRATE<<(FRACBITS-1); // FixedDiv((60*TICRATE)<next = def; - //CONS_Printf("S_LoadMusicDefs: Added song '%s'\n", def->name); - } - } - -skip_lump: - stoken = strtok(NULL, "\r\n "); - line++; + CONS_Alert(CONS_WARNING, + "MUSICDEF: Field '%s' is missing name. (file %s, line %d)\n", + stoken, wadfiles[wadnum]->filename, line); + return false; } else { - // If this is set true, the line was invalid. - boolean brokenline = false; + musicdef_t *prev = NULL; + def = musicdefstart; - // Delimit only by line break. - value = strtok(NULL, "\r\n"); + // Search if this is a replacement + //CONS_Printf("S_LoadMusicDefs: Searching for song replacement...\n"); + while (def) + { + if (!stricmp(def->name, value)) + { + //CONS_Printf("S_LoadMusicDefs: Found song replacement '%s'\n", def->name); + break; + } + prev = def; + def = def->next; + } + + // Nothing found, add to the end. + if (!def) + { + def = Z_Calloc(sizeof (musicdef_t), PU_STATIC, NULL); + STRBUFCPY(def->name, value); + strlwr(def->name); + def->bpm = TICRATE<<(FRACBITS-1); // FixedDiv((60*TICRATE)<next = def; + //CONS_Printf("S_LoadMusicDefs: Added song '%s'\n", def->name); + } + + (*defp) = def; + } + } + else + { + value = strtok(NULL, ""); + + if (value) + { // Find the equals sign. value = strchr(value, '='); + } - // It's not there?! - if (!value) - brokenline = true; - else - { - // Skip the equals sign. - value++; - - // Now skip funny whitespace. - if (value[0] == '\0') // :NOTHING: - brokenline = true; - else - value += strspn(value, "\t "); - } - - // If the line is valid, copy the text line from the lump data. - if (!brokenline) - { - // strtok returns memory that already belongs to the input string. - value = musdeftext + (value - buf); - - // Find the length of the line. - size = strcspn(value, "\r\n"); - - // Copy the line. - textline = malloc(size+1); - if (!textline) - I_Error("S_LoadMusicDefs: No more free memory for text line\n"); - M_Memcpy(textline, value, size); - textline[size] = '\0'; - } - else - { - CONS_Alert(CONS_WARNING, "MUSICDEF: Field '%s' is missing value. (file %s, line %d)\n", stoken, wadfiles[wadnum]->filename, line); - stoken = strtok(NULL, "\r\n"); // skip end of line - goto skip_field; - } + if (!value) + { + CONS_Alert(CONS_WARNING, + "MUSICDEF: Field '%s' is missing value. (file %s, line %d)\n", + stoken, wadfiles[wadnum]->filename, line); + return false; + } + else + { + def = (*defp); if (!def) { - CONS_Alert(CONS_ERROR, "MUSICDEF: No music definition before field '%s'. (file %s, line %d)\n", stoken, wadfiles[wadnum]->filename, line); - free(textline); - free(buf); - free(musdeftext); - return; + CONS_Alert(CONS_ERROR, + "MUSICDEF: No music definition before field '%s'. (file %s, line %d)\n", + stoken, wadfiles[wadnum]->filename, line); + return false; } - i = atoi(textline); + // Skip the equals sign. + value++; + // Now skip funny whitespace. + value += strspn(value, "\t "); + + textline = value; + i = atoi(value); + + /* based ignored lumps */ if (!stricmp(stoken, "usage")) { #if 0 // Ignore for now STRBUFCPY(def->usage, textline); - //CONS_Printf("S_LoadMusicDefs: Set usage to '%s'\n", def->usage); #endif } else if (!stricmp(stoken, "source")) { #if 0 // Ignore for now STRBUFCPY(def->source, textline); - //CONS_Printf("S_LoadMusicDefs: Set source to '%s'\n", def->usage); #endif } else if (!stricmp(stoken, "title")) { STRBUFCPY(def->title, textline); - //CONS_Printf("S_LoadMusicDefs: Set title to '%s'\n", def->source); } else if (!stricmp(stoken, "alttitle")) { STRBUFCPY(def->alttitle, textline); - //CONS_Printf("S_LoadMusicDefs: Set alttitle to '%s'\n", def->source); } else if (!stricmp(stoken, "authors")) { STRBUFCPY(def->authors, textline); - //CONS_Printf("S_LoadMusicDefs: Set authors to '%s'\n", def->source); } else if (!stricmp(stoken, "soundtestpage")) { def->soundtestpage = (UINT8)i; } else if (!stricmp(stoken, "soundtestcond")) { @@ -1670,21 +1594,86 @@ skip_lump: if (bpmf > 0) def->bpm = FixedDiv((60*TICRATE)<filename, line); + CONS_Alert(CONS_WARNING, + "MUSICDEF: Invalid field '%s'. (file %s, line %d)\n", + stoken, wadfiles[wadnum]->filename, line); } - - // Free the temporary text line from memory. - free(textline); - -skip_field: - stoken = strtok(NULL, "\r\n= "); - line++; } } - free(buf); + return true; +} + +void S_LoadMusicDefs(UINT16 wadnum) +{ + UINT16 lumpnum; + char *lump; + char *musdeftext; + size_t size; + + char *lf; + char *stoken; + + size_t nlf; + size_t ncr; + + musicdef_t *def = NULL; + int line = 1; // for better error msgs + + lumpnum = W_CheckForMusicDefInPwad(wadnum); + if (lumpnum == INT16_MAX) + return; + + lump = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); + size = W_LumpLengthPwad(wadnum, lumpnum); + + // Null-terminated MUSICDEF lump. + musdeftext = malloc(size+1); + if (!musdeftext) + I_Error("S_LoadMusicDefs: No more free memory for the parser\n"); + M_Memcpy(musdeftext, lump, size); + musdeftext[size] = '\0'; + + // Find music def + stoken = musdeftext; + for (;;) + { + lf = strpbrk(stoken, "\r\n"); + if (lf) + { + if (*lf == '\n') + nlf = 1; + else + nlf = 0; + *lf++ = '\0';/* now we can delimit to here */ + } + + stoken = strtok(stoken, " "); + if (stoken) + { + if (! ReadMusicDefFields(wadnum, line, stoken, &def)) + break; + } + + if (lf) + { + do + { + line += nlf; + ncr = strspn(lf, "\r");/* skip CR */ + lf += ncr; + nlf = strspn(lf, "\n"); + lf += nlf; + } + while (nlf || ncr) ; + + stoken = lf;/* now the next nonempty line */ + } + else + break;/* EOF */ + } + free(musdeftext); - return; } // From 9dbc54284ecdc46080f0e00a5f35040ba94922fc Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 18 Jan 2020 23:12:30 -0800 Subject: [PATCH 66/83] Opt into new MUSICDEF format (2.2.0 compatibility) The "VERSION" directive enables features available in a certain version of SRB2. It may be used as "VERSION 2.2.0". --- src/s_sound.c | 92 +++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 79 insertions(+), 13 deletions(-) diff --git a/src/s_sound.c b/src/s_sound.c index 848fd671a..d11fc4321 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1441,6 +1441,12 @@ static tic_t pause_starttic; /// Music Definitions /// ------------------------ +enum +{ + MUSICDEF_220, + MUSICDEF_221, +}; + musicdef_t soundtestsfx = { "_STSFX", // prevents exactly one valid track name from being used on the sound test "Sound Effects", @@ -1472,10 +1478,27 @@ static UINT16 W_CheckForMusicDefInPwad(UINT16 wadid) return INT16_MAX; // not found } +static void +MusicDefStrcpy (char *p, const char *s, size_t n, int version) +{ + strlcpy(p, s, n); + if (version == MUSICDEF_220) + { + while (( p = strchr(p, '_') )) + { + n = strspn(p, "_"); + memset(p, ' ', n); // turn _ into spaces. + p += n; + } + } +} + static boolean -ReadMusicDefFields (UINT16 wadnum, int line, char *stoken, musicdef_t **defp) +ReadMusicDefFields (UINT16 wadnum, int line, boolean fields, char *stoken, + musicdef_t **defp, int *versionp) { musicdef_t *def; + int version; char *value; char *textline; @@ -1525,14 +1548,47 @@ ReadMusicDefFields (UINT16 wadnum, int line, char *stoken, musicdef_t **defp) (*defp) = def; } } + else if (!stricmp(stoken, "version")) + { + if (fields)/* is this not the first field? */ + { + CONS_Alert(CONS_WARNING, + "MUSICDEF: Field '%s' must come first. (file %s, line %d)\n", + stoken, wadfiles[wadnum]->filename, line); + return false; + } + else + { + value = strtok(NULL, " "); + if (!value) + { + CONS_Alert(CONS_WARNING, + "MUSICDEF: Field '%s' is missing version. (file %s, line %d)\n", + stoken, wadfiles[wadnum]->filename, line); + return false; + } + else + { + if (strcasecmp(value, "2.2.0")) + (*versionp) = MUSICDEF_221; + } + } + } else { - value = strtok(NULL, ""); + version = (*versionp); - if (value) + if (version == MUSICDEF_220) + value = strtok(NULL, " ="); + else { - // Find the equals sign. - value = strchr(value, '='); + value = strtok(NULL, ""); + + if (value) + { + // Find the equals sign. + value = strchr(value, '='); + } } if (!value) @@ -1554,11 +1610,14 @@ ReadMusicDefFields (UINT16 wadnum, int line, char *stoken, musicdef_t **defp) return false; } - // Skip the equals sign. - value++; + if (version != MUSICDEF_220) + { + // Skip the equals sign. + value++; - // Now skip funny whitespace. - value += strspn(value, "\t "); + // Now skip funny whitespace. + value += strspn(value, "\t "); + } textline = value; i = atoi(value); @@ -1573,11 +1632,14 @@ ReadMusicDefFields (UINT16 wadnum, int line, char *stoken, musicdef_t **defp) STRBUFCPY(def->source, textline); #endif } else if (!stricmp(stoken, "title")) { - STRBUFCPY(def->title, textline); + MusicDefStrcpy(def->title, textline, + sizeof def->title, version); } else if (!stricmp(stoken, "alttitle")) { - STRBUFCPY(def->alttitle, textline); + MusicDefStrcpy(def->alttitle, textline, + sizeof def->alttitle, version); } else if (!stricmp(stoken, "authors")) { - STRBUFCPY(def->authors, textline); + MusicDefStrcpy(def->authors, textline, + sizeof def->authors, version); } else if (!stricmp(stoken, "soundtestpage")) { def->soundtestpage = (UINT8)i; } else if (!stricmp(stoken, "soundtestcond")) { @@ -1618,7 +1680,9 @@ void S_LoadMusicDefs(UINT16 wadnum) size_t ncr; musicdef_t *def = NULL; + int version = MUSICDEF_220; int line = 1; // for better error msgs + boolean fields = false; lumpnum = W_CheckForMusicDefInPwad(wadnum); if (lumpnum == INT16_MAX) @@ -1651,8 +1715,10 @@ void S_LoadMusicDefs(UINT16 wadnum) stoken = strtok(stoken, " "); if (stoken) { - if (! ReadMusicDefFields(wadnum, line, stoken, &def)) + if (! ReadMusicDefFields(wadnum, line, fields, stoken, + &def, &version)) break; + fields = true; } if (lf) From ad505a6fe7cd3a0b91644e27f5f1c033644eaa35 Mon Sep 17 00:00:00 2001 From: Confusion Date: Sun, 19 Jan 2020 17:55:22 +0300 Subject: [PATCH 67/83] Fix title screen broken when leaving during resynch --- src/d_clisrv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 5fa09e230..704fc0901 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2540,6 +2540,7 @@ void CL_Reset(void) multiplayer = false; servernode = 0; server = true; + resynch_local_inprogress = false; doomcom->numnodes = 1; doomcom->numslots = 1; SV_StopServer(); From 2d8ea7125c24e1e3c6e8b56bdaabfeaa54354e25 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 20 Jan 2020 15:36:27 -0800 Subject: [PATCH 68/83] Remove unnecessary optimization --- src/s_sound.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/s_sound.c b/src/s_sound.c index d11fc4321..d84e20ab4 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1485,11 +1485,7 @@ MusicDefStrcpy (char *p, const char *s, size_t n, int version) if (version == MUSICDEF_220) { while (( p = strchr(p, '_') )) - { - n = strspn(p, "_"); - memset(p, ' ', n); // turn _ into spaces. - p += n; - } + *p++ = ' '; // turn _ into spaces. } } From 49a4c7d5f3db21808e1d4875b6f5d5b6989a5ac7 Mon Sep 17 00:00:00 2001 From: Zwip-Zwap Zapony Date: Tue, 21 Jan 2020 14:53:05 +0100 Subject: [PATCH 69/83] Separate "turnmultiplier"s for splitscreen players This fixes player 2 using player 1's "cam_turnmultiplier" instead of player 2's "cam2_turnmultiplier" --- src/g_game.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 646147e73..f1b9b0b5c 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1140,7 +1140,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) INT32 *myaiming = (ssplayer == 1 ? &localaiming : &localaiming2); angle_t drawangleoffset = (player->powers[pw_carry] == CR_ROLLOUT) ? ANGLE_180 : 0; - INT32 chasecam, chasefreelook, alwaysfreelook, usejoystick, invertmouse, mousemove; + INT32 chasecam, chasefreelook, alwaysfreelook, usejoystick, invertmouse, turnmultiplier, mousemove; controlstyle_e controlstyle = G_ControlStyle(ssplayer); INT32 *mx; INT32 *my; INT32 *mly; @@ -1163,6 +1163,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) alwaysfreelook = cv_alwaysfreelook.value; usejoystick = cv_usejoystick.value; invertmouse = cv_invertmouse.value; + turnmultiplier = cv_cam_turnmultiplier.value; mousemove = cv_mousemove.value; mx = &mousex; my = &mousey; @@ -1176,6 +1177,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) alwaysfreelook = cv_alwaysfreelook2.value; usejoystick = cv_usejoystick2.value; invertmouse = cv_invertmouse2.value; + turnmultiplier = cv_cam2_turnmultiplier.value; mousemove = cv_mousemove2.value; mx = &mouse2x; my = &mouse2y; @@ -1293,14 +1295,14 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) { if (turnright && turnleft); else if (turnright) - cmd->angleturn = (INT16)(cmd->angleturn - ((angleturn[tspeed] * cv_cam_turnmultiplier.value)>>FRACBITS)); + cmd->angleturn = (INT16)(cmd->angleturn - ((angleturn[tspeed] * turnmultiplier)>>FRACBITS)); else if (turnleft) - cmd->angleturn = (INT16)(cmd->angleturn + ((angleturn[tspeed] * cv_cam_turnmultiplier.value)>>FRACBITS)); + cmd->angleturn = (INT16)(cmd->angleturn + ((angleturn[tspeed] * turnmultiplier)>>FRACBITS)); if (analogjoystickmove && lookjoystickvector.xaxis != 0) { // JOYAXISRANGE should be 1023 (divide by 1024) - cmd->angleturn = (INT16)(cmd->angleturn - ((((lookjoystickvector.xaxis * angleturn[1]) >> 10) * cv_cam_turnmultiplier.value)>>FRACBITS)); // ANALOG! + cmd->angleturn = (INT16)(cmd->angleturn - ((((lookjoystickvector.xaxis * angleturn[1]) >> 10) * turnmultiplier)>>FRACBITS)); // ANALOG! } if (turnright || turnleft || abs(cmd->angleturn) > angleturn[2]) From d374bf4f9ba239d86b04f93878a496c21280eaf0 Mon Sep 17 00:00:00 2001 From: Louis-Antoine Date: Wed, 22 Jan 2020 03:05:08 +0100 Subject: [PATCH 70/83] Let clients rejoin the server without losing their status This is accomplished by simply preserving the player's body after disconnecting. Bodies will despawn after the number of minutes specified by the "rejointimeout" console variable (float). A value of 0 disables the feature completely. Clients rejoining are identified by their IP address, and may rejoin even if the server is full or joins are disabled, for as long as their body remains. From a technical standpoint, when the user disconnects, the player they were controlling does not leave, the underlying player_t just keeps working normally, except it does not receive any input anymore. When the user reconnects, they are simply "relinked" to their player_t. Those "soulless" players can be identified through their "quittime" field, which is the number of tics elapsed since the user disconnected, or zero if still connected. "quittime" is exposed to Lua. --- src/command.c | 2 +- src/d_clisrv.c | 316 +++++++++++++++++++++++++++---------------- src/d_clisrv.h | 5 +- src/d_netcmd.c | 35 ++--- src/d_player.h | 1 + src/g_game.c | 4 +- src/hu_stuff.c | 14 +- src/lua_consolelib.c | 2 +- src/lua_hook.h | 2 +- src/lua_hooklib.c | 2 +- src/lua_playerlib.c | 4 + src/p_saveg.c | 2 + src/p_tick.c | 13 +- 13 files changed, 252 insertions(+), 150 deletions(-) diff --git a/src/command.c b/src/command.c index 31c9b50ad..8a0fc3f4e 100644 --- a/src/command.c +++ b/src/command.c @@ -1407,7 +1407,7 @@ static void Got_NetVar(UINT8 **p, INT32 playernum) // not from server or remote admin, must be hacked/buggy client CONS_Alert(CONS_WARNING, M_GetText("Illegal netvar command received from %s\n"), player_names[playernum]); if (server) - SendKick(playernum, KICK_MSG_CON_FAIL); + SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); return; } netid = READUINT16(*p); diff --git a/src/d_clisrv.c b/src/d_clisrv.c index e85664d38..d40027a3d 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -21,6 +21,7 @@ #include "d_net.h" #include "d_main.h" #include "g_game.h" +#include "st_stuff.h" #include "hu_stuff.h" #include "keys.h" #include "g_input.h" // JOY1 @@ -391,7 +392,7 @@ static void ExtraDataTicker(void) { if (server) { - SendKick(i, KICK_MSG_CON_FAIL); + SendKick(i, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); DEBFILE(va("player %d kicked [gametic=%u] reason as follows:\n", i, gametic)); } CONS_Alert(CONS_WARNING, M_GetText("Got unknown net command [%s]=%d (max %d)\n"), sizeu1(curpos - bufferstart), *curpos, bufferstart[0]); @@ -437,6 +438,9 @@ void SendKick(UINT8 playernum, UINT8 msg) { UINT8 buf[2]; + if (!(server && cv_rejointimeout.value)) + msg &= ~KICK_MSG_KEEP_BODY; + buf[0] = playernum; buf[1] = msg; SendNetXCmd(XD_KICK, &buf, 2); @@ -1064,7 +1068,7 @@ static void SV_SendResynch(INT32 node) if (resynch_score[node] > (unsigned)cv_resynchattempts.value*250) { - SendKick(nodetoplayer[node], KICK_MSG_CON_FAIL); + SendKick(nodetoplayer[node], KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); resynch_score[node] = 0; } } @@ -2403,6 +2407,7 @@ void CL_ClearPlayer(INT32 playernum) if (players[playernum].mo) P_RemoveMobj(players[playernum].mo); memset(&players[playernum], 0, sizeof (player_t)); + memset(playeraddress[playernum], 0, sizeof(*playeraddress)); } // @@ -2410,7 +2415,7 @@ void CL_ClearPlayer(INT32 playernum) // // Removes a player from the current game // -static void CL_RemovePlayer(INT32 playernum, INT32 reason) +static void CL_RemovePlayer(INT32 playernum, kickreason_t reason) { // Sanity check: exceptional cases (i.e. c-fails) can cause multiple // kick commands to be issued for the same player. @@ -2423,9 +2428,6 @@ static void CL_RemovePlayer(INT32 playernum, INT32 reason) playerpernode[node]--; if (playerpernode[node] <= 0) { - // If a resynch was in progress, well, it no longer needs to be. - SV_InitResynchVars(playernode[playernum]); - nodeingame[playernode[playernum]] = false; Net_CloseConnection(playernode[playernum]); ResetNode(node); @@ -2812,9 +2814,12 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) char buf[3 + MAX_REASONLENGTH]; char *reason = buf; kickreason_t kickreason = KR_KICK; + boolean keepbody; pnum = READUINT8(*p); msg = READUINT8(*p); + keepbody = (msg & KICK_MSG_KEEP_BODY) != 0; + msg &= ~KICK_MSG_KEEP_BODY; if (pnum == serverplayer && IsPlayerAdmin(playernum)) { @@ -2874,6 +2879,7 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) */ pnum = playernum; msg = KICK_MSG_CON_FAIL; + keepbody = true; } //CONS_Printf("\x82%s ", player_names[pnum]); @@ -2942,7 +2948,7 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) kickreason = KR_TIMEOUT; break; case KICK_MSG_PLAYER_QUIT: - if (netgame) // not splitscreen/bots + if (netgame && !players[pnum].quittime) // not splitscreen/bots or soulless body HU_AddChatText(va("\x82*%s left the game", player_names[pnum]), false); kickreason = KR_LEAVE; break; @@ -2983,6 +2989,24 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) else M_StartMessage(M_GetText("You have been kicked by the server\n\nPress ESC\n"), NULL, MM_NOTHING); } + else if (keepbody) + { + if (server && !demoplayback) + { + INT32 node = playernode[pnum]; + playerpernode[node]--; + if (playerpernode[node] <= 0) + { + nodeingame[node] = false; + Net_CloseConnection(node); + ResetNode(node); + } + } + + playernode[pnum] = UINT8_MAX; + + players[pnum].quittime = 1; + } else CL_RemovePlayer(pnum, kickreason); } @@ -2991,6 +3015,9 @@ consvar_t cv_allownewplayer = {"allowjoin", "On", CV_SAVE|CV_NETVAR, CV_OnOff, N consvar_t cv_joinnextround = {"joinnextround", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; /// \todo not done static CV_PossibleValue_t maxplayers_cons_t[] = {{2, "MIN"}, {32, "MAX"}, {0, NULL}}; consvar_t cv_maxplayers = {"maxplayers", "8", CV_SAVE, maxplayers_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +static CV_PossibleValue_t rejointimeout_cons_t[] = {{1, "MIN"}, {60 * FRACUNIT, "MAX"}, {0, "Off"}, {0, NULL}}; +consvar_t cv_rejointimeout = {"rejointimeout", "Off", CV_SAVE|CV_FLOAT, rejointimeout_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; + static CV_PossibleValue_t resynchattempts_cons_t[] = {{1, "MIN"}, {20, "MAX"}, {0, "No"}, {0, NULL}}; consvar_t cv_resynchattempts = {"resynchattempts", "10", CV_SAVE, resynchattempts_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL }; consvar_t cv_blamecfail = {"blamecfail", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL }; @@ -3060,6 +3087,7 @@ static void ResetNode(INT32 node) nodewaiting[node] = 0; playerpernode[node] = 0; sendingsavegame[node] = false; + SV_InitResynchVars(node); } void SV_ResetServer(void) @@ -3075,13 +3103,8 @@ void SV_ResetServer(void) tictoclear = maketic; for (i = 0; i < MAXNETNODES; i++) - { ResetNode(i); - // Make sure resynch status doesn't get carried over! - SV_InitResynchVars(i); - } - for (i = 0; i < MAXPLAYERS; i++) { #ifdef HAVE_BLUA @@ -3089,6 +3112,7 @@ void SV_ResetServer(void) #endif playeringame[i] = false; playernode[i] = UINT8_MAX; + memset(playeraddress[i], 0, sizeof(*playeraddress)); sprintf(player_names[i], "Player %d", i + 1); adminplayers[i] = -1; // Populate the entire adminplayers array with -1. } @@ -3179,6 +3203,37 @@ void D_QuitNetGame(void) #endif } +static INT32 FindRejoinerNum(SINT8 node) +{ + char strippednodeaddress[64]; + const char *nodeaddress; + char *port; + INT32 i; + + // Make sure there is no dead dress before proceeding to the stripping + if (!I_GetNodeAddress) + return -1; + nodeaddress = I_GetNodeAddress(node); + if (!nodeaddress) + return -1; + + // Strip the address of its port + strcpy(strippednodeaddress, nodeaddress); + port = strchr(strippednodeaddress, ':'); + if (port) + *port = '\0'; + + // Check if any player matches the stripped address + for (i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i] && playeraddress[i][0] && playernode[i] == UINT8_MAX + && !strcmp(playeraddress[i], strippednodeaddress)) + return i; + } + + return -1; +} + // Adds a node to the game (player will follow at map change or at savegame....) static inline void SV_AddNode(INT32 node) { @@ -3195,13 +3250,16 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum) { INT16 node, newplayernum; boolean splitscreenplayer; + boolean rejoined; + player_t *newplayer; + char *port; if (playernum != serverplayer && !IsPlayerAdmin(playernum)) { // protect against hacked/buggy client CONS_Alert(CONS_WARNING, M_GetText("Illegal add player command received from %s\n"), player_names[playernum]); if (server) - SendKick(playernum, KICK_MSG_CON_FAIL); + SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); return; } @@ -3210,15 +3268,34 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum) splitscreenplayer = newplayernum & 0x80; newplayernum &= ~0x80; - // Clear player before joining, lest some things get set incorrectly - // HACK: don't do this for splitscreen, it relies on preset values - if (!splitscreen && !botingame) - CL_ClearPlayer(newplayernum); - playeringame[newplayernum] = true; + rejoined = playeringame[newplayernum]; + + if (!rejoined) + { + // Clear player before joining, lest some things get set incorrectly + // HACK: don't do this for splitscreen, it relies on preset values + if (!splitscreen && !botingame) + CL_ClearPlayer(newplayernum); + playeringame[newplayernum] = true; + G_AddPlayer(newplayernum); + if (newplayernum+1 > doomcom->numslots) + doomcom->numslots = (INT16)(newplayernum+1); + + if (server && I_GetNodeAddress) + { + strcpy(playeraddress[newplayernum], I_GetNodeAddress(node)); + port = strchr(playeraddress[newplayernum], ':'); + if (port) + *port = '\0'; + } + } + + newplayer = &players[newplayernum]; + + newplayer->jointime = 0; + newplayer->quittime = 0; + READSTRINGN(*p, player_names[newplayernum], MAXPLAYERNAME); - G_AddPlayer(newplayernum); - if (newplayernum+1 > doomcom->numslots) - doomcom->numslots = (INT16)(newplayernum+1); // the server is creating my player if (node == mynode) @@ -3236,29 +3313,67 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum) secondarydisplayplayer = newplayernum; DEBFILE("spawning my brother\n"); if (botingame) - players[newplayernum].bot = 1; + newplayer->bot = 1; } D_SendPlayerConfig(); addedtogame = true; + + if (rejoined) + { + if (newplayer->mo) + { + if (!splitscreenplayer) + localangle = newplayer->mo->angle; + else + localangle2 = newplayer->mo->angle; + + newplayer->viewheight = 41*newplayer->height/48; + + if (newplayer->mo->eflags & MFE_VERTICALFLIP) + newplayer->viewz = newplayer->mo->z + newplayer->mo->height - newplayer->viewheight; + else + newplayer->viewz = newplayer->mo->z + newplayer->viewheight; + } + + // wake up the status bar + ST_Start(); + // wake up the heads up text + HU_Start(); + + if (camera.chase && !splitscreenplayer) + P_ResetCamera(newplayer, &camera); + if (camera2.chase && splitscreenplayer) + P_ResetCamera(newplayer, &camera2); + } } if (netgame) { - if (server && cv_showjoinaddress.value) - { - const char *address; - if (I_GetNodeAddress && (address = I_GetNodeAddress(node)) != NULL) - HU_AddChatText(va("\x82*%s has joined the game (player %d) (%s)", player_names[newplayernum], newplayernum, address), false); // merge join notification + IP to avoid clogging console/chat. - } + char joinmsg[256]; + + if (rejoined) + strcpy(joinmsg, M_GetText("\x82*%s has rejoined the game (player %d)")); else - HU_AddChatText(va("\x82*%s has joined the game (player %d)", player_names[newplayernum], newplayernum), false); // if you don't wanna see the join address. + strcpy(joinmsg, M_GetText("\x82*%s has joined the game (player %d)")); + strcpy(joinmsg, va(joinmsg, player_names[newplayernum], newplayernum)); + + // Merge join notification + IP to avoid clogging console/chat + if (server && cv_showjoinaddress.value && I_GetNodeAddress) + { + const char *address = I_GetNodeAddress(node); + if (address) + strcat(joinmsg, va(" (%s)", address)); + } + + HU_AddChatText(joinmsg, false); } if (server && multiplayer && motd[0] != '\0') COM_BufAddText(va("sayto %d %s\n", newplayernum, motd)); #ifdef HAVE_BLUA - LUAh_PlayerJoin(newplayernum); + if (!rejoined) + LUAh_PlayerJoin(newplayernum); #endif } @@ -3267,11 +3382,7 @@ static boolean SV_AddWaitingPlayers(const char *name, const char *name2) INT32 node, n, newplayer = false; UINT8 buf[2 + MAXPLAYERNAME]; UINT8 *p; - UINT8 newplayernum = 0; - - // What is the reason for this? Why can't newplayernum always be 0? - if (dedicated) - newplayernum = 1; + INT32 newplayernum; for (node = 0; node < MAXNETNODES; node++) { @@ -3280,68 +3391,22 @@ static boolean SV_AddWaitingPlayers(const char *name, const char *name2) { newplayer = true; - if (netgame) - // !!!!!!!!! EXTREMELY SUPER MEGA GIGA ULTRA ULTIMATELY TERRIBLY IMPORTANT !!!!!!!!! - // - // The line just after that comment is an awful, horrible, terrible, TERRIBLE hack. - // - // Basically, the fix I did in order to fix the download freezes happens - // to cause situations in which a player number does not match - // the node number associated to that player. - // That is totally normal, there is absolutely *nothing* wrong with that. - // Really. Player 7 being tied to node 29, for instance, is totally fine. - // - // HOWEVER. A few (broken) parts of the netcode do the TERRIBLE mistake - // of mixing up the concepts of node and player, resulting in - // incorrect handling of cases where a player is tied to a node that has - // a different number (which is a totally normal case, or at least should be). - // This incorrect handling can go as far as literally - // anyone from joining your server at all, forever. - // - // Given those two facts, there are two options available - // in order to let this download freeze fix be: - // 1) Fix the broken parts that assume a node is a player or similar bullshit. - // 2) Change the part this comment is located at, so that any player who joins - // is given the same number as their associated node. - // - // No need to say, 1) is by far the obvious best, whereas 2) is a terrible hack. - // Unfortunately, after trying 1), I most likely didn't manage to find all - // of those broken parts, and thus 2) has become the only safe option that remains. - // - // So I did this hack. - // - // If it isn't clear enough, in order to get rid of this ugly hack, - // you will have to fix all parts of the netcode that - // make a confusion between nodes and players. - // - // And if it STILL isn't clear enough, a node and a player - // is NOT the same thing. Never. NEVER. *NEVER*. - // - // And if someday you make the terrible mistake of - // daring to have the unforgivable idea to try thinking - // that a node might possibly be the same as a player, - // or that a player should have the same number as its node, - // be sure that I will somehow know about it and - // hunt you down tirelessly and make you regret it, - // even if you live on the other side of the world. - // - // TODO: vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv - // \todo >>>>>>>>>> Remove this horrible hack as soon as possible <<<<<<<<<< - // TODO: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - // - // !!!!!!!!! EXTREMELY SUPER MEGA GIGA ULTRA ULTIMATELY TERRIBLY IMPORTANT !!!!!!!!! - newplayernum = node; // OMFG SAY WELCOME TO TEH NEW HACK FOR FIX FIL DOWNLOAD!!1! - else // Don't use the hack if we don't have to + newplayernum = FindRejoinerNum(node); + if (newplayernum == -1) + { // search for a free playernum // we can't use playeringame since it is not updated here - for (; newplayernum < MAXPLAYERS; newplayernum++) + for (newplayernum = dedicated ? 1 : 0; newplayernum < MAXPLAYERS; newplayernum++) { + if (playeringame[newplayernum]) + continue; for (n = 0; n < MAXNETNODES; n++) if (nodetoplayer[n] == newplayernum || nodetoplayer2[n] == newplayernum) break; if (n == MAXNETNODES) break; } + } // should never happen since we check the playernum // before accepting the join @@ -3368,8 +3433,6 @@ static boolean SV_AddWaitingPlayers(const char *name, const char *name2) SendNetXCmd(XD_ADDPLAYER, &buf, p - buf); DEBFILE(va("Server added player %d node %d\n", newplayernum, node)); - // use the next free slot (we can't put playeringame[newplayernum] = true here) - newplayernum++; } } @@ -3495,16 +3558,19 @@ static size_t TotalTextCmdPerTic(tic_t tic) static void HandleConnect(SINT8 node) { char names[MAXSPLITSCREENPLAYERS][MAXPLAYERNAME + 1]; + INT32 rejoinernum; INT32 i; + rejoinernum = FindRejoinerNum(node); + if (bannednode && bannednode[node]) SV_SendRefuse(node, M_GetText("You have been banned\nfrom the server")); else if (netbuffer->u.clientcfg.version != VERSION || netbuffer->u.clientcfg.subversion != SUBVERSION) SV_SendRefuse(node, va(M_GetText("Different SRB2 versions cannot\nplay a netgame!\n(server version %d.%d.%d)"), VERSION/100, VERSION%100, SUBVERSION)); - else if (!cv_allownewplayer.value && node) + else if (!cv_allownewplayer.value && node && rejoinernum == -1) SV_SendRefuse(node, M_GetText("The server is not accepting\njoins for the moment")); - else if (D_NumPlayers() >= cv_maxplayers.value) + else if (D_NumPlayers() >= cv_maxplayers.value && rejoinernum == -1) SV_SendRefuse(node, va(M_GetText("Maximum players reached: %d"), cv_maxplayers.value)); else if (netgame && netbuffer->u.clientcfg.localplayers > 1) // Hacked client? SV_SendRefuse(node, M_GetText("Too many players from\nthis node.")); @@ -3519,7 +3585,7 @@ static void HandleConnect(SINT8 node) for (i = 0; i < netbuffer->u.clientcfg.localplayers - playerpernode[node]; i++) { strlcpy(names[i], netbuffer->u.clientcfg.names[i], MAXPLAYERNAME + 1); - if (!EnsurePlayerNameIsGood(names[i], -1)) + if (!EnsurePlayerNameIsGood(names[i], rejoinernum)) { SV_SendRefuse(node, "Bad player name"); return; @@ -3956,7 +4022,7 @@ static void HandlePacketFromPlayer(SINT8 node) } else { - SendKick(netconsole, KICK_MSG_CON_FAIL); + SendKick(netconsole, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); DEBFILE(va("player %d kicked (synch failure) [%u] %d!=%d\n", netconsole, realstart, consistancy[realstart%BACKUPTICS], SHORT(netbuffer->u.clientpak.consistancy))); @@ -4075,6 +4141,7 @@ static void HandlePacketFromPlayer(SINT8 node) kickmsg = KICK_MSG_TIMEOUT; else kickmsg = KICK_MSG_PLAYER_QUIT; + kickmsg |= KICK_MSG_KEEP_BODY; SendKick(netconsole, kickmsg); nodetoplayer[node] = -1; @@ -4096,7 +4163,7 @@ static void HandlePacketFromPlayer(SINT8 node) { CONS_Alert(CONS_WARNING, M_GetText("%s received from non-host %d\n"), "PT_RESYNCHEND", node); if (server) - SendKick(netconsole, KICK_MSG_CON_FAIL); + SendKick(netconsole, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); break; } resynch_local_inprogress = false; @@ -4114,7 +4181,7 @@ static void HandlePacketFromPlayer(SINT8 node) { CONS_Alert(CONS_WARNING, M_GetText("%s received from non-host %d\n"), "PT_SERVERTICS", node); if (server) - SendKick(netconsole, KICK_MSG_CON_FAIL); + SendKick(netconsole, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); break; } @@ -4174,7 +4241,7 @@ static void HandlePacketFromPlayer(SINT8 node) { CONS_Alert(CONS_WARNING, M_GetText("%s received from non-host %d\n"), "PT_RESYNCHING", node); if (server) - SendKick(netconsole, KICK_MSG_CON_FAIL); + SendKick(netconsole, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); break; } resynch_local_inprogress = true; @@ -4186,7 +4253,7 @@ static void HandlePacketFromPlayer(SINT8 node) { CONS_Alert(CONS_WARNING, M_GetText("%s received from non-host %d\n"), "PT_PING", node); if (server) - SendKick(netconsole, KICK_MSG_CON_FAIL); + SendKick(netconsole, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); break; } @@ -4210,7 +4277,7 @@ static void HandlePacketFromPlayer(SINT8 node) { CONS_Alert(CONS_WARNING, M_GetText("%s received from non-host %d\n"), "PT_FILEFRAGMENT", node); if (server) - SendKick(netconsole, KICK_MSG_CON_FAIL); + SendKick(netconsole, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); break; } if (client) @@ -4406,7 +4473,7 @@ static void CL_SendClientCmd(void) packetsize = sizeof (clientcmd_pak) - sizeof (ticcmd_t) - sizeof (INT16); HSendPacket(servernode, false, 0, packetsize); } - else if (gamestate != GS_NULL) + else if (gamestate != GS_NULL && addedtogame) { G_MoveTiccmd(&netbuffer->u.clientpak.cmd, &localcmds, 1); netbuffer->u.clientpak.consistancy = SHORT(consistancy[gametic%BACKUPTICS]); @@ -4582,6 +4649,11 @@ static void Local_Maketic(INT32 realtics) localcmds.angleturn |= TICCMD_RECEIVED; } +// This function is utter bullshit and is responsible for +// the random desynch that happens when a player spawns. +// This is because ticcmds are resent to clients if a packet +// was dropped, and thus modifying them can lead to several +// clients having their ticcmds set to different values. void SV_SpawnPlayer(INT32 playernum, INT32 x, INT32 y, angle_t angle) { tic_t tic; @@ -4615,28 +4687,36 @@ void SV_SpawnPlayer(INT32 playernum, INT32 x, INT32 y, angle_t angle) // create missed tic static void SV_Maketic(void) { - INT32 j; + INT32 i; - for (j = 0; j < MAXNETNODES; j++) - if (playerpernode[j]) + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; + + // We didn't receive this tic + if ((netcmds[maketic % BACKUPTICS][i].angleturn & TICCMD_RECEIVED) == 0) { - INT32 player = nodetoplayer[j]; - if ((netcmds[maketic%BACKUPTICS][player].angleturn & TICCMD_RECEIVED) == 0) - { // we didn't receive this tic - INT32 i; + ticcmd_t * ticcmd = &netcmds[(maketic ) % BACKUPTICS][i]; + ticcmd_t *prevticcmd = &netcmds[(maketic - 1) % BACKUPTICS][i]; - DEBFILE(va("MISS tic%4d for node %d\n", maketic, j)); -#if defined(PARANOIA) && 0 - CONS_Debug(DBG_NETPLAY, "Client Misstic %d\n", maketic); -#endif - // copy the old tic - for (i = 0; i < playerpernode[j]; i++, player = nodetoplayer2[j]) - { - netcmds[maketic%BACKUPTICS][player] = netcmds[(maketic-1)%BACKUPTICS][player]; - netcmds[maketic%BACKUPTICS][player].angleturn &= ~TICCMD_RECEIVED; - } + if (players[i].quittime) + { + // Copy the angle/aiming from the previous tic + // and empty the other inputs + memset(ticcmd, 0, sizeof(netcmds[0][0])); + ticcmd->angleturn = prevticcmd->angleturn | TICCMD_RECEIVED; + ticcmd->aiming = prevticcmd->aiming; + } + else + { + DEBFILE(va("MISS tic%4d for player %d\n", maketic, i)); + // Copy the input from the previous tic + *ticcmd = *prevticcmd; + ticcmd->angleturn &= ~TICCMD_RECEIVED; } } + } // all tic are now proceed make the next maketic++; @@ -4758,7 +4838,7 @@ static inline void PingUpdate(void) // ok your net has been bad for too long, you deserve to die. { pingtimeout[i] = 0; - SendKick(i, KICK_MSG_PING_HIGH); + SendKick(i, KICK_MSG_PING_HIGH | KICK_MSG_KEEP_BODY); } } /* diff --git a/src/d_clisrv.h b/src/d_clisrv.h index 99fae32fb..5ee11056a 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -463,6 +463,7 @@ extern consvar_t cv_playbackspeed; #define KICK_MSG_PING_HIGH 6 #define KICK_MSG_CUSTOM_KICK 7 #define KICK_MSG_CUSTOM_BAN 8 +#define KICK_MSG_KEEP_BODY 0x80 typedef enum { @@ -490,7 +491,9 @@ extern UINT32 realpingtable[MAXPLAYERS]; extern UINT32 playerpingtable[MAXPLAYERS]; extern tic_t servermaxping; -extern consvar_t cv_joinnextround, cv_allownewplayer, cv_maxplayers, cv_resynchattempts, cv_blamecfail, cv_maxsend, cv_noticedownload, cv_downloadspeed; +extern consvar_t cv_allownewplayer, cv_joinnextround, cv_maxplayers, cv_rejointimeout; +extern consvar_t cv_resynchattempts, cv_blamecfail; +extern consvar_t cv_maxsend, cv_noticedownload, cv_downloadspeed; // Used in d_net, the only dependence tic_t ExpandTics(INT32 low); diff --git a/src/d_netcmd.c b/src/d_netcmd.c index cfcc1b2c5..af1bb8948 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -572,6 +572,7 @@ void D_RegisterServerCommands(void) // d_clisrv CV_RegisterVar(&cv_maxplayers); + CV_RegisterVar(&cv_rejointimeout); CV_RegisterVar(&cv_resynchattempts); CV_RegisterVar(&cv_maxsend); CV_RegisterVar(&cv_noticedownload); @@ -1091,7 +1092,7 @@ static void SetPlayerName(INT32 playernum, char *newname) { CONS_Printf(M_GetText("Player %d sent a bad name change\n"), playernum+1); if (server && netgame) - SendKick(playernum, KICK_MSG_CON_FAIL); + SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); } } @@ -1449,7 +1450,7 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum) if (kick) { CONS_Alert(CONS_WARNING, M_GetText("Illegal color change received from %s (team: %d), color: %d)\n"), player_names[playernum], p->ctfteam, p->skincolor); - SendKick(playernum, KICK_MSG_CON_FAIL); + SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); return; } } @@ -2032,7 +2033,7 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum) { CONS_Alert(CONS_WARNING, M_GetText("Illegal map change received from %s\n"), player_names[playernum]); if (server) - SendKick(playernum, KICK_MSG_CON_FAIL); + SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); return; } @@ -2142,7 +2143,7 @@ static void Got_Pause(UINT8 **cp, INT32 playernum) { CONS_Alert(CONS_WARNING, M_GetText("Illegal pause command received from %s\n"), player_names[playernum]); if (server) - SendKick(playernum, KICK_MSG_CON_FAIL); + SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); return; } @@ -2215,7 +2216,7 @@ static void Got_Suicide(UINT8 **cp, INT32 playernum) { CONS_Alert(CONS_WARNING, M_GetText("Illegal suicide command received from %s\n"), player_names[playernum]); if (server) - SendKick(playernum, KICK_MSG_CON_FAIL); + SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); return; } @@ -2278,7 +2279,7 @@ static void Got_Clearscores(UINT8 **cp, INT32 playernum) { CONS_Alert(CONS_WARNING, M_GetText("Illegal clear scores command received from %s\n"), player_names[playernum]); if (server) - SendKick(playernum, KICK_MSG_CON_FAIL); + SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); return; } @@ -2625,7 +2626,7 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum) // this should never happen unless the client is hacked/buggy CONS_Alert(CONS_WARNING, M_GetText("Illegal team change received from player %s\n"), player_names[playernum]); if (server) - SendKick(playernum, KICK_MSG_CON_FAIL); + SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); } if (NetPacket.packet.verification) // Special marker that the server sent the request @@ -2634,7 +2635,7 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum) { CONS_Alert(CONS_WARNING, M_GetText("Illegal team change received from player %s\n"), player_names[playernum]); if (server) - SendKick(playernum, KICK_MSG_CON_FAIL); + SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); return; } playernum = NetPacket.packet.playernum; @@ -2667,7 +2668,7 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum) { CONS_Alert(CONS_WARNING, M_GetText("Illegal team change received from player %s\n"), player_names[playernum]); if (server) - SendKick(playernum, KICK_MSG_CON_FAIL); + SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); } return; } @@ -2716,7 +2717,7 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum) if (server && ((NetPacket.packet.newteam < 0 || NetPacket.packet.newteam > 3) || error)) { CONS_Alert(CONS_WARNING, M_GetText("Illegal team change received from player %s\n"), player_names[playernum]); - SendKick(playernum, KICK_MSG_CON_FAIL); + SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); } //Safety first! @@ -3000,7 +3001,7 @@ static void Got_Verification(UINT8 **cp, INT32 playernum) { CONS_Alert(CONS_WARNING, M_GetText("Illegal verification received from %s (serverplayer is %s)\n"), player_names[playernum], player_names[serverplayer]); if (server) - SendKick(playernum, KICK_MSG_CON_FAIL); + SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); return; } @@ -3050,7 +3051,7 @@ static void Got_Removal(UINT8 **cp, INT32 playernum) { CONS_Alert(CONS_WARNING, M_GetText("Illegal demotion received from %s (serverplayer is %s)\n"), player_names[playernum], player_names[serverplayer]); if (server) - SendKick(playernum, KICK_MSG_CON_FAIL); + SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); return; } @@ -3124,7 +3125,7 @@ static void Got_MotD_f(UINT8 **cp, INT32 playernum) { CONS_Alert(CONS_WARNING, M_GetText("Illegal motd change received from %s\n"), player_names[playernum]); if (server) - SendKick(playernum, KICK_MSG_CON_FAIL); + SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); Z_Free(mymotd); return; } @@ -3180,7 +3181,7 @@ static void Got_RunSOCcmd(UINT8 **cp, INT32 playernum) { CONS_Alert(CONS_WARNING, M_GetText("Illegal runsoc command received from %s\n"), player_names[playernum]); if (server) - SendKick(playernum, KICK_MSG_CON_FAIL); + SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); return; } @@ -3338,7 +3339,7 @@ static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum) if ((playernum != serverplayer && !IsPlayerAdmin(playernum)) || kick) { CONS_Alert(CONS_WARNING, M_GetText("Illegal addfile command received from %s\n"), player_names[playernum]); - SendKick(playernum, KICK_MSG_CON_FAIL); + SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); return; } @@ -3387,7 +3388,7 @@ static void Got_Addfilecmd(UINT8 **cp, INT32 playernum) { CONS_Alert(CONS_WARNING, M_GetText("Illegal addfile command received from %s\n"), player_names[playernum]); if (server) - SendKick(playernum, KICK_MSG_CON_FAIL); + SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); return; } @@ -4170,7 +4171,7 @@ static void Got_ExitLevelcmd(UINT8 **cp, INT32 playernum) { CONS_Alert(CONS_WARNING, M_GetText("Illegal exitlevel command received from %s\n"), player_names[playernum]); if (server) - SendKick(playernum, KICK_MSG_CON_FAIL); + SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); return; } diff --git a/src/d_player.h b/src/d_player.h index 62f38193f..db55a9913 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -510,6 +510,7 @@ typedef struct player_s UINT8 bot; tic_t jointime; // Timer when player joins game to change skin/color + tic_t quittime; // Time elapsed since user disconnected, zero if connected #ifdef HWRENDER fixed_t fovadd; // adjust FOV for hw rendering #endif diff --git a/src/g_game.c b/src/g_game.c index 2a12dd298..956751bb9 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2307,6 +2307,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) INT32 skin; UINT32 availabilities; tic_t jointime; + tic_t quittime; boolean spectator; boolean outofcoop; INT16 bot; @@ -2320,6 +2321,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) ctfteam = players[player].ctfteam; exiting = players[player].exiting; jointime = players[player].jointime; + quittime = players[player].quittime; spectator = players[player].spectator; outofcoop = players[player].outofcoop; pflags = (players[player].pflags & (PF_FLIPCAM|PF_ANALOGMODE|PF_DIRECTIONCHAR|PF_AUTOBRAKE|PF_TAGIT|PF_GAMETYPEOVER)); @@ -2391,6 +2393,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) p->pflags = pflags; p->ctfteam = ctfteam; p->jointime = jointime; + p->quittime = quittime; p->spectator = spectator; p->outofcoop = outofcoop; @@ -2974,7 +2977,6 @@ void G_AddPlayer(INT32 playernum) } } - p->jointime = 0; p->playerstate = PST_REBORN; p->height = mobjinfo[MT_PLAYER].height; diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 1ad04f6ff..66ed8b11a 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -659,7 +659,7 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) M_GetText("Illegal say command received from %s while muted\n") : M_GetText("Illegal csay command received from non-admin %s\n"), player_names[playernum]); if (server) - SendKick(playernum, KICK_MSG_CON_FAIL); + SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); return; } @@ -673,7 +673,7 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) { CONS_Alert(CONS_WARNING, M_GetText("Illegal say command received from %s containing invalid characters\n"), player_names[playernum]); if (server) - SendKick(playernum, KICK_MSG_CON_FAIL); + SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); return; } } @@ -2367,7 +2367,7 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I if (!splitscreen) // don't draw it on splitscreen, { - if (!(tab[i].num == serverplayer)) + if (!(tab[i].num == serverplayer || players[tab[i].num].quittime)) HU_drawPing(x+ 253, y, playerpingtable[tab[i].num], false, 0); //else // V_DrawSmallString(x+ 246, y+4, V_YELLOWMAP, "SERVER"); @@ -2566,7 +2566,7 @@ static void HU_Draw32TeamTabRankings(playersort_t *tab, INT32 whiteplayer) V_DrawRightAlignedThinString(x+128, y, ((players[tab[i].num].spectator || players[tab[i].num].playerstate == PST_DEAD) ? 0 : V_TRANSLUCENT), va("%u", tab[i].count)); if (!splitscreen) { - if (!(tab[i].num == serverplayer)) + if (!(tab[i].num == serverplayer || players[tab[i].num].quittime)) HU_drawPing(x+ 135, y+1, playerpingtable[tab[i].num], true, 0); //else //V_DrawSmallString(x+ 129, y+4, V_YELLOWMAP, "HOST"); @@ -2690,7 +2690,7 @@ void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer) V_DrawRightAlignedThinString(x+100, y, (greycheck ? V_TRANSLUCENT : 0), va("%u", tab[i].count)); if (!splitscreen) { - if (!(tab[i].num == serverplayer)) + if (!(tab[i].num == serverplayer || players[tab[i].num].quittime)) HU_drawPing(x+ 113, y, playerpingtable[tab[i].num], false, 0); //else // V_DrawSmallString(x+ 94, y+4, V_YELLOWMAP, "SERVER"); @@ -2721,7 +2721,7 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline supercheck = supercheckdef; strlcpy(name, tab[i].name, 7); - if (!(tab[i].num == serverplayer)) + if (!(tab[i].num == serverplayer || players[tab[i].num].quittime)) HU_drawPing(x+ 113, y, playerpingtable[tab[i].num], false, 0); //else // V_DrawSmallString(x+ 94, y+4, V_YELLOWMAP, "SERVER"); @@ -2829,7 +2829,7 @@ static void HU_Draw32TabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scor strlcpy(name, tab[i].name, 7); if (!splitscreen) // don't draw it on splitscreen, { - if (!(tab[i].num == serverplayer)) + if (!(tab[i].num == serverplayer || players[tab[i].num].quittime)) HU_drawPing(x+ 135, y+1, playerpingtable[tab[i].num], true, 0); //else // V_DrawSmallString(x+ 129, y+4, V_YELLOWMAP, "HOST"); diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c index 4d23f73b2..90ea85382 100644 --- a/src/lua_consolelib.c +++ b/src/lua_consolelib.c @@ -87,7 +87,7 @@ deny: CONS_Alert(CONS_WARNING, M_GetText("Illegal lua command received from %s\n"), player_names[playernum]); if (server) - SendKick(playernum, KICK_MSG_CON_FAIL); + SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); } // Wrapper for COM_AddCommand commands diff --git a/src/lua_hook.h b/src/lua_hook.h index 6617bca93..c092c0a94 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -91,7 +91,7 @@ boolean LUAh_HurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source, UINT8 boolean LUAh_MapThingSpawn(mobj_t *mo, mapthing_t *mthing); // Hook for P_SpawnMapThing by mobj type boolean LUAh_FollowMobj(player_t *player, mobj_t *mobj); // Hook for P_PlayerAfterThink Smiles mobj-following UINT8 LUAh_PlayerCanDamage(player_t *player, mobj_t *mobj); // Hook for P_PlayerCanDamage -void LUAh_PlayerQuit(player_t *plr, int reason); // Hook for player quitting +void LUAh_PlayerQuit(player_t *plr, kickreason_t reason); // Hook for player quitting void LUAh_IntermissionThinker(void); // Hook for Y_Ticker #endif diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index ef87d0b6f..acc82a66a 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -1295,7 +1295,7 @@ UINT8 LUAh_PlayerCanDamage(player_t *player, mobj_t *mobj) return shouldCollide; } -void LUAh_PlayerQuit(player_t *plr, int reason) +void LUAh_PlayerQuit(player_t *plr, kickreason_t reason) { hook_p hookp; if (!gL || !(hooksAvailable[hook_PlayerQuit/8] & (1<<(hook_PlayerQuit%8)))) diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index c501fbbb2..1dd4c45b5 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -362,6 +362,8 @@ static int player_get(lua_State *L) lua_pushinteger(L, plr->bot); else if (fastcmp(field,"jointime")) lua_pushinteger(L, plr->jointime); + else if (fastcmp(field,"quittime")) + lua_pushinteger(L, plr->quittime); #ifdef HWRENDER else if (fastcmp(field,"fovadd")) lua_pushfixed(L, plr->fovadd); @@ -701,6 +703,8 @@ static int player_set(lua_State *L) return NOSET; else if (fastcmp(field,"jointime")) plr->jointime = (tic_t)luaL_checkinteger(L, 3); + else if (fastcmp(field,"quittime")) + plr->quittime = (tic_t)luaL_checkinteger(L, 3); #ifdef HWRENDER else if (fastcmp(field,"fovadd")) plr->fovadd = luaL_checkfixed(L, 3); diff --git a/src/p_saveg.c b/src/p_saveg.c index 89447db80..1db1e893e 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -255,6 +255,7 @@ static void P_NetArchivePlayers(void) WRITEINT32(save_p, players[i].onconveyor); WRITEUINT32(save_p, players[i].jointime); + WRITEUINT32(save_p, players[i].quittime); WRITEUINT16(save_p, flags); @@ -446,6 +447,7 @@ static void P_NetUnArchivePlayers(void) players[i].onconveyor = READINT32(save_p); players[i].jointime = READUINT32(save_p); + players[i].quittime = READUINT32(save_p); flags = READUINT16(save_p); diff --git a/src/p_tick.c b/src/p_tick.c index e0f60bd22..6f28d0de0 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -590,10 +590,19 @@ void P_Ticker(boolean run) { INT32 i; - //Increment jointime even if paused. + // Increment jointime and quittime even if paused for (i = 0; i < MAXPLAYERS; i++) if (playeringame[i]) - ++players[i].jointime; + { + players[i].jointime++; + + if (players[i].quittime) + { + players[i].quittime++; + if (server && players[i].quittime >= FixedMul(cv_rejointimeout.value, 60 * TICRATE)) + SendKick(i, KICK_MSG_PLAYER_QUIT); + } + } if (objectplacing) { From 73d0549fa43da04aa8954c53766aa727b2c71204 Mon Sep 17 00:00:00 2001 From: Louis-Antoine Date: Wed, 22 Jan 2020 03:11:05 +0100 Subject: [PATCH 71/83] Ignore players towards exit count 30 seconds after their disconnection --- src/g_game.c | 2 ++ src/p_user.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/g_game.c b/src/g_game.c index 956751bb9..30519b379 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2999,6 +2999,8 @@ boolean G_EnoughPlayersFinished(void) { if (!playeringame[i] || players[i].spectator || players[i].bot) continue; + if (players[i].quittime > 30 * TICRATE) + continue; if (players[i].lives <= 0) continue; diff --git a/src/p_user.c b/src/p_user.c index ea42a2c36..4044428b8 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -11479,6 +11479,8 @@ void P_PlayerThink(player_t *player) { if (!playeringame[i] || players[i].spectator || players[i].bot) continue; + if (players[i].quittime > 30 * TICRATE) + continue; if (players[i].lives <= 0) continue; From d03c928baa35e133683df7395bbb775aa29cd5a7 Mon Sep 17 00:00:00 2001 From: Louis-Antoine Date: Wed, 22 Jan 2020 03:14:44 +0100 Subject: [PATCH 72/83] Give flashing tics to disconnected players and prevent drowning --- src/p_enemy.c | 3 +++ src/p_user.c | 8 ++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index 74a11fe67..186b0854d 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -748,6 +748,9 @@ boolean P_LookForPlayers(mobj_t *actor, boolean allaround, boolean tracer, fixed if (player->bot) continue; // ignore bots + if (player->quittime) + continue; // Ignore uncontrolled bodies + if (dist > 0 && P_AproxDistance(P_AproxDistance(player->mo->x - actor->x, player->mo->y - actor->y), player->mo->z - actor->z) > dist) continue; // Too far away diff --git a/src/p_user.c b/src/p_user.c index 4044428b8..2d87c910b 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -11921,6 +11921,10 @@ void P_PlayerThink(player_t *player) player->pflags &= ~PF_USEDOWN; } + // IF PLAYER NOT HERE THEN FLASH END IF + if (player->quittime && player->powers[pw_flashing] < flashingtics - 1) + player->powers[pw_flashing] = flashingtics - 1; + // Counters, time dependent power ups. // Time Bonus & Ring Bonus count settings @@ -11964,12 +11968,12 @@ void P_PlayerThink(player_t *player) else player->powers[pw_underwater] = 0; } - else if (player->powers[pw_underwater] && !(maptol & TOL_NIGHTS) && !((netgame || multiplayer) && player->spectator)) // underwater timer + else if (player->powers[pw_underwater] && !(maptol & TOL_NIGHTS) && !((netgame || multiplayer) && (player->spectator || player->quittime))) // underwater timer player->powers[pw_underwater]--; if (player->powers[pw_spacetime] && (player->pflags & PF_GODMODE || (player->powers[pw_shield] & SH_PROTECTWATER))) player->powers[pw_spacetime] = 0; - else if (player->powers[pw_spacetime] && !(maptol & TOL_NIGHTS) && !((netgame || multiplayer) && player->spectator)) // underwater timer + else if (player->powers[pw_spacetime] && !(maptol & TOL_NIGHTS) && !((netgame || multiplayer) && (player->spectator || player->quittime))) // underwater timer player->powers[pw_spacetime]--; if (player->powers[pw_gravityboots] && player->powers[pw_gravityboots] < UINT16_MAX) From 412ba38a81b79909383bdeb94f12baf381b791d0 Mon Sep 17 00:00:00 2001 From: Louis-Antoine Date: Wed, 22 Jan 2020 03:19:15 +0100 Subject: [PATCH 73/83] Refactor player spawning code a little --- src/g_game.c | 126 ++++++++++++++++++++++++++------------------------ src/g_game.h | 4 +- src/p_setup.c | 6 +-- 3 files changed, 71 insertions(+), 65 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 30519b379..ce28766ec 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2547,74 +2547,24 @@ static boolean G_CheckSpot(INT32 playernum, mapthing_t *mthing) // or a not-so-appropriate spot, if it initially fails // due to a lack of starts open or something. // -void G_SpawnPlayer(INT32 playernum, boolean starpost) +void G_SpawnPlayer(INT32 playernum) { - mapthing_t *spawnpoint; - if (!playeringame[playernum]) return; P_SpawnPlayer(playernum); - - if (starpost) //Don't even bother with looking for a place to spawn. - { - P_MovePlayerToStarpost(playernum); -#ifdef HAVE_BLUA - LUAh_PlayerSpawn(&players[playernum]); // Lua hook for player spawning :) -#endif - return; - } - - // -- CTF -- - // Order: CTF->DM->Coop - if (gametype == GT_CTF && players[playernum].ctfteam) - { - if (!(spawnpoint = G_FindCTFStart(playernum)) // find a CTF start - && !(spawnpoint = G_FindMatchStart(playernum))) // find a DM start - spawnpoint = G_FindCoopStart(playernum); // fallback - } - - // -- DM/Tag/CTF-spectator/etc -- - // Order: DM->CTF->Coop - else if (gametype == GT_MATCH || gametype == GT_TEAMMATCH || gametype == GT_CTF - || ((gametype == GT_TAG || gametype == GT_HIDEANDSEEK) && !(players[playernum].pflags & PF_TAGIT))) - { - if (!(spawnpoint = G_FindMatchStart(playernum)) // find a DM start - && !(spawnpoint = G_FindCTFStart(playernum))) // find a CTF start - spawnpoint = G_FindCoopStart(playernum); // fallback - } - - // -- Other game modes -- - // Order: Coop->DM->CTF - else - { - if (!(spawnpoint = G_FindCoopStart(playernum)) // find a Co-op start - && !(spawnpoint = G_FindMatchStart(playernum))) // find a DM start - spawnpoint = G_FindCTFStart(playernum); // fallback - } - - //No spawns found. ANYWHERE. - if (!spawnpoint) - { - if (nummapthings) - { - if (playernum == consoleplayer || (splitscreen && playernum == secondarydisplayplayer)) - CONS_Alert(CONS_ERROR, M_GetText("No player spawns found, spawning at the first mapthing!\n")); - spawnpoint = &mapthings[0]; - } - else - { - if (playernum == consoleplayer || (splitscreen && playernum == secondarydisplayplayer)) - CONS_Alert(CONS_ERROR, M_GetText("No player spawns found, spawning at the origin!\n")); - //P_MovePlayerToSpawn handles this fine if the spawnpoint is NULL. - } - } - P_MovePlayerToSpawn(playernum, spawnpoint); - + G_MovePlayerToSpawnOrStarpost(playernum); #ifdef HAVE_BLUA LUAh_PlayerSpawn(&players[playernum]); // Lua hook for player spawning :) #endif +} +void G_MovePlayerToSpawnOrStarpost(INT32 playernum) +{ + if (players[playernum].starposttime) + P_MovePlayerToStarpost(playernum); + else + P_MovePlayerToSpawn(playernum, G_FindMapStart(playernum)); } mapthing_t *G_FindCTFStart(INT32 playernum) @@ -2711,6 +2661,60 @@ mapthing_t *G_FindCoopStart(INT32 playernum) return NULL; } +mapthing_t *G_FindMapStart(INT32 playernum) +{ + mapthing_t *spawnpoint; + + if (!playeringame[playernum]) + return NULL; + + // -- CTF -- + // Order: CTF->DM->Coop + if (gametype == GT_CTF && players[playernum].ctfteam) + { + if (!(spawnpoint = G_FindCTFStart(playernum)) // find a CTF start + && !(spawnpoint = G_FindMatchStart(playernum))) // find a DM start + spawnpoint = G_FindCoopStart(playernum); // fallback + } + + // -- DM/Tag/CTF-spectator/etc -- + // Order: DM->CTF->Coop + else if (gametype == GT_MATCH || gametype == GT_TEAMMATCH || gametype == GT_CTF + || ((gametype == GT_TAG || gametype == GT_HIDEANDSEEK) && !(players[playernum].pflags & PF_TAGIT))) + { + if (!(spawnpoint = G_FindMatchStart(playernum)) // find a DM start + && !(spawnpoint = G_FindCTFStart(playernum))) // find a CTF start + spawnpoint = G_FindCoopStart(playernum); // fallback + } + + // -- Other game modes -- + // Order: Coop->DM->CTF + else + { + if (!(spawnpoint = G_FindCoopStart(playernum)) // find a Co-op start + && !(spawnpoint = G_FindMatchStart(playernum))) // find a DM start + spawnpoint = G_FindCTFStart(playernum); // fallback + } + + //No spawns found. ANYWHERE. + if (!spawnpoint) + { + if (nummapthings) + { + if (playernum == consoleplayer || (splitscreen && playernum == secondarydisplayplayer)) + CONS_Alert(CONS_ERROR, M_GetText("No player spawns found, spawning at the first mapthing!\n")); + spawnpoint = &mapthings[0]; + } + else + { + if (playernum == consoleplayer || (splitscreen && playernum == secondarydisplayplayer)) + CONS_Alert(CONS_ERROR, M_GetText("No player spawns found, spawning at the origin!\n")); + } + } + + return spawnpoint; +} + // Go back through all the projectiles and remove all references to the old // player mobj, replacing them with the new one. void G_ChangePlayerReferences(mobj_t *oldmo, mobj_t *newmo) @@ -2889,7 +2893,7 @@ void G_DoReborn(INT32 playernum) { if (!playeringame[i]) continue; - G_SpawnPlayer(i, (players[i].starposttime)); + G_SpawnPlayer(i); } // restore time in netgame (see also p_setup.c) @@ -2935,7 +2939,7 @@ void G_DoReborn(INT32 playernum) P_RemoveMobj(player->mo); } - G_SpawnPlayer(playernum, (player->starposttime)); + G_SpawnPlayer(playernum); if (oldmo) G_ChangePlayerReferences(oldmo, players[playernum].mo); } diff --git a/src/g_game.h b/src/g_game.h index e7f4a4677..7c4bd2161 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -133,7 +133,9 @@ void G_FreeMapSearch(mapsearchfreq_t *freq, INT32 freqc); mapthing_t *G_FindCTFStart(INT32 playernum); mapthing_t *G_FindMatchStart(INT32 playernum); mapthing_t *G_FindCoopStart(INT32 playernum); -void G_SpawnPlayer(INT32 playernum, boolean starpost); +mapthing_t *G_FindMapStart(INT32 playernum); +void G_MovePlayerToSpawnOrStarpost(INT32 playernum); +void G_SpawnPlayer(INT32 playernum); // Can be called by the startup code or M_Responder. // A normal game starts at map 1, but a warp test can start elsewhere diff --git a/src/p_setup.c b/src/p_setup.c index 673a9024e..b45d3bd80 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3057,11 +3057,11 @@ boolean P_SetupLevel(boolean skipprecip) if (players[i].starposttime) { - G_SpawnPlayer(i, true); + G_SpawnPlayer(i); P_ClearStarPost(players[i].starpostnum); } else - G_SpawnPlayer(i, false); + G_SpawnPlayer(i); } } @@ -3133,7 +3133,7 @@ boolean P_SetupLevel(boolean skipprecip) if (players[playersactive[i]].mo) P_RemoveMobj(players[playersactive[i]].mo); - G_SpawnPlayer(playersactive[i], false); //respawn the lucky player in his dedicated spawn location. + G_SpawnPlayer(playersactive[i]); //respawn the lucky player in his dedicated spawn location. } else CONS_Printf(M_GetText("No player currently available to become IT. Awaiting available players.\n")); From 2527b6c3892ea616fa17b689a9f1a04b67dd0df5 Mon Sep 17 00:00:00 2001 From: Louis-Antoine Date: Wed, 22 Jan 2020 03:20:27 +0100 Subject: [PATCH 74/83] Teleport disconnected players to starpost if they fall in a pit --- src/p_spec.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index dba4e17b5..7547f604f 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -4415,10 +4415,18 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers case 6: // Death Pit (Camera Mod) case 7: // Death Pit (No Camera Mod) if (roversector || P_MobjReadyToTrigger(player->mo, sector)) - P_DamageMobj(player->mo, NULL, NULL, 1, DMG_DEATHPIT); + { + if (player->quittime) + G_MovePlayerToSpawnOrStarpost(player - players); + else + P_DamageMobj(player->mo, NULL, NULL, 1, DMG_DEATHPIT); + } break; case 8: // Instant Kill - P_DamageMobj(player->mo, NULL, NULL, 1, DMG_INSTAKILL); + if (player->quittime) + G_MovePlayerToSpawnOrStarpost(player - players); + else + P_DamageMobj(player->mo, NULL, NULL, 1, DMG_INSTAKILL); break; case 9: // Ring Drainer (Floor Touch) case 10: // Ring Drainer (No Floor Touch) From cfec8609f943c2b7520027e06cd5fa0839e02754 Mon Sep 17 00:00:00 2001 From: Louis-Antoine Date: Wed, 22 Jan 2020 04:01:06 +0100 Subject: [PATCH 75/83] Fix missing declaration --- src/d_clisrv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index fc50177ef..0106d559c 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -77,6 +77,7 @@ char motd[254], server_context[8]; // Message of the Day, Unique Context (even w // Server specific vars UINT8 playernode[MAXPLAYERS]; +char playeraddress[MAXPLAYERS][64]; // Minimum timeout for sending the savegame // The actual timeout will be longer depending on the savegame length From fb28ede66049396d531c1d910646882a037569c4 Mon Sep 17 00:00:00 2001 From: Louis-Antoine Date: Wed, 22 Jan 2020 16:58:57 +0100 Subject: [PATCH 76/83] Rename R_IsPointInSubsector to R_PointInSubsectorOrNull/Nil The old name made it really easy to accidentally read R_IsPointInSubsector as R_PointInSubsector, and anyway it didn't even make sense... --- src/lua_baselib.c | 6 +++--- src/m_cheat.c | 8 ++++---- src/p_mobj.c | 2 +- src/p_user.c | 4 ++-- src/r_main.c | 4 ++-- src/r_main.h | 2 +- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 7a16f3c69..66bd30e32 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -2193,11 +2193,11 @@ static int lib_rPointInSubsector(lua_State *L) return 1; } -static int lib_rIsPointInSubsector(lua_State *L) +static int lib_rPointInSubsectorOrNil(lua_State *L) { fixed_t x = luaL_checkfixed(L, 1); fixed_t y = luaL_checkfixed(L, 2); - subsector_t *sub = R_IsPointInSubsector(x, y); + subsector_t *sub = R_PointInSubsectorOrNull(x, y); //HUDSAFE INLEVEL if (sub) @@ -3141,7 +3141,7 @@ static luaL_Reg lib[] = { {"R_PointToDist",lib_rPointToDist}, {"R_PointToDist2",lib_rPointToDist2}, {"R_PointInSubsector",lib_rPointInSubsector}, - {"R_IsPointInSubsector",lib_rIsPointInSubsector}, + {"R_PointInSubsectorOrNil",lib_rPointInSubsectorOrNil}, // r_things (sprite) {"R_Char2Frame",lib_rChar2Frame}, diff --git a/src/m_cheat.c b/src/m_cheat.c index c284acf3e..980d9fc21 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -452,7 +452,7 @@ void Command_RTeleport_f(void) else inty = 0; - ss = R_IsPointInSubsector(p->mo->x + intx*FRACUNIT, p->mo->y + inty*FRACUNIT); + ss = R_PointInSubsectorOrNull(p->mo->x + intx*FRACUNIT, p->mo->y + inty*FRACUNIT); if (!ss || ss->sector->ceilingheight - ss->sector->floorheight < p->mo->height) { CONS_Alert(CONS_NOTICE, M_GetText("Not a valid location.\n")); @@ -530,7 +530,7 @@ void Command_Teleport_f(void) inty = mt->y<z<sector->ceilingheight - ss->sector->floorheight < p->mo->height) { CONS_Alert(CONS_NOTICE, M_GetText("Spawnpoint not in a valid location.\n")); @@ -597,7 +597,7 @@ void Command_Teleport_f(void) return; } - ss = R_IsPointInSubsector(mo2->x, mo2->y); + ss = R_PointInSubsectorOrNull(mo2->x, mo2->y); if (!ss || ss->sector->ceilingheight - ss->sector->floorheight < p->mo->height) { CONS_Alert(CONS_NOTICE, M_GetText("Starpost not in a valid location.\n")); @@ -653,7 +653,7 @@ void Command_Teleport_f(void) } } - ss = R_IsPointInSubsector(intx, inty); + ss = R_PointInSubsectorOrNull(intx, inty); if (!ss || ss->sector->ceilingheight - ss->sector->floorheight < p->mo->height) { CONS_Alert(CONS_NOTICE, M_GetText("Not a valid location.\n")); diff --git a/src/p_mobj.c b/src/p_mobj.c index a8599ceb5..c4ba9c14f 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11114,7 +11114,7 @@ void P_SpawnPrecipitation(void) x = basex + ((M_RandomKey(MAPBLOCKUNITS<<3)<>3); y = basey + ((M_RandomKey(MAPBLOCKUNITS<<3)<>3); - precipsector = R_IsPointInSubsector(x, y); + precipsector = R_PointInSubsectorOrNull(x, y); // No sector? Stop wasting time, // move on to the next entry in the blockmap diff --git a/src/p_user.c b/src/p_user.c index a1df8a58b..74349e185 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -3160,7 +3160,7 @@ static void P_DoClimbing(player_t *player) platx = P_ReturnThrustX(player->mo, player->mo->angle, player->mo->radius + FixedMul(8*FRACUNIT, player->mo->scale)); platy = P_ReturnThrustY(player->mo, player->mo->angle, player->mo->radius + FixedMul(8*FRACUNIT, player->mo->scale)); - glidesector = R_IsPointInSubsector(player->mo->x + platx, player->mo->y + platy); + glidesector = R_PointInSubsectorOrNull(player->mo->x + platx, player->mo->y + platy); { boolean floorclimb = false; @@ -10235,7 +10235,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall } // move camera down to move under lower ceilings - newsubsec = R_IsPointInSubsector(((mo->x>>FRACBITS) + (thiscam->x>>FRACBITS))<<(FRACBITS-1), ((mo->y>>FRACBITS) + (thiscam->y>>FRACBITS))<<(FRACBITS-1)); + newsubsec = R_PointInSubsectorOrNull(((mo->x>>FRACBITS) + (thiscam->x>>FRACBITS))<<(FRACBITS-1), ((mo->y>>FRACBITS) + (thiscam->y>>FRACBITS))<<(FRACBITS-1)); if (!newsubsec) newsubsec = thiscam->subsector; diff --git a/src/r_main.c b/src/r_main.c index a93cd6f49..f4daac834 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -701,9 +701,9 @@ subsector_t *R_PointInSubsector(fixed_t x, fixed_t y) } // -// R_IsPointInSubsector, same as above but returns 0 if not in subsector +// R_PointInSubsectorOrNull, same as above but returns 0 if not in subsector // -subsector_t *R_IsPointInSubsector(fixed_t x, fixed_t y) +subsector_t *R_PointInSubsectorOrNull(fixed_t x, fixed_t y) { node_t *node; INT32 side, i; diff --git a/src/r_main.h b/src/r_main.h index 3e575fbd7..d72e94973 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -64,7 +64,7 @@ fixed_t R_PointToDist2(fixed_t px2, fixed_t py2, fixed_t px1, fixed_t py1); fixed_t R_ScaleFromGlobalAngle(angle_t visangle); subsector_t *R_PointInSubsector(fixed_t x, fixed_t y); -subsector_t *R_IsPointInSubsector(fixed_t x, fixed_t y); +subsector_t *R_PointInSubsectorOrNull(fixed_t x, fixed_t y); boolean R_DoCulling(line_t *cullheight, line_t *viewcullheight, fixed_t vz, fixed_t bottomh, fixed_t toph); From ce20642fa7597d2a4418d1572894b0b90f1cdb42 Mon Sep 17 00:00:00 2001 From: Louis-Antoine Date: Thu, 23 Jan 2020 18:52:16 +0100 Subject: [PATCH 77/83] Do not protect non-IT players in tag gametypes --- src/p_user.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/p_user.c b/src/p_user.c index b01f702fa..832a6a30e 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -12211,7 +12211,8 @@ void P_PlayerThink(player_t *player) } // IF PLAYER NOT HERE THEN FLASH END IF - if (player->quittime && player->powers[pw_flashing] < flashingtics - 1) + if (player->quittime && player->powers[pw_flashing] < flashingtics - 1 + && !(G_TagGametype() && !(player->pflags & PF_TAGIT)) && !player->gotflag) player->powers[pw_flashing] = flashingtics - 1; // Counters, time dependent power ups. From b0b22b53d6a99f7a40f386e85e580e4de4866cde Mon Sep 17 00:00:00 2001 From: Louis-Antoine Date: Thu, 23 Jan 2020 19:58:13 +0100 Subject: [PATCH 78/83] Ignore disconnected players in tag gametypes Disconnected players do not become IT at round start. If all non-ITs are disconnected, the round ends. If all ITs are disconnected, one of the non-ITs becomes IT, or the round ends if in Hide & Seek. --- src/p_inter.c | 4 ++-- src/p_setup.c | 2 +- src/p_tick.c | 4 ++++ 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/p_inter.c b/src/p_inter.c index 71dcd70a1..8090b7406 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2257,9 +2257,9 @@ void P_CheckSurvivors(void) { if (players[i].spectator) spectators++; - else if (players[i].pflags & PF_TAGIT) + else if ((players[i].pflags & PF_TAGIT) && players[i].quittime < 30 * TICRATE) taggers++; - else if (!(players[i].pflags & PF_GAMETYPEOVER)) + else if (!(players[i].pflags & PF_GAMETYPEOVER) && players[i].quittime < 30 * TICRATE) { survivorarray[survivors] = i; survivors++; diff --git a/src/p_setup.c b/src/p_setup.c index 679060d44..729ee00c2 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3097,7 +3097,7 @@ static void P_InitTagGametype(void) //Also, you'd never have to loop through all 32 players slots to find anything ever again. for (i = 0; i < MAXPLAYERS; i++) { - if (playeringame[i] && !players[i].spectator) + if (playeringame[i] && !(players[i].spectator && players[i].quittime)) { playersactive[realnumplayers] = i; //stores the player's node in the array. realnumplayers++; diff --git a/src/p_tick.c b/src/p_tick.c index 4dd3bb30a..a4b8aa097 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -599,6 +599,10 @@ void P_Ticker(boolean run) if (players[i].quittime) { players[i].quittime++; + + if (players[i].quittime == 30 * TICRATE) + P_CheckSurvivors(); + if (server && players[i].quittime >= FixedMul(cv_rejointimeout.value, 60 * TICRATE)) SendKick(i, KICK_MSG_PLAYER_QUIT); } From ba127008cfcbc861feb146f7fb6706f6421ab8a0 Mon Sep 17 00:00:00 2001 From: Louis-Antoine Date: Thu, 23 Jan 2020 19:59:41 +0100 Subject: [PATCH 79/83] Do not spam player quit net commands --- src/p_tick.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/p_tick.c b/src/p_tick.c index a4b8aa097..348f2557c 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -603,7 +603,8 @@ void P_Ticker(boolean run) if (players[i].quittime == 30 * TICRATE) P_CheckSurvivors(); - if (server && players[i].quittime >= FixedMul(cv_rejointimeout.value, 60 * TICRATE)) + if (server && players[i].quittime >= FixedMul(cv_rejointimeout.value, 60 * TICRATE) + && !(players[i].quittime % TICRATE)) SendKick(i, KICK_MSG_PLAYER_QUIT); } } From 8bd897a269fc26e0894019169356eec777d88c0a Mon Sep 17 00:00:00 2001 From: Louis-Antoine Date: Fri, 24 Jan 2020 19:56:57 +0100 Subject: [PATCH 80/83] Be silent when "kicking" a disconnected player This lets the host manually remove a body if they want, without polluting the chat with redundant messages. --- src/d_clisrv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 0106d559c..841a0e322 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2918,7 +2918,8 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) switch (msg) { case KICK_MSG_GO_AWAY: - HU_AddChatText(va("\x82*%s has been kicked (Go away)", player_names[pnum]), false); + if (!players[pnum].quittime) + HU_AddChatText(va("\x82*%s has been kicked (Go away)", player_names[pnum]), false); kickreason = KR_KICK; break; case KICK_MSG_PING_HIGH: From 59ed381fc08edd6888967e27545c485ab670210b Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 24 Jan 2020 16:38:46 -0800 Subject: [PATCH 81/83] Credit Tatsuru, he's done a bit --- src/f_finale.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/f_finale.c b/src/f_finale.c index 87e41df78..99ff586f4 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1165,6 +1165,7 @@ static const char *credits[] = { "Tasos \"tatokis\" Sahanidis", // Corrected C FixedMul, making 64-bit builds netplay compatible "Wessel \"sphere\" Smit", "Ben \"Cue\" Woodford", + "Ikaro \"Tatsuru\" Vinhas", // Git contributors with 5+ approved merges of substantive quality, // or contributors with at least one groundbreaking merge, may be named. // Everyone else is acknowledged under "Special Thanks > SRB2 Community Contributors". From c9bc3837f9b05be6e66dc204d98cd511bbf5a475 Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 24 Jan 2020 16:44:53 -0800 Subject: [PATCH 82/83] Signed is unsigned, cool --- src/p_tick.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_tick.c b/src/p_tick.c index 348f2557c..0b30ff42d 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -603,7 +603,7 @@ void P_Ticker(boolean run) if (players[i].quittime == 30 * TICRATE) P_CheckSurvivors(); - if (server && players[i].quittime >= FixedMul(cv_rejointimeout.value, 60 * TICRATE) + if (server && players[i].quittime >= (tic_t)FixedMul(cv_rejointimeout.value, 60 * TICRATE) && !(players[i].quittime % TICRATE)) SendKick(i, KICK_MSG_PLAYER_QUIT); } From d30b48cfd1b74f7f2a60a1e1f2a7347dc4aaaf11 Mon Sep 17 00:00:00 2001 From: Louis-Antoine Date: Sat, 25 Jan 2020 14:04:16 +0100 Subject: [PATCH 83/83] Fix lava removing fire shield --- src/p_mobj.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index c4ba9c14f..e6d84086c 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -3396,7 +3396,7 @@ void P_MobjCheckWater(mobj_t *mobj) if (!((p->powers[pw_super]) || (p->powers[pw_invulnerability]))) { boolean electric = !!(p->powers[pw_shield] & SH_PROTECTELECTRIC); - if (electric || ((p->powers[pw_shield] & SH_PROTECTFIRE) && !(p->powers[pw_shield] & SH_PROTECTWATER))) + if (electric || ((p->powers[pw_shield] & SH_PROTECTFIRE) && !(p->powers[pw_shield] & SH_PROTECTWATER) && !(mobj->eflags & MFE_TOUCHLAVA))) { // Water removes electric and non-water fire shields... P_FlashPal(p, electric