diff --git a/CMakeLists.txt b/CMakeLists.txt index b70221859..96e32a06d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.0) # DO NOT CHANGE THIS SRB2 STRING! Some variable names depend on this string. # Version change is fine. project(SRB2 - VERSION 2.1.24 + VERSION 2.1.25 LANGUAGES C) if(${PROJECT_SOURCE_DIR} MATCHES ${PROJECT_BINARY_DIR}) diff --git a/appveyor.yml b/appveyor.yml index b37bd1a65..d58976fd5 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 2.1.24.{branch}-{build} +version: 2.1.25.{branch}-{build} os: MinGW environment: diff --git a/src/config.h.in b/src/config.h.in index 1e6a7f514..63d24a3be 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -35,7 +35,7 @@ #define ASSET_HASH_PLAYER_DTA "cfca0f1c73023cbbd8f844f45480f799" #define ASSET_HASH_RINGS_DTA "85901ad4bf94637e5753d2ac2c03ea26" #ifdef USE_PATCH_DTA -#define ASSET_HASH_PATCH_DTA "b04fd9624bfd94dc96dcf4f400f7deb4" +#define ASSET_HASH_PATCH_DTA "636BD1C9269629AEAC2C3C184754D471" #endif #endif diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 274fe398a..28d327ece 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -44,6 +44,7 @@ #include "lzf.h" #include "lua_script.h" #include "lua_hook.h" +#include "md5.h" #ifdef CLIENT_LOADINGSCREEN // cl loading screen @@ -116,6 +117,9 @@ static UINT8 resynch_local_inprogress = false; // WE are desynched and getting p static UINT8 player_joining = false; UINT8 hu_resynching = 0; +UINT8 adminpassmd5[16]; +boolean adminpasswordset = false; + // Client specific static ticcmd_t localcmds; static ticcmd_t localcmds2; @@ -3760,6 +3764,7 @@ static void HandlePacketFromPlayer(SINT8 node) XBOXSTATIC INT32 netconsole; XBOXSTATIC tic_t realend, realstart; XBOXSTATIC UINT8 *pak, *txtpak, numtxtpak; + XBOXSTATIC UINT8 finalmd5[16];/* Well, it's the cool thing to do? */ FILESTAMP txtpak = NULL; @@ -3958,6 +3963,32 @@ FILESTAMP textcmd[0] += (UINT8)netbuffer->u.textcmd[0]; } break; + case PT_LOGIN: + if (client) + break; + +#ifndef NOMD5 + if (doomcom->datalength < 16)/* ignore partial sends */ + break; + + if (!adminpasswordset) + { + CONS_Printf(M_GetText("Password from %s failed (no password set).\n"), player_names[netconsole]); + break; + } + + // Do the final pass to compare with the sent md5 + D_MD5PasswordPass(adminpassmd5, 16, va("PNUM%02d", netconsole), &finalmd5); + + if (!memcmp(netbuffer->u.md5sum, finalmd5, 16)) + { + CONS_Printf(M_GetText("%s passed authentication.\n"), player_names[netconsole]); + COM_BufInsertText(va("promote %d\n", netconsole)); // do this immediately + } + else + CONS_Printf(M_GetText("Password from %s failed.\n"), player_names[netconsole]); +#endif + break; case PT_NODETIMEOUT: case PT_CLIENTQUIT: if (client) @@ -4841,3 +4872,29 @@ tic_t GetLag(INT32 node) { return gametic - nettics[node]; } + +void D_MD5PasswordPass(const UINT8 *buffer, size_t len, const char *salt, void *dest) +{ +#ifdef NOMD5 + (void)buffer; + (void)len; + (void)salt; + memset(dest, 0, 16); +#else + XBOXSTATIC char tmpbuf[256]; + const size_t sl = strlen(salt); + + if (len > 256-sl) + len = 256-sl; + + memcpy(tmpbuf, buffer, len); + memmove(&tmpbuf[len], salt, sl); + //strcpy(&tmpbuf[len], salt); + len += strlen(salt); + if (len < 256) + memset(&tmpbuf[len],0,256-len); + + // Yes, we intentionally md5 the ENTIRE buffer regardless of size... + md5_buffer(tmpbuf, 256, dest); +#endif +} diff --git a/src/d_clisrv.h b/src/d_clisrv.h index 8443b3fc0..c005f3f9a 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -70,6 +70,9 @@ typedef enum PT_NODETIMEOUT, // Packet sent to self if the connection times out. PT_RESYNCHING, // Packet sent to resync players. // Blocks game advance until synched. + + PT_LOGIN, // Login attempt from the client. + #ifdef NEWPING PT_PING, // Packet sent to tell clients the other client's latency to server. #endif @@ -398,6 +401,7 @@ typedef struct UINT8 textcmd[MAXTEXTCMD+1]; // 66049 bytes (wut??? 64k??? More like 257 bytes...) filetx_pak filetxpak; // 139 bytes clientconfig_pak clientcfg; // 136 bytes + UINT8 md5sum[16]; serverinfo_pak serverinfo; // 1024 bytes serverrefuse_pak serverrefuse; // 65025 bytes (somehow I feel like those values are garbage...) askinfo_pak askinfo; // 61 bytes @@ -526,5 +530,10 @@ void D_ResetTiccmds(void); tic_t GetLag(INT32 node); UINT8 GetFreeXCmdSize(void); +void D_MD5PasswordPass(const UINT8 *buffer, size_t len, const char *salt, void *dest); + extern UINT8 hu_resynching; + +extern UINT8 adminpassmd5[16]; +extern boolean adminpasswordset; #endif diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 998eef05d..cc9127af0 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -34,18 +34,19 @@ #include "p_spec.h" #include "m_cheat.h" #include "d_clisrv.h" +#include "d_net.h" #include "v_video.h" #include "d_main.h" #include "m_random.h" #include "f_finale.h" #include "filesrch.h" #include "mserv.h" -#include "md5.h" #include "z_zone.h" #include "lua_script.h" #include "lua_hook.h" #include "m_cond.h" #include "m_anigif.h" +#include "md5.h" #ifdef NETGAME_DEVMODE #define CV_RESTRICT CV_NETVAR @@ -143,7 +144,6 @@ static void Command_Clearscores_f(void); // Remote Administration static void Command_Changepassword_f(void); static void Command_Login_f(void); -static void Got_Login(UINT8 **cp, INT32 playernum); static void Got_Verification(UINT8 **cp, INT32 playernum); static void Got_Removal(UINT8 **cp, INT32 playernum); static void Command_Verify_f(void); @@ -437,7 +437,6 @@ void D_RegisterServerCommands(void) // Remote Administration COM_AddCommand("password", Command_Changepassword_f); - RegisterNetXCmd(XD_LOGIN, Got_Login); COM_AddCommand("login", Command_Login_f); // useful in dedicated to kick off remote admin COM_AddCommand("promote", Command_Verify_f); RegisterNetXCmd(XD_VERIFIED, Got_Verification); @@ -2652,35 +2651,7 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum) // Attempts to make password system a little sane without // rewriting the entire goddamn XD_file system // -#include "md5.h" -static void D_MD5PasswordPass(const UINT8 *buffer, size_t len, const char *salt, void *dest) -{ -#ifdef NOMD5 - (void)buffer; - (void)len; - (void)salt; - memset(dest, 0, 16); -#else - XBOXSTATIC char tmpbuf[256]; - const size_t sl = strlen(salt); - - if (len > 256-sl) - len = 256-sl; - memcpy(tmpbuf, buffer, len); - memmove(&tmpbuf[len], salt, sl); - //strcpy(&tmpbuf[len], salt); - len += strlen(salt); - if (len < 256) - memset(&tmpbuf[len],0,256-len); - - // Yes, we intentionally md5 the ENTIRE buffer regardless of size... - md5_buffer(tmpbuf, 256, dest); -#endif -} - #define BASESALT "basepasswordstorage" -static UINT8 adminpassmd5[16]; -static boolean adminpasswordset = false; void D_SetPassword(const char *pw) { @@ -2718,7 +2689,6 @@ static void Command_Login_f(void) // If we have no MD5 support then completely disable XD_LOGIN responses for security. CONS_Alert(CONS_NOTICE, "Remote administration commands are not supported in this build.\n"); #else - XBOXSTATIC UINT8 finalmd5[16]; const char *pw; if (!netgame) @@ -2738,47 +2708,15 @@ static void Command_Login_f(void) pw = COM_Argv(1); // Do the base pass to get what the server has (or should?) - D_MD5PasswordPass((const UINT8 *)pw, strlen(pw), BASESALT, &finalmd5); + D_MD5PasswordPass((const UINT8 *)pw, strlen(pw), BASESALT, &netbuffer->u.md5sum); // Do the final pass to get the comparison the server will come up with - D_MD5PasswordPass(finalmd5, 16, va("PNUM%02d", consoleplayer), &finalmd5); + D_MD5PasswordPass(netbuffer->u.md5sum, 16, va("PNUM%02d", consoleplayer), &netbuffer->u.md5sum); CONS_Printf(M_GetText("Sending login... (Notice only given if password is correct.)\n")); - SendNetXCmd(XD_LOGIN, finalmd5, 16); -#endif -} - -static void Got_Login(UINT8 **cp, INT32 playernum) -{ -#ifdef NOMD5 - // If we have no MD5 support then completely disable XD_LOGIN responses for security. - (void)cp; - (void)playernum; -#else - UINT8 sentmd5[16], finalmd5[16]; - - READMEM(*cp, sentmd5, 16); - - if (client) - return; - - if (!adminpasswordset) - { - CONS_Printf(M_GetText("Password from %s failed (no password set).\n"), player_names[playernum]); - return; - } - - // Do the final pass to compare with the sent md5 - D_MD5PasswordPass(adminpassmd5, 16, va("PNUM%02d", playernum), &finalmd5); - - if (!memcmp(sentmd5, finalmd5, 16)) - { - CONS_Printf(M_GetText("%s passed authentication.\n"), player_names[playernum]); - COM_BufInsertText(va("promote %d\n", playernum)); // do this immediately - } - else - CONS_Printf(M_GetText("Password from %s failed.\n"), player_names[playernum]); + netbuffer->packettype = PT_LOGIN; + HSendPacket(servernode, true, 0, 16); #endif } @@ -4000,7 +3938,7 @@ static void Command_ExitLevel_f(void) CONS_Printf(M_GetText("This only works in a netgame.\n")); else if (!(server || (IsPlayerAdmin(consoleplayer)))) CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n")); - else if (gamestate != GS_LEVEL || demoplayback) + else if (( gamestate != GS_LEVEL && gamestate != GS_CREDITS ) || demoplayback) CONS_Printf(M_GetText("You must be in a level to use this.\n")); else SendNetXCmd(XD_EXITLEVEL, NULL, 0); diff --git a/src/d_netcmd.h b/src/d_netcmd.h index b82065c82..244693356 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -125,8 +125,8 @@ typedef enum XD_ADDPLAYER, // 10 XD_TEAMCHANGE, // 11 XD_CLEARSCORES, // 12 - XD_LOGIN, // 13 - XD_VERIFIED, // 14 + // UNUSED 13 (Because I don't want to change these comments) + XD_VERIFIED = 14,//14 XD_RANDOMSEED, // 15 XD_RUNSOC, // 16 XD_REQADDFILE, // 17 diff --git a/src/doomdef.h b/src/doomdef.h index 6b6afbf1b..1c034f5f7 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -150,9 +150,9 @@ extern FILE *logstream; // we use comprevision and compbranch instead. #else #define VERSION 201 // Game version -#define SUBVERSION 24 // more precise version number -#define VERSIONSTRING "v2.1.24" -#define VERSIONSTRINGW L"v2.1.24" +#define SUBVERSION 25 // more precise version number +#define VERSIONSTRING "v2.1.25" +#define VERSIONSTRINGW L"v2.1.25" // Hey! If you change this, add 1 to the MODVERSION below! // Otherwise we can't force updates! #endif @@ -217,7 +217,7 @@ extern FILE *logstream; // it's only for detection of the version the player is using so the MS can alert them of an update. // Only set it higher, not lower, obviously. // Note that we use this to help keep internal testing in check; this is why v2.1.0 is not version "1". -#define MODVERSION 29 +#define MODVERSION 30 // To version config.cfg, MAJOREXECVERSION is set equal to MODVERSION automatically. // Increment MINOREXECVERSION whenever a config change is needed that does not correspond diff --git a/src/doomstat.h b/src/doomstat.h index 8050a1beb..7f8b5fd6e 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -131,6 +131,7 @@ extern UINT8 skincolor_redteam, skincolor_blueteam, skincolor_redring, skincolor extern tic_t countdowntimer; extern boolean countdowntimeup; +extern boolean exitfadestarted; typedef struct { diff --git a/src/g_game.c b/src/g_game.c index f9477f91e..c61056f35 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -15,6 +15,7 @@ #include "console.h" #include "d_main.h" #include "d_player.h" +#include "d_clisrv.h" #include "f_finale.h" #include "p_setup.h" #include "p_saveg.h" @@ -130,6 +131,7 @@ UINT8 skincolor_bluering = SKINCOLOR_STEELBLUE; tic_t countdowntimer = 0; boolean countdowntimeup = false; +boolean exitfadestarted = false; cutscene_t *cutscenes[128]; @@ -1874,7 +1876,9 @@ boolean G_Responder(event_t *ev) if (F_CreditResponder(ev)) { - F_StartGameEvaluation(); + // Skip credits for everyone + if (!netgame || server || IsPlayerAdmin(consoleplayer)) + SendNetXCmd(XD_EXITLEVEL, NULL, 0); return true; } } @@ -2696,6 +2700,10 @@ void G_ExitLevel(void) // Remove CEcho text on round end. HU_ClearCEcho(); } + else if (gamestate == GS_CREDITS) + { + F_StartGameEvaluation(); + } } // See also the enum GameType in doomstat.h @@ -3694,7 +3702,7 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean { // Clear a bunch of variables tokenlist = token = sstimer = redscore = bluescore = lastmap = 0; - countdown = countdown2 = 0; + countdown = countdown2 = exitfadestarted = 0; for (i = 0; i < MAXPLAYERS; i++) { diff --git a/src/p_map.c b/src/p_map.c index 95ad02588..3ce82b4da 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -3345,6 +3345,7 @@ static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush) boolean P_CheckSector(sector_t *sector, boolean crunch) { msecnode_t *n; + size_t i; nofit = false; crushchange = crunch; @@ -3359,9 +3360,57 @@ boolean P_CheckSector(sector_t *sector, boolean crunch) // First, let's see if anything will keep it from crushing. + + // Sal: This stupid function chain is required to fix polyobjects not being able to crush. + // Monster Iestyn: don't use P_CheckSector actually just look for objects in the blockmap instead + validcount++; + + for (i = 0; i < sector->linecount; i++) + { + if (sector->lines[i]->polyobj) + { + polyobj_t *po = sector->lines[i]->polyobj; + if (po->validcount == validcount) + continue; // skip if already checked + if (!(po->flags & POF_SOLID)) + continue; + if (po->lines[0]->backsector == sector) // Make sure you're currently checking the control sector + { + INT32 x, y; + po->validcount = validcount; + + for (y = po->blockbox[BOXBOTTOM]; y <= po->blockbox[BOXTOP]; ++y) + { + for (x = po->blockbox[BOXLEFT]; x <= po->blockbox[BOXRIGHT]; ++x) + { + mobj_t *mo; + + if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight) + continue; + + mo = blocklinks[y * bmapwidth + x]; + + for (; mo; mo = mo->bnext) + { + // Monster Iestyn: do we need to check if a mobj has already been checked? ...probably not I suspect + + if (!P_MobjInsidePolyobj(po, mo)) + continue; + + if (!PIT_ChangeSector(mo, false)) + { + nofit = true; + return nofit; + } + } + } + } + } + } + } + if (sector->numattached) { - size_t i; sector_t *sec; for (i = 0; i < sector->numattached; i++) { @@ -3421,9 +3470,53 @@ boolean P_CheckSector(sector_t *sector, boolean crunch) } while (n); // repeat from scratch until all things left are marked valid // Nothing blocked us, so lets crush for real! + + // Sal: This stupid function chain is required to fix polyobjects not being able to crush. + // Monster Iestyn: don't use P_CheckSector actually just look for objects in the blockmap instead + validcount++; + + for (i = 0; i < sector->linecount; i++) + { + if (sector->lines[i]->polyobj) + { + polyobj_t *po = sector->lines[i]->polyobj; + if (po->validcount == validcount) + continue; // skip if already checked + if (!(po->flags & POF_SOLID)) + continue; + if (po->lines[0]->backsector == sector) // Make sure you're currently checking the control sector + { + INT32 x, y; + po->validcount = validcount; + + for (y = po->blockbox[BOXBOTTOM]; y <= po->blockbox[BOXTOP]; ++y) + { + for (x = po->blockbox[BOXLEFT]; x <= po->blockbox[BOXRIGHT]; ++x) + { + mobj_t *mo; + + if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight) + continue; + + mo = blocklinks[y * bmapwidth + x]; + + for (; mo; mo = mo->bnext) + { + // Monster Iestyn: do we need to check if a mobj has already been checked? ...probably not I suspect + + if (!P_MobjInsidePolyobj(po, mo)) + continue; + + PIT_ChangeSector(mo, true); + return nofit; + } + } + } + } + } + } if (sector->numattached) { - size_t i; sector_t *sec; for (i = 0; i < sector->numattached; i++) { diff --git a/src/p_maputl.c b/src/p_maputl.c index 1be57399c..5368c137e 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -418,10 +418,6 @@ void P_CameraLineOpening(line_t *linedef) if (front->ffloors || back->ffloors) { ffloor_t *rover; - fixed_t highestceiling = highceiling; - fixed_t lowestceiling = opentop; - fixed_t highestfloor = openbottom; - fixed_t lowestfloor = lowfloor; fixed_t delta1, delta2; // Check for frontsector's fake floors @@ -437,15 +433,15 @@ void P_CameraLineOpening(line_t *linedef) delta1 = abs(mapcampointer->z - (bottomheight + ((topheight - bottomheight)/2))); delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2))); - if (bottomheight < lowestceiling && delta1 >= delta2) - lowestceiling = bottomheight; - else if (bottomheight < highestceiling && delta1 >= delta2) - highestceiling = bottomheight; + if (bottomheight < opentop && delta1 >= delta2) + opentop = bottomheight; + else if (bottomheight < highceiling && delta1 >= delta2) + highceiling = bottomheight; - if (topheight > highestfloor && delta1 < delta2) - highestfloor = topheight; - else if (topheight > lowestfloor && delta1 < delta2) - lowestfloor = topheight; + if (topheight > openbottom && delta1 < delta2) + openbottom = topheight; + else if (topheight > lowfloor && delta1 < delta2) + lowfloor = topheight; } // Check for backsectors fake floors @@ -461,28 +457,16 @@ void P_CameraLineOpening(line_t *linedef) delta1 = abs(mapcampointer->z - (bottomheight + ((topheight - bottomheight)/2))); delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2))); - if (bottomheight < lowestceiling && delta1 >= delta2) - lowestceiling = bottomheight; - else if (bottomheight < highestceiling && delta1 >= delta2) - highestceiling = bottomheight; + if (bottomheight < opentop && delta1 >= delta2) + opentop = bottomheight; + else if (bottomheight < highceiling && delta1 >= delta2) + highceiling = bottomheight; - if (topheight > highestfloor && delta1 < delta2) - highestfloor = topheight; - else if (topheight > lowestfloor && delta1 < delta2) - lowestfloor = topheight; + if (topheight > openbottom && delta1 < delta2) + openbottom = topheight; + else if (topheight > lowfloor && delta1 < delta2) + lowfloor = topheight; } - - if (highestceiling < highceiling) - highceiling = highestceiling; - - if (highestfloor > openbottom) - openbottom = highestfloor; - - if (lowestceiling < opentop) - opentop = lowestceiling; - - if (lowestfloor > lowfloor) - lowfloor = lowestfloor; } openrange = opentop - openbottom; return; @@ -500,23 +484,26 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) return; } - // Treat polyobjects kind of like 3D Floors -#ifdef POLYOBJECTS - if (linedef->polyobj && (linedef->polyobj->flags & POF_TESTHEIGHT)) - { - front = linedef->frontsector; - back = linedef->frontsector; - } - else -#endif - { - front = linedef->frontsector; - back = linedef->backsector; - } + front = linedef->frontsector; + back = linedef->backsector; I_Assert(front != NULL); I_Assert(back != NULL); +#ifdef POLYOBJECTS + if (linedef->polyobj) + { + // set these defaults so that polyobjects don't interfere with collision above or below them + opentop = INT32_MAX; + openbottom = INT32_MIN; + highceiling = INT32_MIN; + lowfloor = INT32_MAX; +#ifdef ESLOPE + opentopslope = openbottomslope = NULL; +#endif + } + else +#endif { // Set open and high/low values here fixed_t frontheight, backheight; @@ -622,25 +609,49 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) } } } - - // Check for fake floors in the sector. - if (front->ffloors || back->ffloors #ifdef POLYOBJECTS - || linedef->polyobj + if (linedef->polyobj) + { + // Treat polyobj's backsector like a 3D Floor + if (linedef->polyobj->flags & POF_TESTHEIGHT) + { + const sector_t *polysec = linedef->backsector; + fixed_t polytop, polybottom; + fixed_t delta1, delta2; + + if (linedef->polyobj->flags & POF_CLIPPLANES) + { + polytop = polysec->ceilingheight; + polybottom = polysec->floorheight; + } + else + { + polytop = INT32_MAX; + polybottom = INT32_MIN; + } + + delta1 = abs(mobj->z - (polybottom + ((polytop - polybottom)/2))); + delta2 = abs(thingtop - (polybottom + ((polytop - polybottom)/2))); + + if (polybottom < opentop && delta1 >= delta2) + opentop = polybottom; + else if (polybottom < highceiling && delta1 >= delta2) + highceiling = polybottom; + + if (polytop > openbottom && delta1 < delta2) + openbottom = polytop; + else if (polytop > lowfloor && delta1 < delta2) + lowfloor = polytop; + } + // otherwise don't do anything special, pretend there's nothing else there + } + else #endif - ) + // Check for fake floors in the sector. + if (front->ffloors || back->ffloors) { ffloor_t *rover; - - fixed_t highestceiling = highceiling; - fixed_t lowestceiling = opentop; - fixed_t highestfloor = openbottom; - fixed_t lowestfloor = lowfloor; fixed_t delta1, delta2; -#ifdef ESLOPE - pslope_t *ceilingslope = opentopslope; - pslope_t *floorslope = openbottomslope; -#endif // Check for frontsector's fake floors for (rover = front->ffloors; rover; rover = rover->next) @@ -663,26 +674,26 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if (delta1 >= delta2 && !(rover->flags & FF_PLATFORM)) // thing is below FOF { - if (bottomheight < lowestceiling) { - lowestceiling = bottomheight; + if (bottomheight < opentop) { + opentop = bottomheight; #ifdef ESLOPE - ceilingslope = *rover->b_slope; + opentopslope = *rover->b_slope; #endif } - else if (bottomheight < highestceiling) - highestceiling = bottomheight; + else if (bottomheight < highceiling) + highceiling = bottomheight; } if (delta1 < delta2 && !(rover->flags & FF_REVERSEPLATFORM)) // thing is above FOF { - if (topheight > highestfloor) { - highestfloor = topheight; + if (topheight > openbottom) { + openbottom = topheight; #ifdef ESLOPE - floorslope = *rover->t_slope; + openbottomslope = *rover->t_slope; #endif } - else if (topheight > lowestfloor) - lowestfloor = topheight; + else if (topheight > lowfloor) + lowfloor = topheight; } } @@ -707,75 +718,28 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if (delta1 >= delta2 && !(rover->flags & FF_PLATFORM)) // thing is below FOF { - if (bottomheight < lowestceiling) { - lowestceiling = bottomheight; + if (bottomheight < opentop) { + opentop = bottomheight; #ifdef ESLOPE - ceilingslope = *rover->b_slope; + opentopslope = *rover->b_slope; #endif } - else if (bottomheight < highestceiling) - highestceiling = bottomheight; + else if (bottomheight < highceiling) + highceiling = bottomheight; } if (delta1 < delta2 && !(rover->flags & FF_REVERSEPLATFORM)) // thing is above FOF { - if (topheight > highestfloor) { - highestfloor = topheight; + if (topheight > openbottom) { + openbottom = topheight; #ifdef ESLOPE - floorslope = *rover->t_slope; + openbottomslope = *rover->t_slope; #endif } - else if (topheight > lowestfloor) - lowestfloor = topheight; + else if (topheight > lowfloor) + lowfloor = topheight; } } - -#ifdef POLYOBJECTS - // Treat polyobj's backsector like a 3D Floor - if (linedef->polyobj && (linedef->polyobj->flags & POF_TESTHEIGHT)) - { - const sector_t *polysec = linedef->backsector; - - delta1 = abs(mobj->z - (polysec->floorheight + ((polysec->ceilingheight - polysec->floorheight)/2))); - delta2 = abs(thingtop - (polysec->floorheight + ((polysec->ceilingheight - polysec->floorheight)/2))); - if (polysec->floorheight < lowestceiling && delta1 >= delta2) { - lowestceiling = polysec->floorheight; -#ifdef ESLOPE - ceilingslope = NULL; -#endif - } - else if (polysec->floorheight < highestceiling && delta1 >= delta2) - highestceiling = polysec->floorheight; - - if (polysec->ceilingheight > highestfloor && delta1 < delta2) { - highestfloor = polysec->ceilingheight; -#ifdef ESLOPE - floorslope = NULL; -#endif - } - else if (polysec->ceilingheight > lowestfloor && delta1 < delta2) - lowestfloor = polysec->ceilingheight; - } -#endif - if (highestceiling < highceiling) - highceiling = highestceiling; - - if (highestfloor > openbottom) { - openbottom = highestfloor; -#ifdef ESLOPE - openbottomslope = floorslope; -#endif - } - - if (lowestceiling < opentop) { - opentop = lowestceiling; -#ifdef ESLOPE - opentopslope = ceilingslope; -#endif - } - - if (lowestfloor > lowfloor) - lowfloor = lowestfloor; } } diff --git a/src/p_mobj.c b/src/p_mobj.c index 850ec2987..e2543f553 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -6033,7 +6033,7 @@ void P_RunOverlays(void) { angle_t viewingangle; - if (players[displayplayer].awayviewtics) + if (players[displayplayer].awayviewtics && players[displayplayer].awayviewmobj != NULL && !P_MobjWasRemoved(players[displayplayer].awayviewmobj)) viewingangle = R_PointToAngle2(mo->target->x, mo->target->y, players[displayplayer].awayviewmobj->x, players[displayplayer].awayviewmobj->y); else if (!camera.chase && players[displayplayer].mo) viewingangle = R_PointToAngle2(mo->target->x, mo->target->y, players[displayplayer].mo->x, players[displayplayer].mo->y); diff --git a/src/p_polyobj.c b/src/p_polyobj.c index 82c57c85b..ba01ee442 100644 --- a/src/p_polyobj.c +++ b/src/p_polyobj.c @@ -1860,7 +1860,8 @@ void T_PolyObjWaypoint(polywaypoint_t *th) po->lines[0]->backsector->floorheight = target->z - amtz; po->lines[0]->backsector->ceilingheight = target->z + amtz; // Sal: Remember to check your sectors! - P_CheckSector(po->lines[0]->frontsector, (boolean)(po->damage)); + // Monster Iestyn: we only need to bother with the back sector, now that P_CheckSector automatically checks the blockmap + // updating objects in the front one too just added teleporting to ground bugs P_CheckSector(po->lines[0]->backsector, (boolean)(po->damage)); // Apply action to mirroring polyobjects as well start = 0; @@ -1874,7 +1875,8 @@ void T_PolyObjWaypoint(polywaypoint_t *th) po->lines[0]->backsector->floorheight += diffz; // move up/down by same amount as the parent did po->lines[0]->backsector->ceilingheight += diffz; // Sal: Remember to check your sectors! - P_CheckSector(po->lines[0]->frontsector, (boolean)(po->damage)); + // Monster Iestyn: we only need to bother with the back sector, now that P_CheckSector automatically checks the blockmap + // updating objects in the front one too just added teleporting to ground bugs P_CheckSector(po->lines[0]->backsector, (boolean)(po->damage)); } @@ -2037,8 +2039,9 @@ void T_PolyObjWaypoint(polywaypoint_t *th) po->lines[0]->backsector->floorheight += momz; po->lines[0]->backsector->ceilingheight += momz; // Sal: Remember to check your sectors! - P_CheckSector(po->lines[0]->frontsector, (boolean)(po->damage)); // frontsector is NEEDED for crushing - P_CheckSector(po->lines[0]->backsector, (boolean)(po->damage)); // backsector may not be necessary, but just in case + // Monster Iestyn: we only need to bother with the back sector, now that P_CheckSector automatically checks the blockmap + // updating objects in the front one too just added teleporting to ground bugs + P_CheckSector(po->lines[0]->backsector, (boolean)(po->damage)); // Apply action to mirroring polyobjects as well start = 0; @@ -2052,7 +2055,8 @@ void T_PolyObjWaypoint(polywaypoint_t *th) po->lines[0]->backsector->floorheight += momz; po->lines[0]->backsector->ceilingheight += momz; // Sal: Remember to check your sectors! - P_CheckSector(po->lines[0]->frontsector, (boolean)(po->damage)); + // Monster Iestyn: we only need to bother with the back sector, now that P_CheckSector automatically checks the blockmap + // updating objects in the front one too just added teleporting to ground bugs P_CheckSector(po->lines[0]->backsector, (boolean)(po->damage)); } } diff --git a/src/p_setup.c b/src/p_setup.c index 033e99f10..b2636c350 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2311,7 +2311,7 @@ static void P_LevelInitStuff(void) players[i].lives = cv_startinglives.value; } - players[i].realtime = countdown = countdown2 = 0; + players[i].realtime = countdown = countdown2 = exitfadestarted = 0; players[i].gotcontinue = false; diff --git a/src/p_slopes.c b/src/p_slopes.c index 4e12b104f..19d0bbbb7 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -584,23 +584,28 @@ static pslope_t *P_NewVertexSlope(INT16 tag1, INT16 tag2, INT16 tag3, UINT8 flag // void P_CopySectorSlope(line_t *line) { - sector_t *fsec = line->frontsector; - int i, special = line->special; + sector_t *fsec = line->frontsector; + int i, special = line->special; - // Check for copy linedefs - for(i = -1; (i = P_FindSectorFromLineTag(line, i)) >= 0;) - { - sector_t *srcsec = sectors + i; + // Check for copy linedefs + for (i = -1; (i = P_FindSectorFromLineTag(line, i)) >= 0;) + { + sector_t *srcsec = sectors + i; - if((special - 719) & 1 && !fsec->f_slope && srcsec->f_slope) - fsec->f_slope = srcsec->f_slope; //P_CopySlope(srcsec->f_slope); - if((special - 719) & 2 && !fsec->c_slope && srcsec->c_slope) - fsec->c_slope = srcsec->c_slope; //P_CopySlope(srcsec->c_slope); - } + if ((special - 719) & 1 && !fsec->f_slope && srcsec->f_slope) + fsec->f_slope = srcsec->f_slope; //P_CopySlope(srcsec->f_slope); + if ((special - 719) & 2 && !fsec->c_slope && srcsec->c_slope) + fsec->c_slope = srcsec->c_slope; //P_CopySlope(srcsec->c_slope); + } - fsec->hasslope = true; + fsec->hasslope = true; - line->special = 0; // Linedef was use to set slopes, it finished its job, so now make it a normal linedef + // if this is an FOF control sector, make sure any target sectors also are marked as having slopes + if (fsec->numattached) + for (i = 0; i < (int)fsec->numattached; i++) + sectors[fsec->attached[i]].hasslope = true; + + line->special = 0; // Linedef was use to set slopes, it finished its job, so now make it a normal linedef } // diff --git a/src/p_spec.c b/src/p_spec.c index f3be86ee1..d4ead74fe 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -4973,6 +4973,10 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, f // Add slopes ffloor->t_slope = &sec2->c_slope; ffloor->b_slope = &sec2->f_slope; + // mark the target sector as having slopes, if the FOF has any of its own + // (this fixes FOF slopes glitching initially at level load in software mode) + if (sec2->hasslope) + sec->hasslope = true; #endif if ((flags & FF_SOLID) && (master->flags & ML_EFFECT1)) // Block player only diff --git a/src/p_user.c b/src/p_user.c index f04386fec..3710e87f1 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8741,14 +8741,8 @@ void P_PlayerThink(player_t *player) if (player->flashcount) player->flashcount--; - // Re-fixed by Jimita (11-12-2018) - if (player->awayviewtics) - { + if (player->awayviewtics && player->awayviewtics != -1) player->awayviewtics--; - if (!player->awayviewtics) - player->awayviewtics = -1; - // The timer might've reached zero, but we'll run the remote view camera anyway by setting it to -1. - } /// \note do this in the cheat code if (player->pflags & PF_NOCLIP) @@ -8824,6 +8818,48 @@ void P_PlayerThink(player_t *player) if (player->exiting && countdown2) player->exiting = 5; + // The following code is disabled for now as this causes the game to freeze sometimes + // Monster Iestyn -- 16/08/19 +#if 0 + // Same check as below, just at 1 second before + // so we can fade music + if (!exitfadestarted && + player->exiting > 0 && player->exiting <= 1*TICRATE && + (!multiplayer || gametype == GT_COOP ? !mapheaderinfo[gamemap-1]->musinterfadeout : true) && + // don't fade if we're fading during intermission. follows Y_StartIntermission intertype = int_coop + (gametype == GT_RACE || gametype == GT_COMPETITION ? countdown2 == 0 : true) && // don't fade on timeout + player->lives > 0 && // don't fade on game over (competition) + P_IsLocalPlayer(player)) + { + if (cv_playersforexit.value) + { + INT32 i; + + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i] || players[i].spectator || players[i].bot) + continue; + if (players[i].lives <= 0) + continue; + + if (!players[i].exiting || players[i].exiting > 1*TICRATE) + break; + } + + if (i == MAXPLAYERS) + { + exitfadestarted = true; + S_FadeOutStopMusic(1*MUSICRATE); + } + } + else + { + exitfadestarted = true; + S_FadeOutStopMusic(1*MUSICRATE); + } + } +#endif + if (player->exiting == 2 || countdown2 == 2) { if (cv_playersforexit.value) // Count to be sure everyone's exited @@ -9526,9 +9562,6 @@ void P_PlayerAfterThink(player_t *player) } } - if (player->awayviewtics < 0) - player->awayviewtics = 0; - // spectator invisibility and nogravity. if ((netgame || multiplayer) && player->spectator) { diff --git a/src/r_data.c b/src/r_data.c index 29a9c52bb..bd12eb248 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -404,16 +404,7 @@ void R_LoadTextures(void) // 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 (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) + 1; - texend = W_CheckNumForNamePwad(TX_END, (UINT16)w, 0); - } + // Count the textures from TEXTURES lumps texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0); while (texturesLumpPos != INT16_MAX) @@ -422,19 +413,43 @@ void R_LoadTextures(void) texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, texturesLumpPos + 1); } - // Add all the textures between TX_START and TX_END - if (texstart != INT16_MAX && texend != INT16_MAX) + // 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 && w == (numwadfiles - 1)) - { - I_Error("No textures detected in any WADs!\n"); - } } + // 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); @@ -469,7 +484,7 @@ void R_LoadTextures(void) } else { - texstart = W_CheckNumForNamePwad(TX_START, (UINT16)w, 0) + 1; + 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) @@ -479,9 +494,16 @@ void R_LoadTextures(void) 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. - for (j = 0; j < (texend - texstart); i++, j++) + for (j = 0; j < (texend - texstart); j++) { + if (wadfiles[w]->type == RET_PK3) + { + if (W_IsLumpFolder((UINT16)w, texstart + j)) // Check if lump is a folder + continue; // If it is then SKIP IT + } patchlump = W_CacheLumpNumPwad((UINT16)w, texstart + j, PU_CACHE); //CONS_Printf("\n\"%s\" is a single patch, dimensions %d x %d",W_CheckNameForNumPwad((UINT16)w,texstart+j),patchlump->width, patchlump->height); @@ -506,9 +528,9 @@ void R_LoadTextures(void) k = 1; while (k << 1 <= texture->width) k <<= 1; - texturewidthmask[i] = k - 1; textureheight[i] = texture->height << FRACBITS; + i++; } } } diff --git a/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj b/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj index 878db3d8d..9297833e2 100644 --- a/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj +++ b/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj @@ -1219,7 +1219,7 @@ C01FCF4B08A954540054247B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - CURRENT_PROJECT_VERSION = 2.1.24; + CURRENT_PROJECT_VERSION = 2.1.25; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", NORMALSRB2, @@ -1231,7 +1231,7 @@ C01FCF4C08A954540054247B /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - CURRENT_PROJECT_VERSION = 2.1.24; + CURRENT_PROJECT_VERSION = 2.1.25; GCC_ENABLE_FIX_AND_CONTINUE = NO; GCC_GENERATE_DEBUGGING_SYMBOLS = NO; GCC_PREPROCESSOR_DEFINITIONS = ( diff --git a/src/sdl12/macosx/Srb2mac.xcodeproj/project.pbxproj b/src/sdl12/macosx/Srb2mac.xcodeproj/project.pbxproj index 6b3997b1f..d67903819 100644 --- a/src/sdl12/macosx/Srb2mac.xcodeproj/project.pbxproj +++ b/src/sdl12/macosx/Srb2mac.xcodeproj/project.pbxproj @@ -1219,7 +1219,7 @@ C01FCF4B08A954540054247B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - CURRENT_PROJECT_VERSION = 2.1.24; + CURRENT_PROJECT_VERSION = 2.1.25; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", NORMALSRB2, @@ -1231,7 +1231,7 @@ C01FCF4C08A954540054247B /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - CURRENT_PROJECT_VERSION = 2.1.24; + CURRENT_PROJECT_VERSION = 2.1.25; GCC_ENABLE_FIX_AND_CONTINUE = NO; GCC_GENERATE_DEBUGGING_SYMBOLS = NO; GCC_PREPROCESSOR_DEFINITIONS = ( diff --git a/src/w_wad.c b/src/w_wad.c index e18c5a084..7de64f9ad 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -1159,6 +1159,22 @@ boolean W_IsLumpWad(lumpnum_t lumpnum) return false; // WADs should never be inside non-PK3s as far as SRB2 is concerned } +// +// W_IsLumpFolder +// Is the lump a folder? (in a PK3 obviously) +// +boolean W_IsLumpFolder(UINT16 wad, UINT16 lump) +{ + if (wadfiles[wad]->type == RET_PK3) + { + const char *name = wadfiles[wad]->lumpinfo[lump].name2; + + return (name[strlen(name)-1] == '/'); // folders end in '/' + } + + return false; // non-PK3s don't have folders +} + #ifdef HAVE_ZLIB /* report a zlib or i/o error */ void zerr(int ret) diff --git a/src/w_wad.h b/src/w_wad.h index e2e17740f..87566c3ee 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -154,6 +154,7 @@ size_t W_LumpLengthPwad(UINT16 wad, UINT16 lump); size_t W_LumpLength(lumpnum_t lumpnum); boolean W_IsLumpWad(lumpnum_t lumpnum); // for loading maps from WADs in PK3s +boolean W_IsLumpFolder(UINT16 wad, UINT16 lump); // for detecting folder "lumps" #ifdef HAVE_ZLIB void zerr(int ret); // zlib error checking