diff --git a/assets/CMakeLists.txt b/assets/CMakeLists.txt index 89be796ad..e5cfa5ca2 100644 --- a/assets/CMakeLists.txt +++ b/assets/CMakeLists.txt @@ -17,7 +17,7 @@ set(SRB2_ASSET_HASHED gfx.pk3;\ textures.pk3;\ chars.pk3;\ -maps.wad;\ +maps.pk3;\ patch.pk3" CACHE STRING "Asset filenames to apply MD5 checks. No spaces between entries!" ) diff --git a/src/command.c b/src/command.c index 3eebe32d1..6d9c86d3e 100644 --- a/src/command.c +++ b/src/command.c @@ -902,7 +902,10 @@ static void COM_Add_f(void) return; } - CV_AddValue(cvar, atoi(COM_Argv(2))); + if (( cvar->flags & CV_FLOAT )) + CV_Set(cvar, va("%f", FIXED_TO_FLOAT (cvar->value) + atof(COM_Argv(2)))); + else + CV_AddValue(cvar, atoi(COM_Argv(2))); } // ========================================================================= diff --git a/src/config.h.in b/src/config.h.in index 4bf84ff1d..964207e34 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -15,7 +15,7 @@ #define ASSET_HASH_GFX_PK3 "${SRB2_ASSET_gfx.pk3_HASH}" #define ASSET_HASH_TEXTURES_PK3 "${SRB2_ASSET_textures.pk3_HASH}" #define ASSET_HASH_CHARS_PK3 "${SRB2_ASSET_chars.pk3_HASH}" -#define ASSET_HASH_MAPS_WAD "${SRB2_ASSET_maps.wad_HASH}" +#define ASSET_HASH_MAPS_PK3 "${SRB2_ASSET_maps.pk3_HASH}" #ifdef USE_PATCH_FILE #define ASSET_HASH_PATCH_PK3 "${SRB2_ASSET_patch.pk3_HASH}" #endif @@ -36,7 +36,7 @@ #define ASSET_HASH_GFX_PK3 "00000000000000000000000000000000" #define ASSET_HASH_TEXTURES_PK3 "00000000000000000000000000000000" #define ASSET_HASH_CHARS_PK3 "00000000000000000000000000000000" -#define ASSET_HASH_MAPS_WAD "00000000000000000000000000000000" +#define ASSET_HASH_MAPS_PK3 "00000000000000000000000000000000" #ifdef USE_PATCH_FILE #define ASSET_HASH_PATCH_PK3 "00000000000000000000000000000000" #endif diff --git a/src/d_clisrv.c b/src/d_clisrv.c index fa228df06..4d61194c4 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1428,8 +1428,14 @@ static void SV_SendPlayerInfo(INT32 node) UINT8 i; netbuffer->packettype = PT_PLAYERINFO; - for (i = 0; i < MAXPLAYERS; i++) + for (i = 0; i < MSCOMPAT_MAXPLAYERS; i++) { + if (i >= MAXPLAYERS) + { + netbuffer->u.playerinfo[i].node = 255; + continue; + } + if (!playeringame[i]) { netbuffer->u.playerinfo[i].node = 255; // This slot is empty. @@ -1477,7 +1483,7 @@ static void SV_SendPlayerInfo(INT32 node) netbuffer->u.playerinfo[i].data |= 0x80; } - HSendPacket(node, false, 0, sizeof(plrinfo) * MAXPLAYERS); + HSendPacket(node, false, 0, sizeof(plrinfo) * MSCOMPAT_MAXPLAYERS); } /** Sends a PT_SERVERCFG packet diff --git a/src/d_clisrv.h b/src/d_clisrv.h index e7879d582..66d9e73ea 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -468,7 +468,7 @@ typedef struct serverrefuse_pak serverrefuse; // 65025 bytes (somehow I feel like those values are garbage...) askinfo_pak askinfo; // 61 bytes msaskinfo_pak msaskinfo; // 22 bytes - plrinfo playerinfo[MAXPLAYERS]; // 576 bytes(?) + plrinfo playerinfo[MSCOMPAT_MAXPLAYERS];// 576 bytes(?) plrconfig playerconfig[MAXPLAYERS]; // (up to) 528 bytes(?) INT32 filesneedednum; // 4 bytes filesneededconfig_pak filesneededcfg; // ??? bytes diff --git a/src/d_main.c b/src/d_main.c index 1404a5e61..30d82b256 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -447,7 +447,7 @@ static void D_Display(void) { if (i > 0) // Splitscreen-specific { - switch (i) + switch (i) { case 1: if (splitscreen > 1) @@ -896,11 +896,18 @@ static void IdentifyVersion(void) D_AddFile(va(pandf,srb2waddir,"gfx.pk3"), startupwadfiles); D_AddFile(va(pandf,srb2waddir,"textures.pk3"), startupwadfiles); D_AddFile(va(pandf,srb2waddir,"chars.pk3"), startupwadfiles); - D_AddFile(va(pandf,srb2waddir,"maps.wad"), startupwadfiles); // TODO: make this a pk3 too! + D_AddFile(va(pandf,srb2waddir,"maps.pk3"), startupwadfiles); #ifdef USE_PATCH_FILE D_AddFile(va(pandf,srb2waddir,"patch.pk3"), startupwadfiles); #endif +#if 0 + // TODO: pk3 doesn't support music replacement IIRC + // music barely benefits from the compression anyway + // would be nice for the folders, though + D_AddFile(va(pandf,srb2waddir,"sounds.pk3"), startupwadfiles); + D_AddFile(va(pandf,srb2waddir,"music.pk3"), startupwadfiles); +#else #if !defined (HAVE_SDL) || defined (HAVE_MIXER) #define MUSICTEST(str) \ {\ @@ -915,6 +922,7 @@ static void IdentifyVersion(void) MUSICTEST("music.wad") #undef MUSICTEST #endif +#endif } /* ======================================================================== */ @@ -1182,12 +1190,12 @@ void D_SRB2Main(void) M_InitCharacterTables(); // load wad, including the main wad file - CONS_Printf("W_InitMultipleFiles(): Adding IWAD and main PWADs.\n"); + CONS_Printf("W_InitMultipleFiles(): Adding main IWAD and PWADs.\n"); if (!W_InitMultipleFiles(startupwadfiles, false)) #ifdef _DEBUG - CONS_Error("A WAD file was not found or not valid.\nCheck the log to see which ones.\n"); + CONS_Error("A main WAD file was not found or not valid.\nCheck the log to see which ones.\n"); #else - I_Error("A WAD file was not found or not valid.\nCheck the log to see which ones.\n"); + I_Error("A main WAD file was not found or not valid.\nCheck the log to see which ones.\n"); #endif D_CleanFile(startupwadfiles); @@ -1200,7 +1208,7 @@ void D_SRB2Main(void) mainwads++; W_VerifyFileMD5(mainwads, ASSET_HASH_GFX_PK3); // gfx.pk3 mainwads++; W_VerifyFileMD5(mainwads, ASSET_HASH_TEXTURES_PK3); // textures.pk3 mainwads++; W_VerifyFileMD5(mainwads, ASSET_HASH_CHARS_PK3); // chars.pk3 - mainwads++; W_VerifyFileMD5(mainwads, ASSET_HASH_MAPS_WAD); // maps.wad -- 4 - If you touch this, make sure to touch up the majormods stuff below. + mainwads++; W_VerifyFileMD5(mainwads, ASSET_HASH_MAPS_PK3); // maps.pk3 -- 4 - If you touch this, make sure to touch up the majormods stuff below. #ifdef USE_PATCH_FILE mainwads++; W_VerifyFileMD5(mainwads, ASSET_HASH_PATCH_PK3); // patch.pk3 #endif @@ -1208,7 +1216,7 @@ void D_SRB2Main(void) mainwads++; // gfx.pk3 mainwads++; // textures.pk3 mainwads++; // chars.pk3 - mainwads++; // maps.wad + mainwads++; // maps.pk3 #ifdef USE_PATCH_FILE mainwads++; // patch.pk3 #endif @@ -1241,8 +1249,9 @@ void D_SRB2Main(void) } } + CONS_Printf("W_InitMultipleFiles(): Adding external PWADs.\n"); if (!W_InitMultipleFiles(startuppwads, true)) - CONS_Error("A PWAD file was not found or not valid.\nCheck the log to see which ones.\n"); + M_StartMessage(M_GetText("A PWAD file was not found or not valid.\nCheck log.txt to see which ones.\n\nPress ESC\n"), NULL, MM_NOTHING); D_CleanFile(startuppwads); // diff --git a/src/d_netcmd.c b/src/d_netcmd.c index c4d99e840..11c4547de 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -2041,7 +2041,7 @@ static void Command_View_f(void) return; } - displayplayerp = &displayplayers[viewnum]; + displayplayerp = &displayplayers[viewnum-1]; if (COM_Argc() > 1)/* switch to player */ { diff --git a/src/d_netfil.c b/src/d_netfil.c index 0b9dc9126..155700807 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -130,7 +130,8 @@ UINT8 *PutFileNeeded(UINT16 firstfile) nameonly(strcpy(wadfilename, wadfiles[i]->filename)); - if (p + 1 + 4 + strlen(wadfilename) + 16 > p_start + MAXFILENEEDED) + // Look below at the WRITE macros to understand what these numbers mean. + if (p + 1 + 4 + min(strlen(wadfilename) + 1, MAX_WADPATH) + 16 > p_start + MAXFILENEEDED) { // Too many files to send all at once if (netbuffer->packettype == PT_MOREFILESNEEDED) diff --git a/src/d_player.h b/src/d_player.h index d2ed296ce..de6cbc46c 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -327,6 +327,9 @@ typedef enum k_jawztargetdelay, // Delay for Jawz target switching, to make it less twitchy k_spectatewait, // How long have you been waiting as a spectator k_growcancel, // Hold the item button down to cancel Grow + k_tiregrease, // Reduced friction timer after hitting a horizontal spring + k_springstars, // Spawn stars around a player when they hit a spring + k_springcolor, // Color of spring stars NUMKARTSTUFF } kartstufftype_t; diff --git a/src/dehacked.c b/src/dehacked.c index be45f3f0f..829f03343 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1230,8 +1230,9 @@ static void readlevelheader(MYFILE *f, INT32 num) } else if (fastcmp(word, "WEATHER")) mapheaderinfo[num-1]->weather = (UINT8)get_number(word2); - else if (fastcmp(word, "SKYNUM")) - mapheaderinfo[num-1]->skynum = (INT16)i; + else if (fastcmp(word, "SKYTEXTURE")) + deh_strlcpy(mapheaderinfo[num-1]->skytexture, word2, + sizeof(mapheaderinfo[num-1]->skytexture), va("Level header %d: sky texture", num)); else if (fastcmp(word, "INTERSCREEN")) strncpy(mapheaderinfo[num-1]->interscreen, word2, 8); else if (fastcmp(word, "PRECUTSCENENUM")) @@ -5609,44 +5610,77 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_RBIRD2", "S_RBIRD3", - "S_YELLOWSPRING", + // Yellow Spring + "S_YELLOWSPRING1", "S_YELLOWSPRING2", "S_YELLOWSPRING3", "S_YELLOWSPRING4", - "S_YELLOWSPRING5", - "S_REDSPRING", + // Red Spring + "S_REDSPRING1", "S_REDSPRING2", "S_REDSPRING3", "S_REDSPRING4", - "S_REDSPRING5", - // Blue Springs - "S_BLUESPRING", + // Blue Spring + "S_BLUESPRING1", "S_BLUESPRING2", "S_BLUESPRING3", "S_BLUESPRING4", - "S_BLUESPRING5", + + // Grey Spring + "S_GREYSPRING1", + "S_GREYSPRING2", + "S_GREYSPRING3", + "S_GREYSPRING4", // Yellow Diagonal Spring "S_YDIAG1", "S_YDIAG2", "S_YDIAG3", "S_YDIAG4", - "S_YDIAG5", - "S_YDIAG6", - "S_YDIAG7", - "S_YDIAG8", // Red Diagonal Spring "S_RDIAG1", "S_RDIAG2", "S_RDIAG3", "S_RDIAG4", - "S_RDIAG5", - "S_RDIAG6", - "S_RDIAG7", - "S_RDIAG8", + + // Blue Diagonal Spring + "S_BDIAG1", + "S_BDIAG2", + "S_BDIAG3", + "S_BDIAG4", + + // Grey Diagonal Spring + "S_GDIAG1", + "S_GDIAG2", + "S_GDIAG3", + "S_GDIAG4", + + // Yellow Horizontal Spring + "S_YHORIZ1", + "S_YHORIZ2", + "S_YHORIZ3", + "S_YHORIZ4", + + // Red Horizontal Spring + "S_RHORIZ1", + "S_RHORIZ2", + "S_RHORIZ3", + "S_RHORIZ4", + + // Blue Horizontal Spring + "S_BHORIZ1", + "S_BHORIZ2", + "S_BHORIZ3", + "S_BHORIZ4", + + // Grey Horizontal Spring + "S_GHORIZ1", + "S_GHORIZ2", + "S_GHORIZ3", + "S_GHORIZ4", // Rain "S_RAIN1", @@ -6271,26 +6305,6 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_SRB1_GENREX1", "S_SRB1_GENREX2", - // Gray Springs - "S_GRAYSPRING", - "S_GRAYSPRING2", - "S_GRAYSPRING3", - "S_GRAYSPRING4", - "S_GRAYSPRING5", - - // Invis-spring - this is used just for the sproing sound. - "S_INVISSPRING", - - // Blue Diagonal Spring - "S_BDIAG1", - "S_BDIAG2", - "S_BDIAG3", - "S_BDIAG4", - "S_BDIAG5", - "S_BDIAG6", - "S_BDIAG7", - "S_BDIAG8", - //{ Random Item Box "S_RANDOMITEM1", "S_RANDOMITEM2", @@ -7199,6 +7213,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_DRAFTDUST4", "S_DRAFTDUST5", + "S_TIREGREASE", + #ifdef SEENAMES "S_NAMECHECK", #endif @@ -7328,11 +7344,18 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s // Springs and others "MT_FAN", "MT_STEAM", // Steam riser - "MT_BLUESPRING", "MT_YELLOWSPRING", "MT_REDSPRING", + "MT_BLUESPRING", + "MT_GREYSPRING", "MT_YELLOWDIAG", // Yellow Diagonal Spring "MT_REDDIAG", // Red Diagonal Spring + "MT_BLUEDIAG", // Blue Diagonal Spring + "MT_GREYDIAG", // Grey Diagonal Spring + "MT_YELLOWHORIZ", // Yellow Horizontal Spring + "MT_REDHORIZ", // Red Horizontal Spring + "MT_BLUEHORIZ", // Blue Horizontal Spring + "MT_GREYHORIZ", // Grey Horizontal Spring // Interactive Objects "MT_BUBBLES", // Bubble source @@ -7714,9 +7737,6 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_SRB1_GENREX", // SRB2kart - "MT_GRAYSPRING", - "MT_INVISSPRING", - "MT_BLUEDIAG", "MT_RANDOMITEM", "MT_RANDOMITEMPOP", "MT_FLOATINGITEM", @@ -7987,6 +8007,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_KARMAFIREWORK", "MT_RINGSPARKS", "MT_DRAFTDUST", + "MT_TIREGREASE", #ifdef SEENAMES "MT_NAMECHECK", @@ -8473,7 +8494,10 @@ static const char *const KARTSTUFF_LIST[] = { "GETSPARKS", "JAWZTARGETDELAY", "SPECTATEWAIT", - "GROWCANCEL" + "GROWCANCEL", + "TIREGREASE", + "SPRINGSTARS", + "SPRINGCOLOR" }; #endif @@ -9903,11 +9927,11 @@ static inline int lib_getenum(lua_State *L) } else if (fastcmp(word,"globalweather")) { lua_pushinteger(L, globalweather); return 1; - } else if (fastcmp(word,"levelskynum")) { - lua_pushinteger(L, levelskynum); + } else if (fastcmp(word,"levelskytexture")) { + lua_pushstring(L, levelskytexture); return 1; - } else if (fastcmp(word,"globallevelskynum")) { - lua_pushinteger(L, globallevelskynum); + } else if (fastcmp(word,"globallevelskytexture")) { + lua_pushstring(L, globallevelskytexture); return 1; } else if (fastcmp(word,"mapmusname")) { lua_pushstring(L, mapmusname); diff --git a/src/doomdef.h b/src/doomdef.h index 728dc3ab9..645864257 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -249,6 +249,9 @@ extern FILE *logstream; #define PLAYERSMASK (MAXPLAYERS-1) #define MAXPLAYERNAME 21 +// Master Server compatibility ONLY +#define MSCOMPAT_MAXPLAYERS (32) + typedef enum { SKINCOLOR_NONE = 0, diff --git a/src/doomstat.h b/src/doomstat.h index 1f855da27..1f0182c7d 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -227,7 +227,7 @@ typedef struct UINT32 muspos; ///< Music position to jump to. char forcecharacter[17]; ///< (SKINNAMESIZE+1) Skin to switch to or "" to disable. UINT8 weather; ///< 0 = sunny day, 1 = storm, 2 = snow, 3 = rain, 4 = blank, 5 = thunder w/o rain, 6 = rain w/o lightning, 7 = heat wave. - INT16 skynum; ///< Sky number to use. + char skytexture[9]; ///< Sky texture to use. INT16 skybox_scalex; ///< Skybox X axis scale. (0 = no movement, 1 = 1:1 movement, 16 = 16:1 slow movement, -4 = 1:4 fast movement, etc.) INT16 skybox_scaley; ///< Skybox Y axis scale. INT16 skybox_scalez; ///< Skybox Z axis scale. @@ -435,6 +435,7 @@ extern INT32 sneakertime; extern INT32 itemtime; extern INT32 comebacktime; extern INT32 bumptime; +extern INT32 greasetics; extern INT32 wipeoutslowtime; extern INT32 wantedreduce; extern INT32 wantedfrequency; diff --git a/src/g_game.c b/src/g_game.c index a78a7489b..b3530a08d 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -216,6 +216,7 @@ INT32 sneakertime = TICRATE + (TICRATE/3); INT32 itemtime = 8*TICRATE; INT32 comebacktime = 10*TICRATE; INT32 bumptime = 6; +INT32 greasetics = 3*TICRATE; INT32 wipeoutslowtime = 20; INT32 wantedreduce = 5*TICRATE; INT32 wantedfrequency = 10*TICRATE; @@ -3642,7 +3643,7 @@ tryagain: void G_AddMapToBuffer(INT16 map) { - INT16 bufx, refreshnum = (TOLMaps(G_TOLFlag(gametype)) / 2) + 1; + INT16 bufx, refreshnum = max(0, TOLMaps(G_TOLFlag(gametype))-3); // Add the map to the buffer. for (bufx = NUMMAPS-1; bufx > 0; bufx--) @@ -6483,10 +6484,10 @@ void G_WriteStanding(UINT8 ranking, char *name, INT32 skinnum, UINT8 color, UINT { char temp[16]; - if (demoinfo_p && (UINT32)(*demoinfo_p) == 0) + if (demoinfo_p && *(UINT32 *)demoinfo_p == 0) { WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker - WRITEUINT32(demoinfo_p, demo_p - demobuffer); + *(UINT32 *)demoinfo_p = demo_p - demobuffer; } WRITEUINT8(demo_p, DW_STANDING); @@ -8178,16 +8179,17 @@ boolean G_CheckDemoStatus(void) void G_SaveDemo(void) { - UINT8 *p = demobuffer+16; // checksum position + UINT8 *p = demobuffer+16; // after version + UINT32 length; #ifdef NOMD5 UINT8 i; #endif // Ensure extrainfo pointer is always available, even if no info is present. - if (demoinfo_p && (UINT32)(*demoinfo_p) == 0) + if (demoinfo_p && *(UINT32 *)demoinfo_p == 0) { WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker - WRITEUINT32(demoinfo_p, (UINT32)(demo_p - demobuffer)); + *(UINT32 *)demoinfo_p = demo_p - demobuffer; } WRITEUINT8(demo_p, DW_END); // Mark end of demo extra data. @@ -8233,12 +8235,14 @@ void G_SaveDemo(void) sprintf(writepoint, "%s.lmp", demo_slug); } + length = *(UINT32 *)demoinfo_p; + WRITEUINT32(demoinfo_p, length); #ifdef NOMD5 for (i = 0; i < 16; i++, p++) *p = M_RandomByte(); // This MD5 was chosen by fair dice roll and most likely < 50% correct. #else // Make a checksum of everything after the checksum in the file up to the end of the standard data. Extrainfo is freely modifiable. - md5_buffer((char *)p+16, (demobuffer + (UINT32)*demoinfo_p) - (p+16), p); + md5_buffer((char *)p+16, (demobuffer + length) - (p+16), p); #endif diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 3fe1e18be..659af386d 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -1319,7 +1319,7 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, // HWR_DrawSkyWalls // Draw walls into the depth buffer so that anything behind is culled properly -static void HWR_DrawSkyWall(wallVert3D *wallVerts, FSurfaceInfo *Surf, fixed_t bottom, fixed_t top) +static void HWR_DrawSkyWall(wallVert3D *wallVerts, FSurfaceInfo *Surf) { HWD.pfnSetTexture(NULL); // no texture @@ -1327,9 +1327,6 @@ static void HWR_DrawSkyWall(wallVert3D *wallVerts, FSurfaceInfo *Surf, fixed_t b wallVerts[0].t = wallVerts[1].t = 0; wallVerts[0].s = wallVerts[3].s = 0; wallVerts[2].s = wallVerts[1].s = 0; - // set top/bottom coords - wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(top); // No real way to find the correct height of this - wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(bottom); // worldlow/bottom because it needs to cover up the lower thok barrier wall HWR_ProjectWall(wallVerts, Surf, PF_Invisible|PF_Clip|PF_NoTexture, 255, NULL); // PF_Invisible so it's not drawn into the colour buffer // PF_NoTexture for no texture @@ -1462,6 +1459,111 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) worldlow = gr_backsector->floorheight; #endif + // Sky culling + if (!gr_curline->polyseg) // Don't do it for polyobjects + { + // Sky Ceilings + wallVerts[3].y = wallVerts[2].y = FIXED_TO_FLOAT(INT32_MAX); + + if (gr_frontsector->ceilingpic == skyflatnum) + { + if (gr_backsector->ceilingpic == skyflatnum) + { + // Both front and back sectors are sky, needs skywall from the frontsector's ceiling, but only if the + // backsector is lower + if ((worldhigh <= worldtop) +#ifdef ESLOPE + && (worldhighslope <= worldtopslope) +#endif + ) + { +#ifdef ESLOPE + wallVerts[0].y = FIXED_TO_FLOAT(worldhigh); + wallVerts[1].y = FIXED_TO_FLOAT(worldhighslope); +#else + wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(worldhigh); +#endif + HWR_DrawSkyWall(wallVerts, &Surf); + } + } + else + { + // Only the frontsector is sky, just draw a skywall from the front ceiling +#ifdef ESLOPE + wallVerts[0].y = FIXED_TO_FLOAT(worldtop); + wallVerts[1].y = FIXED_TO_FLOAT(worldtopslope); +#else + wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(worldtop); +#endif + HWR_DrawSkyWall(wallVerts, &Surf); + } + } + else if (gr_backsector->ceilingpic == skyflatnum) + { + // Only the backsector is sky, just draw a skywall from the front ceiling +#ifdef ESLOPE + wallVerts[0].y = FIXED_TO_FLOAT(worldtop); + wallVerts[1].y = FIXED_TO_FLOAT(worldtopslope); +#else + wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(worldtop); +#endif + HWR_DrawSkyWall(wallVerts, &Surf); + } + + + // Sky Floors + wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(INT32_MIN); + + if (gr_frontsector->floorpic == skyflatnum) + { + if (gr_backsector->floorpic == skyflatnum) + { + // Both front and back sectors are sky, needs skywall from the backsector's floor, but only if the + // it's higher, also needs to check for bottomtexture as the floors don't usually move down + // when both sides are sky floors + if ((worldlow >= worldbottom) +#ifdef ESLOPE + && (worldlowslope >= worldbottomslope) +#endif + && !(gr_sidedef->bottomtexture)) + { +#ifdef ESLOPE + wallVerts[3].y = FIXED_TO_FLOAT(worldlow); + wallVerts[2].y = FIXED_TO_FLOAT(worldlowslope); +#else + wallVerts[3].y = wallVerts[2].y = FIXED_TO_FLOAT(worldlow); +#endif + + HWR_DrawSkyWall(wallVerts, &Surf); + } + } + else + { + // Only the backsector has sky, just draw a skywall from the back floor +#ifdef ESLOPE + wallVerts[3].y = FIXED_TO_FLOAT(worldbottom); + wallVerts[2].y = FIXED_TO_FLOAT(worldbottomslope); +#else + wallVerts[3].y = wallVerts[2].y = FIXED_TO_FLOAT(worldbottom); +#endif + + HWR_DrawSkyWall(wallVerts, &Surf); + } + } + else if ((gr_backsector->floorpic == skyflatnum) && !(gr_sidedef->bottomtexture)) + { + // Only the backsector has sky, just draw a skywall from the back floor if there's no bottomtexture +#ifdef ESLOPE + wallVerts[3].y = FIXED_TO_FLOAT(worldlow); + wallVerts[2].y = FIXED_TO_FLOAT(worldlowslope); +#else + wallVerts[3].y = wallVerts[2].y = FIXED_TO_FLOAT(worldlow); +#endif + + HWR_DrawSkyWall(wallVerts, &Surf); + } + } + // hack to allow height changes in outdoor areas // This is what gets rid of the upper textures if there should be sky if (gr_frontsector->ceilingpic == skyflatnum && @@ -1914,85 +2016,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) Surf.FlatColor.rgba = 0xffffffff; }*/ } - - // Isn't this just the most lovely mess - if (!gr_curline->polyseg) // Don't do it for polyobjects - { - if (gr_frontsector->ceilingpic == skyflatnum || gr_backsector->ceilingpic == skyflatnum) - { - fixed_t depthwallheight; - - if (!gr_sidedef->toptexture || (gr_frontsector->ceilingpic == skyflatnum && gr_backsector->ceilingpic == skyflatnum)) // when both sectors are sky, the top texture isn't drawn - depthwallheight = gr_frontsector->ceilingheight < gr_backsector->ceilingheight ? gr_frontsector->ceilingheight : gr_backsector->ceilingheight; - else - depthwallheight = gr_frontsector->ceilingheight > gr_backsector->ceilingheight ? gr_frontsector->ceilingheight : gr_backsector->ceilingheight; - - if (gr_frontsector->ceilingheight-gr_frontsector->floorheight <= 0) // current sector is a thok barrier - { - if (gr_backsector->ceilingheight-gr_backsector->floorheight <= 0) // behind sector is also a thok barrier - { - if (!gr_sidedef->bottomtexture) // Only extend further down if there's no texture - HWR_DrawSkyWall(wallVerts, &Surf, worldbottom < worldlow ? worldbottom : worldlow, INT32_MAX); - else - HWR_DrawSkyWall(wallVerts, &Surf, worldbottom > worldlow ? worldbottom : worldlow, INT32_MAX); - } - // behind sector is not a thok barrier - else if (gr_backsector->ceilingheight <= gr_frontsector->ceilingheight) // behind sector ceiling is lower or equal to current sector - HWR_DrawSkyWall(wallVerts, &Surf, depthwallheight, INT32_MAX); - // gr_front/backsector heights need to be used here because of the worldtop being set to worldhigh earlier on - } - else if (gr_backsector->ceilingheight-gr_backsector->floorheight <= 0) // behind sector is a thok barrier, current sector is not - { - if (gr_backsector->ceilingheight >= gr_frontsector->ceilingheight // thok barrier ceiling height is equal to or greater than current sector ceiling height - || gr_backsector->floorheight <= gr_frontsector->floorheight // thok barrier ceiling height is equal to or less than current sector floor height - || gr_backsector->ceilingpic != skyflatnum) // thok barrier is not a sky - HWR_DrawSkyWall(wallVerts, &Surf, depthwallheight, INT32_MAX); - } - else // neither sectors are thok barriers - { - if ((gr_backsector->ceilingheight < gr_frontsector->ceilingheight && !gr_sidedef->toptexture) // no top texture and sector behind is lower - || gr_backsector->ceilingpic != skyflatnum) // behind sector is not a sky - HWR_DrawSkyWall(wallVerts, &Surf, depthwallheight, INT32_MAX); - } - } - // And now for sky floors! - if (gr_frontsector->floorpic == skyflatnum || gr_backsector->floorpic == skyflatnum) - { - fixed_t depthwallheight; - - if (!gr_sidedef->bottomtexture) - depthwallheight = worldbottom > worldlow ? worldbottom : worldlow; - else - depthwallheight = worldbottom < worldlow ? worldbottom : worldlow; - - if (gr_frontsector->ceilingheight-gr_frontsector->floorheight <= 0) // current sector is a thok barrier - { - if (gr_backsector->ceilingheight-gr_backsector->floorheight <= 0) // behind sector is also a thok barrier - { - if (!gr_sidedef->toptexture) // Only extend up if there's no texture - HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, worldtop > worldhigh ? worldtop : worldhigh); - else - HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, worldtop < worldhigh ? worldtop : worldhigh); - } - // behind sector is not a thok barrier - else if (gr_backsector->floorheight >= gr_frontsector->floorheight) // behind sector floor is greater or equal to current sector - HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, depthwallheight); - } - else if (gr_backsector->ceilingheight-gr_backsector->floorheight <= 0) // behind sector is a thok barrier, current sector is not - { - if (gr_backsector->floorheight <= gr_frontsector->floorheight // thok barrier floor height is equal to or less than current sector floor height - || gr_backsector->ceilingheight >= gr_frontsector->ceilingheight // thok barrier floor height is equal to or greater than current sector ceiling height - || gr_backsector->floorpic != skyflatnum) // thok barrier is not a sky - HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, depthwallheight); - } - else // neither sectors are thok barriers - { - if ((gr_backsector->floorheight > gr_frontsector->floorheight && !gr_sidedef->bottomtexture) // no bottom texture and sector behind is higher - || gr_backsector->floorpic != skyflatnum) // behind sector is not a sky - HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, depthwallheight); - } - } - } } else { @@ -2060,13 +2083,52 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) HWR_ProjectWall(wallVerts, &Surf, PF_Masked, lightnum, colormap); } } + else + { +#ifdef ESLOPE + //Set textures properly on single sided walls that are sloped + wallVerts[3].y = FIXED_TO_FLOAT(worldtop); + wallVerts[0].y = FIXED_TO_FLOAT(worldbottom); + wallVerts[2].y = FIXED_TO_FLOAT(worldtopslope); + wallVerts[1].y = FIXED_TO_FLOAT(worldbottomslope); +#else + // set top/bottom coords + wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(worldtop); + wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(worldbottom); +#endif + // When there's no midtexture, draw a skywall to prevent rendering behind it + HWR_DrawSkyWall(wallVerts, &Surf); + } + + + // Single sided lines are simple for skywalls, just need to draw from the top or bottom of the sector if there's + // a sky flat if (!gr_curline->polyseg) { if (gr_frontsector->ceilingpic == skyflatnum) // It's a single-sided line with sky for its sector - HWR_DrawSkyWall(wallVerts, &Surf, worldtop, INT32_MAX); + { + wallVerts[3].y = wallVerts[2].y = FIXED_TO_FLOAT(INT32_MAX); +#ifdef ESLOPE + wallVerts[0].y = FIXED_TO_FLOAT(worldtop); + wallVerts[1].y = FIXED_TO_FLOAT(worldtopslope); +#else + wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(worldtop); +#endif + HWR_DrawSkyWall(wallVerts, &Surf); + } if (gr_frontsector->floorpic == skyflatnum) - HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, worldbottom); + { +#ifdef ESLOPE + wallVerts[3].y = FIXED_TO_FLOAT(worldbottom); + wallVerts[2].y = FIXED_TO_FLOAT(worldbottomslope); +#else + wallVerts[3].y = wallVerts[2].y = FIXED_TO_FLOAT(worldbottom); +#endif + wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(INT32_MIN); + + HWR_DrawSkyWall(wallVerts, &Surf); + } } } @@ -2381,7 +2443,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) // e6y: Check whether the player can look beyond this line // #ifdef NEWCLIP -boolean checkforemptylines = true; +static boolean checkforemptylines = true; // Don't modify anything here, just check // Kalaron: Modified for sloped linedefs static boolean CheckClip(seg_t * seg, sector_t * afrontsector, sector_t * abacksector) @@ -2421,62 +2483,47 @@ static boolean CheckClip(seg_t * seg, sector_t * afrontsector, sector_t * abacks backc1 = backc2 = abacksector->ceilingheight; } - // now check for closed sectors! - if (backc1 <= frontf1 && backc2 <= frontf2) + if (viewsector != abacksector && viewsector != afrontsector) { - checkforemptylines = false; - if (!seg->sidedef->toptexture) - return false; + boolean mydoorclosed = false; // My door? Closed!? (doorclosed is actually otherwise unused in openGL) - if (abacksector->ceilingpic == skyflatnum && afrontsector->ceilingpic == skyflatnum) - return false; - - return true; - } - - if (backf1 >= frontc1 && backf2 >= frontc2) - { - checkforemptylines = false; - if (!seg->sidedef->bottomtexture) - return false; - - // properly render skies (consider door "open" if both floors are sky): - if (abacksector->ceilingpic == skyflatnum && afrontsector->ceilingpic == skyflatnum) - return false; - - return true; - } - - if (backc1 <= backf1 && backc2 <= backf2) - { - checkforemptylines = false; - // preserve a kind of transparent door/lift special effect: - if (backc1 < frontc1 || backc2 < frontc2) - { - if (!seg->sidedef->toptexture) - return false; - } - if (backf1 > frontf1 || backf2 > frontf2) - { - if (!seg->sidedef->bottomtexture) - return false; - } - if (abacksector->ceilingpic == skyflatnum && afrontsector->ceilingpic == skyflatnum) - return false; - - if (abacksector->floorpic == skyflatnum && afrontsector->floorpic == skyflatnum) - return false; - - return true; - } - - if (backc1 != frontc1 || backc2 != frontc2 - || backf1 != frontf1 || backf2 != frontf2) + // If the sector behind the line blocks all kinds of view past it + // (back ceiling is lower than close floor, or back floor is higher than close ceiling) + if ((backc1 <= frontf1 && backc2 <= frontf2) + || (backf1 >= frontc1 && backf2 >= frontc2)) { checkforemptylines = false; - return false; + return true; } + // The door is closed if: + // backsector is 0 height or less and + // back ceiling is higher than close ceiling or we need to render a top texture and + // back floor is lower than close floor or we need to render a bottom texture and + // neither front or back sectors are using the sky ceiling + mydoorclosed = (backc1 <= backf1 && backc2 <= backf2 + && ((backc1 >= frontc1 && backc2 >= frontc2) || seg->sidedef->toptexture) + && ((backf1 <= frontf1 && backf2 >= frontf2) || seg->sidedef->bottomtexture) + && (abacksector->ceilingpic != skyflatnum || afrontsector->ceilingpic != skyflatnum)); + + if (mydoorclosed) + { + checkforemptylines = false; + return true; + } + } + + // Window. + // We know it's a window when the above isn't true and the back and front sectors don't match + if (backc1 != frontc1 || backc2 != frontc2 + || backf1 != frontf1 || backf2 != frontf2) + { + checkforemptylines = false; + return false; + } + + // In this case we just need to check whether there is actually a need to render any lines, so checkforempty lines + // stays true return false; } #else @@ -5497,7 +5544,7 @@ static void HWR_AddSprites(sector_t *sec) } #ifdef HWPRECIP - // Someone seriously wants infinite draw distance for precipitation? + // No to infinite precipitation draw distance. if ((limit_dist = (fixed_t)cv_drawdist_precip.value << FRACBITS)) { for (precipthing = sec->preciplist; precipthing; precipthing = precipthing->snext) @@ -5513,13 +5560,6 @@ static void HWR_AddSprites(sector_t *sec) HWR_ProjectPrecipitationSprite(precipthing); } } - else - { - // Draw everything in sector, no checks - for (precipthing = sec->preciplist; precipthing; precipthing = precipthing->snext) - if (!(precipthing->precipflags & PCF_INVISIBLE)) - HWR_ProjectPrecipitationSprite(precipthing); - } #endif } @@ -5882,13 +5922,15 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) static void HWR_DrawSkyBackground(void) { FOutVector v[4]; + texture_t *tex; angle_t angle; float dimensionmultiply; float aspectratio; float angleturn; + tex = textures[texturetranslation[skytexture]]; HWR_GetTexture(texturetranslation[skytexture]); - aspectratio = (float)vid.width/(float)vid.height; + aspectratio = (float)vid.width / (float)vid.height; //Hurdler: the sky is the only texture who need 4.0f instead of 1.0 // because it's called just after clearing the screen @@ -5912,22 +5954,22 @@ static void HWR_DrawSkyBackground(void) // software doesn't draw any further than 1024 for skies anyway, but this doesn't overlap properly // The only time this will probably be an issue is when a sky wider than 1024 is used as a sky AND a regular wall texture - angle = (dup_viewangle + gr_xtoviewangle[0]); - dimensionmultiply = ((float)textures[texturetranslation[skytexture]]->width/256.0f); + angle = -(dup_viewangle + gr_xtoviewangle[0]); + dimensionmultiply = ((float)tex->width/256.0f); if (atransform.mirror) { angle = InvAngle(angle); - dimensionmultiply *= -1; + dimensionmultiply = -dimensionmultiply; } v[0].sow = v[3].sow = ((float) angle / ((ANGLE_90-1)*dimensionmultiply)); - v[2].sow = v[1].sow = (-1.0f/dimensionmultiply)+((float) angle / ((ANGLE_90-1)*dimensionmultiply)); + v[2].sow = v[1].sow = (1.0f/dimensionmultiply)+((float) angle / ((ANGLE_90-1)*dimensionmultiply)); // Y angle = aimingangle; - dimensionmultiply = ((float)textures[texturetranslation[skytexture]]->height/(128.0f*aspectratio)); + dimensionmultiply = ((float)tex->height/(128.0f*aspectratio)); if (splitscreen == 1) { diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index d217f4094..21deed84b 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -653,13 +653,12 @@ spritemd2found: // 0.2126 to red // 0.7152 to green // 0.0722 to blue -// (See this same define in k_kart.c!) +// (See this same define in hw_md2.c!) #define SETBRIGHTNESS(brightness,r,g,b) \ - brightness = (UINT8)(((1063*((UINT16)r)/5000) + (3576*((UINT16)g)/5000) + (361*((UINT16)b)/5000)) / 3) + brightness = (UINT8)(((1063*(UINT16)(r))/5000) + ((3576*(UINT16)(g))/5000) + ((361*(UINT16)(b))/5000)) static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, GLMipmap_t *grmip, INT32 skinnum, skincolors_t color) { - UINT8 i; UINT16 w = gpatch->width, h = gpatch->height; UINT32 size = w*h; RGBA_t *image, *blendimage, *cur, blendcolor; @@ -684,102 +683,188 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, image = gpatch->mipmap.grInfo.data; blendimage = blendgpatch->mipmap.grInfo.data; + blendcolor = V_GetColor(0); // initialize - // Average all of the translation's colors + while (size--) { - const UINT8 div = 6; - const UINT8 start = 4; - UINT32 r, g, b; + UINT16 brightness; - blendcolor = V_GetColor(colortranslations[color][start]); - r = (UINT32)(blendcolor.s.red*blendcolor.s.red); - g = (UINT32)(blendcolor.s.green*blendcolor.s.green); - b = (UINT32)(blendcolor.s.blue*blendcolor.s.blue); - - for (i = 1; i < div; i++) - { - RGBA_t nextcolor = V_GetColor(colortranslations[color][start+i]); - r += (UINT32)(nextcolor.s.red*nextcolor.s.red); - g += (UINT32)(nextcolor.s.green*nextcolor.s.green); - b += (UINT32)(nextcolor.s.blue*nextcolor.s.blue); - } - - blendcolor.s.red = (UINT8)(FixedSqrt((r/div)<>FRACBITS); - blendcolor.s.green = (UINT8)(FixedSqrt((g/div)<>FRACBITS); - blendcolor.s.blue = (UINT8)(FixedSqrt((b/div)<>FRACBITS); - } - - // rainbow support, could theoretically support boss ones too - if (skinnum == TC_RAINBOW) - { - while (size--) + // Don't bother with blending the pixel if the alpha of the blend pixel is 0 + if (skinnum == TC_RAINBOW) { if (image->s.alpha == 0 && blendimage->s.alpha == 0) { - // Don't bother with blending the pixel if the alpha of the blend pixel is 0 cur->rgba = image->rgba; + cur++; image++; blendimage++; + continue; } else { - UINT32 tempcolor; - UINT16 imagebright, blendbright, finalbright, colorbright; + UINT16 imagebright, blendbright; SETBRIGHTNESS(imagebright,image->s.red,image->s.green,image->s.blue); SETBRIGHTNESS(blendbright,blendimage->s.red,blendimage->s.green,blendimage->s.blue); // slightly dumb average between the blend image color and base image colour, usually one or the other will be fully opaque anyway - finalbright = (imagebright*(255-blendimage->s.alpha))/255 + (blendbright*blendimage->s.alpha)/255; - SETBRIGHTNESS(colorbright,blendcolor.s.red,blendcolor.s.green,blendcolor.s.blue); - - tempcolor = (finalbright*blendcolor.s.red)/colorbright; - tempcolor = min(255, tempcolor); - cur->s.red = (UINT8)tempcolor; - tempcolor = (finalbright*blendcolor.s.green)/colorbright; - tempcolor = min(255, tempcolor); - cur->s.green = (UINT8)tempcolor; - tempcolor = (finalbright*blendcolor.s.blue)/colorbright; - tempcolor = min(255, tempcolor); - cur->s.blue = (UINT8)tempcolor; - cur->s.alpha = image->s.alpha; + brightness = (imagebright*(255-blendimage->s.alpha))/255 + (blendbright*blendimage->s.alpha)/255; } - - cur++; image++; blendimage++; } - } - else - { - while (size--) + else { if (blendimage->s.alpha == 0) { - // Don't bother with blending the pixel if the alpha of the blend pixel is 0 cur->rgba = image->rgba; + cur++; image++; blendimage++; + continue; } else { - INT32 tempcolor; - INT16 tempmult, tempalpha; - tempalpha = -(abs(blendimage->s.red-127)-127)*2; - if (tempalpha > 255) - tempalpha = 255; - else if (tempalpha < 0) - tempalpha = 0; + SETBRIGHTNESS(brightness,blendimage->s.red,blendimage->s.green,blendimage->s.blue); + } + } - tempmult = (blendimage->s.red-127)*2; - if (tempmult > 255) - tempmult = 255; - else if (tempmult < 0) - tempmult = 0; + // Calculate a sort of "gradient" for the skincolor + // (Me splitting this into a function didn't work, so I had to ruin this entire function's groove...) + { + RGBA_t nextcolor; + UINT8 firsti, secondi, mul; + UINT32 r, g, b; - tempcolor = (image->s.red*(255-blendimage->s.alpha))/255 + ((tempmult + ((tempalpha*blendcolor.s.red)/255)) * blendimage->s.alpha)/255; - cur->s.red = (UINT8)tempcolor; - tempcolor = (image->s.green*(255-blendimage->s.alpha))/255 + ((tempmult + ((tempalpha*blendcolor.s.green)/255)) * blendimage->s.alpha)/255; - cur->s.green = (UINT8)tempcolor; - tempcolor = (image->s.blue*(255-blendimage->s.alpha))/255 + ((tempmult + ((tempalpha*blendcolor.s.blue)/255)) * blendimage->s.alpha)/255; - cur->s.blue = (UINT8)tempcolor; - cur->s.alpha = image->s.alpha; + // Rainbow needs to find the closest match to the textures themselves, instead of matching brightnesses to other colors. + // Ensue horrible mess. + if (skinnum == TC_RAINBOW) + { + UINT16 brightdif = 256; + UINT8 colorbrightnesses[16]; + INT32 compare, m, d; + UINT8 i; + + // Ignore pure white & pitch black + if (brightness > 253 || brightness < 2) + { + cur->rgba = image->rgba; + cur++; image++; blendimage++; + continue; + } + + firsti = 0; + mul = 0; + + for (i = 0; i < 16; i++) + { + RGBA_t tempc = V_GetColor(colortranslations[color][i]); + SETBRIGHTNESS(colorbrightnesses[i], tempc.s.red, tempc.s.green, tempc.s.blue); // store brightnesses for comparison + } + + for (i = 0; i < 16; i++) + { + if (brightness > colorbrightnesses[i]) // don't allow greater matches (because calculating a makeshift gradient for this is already a huge mess as is) + continue; + compare = abs((INT16)(colorbrightnesses[i]) - (INT16)(brightness)); + if (compare < brightdif) + { + brightdif = (UINT16)compare; + firsti = i; // best matching color that's equal brightness or darker + } + } + + secondi = firsti+1; // next color in line + if (secondi == 16) + { + m = (INT16)brightness; // - 0; + d = (INT16)colorbrightnesses[firsti]; // - 0; + } + else + { + m = (INT16)brightness - (INT16)colorbrightnesses[secondi]; + d = (INT16)colorbrightnesses[firsti] - (INT16)colorbrightnesses[secondi]; + } + + if (m >= d) + m = d-1; + + // calculate the "gradient" multiplier based on how close this color is to the one next in line + if (m <= 0 || d <= 0) + mul = 0; + else + mul = 15 - ((m * 16) / d); + } + else + { + // Thankfully, it's normally way more simple. + // Just convert brightness to a skincolor value, use remainder to find the gradient multipler + firsti = ((UINT8)(255-brightness) / 16); + secondi = firsti+1; + mul = ((UINT8)(255-brightness) % 16); } - cur++; image++; blendimage++; + blendcolor = V_GetColor(colortranslations[color][firsti]); + + if (mul > 0 // If it's 0, then we only need the first color. + && colortranslations[color][firsti] != colortranslations[color][secondi]) // Some colors have duplicate colors in a row, so let's just save the process + { + if (secondi == 16) // blend to black + nextcolor = V_GetColor(31); + else + nextcolor = V_GetColor(colortranslations[color][secondi]); + + // Find difference between points + r = (UINT32)(nextcolor.s.red - blendcolor.s.red); + g = (UINT32)(nextcolor.s.green - blendcolor.s.green); + b = (UINT32)(nextcolor.s.blue - blendcolor.s.blue); + + // Find the gradient of the two points + r = ((mul * r) / 16); + g = ((mul * g) / 16); + b = ((mul * b) / 16); + + // Add gradient value to color + blendcolor.s.red += r; + blendcolor.s.green += g; + blendcolor.s.blue += b; + } } + + if (skinnum == TC_RAINBOW) + { + UINT32 tempcolor; + UINT16 colorbright; + + SETBRIGHTNESS(colorbright,blendcolor.s.red,blendcolor.s.green,blendcolor.s.blue); + if (colorbright == 0) + colorbright = 1; // no dividing by 0 please + + tempcolor = (brightness * blendcolor.s.red) / colorbright; + tempcolor = min(255, tempcolor); + cur->s.red = (UINT8)tempcolor; + + tempcolor = (brightness * blendcolor.s.green) / colorbright; + tempcolor = min(255, tempcolor); + cur->s.green = (UINT8)tempcolor; + + tempcolor = (brightness * blendcolor.s.blue) / colorbright; + tempcolor = min(255, tempcolor); + cur->s.blue = (UINT8)tempcolor; + cur->s.alpha = image->s.alpha; + } + else + { + // Color strength depends on image alpha + INT32 tempcolor; + + tempcolor = ((image->s.red * (255-blendimage->s.alpha)) / 255) + ((blendcolor.s.red * blendimage->s.alpha) / 255); + tempcolor = min(255, tempcolor); + cur->s.red = (UINT8)tempcolor; + + tempcolor = ((image->s.green * (255-blendimage->s.alpha)) / 255) + ((blendcolor.s.green * blendimage->s.alpha) / 255); + tempcolor = min(255, tempcolor); + cur->s.green = (UINT8)tempcolor; + + tempcolor = ((image->s.blue * (255-blendimage->s.alpha)) / 255) + ((blendcolor.s.blue * blendimage->s.alpha) / 255); + tempcolor = min(255, tempcolor); + cur->s.blue = (UINT8)tempcolor; + cur->s.alpha = image->s.alpha; + } + + cur++; image++; blendimage++; } return; @@ -1091,11 +1176,11 @@ void HWR_DrawMD2(gr_vissprite_t *spr) #ifdef USE_FTRANSFORM_ANGLEZ // Slope rotation from Kart p.anglez = 0.0f; - if (spr->mobj->standingslope) + if (spr->mobj->modeltilt) { - fixed_t tempz = spr->mobj->standingslope->normal.z; - fixed_t tempy = spr->mobj->standingslope->normal.y; - fixed_t tempx = spr->mobj->standingslope->normal.x; + fixed_t tempz = spr->mobj->modeltilt->normal.z; + fixed_t tempy = spr->mobj->modeltilt->normal.y; + fixed_t tempx = spr->mobj->modeltilt->normal.x; fixed_t tempangle = AngleFixed(R_PointToAngle2(0, 0, FixedSqrt(FixedMul(tempy, tempy) + FixedMul(tempz, tempz)), tempx)); p.anglez = FIXED_TO_FLOAT(tempangle); tempangle = -AngleFixed(R_PointToAngle2(0, 0, tempz, tempy)); diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 7a912e010..38324dbd9 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -2386,7 +2386,7 @@ void HU_Drawer(void) }*/ // draw song credits - if (cv_songcredits.value) + if (cv_songcredits.value && !( hu_showscores && (netgame || multiplayer) )) HU_DrawSongCredits(); // draw desynch text diff --git a/src/i_tcp.c b/src/i_tcp.c index fb0e5852d..f58aa22bc 100644 --- a/src/i_tcp.c +++ b/src/i_tcp.c @@ -1311,7 +1311,7 @@ static SINT8 SOCK_NetMakeNodewPort(const char *address, const char *port) int gaie; if (!port || !port[0]) - port = port_name; + port = DEFAULTPORT; DEBFILE(va("Creating new node: %s@%s\n", address, port)); diff --git a/src/info.c b/src/info.c index 31f2f8348..cb478b3d8 100644 --- a/src/info.c +++ b/src/info.c @@ -43,33 +43,34 @@ char sprnames[NUMSPRITES + 1][5] = "DFLM","XMS1","XMS2","XMS3","BSZ1","BSZ2","BSZ3","BSZ4","BSZ5","BSZ6", "BSZ7","BSZ8","STLG","DBAL","RCRY","ARMA","ARMF","ARMB","WIND","MAGN", "ELEM","FORC","PITY","IVSP","SSPK","GOAL","BIRD","BUNY","MOUS","CHIC", - "COWZ","RBRD","SPRY","SPRR","SPRB","YSPR","RSPR","RAIN","SNO1","SPLH", - "SPLA","SMOK","BUBP","BUBO","BUBN","BUBM","POPP","TFOG","SEED","PRTL", - "SCOR","DRWN","TTAG","GFLG","RRNG","RNGB","RNGR","RNGI","RNGA","RNGE", - "RNGS","RNGG","PIKB","PIKR","PIKA","PIKE","PIKS","PIKG","TAUT","TGRE", - "TSCR","COIN","CPRK","GOOM","BGOM","FFWR","FBLL","SHLL","PUMA","HAMM", - "KOOP","BFLM","MAXE","MUS1","MUS2","TOAD","NDRN","SUPE","SUPZ","NDRL", - "NSPK","NBMP","HOOP","NSCR","NPRU","CAPS","SUPT","SPRK","BOM1","BOM2", - "BOM3","BOM4","ROIA","ROIB","ROIC","ROID","ROIE","ROIF","ROIG","ROIH", - "ROII","ROIJ","ROIK","ROIL","ROIM","ROIN","ROIO","ROIP","BBAL","GWLG", - "GWLR","SRBA","SRBB","SRBC","SRBD","SRBE","SRBF","SRBG","SRBH","SRBI", - "SRBJ","SRBK","SRBL","SRBM","SRBN","SRBO", + "COWZ","RBRD","SPVY","SPVR","SPVB","SPVG","SPDY","SPDR","SPDB","SPDG", + "SPHY","SPHR","SPHB","SPHG","RAIN","SNO1","SPLH","SPLA","SMOK","BUBP", + "BUBO","BUBN","BUBM","POPP","TFOG","SEED","PRTL","SCOR","DRWN","TTAG", + "GFLG","RRNG","RNGB","RNGR","RNGI","RNGA","RNGE","RNGS","RNGG","PIKB", + "PIKR","PIKA","PIKE","PIKS","PIKG","TAUT","TGRE","TSCR","COIN","CPRK", + "GOOM","BGOM","FFWR","FBLL","SHLL","PUMA","HAMM","KOOP","BFLM","MAXE", + "MUS1","MUS2","TOAD","NDRN","SUPE","SUPZ","NDRL","NSPK","NBMP","HOOP", + "NSCR","NPRU","CAPS","SUPT","SPRK","BOM1","BOM2","BOM3","BOM4","ROIA", + "ROIB","ROIC","ROID","ROIE","ROIF","ROIG","ROIH","ROII","ROIJ","ROIK", + "ROIL","ROIM","ROIN","ROIO","ROIP","BBAL","GWLG","GWLR","SRBA","SRBB", + "SRBC","SRBD","SRBE","SRBF","SRBG","SRBH","SRBI","SRBJ","SRBK","SRBL", + "SRBM","SRBN","SRBO", //SRB2kart Sprites - "SPRG","BSPR","RNDM","RPOP","SGNS","FAST","DSHR","BOST","BOSM","KFRE", - "KINV","KINF","WIPD","DRIF","BDRF","DUST","RSHE","FITM","BANA","ORBN", - "JAWZ","SSMN","KRBM","BHOG","BHBM","SPBM","THNS","SINK","SITR","KBLN", - "DEZL","POKE","AUDI","DECO","DOOD","SNES","GBAS","SPRS","BUZB","CHOM", - "SACO","CRAB","SHAD","BRNG","BUMP","FLEN","CLAS","PSHW","ISTA","ISTB", - "ARRO","ITEM","ITMO","ITMI","ITMN","WANT","PBOM","HIT1","HIT2","HIT3", - "RETI","AIDU","KSPK","LZI1","LZI2","KLIT","FZSM","FZBM","FPRT","SBUS", - "MARB","FUFO","RUST","BLON","VAPE","HTZA","HTZB","SGVA","SGVB","SGVC", - "PGTR","PGF1","PGF2","PGF3","PGBH","DPLR","SPTL","ENM1","GARU","MARR", - "REAP","JITB","CDMO","CDBU","PINE","PPLR","DPPT","AATR","COCO","BDST", - "FROG","CBRA","HOLE","BBRA","EGFG","SMKP","MTYM","THWP","SNOB","ICEB", - "CNDL","DOCH","DUCK","GTRE","CHES","CHIM","DRGN","LZMN","PGSS","ZTCH", - "MKMA","MKMP","RTCH","BOWL","BOWH","BRRL","BRRR","HRSE","TOAH","BFRT", - "OFRT","RFRT","PFRT","ASPK","HBST","HBSO","HBSF","WBLZ","WBLN","FWRK", - "MXCL","RGSP","DRAF","XMS4","XMS5","VIEW" + "RNDM","RPOP","SGNS","FAST","DSHR","BOST","BOSM","KFRE","KINV","KINF", + "WIPD","DRIF","BDRF","DUST","RSHE","FITM","BANA","ORBN","JAWZ","SSMN", + "KRBM","BHOG","BHBM","SPBM","THNS","SINK","SITR","KBLN","DEZL","POKE", + "AUDI","DECO","DOOD","SNES","GBAS","SPRS","BUZB","CHOM","SACO","CRAB", + "SHAD","BRNG","BUMP","FLEN","CLAS","PSHW","ISTA","ISTB","ARRO","ITEM", + "ITMO","ITMI","ITMN","WANT","PBOM","HIT1","HIT2","HIT3","RETI","AIDU", + "KSPK","LZI1","LZI2","KLIT","FZSM","FZBM","FPRT","SBUS","MARB","FUFO", + "RUST","BLON","VAPE","HTZA","HTZB","SGVA","SGVB","SGVC","PGTR","PGF1", + "PGF2","PGF3","PGBH","DPLR","SPTL","ENM1","GARU","MARR","REAP","JITB", + "CDMO","CDBU","PINE","PPLR","DPPT","AATR","COCO","BDST","FROG","CBRA", + "HOLE","BBRA","EGFG","SMKP","MTYM","THWP","SNOB","ICEB","CNDL","DOCH", + "DUCK","GTRE","CHES","CHIM","DRGN","LZMN","PGSS","ZTCH","MKMA","MKMP", + "RTCH","BOWL","BOWH","BRRL","BRRR","HRSE","TOAH","BFRT","OFRT","RFRT", + "PFRT","ASPK","HBST","HBSO","HBSF","WBLZ","WBLN","FWRK","MXCL","RGSP", + "DRAF","GRES","XMS4","XMS5","VIEW" }; // Doesn't work with g++, needs actionf_p1 (don't modify this comment) @@ -1795,45 +1796,76 @@ state_t states[NUMSTATES] = {SPR_RBRD, 1, 4, {A_Chase}, 0, 0, S_RBIRD2}, // S_RBIRD3 // Yellow Spring - {SPR_SPRY, 0, -1, {NULL}, 0, 0, S_NULL}, // S_YELLOWSPRING - {SPR_SPRY, 4, 4, {A_Pain}, 0, 0, S_YELLOWSPRING3}, // S_YELLOWSPRING2 - {SPR_SPRY, 3, 1, {NULL}, 0, 0, S_YELLOWSPRING4}, // S_YELLOWSPRING3 - {SPR_SPRY, 2, 1, {NULL}, 0, 0, S_YELLOWSPRING5}, // S_YELLOWSPRING4 - {SPR_SPRY, 1, 1, {NULL}, 0, 0, S_YELLOWSPRING}, // S_YELLOWSPRING5 + {SPR_SPVY, 0, -1, {NULL}, 0, 0, S_NULL}, // S_YELLOWSPRING1 + {SPR_SPVY, 1, 1, {A_Pain}, 0, 0, S_YELLOWSPRING3}, // S_YELLOWSPRING2 + {SPR_SPVY, 0, 1, {NULL}, 0, 0, S_YELLOWSPRING4}, // S_YELLOWSPRING3 + {SPR_SPVY, 2, 4, {NULL}, 0, 0, S_YELLOWSPRING1}, // S_YELLOWSPRING4 // Red Spring - {SPR_SPRR, 0, -1, {NULL}, 0, 0, S_NULL}, // S_REDSPRING - {SPR_SPRR, 4, 4, {A_Pain}, 0, 0, S_REDSPRING3}, // S_REDSPRING2 - {SPR_SPRR, 3, 1, {NULL}, 0, 0, S_REDSPRING4}, // S_REDSPRING3 - {SPR_SPRR, 2, 1, {NULL}, 0, 0, S_REDSPRING5}, // S_REDSPRING4 - {SPR_SPRR, 1, 1, {NULL}, 0, 0, S_REDSPRING}, // S_REDSPRING5 + {SPR_SPVR, 0, -1, {NULL}, 0, 0, S_NULL}, // S_REDSPRING1 + {SPR_SPVR, 1, 1, {A_Pain}, 0, 0, S_REDSPRING3}, // S_REDSPRING2 + {SPR_SPVR, 0, 1, {NULL}, 0, 0, S_REDSPRING4}, // S_REDSPRING3 + {SPR_SPVR, 2, 4, {NULL}, 0, 0, S_REDSPRING1}, // S_REDSPRING4 // Blue Spring - {SPR_SPRB, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BLUESPRING - {SPR_SPRB, 4, 4, {A_Pain}, 0, 0, S_BLUESPRING3}, // S_BLUESPRING2 - {SPR_SPRB, 3, 1, {NULL}, 0, 0, S_BLUESPRING4}, // S_BLUESPRING3 - {SPR_SPRB, 2, 1, {NULL}, 0, 0, S_BLUESPRING5}, // S_BLUESPRING4 - {SPR_SPRB, 1, 1, {NULL}, 0, 0, S_BLUESPRING}, // S_BLUESPRING5 + {SPR_SPVB, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BLUESPRING1 + {SPR_SPVB, 1, 1, {A_Pain}, 0, 0, S_BLUESPRING3}, // S_BLUESPRING2 + {SPR_SPVB, 0, 1, {NULL}, 0, 0, S_BLUESPRING4}, // S_BLUESPRING3 + {SPR_SPVB, 2, 4, {NULL}, 0, 0, S_BLUESPRING1}, // S_BLUESPRING4 + + // Grey Spring + {SPR_SPVG, 0, -1, {NULL}, 0, 0, S_NULL}, // S_GREYSPRING1 + {SPR_SPVG, 1, 1, {A_Pain}, 0, 0, S_GREYSPRING3}, // S_GREYSPRING2 + {SPR_SPVG, 0, 1, {NULL}, 0, 0, S_GREYSPRING4}, // S_GREYSPRING3 + {SPR_SPVG, 2, 4, {NULL}, 0, 0, S_GREYSPRING1}, // S_GREYSPRING4 // Yellow Diagonal Spring - {SPR_YSPR, 0, -1, {NULL}, 0, 0, S_NULL}, // S_YDIAG1 - {SPR_YSPR, 1, 1, {A_Pain}, 0, 0, S_YDIAG3}, // S_YDIAG2 - {SPR_YSPR, 2, 1, {NULL}, 0, 0, S_YDIAG4}, // S_YDIAG3 - {SPR_YSPR, 3, 1, {NULL}, 0, 0, S_YDIAG5}, // S_YDIAG4 - {SPR_YSPR, 4, 1, {NULL}, 0, 0, S_YDIAG6}, // S_YDIAG5 - {SPR_YSPR, 3, 1, {NULL}, 0, 0, S_YDIAG7}, // S_YDIAG6 - {SPR_YSPR, 2, 1, {NULL}, 0, 0, S_YDIAG8}, // S_YDIAG7 - {SPR_YSPR, 1, 1, {NULL}, 0, 0, S_YDIAG1}, // S_YDIAG8 + {SPR_SPDY, 0, -1, {NULL}, 0, 0, S_NULL}, // S_YDIAG1 + {SPR_SPDY, 1, 1, {A_Pain}, 0, 0, S_YDIAG3}, // S_YDIAG2 + {SPR_SPDY, 0, 1, {NULL}, 0, 0, S_YDIAG4}, // S_YDIAG3 + {SPR_SPDY, 2, 4, {NULL}, 0, 0, S_YDIAG1}, // S_YDIAG4 // Red Diagonal Spring - {SPR_RSPR, 0, -1, {NULL}, 0, 0, S_NULL}, // S_RDIAG1 - {SPR_RSPR, 1, 1, {A_Pain}, 0, 0, S_RDIAG3}, // S_RDIAG2 - {SPR_RSPR, 2, 1, {NULL}, 0, 0, S_RDIAG4}, // S_RDIAG3 - {SPR_RSPR, 3, 1, {NULL}, 0, 0, S_RDIAG5}, // S_RDIAG4 - {SPR_RSPR, 4, 1, {NULL}, 0, 0, S_RDIAG6}, // S_RDIAG5 - {SPR_RSPR, 3, 1, {NULL}, 0, 0, S_RDIAG7}, // S_RDIAG6 - {SPR_RSPR, 2, 1, {NULL}, 0, 0, S_RDIAG8}, // S_RDIAG7 - {SPR_RSPR, 1, 1, {NULL}, 0, 0, S_RDIAG1}, // S_RDIAG8 + {SPR_SPDR, 0, -1, {NULL}, 0, 0, S_NULL}, // S_RDIAG1 + {SPR_SPDR, 1, 1, {A_Pain}, 0, 0, S_RDIAG3}, // S_RDIAG2 + {SPR_SPDR, 0, 1, {NULL}, 0, 0, S_RDIAG4}, // S_RDIAG3 + {SPR_SPDR, 2, 4, {NULL}, 0, 0, S_RDIAG1}, // S_RDIAG4 + + // Blue Diagonal Spring + {SPR_SPDB, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BDIAG1 + {SPR_SPDB, 1, 1, {A_Pain}, 0, 0, S_BDIAG3}, // S_BDIAG2 + {SPR_SPDB, 0, 1, {NULL}, 0, 0, S_BDIAG4}, // S_BDIAG3 + {SPR_SPDB, 2, 4, {NULL}, 0, 0, S_BDIAG1}, // S_BDIAG4 + + // Grey Diagonal Spring + {SPR_SPDG, 0, -1, {NULL}, 0, 0, S_NULL}, // S_GDIAG1 + {SPR_SPDG, 1, 1, {A_Pain}, 0, 0, S_GDIAG3}, // S_GDIAG2 + {SPR_SPDG, 0, 1, {NULL}, 0, 0, S_GDIAG4}, // S_GDIAG3 + {SPR_SPDG, 2, 4, {NULL}, 0, 0, S_GDIAG1}, // S_GDIAG4 + + // Yellow Horizontal Spring + {SPR_SPHY, 0, -1, {NULL}, 0, 0, S_NULL}, // S_YHORIZ1 + {SPR_SPHY, 1, 1, {A_Pain}, 0, 0, S_YHORIZ3}, // S_YHORIZ2 + {SPR_SPHY, 0, 1, {NULL}, 0, 0, S_YHORIZ4}, // S_YHORIZ3 + {SPR_SPHY, 2, 4, {NULL}, 0, 0, S_YHORIZ1}, // S_YHORIZ4 + + // Red Horizontal Spring + {SPR_SPHR, 0, -1, {NULL}, 0, 0, S_NULL}, // S_RHORIZ1 + {SPR_SPHR, 1, 1, {A_Pain}, 0, 0, S_RHORIZ3}, // S_RHORIZ2 + {SPR_SPHR, 0, 1, {NULL}, 0, 0, S_RHORIZ4}, // S_RHORIZ3 + {SPR_SPHR, 2, 4, {NULL}, 0, 0, S_RHORIZ1}, // S_RHORIZ4 + + // Blue Horizontal Spring + {SPR_SPHB, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BHORIZ1 + {SPR_SPHB, 1, 1, {A_Pain}, 0, 0, S_BHORIZ3}, // S_BHORIZ2 + {SPR_SPHB, 0, 1, {NULL}, 0, 0, S_BHORIZ4}, // S_BHORIZ3 + {SPR_SPHB, 2, 4, {NULL}, 0, 0, S_BHORIZ1}, // S_BHORIZ4 + + // Grey Horizontal Spring + {SPR_SPHG, 0, -1, {NULL}, 0, 0, S_NULL}, // S_GHORIZ1 + {SPR_SPHG, 1, 1, {A_Pain}, 0, 0, S_GHORIZ3}, // S_GHORIZ2 + {SPR_SPHG, 0, 1, {NULL}, 0, 0, S_GHORIZ4}, // S_GHORIZ3 + {SPR_SPHG, 2, 4, {NULL}, 0, 0, S_GHORIZ1}, // S_GHORIZ4 // Rain {SPR_RAIN, FF_TRANS50, -1, {NULL}, 0, 0, S_NULL}, // S_RAIN1 @@ -2512,23 +2544,6 @@ state_t states[NUMSTATES] = {SPR_SRBO, 0, 2, {A_BuzzFly}, 0, 0, S_SRB1_GENREX2}, // S_SRB1_GENREX2 // SRB2kart - {SPR_SPRG, 0, -1, {NULL}, 0, 0, S_NULL}, // S_GRAYSPRING - {SPR_SPRG, 4, 4, {A_Pain}, 0, 0, S_GRAYSPRING3}, // S_GRAYSPRING2 - {SPR_SPRG, 3, 1, {NULL}, 0, 0, S_GRAYSPRING4}, // S_GRAYSPRING3 - {SPR_SPRG, 2, 1, {NULL}, 0, 0, S_GRAYSPRING5}, // S_GRAYSPRING4 - {SPR_SPRG, 1, 1, {NULL}, 0, 0, S_GRAYSPRING}, // S_GRAYSPRING5 - - {SPR_NULL, 0, 1, {A_Pain}, 0, 0, S_INVISIBLE}, // S_INVISSPRING - - {SPR_BSPR, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BDIAG1 - {SPR_BSPR, 1, 1, {A_Pain}, 0, 0, S_BDIAG3}, // S_BDIAG2 - {SPR_BSPR, 2, 1, {NULL}, 0, 0, S_BDIAG4}, // S_BDIAG3 - {SPR_BSPR, 3, 1, {NULL}, 0, 0, S_BDIAG5}, // S_BDIAG4 - {SPR_BSPR, 4, 1, {NULL}, 0, 0, S_BDIAG6}, // S_BDIAG5 - {SPR_BSPR, 3, 1, {NULL}, 0, 0, S_BDIAG7}, // S_BDIAG6 - {SPR_BSPR, 2, 1, {NULL}, 0, 0, S_BDIAG8}, // S_BDIAG7 - {SPR_BSPR, 1, 1, {NULL}, 0, 0, S_BDIAG1}, // S_BDIAG8 - {SPR_RNDM, 0|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_RANDOMITEM2}, // S_RANDOMITEM1 {SPR_RNDM, 1|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_RANDOMITEM3}, // S_RANDOMITEM2 {SPR_RNDM, 2|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_RANDOMITEM4}, // S_RANDOMITEM3 @@ -3437,6 +3452,8 @@ state_t states[NUMSTATES] = {SPR_DRAF, 3, 1, {NULL}, 0, 0, S_DRAFTDUST5}, // S_DRAFTDUST4 {SPR_DRAF, 4, 1, {NULL}, 0, 0, S_NULL}, // S_DRAFTDUST5 + {SPR_GRES, FF_ANIMATE|FF_PAPERSPRITE, -1, {NULL}, 2, 4, S_NULL}, // S_TIREGREASE + #ifdef SEENAMES {SPR_NULL, 0, 1, {NULL}, 0, 0, S_NULL}, // S_NAMECHECK #endif @@ -4236,8 +4253,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 32, // reactiontime sfx_None, // attacksound S_NULL, // painstate - 0, // painchance - sfx_spring, // painsound + SKINCOLOR_TEA, // painchance + sfx_s3kb1, // painsound S_NULL, // meleestate S_NULL, // missilestate S_XPLD1, // deathstate @@ -4247,7 +4264,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 24*FRACUNIT, // radius 40*FRACUNIT, // height 0, // display offset - 13*FRACUNIT, // mass + 15*FRACUNIT, // mass 0, // damage sfx_None, // activesound MF_ENEMY|MF_SPECIAL|MF_SHOOTABLE, // flags @@ -4263,8 +4280,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 32, // reactiontime sfx_None, // attacksound S_NULL, // painstate - 0, // painchance - sfx_spring, // painsound + SKINCOLOR_YELLOW, // painchance + sfx_s3kb1, // painsound S_NULL, // meleestate S_NULL, // missilestate S_XPLD1, // deathstate @@ -4274,7 +4291,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 24*FRACUNIT, // radius 40*FRACUNIT, // height 0, // display offset - 26*FRACUNIT, // mass + 25*FRACUNIT, // mass 0, // damage sfx_None, // activesound MF_ENEMY|MF_SPECIAL|MF_SHOOTABLE, // flags @@ -4681,7 +4698,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // display offset 0, // mass 0, // damage - sfx_spring, // activesound + sfx_s3kb1, // activesound MF_SPECIAL|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOCLIPTHING, // flags S_EGGMOBILE2_POGO5 // raisestate }, @@ -6058,54 +6075,27 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_BLUESPRING - 552, // doomednum - S_BLUESPRING, // spawnstate - 1000, // spawnhealth - S_BLUESPRING2, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_spring, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 0, // display offset - 14*FRACUNIT, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID|MF_SPRING|MF_DONTENCOREMAP, // flags - S_BLUESPRING2 // raisestate - }, - { // MT_YELLOWSPRING 550, // doomednum - S_YELLOWSPRING, // spawnstate + S_YELLOWSPRING1,// spawnstate 1000, // spawnhealth S_YELLOWSPRING2,// seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate - 0, // painchance - sfx_spring, // painsound + SKINCOLOR_YELLOW, // painchance + sfx_s3kb1, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height + 48*FRACUNIT, // radius + 32*FRACUNIT, // height 0, // display offset - 26*FRACUNIT, // mass + 25*FRACUNIT, // mass 0, // damage sfx_None, // activesound MF_SOLID|MF_SPRING|MF_DONTENCOREMAP, // flags @@ -6114,23 +6104,23 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = { // MT_REDSPRING 551, // doomednum - S_REDSPRING, // spawnstate + S_REDSPRING1, // spawnstate 1000, // spawnhealth S_REDSPRING2, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate - 0, // painchance - sfx_spring, // painsound + SKINCOLOR_SALMON, // painchance + sfx_s3kb1, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height + 48*FRACUNIT, // radius + 32*FRACUNIT, // height 0, // display offset 40*FRACUNIT, // mass 0, // damage @@ -6139,8 +6129,62 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_REDSPRING2 // raisestate }, + { // MT_BLUESPRING + 552, // doomednum + S_BLUESPRING1, // spawnstate + 1000, // spawnhealth + S_BLUESPRING2, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + SKINCOLOR_PASTEL, // painchance + sfx_s3kb1, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 48*FRACUNIT, // radius + 32*FRACUNIT, // height + 0, // display offset + 64*FRACUNIT, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID|MF_SPRING|MF_DONTENCOREMAP, // flags + S_BLUESPRING2 // raisestate + }, + + { // MT_GREYSPRING + 553, // doomednum + S_GREYSPRING1, // spawnstate + 1000, // spawnhealth + S_GREYSPRING2, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + SKINCOLOR_POPCORN, // painchance + sfx_s3kb1, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 48*FRACUNIT, // radius + 32*FRACUNIT, // height + 0, // display offset + 15*FRACUNIT, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID|MF_SPRING|MF_DONTENCOREMAP, // flags + S_GREYSPRING2 // raisestate + }, + { // MT_YELLOWDIAG - 555, // doomednum + 554, // doomednum S_YDIAG1, // spawnstate 1, // spawnhealth S_YDIAG2, // seestate @@ -6148,26 +6192,26 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate - 0, // painchance - sfx_spring, // painsound + SKINCOLOR_YELLOW, // painchance + sfx_s3kb1, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed - 16*FRACUNIT, // radius - 16*FRACUNIT, // height + 48*FRACUNIT, // radius + 56*FRACUNIT, // height 0, // display offset - 26*FRACUNIT, // mass - 26*FRACUNIT, // damage + 25*FRACUNIT, // mass + 25*FRACUNIT, // damage sfx_None, // activesound MF_SOLID|MF_SPRING|MF_DONTENCOREMAP, // flags S_YDIAG2 // raisestate }, { // MT_REDDIAG - 556, // doomednum + 555, // doomednum S_RDIAG1, // spawnstate 1, // spawnhealth S_RDIAG2, // seestate @@ -6175,16 +6219,16 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate - 0, // painchance - sfx_spring, // painsound + SKINCOLOR_SALMON, // painchance + sfx_s3kb1, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed - 16*FRACUNIT, // radius - 16*FRACUNIT, // height + 48*FRACUNIT, // radius + 56*FRACUNIT, // height 0, // display offset 40*FRACUNIT, // mass 40*FRACUNIT, // damage @@ -6193,6 +6237,168 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_RDIAG2 // raisestate }, + { // MT_BLUEDIAG + 556, // doomednum + S_BDIAG1, // spawnstate + 1, // spawnhealth + S_BDIAG2, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + SKINCOLOR_PASTEL, // painchance + sfx_s3kb1, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 48*FRACUNIT, // radius + 56*FRACUNIT, // height + 0, // display offset + 64*FRACUNIT, // mass + 64*FRACUNIT, // damage + sfx_None, // activesound + MF_SOLID|MF_SPRING|MF_DONTENCOREMAP, // flags + S_BDIAG2 // raisestate + }, + + { // MT_GREYDIAG + 557, // doomednum + S_GDIAG1, // spawnstate + 1, // spawnhealth + S_GDIAG2, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + SKINCOLOR_POPCORN, // painchance + sfx_s3kb1, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 48*FRACUNIT, // radius + 56*FRACUNIT, // height + 0, // display offset + 15*FRACUNIT, // mass + 15*FRACUNIT, // damage + sfx_None, // activesound + MF_SOLID|MF_SPRING|MF_DONTENCOREMAP, // flags + S_GDIAG2 // raisestate + }, + + { // MT_YELLOWHORIZ + 558, // doomednum + S_YHORIZ1, // spawnstate + 1, // spawnhealth + S_YHORIZ2, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + SKINCOLOR_YELLOW, // painchance + sfx_s3kb1, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 48*FRACUNIT, // radius + 56*FRACUNIT, // height + 0, // display offset + 0, // mass + 45*FRACUNIT, // damage + sfx_None, // activesound + MF_SOLID|MF_SPRING|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags + S_YHORIZ2 // raisestate + }, + + { // MT_REDHORIZ + 559, // doomednum + S_RHORIZ1, // spawnstate + 1, // spawnhealth + S_RHORIZ2, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + SKINCOLOR_SALMON, // painchance + sfx_s3kb1, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 48*FRACUNIT, // radius + 56*FRACUNIT, // height + 0, // display offset + 0, // mass + 72*FRACUNIT, // damage + sfx_None, // activesound + MF_SOLID|MF_SPRING|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags + S_RHORIZ2 // raisestate + }, + + { // MT_BLUEHORIZ + 560, // doomednum + S_BHORIZ1, // spawnstate + 1, // spawnhealth + S_BHORIZ2, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + SKINCOLOR_PASTEL, // painchance + sfx_s3kb1, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 48*FRACUNIT, // radius + 56*FRACUNIT, // height + 0, // display offset + 0, // mass + 115*FRACUNIT, // damage + sfx_None, // activesound + MF_SOLID|MF_SPRING|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags + S_BHORIZ2 // raisestate + }, + + { // MT_GREYHORIZ + 561, // doomednum + S_GHORIZ1, // spawnstate + 1, // spawnhealth + S_GHORIZ2, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + SKINCOLOR_POPCORN, // painchance + sfx_s3kb1, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 48*FRACUNIT, // radius + 56*FRACUNIT, // height + 0, // display offset + 0, // mass + 27*FRACUNIT, // damage + sfx_None, // activesound + MF_SOLID|MF_SPRING|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags + S_GHORIZ2 // raisestate + }, + { // MT_BUBBLES 500, // doomednum S_BUBBLES1, // spawnstate @@ -14800,88 +15006,6 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = }, // SRB2kart MT's - - { // MT_GRAYSPRING - 553, // doomednum - S_GRAYSPRING, // spawnstate - 100, // spawnhealth - S_GRAYSPRING2, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_spring, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 0, // display offset - 6*FRACUNIT, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID|MF_SPRING|MF_DONTENCOREMAP, // flags - S_GRAYSPRING2 // raisestate - }, - - { // MT_INVISSPRING - 554, // doomednum - S_INVISIBLE, // spawnstate - 100, // spawnhealth - S_INVISSPRING, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_spring, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 0, // display offset - 6*FRACUNIT, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID|MF_SPRING, // flags - S_INVISSPRING // raisestate - }, - - { // MT_BLUEDIAG - 557, // doomednum - S_BDIAG1, // spawnstate - 1, // spawnhealth - S_BDIAG2, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_spring, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16*FRACUNIT, // radius - 16*FRACUNIT, // height - 0, // display offset - 14*FRACUNIT, // mass - 14*FRACUNIT, // damage - sfx_None, // activesound - MF_SOLID|MF_SPRING|MF_DONTENCOREMAP, // flags - S_BDIAG2 // raisestate - }, - { // MT_RANDOMITEM 2000, // doomednum S_RANDOMITEM1, // spawnstate @@ -20149,6 +20273,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_TIREGREASE + -1, // doomednum + S_TIREGREASE, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 8<destscale = (3*player->mo->scale)/2)); band->color = colors[c]; band->colorized = true; @@ -1637,7 +1637,7 @@ static void K_DrawDraftCombiring(player_t *player, player_t *victim, fixed_t cur curx += stepx; cury += stepy; curz += stepz; - + offset = abs(offset-1) % 3; n--; } @@ -2320,6 +2320,9 @@ fixed_t K_3dKartMovement(player_t *player, boolean onground, fixed_t forwardmove // ACCELCODE!!!1!11! oldspeed = R_PointToDist2(0, 0, player->rmomx, player->rmomy); // FixedMul(P_AproxDistance(player->rmomx, player->rmomy), player->mo->scale); + // Don't calculate the acceleration as ever being above top speed + if (oldspeed > p_speed) + oldspeed = p_speed; newspeed = FixedDiv(FixedDiv(FixedMul(oldspeed, accelmax - p_accel) + FixedMul(p_speed, p_accel), accelmax), ORIG_FRICTION); if (player->kartstuff[k_pogospring]) // Pogo Spring minimum/maximum thrust @@ -3414,7 +3417,7 @@ void K_SpawnDraftDust(mobj_t *mo) ang = mo->player->frameangle; - if (mo->player->kartstuff[k_drift] != 0) + if (mo->player->kartstuff[k_drift] != 0) { drifting = true; ang += (mo->player->kartstuff[k_drift] * ((ANGLE_270 + ANGLE_22h) / 5)); // -112.5 doesn't work. I fucking HATE SRB2 angles @@ -4526,6 +4529,15 @@ static void K_MoveHeldObjects(player_t *player) if (R_PointToDist2(cur->x, cur->y, targx, targy) > 768*FRACUNIT) P_TeleportMove(cur, targx, targy, cur->z); +#ifdef ESLOPE + if (P_IsObjectOnGround(cur)) + { + // Slope values are set in the function, but we DON'T want to use its return value. + P_CalculateShadowFloor(cur, cur->x, cur->y, cur->z, + cur->radius, cur->height, (cur->eflags & MFE_VERTICALFLIP), false); + } +#endif + cur = cur->hnext; } } @@ -4615,6 +4627,9 @@ static void K_MoveHeldObjects(player_t *player) P_TeleportMove(cur, targx, targy, targz); K_FlipFromObject(cur, player->mo); // Update graviflip in real time thanks. +#ifdef HWRENDER + cur->modeltilt = player->mo->modeltilt; +#endif num = (num+1) % 2; cur = cur->hnext; } @@ -5058,6 +5073,29 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (P_IsDisplayPlayer(player)) debtflag->flags2 |= MF2_DONTDRAW; } + + if (player->kartstuff[k_springstars] && (leveltime & 1)) + { + fixed_t randx = P_RandomRange(-40, 40) * player->mo->scale; + fixed_t randy = P_RandomRange(-40, 40) * player->mo->scale; + fixed_t randz = P_RandomRange(0, player->mo->height >> FRACBITS) << FRACBITS; + mobj_t *star = P_SpawnMobj( + player->mo->x + randx, + player->mo->y + randy, + player->mo->z + randz, + MT_KARMAFIREWORK); + + star->color = player->kartstuff[k_springcolor]; + star->flags |= MF_NOGRAVITY; + star->momx = player->mo->momx / 2; + star->momy = player->mo->momy / 2; + star->momz = player->mo->momz / 2; + star->fuse = 12; + star->scale = player->mo->scale; + star->destscale = star->scale / 2; + + player->kartstuff[k_springstars]--; + } } if (player->playerstate == PST_DEAD || player->kartstuff[k_respawn] > 1) // Ensure these are set correctly here @@ -5260,6 +5298,9 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->kartstuff[k_justbumped]) player->kartstuff[k_justbumped]--; + if (player->kartstuff[k_tiregrease]) + player->kartstuff[k_tiregrease]--; + // This doesn't go in HUD update because it has potential gameplay ramifications if (player->karthud[khud_itemblink] && player->karthud[khud_itemblink]-- <= 0) { @@ -5300,17 +5341,6 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) } } - // ??? - /* - if (player->kartstuff[k_jmp] > 1 && onground) - { - S_StartSound(player->mo, sfx_spring); - P_DoJump(player, false); - player->mo->momz *= player->kartstuff[k_jmp]; - player->kartstuff[k_jmp] = 0; - } - */ - if (player->kartstuff[k_comebacktimer]) player->kartstuff[k_comebackmode] = 0; @@ -5440,15 +5470,16 @@ static INT16 K_GetKartDriftValue(player_t *player, fixed_t countersteer) return 0; if (player->kartstuff[k_driftend] != 0) - { return -266*player->kartstuff[k_drift]; // Drift has ended and we are tweaking their angle back a bit - } //basedrift = 90*player->kartstuff[k_drift]; // 450 //basedrift = 93*player->kartstuff[k_drift] - driftweight*3*player->kartstuff[k_drift]/10; // 447 - 303 basedrift = 83*player->kartstuff[k_drift] - (driftweight - 14)*player->kartstuff[k_drift]/5; // 415 - 303 driftangle = abs((252 - driftweight)*player->kartstuff[k_drift]/5); + if (player->kartstuff[k_tiregrease] > 0) // Buff drift-steering while in greasemode + basedrift += (basedrift / greasetics) * player->kartstuff[k_tiregrease]; + return basedrift + FixedMul(driftangle, countersteer); } @@ -5922,7 +5953,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) && NO_HYUDORO && !(HOLDING_ITEM || player->kartstuff[k_itemamount] || player->kartstuff[k_itemroulette] - || player->kartstuff[k_growshrinktimer] // Being disabled during Shrink was unintended but people seemed to be okay with it sooo... + || player->kartstuff[k_growshrinktimer] > 0 || player->kartstuff[k_rocketsneakertimer] || player->kartstuff[k_eggmanexplode])) player->kartstuff[k_userings] = 1; @@ -6490,6 +6521,12 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if (onground) { + fixed_t prevfriction = player->mo->friction; + + // Reduce friction after hitting a horizontal spring + if (player->kartstuff[k_tiregrease]) + player->mo->friction += ((FRACUNIT - prevfriction) / greasetics) * player->kartstuff[k_tiregrease]; + // Friction if (!player->kartstuff[k_offroad]) { @@ -6502,9 +6539,20 @@ void K_MoveKartPlayer(player_t *player, boolean onground) // Karma ice physics if (G_BattleGametype() && player->kartstuff[k_bumper] <= 0) - { player->mo->friction += 1228; + // Wipeout slowdown + if (player->kartstuff[k_spinouttimer] && player->kartstuff[k_wipeoutslow]) + { + if (player->kartstuff[k_offroad]) + player->mo->friction -= 4912; + if (player->kartstuff[k_wipeoutslow] == 1) + player->mo->friction -= 9824; + } + + // Friction was changed, so we must recalculate a bunch of stuff + if (player->mo->friction != prevfriction) + { if (player->mo->friction > FRACUNIT) player->mo->friction = FRACUNIT; if (player->mo->friction < 0) @@ -6515,20 +6563,11 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if (player->mo->movefactor < FRACUNIT) player->mo->movefactor = 19*player->mo->movefactor - 18*FRACUNIT; else - player->mo->movefactor = FRACUNIT; //player->mo->movefactor = ((player->mo->friction - 0xDB34)*(0xA))/0x80; + player->mo->movefactor = FRACUNIT; if (player->mo->movefactor < 32) player->mo->movefactor = 32; } - - // Wipeout slowdown - if (player->kartstuff[k_spinouttimer] && player->kartstuff[k_wipeoutslow]) - { - if (player->kartstuff[k_offroad]) - player->mo->friction -= 4912; - if (player->kartstuff[k_wipeoutslow] == 1) - player->mo->friction -= 9824; - } } K_KartDrift(player, onground); @@ -9560,7 +9599,7 @@ void K_drawKartFreePlay(UINT32 flashtime) return; V_DrawKartString((BASEVIDWIDTH - (LAPS_X+1)) - (12*9), // mirror the laps thingy - LAPS_Y+3, V_SNAPTOBOTTOM|V_SNAPTORIGHT, "FREE PLAY"); + LAPS_Y+3, V_HUDTRANS|V_SNAPTOBOTTOM|V_SNAPTORIGHT, "FREE PLAY"); } static void K_drawDistributionDebugger(void) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 38af4d2e9..7464743c3 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -1405,15 +1405,15 @@ static int lib_pIsFlagAtBase(lua_State *L) static int lib_pSetupLevelSky(lua_State *L) { - INT32 skynum = (INT32)luaL_checkinteger(L, 1); + const char *skytexname = luaL_checkstring(L, 1); player_t *user = NULL; NOHUD if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) // if a player, setup sky for only the player, otherwise setup sky for all players user = *((player_t **)luaL_checkudata(L, 2, META_PLAYER)); if (!user) // global - P_SetupLevelSky(skynum, true); + P_SetupLevelSky(skytexname, true); else if (P_IsLocalPlayer(user)) - P_SetupLevelSky(skynum, false); + P_SetupLevelSky(skytexname, false); return 0; } diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 19292b3d6..0522cb737 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -1487,8 +1487,8 @@ static int mapheaderinfo_get(lua_State *L) lua_pushstring(L, header->forcecharacter); else if (fastcmp(field,"weather")) lua_pushinteger(L, header->weather); - else if (fastcmp(field,"skynum")) - lua_pushinteger(L, header->skynum); + else if (fastcmp(field,"skytexture")) + lua_pushstring(L, header->skytexture); else if (fastcmp(field,"skybox_scalex")) lua_pushinteger(L, header->skybox_scalex); else if (fastcmp(field,"skybox_scaley")) diff --git a/src/m_anigif.c b/src/m_anigif.c index 4e68819bc..4dfc77cb3 100644 --- a/src/m_anigif.c +++ b/src/m_anigif.c @@ -422,7 +422,7 @@ static void GIF_headwrite(void) WRITEUINT16(p, rheight); // colors, aspect, etc - WRITEUINT8(p, 0xF7); + WRITEUINT8(p, 0xFF); // TRANSPARENTPIXEL WRITEUINT8(p, 0x00); WRITEUINT8(p, 0x00); diff --git a/src/m_cheat.c b/src/m_cheat.c index e7e877ada..c24a8014b 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -577,14 +577,14 @@ void Command_Skynum_f(void) if (COM_Argc() != 2) { - CONS_Printf(M_GetText("skynum : change the sky\n")); - CONS_Printf(M_GetText("Current sky is %d\n"), levelskynum); + CONS_Printf(M_GetText("skynum : change the sky\n")); + CONS_Printf(M_GetText("Current sky is %s\n"), levelskytexture); return; } CONS_Printf(M_GetText("Previewing sky %s...\n"), COM_Argv(1)); - P_SetupLevelSky(atoi(COM_Argv(1)), false); + P_SetupLevelSky(COM_Argv(1), false); } void Command_Weather_f(void) diff --git a/src/m_menu.c b/src/m_menu.c index 01cfabac6..166b115d6 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -522,7 +522,7 @@ static menuitem_t PlaybackMenu[] = {IT_CALL | IT_STRING, "M_PREW", "Rewind", M_PlaybackRewind, 20}, {IT_CALL | IT_STRING, "M_PPAUSE", "Pause", M_PlaybackPause, 36}, - {IT_CALL | IT_STRING, "M_PFFWD", "Fast-Foward", M_PlaybackFastForward, 52}, + {IT_CALL | IT_STRING, "M_PFFWD", "Fast-Forward", M_PlaybackFastForward, 52}, {IT_CALL | IT_STRING, "M_PSTEPB", "Backup Frame", M_PlaybackRewind, 20}, {IT_CALL | IT_STRING, "M_PRESUM", "Resume", M_PlaybackPause, 36}, {IT_CALL | IT_STRING, "M_PFADV", "Advance Frame", M_PlaybackAdvance, 52}, @@ -8433,7 +8433,11 @@ static void M_ConnectMenu(INT32 choice) // first page of servers serverlistpage = 0; if (ms_RoomId < 0) + { M_RoomMenu(0); // Select a room instead of staring at an empty list + // This prevents us from returning to the modified game alert. + currentMenu->prevMenu = &MP_MainDef; + } else M_SetupNextMenu(&MP_ConnectDef); itemOn = 0; diff --git a/src/mserv.c b/src/mserv.c index 29aa99fae..c7344b16a 100644 --- a/src/mserv.c +++ b/src/mserv.c @@ -661,19 +661,11 @@ FUNCMATH static const char *int2str(INT32 n) #ifndef NONET static INT32 ConnectionFailed(void) { - time(&MSLastPing); con_state = MSCS_FAILED; CONS_Alert(CONS_ERROR, M_GetText("Connection to Master Server failed\n")); CloseConnection(); return MS_CONNECT_ERROR; } - -static INT32 ConnectionFailedwerrno(int no) -{ - CONS_Alert(CONS_ERROR, M_GetText("Master Server socket error: %s\n"), - strerror(no)); - return ConnectionFailed(); -} #endif /** Tries to register the local game server on the master server. @@ -690,43 +682,57 @@ static INT32 AddToMasterServer(boolean firstadd) msg_server_t *info = (msg_server_t *)msg.buffer; INT32 room = -1; fd_set tset; + time_t timestamp = time(NULL); UINT32 signature, tmp; const char *insname; - if (socket_fd == (SOCKET_TYPE)ERRSOCKET)/* Woah, our socket was closed! */ - { - if (MS_Connect(GetMasterServerIP(), GetMasterServerPort(), 0)) - return ConnectionFailedwerrno(errno); - } - M_Memcpy(&tset, &wset, sizeof (tset)); res = select(255, NULL, &tset, NULL, &select_timeout); - if (res == ERRSOCKET) - return ConnectionFailedwerrno(errno); - if (res == 0)/* nothing selected */ + if (res != ERRSOCKET && !res) { - /* - Timeout next call because SendPingToMasterServer - (our calling function) already calls this once - every two minutes. - */ - if (retry++ == 1) + if (retry++ > 30) // an about 30 second timeout { retry = 0; CONS_Alert(CONS_ERROR, M_GetText("Master Server timed out\n")); + MSLastPing = timestamp; return ConnectionFailed(); } return MS_CONNECT_ERROR; } retry = 0; + /* + Somehow we can still select our old socket despite it being closed(?). + Atleast, that's what I THINK is happening. Anyway, we have to check that we + haven't open a socket, and actually open it! + */ + /*if (res == ERRSOCKET)*//* wtf? no! */ + if (socket_fd == (SOCKET_TYPE)ERRSOCKET) + { + if (MS_Connect(GetMasterServerIP(), GetMasterServerPort(), 0)) + { + CONS_Alert(CONS_ERROR, M_GetText("Master Server socket error #%u: %s\n"), errno, strerror(errno)); + MSLastPing = timestamp; + return ConnectionFailed(); + } + } // so, the socket is writable, but what does that mean, that the connection is // ok, or bad... let see that! j = (socklen_t)sizeof (i); - if (getsockopt(socket_fd, SOL_SOCKET, SO_ERROR, (char *)&i, &j) == ERRSOCKET) - return ConnectionFailedwerrno(errno); + getsockopt(socket_fd, SOL_SOCKET, SO_ERROR, (char *)&i, &j); + /* + This is also wrong. If getsockopt fails, i doesn't have to be set. Plus, if + it is set (which it appearantly is on linux), we check errno anyway. And in + the case that i is returned as normal, we don't even report the correct + value! So we accomplish NOTHING, except returning due to dumb luck. + If you care, fix this--I don't. -James (R.) + */ if (i) // it was bad - return ConnectionFailedwerrno(i); + { + CONS_Alert(CONS_ERROR, M_GetText("Master Server socket error #%u: %s\n"), errno, strerror(errno)); + MSLastPing = timestamp; + return ConnectionFailed(); + } #ifdef PARANOIA if (ms_RoomId <= 0) @@ -759,12 +765,15 @@ static INT32 AddToMasterServer(boolean firstadd) msg.length = (UINT32)sizeof (msg_server_t); msg.room = 0; if (MS_Write(&msg) < 0) + { + MSLastPing = timestamp; return ConnectionFailed(); + } if(con_state != MSCS_REGISTERED) CONS_Printf(M_GetText("Master Server update successful.\n")); - time(&MSLastPing); + MSLastPing = timestamp; con_state = MSCS_REGISTERED; CloseConnection(); #endif diff --git a/src/p_enemy.c b/src/p_enemy.c index 7baca2adc..9569b2c4c 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3558,6 +3558,8 @@ void A_BubbleCheck(mobj_t *actor) // void A_AttractChase(mobj_t *actor) { + fixed_t z; + #ifdef HAVE_BLUA if (LUA_CallAction("A_AttractChase", actor)) return; @@ -3601,7 +3603,12 @@ void A_AttractChase(mobj_t *actor) { fixed_t offz = FixedMul(80*actor->target->scale, FINESINE(FixedAngle((90 - (9 * abs(10 - actor->extravalue1))) << FRACBITS) >> ANGLETOFINESHIFT)); //P_SetScale(actor, (actor->destscale = actor->target->scale)); - P_TeleportMove(actor, actor->target->x, actor->target->y, actor->target->z + actor->target->height + offz); + z = actor->target->z; + if (( actor->eflags & MFE_VERTICALFLIP )) + z -= actor->height + offz; + else + z += actor->target->height + offz; + P_TeleportMove(actor, actor->target->x, actor->target->y, z); actor->extravalue1++; } } @@ -3628,10 +3635,15 @@ void A_AttractChase(mobj_t *actor) fixed_t dist = (actor->target->radius/4) * (16 - actor->extravalue1); P_SetScale(actor, (actor->destscale = actor->target->scale - ((actor->target->scale/14) * actor->extravalue1))); + z = actor->target->z; + if (( actor->eflags & MFE_VERTICALFLIP )) + z += actor->target->height - actor->height - 24 * actor->target->scale; + else + z += 24 * actor->target->scale; P_TeleportMove(actor, actor->target->x + FixedMul(dist, FINECOSINE(actor->angle >> ANGLETOFINESHIFT)), actor->target->y + FixedMul(dist, FINESINE(actor->angle >> ANGLETOFINESHIFT)), - actor->target->z + (24 * actor->target->scale)); + z); actor->angle += ANG30; actor->extravalue1++; @@ -8309,7 +8321,11 @@ void A_ItemPop(mobj_t *actor) void A_JawzChase(mobj_t *actor) { + const fixed_t currentspeed = R_PointToDist2(0, 0, actor->momx, actor->momy); player_t *player; + fixed_t thrustamount = 0; + fixed_t frictionsafety = (actor->friction == 0) ? 1 : actor->friction; + fixed_t topspeed = actor->movefactor; #ifdef HAVE_BLUA if (LUA_CallAction("A_JawzChase", actor)) return; @@ -8322,20 +8338,100 @@ void A_JawzChase(mobj_t *actor) if (actor->tracer->health) { + const angle_t targetangle = R_PointToAngle2(actor->x, actor->y, actor->tracer->x, actor->tracer->y); mobj_t *ret; + angle_t angledelta = actor->angle - targetangle; + boolean turnclockwise = true; + + if (G_RaceGametype()) + { + const fixed_t distbarrier = FixedMul(512*mapobjectscale, FRACUNIT + ((gamespeed-1) * (FRACUNIT/4))); + const fixed_t distaway = P_AproxDistance(actor->tracer->x - actor->x, actor->tracer->y - actor->y); + if (distaway < distbarrier) + { + if (actor->tracer->player) + { + fixed_t speeddifference = abs(topspeed - min(actor->tracer->player->speed, K_GetKartSpeed(actor->tracer->player, false))); + topspeed = topspeed - FixedMul(speeddifference, FRACUNIT-FixedDiv(distaway, distbarrier)); + } + } + } + + if (angledelta != 0) + { + angle_t MAX_JAWZ_TURN = ANGLE_90/15; // We can turn a maximum of 6 degrees per frame at regular max speed + // MAX_JAWZ_TURN gets stronger the slower the top speed of jawz + if (topspeed < actor->movefactor) + { + if (topspeed == 0) + { + MAX_JAWZ_TURN = ANGLE_180; + } + else + { + fixed_t anglemultiplier = FixedDiv(actor->movefactor, topspeed); + MAX_JAWZ_TURN += FixedAngle(FixedMul(AngleFixed(MAX_JAWZ_TURN), anglemultiplier)); + } + } + + if (angledelta > ANGLE_180) + { + angledelta = InvAngle(angledelta); + turnclockwise = false; + } + + if (angledelta > MAX_JAWZ_TURN) + { + angledelta = MAX_JAWZ_TURN; + } + + if (turnclockwise) + { + actor->angle -= angledelta; + } + else + { + actor->angle += angledelta; + } + } ret = P_SpawnMobj(actor->tracer->x, actor->tracer->y, actor->tracer->z, MT_PLAYERRETICULE); P_SetTarget(&ret->target, actor->tracer); ret->frame |= ((leveltime % 10) / 2) + 5; ret->color = actor->cvmem; - - P_Thrust(actor, R_PointToAngle2(actor->x, actor->y, actor->tracer->x, actor->tracer->y), (7*actor->movefactor)/64); - return; } else P_SetTarget(&actor->tracer, NULL); } + if (!P_IsObjectOnGround(actor)) + { + // No friction in the air + frictionsafety = FRACUNIT; + } + + if (currentspeed >= topspeed) + { + // Thrust as if you were at top speed, slow down naturally + thrustamount = FixedDiv(topspeed, frictionsafety) - topspeed; + } + else + { + const fixed_t beatfriction = FixedDiv(currentspeed, frictionsafety) - currentspeed; + // Thrust to immediately get to top speed + thrustamount = beatfriction + FixedDiv(topspeed - currentspeed, frictionsafety); + } + + if (!actor->tracer) + { + actor->angle = R_PointToAngle2(0, 0, actor->momx, actor->momy); + } + + P_Thrust(actor, actor->angle, thrustamount); + + if ((actor->tracer != NULL) && (actor->tracer->health > 0)) + return; + if (actor->extravalue1) // Disable looking by setting this return; diff --git a/src/p_inter.c b/src/p_inter.c index de14b3db9..8cf9703d0 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -3306,12 +3306,12 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings) // 20 is the ring cap in kart if (num_rings > 20) - num_rings = 20; + num_rings = 20; else if (num_rings <= 0) return; // Cap the maximum loss automatically to 2 in ring debt - if (player->kartstuff[k_rings] <= 0 && num_rings > 2) + if (player->kartstuff[k_rings] <= 0 && num_rings > 2) num_rings = 2; P_GivePlayerRings(player, -num_rings); diff --git a/src/p_local.h b/src/p_local.h index bc25affd4..d4da9fe29 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -227,6 +227,7 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state); boolean P_SetMobjState(mobj_t *mobj, statenum_t state); //void P_RunShields(void); void P_RunOverlays(void); +fixed_t P_CalculateShadowFloor(mobj_t *mobj, fixed_t x, fixed_t y, fixed_t z, fixed_t radius, fixed_t height, boolean flip, boolean player); void P_RunShadows(void); void P_MobjThinker(mobj_t *mobj); boolean P_RailThinker(mobj_t *mobj); diff --git a/src/p_map.c b/src/p_map.c index d99105005..d4f2a94fa 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -113,14 +113,18 @@ boolean P_TeleportMove(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z) // MOVEMENT ITERATOR FUNCTIONS // ========================================================================= +//#define TELEPORTJANK + boolean P_DoSpring(mobj_t *spring, mobj_t *object) { //INT32 pflags; const fixed_t hscale = mapobjectscale + (mapobjectscale - object->scale); const fixed_t vscale = mapobjectscale + (object->scale - mapobjectscale); - fixed_t offx, offy; fixed_t vertispeed = spring->info->mass; fixed_t horizspeed = spring->info->damage; + UINT8 starcolor = (spring->info->painchance % MAXTRANSLATIONS); + fixed_t savemomx = 0; + fixed_t savemomy = 0; if (object->eflags & MFE_SPRUNG) // Object was already sprung this tic return false; @@ -142,29 +146,36 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) object->eflags |= MFE_SPRUNG; // apply this flag asap! spring->flags &= ~(MF_SOLID|MF_SPECIAL); // De-solidify +#ifdef TELEPORTJANK if (horizspeed && vertispeed) // Mimic SA { object->momx = object->momy = 0; P_TryMove(object, spring->x, spring->y, true); } +#endif if (spring->eflags & MFE_VERTICALFLIP) vertispeed *= -1; + // Vertical springs teleport you on TOP of them. if (vertispeed > 0) object->z = spring->z + spring->height + 1; else if (vertispeed < 0) object->z = spring->z - object->height - 1; else { + fixed_t offx, offy; + // Horizontal springs teleport you in FRONT of them. + savemomx = object->momx; + savemomy = object->momy; object->momx = object->momy = 0; // Overestimate the distance to position you at offx = P_ReturnThrustX(spring, spring->angle, (spring->radius + object->radius + 1) * 2); offy = P_ReturnThrustY(spring, spring->angle, (spring->radius + object->radius + 1) * 2); - // Make it square by clipping + // Then clip it down to a square, so it matches the hitbox size. if (offx > (spring->radius + object->radius + 1)) offx = spring->radius + object->radius + 1; else if (offx < -(spring->radius + object->radius + 1)) @@ -175,27 +186,94 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) else if (offy < -(spring->radius + object->radius + 1)) offy = -(spring->radius + object->radius + 1); - // Set position! P_TryMove(object, spring->x + offx, spring->y + offy, true); } if (vertispeed) - object->momz = FixedMul(vertispeed,FixedSqrt(FixedMul(vscale, spring->scale))); + object->momz = FixedMul(vertispeed, FixedSqrt(FixedMul(vscale, spring->scale))); if (horizspeed) { - if (!object->player) - P_InstaThrustEvenIn2D(object, spring->angle, FixedMul(horizspeed,FixedSqrt(FixedMul(hscale, spring->scale)))); + angle_t finalAngle = spring->angle; + fixed_t finalSpeed = horizspeed; + fixed_t objectSpeed; + + if (object->player) + objectSpeed = object->player->speed; else + objectSpeed = R_PointToDist2(0, 0, savemomx, savemomy); + + if (!vertispeed) { - fixed_t finalSpeed = FixedDiv(horizspeed, hscale); - fixed_t pSpeed = object->player->speed; + // Scale to gamespeed + finalSpeed = FixedMul(finalSpeed, K_GetKartGameSpeedScalar(gamespeed)); - if (pSpeed > finalSpeed) - finalSpeed = pSpeed; + // Reflect your momentum angle against the surface of horizontal springs. + // This makes it a bit more interesting & unique than just being a speed boost in a pre-defined direction + if (savemomx || savemomy) + { + angle_t momang; + INT32 angoffset; + boolean subtract = false; - P_InstaThrustEvenIn2D(object, spring->angle, FixedMul(finalSpeed,FixedSqrt(FixedMul(hscale, spring->scale)))); + momang = R_PointToAngle2(0, 0, savemomx, savemomy); + + angoffset = momang; + angoffset -= spring->angle; // Subtract + + // Flip on wrong side + if ((angle_t)angoffset > ANGLE_180) + { + angoffset = InvAngle((angle_t)angoffset); + subtract = !subtract; + } + + // Fix going directly against the spring's angle sending you the wrong way + if ((spring->angle - momang) > ANGLE_90) + angoffset = ANGLE_180 - angoffset; + + // Offset is reduced to cap it (90 / 2 = max of 45 degrees) + angoffset /= 2; + + // Reduce further based on how slow your speed is compared to the spring's speed + if (finalSpeed > objectSpeed) + angoffset = FixedDiv(angoffset, FixedDiv(finalSpeed, objectSpeed)); + + if (subtract) + angoffset = (signed)(spring->angle) - angoffset; + else + angoffset = (signed)(spring->angle) + angoffset; + + finalAngle = angoffset; + } } + + if (object->player) + { + // Less friction when hitting horizontal springs + if (!vertispeed) + { + if (!object->player->kartstuff[k_tiregrease]) + { + UINT8 i; + for (i = 0; i < 2; i++) + { + mobj_t *grease; + grease = P_SpawnMobj(object->x, object->y, object->z, MT_TIREGREASE); + P_SetTarget(&grease->target, object); + grease->angle = R_PointToAngle2(0, 0, object->momx, object->momy); + grease->extravalue1 = i; + } + } + + object->player->kartstuff[k_tiregrease] = greasetics; //FixedMul(greasetics << FRACBITS, finalSpeed/72) >> FRACBITS + } + } + + // Horizontal speed is used as a minimum thrust, not a direct replacement + finalSpeed = max(objectSpeed, finalSpeed); + + P_InstaThrustEvenIn2D(object, finalAngle, FixedMul(finalSpeed, FixedSqrt(FixedMul(hscale, spring->scale)))); } // Re-solidify @@ -208,46 +286,12 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) if (spring->flags & MF_ENEMY) // Spring shells P_SetTarget(&spring->target, object); - if (horizspeed && object->player->cmd.forwardmove == 0 && object->player->cmd.sidemove == 0) - { - object->angle = spring->angle; - - if (!demo.playback || P_AnalogMove(object->player)) - { - if (object->player == &players[consoleplayer]) - localangle[0] = spring->angle; - else if (object->player == &players[displayplayers[1]]) - localangle[1] = spring->angle; - else if (object->player == &players[displayplayers[2]]) - localangle[2] = spring->angle; - else if (object->player == &players[displayplayers[3]]) - localangle[3] = spring->angle; - } - } - - //pflags = object->player->pflags & (PF_JUMPED|PF_SPINNING|PF_THOKKED); // I still need these. P_ResetPlayer(object->player); - /* // SRB2kart - Springs don't need to change player state in kart. - if (P_MobjFlip(object)*vertispeed > 0) - P_SetPlayerMobjState(object, S_PLAY_SPRING); - else if (P_MobjFlip(object)*vertispeed < 0) - P_SetPlayerMobjState(object, S_PLAY_FALL1); - else // horizontal spring - { - if (pflags & (PF_JUMPED|PF_SPINNING) && object->player->panim == PA_ROLL) - object->player->pflags = pflags; - else - P_SetPlayerMobjState(object, S_PLAY_RUN1); - } - - if (spring->info->painchance) - { - object->player->pflags |= PF_JUMPED; - P_SetPlayerMobjState(object, S_PLAY_ATK1); - } - */ + object->player->kartstuff[k_springstars] = max(vertispeed, horizspeed) / FRACUNIT / 2; + object->player->kartstuff[k_springcolor] = starcolor; } + return true; } @@ -1163,6 +1207,7 @@ static boolean PIT_CheckThing(mobj_t *thing) //else if (tmz > thzh - sprarea && tmz < thzh) // Don't damage people springing up / down return true; } + // missiles can hit other things if (tmthing->flags & MF_MISSILE || tmthing->type == MT_SHELL) { @@ -2892,14 +2937,24 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) P_HandleSlopeLanding(thing, tmfloorslope); if (thing->momz <= 0) + { thing->standingslope = tmfloorslope; +#ifdef HWRENDER + thing->modeltilt = thing->standingslope; +#endif + } } else if (thing->z+thing->height >= tmceilingz && (thing->eflags & MFE_VERTICALFLIP)) { if (!startingonground && tmceilingslope) P_HandleSlopeLanding(thing, tmceilingslope); if (thing->momz >= 0) + { thing->standingslope = tmceilingslope; +#ifdef HWRENDER + thing->modeltilt = thing->standingslope; +#endif + } } } else // don't set standingslope if you're not going to clip against it @@ -4702,7 +4757,7 @@ fixed_t P_FloorzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height) if (!(rover->flags & FF_EXISTS)) continue; - if ((!(rover->flags & FF_SOLID || rover->flags & FF_QUICKSAND) || (rover->flags & FF_SWIMMABLE))) + if (!((rover->flags & FF_SOLID) || (rover->flags & FF_QUICKSAND)) || (rover->flags & FF_SWIMMABLE)) continue; topheight = *rover->topheight; diff --git a/src/p_mobj.c b/src/p_mobj.c index 9919b2266..3694fc919 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1848,6 +1848,9 @@ void P_XYMovement(mobj_t *mo) // Now compare the Zs of the different quantizations if (oldangle-newangle > ANG30 && oldangle-newangle < ANGLE_180) { // Allow for a bit of sticking - this value can be adjusted later mo->standingslope = oldslope; +#ifdef HWRENDER + mo->modeltilt = mo->standingslope; +#endif P_SlopeLaunch(mo); //CONS_Printf("launched off of slope - "); @@ -1937,7 +1940,7 @@ void P_XYMovement(mobj_t *mo) #endif //{ SRB2kart stuff - if (mo->type == MT_ORBINAUT || mo->type == MT_JAWZ_DUD || mo->type == MT_JAWZ || mo->type == MT_BALLHOG || mo->type == MT_FLINGRING) //(mo->type == MT_JAWZ && !mo->tracer)) + if (mo->type == MT_BALLHOG || mo->type == MT_FLINGRING) //(mo->type == MT_JAWZ && !mo->tracer)) return; if (mo->player && (mo->player->kartstuff[k_spinouttimer] && !mo->player->kartstuff[k_wipeoutslow]) && mo->player->speed <= K_GetKartSpeed(mo->player, false)/2) @@ -2421,6 +2424,9 @@ static boolean P_ZMovement(mobj_t *mo) if (((mo->eflags & MFE_VERTICALFLIP) ? tmceilingslope : tmfloorslope) && (mo->type != MT_STEAM)) { mo->standingslope = (mo->eflags & MFE_VERTICALFLIP) ? tmceilingslope : tmfloorslope; +#ifdef HWRENDER + mo->modeltilt = mo->standingslope; +#endif P_ReverseQuantizeMomentumToSlope(&mom, mo->standingslope); } #endif @@ -6199,13 +6205,178 @@ static void P_RemoveOverlay(mobj_t *thing) } } +// Simplified version of a code bit in P_MobjFloorZ +static fixed_t P_ShadowSlopeZ(pslope_t *slope, fixed_t x, fixed_t y, fixed_t radius, boolean ceiling) +{ + fixed_t testx, testy; + + if (slope->d.x < 0) + testx = radius; + else + testx = -radius; + + if (slope->d.y < 0) + testy = radius; + else + testy = -radius; + + if ((slope->zdelta > 0) ^ !!(ceiling)) + { + testx = -testx; + testy = -testy; + } + + testx += x; + testy += y; + + return P_GetZAt(slope, testx, testy); +} + +// Sets standingslope/modeltilt, returns z position for shadows; used also for stuff like bananas +// (I would've preferred to be able to return both the slope & z, but I'll take what I can get...) +fixed_t P_CalculateShadowFloor(mobj_t *mobj, fixed_t x, fixed_t y, fixed_t z, fixed_t radius, fixed_t height, boolean flip, boolean player) +{ + fixed_t newz; + sector_t *sec; +#ifdef ESLOPE + pslope_t *slope = NULL; +#endif + + sec = R_PointInSubsector(x, y)->sector; + + if (flip) + { +#ifdef ESLOPE + if (sec->c_slope) + { + slope = sec->c_slope; + newz = P_ShadowSlopeZ(slope, x, y, radius, true); + } + else +#endif + newz = sec->ceilingheight; + } + else + { +#ifdef ESLOPE + if (sec->f_slope) + { + slope = sec->f_slope; + newz = P_ShadowSlopeZ(slope, x, y, radius, false); + } + else +#endif + newz = sec->floorheight; + } + + // Check FOFs for a better suited slope + if (sec->ffloors) + { + ffloor_t *rover; + + for (rover = sec->ffloors; rover; rover = rover->next) + { + fixed_t top, bottom; + fixed_t d1, d2; + + if (!(rover->flags & FF_EXISTS)) + continue; + + if ((!(((rover->flags & FF_BLOCKPLAYER && player) + || (rover->flags & FF_BLOCKOTHERS && !player)) + || (rover->flags & FF_QUICKSAND)) + || (rover->flags & FF_SWIMMABLE))) + continue; + +#ifdef ESLOPE + if (*rover->t_slope) + top = P_ShadowSlopeZ(*rover->t_slope, x, y, radius, false); + else +#endif + top = *rover->topheight; + +#ifdef ESLOPE + if (*rover->b_slope) + bottom = P_ShadowSlopeZ(*rover->b_slope, x, y, radius, true); + else +#endif + bottom = *rover->bottomheight; + + if (flip) + { + if (rover->flags & FF_QUICKSAND) + { + if (z < top && (z + height) > bottom) + { + if (newz > (z + height)) + { + newz = (z + height); + slope = NULL; + } + } + continue; + } + + d1 = (z + height) - (top + ((bottom - top)/2)); + d2 = z - (top + ((bottom - top)/2)); + + if (bottom < newz && abs(d1) < abs(d2)) + { + newz = bottom; +#ifdef ESLOPE + if (*rover->b_slope) + slope = *rover->b_slope; +#endif + } + } + else + { + if (rover->flags & FF_QUICKSAND) + { + if (z < top && (z + height) > bottom) + { + if (newz < z) + { + newz = z; + slope = NULL; + } + } + continue; + } + + d1 = z - (bottom + ((top - bottom)/2)); + d2 = (z + height) - (bottom + ((top - bottom)/2)); + + if (top > newz && abs(d1) < abs(d2)) + { + newz = top; +#ifdef ESLOPE + if (*rover->t_slope) + slope = *rover->t_slope; +#endif + } + } + } + } + +#if 0 + mobj->standingslope = slope; +#endif +#ifdef HWRENDER + mobj->modeltilt = slope; +#endif + + return newz; +} + void P_RunShadows(void) { mobj_t *mobj, *next, *dest; for (mobj = shadowcap; mobj; mobj = next) { - fixed_t floorz; + boolean flip; + fixed_t newz; next = mobj->hnext; P_SetTarget(&mobj->hnext, NULL); @@ -6216,16 +6387,22 @@ void P_RunShadows(void) continue; // shouldn't you already be dead? } - if (mobj->target->player) - floorz = mobj->target->floorz; - else // FOR SOME REASON, plain floorz is not reliable for normal objects, only players?! - floorz = P_FloorzAtPos(mobj->target->x, mobj->target->y, mobj->target->z, mobj->target->height); - K_MatchGenericExtraFlags(mobj, mobj->target); + flip = (mobj->eflags & MFE_VERTICALFLIP); - if (((mobj->target->eflags & MFE_VERTICALFLIP) && mobj->target->z+mobj->target->height > mobj->target->ceilingz) - || (!(mobj->target->eflags & MFE_VERTICALFLIP) && mobj->target->z < floorz)) - mobj->flags2 |= MF2_DONTDRAW; + newz = P_CalculateShadowFloor(mobj, mobj->target->x, mobj->target->y, mobj->target->z, + mobj->target->radius, mobj->target->height, flip, (mobj->target->player != NULL)); + + if (flip) + { + if ((mobj->target->z + mobj->target->height) > newz) + mobj->flags2 |= MF2_DONTDRAW; + } + else + { + if (mobj->target->z < newz) + mobj->flags2 |= MF2_DONTDRAW; + } // First scale to the same radius P_SetScale(mobj, FixedDiv(mobj->target->radius, mobj->info->radius)); @@ -6237,13 +6414,12 @@ void P_RunShadows(void) P_TeleportMove(mobj, dest->x, dest->y, mobj->target->z); - if (((mobj->eflags & MFE_VERTICALFLIP) && (mobj->ceilingz > mobj->z+mobj->height)) - || (!(mobj->eflags & MFE_VERTICALFLIP) && (floorz < mobj->z))) + if ((flip && newz > (mobj->z + mobj->height)) || (!flip && newz < mobj->z)) { INT32 i; fixed_t prevz; - mobj->z = (mobj->eflags & MFE_VERTICALFLIP ? mobj->ceilingz : floorz); + mobj->z = newz; for (i = 0; i < MAXFFLOORS; i++) { @@ -6255,7 +6431,7 @@ void P_RunShadows(void) // Check new position to see if you should still be on that ledge P_TeleportMove(mobj, dest->x, dest->y, mobj->z); - mobj->z = (mobj->eflags & MFE_VERTICALFLIP ? mobj->ceilingz : floorz); + mobj->z = newz; if (mobj->z == prevz) break; @@ -7935,9 +8111,18 @@ void P_MobjThinker(mobj_t *mobj) else { fixed_t finalspeed = mobj->movefactor; + const fixed_t currentspeed = R_PointToDist2(0, 0, mobj->momx, mobj->momy); + fixed_t thrustamount = 0; + fixed_t frictionsafety = (mobj->friction == 0) ? 1 : mobj->friction; mobj_t *ghost = P_SpawnGhostMobj(mobj); ghost->colorized = true; // already has color! + if (!grounded) + { + // No friction in the air + frictionsafety = FRACUNIT; + } + mobj->angle = R_PointToAngle2(0, 0, mobj->momx, mobj->momy); if (mobj->health <= 5) { @@ -7946,7 +8131,19 @@ void P_MobjThinker(mobj_t *mobj) finalspeed = FixedMul(finalspeed, FRACUNIT-FRACUNIT/4); } - P_InstaThrust(mobj, mobj->angle, finalspeed); + if (currentspeed >= finalspeed) + { + // Thrust as if you were at top speed, slow down naturally + thrustamount = FixedDiv(finalspeed, frictionsafety) - finalspeed; + } + else + { + const fixed_t beatfriction = FixedDiv(currentspeed, frictionsafety) - currentspeed; + // Thrust to immediately get to top speed + thrustamount = beatfriction + FixedDiv(finalspeed - currentspeed, frictionsafety); + } + + P_Thrust(mobj, mobj->angle, thrustamount); if (grounded) { @@ -7968,9 +8165,6 @@ void P_MobjThinker(mobj_t *mobj) case MT_JAWZ: { sector_t *sec2; - fixed_t topspeed = mobj->movefactor; - fixed_t distbarrier = 512*mapobjectscale; - fixed_t distaway; mobj_t *ghost = P_SpawnGhostMobj(mobj); if (mobj->target && !P_MobjWasRemoved(mobj->target) && mobj->target->player) @@ -7984,37 +8178,7 @@ void P_MobjThinker(mobj_t *mobj) if (leveltime % TICRATE == 0) S_StartSound(mobj, mobj->info->activesound); - distbarrier = FixedMul(distbarrier, FRACUNIT + ((gamespeed-1) * (FRACUNIT/4))); - - if (G_RaceGametype() && mobj->tracer) - { - distaway = P_AproxDistance(mobj->tracer->x - mobj->x, mobj->tracer->y - mobj->y); - if (distaway < distbarrier) - { - if (mobj->tracer->player) - { - fixed_t speeddifference = abs(topspeed - min(mobj->tracer->player->speed, K_GetKartSpeed(mobj->tracer->player, false))); - topspeed = topspeed - FixedMul(speeddifference, FRACUNIT-FixedDiv(distaway, distbarrier)); - } - } - } - - if (G_BattleGametype()) - { - mobj->friction -= 1228; - if (mobj->friction > FRACUNIT) - mobj->friction = FRACUNIT; - if (mobj->friction < 0) - mobj->friction = 0; - } - - mobj->angle = R_PointToAngle2(0, 0, mobj->momx, mobj->momy); - P_InstaThrust(mobj, mobj->angle, topspeed); - - if (mobj->tracer) - mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->tracer->x, mobj->tracer->y); - else - mobj->angle = R_PointToAngle2(0, 0, mobj->momx, mobj->momy); + // Movement handling has ALL been moved to A_JawzChase K_DriftDustHandling(mobj); @@ -8042,6 +8206,9 @@ void P_MobjThinker(mobj_t *mobj) else { mobj_t *ghost = P_SpawnGhostMobj(mobj); + const fixed_t currentspeed = R_PointToDist2(0, 0, mobj->momx, mobj->momy); + fixed_t frictionsafety = (mobj->friction == 0) ? 1 : mobj->friction; + fixed_t thrustamount = 0; if (mobj->target && !P_MobjWasRemoved(mobj->target) && mobj->target->player) { @@ -8049,8 +8216,26 @@ void P_MobjThinker(mobj_t *mobj) ghost->colorized = true; } + if (!grounded) + { + // No friction in the air + frictionsafety = FRACUNIT; + } + + if (currentspeed >= mobj->movefactor) + { + // Thrust as if you were at top speed, slow down naturally + thrustamount = FixedDiv(mobj->movefactor, frictionsafety) - mobj->movefactor; + } + else + { + const fixed_t beatfriction = FixedDiv(currentspeed, frictionsafety) - currentspeed; + // Thrust to immediately get to top speed + thrustamount = beatfriction + FixedDiv(mobj->movefactor - currentspeed, frictionsafety); + } + mobj->angle = R_PointToAngle2(0, 0, mobj->momx, mobj->momy); - P_InstaThrust(mobj, mobj->angle, mobj->movefactor); + P_Thrust(mobj, mobj->angle, thrustamount); if (grounded) { @@ -8207,6 +8392,9 @@ void P_MobjThinker(mobj_t *mobj) P_TeleportMove(mobj, mobj->target->x + P_ReturnThrustX(mobj, mobj->angle+ANGLE_180, mobj->target->radius), mobj->target->y + P_ReturnThrustY(mobj, mobj->angle+ANGLE_180, mobj->target->radius), mobj->target->z); P_SetScale(mobj, mobj->target->scale); +#ifdef HWRENDER + mobj->modeltilt = mobj->target->modeltilt; +#endif { player_t *p = NULL; @@ -8347,9 +8535,67 @@ void P_MobjThinker(mobj_t *mobj) } K_MatchGenericExtraFlags(mobj, mobj->target); - P_TeleportMove(mobj, mobj->target->x + FINECOSINE(mobj->angle >> ANGLETOFINESHIFT), - mobj->target->y + FINESINE(mobj->angle >> ANGLETOFINESHIFT), - mobj->target->z + mobj->target->height); + { + fixed_t z; + z = mobj->target->z; + if (( mobj->eflags & MFE_VERTICALFLIP )) + z -= mobj->height; + else + z += mobj->target->height; + P_TeleportMove(mobj, mobj->target->x + FINECOSINE(mobj->angle >> ANGLETOFINESHIFT), + mobj->target->y + FINESINE(mobj->angle >> ANGLETOFINESHIFT), + z); + } + break; + case MT_TIREGREASE: + if (!mobj->target || P_MobjWasRemoved(mobj->target) || !mobj->target->player + || !mobj->target->player->kartstuff[k_tiregrease]) + { + P_RemoveMobj(mobj); + return; + } + + K_MatchGenericExtraFlags(mobj, mobj->target); + + { + const angle_t off = FixedAngle(40*FRACUNIT); + angle_t ang = mobj->target->angle; + fixed_t z; + UINT8 trans = (mobj->target->player->kartstuff[k_tiregrease] * (NUMTRANSMAPS+1)) / greasetics; + + if (trans > NUMTRANSMAPS) + trans = NUMTRANSMAPS; + + trans = NUMTRANSMAPS - trans; + + z = mobj->target->z; + if (mobj->eflags & MFE_VERTICALFLIP) + z += mobj->target->height; + + if (mobj->target->momx || mobj->target->momy) + ang = R_PointToAngle2(0, 0, mobj->target->momx, mobj->target->momy); + + if (mobj->extravalue1) + ang = (signed)(ang - off); + else + ang = (signed)(ang + off); + + P_TeleportMove(mobj, + mobj->target->x - FixedMul(mobj->target->radius, FINECOSINE(ang >> ANGLETOFINESHIFT)), + mobj->target->y - FixedMul(mobj->target->radius, FINESINE(ang >> ANGLETOFINESHIFT)), + z); + mobj->angle = ang; + + if (leveltime & 1) + mobj->flags2 |= MF2_DONTDRAW; + + if (trans >= NUMTRANSMAPS) + mobj->flags2 |= MF2_DONTDRAW; + else if (trans == 0) + mobj->frame = (mobj->frame & ~FF_TRANSMASK); + else + mobj->frame = (mobj->frame & ~FF_TRANSMASK)|(trans << FF_TRANSSHIFT); + } break; case MT_THUNDERSHIELD: { @@ -9053,6 +9299,9 @@ void P_MobjThinker(mobj_t *mobj) } break; case MT_KARMAFIREWORK: + if (mobj->flags & MF_NOGRAVITY) + break; + if (mobj->momz == 0) { P_RemoveMobj(mobj); @@ -9439,7 +9688,9 @@ for (i = ((mobj->flags2 & MF2_STRONGBOX) ? strongboxamt : weakboxamt); i; --i) s || mobj->type == MT_BIGTUMBLEWEED || mobj->type == MT_LITTLETUMBLEWEED || mobj->type == MT_CANNONBALLDECOR - || mobj->type == MT_FALLINGROCK) { + || mobj->type == MT_FALLINGROCK + || mobj->type == MT_ORBINAUT + || mobj->type == MT_JAWZ || mobj->type == MT_JAWZ_DUD) { P_TryMove(mobj, mobj->x, mobj->y, true); // Sets mo->standingslope correctly //if (mobj->standingslope) CONS_Printf("slope physics on mobj\n"); P_ButteredSlope(mobj); @@ -10770,8 +11021,16 @@ void P_RespawnSpecials(void) if (pcount == 1) // No respawn when alone return; else if (pcount > 1) + { time = (180 - (pcount * 10))*TICRATE; + // If the map is longer or shorter than 3 laps, then adjust ring respawn to account for this. + // 5 lap courses would have more retreaded ground, while 2 lap courses would have less. + if ((mapheaderinfo[gamemap-1]->numlaps != 3) + && !(mapheaderinfo[gamemap-1]->levelflags & LF_SECTIONRACE)) + time = (time * 3) / max(1, mapheaderinfo[gamemap-1]->numlaps); + } + // only respawn items when cv_itemrespawn is on //if (!cv_itemrespawn.value) // TODO: remove this cvar //return; @@ -11992,7 +12251,7 @@ ML_NOCLIMB : Direction not controllable { if (mthing->options & MTF_AMBUSH) { - if (i == MT_YELLOWDIAG || i == MT_REDDIAG) + if (mobj->flags & MF_SPRING && mobj->info->damage) mobj->angle += ANGLE_22h; if (mobj->flags & MF_NIGHTSITEM) diff --git a/src/p_mobj.h b/src/p_mobj.h index dfc8fc738..aec2ed951 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -370,6 +370,9 @@ typedef struct mobj_s #ifdef ESLOPE struct pslope_s *standingslope; // The slope that the object is standing on (shouldn't need synced in savegames, right?) +#ifdef HWRENDER + struct pslope_s *modeltilt; // Slope used for model tilting. Also is not synched, this is totally visual. +#endif #endif boolean colorized; // Whether the mobj uses the rainbow colormap diff --git a/src/p_saveg.c b/src/p_saveg.c index 7d2e9a307..e083c2c5b 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -2144,7 +2144,12 @@ static void LoadMobjThinker(actionf_p1 thinker) mobj->hprev = (mobj_t *)(size_t)READUINT32(save_p); #ifdef ESLOPE if (diff2 & MD2_SLOPE) + { mobj->standingslope = P_SlopeById(READUINT16(save_p)); +#ifdef HWRENDER + mobj->modeltilt = mobj->standingslope; +#endif + } #endif if (diff2 & MD2_COLORIZED) mobj->colorized = READUINT8(save_p); @@ -3091,7 +3096,7 @@ static inline void P_NetArchiveSpecials(void) WRITEUINT32(save_p, 0xffffffff); // Sky number - WRITEINT32(save_p, globallevelskynum); + WRITESTRINGN(save_p, globallevelskytexture, 9); // Current global weather type WRITEUINT8(save_p, globalweather); @@ -3110,8 +3115,8 @@ static inline void P_NetArchiveSpecials(void) // static void P_NetUnArchiveSpecials(void) { + char skytex[9]; size_t i; - INT32 j; if (READUINT32(save_p) != ARCHIVEBLOCK_SPECIALS) I_Error("Bad $$$.sav at archive block Specials"); @@ -3124,9 +3129,9 @@ static void P_NetUnArchiveSpecials(void) itemrespawntime[iquehead++] = READINT32(save_p); } - j = READINT32(save_p); - if (j != globallevelskynum) - P_SetupLevelSky(j, true); + READSTRINGN(save_p, skytex, sizeof(skytex)); + if (strcmp(skytex, globallevelskytexture)) + P_SetupLevelSky(skytex, true); globalweather = READUINT8(save_p); diff --git a/src/p_setup.c b/src/p_setup.c index d1ef91705..b7a482ce9 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -207,8 +207,9 @@ static void P_ClearSingleMapHeaderInfo(INT16 i) mapheaderinfo[num]->forcecharacter[0] = '\0'; DEH_WriteUndoline("WEATHER", va("%d", mapheaderinfo[num]->weather), UNDO_NONE); mapheaderinfo[num]->weather = 0; - DEH_WriteUndoline("SKYNUM", va("%d", mapheaderinfo[num]->skynum), UNDO_NONE); - mapheaderinfo[num]->skynum = 1; + DEH_WriteUndoline("SKYTEXTURE", va("%d", mapheaderinfo[num]->skytexture), UNDO_NONE); + snprintf(mapheaderinfo[num]->skytexture, 9, "SKY1"); + mapheaderinfo[num]->skytexture[8] = 0; DEH_WriteUndoline("SKYBOXSCALEX", va("%d", mapheaderinfo[num]->skybox_scalex), UNDO_NONE); mapheaderinfo[num]->skybox_scalex = 16; DEH_WriteUndoline("SKYBOXSCALEY", va("%d", mapheaderinfo[num]->skybox_scaley), UNDO_NONE); @@ -2255,17 +2256,18 @@ static inline boolean P_CheckLevel(lumpnum_t lumpnum) /** Sets up a sky texture to use for the level. * The sky texture is used instead of F_SKY1. */ -void P_SetupLevelSky(INT32 skynum, boolean global) +void P_SetupLevelSky(const char *skytexname, boolean global) { - char skytexname[12]; + char tex[9]; + strncpy(tex, skytexname, 9); + tex[8] = 0; - sprintf(skytexname, "SKY%d", skynum); - skytexture = R_TextureNumForName(skytexname); - levelskynum = skynum; + skytexture = R_TextureNumForName(tex); + strncpy(levelskytexture, tex, 9); // Global change if (global) - globallevelskynum = levelskynum; + strncpy(globallevelskytexture, tex, 9); // Don't go beyond for dedicated servers if (dedicated) @@ -2973,7 +2975,7 @@ boolean P_SetupLevel(boolean skipprecip) CON_SetupBackColormap(); // SRB2 determines the sky texture to be used depending on the map header. - P_SetupLevelSky(mapheaderinfo[gamemap-1]->skynum, true); + P_SetupLevelSky(mapheaderinfo[gamemap-1]->skytexture, true); P_MakeMapMD5(lastloadedmaplumpnum, &mapmd5); diff --git a/src/p_setup.h b/src/p_setup.h index c4a3aab9a..9abcfe5f6 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -54,7 +54,7 @@ INT32 P_CheckLevelFlat(const char *flatname); extern size_t nummapthings; extern mapthing_t *mapthings; -void P_SetupLevelSky(INT32 skynum, boolean global); +void P_SetupLevelSky(const char *skytexname, boolean global); #ifdef SCANTHINGS void P_ScanThings(INT16 mapnum, INT16 wadnum, INT16 lumpnum); #endif diff --git a/src/p_slopes.c b/src/p_slopes.c index 76af7bfde..e623b6f19 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -625,8 +625,7 @@ void P_ResetDynamicSlopes(void) { slopelist = NULL; slopecount = 0; - // We'll handle copy slopes later, after all the tag lists have been made. - // Yes, this means copied slopes won't affect things' spawning heights. Too bad for you. + /// Generates line special-defined slopes. for (i = 0; i < numlines; i++) { switch (lines[i].special) @@ -725,11 +724,21 @@ void P_ResetDynamicSlopes(void) { break; } } + + /// Copies slopes from tagged sectors via line specials. + /// \note Doesn't actually copy, but instead they share the same pointers. + for (i = 0; i < numlines; i++) + switch (lines[i].special) + { + case 720: + case 721: + case 722: + P_CopySectorSlope(&lines[i]); + default: + break; + } } - - - // ============================================================================ // // Various utilities related to slopes @@ -827,6 +836,9 @@ void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope) if (P_MobjFlip(thing)*(thing->momz) < 0) { // falling, land on slope thing->momz = -P_MobjFlip(thing); thing->standingslope = slope; +#ifdef HWRENDER + thing->modeltilt = thing->standingslope; +#endif } return; } @@ -843,6 +855,9 @@ void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope) thing->momz = -P_MobjFlip(thing); thing->standingslope = slope; +#ifdef HWRENDER + thing->modeltilt = thing->standingslope; +#endif } } @@ -862,33 +877,31 @@ void P_ButteredSlope(mobj_t *mo) return; // don't slide down slopes if you can't touch them or you're not affected by gravity if (mo->player) { - if (abs(mo->standingslope->zdelta) < FRACUNIT/4 && !(mo->player->pflags & PF_SPINNING)) + // Changed in kart to only not apply physics on very slight slopes (I think about 4 degree angles) + if (abs(mo->standingslope->zdelta) < FRACUNIT/21 && !(mo->player->pflags & PF_SPINNING)) return; // Don't slide on non-steep slopes unless spinning + // This only means you can be stopped on slopes that aren't steeper than 45 degrees if (abs(mo->standingslope->zdelta) < FRACUNIT/2 && !(mo->player->rmomx || mo->player->rmomy)) return; // Allow the player to stand still on slopes below a certain steepness } - thrust = FINESINE(mo->standingslope->zangle>>ANGLETOFINESHIFT) * 15 / 16 * (mo->eflags & MFE_VERTICALFLIP ? 1 : -1); + thrust = FINESINE(mo->standingslope->zangle>>ANGLETOFINESHIFT) * 4 / 5 * (mo->eflags & MFE_VERTICALFLIP ? 1 : -1); - if (mo->player && (mo->player->pflags & PF_SPINNING)) { - fixed_t mult = 0; + if (mo->player) { + fixed_t mult = FRACUNIT; if (mo->momx || mo->momy) { angle_t angle = R_PointToAngle2(0, 0, mo->momx, mo->momy) - mo->standingslope->xydirection; if (P_MobjFlip(mo) * mo->standingslope->zdelta < 0) angle ^= ANGLE_180; - mult = FINECOSINE(angle >> ANGLETOFINESHIFT); + mult = FRACUNIT + (FRACUNIT + FINECOSINE(angle>>ANGLETOFINESHIFT))*3/2; } - thrust = FixedMul(thrust, FRACUNIT*2/3 + mult/8); + thrust = FixedMul(thrust, mult); } - if (mo->momx || mo->momy) // Slightly increase thrust based on the object's speed - thrust = FixedMul(thrust, FRACUNIT+P_AproxDistance(mo->momx, mo->momy)/16); - // This makes it harder to zigzag up steep slopes, as well as allows greater top speed when rolling down - // Let's get the gravity strength for the object... thrust = FixedMul(thrust, abs(P_GetMobjGravity(mo))); diff --git a/src/p_spec.c b/src/p_spec.c index e0c1a7465..daef60a09 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2802,7 +2802,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 423: // Change Sky if ((mo && mo->player && P_IsLocalPlayer(mo->player)) || (line->flags & ML_NOCLIMB)) - P_SetupLevelSky(sides[line->sidenum[0]].textureoffset>>FRACBITS, (line->flags & ML_NOCLIMB)); + P_SetupLevelSky(sides[line->sidenum[0]].text, (line->flags & ML_NOCLIMB)); break; case 424: // Change Weather @@ -6693,14 +6693,6 @@ void P_SpawnSpecials(INT32 fromnetsave) sectors[s].midmap = lines[i].frontsector->midmap; break; -#ifdef ESLOPE // Slope copy specials. Handled here for sanity. - case 720: - case 721: - case 722: - P_CopySectorSlope(&lines[i]); - break; -#endif - default: break; } diff --git a/src/p_user.c b/src/p_user.c index afa0966cf..324240ce8 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1645,12 +1645,16 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj) ghost->frame |= tr_trans50<fuse = ghost->info->damage; ghost->skin = mobj->skin; + ghost->standingslope = mobj->standingslope; +#ifdef HWRENDER + ghost->modeltilt = mobj->modeltilt; +#endif if (mobj->flags2 & MF2_OBJECTFLIP) ghost->flags |= MF2_OBJECTFLIP; if (!(mobj->flags & MF_DONTENCOREMAP)) - mobj->flags &= ~MF_DONTENCOREMAP; + ghost->flags &= ~MF_DONTENCOREMAP; return ghost; } @@ -4186,27 +4190,33 @@ static void P_3dMovement(player_t *player) // If "no" to 2, normalize to topspeed, so we can't suddenly run faster than it of our own accord. // If "no" to 1, we're not reaching any limits yet, so ignore this entirely! // -Shadow Hog - newMagnitude = R_PointToDist2(player->mo->momx - player->cmomx, player->mo->momy - player->cmomy, 0, 0); - if (newMagnitude > K_GetKartSpeed(player, true)) //topspeed) + // Only do this forced cap of speed when in midair, the kart acceleration code takes into account friction, and + // doesn't let you accelerate past top speed, so this is unnecessary on the ground, but in the air is needed to + // allow for being able to change direction on spring jumps without being accelerated into the void - Sryder + if (!P_IsObjectOnGround(player->mo)) { - fixed_t tempmomx, tempmomy; - if (oldMagnitude > K_GetKartSpeed(player, true)) + newMagnitude = R_PointToDist2(player->mo->momx - player->cmomx, player->mo->momy - player->cmomy, 0, 0); + if (newMagnitude > K_GetKartSpeed(player, true)) //topspeed) { - if (newMagnitude > oldMagnitude) + fixed_t tempmomx, tempmomy; + if (oldMagnitude > K_GetKartSpeed(player, true)) { - tempmomx = FixedMul(FixedDiv(player->mo->momx - player->cmomx, newMagnitude), oldMagnitude); - tempmomy = FixedMul(FixedDiv(player->mo->momy - player->cmomy, newMagnitude), oldMagnitude); + if (newMagnitude > oldMagnitude) + { + tempmomx = FixedMul(FixedDiv(player->mo->momx - player->cmomx, newMagnitude), oldMagnitude); + tempmomy = FixedMul(FixedDiv(player->mo->momy - player->cmomy, newMagnitude), oldMagnitude); + player->mo->momx = tempmomx + player->cmomx; + player->mo->momy = tempmomy + player->cmomy; + } + // else do nothing + } + else + { + tempmomx = FixedMul(FixedDiv(player->mo->momx - player->cmomx, newMagnitude), K_GetKartSpeed(player, true)); //topspeed) + tempmomy = FixedMul(FixedDiv(player->mo->momy - player->cmomy, newMagnitude), K_GetKartSpeed(player, true)); //topspeed) player->mo->momx = tempmomx + player->cmomx; player->mo->momy = tempmomy + player->cmomy; } - // else do nothing - } - else - { - tempmomx = FixedMul(FixedDiv(player->mo->momx - player->cmomx, newMagnitude), K_GetKartSpeed(player, true)); //topspeed) - tempmomy = FixedMul(FixedDiv(player->mo->momy - player->cmomy, newMagnitude), K_GetKartSpeed(player, true)); //topspeed) - player->mo->momx = tempmomx + player->cmomx; - player->mo->momy = tempmomy + player->cmomy; } } } diff --git a/src/r_data.c b/src/r_data.c index 7fb11855f..6aebf5a4a 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -267,7 +267,7 @@ static UINT8 *R_GenerateTexture(size_t texnum) texturememory += blocksize; block = Z_Malloc(blocksize+1, PU_STATIC, &texturecache[texnum]); - memset(block, 0xF7, blocksize+1); // Transparency hack + memset(block, 0xFF, blocksize+1); // TRANSPARENTPIXEL // columns lookup table colofs = (UINT32 *)(void *)block; @@ -1631,7 +1631,7 @@ void R_PrecacheLevel(void) // Sky texture is always present. // Note that F_SKY1 is the name used to indicate a sky floor/ceiling as a flat, - // while the sky texture is stored like a wall texture, with a skynum dependent name. + // while the sky texture is stored like a wall texture, with a texture name set by the map. texturepresent[skytexture] = 1; texturememory = 0; diff --git a/src/r_plane.c b/src/r_plane.c index db5bfbda2..ec105bf75 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -734,7 +734,7 @@ void R_DrawPlanes(void) dc_x = x; dc_source = R_GetColumn(texturetranslation[skytexture], - angle); + -angle); // Negative because skies were being drawn horizontally flipped wallcolfunc(); } } diff --git a/src/r_sky.c b/src/r_sky.c index fe1630e90..1fe0fe0e6 100644 --- a/src/r_sky.c +++ b/src/r_sky.c @@ -47,8 +47,8 @@ fixed_t skyscale; /** \brief used for keeping track of the current sky */ -INT32 levelskynum; -INT32 globallevelskynum; +char levelskytexture[9]; +char globallevelskytexture[9]; /** \brief The R_SetupSkyDraw function diff --git a/src/r_sky.h b/src/r_sky.h index 86b615595..a41b24463 100644 --- a/src/r_sky.h +++ b/src/r_sky.h @@ -30,8 +30,8 @@ extern INT32 skytexture, skytexturemid; extern fixed_t skyscale; extern INT32 skyflatnum; -extern INT32 levelskynum; -extern INT32 globallevelskynum; +extern char levelskytexture[9]; +extern char globallevelskytexture[9]; // call after skytexture is set to adapt for old/new skies void R_SetupSkyDraw(void); diff --git a/src/screen.c b/src/screen.c index 4cb8bac5d..96a78ae8e 100644 --- a/src/screen.c +++ b/src/screen.c @@ -427,13 +427,13 @@ void SCR_DisplayTicRate(void) ticcntcolor|V_NOSCALESTART, va("%02d/%02u", totaltics, TICRATE));*/ // draw "FPS" - V_DrawFixedPatch(306< servermaxping)) // only show 2 (warning) if our ping is at a bad level { INT32 dispy = cv_ticrate.value ? 160 : 181; - HU_drawPing(307, dispy, ping, V_SNAPTORIGHT | V_SNAPTOBOTTOM); + HU_drawPing(307, dispy, ping, V_SNAPTORIGHT | V_SNAPTOBOTTOM | V_HUDTRANS); } } diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 42e0a917f..e5f1c23fc 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -1377,11 +1377,14 @@ void I_FinishUpdate(void) if (I_SkipFrame()) return; - if (cv_ticrate.value) - SCR_DisplayTicRate(); + if (st_overlay) + { + if (cv_ticrate.value) + SCR_DisplayTicRate(); - if (cv_showping.value && netgame && consoleplayer != serverplayer) - SCR_DisplayLocalPing(); + if (cv_showping.value && netgame && consoleplayer != serverplayer) + SCR_DisplayLocalPing(); + } if (rendermode == render_soft && screens[0]) {