From fec3c19bd081dbf2109b0deac3ec565adcdc01df Mon Sep 17 00:00:00 2001 From: NepDisk Date: Tue, 24 Jun 2025 07:51:33 -0400 Subject: [PATCH 01/27] Fix Windows Clang compile --- src/CMakeLists.txt | 6 +++++- src/win32/Srb2win.rc | 3 --- toolchain/LinuxCLANG.cmake | 3 +++ toolchain/{windowsCLANG.cmake => WindowsCLANG.cmake} | 3 +++ toolchain/{windowsGCC.cmake => WindowsGCC.cmake} | 0 5 files changed, 11 insertions(+), 4 deletions(-) rename toolchain/{windowsCLANG.cmake => WindowsCLANG.cmake} (93%) rename toolchain/{windowsGCC.cmake => WindowsGCC.cmake} (100%) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index abd6a66b1..348e29ea6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -4,7 +4,11 @@ if(("${CMAKE_COMPILER_IS_GNUCC}" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang") AND target_link_options(SRB2SDL2 PRIVATE "-Wl,--disable-dynamicbase") if("${SRB2_CONFIG_STATIC_STDLIB}") # On MinGW with internal libraries, link the standard library statically - target_link_options(SRB2SDL2 PRIVATE -Wl,--add-stdcall-alias -static-libgcc -static-libstdc++ -static -lpthread) + if(CMAKE_LINKER_TYPE STREQUAL "LLD") + target_link_options(SRB2SDL2 PRIVATE -Wl, -static-libgcc -static-libstdc++ -static -lpthread) + else() + target_link_options(SRB2SDL2 PRIVATE -Wl,--add-stdcall-alias -static-libgcc -static-libstdc++ -static -lpthread) + endif() set(THREADS_PREFER_PTHREAD_FLAG TRUE) find_package(Threads REQUIRED) target_link_libraries(SRB2SDL2 PRIVATE Threads::Threads) diff --git a/src/win32/Srb2win.rc b/src/win32/Srb2win.rc index 4ee69b58c..042a7fdf0 100644 --- a/src/win32/Srb2win.rc +++ b/src/win32/Srb2win.rc @@ -1,9 +1,6 @@ -#include - //Microsoft Developer Studio generated resource script. // #include "resource.h" -#include "winver.h" #define APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// diff --git a/toolchain/LinuxCLANG.cmake b/toolchain/LinuxCLANG.cmake index eaa087ab3..849961d27 100644 --- a/toolchain/LinuxCLANG.cmake +++ b/toolchain/LinuxCLANG.cmake @@ -5,3 +5,6 @@ set(CMAKE_CXX_COMPILER clang++) # Set that this is clang. set(CMAKE_C_COMPILER_ID clang) set(CMAKE_CXX_COMPILER_ID clang) + +# Use LLD to link +set(CMAKE_LINKER_TYPE LLD) diff --git a/toolchain/windowsCLANG.cmake b/toolchain/WindowsCLANG.cmake similarity index 93% rename from toolchain/windowsCLANG.cmake rename to toolchain/WindowsCLANG.cmake index 5ed085f8f..421c9e942 100644 --- a/toolchain/windowsCLANG.cmake +++ b/toolchain/WindowsCLANG.cmake @@ -16,3 +16,6 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) # search headers and libraries in the target environment set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + +# Use LLD to link +set(CMAKE_LINKER_TYPE LLD) diff --git a/toolchain/windowsGCC.cmake b/toolchain/WindowsGCC.cmake similarity index 100% rename from toolchain/windowsGCC.cmake rename to toolchain/WindowsGCC.cmake From 02196b622cd628e4f2fed7a2e8397a2933b85921 Mon Sep 17 00:00:00 2001 From: NepDisk Date: Tue, 24 Jun 2025 10:40:21 -0400 Subject: [PATCH 02/27] Allow reading and writing *time variables from SOC and Lua This should also for simple edits such as extending hyudoro length without janky lua scripts --- src/deh_soc.c | 45 ++++++++++++++++++++++++++++++++++---- src/doomstat.h | 2 +- src/g_game.c | 2 +- src/k_kart.c | 6 +++--- src/lua_script.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++ src/p_saveg.c | 26 ++++++++++++++++++++++ 6 files changed, 128 insertions(+), 9 deletions(-) diff --git a/src/deh_soc.c b/src/deh_soc.c index cfd80b952..60c7cfc6c 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -3209,6 +3209,47 @@ void readmaincfg(MYFILE *f) { ammoremovaltics = get_number(word2); } + // BlanKart: Easy ways to set these for balance purposes + else if (fastcmp(word, "HYUDOROTIME")) + { + hyudorotime = get_number(word2); + } + else if (fastcmp(word, "STEALTIME")) + { + stealtime = get_number(word2); + } + else if (fastcmp(word, "WATERPANELTIME")) + { + waterpaneltime = get_number(word2); + } + else if (fastcmp(word, "SNEAKERTIME")) + { + sneakertime = get_number(word2); + } + else if (fastcmp(word, "BUBBLETIME")) + { + bubbletime = get_number(word2); + } + else if (fastcmp(word, "COMEBACKTIME")) + { + comebacktime = get_number(word2); + } + else if (fastcmp(word, "GREASETICS")) + { + greasetics = get_number(word2); + } + else if (fastcmp(word, "WIPEOUTSLOWTIME")) + { + wipeoutslowtime = get_number(word2); + } + else if (fastcmp(word, "WANTEDREDUCE")) + { + wantedreduce = get_number(word2); + } + else if (fastcmp(word, "WANTEDFREQUENCY")) + { + wantedfrequency = get_number(word2); + } else if (fastcmp(word, "INTROTOPLAY")) { introtoplay = (UINT8)get_number(word2); @@ -3224,10 +3265,6 @@ void readmaincfg(MYFILE *f) if (creditscutscene > 128) creditscutscene = 128; } - else if (fastcmp(word, "USEBLACKROCK")) - { - useBlackRock = (UINT8)(value || word2[0] == 'T' || word2[0] == 'Y'); - } else if (fastcmp(word, "LOOPTITLE")) { looptitle = (value || word2[0] == 'T' || word2[0] == 'Y'); diff --git a/src/doomstat.h b/src/doomstat.h index 39a535a20..4f7f9f57e 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -609,6 +609,7 @@ extern tic_t battleexittime; extern INT32 hyudorotime; extern INT32 stealtime; extern INT32 sneakertime; +extern INT32 waterpaneltime; extern INT32 itemtime; extern INT32 bubbletime; extern INT32 comebacktime; @@ -620,7 +621,6 @@ extern INT32 wantedfrequency; extern UINT8 introtoplay; extern UINT8 creditscutscene; -extern UINT8 useBlackRock; extern UINT8 use1upSound; extern UINT8 maxXtraLife; // Max extra lives from rings diff --git a/src/g_game.c b/src/g_game.c index 13cec79e6..4e0b38632 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -240,6 +240,7 @@ tic_t battleexittime = 8*TICRATE; INT32 hyudorotime = 7*TICRATE; INT32 stealtime = TICRATE/2; INT32 sneakertime = TICRATE + (TICRATE/3); +INT32 waterpaneltime = TICRATE*2; INT32 itemtime = 8*TICRATE; INT32 bubbletime = TICRATE/2; INT32 comebacktime = 3*TICRATE; @@ -254,7 +255,6 @@ UINT8 maxXtraLife = 2; // Max extra lives from rings UINT8 introtoplay; UINT8 creditscutscene; -UINT8 useBlackRock = 1; // Emerald locations mobj_t *hunt1; diff --git a/src/k_kart.c b/src/k_kart.c index f413c9ff3..bcf7a42bf 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -5535,7 +5535,7 @@ static void K_SneakerPanelEffect(player_t *player, INT32 type) void K_DoSneaker(player_t *player, INT32 type) { const fixed_t intendedboost = K_GetSneakerBoostSpeed(); - const tic_t sneakerduration = (type == 3) ? TICRATE*2 : sneakertime; + const tic_t sneakerduration = (type == SNEAKERTYPE_WATERPANEL) ? waterpaneltime : sneakertime; if (player->floorboost == 0 || player->floorboost == 3) { @@ -5548,7 +5548,7 @@ void K_DoSneaker(player_t *player, INT32 type) K_SneakerPanelEffect(player, type); - if (type != 0 && type != 3) + if (type != SNEAKERTYPE_PANEL && type != SNEAKERTYPE_WATERPANEL) { K_PlayBoostTaunt(player->mo); } @@ -5561,7 +5561,7 @@ void K_DoSneaker(player_t *player, INT32 type) player->numsneakers = CLAMP(player->numsneakers+1, 0, stackingactive ? MAXSNEAKERSTACK : 1); } - if (type == 3) + if (type == SNEAKERTYPE_WATERPANEL) { // Water Running please! player->mo->flags2 |= MF2_WATERRUN; diff --git a/src/lua_script.c b/src/lua_script.c index d77ab74a2..b5bb1df68 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -365,6 +365,12 @@ int LUA_PushGlobals(lua_State *L, const char *word) } else if (fastcmp(word,"gamespeed")) { lua_pushinteger(L, gamespeed); return 1; + } else if (fastcmp(word,"nummapboxes")) { + lua_pushinteger(L, nummapboxes); + return 1; + } else if (fastcmp(word,"numgotboxes")) { + lua_pushinteger(L, numgotboxes); + return 1; } else if (fastcmp(word,"itembreaker")) { lua_pushinteger(L, itembreaker); return 1; @@ -428,6 +434,36 @@ int LUA_PushGlobals(lua_State *L, const char *word) } else if (fastcmp(word, "compatmode")) { lua_pushboolean(L, lua_compatmode); return 1; + } else if (fastcmp(word, "hyudorotime")) { + lua_pushinteger(L, hyudorotime); + return 1; + } else if (fastcmp(word, "stealtime")) { + lua_pushinteger(L, stealtime); + return 1; + } else if (fastcmp(word, "sneakertime")) { + lua_pushinteger(L, sneakertime); + return 1; + } else if (fastcmp(word, "waterpaneltime")) { + lua_pushinteger(L, waterpaneltime); + return 1; + } else if (fastcmp(word, "bubbletime")) { + lua_pushinteger(L, bubbletime); + return 1; + } else if (fastcmp(word, "comebacktime")) { + lua_pushinteger(L, comebacktime); + return 1; + } else if (fastcmp(word, "greasetics")) { + lua_pushinteger(L, greasetics); + return 1; + } else if (fastcmp(word, "wipeoutslowtime")) { + lua_pushinteger(L, wipeoutslowtime); + return 1; + } else if (fastcmp(word, "wantedreduce")) { + lua_pushinteger(L, wantedreduce); + return 1; + } else if (fastcmp(word, "wantedfrequency")) { + lua_pushinteger(L, wantedfrequency); + return 1; } else if (fastcmp(word, "mapnamespace")) { lua_pushstring(L, P_MapNamespaceString(mapnamespace)); return 1; @@ -513,6 +549,26 @@ int LUA_WriteGlobals(lua_State *L, const char *word) nummapboxes = (INT32)luaL_checkinteger(L, 2); else if (fastcmp(word,"numgotboxes")) numgotboxes = (INT32)luaL_checkinteger(L, 2); + else if (fastcmp(word, "hyudorotime")) + hyudorotime = (INT32)luaL_checkinteger(L, 2); + else if (fastcmp(word, "stealtime")) + stealtime = (INT32)luaL_checkinteger(L, 2); + else if (fastcmp(word, "sneakertime")) + sneakertime = (INT32)luaL_checkinteger(L, 2); + else if (fastcmp(word, "waterpaneltime")) + waterpaneltime = (INT32)luaL_checkinteger(L, 2); + else if (fastcmp(word, "bubbletime")) + bubbletime = (INT32)luaL_checkinteger(L, 2); + else if (fastcmp(word, "comebacktime")) + comebacktime = (INT32)luaL_checkinteger(L, 2); + else if (fastcmp(word, "greasetics")) + greasetics = (INT32)luaL_checkinteger(L, 2); + else if (fastcmp(word, "wipeoutslowtime")) + wipeoutslowtime = (INT32)luaL_checkinteger(L, 2); + else if (fastcmp(word, "wantedreduce")) + wantedreduce = (INT32)luaL_checkinteger(L, 2); + else if (fastcmp(word, "wantedfrequency")) + wantedfrequency = (INT32)luaL_checkinteger(L, 2); else return 0; diff --git a/src/p_saveg.c b/src/p_saveg.c index 363d0ad75..794a31849 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -5209,6 +5209,7 @@ static void P_NetArchiveMisc(savebuffer_t *save, boolean resending) WRITEFIXED(save->p, mapobjectscale); // SRB2kart + WRITEINT32(save->p, nummapboxes); WRITEINT32(save->p, numgotboxes); WRITEUINT8(save->p, numtargets); WRITEUINT8(save->p, itembreaker); @@ -5239,6 +5240,18 @@ static void P_NetArchiveMisc(savebuffer_t *save, boolean resending) WRITEUINT32(save->p, introtime); WRITEUINT32(save->p, starttime); + WRITEINT32(save->p, hyudorotime); + WRITEINT32(save->p, stealtime); + WRITEINT32(save->p, sneakertime); + WRITEINT32(save->p, itemtime); + WRITEINT32(save->p, bubbletime); + WRITEINT32(save->p, comebacktime); + WRITEINT32(save->p, bumptime); + WRITEINT32(save->p, greasetics); + WRITEINT32(save->p, wipeoutslowtime); + WRITEINT32(save->p, wantedreduce); + WRITEINT32(save->p, wantedfrequency); + WRITEUINT32(save->p, timelimitintics); WRITEUINT32(save->p, extratimeintics); WRITEUINT32(save->p, secretextratime); @@ -5379,6 +5392,7 @@ FUNCINLINE static ATTRINLINE boolean P_NetUnArchiveMisc(savebuffer_t *save, bool mapobjectscale = READFIXED(save->p); // SRB2kart + nummapboxes = READINT32(save->p); numgotboxes = READINT32(save->p); numtargets = READUINT8(save->p); itembreaker = (boolean)READUINT8(save->p); @@ -5408,6 +5422,18 @@ FUNCINLINE static ATTRINLINE boolean P_NetUnArchiveMisc(savebuffer_t *save, bool introtime = READUINT32(save->p); starttime = READUINT32(save->p); + + hyudorotime = READINT32(save->p); + stealtime = READINT32(save->p); + sneakertime = READINT32(save->p); + itemtime = READINT32(save->p); + bubbletime = READINT32(save->p); + comebacktime = READINT32(save->p); + bumptime = READINT32(save->p); + greasetics = READINT32(save->p); + wipeoutslowtime = READINT32(save->p); + wantedreduce = READINT32(save->p); + wantedfrequency = READINT32(save->p); timelimitintics = READUINT32(save->p); extratimeintics = READUINT32(save->p); From 3da0b4ce0c8ffc656f5aaac09cad54c486b2072b Mon Sep 17 00:00:00 2001 From: NepDisk Date: Tue, 24 Jun 2025 10:48:58 -0400 Subject: [PATCH 03/27] Add waterpaneltime to be neysynched I always forget something... --- src/p_saveg.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/p_saveg.c b/src/p_saveg.c index 794a31849..3db594de2 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -5243,6 +5243,7 @@ static void P_NetArchiveMisc(savebuffer_t *save, boolean resending) WRITEINT32(save->p, hyudorotime); WRITEINT32(save->p, stealtime); WRITEINT32(save->p, sneakertime); + WRITEINT32(save->p, waterpaneltime); WRITEINT32(save->p, itemtime); WRITEINT32(save->p, bubbletime); WRITEINT32(save->p, comebacktime); @@ -5426,6 +5427,7 @@ FUNCINLINE static ATTRINLINE boolean P_NetUnArchiveMisc(savebuffer_t *save, bool hyudorotime = READINT32(save->p); stealtime = READINT32(save->p); sneakertime = READINT32(save->p); + waterpaneltime = READINT32(save->p); itemtime = READINT32(save->p); bubbletime = READINT32(save->p); comebacktime = READINT32(save->p); From 6fa3c4f751a8c3621a26d5a3cd8c63943c46777e Mon Sep 17 00:00:00 2001 From: NepDisk Date: Tue, 24 Jun 2025 10:54:34 -0400 Subject: [PATCH 04/27] Fix dedi crash due to invalid pstartmap value --- src/d_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/d_main.cpp b/src/d_main.cpp index d770133a7..68e05dbd1 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -1238,7 +1238,7 @@ void D_SRB2Main(void) { INT32 p; - INT32 pstartmap = 0; + INT32 pstartmap = 1; boolean autostart = false; /* break the version string into version numbers, for netplay */ From d4f0336ede3922b0140762af216326e7667b96b0 Mon Sep 17 00:00:00 2001 From: NepDisk Date: Tue, 24 Jun 2025 11:42:21 -0400 Subject: [PATCH 05/27] Shut up dedicated --- src/dehacked.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/dehacked.c b/src/dehacked.c index 2d6023c09..4a0c5d2c6 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -176,6 +176,34 @@ static void ignorelines(MYFILE *f) Z_Free(s); } +static void ignoremenulines(MYFILE *f) +{ + char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL); + char *tmp; + do + { + if (myfgets(s, MAXLINELEN, f)) + { + if (s[0] == '\n') + break; + + // First remove trailing newline, if there is one + tmp = strchr(s, '\n'); + if (tmp) + *tmp = '\0'; + + tmp = strchr(s, '#'); + if (tmp) + *tmp = '\0'; + if (s == tmp) + continue; // Skip comment lines, but don't break. + + ignorelines(f); + } + } while (!myfeof(f)); + Z_Free(s); +} + void DEH_Link(const char *name, dehinfo_t *info, strbuf_t **buf) { info->namehash = HASH32(name, strlen(name)); @@ -625,7 +653,10 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile) else if (fastcmp(word, "MENU")) { if (dedicated) + { + ignoremenulines(f); continue; // dedis don't need menus, silly! + } if (i == 0 && word2[0] != '0') // If word2 isn't a number i = get_menutype(word2); // find a huditem by name From ffde1365a5e270c7b41339e62a4182099e0ee67f Mon Sep 17 00:00:00 2001 From: Sky Dusk <47698279+Ace-Lite@users.noreply.github.com> Date: Sun, 22 Jun 2025 15:41:54 +0200 Subject: [PATCH 06/27] Remove format whitelist for read only Lua IO and allow more formats. --- src/blua/liolib.c | 40 ++++++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/src/blua/liolib.c b/src/blua/liolib.c index e6c294de0..c885a2eff 100644 --- a/src/blua/liolib.c +++ b/src/blua/liolib.c @@ -37,6 +37,15 @@ // Allow scripters to write files of these types to SRB2's folder static const char *whitelist[] = { ".bmp", + ".png", + + ".obj", + + ".json", + ".yaml", + ".xml", + ".csv", + ".soc", ".cfg", ".csv", ".dat", @@ -176,7 +185,7 @@ void MakePathDirs(char *path) } -static int CheckFileName(lua_State *L, const char *filename) +static int CheckFileName(lua_State* L, const char* filename, boolean extensioncheck) { int length = strlen(filename); boolean pass = false; @@ -188,12 +197,21 @@ static int CheckFileName(lua_State *L, const char *filename) return pushresult(L,0,filename); } - for (i = 0; i < (sizeof (whitelist) / sizeof(const char *)); i++) - if (!stricmp(&filename[length - strlen(whitelist[i])], whitelist[i])) - { - pass = true; - break; - } + if (extensioncheck) + { + for (i = 0; i < (sizeof(whitelist) / sizeof(const char*)); i++) + if (!stricmp(&filename[length - strlen(whitelist[i])], whitelist[i])) + { + pass = true; + break; + } + } + else + { + pass = true; + } + + if (strstr(filename, "./") || strstr(filename, "..") || strchr(filename, ':') || filename[0] == '/' @@ -214,7 +232,10 @@ static int io_openlocal (lua_State *L) { luafiletransfer_t *filetransfer; int checkresult; - checkresult = CheckFileName(L, filename); + // Decision was made for normal reading (binary + text) to have no whitelist restrictions + boolean readcheck = (strchr(mode, 'w') != NULL) || (strchr(mode, 'a') != NULL) || (strchr(mode, '+') != NULL); + + checkresult = CheckFileName(L, filename, readcheck); if (checkresult) return checkresult; @@ -240,11 +261,10 @@ static int io_open (lua_State *L) { const char *mode = luaL_optstring(L, 2, "r"); int checkresult; - checkresult = CheckFileName(L, filename); + checkresult = CheckFileName(L, filename, false); if (checkresult) return checkresult; - if (lua_isfunction(L,3)) { luaL_checktype(L, 3, LUA_TFUNCTION); From 3fbacbbca27bf367657152c5335244aedde2acfa Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 25 Jun 2025 21:39:35 +0200 Subject: [PATCH 07/27] dont compare our floatangle to ANGLE_180 smol oops --- src/hardware/hw_clip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hardware/hw_clip.c b/src/hardware/hw_clip.c index c09a4e301..3a33e5f36 100644 --- a/src/hardware/hw_clip.c +++ b/src/hardware/hw_clip.c @@ -335,7 +335,7 @@ angle_t gld_FrustumAngle(angle_t tiltangle) // but at least it doesn't overestimate too much... clipfov = atan(1 / projMatrix[0]) * 360 / M_PI; // use the actual view of the scene floatangle = 2.0f + (45.0f + (tilt / 1.9f)) * clipfov / 90.0f; - if (floatangle >= ANGLE_180) + if (floatangle >= 180.0) return 0xffffffff; a1 = (angle_t)(ANG1 * (int)floatangle); return a1; From 36fdc9a37d035334c587aa8c9f2fda3a9ce26f32 Mon Sep 17 00:00:00 2001 From: NepDisk Date: Wed, 25 Jun 2025 17:17:46 -0400 Subject: [PATCH 08/27] Don't make windows users listen to the short loop forever --- src/d_clisrv.c | 13 +++++-------- src/d_clisrv.h | 5 +++++ src/m_menu.c | 1 + 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index d87f482df..4762d89c6 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -553,10 +553,7 @@ char http_source[MAX_MIRROR_LENGTH]; static UINT16 cl_lastcheckedfilecount = 0; // used for full file list -static const char* servmus_1 = "SRVMS1"; -static const char* servmus_2 = "SRVMS2"; - -static void ChangeServMusic(const char* musname, boolean fallback, boolean keepPos) +void ChangeServMusic(const char* musname, boolean fallback, boolean keepPos) { if (S_MusicExists(musname)) if (keepPos) @@ -1616,7 +1613,7 @@ static boolean CL_FinishedFileList(void) "Press ACCEL to continue or BRAKE to cancel.\n\n" ), M_ConfirmConnect, MM_EVENTHANDLER); cl_mode = CL_CONFIRMCONNECT; - ChangeServMusic(servmus_2, true,true); + ChangeServMusic(SERVMUS_2, true,true); } else cl_mode = CL_LOADFILES; @@ -1686,7 +1683,7 @@ static boolean CL_FinishedFileList(void) Z_Free(downloadsize); cl_mode = CL_CONFIRMCONNECT; - ChangeServMusic(servmus_2, true,true); + ChangeServMusic(SERVMUS_2, true,true); } #ifdef HAVE_CURL else @@ -1787,7 +1784,7 @@ static boolean CL_ServerConnectionSearchTicker(tic_t *asksent) } cl_mode = CL_VIEWSERVER; //cl_mode = CL_CHECKFILES; - ChangeServMusic(servmus_1, true,false); + ChangeServMusic(SERVMUS_1, true,false); } else { @@ -1834,7 +1831,7 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic if (cl_lastcheckedfilecount == UINT16_MAX) // All files retrieved { cl_mode = CL_VIEWSERVER; //cl_mode = CL_CHECKFILES; - ChangeServMusic(servmus_1, true,false); + ChangeServMusic(SERVMUS_1, true,false); } else if (fileneedednum != cl_lastcheckedfilecount || I_GetTime() >= *asksent) { diff --git a/src/d_clisrv.h b/src/d_clisrv.h index 0af45d015..8dace7fb1 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -554,6 +554,11 @@ extern UINT8 playernode[MAXPLAYERS]; extern UINT8 playerconsole[MAXPLAYERS]; extern SINT8 joinnode; +#define SERVMUS_1 "SRVMS1" +#define SERVMUS_2 "SRVMS2" + +void ChangeServMusic(const char* musname, boolean fallback, boolean keepPos); + INT32 GetClientMode(void); void ChangeClientMode(INT32 mode); diff --git a/src/m_menu.c b/src/m_menu.c index f8e9ed333..6df4ada5d 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -8047,6 +8047,7 @@ INT32 MR_HandleViewServer(INT32 choice) case KEY_ENTER: S_StartSound(NULL, sfx_menu1); ChangeClientMode(CL_CHECKFILES); + ChangeServMusic(SERVMUS_2, true,true); M_ClearMenus(false); return true; break; From ea0728034800b62806c7cd7a6ac20e5db524b5f7 Mon Sep 17 00:00:00 2001 From: NepDisk Date: Wed, 25 Jun 2025 19:06:32 -0400 Subject: [PATCH 09/27] Fix larger RR size mapthumbnails not scaling during voting --- src/y_inter.c | 45 ++++++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/src/y_inter.c b/src/y_inter.c index eb5fef9b0..ff5eb5dfc 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -1163,6 +1163,22 @@ static inline void Y_DrawAnimatedVoteScreenPatch(boolean widePatch) currentAnimFrame = (currentAnimFrame + 1 > tempFoundAnimVoteFrames - 1) ? 0 : currentAnimFrame + 1; } +static fixed_t Y_CalculatePicScale(fixed_t picscale, INT32 hypoti) +{ + picscale *= 10; + picscale /= (40-hypoti); + + if ( ((hypoti % 5) == 1) || ((hypoti % 5) == 4) || ((hypoti % 5) == 2) ) + { + if ((hypoti % 5) == 2) // scale DOWN the image + picscale -= (hypoti*16); + else + picscale += (hypoti*2); // scale UP the image + } + + return picscale; +} + // // Y_VoteDrawer // @@ -1176,7 +1192,6 @@ void Y_VoteDrawer(void) fixed_t scale; patch_t *pic; INT16 mapnum; - fixed_t picscale = FRACUNIT; // GREENRES fixed_t picwidth = 160; // CEP: scale by screen hypotenuse for extra voting rows @@ -1202,18 +1217,7 @@ void Y_VoteDrawer(void) INT32 hypotdiv = max(10, (40-hypoti)); // readjust the picscale - picscale *= 10; - picscale /= (40-hypoti); - picwidth *= picscale; - - // shitty hack to prevent alignment issues - if ( ((hypoti % 5) == 1) || ((hypoti % 5) == 4) || ((hypoti % 5) == 2) ) - { - if ((hypoti % 5) == 2) // scale DOWN the image - picscale -= (hypoti*16); - else - picscale += (hypoti*2); // scale UP the image - } + picwidth *= Y_CalculatePicScale(FRACUNIT, hypoti); if (rendermode == render_none) return; @@ -1313,7 +1317,7 @@ void Y_VoteDrawer(void) str = levelinfo[i].str; mapnum = votelevels[i][0]; } - scale = M_GetMapThumbnail(mapnum, &pic)/4; + scale = M_GetMapThumbnail(mapnum, &pic)/2; if (selected[i]) { @@ -1377,11 +1381,11 @@ void Y_VoteDrawer(void) } if (!levelinfo[i].encore) - V_DrawFixedPatch((BASEVIDWIDTH-(1200/hypotdiv)-scaledpicdiff)< Date: Thu, 26 Jun 2025 09:57:23 -0400 Subject: [PATCH 10/27] I'm never calling you again This causes buffer overflow sometimes due to not being resized. --- src/d_netcmd.c | 8 ++++---- src/f_finale.c | 2 +- src/g_game.c | 15 ++++++--------- src/g_game.h | 2 +- src/m_menu.c | 4 ++-- 5 files changed, 14 insertions(+), 17 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 9c29eb075..f3585db99 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -2815,11 +2815,11 @@ void D_SetupVote(void) hellpick = 1; if (i == 2) // sometimes a different gametype - m = G_RandMap(G_TOLFlag(secondgt), prevmap, ((secondgt != gametype) ? 2 : 0), 0, true, votebuffer); + m = G_RandMap(G_TOLFlag(secondgt), prevmap, ((secondgt != gametype) ? 2 : 0), 0, votebuffer); else if (i >= VOTEROWS) // unknown-random and formerly force-unknown MAP HELL - m = G_RandMap(G_TOLFlag(gt), prevmap, 0, hellpick, (i < VOTEROWSADDSONE), votebuffer); + m = G_RandMap(G_TOLFlag(gt), prevmap, 0, hellpick, votebuffer); else - m = G_RandMap(G_TOLFlag(gt), prevmap, 0, 0, true, votebuffer); + m = G_RandMap(G_TOLFlag(gt), prevmap, 0, 0, votebuffer); if (i < VOTEROWS) votebuffer[min(i, 2)] = m; // min() is a dumb workaround for gcc 4.4 array-bounds error WRITEUINT16(p, m); @@ -3354,7 +3354,7 @@ static void Command_RandomMap(void) oldmapnum = -1; } - newmapnum = G_RandMap(G_TOLFlag(newgametype), oldmapnum, 0, 0, false, NULL) + 1; + newmapnum = G_RandMap(G_TOLFlag(newgametype), oldmapnum, 0, 0, NULL) + 1; D_MapChange(newmapnum, newgametype, newencoremode, newresetplayers, 0, false, false); } diff --git a/src/f_finale.c b/src/f_finale.c index 77ca2fb0c..6f720e28b 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1596,7 +1596,7 @@ void F_TitleScreenTicker(boolean run) // prevent console spam if failed demoIdleLeft = demoIdleTime; - mapnum = G_RandMap(TOL_RACE, -2, 2, 0, false, NULL); + mapnum = G_RandMap(TOL_RACE, -2, 2, 0, NULL); if (mapnum == 0) // gotta have ONE { return; diff --git a/src/g_game.c b/src/g_game.c index 4e0b38632..4c1ff172e 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3778,11 +3778,11 @@ static INT32 TOLMaps(UINT8 pgametype) * has those flags. * \author Graue */ -static INT16 *okmaps = NULL; -INT16 G_RandMap(UINT32 tolflags, INT16 pprevmap, UINT8 ignorebuffer, UINT8 maphell, boolean callagainsoon, INT16 *extbuffer) +INT16 G_RandMap(UINT32 tolflags, INT16 pprevmap, UINT8 ignorebuffer, UINT8 maphell, INT16 *extbuffer) { UINT32 numokmaps = 0; INT16 ix, bufx; + INT16 *okmaps = NULL; UINT16 extbufsize = 0; boolean usehellmaps; // Only consider Hell maps in this pick @@ -3924,12 +3924,9 @@ tryagain: ix = okmaps[M_RandomKey(numokmaps)]; } - if (!callagainsoon) - { - //CONS_Printf("(freeing okmaps)\n"); - Z_Free(okmaps); - okmaps = NULL; - } + //CONS_Printf("(freeing okmaps)\n"); + Z_Free(okmaps); + okmaps = NULL; return ix; } @@ -4196,7 +4193,7 @@ static INT16 G_GetNextMap(boolean advancemap) } else if (cv_advancemap.value == 2) // Go to random map. { - newmap = G_RandMap(G_TOLFlag(gametype), curmap, 0, 0, false, NULL); + newmap = G_RandMap(G_TOLFlag(gametype), curmap, 0, 0, NULL); } else if (nextmap >= NEXTMAP_SPECIAL) // Loop back around { diff --git a/src/g_game.h b/src/g_game.h index e5d2df6f5..a0179c7fa 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -275,7 +275,7 @@ FUNCMATH INT32 G_TicsToMilliseconds(tic_t tics); UINT32 G_TOLFlag(INT32 pgametype); INT16 G_GetFirstMapOfGametype(UINT8 pgametype); -INT16 G_RandMap(UINT32 tolflags, INT16 pprevmap, UINT8 ignorebuffer, UINT8 maphell, boolean callagainsoon, INT16 *extbuffer); +INT16 G_RandMap(UINT32 tolflags, INT16 pprevmap, UINT8 ignorebuffer, UINT8 maphell, INT16 *extbuffer); void G_AddMapToBuffer(INT16 map); #ifdef __cplusplus diff --git a/src/m_menu.c b/src/m_menu.c index 6df4ada5d..73e87e3ff 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -4482,7 +4482,7 @@ INT32 MR_PlaybackQuit(INT32 choice) INT32 MR_ChangeLevel(INT32 choice) { (void)choice; - INT16 map = cv_nextmap.value ? cv_nextmap.value : G_RandMap(G_TOLFlag(cv_newgametype.value), gamestate == GS_LEVEL ? gamemap-1 : prevmap, 0, 0, false, NULL); + INT16 map = cv_nextmap.value ? cv_nextmap.value : G_RandMap(G_TOLFlag(cv_newgametype.value), gamestate == GS_LEVEL ? gamemap-1 : prevmap, 0, 0, NULL); M_ClearMenus(true); COM_BufAddText(va("map %d -gametype \"%s\"\n", map, cv_newgametype.string)); return true; @@ -6368,7 +6368,7 @@ INT32 MR_StartServer(INT32 choice) G_StopMetalDemo(); if (!cv_nextmap.value) - CV_SetValue(&cv_nextmap, G_RandMap(G_TOLFlag(cv_newgametype.value), -1, 0, 0, false, NULL)+1); + CV_SetValue(&cv_nextmap, G_RandMap(G_TOLFlag(cv_newgametype.value), -1, 0, 0, NULL)+1); if (cv_maxplayers.value < ssplayers+1) CV_SetValue(&cv_maxplayers, ssplayers+1); From 11e29d5afa52f2bad94e0bfe4a28b97558ba2094 Mon Sep 17 00:00:00 2001 From: NepDisk Date: Thu, 26 Jun 2025 11:13:32 -0400 Subject: [PATCH 11/27] Port Saturn's VoteBG scaling code Thanks to Alug and Indev as per usual --- src/d_netcmd.c | 1 + src/p_setup.c | 44 ++++++++++++++++++ src/p_setup.h | 5 ++ src/screen.c | 3 ++ src/screen.h | 2 +- src/v_video.c | 45 ++++++++++++++++++ src/v_video.h | 4 ++ src/y_inter.c | 124 ++++++++++++++++++++++++++++--------------------- 8 files changed, 173 insertions(+), 55 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index f3585db99..d22cea64b 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1172,6 +1172,7 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_renderview); CV_RegisterVar(&cv_vhseffect); CV_RegisterVar(&cv_shittyscreen); + CV_RegisterVar(&cv_votebgscaling); CV_RegisterVar(&cv_renderer); CV_RegisterVar(&cv_scr_depth); CV_RegisterVar(&cv_scr_width); diff --git a/src/p_setup.c b/src/p_setup.c index 061c50939..c82da3227 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -9246,6 +9246,12 @@ boolean P_AddWadFile(const char *wadfilename, wadcompat_t compat) return true; } +// check for replacement votescreen backgrounds +boolean wideracereplaced = false; +boolean racereplaced = false; +boolean widebattlereplaced = false; +boolean battlereplaced = false; + // // Add a WAD file and do the per-WAD setup stages. // Call P_MultiSetupWadFiles as soon as possible after any number of these. @@ -9411,6 +9417,44 @@ UINT16 P_PartialAddWadFile(const char *wadfilename, wadcompat_t compat) // R_LoadSpriteInfoLumps(wadnum, numlumps); + // + // check for votescreen replacements + // + if (!wideracereplaced && !racereplaced && !widebattlereplaced && !battlereplaced) + { + lumpinfo = wadfiles[wadnum]->lumpinfo; + for (i = 0; i < numlumps; i++, lumpinfo++) + { + name = lumpinfo->name; + + // widescreen patch Race + if (!wideracereplaced && !strncmp(name, "INTERSCW", 8)) + { + wideracereplaced = true; + continue; + } + + if (!racereplaced && !strncmp(name, "INTERSCR", 8)) + { + racereplaced = true; + continue; + } + + // widescreen patch Battle + if (!widebattlereplaced && !strncmp(name, "BATTLSCW", 8)) + { + widebattlereplaced = true; + continue; + } + + if (!battlereplaced && !strncmp(name, "BATTLSCR", 8)) + { + battlereplaced = true; + continue; + } + } + } + refreshdirmenu &= ~REFRESHDIR_GAMEDATA; // Under usual circumstances we'd wait for REFRESHDIR_ flags to disappear the next frame, but this one's a bit too dangerous for that... partadd_stage = 0; return wadnum; diff --git a/src/p_setup.h b/src/p_setup.h index c7c438d3d..b207709f2 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -87,6 +87,11 @@ void HWR_LoadLevel(void); #endif boolean P_AddWadFile(const char *wadfilename, wadcompat_t compat); +extern boolean wideracereplaced; +extern boolean racereplaced; +extern boolean widebattlereplaced; +extern boolean battlereplaced; + #define MAPRET_ADDED (1) #define MAPRET_CURRENTREPLACED (1<<1) UINT8 P_InitMapData(boolean existingmapheaders); diff --git a/src/screen.c b/src/screen.c index ac7c0d391..4ee60f956 100644 --- a/src/screen.c +++ b/src/screen.c @@ -65,6 +65,9 @@ consvar_t cv_vhseffect = CVAR_INIT ("vhspause", "On", CV_SAVE, CV_OnOff, NULL); static CV_PossibleValue_t shittyscreen_cons_t[] = {{0, "Okay"}, {1, "Shitty"}, {2, "Extra Shitty"}, {0, NULL}}; consvar_t cv_shittyscreen = CVAR_INIT ("televisionsignal", "Okay", 0, shittyscreen_cons_t, NULL); +static CV_PossibleValue_t votescale_cons_t[] = {{0, "Vanilla"}, {1, "Adaptive"}, {2, "VerticalFill"}, {3, "HorizontalFill"}, {0, NULL}}; +consvar_t cv_votebgscaling = CVAR_INIT ("votebgscaling", "Adaptive", 0, votescale_cons_t, NULL); + CV_PossibleValue_t cv_renderer_t[] = { {1, "Software"}, #ifdef HWRENDER diff --git a/src/screen.h b/src/screen.h index ca3d91fac..de51d7101 100644 --- a/src/screen.h +++ b/src/screen.h @@ -133,7 +133,7 @@ extern INT32 scr_bpp; extern UINT8 *scr_borderpatch; // patch used to fill the view borders extern consvar_t cv_scr_width, cv_scr_height, cv_scr_depth, cv_renderview, cv_renderer, cv_renderhitbox, cv_fullscreen; -extern consvar_t cv_vhseffect, cv_shittyscreen; +extern consvar_t cv_vhseffect, cv_shittyscreen, cv_votebgscaling; extern consvar_t cv_parallelsoftware; // wait for page flipping to end or not diff --git a/src/v_video.c b/src/v_video.c index e4d39cd40..fe57b7af4 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -1539,6 +1539,51 @@ void V_DrawPatchFill(patch_t *pat) } } +// Draws a patch and tries to always fill the screen with the patch +void V_DrawAdaptiveScaledFullScreenPatch(patch_t *patch) +{ + fixed_t x = 0, y = 0; + fixed_t scale = ((vid.width * FRACUNIT) / patch->width); // fit the screen horizontally + fixed_t scaled_height = FixedMul(patch->height << FRACBITS, scale); + + // however, if this means the patch doesent fill out the screen vertically then + if (scaled_height < (vid.height << FRACBITS)) + { + scale = ((vid.height * FRACUNIT) / patch->height); // scale it to fit the screen vertically + x = ((vid.width << FRACBITS) - FixedMul(patch->width << FRACBITS, scale)) / 2; + } + else + y = (vid.height << FRACBITS) - scaled_height; + + V_DrawFixedPatch(x, y, scale, V_NOSCALEPATCH, patch, NULL); +} + +// Draws a patch and scales it to fill out the screen vertically while remaining centered +void V_DrawVerticallyScaledFullScreenPatch(patch_t *patch) +{ + fixed_t scale = ((vid.height * FRACUNIT) / patch->height); + fixed_t x = ((vid.width << FRACBITS) - FixedMul(patch->width << FRACBITS, scale)) / 2; // i fucking hate maths + + V_DrawFixedPatch(x, 0, scale, V_NOSCALEPATCH, patch, NULL); +} + +// Draws a patch and scales it to fill out the screen horizontally +// centers the patch when its too small to fit the screen vertically +void V_DrawHorizontallyScaledFullScreenPatch(patch_t *patch) +{ + fixed_t scale = ((vid.width * FRACUNIT) / patch->width); + fixed_t scaled_height = FixedMul(patch->height << FRACBITS, scale); + fixed_t y = (vid.height << FRACBITS) - scaled_height; + + // center it if it does not fit the screen vertically + if (scaled_height < (vid.height << FRACBITS)) + { + y /= 2; + } + + V_DrawFixedPatch(0, y, scale, V_NOSCALEPATCH, patch, NULL); +} + void V_DrawVhsEffect(boolean rewind) { static fixed_t upbary = 100*FRACUNIT, downbary = 150*FRACUNIT; diff --git a/src/v_video.h b/src/v_video.h index 1a17cd84c..9e518bdb6 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -341,6 +341,10 @@ void V_DoPostProcessor(INT32 view, INT32 param); void V_DrawPatchFill(patch_t *pat); +void V_DrawAdaptiveScaledFullScreenPatch(patch_t *patch); +void V_DrawVerticallyScaledFullScreenPatch(patch_t *patch); +void V_DrawHorizontallyScaledFullScreenPatch(patch_t *patch); + void VID_BlitLinearScreen(const UINT8 *srcptr, UINT8 *destptr, INT32 width, INT32 height, size_t srcrowbytes, size_t destrowbytes); diff --git a/src/y_inter.c b/src/y_inter.c index ff5eb5dfc..0310b0fbe 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -367,27 +367,22 @@ static void Y_CalculateMatchData(UINT8 rankingsmode, void (*comparison)(INT32)) static void Y_AnimatedVoteScreenCheck(void) { char tmpPrefix[] = "INTS"; - boolean stopSearching = false; if (luaVoteScreen) strncpy(tmpPrefix, luaVoteScreen, 4); - else - { - if(gametype == GT_BATTLE) - strcpy(tmpPrefix, "BTLS"); - } + else if(gametype == GT_BATTLE) + strcpy(tmpPrefix, "BTLS"); strncpy(animPrefix, tmpPrefix, 4); animPrefix[4] = 'C'; strncpy(animWidePrefix, tmpPrefix, 4); animWidePrefix[4] = 'W'; - foundAnimVoteFrames = 0; - foundAnimVoteWideFrames = 0; + foundAnimVoteFrames = foundAnimVoteWideFrames = 0; currentAnimFrame = 0; INT32 i = 1; - while(!stopSearching) + for (;;) { boolean normalLumpExists = W_LumpExists(va("%sC%d", tmpPrefix, i)); boolean wideLumpExists = W_LumpExists(va("%sW%d", tmpPrefix, i)); @@ -401,7 +396,7 @@ static void Y_AnimatedVoteScreenCheck(void) foundAnimVoteWideFrames++; } else // If we don't find at least frame 1 (e.g VEXTRN1), let's just stop looking - stopSearching = true; + break; i++; } @@ -1132,35 +1127,53 @@ static void Y_UnloadData(void) // SRB2Kart: Voting! +static void Y_DrawVoteBackground(patch_t *patch) +{ + switch (cv_votebgscaling.value) + { + case 1: // adaptive + V_DrawAdaptiveScaledFullScreenPatch(patch); + break; + case 2: // vertical-fill + V_DrawVerticallyScaledFullScreenPatch(patch); + break; + case 3: // horizontal-fill + V_DrawHorizontallyScaledFullScreenPatch(patch); + break; + case 0: // vanilla + default: + V_DrawScaledPatch(((vid.width/2) / vid.dupx) - (patch->width/2), + (vid.height / vid.dupy) - patch->height, + V_SNAPTOTOP|V_SNAPTOLEFT, patch); + break; + } +} + // Y_DrawAnimatedVoteScreenPatch // // Draw animated patch based on frame counter on vote screen // -static inline void Y_DrawAnimatedVoteScreenPatch(boolean widePatch) +static void Y_DrawAnimatedVoteScreenPatch(boolean widePatch) { + INT32 nextframe = 0; + patch_t *votebg = NULL; char tempAnimPrefix[7]; - (widePatch) ? strcpy(tempAnimPrefix, animWidePrefix) : strcpy(tempAnimPrefix, animPrefix); - INT32 tempFoundAnimVoteFrames = (widePatch) ? foundAnimVoteWideFrames : foundAnimVoteFrames; + const INT32 tempFoundAnimVoteFrames = ((widePatch ? foundAnimVoteWideFrames : foundAnimVoteFrames) - 1); + + strcpy(tempAnimPrefix, (widePatch ? animWidePrefix : animPrefix)); // Just in case someone provides LESS widescreen frames than normal frames or vice versa, reset the frame counter to 0 - if (widePatch) - { - if (currentAnimFrame > foundAnimVoteWideFrames-1) - currentAnimFrame = 0; - } - else - { - if (currentAnimFrame > foundAnimVoteFrames-1) - currentAnimFrame = 0; - } + if (currentAnimFrame > tempFoundAnimVoteFrames) + currentAnimFrame = 0; - patch_t *background = W_CachePatchName(va("%s%d", tempAnimPrefix, currentAnimFrame + 1), PU_CACHE); - V_DrawScaledPatch(((vid.width/2) / vid.dupx) - (SHORT(background->width)/2), // Keep the width/height adjustments, for screens that are less wide than 320(?) - (vid.height / vid.dupy) - SHORT(background->height), - V_SNAPTOTOP|V_SNAPTOLEFT, background); + nextframe = (currentAnimFrame + 1); - if (renderisnewtic && votetic % 2 == 0 && !paused) - currentAnimFrame = (currentAnimFrame + 1 > tempFoundAnimVoteFrames - 1) ? 0 : currentAnimFrame + 1; + votebg = W_CachePatchName(va("%s%d", (widePatch ? animWidePrefix : animPrefix), nextframe), PU_PATCH); + + Y_DrawVoteBackground(votebg); + + if (renderisnewtic && (votetic % 2 == 0) && !paused) + currentAnimFrame = (nextframe > tempFoundAnimVoteFrames) ? 0 : nextframe; } static fixed_t Y_CalculatePicScale(fixed_t picscale, INT32 hypoti) @@ -1179,6 +1192,32 @@ static fixed_t Y_CalculatePicScale(fixed_t picscale, INT32 hypoti) return picscale; } +static void Y_DrawVoteScreenPatch(void) +{ + patch_t *votebg = NULL; + const boolean widescreen = (vid.width / vid.dupx > 320); + + if (foundAnimVoteWideFrames || foundAnimVoteFrames) + { + Y_DrawAnimatedVoteScreenPatch((foundAnimVoteWideFrames && widescreen)); + return; + } + + votebg = bgpatch; // non widescreen patch + + UINT8 prefgametype = (votelevels[0][1] & ~0x80); + const boolean widebgreplaced = (prefgametype == GT_BATTLE) ? widebattlereplaced : wideracereplaced; + const boolean bgreplaced = (prefgametype == GT_BATTLE) ? battlereplaced : racereplaced; + + if ((widescreen && (widebgreplaced || !bgreplaced)) + || (!widescreen && (widebgreplaced && !bgreplaced))) + { + votebg = widebgpatch; + } + + Y_DrawVoteBackground(votebg); +} + // // Y_VoteDrawer // @@ -1236,31 +1275,8 @@ void Y_VoteDrawer(void) V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); - if (widebgpatch && vid.width / vid.dupx > 320) { - - if(foundAnimVoteWideFrames == 0){ - V_DrawScaledPatch(((vid.width/2) / vid.dupx) - (SHORT(widebgpatch->width)/2), - (vid.height / vid.dupy) - SHORT(widebgpatch->height), - V_SNAPTOTOP|V_SNAPTOLEFT, widebgpatch); - } else { - // patch_t *currPatch = W_CachePatchName(va("%s%d", animPrefix, currentAnimFrame+1), PU_CACHE); - // V_DrawScaledPatch(((vid.width/2) / vid.dupx) - (SHORT(currPatch->width)/2), // Keep the width/height adjustments, for screens that are less wide than 320(?) - // (vid.height / vid.dupy) - SHORT(currPatch->height), - // V_SNAPTOTOP|V_SNAPTOLEFT, currPatch); - // if(votetic % 4 == 0 && !paused){ - // currentAnimFrame = (currentAnimFrame+1 > foundAnimVoteFrames-1) ? 0 : currentAnimFrame + 1; - // } - Y_DrawAnimatedVoteScreenPatch(true); - } - } else { - if(foundAnimVoteFrames == 0) { - V_DrawScaledPatch(((vid.width/2) / vid.dupx) - (SHORT(bgpatch->width)/2), // Keep the width/height adjustments, for screens that are less wide than 320(?) - (vid.height / vid.dupy) - SHORT(bgpatch->height), - V_SNAPTOTOP|V_SNAPTOLEFT, bgpatch); - } else { - Y_DrawAnimatedVoteScreenPatch(false); - } - } + // decides which votebg to draw and draws it + Y_DrawVoteScreenPatch(); rowval = (votemax*3)+((votemax > 1) ? (votemax - 1) : 0); for (i = 0; i < (rowval+1); i++) // First, we need to figure out the height of this thing... From 8e94a8c9fd09ce9841eb2cee7b6a1cad2766c5b8 Mon Sep 17 00:00:00 2001 From: NepDisk Date: Thu, 26 Jun 2025 11:56:23 -0400 Subject: [PATCH 12/27] Vote screen visual refactor port from saturn Thanks to Alug as per usual --- src/lua_hudlib.c | 20 +--- src/p_setup.c | 168 +++++++++++++++------------ src/p_setup.h | 5 - src/y_inter.c | 297 +++++++++++++++++++++++++---------------------- src/y_inter.h | 34 +++++- 5 files changed, 288 insertions(+), 236 deletions(-) diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index c71f7f629..d46da6d36 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -1532,15 +1532,10 @@ static int lib_hudenabled(lua_State *L) static int lib_hudsetvotebackground(lua_State *L) { + memset(VoteScreen.luaPrefix, 0, sizeof(VoteScreen.luaPrefix)); + if (lua_isnoneornil(L, 1)) { - if (luaVoteScreen) - { - free(luaVoteScreen); - } - - luaVoteScreen = NULL; - return 0; } @@ -1551,15 +1546,8 @@ static int lib_hudsetvotebackground(lua_State *L) return luaL_argerror(L, 1, "prefix should 4 characters wide"); } - if (!luaVoteScreen) - { - luaVoteScreen = (char*)malloc(5); - luaVoteScreen[4] = 0; - } - - strncpy(luaVoteScreen, prefix, 4); - - strupr(luaVoteScreen); + strncpy(VoteScreen.luaPrefix, prefix, 4); + strupr(VoteScreen.luaPrefix); return 0; } diff --git a/src/p_setup.c b/src/p_setup.c index c82da3227..8b27500eb 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -70,6 +70,8 @@ #include "deh_tables.h" +#include "y_inter.h" + // for MapLoad hook #include "lua_script.h" #include "lua_hook.h" @@ -9246,11 +9248,92 @@ boolean P_AddWadFile(const char *wadfilename, wadcompat_t compat) return true; } -// check for replacement votescreen backgrounds -boolean wideracereplaced = false; -boolean racereplaced = false; -boolean widebattlereplaced = false; -boolean battlereplaced = false; +static size_t sreplaces = 0, mreplaces = 0, digmreplaces = 0; + + +// +// search for sound replacements +// +static boolean P_CheckSoundReplacements(char *name, size_t i) +{ + if (name[0] == 'D') + { + if (name[1] == 'S') + { + for (i = 1; i < NUMSFX; i++) + { + if (S_sfx[i].name && !strnicmp(S_sfx[i].name, name + 2, 6)) + { + // the sound will be reloaded when needed, + // since sfx->data will be NULL + CONS_Debug(DBG_SETUP, "Sound %.8s replaced\n", name); + + I_FreeSfx(&S_sfx[i]); + + // Re-cache it + //if (S_PrecacheSound()) + //S_sfx[j].data = I_GetSfx(&S_sfx[j]); + + sreplaces++; + return true; + } + } + } + else if (name[1] == '_') + { + CONS_Debug(DBG_SETUP, "Music %.8s ignored\n", name); + mreplaces++; + return true; + } + } + else if (name[0] == 'O' && name[1] == '_') + { + CONS_Debug(DBG_SETUP, "Music %.8s replaced\n", name); + digmreplaces++; + return true; + } + return false; +} + +// +// check for non Lua votescreen replacements +// +static boolean P_CheckVoteReplacements(char *name) +{ + // widescreen patch Race + if (!VoteScreen.replaced.widerace && !memcmp(name, "INTERSCW", 8)) + { + VoteScreen.replaced.widerace = true; + return false; + } + + if (!VoteScreen.replaced.race && !memcmp(name, "INTERSCR", 8)) + { + VoteScreen.replaced.race = true; + return false; + } + + // widescreen patch Battle + if (!VoteScreen.replaced.widebattle && !memcmp(name, "BATTLSCW", 8)) + { + VoteScreen.replaced.widebattle = true; + return false; + } + + if (!VoteScreen.replaced.battle && !memcmp(name, "BATTLSCR", 8)) + { + VoteScreen.replaced.battle = true; + return false; + } + + if (VoteScreen.replaced.widerace && VoteScreen.replaced.race + && VoteScreen.replaced.widebattle && VoteScreen.replaced.battle) + { + return true; + } + + return false; +} // // Add a WAD file and do the per-WAD setup stages. @@ -9258,11 +9341,14 @@ boolean battlereplaced = false; // UINT16 P_PartialAddWadFile(const char *wadfilename, wadcompat_t compat) { - size_t i, j, sreplaces = 0, mreplaces = 0, digmreplaces = 0; + size_t i; UINT16 numlumps, wadnum; char *name; + static boolean allvotereplaced = false; lumpinfo_t *lumpinfo; + sreplaces = mreplaces = digmreplaces = 0; + // Vars to help us with the position start and amount of each resource type. // Useful for PK3s since they use folders. // WADs use markers for some resources, but others such as sounds are checked lump-by-lump anyway. @@ -9336,36 +9422,12 @@ UINT16 P_PartialAddWadFile(const char *wadfilename, wadcompat_t compat) for (i = 0; i < numlumps; i++, lumpinfo++) { name = lumpinfo->name; - if (name[0] == 'D') - { - if (name[1] == 'S') - { - for (j = 1; j < NUMSFX; j++) - { - if (S_sfx[j].name && !strnicmp(S_sfx[j].name, name + 2, 6)) - { - // the sound will be reloaded when needed, - // since sfx->data will be NULL - CONS_Debug(DBG_SETUP, "Sound %.8s replaced\n", name); - I_FreeSfx(&S_sfx[j]); + if (P_CheckSoundReplacements(name, i)); + continue; - sreplaces++; - break; // there shouldn't be two sounds with the same name, so stop looking - } - } - } - else if (name[1] == '_') - { - CONS_Debug(DBG_SETUP, "Music %.8s ignored\n", name); - mreplaces++; - } - } - else if (name[0] == 'O' && name[1] == '_') - { - CONS_Debug(DBG_SETUP, "Music %.8s replaced\n", name); - digmreplaces++; - } + if (!allvotereplaced && P_CheckVoteReplacements(name)) + allvotereplaced = true; } break; } @@ -9417,44 +9479,6 @@ UINT16 P_PartialAddWadFile(const char *wadfilename, wadcompat_t compat) // R_LoadSpriteInfoLumps(wadnum, numlumps); - // - // check for votescreen replacements - // - if (!wideracereplaced && !racereplaced && !widebattlereplaced && !battlereplaced) - { - lumpinfo = wadfiles[wadnum]->lumpinfo; - for (i = 0; i < numlumps; i++, lumpinfo++) - { - name = lumpinfo->name; - - // widescreen patch Race - if (!wideracereplaced && !strncmp(name, "INTERSCW", 8)) - { - wideracereplaced = true; - continue; - } - - if (!racereplaced && !strncmp(name, "INTERSCR", 8)) - { - racereplaced = true; - continue; - } - - // widescreen patch Battle - if (!widebattlereplaced && !strncmp(name, "BATTLSCW", 8)) - { - widebattlereplaced = true; - continue; - } - - if (!battlereplaced && !strncmp(name, "BATTLSCR", 8)) - { - battlereplaced = true; - continue; - } - } - } - refreshdirmenu &= ~REFRESHDIR_GAMEDATA; // Under usual circumstances we'd wait for REFRESHDIR_ flags to disappear the next frame, but this one's a bit too dangerous for that... partadd_stage = 0; return wadnum; diff --git a/src/p_setup.h b/src/p_setup.h index b207709f2..c7c438d3d 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -87,11 +87,6 @@ void HWR_LoadLevel(void); #endif boolean P_AddWadFile(const char *wadfilename, wadcompat_t compat); -extern boolean wideracereplaced; -extern boolean racereplaced; -extern boolean widebattlereplaced; -extern boolean battlereplaced; - #define MAPRET_ADDED (1) #define MAPRET_CURRENTREPLACED (1<<1) UINT8 P_InitMapData(boolean existingmapheaders); diff --git a/src/y_inter.c b/src/y_inter.c index 0310b0fbe..38e848f64 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -84,11 +84,10 @@ typedef struct static y_data data; // graphics -static patch_t *bgpatch = NULL; // INTERSCR -static patch_t *widebgpatch = NULL; static patch_t *bgtile = NULL; // SPECTILE/SRB2BACK static patch_t *interpic = NULL; // custom picture defined in map header static boolean usetile; + static INT32 timer; typedef struct @@ -111,19 +110,6 @@ static INT32 intertic; static INT32 endtic = -1; static INT32 sorttic = -1; -patch_t *animVoteFramesPatches = NULL; -// VEXTRN - Vote (V) Extra (EXT) Race (R) Normal (N - Normal sized patch) -// VEXTBN - Vote (V) Extra (EXT) Battle (B) Normal (N - Normal sized patch) -// VEXTBW - Vote (V) Extra (EXT) Battle (B) Normal (W - Wide patch used in software) -// VEXTRW - Vote (V) Extra (EXT) Race (R) Normal (W - Wide patch used in software) -char animPrefix[] = "INTSC"; -char animWidePrefix[] = "INTSW"; -char *luaVoteScreen = NULL; - -INT32 currentAnimFrame = 0; -static INT32 foundAnimVoteFrames = 0; -static INT32 foundAnimVoteWideFrames = 0; - intertype_t intertype = int_none; intertype_t intermissiontypes[NUMGAMETYPES]; @@ -163,6 +149,9 @@ typedef struct boolean loaded; } y_voteclient; +// votescreen stuff +votescreen_t VoteScreen = {0}; + static y_votelvlinfo levelinfo[13]; static y_voteclient voteclient; static INT32 votetic; @@ -172,12 +161,6 @@ static SINT8 votemax = 3; static INT32 voterowmem = 0; static boolean rowchange = false; static boolean votenotyetpicked; -static patch_t *cursor = NULL; -static patch_t *cursor1 = NULL; -static patch_t *cursor2 = NULL; -static patch_t *cursor3 = NULL; -static patch_t *cursor4 = NULL; -static patch_t *rubyicon = NULL; static void Y_UnloadVoteData(void); @@ -360,48 +343,6 @@ static void Y_CalculateMatchData(UINT8 rankingsmode, void (*comparison)(INT32)) } } -// -// Y_AnimatedVoteScreenCheck -// -// Check if the lumps exist (checking for VEXTR(N|W)xx for race and VEXTRB(N|W)xx for battle) -static void Y_AnimatedVoteScreenCheck(void) -{ - char tmpPrefix[] = "INTS"; - - if (luaVoteScreen) - strncpy(tmpPrefix, luaVoteScreen, 4); - else if(gametype == GT_BATTLE) - strcpy(tmpPrefix, "BTLS"); - - strncpy(animPrefix, tmpPrefix, 4); - animPrefix[4] = 'C'; - strncpy(animWidePrefix, tmpPrefix, 4); - animWidePrefix[4] = 'W'; - - foundAnimVoteFrames = foundAnimVoteWideFrames = 0; - currentAnimFrame = 0; - - INT32 i = 1; - for (;;) - { - boolean normalLumpExists = W_LumpExists(va("%sC%d", tmpPrefix, i)); - boolean wideLumpExists = W_LumpExists(va("%sW%d", tmpPrefix, i)); - - if (normalLumpExists || wideLumpExists) - { - if (normalLumpExists) - foundAnimVoteFrames++; - - if (wideLumpExists) - foundAnimVoteWideFrames++; - } - else // If we don't find at least frame 1 (e.g VEXTRN1), let's just stop looking - break; - - i++; - } -} - // // Y_ConsiderScreenBuffer // @@ -521,11 +462,11 @@ void Y_IntermissionDrawer(void) else if (rendermode != render_soft && usebuffer) HWR_DrawIntermissionBG(); #endif - else if (bgpatch) + else if (VoteScreen.bgpatch) { fixed_t hs = vid.width * FRACUNIT / BASEVIDWIDTH; fixed_t vs = vid.height * FRACUNIT / BASEVIDHEIGHT; - V_DrawStretchyFixedPatch(0, 0, hs, vs, V_NOSCALEPATCH, bgpatch, NULL); + V_DrawStretchyFixedPatch(0, 0, hs, vs, V_NOSCALEPATCH, VoteScreen.bgpatch, NULL); } } else if (bgtile) @@ -1086,7 +1027,8 @@ void Y_EndIntermission(void) K_RetireBots(); } - Y_UnloadData(); + if (!dedicated) + Y_UnloadData(); endtic = -1; sorttic = -1; @@ -1105,7 +1047,7 @@ static void Y_FollowIntermission(void) G_AfterIntermission(); } -#define UNLOAD(x) if (x) {Patch_Free(x);} x = NULL; +#define UNLOAD(x) {if ((x) != NULL) {Patch_Free(x);} x = NULL;} #define CLEANUP(x) x = NULL; // @@ -1113,21 +1055,65 @@ static void Y_FollowIntermission(void) // static void Y_UnloadData(void) { - // In hardware mode, don't Z_ChangeTag a pointer returned by W_CachePatchName(). - // It doesn't work and is unnecessary. - if (rendermode != render_soft) - return; - // unload the background patches - UNLOAD(bgpatch); - UNLOAD(widebgpatch); + UNLOAD(VoteScreen.bgpatch); + UNLOAD(VoteScreen.widebgpatch); UNLOAD(bgtile); UNLOAD(interpic); } // SRB2Kart: Voting! -static void Y_DrawVoteBackground(patch_t *patch) +// +// Y_VoteScreenCheck +// +static void Y_VoteScreenCheck(void) +{ + strcpy(VoteScreen.Prefix, "INTS"); + + if (VoteScreen.luaPrefix[0] != 0) + strlcpy(VoteScreen.Prefix, VoteScreen.luaPrefix, sizeof(VoteScreen.Prefix)); + else if (gametype == GT_BATTLE) + strcpy(VoteScreen.Prefix, "BTLS"); + + VoteScreen.foundLuaVoteFrames = VoteScreen.foundLuaVoteWideFrames = 0; + VoteScreen.currentAnimFrame = 0; + + INT32 i = 1; + + // check for lua vote background replacements + for (;;) + { + // Check if the lumps exist (checking for VEXTR(N|W)xx for race and VEXTRB(N|W)xx for battle) + boolean normalLumpExists = W_LumpExists(va("%sC%d", VoteScreen.Prefix, i)); + boolean wideLumpExists = W_LumpExists(va("%sW%d", VoteScreen.Prefix, i)); + + if (normalLumpExists || wideLumpExists) + { + if (normalLumpExists) + VoteScreen.foundLuaVoteFrames++; + + if (wideLumpExists) + VoteScreen.foundLuaVoteWideFrames++; + } + else // If we don't find at least frame 1 (e.g VEXTRN1), let's just stop looking + break; + + i++; + } + + // non lua vote background handling + boolean prefbattletype = ((votelevels[0][1] & ~0x80) == GT_BATTLE); + VoteScreen.widebgpatch = W_CachePatchName((prefbattletype ? "BATTLSCW" : "INTERSCW"), PU_PATCH); + VoteScreen.bgpatch = W_CachePatchName((prefbattletype ? "BATTLSCR" : "INTERSCR"), PU_PATCH); +} + +// +// Y_VoteBackgroundDrawer +// +// Determines which patch drawer to use for scaling +// +static void Y_VoteBackgroundDrawer(patch_t *patch) { switch (cv_votebgscaling.value) { @@ -1149,31 +1135,75 @@ static void Y_DrawVoteBackground(patch_t *patch) } } -// Y_DrawAnimatedVoteScreenPatch // -// Draw animated patch based on frame counter on vote screen +// Y_DrawLuaVoteScreenPatch // -static void Y_DrawAnimatedVoteScreenPatch(boolean widePatch) +// Handles votebackgrounds set by "setVoteBackground" +// Aswell as animated patches +// +static void Y_DrawLuaVoteScreenPatch(boolean widePatch) { INT32 nextframe = 0; patch_t *votebg = NULL; - char tempAnimPrefix[7]; - const INT32 tempFoundAnimVoteFrames = ((widePatch ? foundAnimVoteWideFrames : foundAnimVoteFrames) - 1); + char tempPrefix[6]; + const INT32 tempfoundAnimLuaVoteFrames = ((widePatch ? VoteScreen.foundLuaVoteWideFrames : VoteScreen.foundLuaVoteFrames) - 1); - strcpy(tempAnimPrefix, (widePatch ? animWidePrefix : animPrefix)); + strcpy(tempPrefix, va("%s%s", VoteScreen.Prefix, (widePatch ? "W" : "C"))); + + // Draw non animated patch + if (!tempfoundAnimLuaVoteFrames) + { + votebg = W_CachePatchName(va("%s1", tempPrefix), PU_PATCH); + Y_VoteBackgroundDrawer(votebg); + return; + } + + // Draw animated patch based on frame counter on vote screen // Just in case someone provides LESS widescreen frames than normal frames or vice versa, reset the frame counter to 0 - if (currentAnimFrame > tempFoundAnimVoteFrames) - currentAnimFrame = 0; + if (VoteScreen.currentAnimFrame > tempfoundAnimLuaVoteFrames) + VoteScreen.currentAnimFrame = 0; - nextframe = (currentAnimFrame + 1); + nextframe = (VoteScreen.currentAnimFrame + 1); - votebg = W_CachePatchName(va("%s%d", (widePatch ? animWidePrefix : animPrefix), nextframe), PU_PATCH); + votebg = W_CachePatchName(va("%s%d", tempPrefix, nextframe), PU_PATCH); - Y_DrawVoteBackground(votebg); + Y_VoteBackgroundDrawer(votebg); if (renderisnewtic && (votetic % 2 == 0) && !paused) - currentAnimFrame = (nextframe > tempFoundAnimVoteFrames) ? 0 : nextframe; + VoteScreen.currentAnimFrame = (nextframe > tempfoundAnimLuaVoteFrames) ? 0 : nextframe; +} + +// +// Y_DrawVoteScreenPatch +// + +static void Y_DrawVoteScreenPatch(void) +{ + patch_t *votebg = NULL; + const boolean widescreen = (vid.width / vid.dupx > 320); + + if (VoteScreen.foundLuaVoteWideFrames || VoteScreen.foundLuaVoteFrames) + { + Y_DrawLuaVoteScreenPatch(((widescreen && VoteScreen.foundLuaVoteWideFrames) || !VoteScreen.foundLuaVoteFrames)); + return; + } + + // non widescreen patch + votebg = VoteScreen.bgpatch; + + UINT8 prefgametype = (votelevels[0][1] & ~0x80); + const boolean widebgreplaced = (prefgametype == GT_BATTLE) ? VoteScreen.replaced.widebattle : VoteScreen.replaced.widerace; + const boolean bgreplaced = (prefgametype == GT_BATTLE) ? VoteScreen.replaced.battle : VoteScreen.replaced.race; + + // we check a bunch of stuff to always have a "valid" fallback + if ((widescreen && (widebgreplaced || !bgreplaced)) + || (!widescreen && (widebgreplaced && !bgreplaced))) + { + votebg = VoteScreen.widebgpatch; // widescreen patch + } + + Y_VoteBackgroundDrawer(votebg); } static fixed_t Y_CalculatePicScale(fixed_t picscale, INT32 hypoti) @@ -1192,32 +1222,6 @@ static fixed_t Y_CalculatePicScale(fixed_t picscale, INT32 hypoti) return picscale; } -static void Y_DrawVoteScreenPatch(void) -{ - patch_t *votebg = NULL; - const boolean widescreen = (vid.width / vid.dupx > 320); - - if (foundAnimVoteWideFrames || foundAnimVoteFrames) - { - Y_DrawAnimatedVoteScreenPatch((foundAnimVoteWideFrames && widescreen)); - return; - } - - votebg = bgpatch; // non widescreen patch - - UINT8 prefgametype = (votelevels[0][1] & ~0x80); - const boolean widebgreplaced = (prefgametype == GT_BATTLE) ? widebattlereplaced : wideracereplaced; - const boolean bgreplaced = (prefgametype == GT_BATTLE) ? battlereplaced : racereplaced; - - if ((widescreen && (widebgreplaced || !bgreplaced)) - || (!widescreen && (widebgreplaced && !bgreplaced))) - { - votebg = widebgpatch; - } - - Y_DrawVoteBackground(votebg); -} - // // Y_VoteDrawer // @@ -1351,7 +1355,7 @@ void Y_VoteDrawer(void) if (!splitscreen) { - thiscurs = cursor; + thiscurs = VoteScreen.cursor[0]; p = consoleplayer; color = levelinfo[i].gtc; colormap = NULL; @@ -1361,19 +1365,19 @@ void Y_VoteDrawer(void) switch (j) { case 1: - thiscurs = cursor2; + thiscurs = VoteScreen.cursor[2]; p = g_localplayers[1]; break; case 2: - thiscurs = cursor3; + thiscurs = VoteScreen.cursor[3]; p = g_localplayers[2]; break; case 3: - thiscurs = cursor4; + thiscurs = VoteScreen.cursor[4]; p = g_localplayers[3]; break; default: - thiscurs = cursor1; + thiscurs = VoteScreen.cursor[1]; p = g_localplayers[0]; break; } @@ -1401,7 +1405,7 @@ void Y_VoteDrawer(void) else { V_DrawFixedPatch(((BASEVIDWIDTH-(1200/hypotdiv)-scaledpicdiff)<width, scale))< 1) ? (cv_votemaxrows.value - 1) : 0); - boolean battlemode = ((votelevels[0][1] & ~VOTEMODIFIER_ENCORE) == GT_BATTLE); // todo gametyperules votemax = cv_votemaxrows.value; // can we please avoid SIGSEGVs voterowmem = cv_votemaxrows.value; // this is just for the notif system @@ -1868,16 +1889,8 @@ void Y_StartVote(void) I_Error("voteendtic is dirty"); #endif - Y_AnimatedVoteScreenCheck(); - - widebgpatch = W_CachePatchName((battlemode ? "BATTLSCW" : "INTERSCW"), PU_STATIC); - bgpatch = W_CachePatchName((battlemode ? "BATTLSCR" : "INTERSCR"), PU_STATIC); - cursor = W_CachePatchName("M_CURSOR", PU_STATIC); - cursor1 = W_CachePatchName("P1CURSOR", PU_STATIC); - cursor2 = W_CachePatchName("P2CURSOR", PU_STATIC); - cursor3 = W_CachePatchName("P3CURSOR", PU_STATIC); - cursor4 = W_CachePatchName("P4CURSOR", PU_STATIC); - rubyicon = W_CachePatchName("RUBYICON", PU_STATIC); + // cache vote patches + Y_InitVoteDrawing(); timer = cv_votetime.value*TICRATE; pickedvote = -1; @@ -1966,17 +1979,17 @@ static void Y_UnloadVoteData(void) { voteclient.loaded = false; - if (rendermode != render_soft) + if (dedicated) return; - UNLOAD(widebgpatch); - UNLOAD(bgpatch); - UNLOAD(cursor); - UNLOAD(cursor1); - UNLOAD(cursor2); - UNLOAD(cursor3); - UNLOAD(cursor4); - UNLOAD(rubyicon); + UNLOAD(VoteScreen.widebgpatch); + UNLOAD(VoteScreen.bgpatch); + UNLOAD(VoteScreen.cursor[0]); + UNLOAD(VoteScreen.cursor[1]); + UNLOAD(VoteScreen.cursor[2]); + UNLOAD(VoteScreen.cursor[3]); + UNLOAD(VoteScreen.cursor[4]); + UNLOAD(VoteScreen.rubyicon); } // diff --git a/src/y_inter.h b/src/y_inter.h index 3ad092744..aebf75d45 100644 --- a/src/y_inter.h +++ b/src/y_inter.h @@ -17,7 +17,6 @@ extern "C" { #endif extern boolean usebuffer; -extern char *luaVoteScreen; void Y_IntermissionDrawer(void); void Y_Ticker(void); @@ -47,6 +46,39 @@ typedef enum extern intertype_t intertype; extern intertype_t intermissiontypes[NUMGAMETYPES]; +// Votescreen stuff +typedef struct +{ + boolean race; // non lua race patch replaced + boolean widerace; // non lua widescreen race patch replaced + boolean battle; // non lua battle patch replaced + boolean widebattle; // non lua widescreen battle patch replaced +} votereplace_t; + +// VEXTRN - Vote (V) Extra (EXT) Race (R) Normal (N - Normal sized patch) +// VEXTRW - Vote (V) Extra (EXT) Race (R) Normal (W - Wide patch) +// VEXTBN - Vote (V) Extra (EXT) Battle (B) Normal (N - Normal sized patch) +// VEXTBW - Vote (V) Extra (EXT) Battle (B) Normal (W - Wide patch) +typedef struct +{ + char Prefix[5]; // Race = INTSX, Battle = BTLSX + char luaPrefix[5]; // prefix for lua votescreens + + INT32 currentAnimFrame; // current animated background frame + + INT32 foundLuaVoteFrames; // normal lua patch frames + INT32 foundLuaVoteWideFrames; // widescreen lua patch frames + + votereplace_t replaced; // checks which non lua patch has been replaced + + patch_t *bgpatch; // votebackground patch + patch_t *widebgpatch; // wide votebackground patch + + patch_t *cursor[5]; // cursor patches + patch_t *rubyicon; // encore ruby patch +} votescreen_t; +extern votescreen_t VoteScreen; + #ifdef __cplusplus } // extern "C" #endif From 02fa20bc11d9a6c45fa9e77dc99afd2355b293dd Mon Sep 17 00:00:00 2001 From: NepDisk Date: Thu, 26 Jun 2025 14:13:51 -0400 Subject: [PATCH 13/27] Update hash for fixed brightmaps --- src/d_main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/d_main.cpp b/src/d_main.cpp index 68e05dbd1..39b4497b2 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -86,8 +86,8 @@ #define ASSET_HASH_TEXTURES_KART 0xb4211b2f32b6a291 #define ASSET_HASH_CHARS_KART 0x1e68a3e01aa5c68b #define ASSET_HASH_MAPS_KART 0x38558ed00da41ce9 -#define ASSET_HASH_MAIN_PK3 0xc71788f74f5972ad -#define ASSET_HASH_MAPPATCH_PK3 0xac5a4a1a51f9ec01 +#define ASSET_HASH_MAIN_PK3 0x2f531b0494b45681 +#define ASSET_HASH_MAPPATCH_PK3 0x15f16c3b176f595b #define ASSET_HASH_BONUSCHARS_KART 0x60e6f13d822a7461 #ifdef USE_PATCH_FILE #define ASSET_HASH_PATCH_PK3 0x0000000000000000 From e450f21ddf8064e75c8ad7a0968bef0d185d36ce Mon Sep 17 00:00:00 2001 From: NepDisk Date: Thu, 26 Jun 2025 14:25:21 -0400 Subject: [PATCH 14/27] Fix battle offsets applying to custom offsets on ring meter --- src/k_hud.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/k_hud.c b/src/k_hud.c index 13e51fde8..ec8ea6375 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -2461,11 +2461,14 @@ static void K_drawRingMeter(void) UINT8 *colormap = NULL; SINT8 coloroffset = 0; - if (gametype == GT_BATTLE) - ringoffsety -= 4; + if (cv_speed_xoffset.value == 0 && cv_speed_yoffset.value == 0) + { + if (gametype == GT_BATTLE) + ringoffsety -= 4; - if (itembreaker) - ringoffsety -= 2; + if (itembreaker) + ringoffsety -= 2; + } if (K_UseColorHud()) coloroffset = 2; From e1905d85cfd6ad61f9925c42e10bee16e7913603 Mon Sep 17 00:00:00 2001 From: NepDisk Date: Thu, 26 Jun 2025 15:54:06 -0400 Subject: [PATCH 15/27] Port Saturn menu additions --- src/m_menu.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 57 insertions(+), 7 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 73e87e3ff..cc09de247 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -332,6 +332,9 @@ CV_PossibleValue_t gametype_cons_t[NUMGAMETYPES+1]; consvar_t cv_newgametype = CVAR_INIT ("newgametype", "Race", CV_HIDEN|CV_CALL, gametype_cons_t, Newgametype_OnChange); +consvar_t cv_showallmaps = CVAR_INIT ("showallmaps", "No", CV_SAVE, CV_YesNo, NULL); +consvar_t cv_showtrackaddon = CVAR_INIT ("showtrackaddon", "Yes", CV_SAVE, CV_YesNo, NULL); + static CV_PossibleValue_t serversort_cons_t[] = { {0,"Ping"}, {1,"Modified State"}, @@ -1630,6 +1633,19 @@ boolean M_Responder(event_t *ev) return true; + case KEY_SPACE: + noFurtherInput = true; + if (!item || !item->cvar) + return true; + + if (item->cvar == &cv_nextmap) + { + S_StartSound(NULL, sfx_menu1); + COM_ImmedExecute("add kartencore 1"); + return true; + } + return true; + case KEY_BACKSPACE: if (!item || !item->cvar || item->cvar == &cv_chooseskin @@ -2002,6 +2018,9 @@ void M_Init(void) COM_AddCommand("manual", Command_Manual_f); + CV_RegisterVar(&cv_showallmaps); + CV_RegisterVar(&cv_showtrackaddon); + // Menu hacks CV_RegisterVar(&cv_dummymenuplayer); CV_RegisterVar(&cv_dummyteam); @@ -2831,17 +2850,17 @@ boolean M_CanShowLevelInList(INT32 mapnum, INT32 gt) switch (levellistmode) { case LLM_CREATESERVER: - // Should the map be hidden? - if (mapheaderinfo[mapnum]->menuflags & LF2_HIDEINMENU && mapnum+1 != gamemap) - return false; - - if (M_MapLocked(mapnum+1)) - return false; // not unlocked - // Check for TOL if (gt >= 0 && !(mapheaderinfo[mapnum]->typeoflevel & G_TOLFlag(gt))) return false; + // Should the map be hidden? + if (mapheaderinfo[mapnum]->menuflags & LF2_HIDEINMENU && mapnum+1 != gamemap) + return cv_showallmaps.value; + + if (M_MapLocked(mapnum+1)) + return cv_showallmaps.value; // not unlocked + return true; /*case LLM_LEVELSELECT: @@ -6401,12 +6420,28 @@ static void M_DrawLevelSelectOnly(INT16 y, boolean selected, boolean leftfade, b patch_t *PictureOfLevel; INT32 x, w, i, oldval, trans, dupadjust = ((vid.width/vid.dupx) - BASEVIDWIDTH)>>1; fixed_t scale = M_GetMapThumbnail(cv_nextmap.value-1, &PictureOfLevel)/4; + menuitem_t *item = currentMenu->numitems ? ¤tMenu->menuitems[itemOn] : NULL; + w = FixedMul(SHORT(PictureOfLevel->width), scale); i = FixedMul(SHORT(PictureOfLevel->height), scale); x = BASEVIDWIDTH/2 - w/2; y = y + 60 - i; + if ((levellistmode != LLM_TIMEATTACK) && (item->cvar == &cv_nextmap)) // so it doesent show in record attack menu + { + char encoretoggle[40] = {0}; + const char *item1 = gamecontrol[0][gc_fire][0] != 0 ? G_KeynumToString(gamecontrol[0][gc_fire][0]) : NULL; + const char *item2 = gamecontrol[0][gc_fire][1] != 0 ? G_KeynumToString(gamecontrol[0][gc_fire][1]) : NULL; + + if (item1 != NULL && item2 != NULL) + snprintf(encoretoggle, 40, "%s/%s - Toggle Encore: %s", item1, item2, cv_kartencore.string); + else + snprintf(encoretoggle, 40, "%s - Toggle Encore: %s", item1 != NULL ? item1 : item2 != NULL ? item2 : "Item", cv_kartencore.string); + + V_DrawThinString(1, BASEVIDHEIGHT-8-1, V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_TRANSLUCENT|V_ALLOWLOWERCASE, encoretoggle); + } + if (selected && skullAnimCounter < 4) trans = 0; else @@ -6414,6 +6449,21 @@ static void M_DrawLevelSelectOnly(INT16 y, boolean selected, boolean leftfade, b V_DrawFill(x-1, y-1, w+2, i+2, trans); // variable reuse... + if (cv_nextmap.value && cv_showtrackaddon.value) + { + char *addonname = wadfiles[WADFILENUM(mapheaderinfo[cv_nextmap.value-1]->lumpnum)]->filename; + INT32 len; + INT32 charlimit = 21 + (dupadjust/5); + nameonly(addonname); + len = strlen(addonname); +#define charsonside 14 + if (len > charlimit) + V_DrawThinString(x+w+5, y+i-8, V_TRANSLUCENT|MENUCAPS, va("%.*s...%s", charsonside, addonname, addonname+((len-charlimit) + charsonside))); // variable reuse... +#undef charsonside + else + V_DrawThinString(x+w+5, y+i-8, V_TRANSLUCENT|MENUCAPS, addonname); // variable reuse... + } + if ((cv_kartencore.value != 1) || gamestate == GS_TIMEATTACK || cv_newgametype.value != GT_RACE) V_DrawFixedPatch(x< Date: Thu, 26 Jun 2025 16:36:51 -0400 Subject: [PATCH 16/27] Update hash and put little easteregg --- src/d_main.cpp | 4 ++-- src/f_finale.c | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/d_main.cpp b/src/d_main.cpp index 39b4497b2..a431aed13 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -86,8 +86,8 @@ #define ASSET_HASH_TEXTURES_KART 0xb4211b2f32b6a291 #define ASSET_HASH_CHARS_KART 0x1e68a3e01aa5c68b #define ASSET_HASH_MAPS_KART 0x38558ed00da41ce9 -#define ASSET_HASH_MAIN_PK3 0x2f531b0494b45681 -#define ASSET_HASH_MAPPATCH_PK3 0x15f16c3b176f595b +#define ASSET_HASH_MAIN_PK3 0x9a6188063fcdcc93 +#define ASSET_HASH_MAPPATCH_PK3 0x93a9213b2b2ba260 #define ASSET_HASH_BONUSCHARS_KART 0x60e6f13d822a7461 #ifdef USE_PATCH_FILE #define ASSET_HASH_PATCH_PK3 0x0000000000000000 diff --git a/src/f_finale.c b/src/f_finale.c index 6f720e28b..a1663b037 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -465,7 +465,9 @@ void F_IntroTicker(void) } if (finalecount == 80) { - sfxenum_t rsound = skins[1].soundsid[SKSKWIN]; + char chars[5][10] = {"tails", "chao", "aiai", "sakura"}; + SINT8 random = P_RandomRange(0, 3); + sfxenum_t rsound = skins[R_SkinAvailable(chars[random])].soundsid[SKSKWIN]; S_StartSound(NULL, sfx_flgcap); S_StartSound(NULL, rsound); } From 24715a611d0fdb8835ab51db63847d8bc758b23c Mon Sep 17 00:00:00 2001 From: NepDisk Date: Thu, 26 Jun 2025 17:26:02 -0400 Subject: [PATCH 17/27] Properly setup encore levelselect input --- src/m_menu.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index cc09de247..5245cff3b 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1314,6 +1314,21 @@ boolean M_Responder(event_t *ev) default: break; } + + if (menustack[0]) + { + menuitem_t *item = currentMenu->numitems ? ¤tMenu->menuitems[itemOn] : NULL; + if (item && item->cvar == &cv_nextmap) + { + if (ch == gamecontrol[0][gc_fire][0] + || ch == gamecontrol[0][gc_fire][1]) + { + S_StartSound(NULL, sfx_menu1); + COM_ImmedExecute("add kartencore 1"); + } + } + } + } else if (menustack[0]) { @@ -1633,19 +1648,6 @@ boolean M_Responder(event_t *ev) return true; - case KEY_SPACE: - noFurtherInput = true; - if (!item || !item->cvar) - return true; - - if (item->cvar == &cv_nextmap) - { - S_StartSound(NULL, sfx_menu1); - COM_ImmedExecute("add kartencore 1"); - return true; - } - return true; - case KEY_BACKSPACE: if (!item || !item->cvar || item->cvar == &cv_chooseskin From 76fc2b21d7f9254d7159df540a18a07e6acc218c Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 27 Jun 2025 11:47:53 +0200 Subject: [PATCH 18/27] Fix software sky threading synchronization issues By splitting sky drawing from plane drawing, so both dont step on each other during drawing this also marginally improves performance --- src/r_main.cpp | 96 ++++++++++-------------- src/r_plane.cpp | 195 ++++++++++++++++++++++++++++-------------------- 2 files changed, 155 insertions(+), 136 deletions(-) diff --git a/src/r_main.cpp b/src/r_main.cpp index 064de28ef..d3e994aab 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -1533,47 +1533,30 @@ static void R_RenderViewpoint(maskcount_t* mask, INT32 cachenum) void R_RenderPlayerView(void) { - INT32 nummasks = 1; - maskcount_t* masks = static_cast(malloc(sizeof(maskcount_t))); - player_t * player = &players[displayplayers[viewssnum]]; - const boolean skybox = (skyboxmo[0] && cv_skybox.value); - UINT8 i; + INT32 nummasks = 1; + maskcount_t* masks = static_cast(malloc(sizeof(maskcount_t))); + player_t * player = &players[displayplayers[viewssnum]]; + const boolean skybox = (skyboxmo[0] && cv_skybox.value); + const boolean oldsky = (skybox && mapnamespace == MNS_SRB2KART); - srb2::ThreadPool::Sema tp_sema; - srb2::g_main_threadpool->begin_sema(); + // using sky portals on kart maps usually results in pretty bad performance + skyVisible = oldsky && skyVisiblePerPlayer[viewssnum]; - // using sky portals on kart maps usually results in very bad performance - if (mapnamespace == MNS_SRB2KART) + if (skyVisible) { - // load previous saved value of skyVisible for the player - for (i = 0; i <= splitscreen; i++) - { - if (player != &players[displayplayers[i]]) - continue; - skyVisible = skyVisiblePerPlayer[i]; - break; - } - if (skybox && skyVisible) - { - R_SkyboxFrame(viewssnum); - R_ClearClipSegs(); - R_ClearDrawSegs(); - R_ClearSegTables(); - R_ClearPlanes(); - R_ClearSprites(); - Mask_Pre(&masks[nummasks - 1]); - R_RenderBSPNode((INT32)numnodes - 1); - Mask_Post(&masks[nummasks - 1]); - R_ClipSprites(drawsegs, NULL); - R_DrawPlanes(); - // well sometimes synchronization is off and may result in some visual glitching, oh well - tp_sema = srb2::g_main_threadpool->end_sema(); - srb2::g_main_threadpool->notify_sema(tp_sema); - srb2::g_main_threadpool->wait_sema(tp_sema); - srb2::g_main_threadpool->begin_sema(); - R_DrawMasked(masks, nummasks); - } + R_SkyboxFrame(viewssnum); + R_ClearClipSegs(); + R_ClearDrawSegs(); + R_ClearSegTables(); + R_ClearPlanes(); + R_ClearSprites(); + R_RenderViewpoint(&masks[nummasks - 1], nummasks - 1); + R_ClipSprites(drawsegs, NULL); + R_DrawSkyPlanes(); + R_DrawPlanes(); + R_DrawMasked(masks, nummasks); } + R_SetupFrame(viewssnum, skybox); skyVisible = false; framecount++; @@ -1589,7 +1572,7 @@ void R_RenderPlayerView(void) portalclipend = viewwidth-viewmorph[viewssnum].x1-1; R_PortalClearClipSegs(portalclipstart, portalclipend); memcpy(ceilingclip, viewmorph[viewssnum].ceilingclip, sizeof(INT16)*vid.width); - memcpy(floorclip, viewmorph[viewssnum].floorclip, sizeof(INT16)*vid.width); + memcpy(floorclip, viewmorph[viewssnum].floorclip, sizeof(INT16)*vid.width); } else { @@ -1611,6 +1594,7 @@ void R_RenderPlayerView(void) mytotal = 0; ProfZeroTimer(); #endif + ps_numbspcalls = ps_numpolyobjects = ps_numdrawnodes = 0; ps_bsptime = I_GetPreciseTime(); @@ -1631,7 +1615,7 @@ void R_RenderPlayerView(void) ps_sw_spritecliptime = I_GetPreciseTime() - ps_sw_spritecliptime; // Add skybox portals caused by sky visplanes. - if (mapnamespace != MNS_SRB2KART && skybox) + if (skybox && !oldsky) Portal_AddSkyboxPortals(); // Portal rendering. Hijacks the BSP traversal. @@ -1672,7 +1656,6 @@ void R_RenderPlayerView(void) // Render the BSP from the new viewpoint, and clip // any sprites with the new clipsegs and window. - R_RenderViewpoint(&masks[nummasks - 1], nummasks - 1); //portalskipprecipmobjs = false; @@ -1690,10 +1673,8 @@ void R_RenderPlayerView(void) ps_sw_portaltime = I_GetPreciseTime() - ps_sw_portaltime; ps_sw_planetime = I_GetPreciseTime(); + R_DrawSkyPlanes(); R_DrawPlanes(); - tp_sema = srb2::g_main_threadpool->end_sema(); - srb2::g_main_threadpool->notify_sema(tp_sema); - srb2::g_main_threadpool->wait_sema(tp_sema); ps_sw_planetime = I_GetPreciseTime() - ps_sw_planetime; // draw mid texture and sprite @@ -1710,6 +1691,7 @@ void R_RenderPlayerView(void) { if (pl->minx > pl->maxx) continue; + auto col = [](int x, int top, int bot) { if (top > bot) @@ -1718,7 +1700,9 @@ void R_RenderPlayerView(void) top = 0; if (bot > viewheight-1) bot = viewheight-1; + UINT8* p = &topleft[x + top * vid.width]; + while (top <= bot) { *p = 35; @@ -1726,21 +1710,27 @@ void R_RenderPlayerView(void) top++; } }; + auto span = [col](int x, int top, int bot) { if (top <= bot) col(x, top, bot); }; + INT32 top = pl->top[pl->minx]; INT32 bottom = pl->bottom[pl->minx]; + span(pl->minx, top, bottom); span(pl->maxx, pl->top[pl->maxx], pl->bottom[pl->maxx]); + for (INT32 x = pl->minx + 1; x < std::min(pl->maxx, viewwidth); ++x) { INT32 new_top = pl->top[x]; INT32 new_bottom = pl->bottom[x]; + if (new_top > new_bottom) continue; + if (top > bottom) { col(x, new_top, new_top); @@ -1751,6 +1741,7 @@ void R_RenderPlayerView(void) col(x, top, new_top); col(x, bottom, new_bottom); } + top = new_top; bottom = new_bottom; } @@ -1761,13 +1752,13 @@ void R_RenderPlayerView(void) // debugrender_portal: fill portals with red, draw over everything if (portal_base && cv_debugrender_portal.value) { - const UINT8 pal = 0x23; // red portal_t *portal; + constexpr UINT8 pal = 0x23; // red for (portal = portal_base; portal; portal = portal_base) { - INT32 width = (portal->end - portal->start); INT32 i; + INT32 width = (portal->end - portal->start); for (i = 0; i < std::min(width, viewwidth); ++i) { @@ -1784,18 +1775,9 @@ void R_RenderPlayerView(void) } } - if (mapnamespace == MNS_SRB2KART) - { - // save value to skyVisiblePerPlayer - // this is so that P1 can't affect whether P2 can see a skybox or not, or vice versa - for (i = 0; i <= splitscreen; i++) - { - if (player != &players[displayplayers[i]]) - continue; - skyVisiblePerPlayer[i] = skyVisible; - break; - } - } + // save value to skyVisiblePerPlayer + // this is so that P1 can't affect whether P2 can see a skybox or not, or vice versa + skyVisiblePerPlayer[viewssnum] = (!oldsky || skyVisible); // if we dont draw the sky using the old method, always mark this as true free(masks); } diff --git a/src/r_plane.cpp b/src/r_plane.cpp index cd0bd462d..291c17fbb 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -149,12 +149,13 @@ static void R_MapPlane(drawspandata_t *ds, spandrawfunc_t *spanfunc, INT32 y, IN if (!R_CheckMapPlane(__func__, y, x1, x2)) return; - angle = (ds->currentplane->viewangle + ds->currentplane->plangle)>>ANGLETOFINESHIFT; + angle = (ds->currentplane->viewangle + ds->currentplane->plangle)>>ANGLETOFINESHIFT; planecos = FINECOSINE(angle); planesin = FINESINE(angle); distance = FixedMul(ds->planeheight, yslope[y]); - span = abs(centery - y); + span = abs(centery - y); + if (span) // Don't divide by zero { ds->xstep = FixedMul(planesin, ds->planeheight) / span; @@ -214,7 +215,7 @@ static void R_MapPlane(drawspandata_t *ds, spandrawfunc_t *spanfunc, INT32 y, IN } } - ds->y = y; + ds->y = y; ds->x1 = x1; ds->x2 = x2; @@ -306,6 +307,7 @@ void R_ClearPlanes(void) static visplane_t *new_visplane(unsigned hash) { visplane_t *check = freetail; + if (!check) { check = static_cast(calloc(1, sizeof (*check))); @@ -317,6 +319,7 @@ static visplane_t *new_visplane(unsigned hash) if (!freetail) freehead = &freetail; } + check->next = visplanes[hash]; visplanes[hash] = check; @@ -409,6 +412,7 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel, if (!pfloor) { hash = visplane_hash(picnum, lightlevel, height); + for (check = visplanes[hash]; check; check = check->next) { if (polyobj != check->polyobj) @@ -456,8 +460,8 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel, check->ripple = ripple; check->damage = damage; - memset(check->top, 0xff, sizeof (check->top)); - memset(check->bottom, 0x00, sizeof (check->bottom)); + memset(check->top, 0xff, sizeof(check->top)); + memset(check->bottom, 0x00, sizeof(check->bottom)); return check; } @@ -512,8 +516,7 @@ visplane_t *R_CheckPlane(visplane_t *pl, INT32 start, INT32 stop) } else { - unsigned hash = - visplane_hash(pl->picnum, pl->lightlevel, pl->height); + unsigned hash = visplane_hash(pl->picnum, pl->lightlevel, pl->height); new_pl = new_visplane(hash); } @@ -537,8 +540,8 @@ visplane_t *R_CheckPlane(visplane_t *pl, INT32 start, INT32 stop) pl = new_pl; pl->minx = start; pl->maxx = stop; - memset(pl->top, 0xff, sizeof pl->top); - memset(pl->bottom, 0x00, sizeof pl->bottom); + memset(pl->top, 0xff, sizeof(pl->top)); + memset(pl->bottom, 0x00, sizeof(pl->bottom)); } return pl; } @@ -570,7 +573,7 @@ static void R_MakeSpans(void (*mapfunc)(drawspandata_t* ds, void(*spanfunc)(draw if (b1 >= vid.height) b1 = vid.height-1; if (t2 >= vid.height) t2 = vid.height-1; if (b2 >= vid.height) b2 = vid.height-1; - if (x-1 >= vid.width) x = vid.width; + if (x-1 >= vid.width) x = vid.width; // We want to draw N spans per subtask to ensure the work is // coarse enough to not be too slow due to task scheduling overhead. @@ -582,6 +585,7 @@ static void R_MakeSpans(void (*mapfunc)(drawspandata_t* ds, void(*spanfunc)(draw { INT32 spanstartcopy[kSpanTaskGranularity] = {0}; INT32 taskspans = 0; + for (int i = 0; i < kSpanTaskGranularity; i++) { if (!((t1 + i) < t2 && (t1 + i) <= b1)) @@ -591,12 +595,14 @@ static void R_MakeSpans(void (*mapfunc)(drawspandata_t* ds, void(*spanfunc)(draw spanstartcopy[i] = spanstart[t1 + i]; taskspans += 1; } + auto task = [=]() mutable -> void { for (int i = 0; i < taskspans; i++) { mapfunc(&dc_copy, spanfunc, t1 + i, spanstartcopy[i], x - 1, false); } }; + if (allow_parallel) { srb2::g_main_threadpool->schedule(std::move(task)); @@ -605,12 +611,14 @@ static void R_MakeSpans(void (*mapfunc)(drawspandata_t* ds, void(*spanfunc)(draw { (task)(); } + t1 += taskspans; } while (b1 > b2 && b1 >= t1) { INT32 spanstartcopy[kSpanTaskGranularity] = {0}; INT32 taskspans = 0; + for (int i = 0; i < kSpanTaskGranularity; i++) { if (!((b1 - i) > b2 && (b1 - i) >= t1)) @@ -620,12 +628,14 @@ static void R_MakeSpans(void (*mapfunc)(drawspandata_t* ds, void(*spanfunc)(draw spanstartcopy[i] = spanstart[b1 - i]; taskspans += 1; } + auto task = [=]() mutable -> void { for (int i = 0; i < taskspans; i++) { mapfunc(&dc_copy, spanfunc, b1 - i, spanstartcopy[i], x - 1, false); } }; + if (allow_parallel) { srb2::g_main_threadpool->schedule(std::move(task)); @@ -634,6 +644,7 @@ static void R_MakeSpans(void (*mapfunc)(drawspandata_t* ds, void(*spanfunc)(draw { (task)(); } + b1 -= taskspans; } @@ -643,28 +654,6 @@ static void R_MakeSpans(void (*mapfunc)(drawspandata_t* ds, void(*spanfunc)(draw spanstart[b2--] = x; } -void R_DrawPlanes(void) -{ - visplane_t *pl; - INT32 i; - drawspandata_t ds {0}; - - ZoneScoped; - - R_UpdatePlaneRipple(&ds); - - for (i = 0; i < MAXVISPLANES; i++, pl++) - { - for (pl = visplanes[i]; pl; pl = pl->next) - { - if (pl->ffloor != NULL || pl->polyobj != NULL) - continue; - - R_DrawSinglePlane(&ds, pl, cv_parallelsoftware.value); - } - } -} - // R_DrawSkyPlane // // Draws the sky within the plane's top/bottom bounds @@ -759,6 +748,75 @@ static void R_DrawSkyPlane(visplane_t *pl, void(*colfunc)(drawcolumndata_t*), bo } } +void R_DrawSkyPlanes(void) +{ + INT32 i; + visplane_t *pl; + + ZoneScoped; + + srb2::ThreadPool::Sema tp_sema; + srb2::g_main_threadpool->begin_sema(); + for (i = 0; i < MAXVISPLANES; i++, pl++) + { + for (pl = visplanes[i]; pl; pl = pl->next) + { + if (pl->picnum != skyflatnum || pl->ffloor || pl->polyobj) + continue; + + INT16 highlight = R_PlaneIsHighlighted(pl); + + if (highlight != -1) + { + drawcolumndata_t dc = {}; + dc.r8_flatcolor = highlight; + dc.lightmap = colormaps; + + for (dc.x = pl->minx; dc.x <= pl->maxx; ++dc.x) + { + dc.yl = pl->top[dc.x]; + dc.yh = pl->bottom[dc.x]; + R_DrawColumn_Flat(&dc); + } + } + else + { + R_DrawSkyPlane(pl, colfunc, cv_parallelsoftware.value); + } + } + } + tp_sema = srb2::g_main_threadpool->end_sema(); + srb2::g_main_threadpool->notify_sema(tp_sema); + srb2::g_main_threadpool->wait_sema(tp_sema); +} + +void R_DrawPlanes(void) +{ + visplane_t *pl; + INT32 i; + drawspandata_t ds {0}; + + ZoneScoped; + + R_UpdatePlaneRipple(&ds); + + srb2::ThreadPool::Sema tp_sema; + srb2::g_main_threadpool->begin_sema(); + for (i = 0; i < MAXVISPLANES; i++, pl++) + { + for (pl = visplanes[i]; pl; pl = pl->next) + { + if (pl->ffloor != NULL || pl->polyobj != NULL) + continue; + + R_DrawSinglePlane(&ds, pl, cv_parallelsoftware.value); + } + } + tp_sema = srb2::g_main_threadpool->end_sema(); + srb2::g_main_threadpool->notify_sema(tp_sema); + srb2::g_main_threadpool->wait_sema(tp_sema); +} + // Returns the height of the sloped plane at (x, y) as a 32.16 fixed_t static INT64 R_GetSlopeZAt(const pslope_t *slope, fixed_t x, fixed_t y) { @@ -939,38 +997,23 @@ void R_DrawSinglePlane(drawspandata_t *ds, visplane_t *pl, boolean allow_paralle INT32 spanfunctype = BASEDRAWFUNC; debugrender_highlight_t debug = debugrender_highlight_t::SW_HI_PLANES; void (*mapfunc)(drawspandata_t*, void(*)(drawspandata_t*), INT32, INT32, INT32, boolean) = R_MapPlane; - INT16 highlight = R_PlaneIsHighlighted(pl); + INT16 highlight; if (!(pl->minx <= pl->maxx)) return; ZoneScoped; - R_UpdatePlaneRipple(ds); - - // sky flat + // we check this here due to drawmasked if (pl->picnum == skyflatnum) { - if (highlight != -1) - { - drawcolumndata_t dc = {}; - dc.r8_flatcolor = highlight; - dc.lightmap = colormaps; - - for (dc.x = pl->minx; dc.x <= pl->maxx; ++dc.x) - { - dc.yl = pl->top[dc.x]; - dc.yh = pl->bottom[dc.x]; - R_DrawColumn_Flat(&dc); - } - } - else - { - R_DrawSkyPlane(pl, colfunc, allow_parallel); - } return; } + R_UpdatePlaneRipple(ds); + + highlight = R_PlaneIsHighlighted(pl); + ds->planeripple.active = false; ds->brightmap = NULL; R_SetSpanFunc(BASEDRAWFUNC, false, false); @@ -980,13 +1023,13 @@ void R_DrawSinglePlane(drawspandata_t *ds, visplane_t *pl, boolean allow_paralle // Hacked up support for alpha value in software mode Tails 09-24-2002 (sidenote: ported to polys 10-15-2014, there was no time travel involved -Red) if (pl->polyobj->translucency >= NUMTRANSMAPS) return; // Don't even draw it - else if (pl->polyobj->translucency > 0) - { - spanfunctype = (pl->polyobj->flags & POF_SPLAT) ? SPANDRAWFUNC_TRANSSPLAT : SPANDRAWFUNC_TRANS; - ds->transmap = R_GetTranslucencyTable(pl->polyobj->translucency); - } - else if (pl->polyobj->flags & POF_SPLAT) // Opaque, but allow transparent flat pixels - spanfunctype = SPANDRAWFUNC_SPLAT; + else if (pl->polyobj->translucency > 0) + { + spanfunctype = (pl->polyobj->flags & POF_SPLAT) ? SPANDRAWFUNC_TRANSSPLAT : SPANDRAWFUNC_TRANS; + ds->transmap = R_GetTranslucencyTable(pl->polyobj->translucency); + } + else if (pl->polyobj->flags & POF_SPLAT) // Opaque, but allow transparent flat pixels + spanfunctype = SPANDRAWFUNC_SPLAT; if (pl->polyobj->translucency == 0 || (pl->extra_colormap && (pl->extra_colormap->flags & CMF_FOG))) light = (pl->lightlevel >> LIGHTSEGSHIFT); @@ -1050,7 +1093,6 @@ void R_DrawSinglePlane(drawspandata_t *ds, visplane_t *pl, boolean allow_paralle debug = SW_HI_PLANES; } - #ifndef NOWATER if (pl->ripple) { INT32 top, bottom; @@ -1061,13 +1103,8 @@ void R_DrawSinglePlane(drawspandata_t *ds, visplane_t *pl, boolean allow_paralle spanfunctype = SPANDRAWFUNC_WATER; // Copy the current scene, ugh - top = pl->high-8; - bottom = pl->low+8; - - if (top < 0) - top = 0; - if (bottom > viewheight) - bottom = viewheight; + top = std::max(0, pl->high - 8); + bottom = std::min(viewheight, pl->low + 8); // Only copy the part of the screen we need UINT8 i = R_GetViewNumber(); @@ -1104,7 +1141,6 @@ void R_DrawSinglePlane(drawspandata_t *ds, visplane_t *pl, boolean allow_paralle vid.width, vid.width); } } - #endif } ds->currentplane = pl; @@ -1116,7 +1152,7 @@ void R_DrawSinglePlane(drawspandata_t *ds, visplane_t *pl, boolean allow_paralle return; texture_t *texture = textures[R_GetTextureNumForFlat(levelflat)]; - ds->flatwidth = texture->width; + ds->flatwidth = texture->width; ds->flatheight = texture->height; /*(if (R_CheckSolidColorFlat()) @@ -1228,8 +1264,8 @@ void R_DrawSinglePlane(drawspandata_t *ds, visplane_t *pl, boolean allow_paralle } // set the maximum value for unsigned - pl->top[pl->maxx+1] = 0xffff; - pl->top[pl->minx-1] = 0xffff; + pl->top[pl->maxx+1] = 0xffff; + pl->top[pl->minx-1] = 0xffff; pl->bottom[pl->maxx+1] = 0x0000; pl->bottom[pl->minx-1] = 0x0000; @@ -1250,10 +1286,11 @@ void R_PlaneBounds(visplane_t *plane) for (i = plane->minx + 1; i <= plane->maxx; i++) { if (plane->top[i] < hi) - hi = plane->top[i]; + hi = plane->top[i]; if (plane->bottom[i] > low) - low = plane->bottom[i]; + low = plane->bottom[i]; } + plane->high = hi; plane->low = low; } @@ -1262,11 +1299,11 @@ INT16 R_PlaneIsHighlighted(const visplane_t *pl) { switch (pl->damage) { - case SD_DEATHPIT: - case SD_INSTAKILL: - return 35; // red + case SD_DEATHPIT: + case SD_INSTAKILL: + return 35; // red - default: - return -1; + default: + return -1; } } From 1fb300d355266938ea96bea19108bb5553ac8250 Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 27 Jun 2025 11:50:12 +0200 Subject: [PATCH 19/27] Small cleanup r_portals --- src/f_finale.c | 2 +- src/p_local.h | 2 +- src/p_tick.c | 9 ++--- src/r_plane.h | 1 + src/r_portal.c | 108 +++++++++++++++++++++++-------------------------- 5 files changed, 57 insertions(+), 65 deletions(-) diff --git a/src/f_finale.c b/src/f_finale.c index a1663b037..f51d7d045 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -480,7 +480,7 @@ void F_IntroTicker(void) // check for skipping if (keypressed) keypressed = false; - + if (animtimer > 0) animtimer--; } diff --git a/src/p_local.h b/src/p_local.h index 8206c8370..5d797bcaf 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -71,7 +71,7 @@ typedef enum THINK_MOBJ, THINK_FLOORS, // thanks diamond square THINK_DYNSLOPE, - + // Lists after this may exist but they do not call an // action in P_RunThinkers NUM_ACTIVETHINKERLISTS, diff --git a/src/p_tick.c b/src/p_tick.c index 92eece7ba..5c3a4ff6d 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -217,7 +217,7 @@ void P_InitThinkers(void) boss3cap = NULL; waypointcap = NULL; kitemcap = NULL; - + iquehead = iquetail = 0; for (i = 0; i <= 15; i++) @@ -782,7 +782,7 @@ void P_Ticker(boolean run) S_StartSound(NULL, sfx_s3kad); // GO! } } - + if (!(gametyperules & GTR_FREEROAM) && leveltime < starttime) // SRB2Kart S_ChangeMusicInternal((encoremode ? "estart" : "kstart"), false); // yes this will be spammed otherwise encore and some stuff WILL overwrite it else if (leveltime == starttime) // The GO! sound stops the level start ambience @@ -793,7 +793,7 @@ void P_Ticker(boolean run) S_ShowMusicCredit(); } } - + } ps_lua_thinkframe_time = I_GetPreciseTime(); @@ -924,10 +924,9 @@ void P_Ticker(boolean run) if (!player->mo) continue; - const boolean isSkyVisibleForPlayer = (!udmf ? skyVisiblePerPlayer[i] : true); const boolean skybox = (skyboxmo[0] && cv_skybox.value); // True if there's a skybox object and skyboxes are on - if (isSkyVisibleForPlayer && skybox) + if (skyVisiblePerPlayer[i] && skybox) { R_SkyboxFrame(i); } diff --git a/src/r_plane.h b/src/r_plane.h index cf4225662..d98263301 100644 --- a/src/r_plane.h +++ b/src/r_plane.h @@ -81,6 +81,7 @@ void R_ClearPlanes(void); void R_ClearFFloorClips (void); void R_DrawPlanes(void); +void R_DrawSkyPlanes(void); visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel, fixed_t xoff, fixed_t yoff, angle_t plangle, extracolormap_t *planecolormap, ffloor_t *ffloor, polyobj_t *polyobj, pslope_t *slope, boolean noencore, boolean ripple, boolean reverseLight, const sector_t *lighting_sector, sectordamage_t damage); diff --git a/src/r_portal.c b/src/r_portal.c index 4e08e3b97..edab00a32 100644 --- a/src/r_portal.c +++ b/src/r_portal.c @@ -20,7 +20,7 @@ #include "r_things.h" #include "r_sky.h" -UINT8 portalrender; /**< When rendering a portal, it establishes the depth of the current BSP traversal. */ +UINT8 portalrender; /**< When rendering a portal, it establishes the depth of the current BSP traversal. */ // Linked list for portals. portal_t *portal_base, *portal_cap; @@ -45,13 +45,13 @@ void Portal_InitList (void) */ void Portal_ClipRange (portal_t* portal) { - INT32 start = portal->start; - INT32 end = portal->end; - INT16 *ceil = portal->ceilingclip; - INT16 *floor = portal->floorclip; - fixed_t *scale = portal->frontscale; - INT32 i; + INT32 start = portal->start; + INT32 end = portal->end; + INT16 *ceil = portal->ceilingclip; + INT16 *floor = portal->floorclip; + fixed_t *scale = portal->frontscale; + for (i = 0; i < end-start; i++) { *ceil = ceilingclip[start+i]; @@ -68,11 +68,11 @@ void Portal_ClipRange (portal_t* portal) void Portal_ClipApply (const portal_t* portal) { INT32 i; - INT32 start = portal->start; - INT32 end = portal->end; - INT16 *ceil = portal->ceilingclip; - INT16 *floor = portal->floorclip; - fixed_t *scale = portal->frontscale; + INT32 start = portal->start; + INT32 end = portal->end; + INT16 *ceil = portal->ceilingclip; + INT16 *floor = portal->floorclip; + fixed_t *scale = portal->frontscale; for (i = 0; i < end-start; i++) { @@ -99,10 +99,10 @@ void Portal_ClipApply (const portal_t* portal) static portal_t* Portal_Add (const INT16 x1, const INT16 x2) { - portal_t *portal = Z_Malloc(sizeof(portal_t), PU_LEVEL, NULL); - INT16 *ceilingclipsave = Z_Malloc(sizeof(INT16)*(x2-x1 + 1), PU_LEVEL, NULL); - INT16 *floorclipsave = Z_Malloc(sizeof(INT16)*(x2-x1 + 1), PU_LEVEL, NULL); - fixed_t *frontscalesave = Z_Malloc(sizeof(fixed_t)*(x2-x1 + 1), PU_LEVEL, NULL); + portal_t *portal = Z_Malloc(sizeof(portal_t), PU_LEVEL, NULL); + INT16 *ceilingclipsave = Z_Malloc(sizeof(INT16)*(x2-x1 + 1), PU_LEVEL, NULL); + INT16 *floorclipsave = Z_Malloc(sizeof(INT16)*(x2-x1 + 1), PU_LEVEL, NULL); + fixed_t *frontscalesave = Z_Malloc(sizeof(fixed_t)*(x2-x1 + 1), PU_LEVEL, NULL); // Linked list. if (!portal_base) @@ -118,11 +118,11 @@ static portal_t* Portal_Add (const INT16 x1, const INT16 x2) portal->next = NULL; // Store clipping values so they can be restored once the portal is rendered. - portal->ceilingclip = ceilingclipsave; - portal->floorclip = floorclipsave; - portal->frontscale = frontscalesave; - portal->start = x1; - portal->end = x2; + portal->ceilingclip = ceilingclipsave; + portal->floorclip = floorclipsave; + portal->frontscale = frontscalesave; + portal->start = x1; + portal->end = x2; // Increase recursion level. portal->pass = portalrender+1; @@ -155,8 +155,8 @@ void Portal_Add2Lines (const INT32 line1, const INT32 line2, const INT32 x1, con portal_t* portal = Portal_Add(x1, x2); // Offset the portal view by the linedef centers - line_t* start = &lines[line1]; - line_t* dest = &lines[line2]; + line_t* start = &lines[line1]; + line_t* dest = &lines[line2]; angle_t dangle = R_PointToAngle2(0,0,dest->dx,dest->dy) - R_PointToAngle2(start->dx,start->dy,0,0); @@ -165,13 +165,6 @@ void Portal_Add2Lines (const INT32 line1, const INT32 line2, const INT32 x1, con vertex_t dest_c, start_c; - if (mapnamespace == MNS_SRB2KART) - { - portal->viewx = viewx; - portal->viewy = viewy; - portal->viewz = viewz; - } - // looking glass center start_c.x = (start->v1->x + start->v2->x) / 2; start_c.y = (start->v1->y + start->v2->y) / 2; @@ -180,24 +173,24 @@ void Portal_Add2Lines (const INT32 line1, const INT32 line2, const INT32 x1, con dest_c.x = (dest->v1->x + dest->v2->x) / 2; dest_c.y = (dest->v1->y + dest->v2->y) / 2; - portal->viewz = viewz + dest->frontsector->floorheight - start->frontsector->floorheight; - - if ((dangle == 0) && (mapnamespace == MNS_SRB2KART)) + if ((mapnamespace == MNS_SRB2KART) && dangle == 0) { // the entrance goes straight opposite the exit, so we just need to mess with the offset. - portal->viewx += dest_c.x - start_c.x; - portal->viewy += dest_c.y - start_c.y; + portal->viewx = viewx + (dest_c.x - start_c.x); + portal->viewy = viewy + (dest_c.y - start_c.y); } else { - disttopoint = R_PointToDist2(start_c.x, start_c.y, viewx, viewy); - angtopoint = R_PointToAngle2(start_c.x, start_c.y, viewx, viewy); - angtopoint += dangle; + disttopoint = R_PointToDist2(start_c.x, start_c.y, viewx, viewy); + angtopoint = R_PointToAngle2(start_c.x, start_c.y, viewx, viewy); + angtopoint += dangle; portal->viewx = dest_c.x + FixedMul(FINECOSINE(angtopoint>>ANGLETOFINESHIFT), disttopoint); portal->viewy = dest_c.y + FixedMul(FINESINE(angtopoint>>ANGLETOFINESHIFT), disttopoint); } + portal->viewz = viewz + (dest->frontsector->floorheight - start->frontsector->floorheight); + portal->viewangle = viewangle + dangle; portal->clipline = line2; @@ -215,22 +208,23 @@ void Portal_Add2Lines (const INT32 line1, const INT32 line2, const INT32 x1, con */ static void Portal_ClipVisplane (const visplane_t* plane, portal_t* portal) { - INT16 start = portal->start; - INT16 end = portal->end; INT32 i; + INT16 start = portal->start; + INT16 end = portal->end; for (i = 0; i < end - start; i++) { // Invalid column. - if (plane->top[i + start] == 65535) + if (plane->top[i + start] == UINT16_MAX) { portal->ceilingclip[i] = -1; - portal->floorclip[i] = -1; + portal->floorclip[i] = -1; continue; } + portal->ceilingclip[i] = plane->top[i + start] - 1; - portal->floorclip[i] = plane->bottom[i + start] + 1; - portal->frontscale[i] = INT32_MAX; + portal->floorclip[i] = plane->bottom[i + start] + 1; + portal->frontscale[i] = INT32_MAX; } } @@ -249,7 +243,6 @@ static boolean TrimVisplaneBounds (const visplane_t* plane, INT16* start, INT16* if (!(*start < *end)) return true; - /** Trims a visplane's horizontal gap to match its render area. * * Visplanes' minx/maxx may sometimes exceed the area they're @@ -257,13 +250,12 @@ static boolean TrimVisplaneBounds (const visplane_t* plane, INT16* start, INT16* * valid area. */ - while (plane->bottom[*start] == 0 && plane->top[*start] == 65535 && *start < *end) + while (plane->bottom[*start] == 0 && plane->top[*start] == UINT16_MAX && *start < *end) { (*start)++; } - - while (plane->bottom[*end - 1] == 0 && plane->top[*start] == 65535 && *end > *start) + while (plane->bottom[*end - 1] == 0 && plane->top[*start] == UINT16_MAX && *end > *start) { (*end)--; } @@ -289,9 +281,9 @@ void Portal_AddSkybox (const visplane_t* plane) Portal_ClipVisplane(plane, portal); - portal->viewx = skyboxmo[0]->x; - portal->viewy = skyboxmo[0]->y; - portal->viewz = skyboxmo[0]->z; + portal->viewx = skyboxmo[0]->x; + portal->viewy = skyboxmo[0]->y; + portal->viewz = skyboxmo[0]->z; portal->viewangle = viewangle + skyboxmo[0]->angle; mh = mapheaderinfo[gamemap-1]; @@ -338,15 +330,15 @@ void Portal_AddSkyboxPortals (void) { for (pl = visplanes[i]; pl; pl = pl->next) { - if (pl->picnum == skyflatnum && !pl->damage) - { - Portal_AddSkybox(pl); + if (pl->picnum != skyflatnum || pl->damage) + continue; - pl->minx = 0; - pl->maxx = -1; + Portal_AddSkybox(pl); - count++; - } + pl->minx = 0; + pl->maxx = -1; + + count++; } } From 258912b685ac1bda322b48ae310635dfa489574d Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 27 Jun 2025 11:53:22 +0200 Subject: [PATCH 20/27] remove obsolute timing stuff from r_main --- src/r_main.cpp | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/src/r_main.cpp b/src/r_main.cpp index d3e994aab..9d2679838 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -45,16 +45,6 @@ #include "hardware/hw_main.h" #endif -//profile stuff --------------------------------------------------------- -//#define TIMING -#ifdef TIMING -#include "p5prof.h" -INT64 mycount; -INT64 mytotal = 0; -//unsigned long nombre = 100000; -#endif -//profile stuff --------------------------------------------------------- - extern consvar_t cv_debugrender_visplanes; extern consvar_t cv_debugrender_freezebsp; @@ -1420,7 +1410,6 @@ void R_SkyboxFrame(int s) newview->z += campos.z * -mh->skybox_scalez; } - R_SetupCommonFrame(player, r_viewmobj->subsector); } @@ -1589,11 +1578,6 @@ void R_RenderPlayerView(void) Mask_Pre(&masks[nummasks - 1]); curdrawsegs = ds_p; -//profile stuff --------------------------------------------------------- -#ifdef TIMING - mytotal = 0; - ProfZeroTimer(); -#endif ps_numbspcalls = ps_numpolyobjects = ps_numdrawnodes = 0; ps_bsptime = I_GetPreciseTime(); @@ -1601,13 +1585,7 @@ void R_RenderPlayerView(void) R_RenderViewpoint(&masks[nummasks - 1], nummasks - 1); ps_bsptime = I_GetPreciseTime() - ps_bsptime; -#ifdef TIMING - RDMSR(0x10, &mycount); - mytotal += mycount; // 64bit add - CONS_Debug(DBG_RENDER, "RenderBSPNode: 0x%d %d\n", *((INT32 *)&mytotal + 1), (INT32)mytotal); -#endif -//profile stuff --------------------------------------------------------- Mask_Post(&masks[nummasks - 1]); ps_sw_spritecliptime = I_GetPreciseTime(); From 5df0ddde3153d471fd74ba9b44a5d2193eac0bea Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 27 Jun 2025 11:59:20 +0200 Subject: [PATCH 21/27] remove erronous mask preparation stuff R_RenderViewpoint already handles this for us --- src/r_main.cpp | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/src/r_main.cpp b/src/r_main.cpp index 9d2679838..b8365cf24 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -1575,19 +1575,11 @@ void R_RenderPlayerView(void) Portal_InitList(); // The head node is the last node output. - - Mask_Pre(&masks[nummasks - 1]); - curdrawsegs = ds_p; - ps_numbspcalls = ps_numpolyobjects = ps_numdrawnodes = 0; ps_bsptime = I_GetPreciseTime(); - R_RenderViewpoint(&masks[nummasks - 1], nummasks - 1); - ps_bsptime = I_GetPreciseTime() - ps_bsptime; - Mask_Post(&masks[nummasks - 1]); - ps_sw_spritecliptime = I_GetPreciseTime(); R_ClipSprites(drawsegs, NULL); ps_sw_spritecliptime = I_GetPreciseTime() - ps_sw_spritecliptime; @@ -1607,7 +1599,7 @@ void R_RenderPlayerView(void) portal_t *portal; - for(portal = portal_base; portal; portal = portal_base) + for (portal = portal_base; portal; portal = portal_base) { portalrender = portal->pass; // Recursiveness depth. @@ -1629,9 +1621,6 @@ void R_RenderPlayerView(void) masks = static_cast(realloc(masks, (++nummasks)*sizeof(maskcount_t))); - Mask_Pre(&masks[nummasks - 1]); - curdrawsegs = ds_p; - // Render the BSP from the new viewpoint, and clip // any sprites with the new clipsegs and window. R_RenderViewpoint(&masks[nummasks - 1], nummasks - 1); From f30d472ad2e9b5ec1a0b24a0cafb39481e494ae3 Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 27 Jun 2025 12:29:56 +0200 Subject: [PATCH 22/27] dont render precip in skyboxes! is really ugly and was never intended, and half the time this would make splashes appear through walls and crap lol --- src/r_main.cpp | 15 ++++++++------- src/r_portal.c | 23 +++++++++++++---------- src/r_portal.h | 29 +++++++++++++++-------------- 3 files changed, 36 insertions(+), 31 deletions(-) diff --git a/src/r_main.cpp b/src/r_main.cpp index b8365cf24..5a4a54e72 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -1502,14 +1502,17 @@ static void Mask_Post (maskcount_t* m) // ================ // viewx, viewy, viewangle, all that good stuff must be set -static void R_RenderViewpoint(maskcount_t* mask, INT32 cachenum) +static void R_RenderViewpoint(maskcount_t* mask, INT32 cachenum, boolean drawprecip) { Mask_Pre(mask); curdrawsegs = ds_p; R_RenderFirstBSPNode(cachenum); - R_AddPrecipitationSprites(); + + // dont draw precip in skyboxes! + if (drawprecip) + R_AddPrecipitationSprites(); Mask_Post(mask); } @@ -1539,7 +1542,7 @@ void R_RenderPlayerView(void) R_ClearSegTables(); R_ClearPlanes(); R_ClearSprites(); - R_RenderViewpoint(&masks[nummasks - 1], nummasks - 1); + R_RenderViewpoint(&masks[nummasks - 1], nummasks - 1, false); R_ClipSprites(drawsegs, NULL); R_DrawSkyPlanes(); R_DrawPlanes(); @@ -1577,7 +1580,7 @@ void R_RenderPlayerView(void) // The head node is the last node output. ps_numbspcalls = ps_numpolyobjects = ps_numdrawnodes = 0; ps_bsptime = I_GetPreciseTime(); - R_RenderViewpoint(&masks[nummasks - 1], nummasks - 1); + R_RenderViewpoint(&masks[nummasks - 1], nummasks - 1, true); ps_bsptime = I_GetPreciseTime() - ps_bsptime; ps_sw_spritecliptime = I_GetPreciseTime(); @@ -1623,9 +1626,7 @@ void R_RenderPlayerView(void) // Render the BSP from the new viewpoint, and clip // any sprites with the new clipsegs and window. - R_RenderViewpoint(&masks[nummasks - 1], nummasks - 1); - - //portalskipprecipmobjs = false; + R_RenderViewpoint(&masks[nummasks - 1], nummasks - 1, !portal->isskybox); R_ClipSprites(ds_p - (masks[nummasks - 1].drawsegs[1] - masks[nummasks - 1].drawsegs[0]), portal); diff --git a/src/r_portal.c b/src/r_portal.c index edab00a32..35cdea232 100644 --- a/src/r_portal.c +++ b/src/r_portal.c @@ -31,7 +31,7 @@ INT32 portalclipstart, portalclipend; portal_t *g_portal; // is curline a portal seg? -void Portal_InitList (void) +void Portal_InitList(void) { portalrender = 0; portal_base = portal_cap = NULL; @@ -43,7 +43,7 @@ void Portal_InitList (void) * the function is called, so it is useful for converting one-sided * lines into portals. */ -void Portal_ClipRange (portal_t* portal) +void Portal_ClipRange(portal_t* portal) { INT32 i; INT32 start = portal->start; @@ -65,7 +65,7 @@ void Portal_ClipRange (portal_t* portal) /** Apply the clipping window from a portal. */ -void Portal_ClipApply (const portal_t* portal) +void Portal_ClipApply(const portal_t* portal) { INT32 i; INT32 start = portal->start; @@ -97,7 +97,7 @@ void Portal_ClipApply (const portal_t* portal) } } -static portal_t* Portal_Add (const INT16 x1, const INT16 x2) +static portal_t* Portal_Add(const INT16 x1, const INT16 x2) { portal_t *portal = Z_Malloc(sizeof(portal_t), PU_LEVEL, NULL); INT16 *ceilingclipsave = Z_Malloc(sizeof(INT16)*(x2-x1 + 1), PU_LEVEL, NULL); @@ -127,10 +127,12 @@ static portal_t* Portal_Add (const INT16 x1, const INT16 x2) // Increase recursion level. portal->pass = portalrender+1; + portal->isskybox = false; + return portal; } -void Portal_Remove (portal_t* portal) +void Portal_Remove(portal_t* portal) { portalcullsector = NULL; portal_base = portal->next; @@ -150,7 +152,7 @@ void Portal_Remove (portal_t* portal) * When the portal renders, it will create the illusion of * the two lines being seamed together. */ -void Portal_Add2Lines (const INT32 line1, const INT32 line2, const INT32 x1, const INT32 x2) +void Portal_Add2Lines(const INT32 line1, const INT32 line2, const INT32 x1, const INT32 x2) { portal_t* portal = Portal_Add(x1, x2); @@ -206,7 +208,7 @@ void Portal_Add2Lines (const INT32 line1, const INT32 line2, const INT32 x1, con * Since visplanes top/bottom windows work in an identical way, * it can just be copied almost directly. */ -static void Portal_ClipVisplane (const visplane_t* plane, portal_t* portal) +static void Portal_ClipVisplane(const visplane_t* plane, portal_t* portal) { INT32 i; INT16 start = portal->start; @@ -230,7 +232,7 @@ static void Portal_ClipVisplane (const visplane_t* plane, portal_t* portal) extern INT32 viewwidth; -static boolean TrimVisplaneBounds (const visplane_t* plane, INT16* start, INT16* end) +static boolean TrimVisplaneBounds(const visplane_t* plane, INT16* start, INT16* end) { *start = plane->minx; *end = plane->maxx + 1; @@ -268,7 +270,7 @@ static boolean TrimVisplaneBounds (const visplane_t* plane, INT16* start, INT16* * Applies the necessary offsets and rotation to give * a depth illusion to the skybox. */ -void Portal_AddSkybox (const visplane_t* plane) +void Portal_AddSkybox(const visplane_t* plane) { INT16 start, end; mapheader_t *mh; @@ -315,12 +317,13 @@ void Portal_AddSkybox (const visplane_t* plane) portal->viewz += viewz * -mh->skybox_scalez; portal->clipline = -1; + portal->isskybox = true; } /** Creates portals for the currently existing sky visplanes. * The visplanes are also removed and cleared from the list. */ -void Portal_AddSkyboxPortals (void) +void Portal_AddSkyboxPortals(void) { visplane_t *pl; INT32 i; diff --git a/src/r_portal.h b/src/r_portal.h index 05fe3d977..cca02e034 100644 --- a/src/r_portal.h +++ b/src/r_portal.h @@ -34,15 +34,16 @@ struct portal_t fixed_t viewz; angle_t viewangle; - UINT8 pass; /**< Keeps track of the portal's recursion depth. */ - INT32 clipline; /**< Optional clipline for line-based portals. */ + UINT8 pass; /**< Keeps track of the portal's recursion depth. */ + INT32 clipline; /**< Optional clipline for line-based portals. */ + boolean isskybox; // Clipping information. - INT32 start; /**< First horizontal pixel coordinate to draw at. */ - INT32 end; /**< Last horizontal pixel coordinate to draw at. */ - INT16 *ceilingclip; /**< Temporary screen top clipping array. */ - INT16 *floorclip; /**< Temporary screen bottom clipping array. */ - fixed_t *frontscale;/**< Temporary screen bottom clipping array. */ + INT32 start; /**< First horizontal pixel coordinate to draw at. */ + INT32 end; /**< Last horizontal pixel coordinate to draw at. */ + INT16 *ceilingclip; /**< Temporary screen top clipping array. */ + INT16 *floorclip; /**< Temporary screen bottom clipping array. */ + fixed_t *frontscale; /**< Temporary screen bottom clipping array. */ }; extern portal_t* portal_base; @@ -53,15 +54,15 @@ extern line_t *portalclipline; extern sector_t *portalcullsector; extern INT32 portalclipstart, portalclipend; -void Portal_InitList (void); -void Portal_Remove (portal_t* portal); -void Portal_Add2Lines (const INT32 line1, const INT32 line2, const INT32 x1, const INT32 x2); -void Portal_AddSkybox (const visplane_t* plane); +void Portal_InitList(void); +void Portal_Remove(portal_t* portal); +void Portal_Add2Lines(const INT32 line1, const INT32 line2, const INT32 x1, const INT32 x2); +void Portal_AddSkybox(const visplane_t* plane); -void Portal_ClipRange (portal_t* portal); -void Portal_ClipApply (const portal_t* portal); +void Portal_ClipRange(portal_t* portal); +void Portal_ClipApply(const portal_t* portal); -void Portal_AddSkyboxPortals (void); +void Portal_AddSkyboxPortals(void); #ifdef __cplusplus } // extern "C" From c8ef0fb705b29db22bdecb934a5b59b037415772 Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 27 Jun 2025 12:49:01 +0200 Subject: [PATCH 23/27] allow threaded render for maskedlist planes since sky synchronizuation issues are fixed, this no longer causes any issues and gives a nice speed bump in some occasions --- src/r_main.cpp | 1 - src/r_things.cpp | 7 ++++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/r_main.cpp b/src/r_main.cpp index 5a4a54e72..b691921ca 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -1527,7 +1527,6 @@ void R_RenderPlayerView(void) { INT32 nummasks = 1; maskcount_t* masks = static_cast(malloc(sizeof(maskcount_t))); - player_t * player = &players[displayplayers[viewssnum]]; const boolean skybox = (skyboxmo[0] && cv_skybox.value); const boolean oldsky = (skybox && mapnamespace == MNS_SRB2KART); diff --git a/src/r_things.cpp b/src/r_things.cpp index 682768d2d..c71bcd076 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -3814,7 +3814,12 @@ static void R_DrawMaskedList (drawnode_t* head) { drawspandata_t ds = {0}; next = r2->prev; - R_DrawSinglePlane(&ds, r2->plane, false); + srb2::ThreadPool::Sema tp_sema; + srb2::g_main_threadpool->begin_sema(); + R_DrawSinglePlane(&ds, r2->plane, cv_parallelsoftware.value); + tp_sema = srb2::g_main_threadpool->end_sema(); + srb2::g_main_threadpool->notify_sema(tp_sema); + srb2::g_main_threadpool->wait_sema(tp_sema); R_DoneWithNode(r2); r2 = next; } From 7c6838c98ed2d5b26e527772420ae5d35aad1538 Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 27 Jun 2025 13:07:58 +0200 Subject: [PATCH 24/27] use M_Random P_ rng functions dont have a seed before loading any level yet so this always returned 3 :blobcatpats: --- src/f_finale.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/f_finale.c b/src/f_finale.c index a1663b037..a4b8f16ba 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -466,7 +466,7 @@ void F_IntroTicker(void) if (finalecount == 80) { char chars[5][10] = {"tails", "chao", "aiai", "sakura"}; - SINT8 random = P_RandomRange(0, 3); + SINT8 random = M_RandomRange(0, 3); sfxenum_t rsound = skins[R_SkinAvailable(chars[random])].soundsid[SKSKWIN]; S_StartSound(NULL, sfx_flgcap); S_StartSound(NULL, rsound); @@ -480,7 +480,7 @@ void F_IntroTicker(void) // check for skipping if (keypressed) keypressed = false; - + if (animtimer > 0) animtimer--; } From b2b0ec19d69d71266d0185f5e273be94a0c78714 Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 27 Jun 2025 13:13:11 +0200 Subject: [PATCH 25/27] draw black background during blan intro screen prevents white border on higher resolutions --- src/f_finale.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/f_finale.c b/src/f_finale.c index a4b8f16ba..2a65b42a8 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -337,16 +337,16 @@ static void F_IntroDrawScene(void) { background = W_CachePatchName("KARTKREW", PU_CACHE); highres = true; + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 0); } if (intro_scenenum == 1) { background = W_CachePatchName("BLANKART", PU_CACHE); highres = false; + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); } - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 0); - if (background) { if (highres) From 45170bb65cbb53ea9c65316423d508272699f59d Mon Sep 17 00:00:00 2001 From: NepDisk Date: Fri, 27 Jun 2025 07:55:35 -0400 Subject: [PATCH 26/27] Fix weird snapping on net jitters --- src/d_clisrv.c | 14 +------------- src/d_main.cpp | 19 ++++++++++++++----- src/p_tick.c | 7 +++++++ 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 4762d89c6..b0578ea59 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -5634,7 +5634,6 @@ boolean TryRunTics(tic_t realtics) if (ticking) { { - boolean tickInterp = true; // run the count * tics while (neededtic > gametic) @@ -5663,19 +5662,8 @@ boolean TryRunTics(tic_t realtics) P_PostLoadLevel(); } - boolean run = (gametic % NEWTICRATERATIO) == 0; - - if (run && tickInterp) - { - // Update old view state BEFORE ticking so resetting - // the old interpolation state from game logic works. - R_UpdateViewInterpolation(); - tickInterp = false; // do not update again in sped-up tics - } - - G_Ticker(run); + G_Ticker((gametic % NEWTICRATERATIO) == 0); } - if (Playing() && netgame && (gametic % TICRATE == 0)) { Schedule_Run(); diff --git a/src/d_main.cpp b/src/d_main.cpp index a431aed13..2206d2963 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -893,7 +893,9 @@ void D_SRB2Loop(void) { renderdeltatics = FLOAT_TO_FIXED(deltatics); - if (!(paused || P_AutoPause()) && !hu_stopped) + const boolean lagging = ((deltatics >= 1.0) || hu_stopped); + + if (!(paused || P_AutoPause()) && !lagging) { rendertimefrac = g_time.timefrac; } @@ -902,7 +904,14 @@ void D_SRB2Loop(void) rendertimefrac = FRACUNIT; } - rendertimefrac_unpaused = g_time.timefrac; + if (!lagging) + { + rendertimefrac_unpaused = g_time.timefrac; + } + else + { + rendertimefrac_unpaused = FRACUNIT; + } } else { @@ -942,7 +951,7 @@ void D_SRB2Loop(void) // Fully completed frame made. finishprecise = I_GetPreciseTime(); - // Use the time before sleep for frameskip calculations: + // Use the time before sleep for frameskip calculations: // post-sleep time is literally being intentionally wasted deltasecs = (double)((INT64)(finishprecise - enterprecise)) / I_GetPrecisePrecision(); deltatics = deltasecs * NEWTICRATE; @@ -1534,11 +1543,11 @@ void D_SRB2Main(void) I_Error("modifiedgame set during startup!"); CONS_Printf("W_InitMultipleFiles(): Adding external PWADs.\n"); - + // HACK: Refer to https://git.do.srb2.org/KartKrew/RingRacers/-/merge_requests/29#note_61574 partadd_earliestfile = numwadfiles; W_InitMultipleFiles(startuppwads, true); - + // Only search for pwad maps and reload graphics if we actually have a pwad added if (startuppwads[0] != NULL) { diff --git a/src/p_tick.c b/src/p_tick.c index 92eece7ba..48a5ed6d3 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -665,6 +665,13 @@ void P_Ticker(boolean run) players[i].jointime++; } + if (run) + { + // Update old view state BEFORE ticking so resetting + // the old interpolation state from game logic works. + R_UpdateViewInterpolation(); + } + if (objectplacing) { if (OP_FreezeObjectplace()) From 7ea321de323ffc17c1887d40412891fd5df99f87 Mon Sep 17 00:00:00 2001 From: NepDisk Date: Fri, 27 Jun 2025 10:22:42 -0400 Subject: [PATCH 27/27] Drift feel improvements Should make it feel closer to v1 --- src/g_game.c | 7 +++++++ src/k_kart.c | 13 ++++++------- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 4c1ff172e..0e9076a0c 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1152,6 +1152,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) if (joystickvector.xaxis != 0) { cmd->turning -= (tspeed * KART_FULLTURN) / JOYAXISRANGE; + cmd->angle -= (tspeed * KART_FULLTURN) / JOYAXISRANGE; side += (joystickvector.xaxis * 4) / JOYAXISRANGE; } @@ -1160,6 +1161,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) { INT32 mousex = gamekeydown[0][KEY_MOUSEMOVE+3] - gamekeydown[0][KEY_MOUSEMOVE+2]; cmd->turning -= (mousex * 8) * (encoremode ? -1 : 1); + cmd->angle -= (mousex * 8) * (encoremode ? -1 : 1); } if (spectating || objectplacing) // SRB2Kart: spectators need special controls @@ -1316,6 +1318,11 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) else if (cmd->turning < -KART_FULLTURN) cmd->turning = -KART_FULLTURN; + if (cmd->angle > KART_FULLTURN) + cmd->angle = KART_FULLTURN; + else if (cmd->angle < -KART_FULLTURN) + cmd->angle = -KART_FULLTURN; + if (cmd->throwdir > KART_FULLTURN) cmd->throwdir = KART_FULLTURN; else if (cmd->throwdir < -KART_FULLTURN) diff --git a/src/k_kart.c b/src/k_kart.c index bcf7a42bf..27dcb174d 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -9152,25 +9152,24 @@ boolean K_CheckPlayersRespawnColliding(INT32 playernum, fixed_t x, fixed_t y) // turndir is the direction the controls are telling us to turn, -1 if turning right and 1 if turning left static INT16 K_GetKartDriftValue(player_t *player, fixed_t countersteer) { - INT16 basedrift, driftadjust; + INT16 basedrift, driftangle; fixed_t driftweight = player->kartweight*14; // 12 if (player->drift == 0 || !P_IsObjectOnGround(player->mo)) { - // If they aren't drifting or on the ground, this doesn't apply + // If they aren't drifting or on the ground this doesn't apply return 0; } if (player->pflags & PF_DRIFTEND) { - // Drift has ended and we are tweaking their angle back a bit - return -266*player->drift; + return -266*player->drift; // Drift has ended and we are tweaking their angle back a bit } - basedrift = (83 * player->drift) - (((driftweight - 14) * player->drift) / 5); // 415 - 303 - driftadjust = abs((252 - driftweight) * player->drift / 5); + basedrift = 83*player->drift - (driftweight - 14)*player->drift/5; // 415 - 303 + driftangle = abs((252 - driftweight)*player->drift/5); - return basedrift + (FixedMul(driftadjust * FRACUNIT, countersteer) / FRACUNIT); + return basedrift + FixedMul(driftangle, countersteer); } INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue)