diff --git a/.travis.yml b/.travis.yml index e9c8d0d7..3081caa6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,6 +26,7 @@ matrix: - p7zip-full - gcc-4.4 compiler: gcc-4.4 + env: GCC44=1 if: env(DPL_ENABLED) != "1" OR env(DPL_TERMINATE_TESTS) != "1" OR NOT branch =~ /^.*deployer.*$/ #gcc-4.4 (Ubuntu/Linaro 4.4.7-8ubuntu1) 4.4.7 - os: linux @@ -39,6 +40,7 @@ matrix: - p7zip-full - gcc-4.6 compiler: gcc-4.6 + env: GCC46=1 if: env(DPL_ENABLED) != "1" OR env(DPL_TERMINATE_TESTS) != "1" OR NOT branch =~ /^.*deployer.*$/ #gcc-4.6 (Ubuntu/Linaro 4.6.4-6ubuntu2) 4.6.4 - os: linux @@ -52,10 +54,12 @@ matrix: - p7zip-full - gcc-4.7 compiler: gcc-4.7 + env: GCC47=1 if: env(DPL_ENABLED) != "1" OR env(DPL_TERMINATE_TESTS) != "1" OR NOT branch =~ /^.*deployer.*$/ #gcc-4.7 - os: linux compiler: gcc + env: GCC48=1 if: env(DPL_ENABLED) != "1" OR env(DPL_TERMINATE_TESTS) != "1" OR NOT branch =~ /^.*deployer.*$/ #gcc (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4 - os: linux @@ -71,6 +75,7 @@ matrix: - p7zip-full - gcc-4.8 compiler: gcc-4.8 + env: GCC48=1 if: env(DPL_ENABLED) != "1" OR env(DPL_TERMINATE_TESTS) != "1" OR NOT branch =~ /^.*deployer.*$/ #gcc-4.8 (Ubuntu 4.8.5-2ubuntu1~14.04.1) 4.8.5 - os: linux @@ -86,7 +91,7 @@ matrix: - p7zip-full - gcc-7 compiler: gcc-7 - env: WFLAGS="-Wno-tautological-compare -Wno-error=implicit-fallthrough -Wno-implicit-fallthrough" + env: WFLAGS="-Wno-tautological-compare -Wno-error=implicit-fallthrough -Wno-implicit-fallthrough" GCC72=1 if: env(DPL_ENABLED) != "1" OR env(DPL_TERMINATE_TESTS) != "1" OR NOT branch =~ /^.*deployer.*$/ #gcc-7 (Ubuntu 7.2.0-1ubuntu1~14.04) 7.2.0 20170802 - os: linux @@ -102,7 +107,7 @@ matrix: - p7zip-full - gcc-8 compiler: gcc-8 - env: WFLAGS="-Wno-tautological-compare -Wno-error=implicit-fallthrough -Wno-implicit-fallthrough -Wno-error=format-overflow" + env: WFLAGS="-Wno-tautological-compare -Wno-error=implicit-fallthrough -Wno-implicit-fallthrough -Wno-error=format-overflow" GCC81=1 if: env(DPL_ENABLED) != "1" OR env(DPL_TERMINATE_TESTS) != "1" OR NOT branch =~ /^.*deployer.*$/ #gcc-8 (Ubuntu 7.2.0-1ubuntu1~14.04) 8.1.0 - os: linux diff --git a/CMakeLists.txt b/CMakeLists.txt index 43142386..631da056 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.0) # DO NOT CHANGE THIS SRB2 STRING! Some variable names depend on this string. # Version change is fine. project(SRB2 - VERSION 1.0.2 + VERSION 1.0.4 LANGUAGES C) if(${PROJECT_SOURCE_DIR} MATCHES ${PROJECT_BINARY_DIR}) @@ -57,7 +57,8 @@ macro(copy_files_to_build_dir target dlllist_var) endmacro() # 64-bit check -if(${CMAKE_SIZEOF_VOID_P} EQUAL 8) +message(STATUS "CMAKE_SIZEOF_VOID_P=" ${CMAKE_SIZEOF_VOID_P}) +if(CMAKE_SIZEOF_VOID_P EQUAL 8) message(STATUS "Target is 64-bit") set(SRB2_SYSTEM_BITS 64) else() diff --git a/appveyor.yml b/appveyor.yml index e7ce1b2f..10b65891 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 1.0.2.{branch}-{build} +version: 1.0.4.{branch}-{build} os: MinGW environment: @@ -29,7 +29,7 @@ environment: ############################## DPL_ENABLED: 0 DPL_TAG_ENABLED: 0 - DPL_INSTALLER_NAME: srb2kart-v102 + DPL_INSTALLER_NAME: srb2kart-v104 # Asset handling is barebones vs. Travis Deployer. We operate on 7z only. # Include the README files and the OpenGL batch in the main and patch archives. # The x86/x64 archives contain the DLL binaries. diff --git a/src/Makefile.cfg b/src/Makefile.cfg index 236d7ae2..a0398154 100644 --- a/src/Makefile.cfg +++ b/src/Makefile.cfg @@ -7,6 +7,10 @@ # and other things # +ifdef GCC81 +GCC80=1 +endif + ifdef GCC80 GCC72=1 endif diff --git a/src/command.c b/src/command.c index 886fc85f..31d1b478 100644 --- a/src/command.c +++ b/src/command.c @@ -1254,7 +1254,8 @@ found: var->string = var->zstring = Z_StrDup(valstr); - if (override) + if (var->flags & CV_PASSWORD); // Don't change value for password field + else if (override) var->value = overrideval; else if (var->flags & CV_FLOAT) { diff --git a/src/command.h b/src/command.h index 71cef9d9..55c8700f 100644 --- a/src/command.h +++ b/src/command.h @@ -95,7 +95,8 @@ typedef enum CV_HIDEN = 1024, // variable is not part of the cvar list so cannot be accessed by the console // can only be set when we have the pointer to it // used on menus - CV_CHEAT = 2048 // Don't let this be used in multiplayer unless cheats are on. + CV_CHEAT = 2048, // Don't let this be used in multiplayer unless cheats are on. + CV_PASSWORD = 4096 // Password field } cvflags_t; typedef struct CV_PossibleValue_s diff --git a/src/config.h.in b/src/config.h.in index a1f5d0a6..bd7e7861 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -37,7 +37,7 @@ * Last updated 2015 / 05 / 03 - SRB2 v2.1.15 - srb2.srb * Last updated 2018 / 12 / 23 - SRB2 v2.1.22 - patch.dta * Last updated 2019 / 01 / 18 - Kart v1.0.2 - Main assets - * Last updated 2019 / 02 / 04 - Kart v1.0.3 - patch.kart + * Last updated 2019 / 03 / 11 - Kart v1.0.4 - patch.kart */ // Base SRB2 hashes @@ -52,7 +52,7 @@ #define ASSET_HASH_CHARS_KART "e2c428347dde52858a3dacd29fc5b964" #define ASSET_HASH_MAPS_KART "1335cd064656aedca359cfbb5233ac4a" #ifdef USE_PATCH_KART -#define ASSET_HASH_PATCH_KART "e06c1c90e5645c886026311964f8e1f5" +#define ASSET_HASH_PATCH_KART "b5f48e1abccfa47a5745199182e2fef4" #endif #endif diff --git a/src/console.c b/src/console.c index a10d73e7..44bb03a3 100644 --- a/src/console.c +++ b/src/console.c @@ -544,6 +544,22 @@ static void CON_MoveConsole(void) } } +INT32 CON_ShiftChar(INT32 ch) +{ + if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) + { + if (shiftdown ^ capslock) + ch = shiftxform[ch]; + } + else // if we're holding shift we should still shift non letter symbols + { + if (shiftdown) + ch = shiftxform[ch]; + } + + return ch; +} + // Clear time of console heads up messages // void CON_ClearHUD(void) @@ -1084,16 +1100,6 @@ boolean CON_Responder(event_t *ev) else if (key == KEY_KPADSLASH) key = '/'; - // capslock - if (key == KEY_CAPSLOCK) // it's a toggle. - { - if (capslock) - capslock = false; - else - capslock = true; - return true; - } - // same capslock code as hu_stuff.c's HU_responder. Check there for details. if ((key >= 'a' && key <= 'z') || (key >= 'A' && key <= 'Z')) { diff --git a/src/console.h b/src/console.h index 98df6ee2..11621746 100644 --- a/src/console.h +++ b/src/console.h @@ -44,6 +44,8 @@ extern UINT8 *yellowmap, *purplemap, *greenmap, *bluemap, *graymap, *redmap, *or // Console bg color (auto updated to match) extern UINT8 *consolebgmap; +INT32 CON_ShiftChar(INT32 ch); + void CON_SetupBackColormap(void); void CON_ClearHUD(void); // clear heads up messages diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 370b2dea..79ed85d7 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -22,6 +22,7 @@ #include "i_video.h" #include "d_net.h" #include "d_main.h" +#include "d_event.h" #include "g_game.h" #include "hu_stuff.h" #include "keys.h" @@ -72,6 +73,7 @@ #define PREDICTIONQUEUE BACKUPTICS #define PREDICTIONMASK (PREDICTIONQUEUE-1) #define MAX_REASONLENGTH 30 +#define FORCECLOSE 0x8000 boolean server = true; // true or false but !server == client #define client (!server) @@ -93,6 +95,7 @@ static tic_t freezetimeout[MAXNETNODES]; // Until when can this node freeze the UINT16 pingmeasurecount = 1; UINT32 realpingtable[MAXPLAYERS]; //the base table of ping where an average will be sent to everyone. UINT32 playerpingtable[MAXPLAYERS]; //table of player latency values. +tic_t servermaxping = 800; // server's max ping. Defaults to 800 #endif SINT8 nodetoplayer[MAXNETNODES]; SINT8 nodetoplayer2[MAXNETNODES]; // say the numplayer for this node if any (splitscreen) @@ -648,6 +651,8 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i) rsp->jointime = (tic_t)LONG(players[i].jointime); + rsp->splitscreenindex = players[i].splitscreenindex; + rsp->hasmo = false; //Transfer important mo information if the player has a body. //This lets us resync players even if they are dead. @@ -783,6 +788,8 @@ static void resynch_read_player(resynch_pak *rsp) players[i].jointime = (tic_t)LONG(rsp->jointime); + players[i].splitscreenindex = rsp->splitscreenindex; + //We get a packet for each player in game. if (!playeringame[i]) return; @@ -1121,12 +1128,22 @@ typedef enum CL_DOWNLOADSAVEGAME, #endif CL_CONNECTED, - CL_ABORTED + CL_ABORTED, + CL_ASKDOWNLOADFILES, + CL_WAITDOWNLOADFILESRESPONSE, + CL_CHALLENGE } cl_mode_t; static void GetPackets(void); static cl_mode_t cl_mode = CL_SEARCHING; +static boolean cl_needsdownload = false; + +static UINT8 cl_challengenum = 0; +static UINT8 cl_challengequestion[MD5_LEN+1]; +static char cl_challengepassword[65]; +static UINT8 cl_challengeanswer[MD5_LEN+1]; +static UINT8 cl_challengeattempted = 0; // Player name send/load @@ -1163,6 +1180,8 @@ static void CV_LoadPlayerNames(UINT8 **p) } #ifdef CLIENT_LOADINGSCREEN +static UINT32 SL_SearchServer(INT32 node); + // // CL_DrawConnectionStatus // @@ -1186,11 +1205,42 @@ static inline void CL_DrawConnectionStatus(void) // 15 pal entries total. const char *cltext; - for (i = 0; i < 16; ++i) - V_DrawFill((BASEVIDWIDTH/2-128) + (i * 16), BASEVIDHEIGHT-24, 16, 8, palstart + ((animtime - i) & 15)); + if (cl_mode != CL_CHALLENGE) + for (i = 0; i < 16; ++i) + V_DrawFill((BASEVIDWIDTH/2-128) + (i * 16), BASEVIDHEIGHT-24, 16, 8, palstart + ((animtime - i) & 15)); switch (cl_mode) { + case CL_CHALLENGE: + { + char asterisks[33]; + size_t sl = min(32, strlen(cl_challengepassword)); + UINT32 serverid; + + memset(asterisks, '*', sl); + memset(asterisks+sl, 0, 33-sl); + + V_DrawString(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, V_MONOSPACE|V_ALLOWLOWERCASE, asterisks); + V_DrawFixedPatch((BASEVIDWIDTH/2) << FRACBITS, (BASEVIDHEIGHT/2) << FRACBITS, FRACUNIT, 0, W_CachePatchName("BSRVLOCK", PU_CACHE), NULL); + + serverid = SL_SearchServer(servernode); + + if (serverid == UINT32_MAX) + { + M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT/2-8, 32, 1); + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2, V_REDMAP, M_GetText("This server is password protected.")); + } + else + { + M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT/2-8, 32, 3); + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2, V_REDMAP, M_GetText("This server,")); + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2+8, V_ALLOWLOWERCASE, serverlist[serverid].info.servername); + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2+16, V_REDMAP, M_GetText("is password protected.")); + } + + cltext = M_GetText(cl_challengeattempted ? "Incorrect password. Please try again." : "Please enter the server password."); + } + break; #ifdef JOININGAME case CL_DOWNLOADSAVEGAME: if (lastfilenum != -1) @@ -1210,6 +1260,9 @@ static inline void CL_DrawConnectionStatus(void) case CL_WAITJOINRESPONSE: cltext = M_GetText("Requesting to join..."); break; + case CL_ASKDOWNLOADFILES: + case CL_WAITDOWNLOADFILESRESPONSE: + cltext = M_GetText("Waiting to download files..."); default: cltext = M_GetText("Connecting to server..."); break; @@ -1287,6 +1340,9 @@ static boolean CL_SendJoin(void) netbuffer->u.clientcfg.localplayers = localplayers; netbuffer->u.clientcfg.version = VERSION; netbuffer->u.clientcfg.subversion = SUBVERSION; + netbuffer->u.clientcfg.needsdownload = cl_needsdownload; + netbuffer->u.clientcfg.challengenum = cl_challengenum; + memcpy(netbuffer->u.clientcfg.challengeanswer, cl_challengeanswer, MD5_LEN); return HSendPacket(servernode, true, 0, sizeof (clientconfig_pak)); } @@ -1307,7 +1363,13 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime) netbuffer->u.serverinfo.gametype = (UINT8)(G_BattleGametype() ? VANILLA_GT_MATCH : VANILLA_GT_RACE); // SRB2Kart: Vanilla's gametype constants for MS support netbuffer->u.serverinfo.modifiedgame = (UINT8)modifiedgame; netbuffer->u.serverinfo.cheatsenabled = CV_CheatsEnabled(); - netbuffer->u.serverinfo.isdedicated = (UINT8)dedicated; + + netbuffer->u.serverinfo.kartvars = (UINT8) ( + (cv_kartspeed.value & SV_SPEEDMASK) | + (dedicated ? SV_DEDICATED : 0) | + (D_IsJoinPasswordOn() ? SV_PASSWORD : 0) + ); + strncpy(netbuffer->u.serverinfo.servername, cv_servername.string, MAXSERVERNAME); strncpy(netbuffer->u.serverinfo.mapname, G_BuildMapName(gamemap), 7); @@ -1740,8 +1802,6 @@ static void SendAskInfo(INT32 node, boolean viams) serverelem_t serverlist[MAXSERVERLIST]; UINT32 serverlistcount = 0; -#define FORCECLOSE 0x8000 - static void SL_ClearServerList(INT32 connectedserver) { UINT32 i; @@ -1867,7 +1927,7 @@ void CL_UpdateServerList(boolean internetsearch, INT32 room) /** Called by CL_ServerConnectionTicker * * \param viams ??? - * \param asksent ??? + * \param asksent The last time we asked the server to join. We re-ask every second in case our request got lost in transmit. * \return False if the connection was aborted * \sa CL_ServerConnectionTicker * \sa CL_ConnectToServer @@ -1960,9 +2020,12 @@ static boolean CL_ServerConnectionSearchTicker(boolean viams, tic_t *asksent) ), NULL, MM_NOTHING); return false; } + + cl_mode = CL_ASKDOWNLOADFILES; + // no problem if can't send packet, we will retry later - if (CL_SendRequestFile()) - cl_mode = CL_DOWNLOADFILES; + //if (CL_SendRequestFile()) + // cl_mode = CL_DOWNLOADFILES; } } else @@ -1992,7 +2055,7 @@ static boolean CL_ServerConnectionSearchTicker(boolean viams, tic_t *asksent) * \param viams ??? * \param tmpsave The name of the gamestate file??? * \param oldtic Used for knowing when to poll events and redraw - * \param asksent ??? + * \param asksent The last time we asked the server to join. We re-ask every second in case our request got lost in transmit. * \return False if the connection was aborted * \sa CL_ServerConnectionSearchTicker * \sa CL_ConnectToServer @@ -2030,6 +2093,7 @@ static boolean CL_ServerConnectionTicker(boolean viams, const char *tmpsave, tic /* FALLTHRU */ case CL_ASKJOIN: + cl_needsdownload = false; CL_LoadServerFiles(); #ifdef JOININGAME // prepare structures to save the file @@ -2038,9 +2102,23 @@ static boolean CL_ServerConnectionTicker(boolean viams, const char *tmpsave, tic CL_PrepareDownloadSaveGame(tmpsave); #endif if (CL_SendJoin()) + { + *asksent = I_GetTime(); cl_mode = CL_WAITJOINRESPONSE; + } break; + case CL_ASKDOWNLOADFILES: + cl_needsdownload = true; + + if (CL_SendJoin()) + { + *asksent = I_GetTime(); + cl_mode = CL_WAITDOWNLOADFILESRESPONSE; + } + break; + + #ifdef JOININGAME case CL_DOWNLOADSAVEGAME: // At this state, the first (and only) needed file is the gamestate @@ -2054,7 +2132,19 @@ static boolean CL_ServerConnectionTicker(boolean viams, const char *tmpsave, tic break; #endif + case CL_CHALLENGE: + (*asksent) = I_GetTime() - NEWTICRATE; // Send password immediately upon entering + break; + case CL_WAITJOINRESPONSE: + case CL_WAITDOWNLOADFILESRESPONSE: + if (*asksent + NEWTICRATE < I_GetTime() && CL_SendJoin()) + { + *asksent = I_GetTime(); + } + + break; + case CL_CONNECTED: default: break; @@ -2072,20 +2162,10 @@ static boolean CL_ServerConnectionTicker(boolean viams, const char *tmpsave, tic // Call it only once by tic if (*oldtic != I_GetTime()) { - INT32 key; - I_OsPolling(); - key = I_GetKey(); - // Only ESC and non-keyboard keys abort connection - if (key == KEY_ESCAPE || key >= KEY_MOUSE1) - { - CONS_Printf(M_GetText("Network game synchronization aborted.\n")); -// M_StartMessage(M_GetText("Network game synchronization aborted.\n\nPress ESC\n"), NULL, MM_NOTHING); - D_QuitNetGame(); - CL_Reset(); - D_StartTitle(); + D_ProcessEvents(); + if (gamestate != GS_WAITINGPLAYERS) return false; - } // why are these here? this is for servers, we're a client //if (key == 's' && server) @@ -2114,6 +2194,71 @@ static boolean CL_ServerConnectionTicker(boolean viams, const char *tmpsave, tic return true; } +boolean CL_Responder(event_t *ev) +{ + size_t len; + INT32 ch; + + if (!(client && cl_mode != CL_CONNECTED && cl_mode != CL_ABORTED)) + return false; // Don't do anything outside of the connection screen + + if (ev->type != ev_keydown) + return false; + + ch = (INT32)ev->data1; + + // Only ESC and non-keyboard keys abort connection + if (ch == KEY_ESCAPE || ch >= KEY_MOUSE1) + { + CONS_Printf(M_GetText("Network game synchronization aborted.\n")); + //M_StartMessage(M_GetText("Network game synchronization aborted.\n\nPress ESC\n"), NULL, MM_NOTHING); + D_QuitNetGame(); + CL_Reset(); + D_StartTitle(); + return true; + } + + if (cl_mode != CL_CHALLENGE) + return false; + + if ((ch >= HU_FONTSTART && ch <= HU_FONTEND && hu_font[ch-HU_FONTSTART]) + || ch == ' ') // Allow spaces, of course + { + len = strlen(cl_challengepassword); + if (len < 64) + { + cl_challengepassword[len+1] = 0; + cl_challengepassword[len] = CON_ShiftChar(ch); + } + + cl_challengeattempted = 0; + } + else if (ch == KEY_BACKSPACE) + { + len = strlen(cl_challengepassword); + + if (len > 0) + cl_challengepassword[len-1] = 0; + + cl_challengeattempted = 0; + } + else if (ch == KEY_ENTER) + { + netgame = true; + multiplayer = true; + +#ifndef NONET + SL_ClearServerList(servernode); +#endif + cl_mode = CL_SEARCHING; + + D_ComputeChallengeAnswer(cl_challengequestion, cl_challengepassword, cl_challengeanswer); + cl_challengeattempted = 1; + } + + return true; +} + /** Use adaptive send using net_bandwidth and stat.sendbytes * * \param viams ??? @@ -2134,6 +2279,7 @@ static void CL_ConnectToServer(boolean viams) #endif cl_mode = CL_SEARCHING; + cl_challengenum = 0; #ifdef CLIENT_LOADINGSCREEN lastfilenum = -1; @@ -2191,6 +2337,8 @@ static void CL_ConnectToServer(boolean viams) SL_ClearServerList(servernode); #endif + cl_challengeattempted = 0; + do { // If the connection was aborted for some reason, leave @@ -2729,7 +2877,10 @@ static void Command_Ban(void) else { if (server) // only the server is allowed to do this right now + { Ban_Add(COM_Argv(2)); + D_SaveBan(); // save the ban list + } if (COM_Argc() == 2) { @@ -2760,6 +2911,42 @@ static void Command_Ban(void) } +static void Command_BanIP(void) +{ + if (COM_Argc() < 2) + { + CONS_Printf(M_GetText("banip : ban an ip address\n")); + return; + } + + if (server) // Only the server can use this, otherwise does nothing. + { + const char *address = (COM_Argv(1)); + const char *reason; + + if (COM_Argc() == 2) + reason = NULL; + else + reason = COM_Argv(2); + + + if (I_SetBanAddress && I_SetBanAddress(address, NULL)) + { + if (reason) + CONS_Printf("Banned IP address %s for: %s\n", address, reason); + else + CONS_Printf("Banned IP address %s\n", address); + + Ban_Add(reason); + D_SaveBan(); + } + else + { + return; + } + } +} + static void Command_Kick(void) { if (COM_Argc() < 2) @@ -3066,6 +3253,7 @@ void D_ClientServerInit(void) COM_AddCommand("getplayernum", Command_GetPlayerNum); COM_AddCommand("kick", Command_Kick); COM_AddCommand("ban", Command_Ban); + COM_AddCommand("banip", Command_BanIP); COM_AddCommand("clearbans", Command_ClearBans); COM_AddCommand("showbanlist", Command_ShowBan); COM_AddCommand("reloadbans", Command_ReloadBan); @@ -3099,6 +3287,9 @@ void D_ClientServerInit(void) gametic = 0; localgametic = 0; + memset(cl_challengequestion, 0x00, MD5_LEN+1); + memset(cl_challengeanswer, 0x00, MD5_LEN+1); + // do not send anything before the real begin SV_StopServer(); SV_ResetServer(); @@ -3320,6 +3511,8 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum) addedtogame = true; } + players[newplayernum].splitscreenindex = splitscreenplayer; + if (netgame) { if (server && cv_showjoinaddress.value) @@ -3586,6 +3779,33 @@ static void HandleConnect(SINT8 node) boolean newnode = false; #endif + if (node != servernode && !nodeingame[node] && D_IsJoinPasswordOn()) + { + // Ensure node sent the correct password challenge + boolean passed = false; + + if (netbuffer->u.clientcfg.challengenum && D_VerifyJoinPasswordChallenge(netbuffer->u.clientcfg.challengenum, netbuffer->u.clientcfg.challengeanswer)) + passed = true; + + if (!passed) + { + D_MakeJoinPasswordChallenge(&netbuffer->u.joinchallenge.challengenum, netbuffer->u.joinchallenge.question); + + netbuffer->packettype = PT_JOINCHALLENGE; + HSendPacket(node, true, 0, sizeof(joinchallenge_pak)); + Net_CloseConnection(node); + + return; + } + } + + if (netbuffer->u.clientcfg.needsdownload) + { + netbuffer->packettype = PT_DOWNLOADFILESOKAY; + HSendPacket(node, true, 0, 0); + return; + } + // client authorised to join nodewaiting[node] = (UINT8)(netbuffer->u.clientcfg.localplayers - playerpernode[node]); if (!nodeingame[node]) @@ -3594,6 +3814,7 @@ static void HandleConnect(SINT8 node) #ifndef NONET newnode = true; #endif + SV_AddNode(node); /// \note Wait what??? @@ -3749,6 +3970,43 @@ static void HandlePacketFromAwayNode(SINT8 node) Net_CloseConnection(node); break; + case PT_JOINCHALLENGE: + if (server && serverrunning) + { // But wait I thought I'm the server? + Net_CloseConnection(node); + break; + } + SERVERONLY + if (cl_mode == CL_WAITJOINRESPONSE || cl_mode == CL_WAITDOWNLOADFILESRESPONSE) + { + cl_challengenum = netbuffer->u.joinchallenge.challengenum; + memcpy(cl_challengequestion, netbuffer->u.joinchallenge.question, 16); + + Net_CloseConnection(node|FORCECLOSE); // Don't need to stay connected while challenging + + cl_mode = CL_CHALLENGE; + + switch (cl_challengeattempted) + { + case 2: + // We already sent a correct password, so throw it back up again. + D_ComputeChallengeAnswer(cl_challengequestion, cl_challengepassword, cl_challengeanswer); + cl_mode = CL_ASKJOIN; + break; + + case 1: + // We entered the wrong password! + S_StartSound(NULL, sfx_s26d); + break; + + default: + // First entry to the password screen. + S_StartSound(NULL, sfx_s224); + break; + } + } + break; + case PT_SERVERREFUSE: // Negative response of client join request if (server && serverrunning) { // But wait I thought I'm the server? @@ -3777,6 +4035,41 @@ static void HandlePacketFromAwayNode(SINT8 node) } break; + case PT_DOWNLOADFILESOKAY: + if (server && serverrunning) + { // But wait I thought I'm the server? + Net_CloseConnection(node); + break; + } + + SERVERONLY + + // This should've already been checked, but just to be safe... + if (!CL_CheckDownloadable()) + { + D_QuitNetGame(); + CL_Reset(); + D_StartTitle(); + M_StartMessage(M_GetText( + "You cannot connect to this server\n" + "because you cannot download the files\n" + "that you are missing from the server.\n\n" + "See the console or log file for\n" + "more details.\n\n" + "Press ESC\n" + ), NULL, MM_NOTHING); + break; + } + + if (cl_challengeattempted == 1) // Successful password noise. + S_StartSound(NULL, sfx_s221); + + cl_challengeattempted = 2; + CONS_Printf("trying to download\n"); + if (CL_SendRequestFile()) + cl_mode = CL_DOWNLOADFILES; + break; + case PT_SERVERCFG: // Positive response of client join request { INT32 j; @@ -3792,6 +4085,9 @@ static void HandlePacketFromAwayNode(SINT8 node) if (cl_mode != CL_WAITJOINRESPONSE) break; + if (cl_challengeattempted == 1) // Successful password noise. + S_StartSound(NULL, sfx_s221); + if (client) { maketic = gametic = neededtic = (tic_t)LONG(netbuffer->u.servercfg.gametic); @@ -4357,10 +4653,12 @@ FILESTAMP //Update client ping table from the server. if (client) { - INT32 i; + UINT8 i; for (i = 0; i < MAXPLAYERS; i++) if (playeringame[i]) playerpingtable[i] = (tic_t)netbuffer->u.pingtable[i]; + + servermaxping = (tic_t)netbuffer->u.pingtable[MAXPLAYERS]; } break; @@ -5003,6 +5301,18 @@ void TryRunTics(tic_t realtics) } #ifdef NEWPING + +/* Ping Update except better: + We call this once per second and check for people's pings. If their ping happens to be too high, we increment some timer and kick them out. + If they're not lagging, decrement the timer by 1. Of course, reset all of this if they leave. + + Why do we do that? Well, I'm a person with unfortunately sometimes unstable internet and happen to keep getting kicked very unconveniently for very short high spikes. (700+ ms) + Because my spikes are so high, the average ping is exponentially higher too (700s really add up...!) which leads me to getting kicked for a short burst of spiking. + With this change here, this doesn't happen anymore as it checks if my ping has been CONSISTENTLY bad for long enough before killing me. +*/ + +static INT32 pingtimeout[MAXPLAYERS]; + static inline void PingUpdate(void) { INT32 i; @@ -5023,6 +5333,9 @@ static inline void PingUpdate(void) laggers[i] = true; numlaggers++; } + else + pingtimeout[i] = 0; + } //kick lagging players... unless everyone but the server's ping sucks. @@ -5033,12 +5346,20 @@ static inline void PingUpdate(void) { if (playeringame[i] && laggers[i]) { - XBOXSTATIC char buf[2]; + pingtimeout[i]++; + if (pingtimeout[i] > cv_pingtimeout.value) // ok your net has been bad for too long, you deserve to die. + { + XBOXSTATIC char buf[2]; - buf[0] = (char)i; - buf[1] = KICK_MSG_PING_HIGH; - SendNetXCmd(XD_KICK, &buf, 2); + pingtimeout[i] = 0; + + buf[0] = (char)i; + buf[1] = KICK_MSG_PING_HIGH; + SendNetXCmd(XD_KICK, &buf, 2); + } } + else // you aren't lagging, but you aren't free yet. In case you'll keep spiking, we just make the timer go back down. (Very unstable net must still get kicked). + pingtimeout[i] = (pingtimeout[i] == 0 ? 0 : pingtimeout[i]-1); } } } @@ -5053,10 +5374,13 @@ static inline void PingUpdate(void) realpingtable[i] = 0; //Reset each as we go. } + // send the server's maxping as last element of our ping table. This is useful to let us know when we're about to get kicked. + netbuffer->u.pingtable[MAXPLAYERS] = cv_maxping.value; + //send out our ping packets for (i = 0; i < MAXNETNODES; i++) if (nodeingame[i]) - HSendPacket(i, true, 0, sizeof(INT32) * MAXPLAYERS); + HSendPacket(i, true, 0, sizeof(INT32) * (MAXPLAYERS+1)); pingmeasurecount = 1; //Reset count } @@ -5070,7 +5394,7 @@ static void UpdatePingTable(void) INT32 i; if (server) { - if (netgame && !(gametime % 255)) + if (netgame && !(gametime % 35)) // update once per second. PingUpdate(); // update node latency values so we can take an average later. for (i = 0; i < MAXPLAYERS; i++) diff --git a/src/d_clisrv.h b/src/d_clisrv.h index 44ead8f4..f195fcc9 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -13,11 +13,14 @@ #ifndef __D_CLISRV__ #define __D_CLISRV__ +#include "d_event.h" #include "d_ticcmd.h" #include "d_netcmd.h" #include "tables.h" #include "d_player.h" +#include "md5.h" + // Network play related stuff. // There is a data struct that stores network // communication related stuff, and another @@ -73,6 +76,9 @@ typedef enum PT_CLIENT4MIS, PT_BASICKEEPALIVE,// Keep the network alive during wipes, as tics aren't advanced and NetUpdate isn't called + PT_JOINCHALLENGE, // You must give a password to joinnnnn + PT_DOWNLOADFILESOKAY, // You can download files from the server.... + PT_CANFAIL, // This is kind of a priority. Anything bigger than CANFAIL // allows HSendPacket(*, true, *, *) to return false. // In addition, this packet can't occupy all the available slots. @@ -283,6 +289,8 @@ typedef struct tic_t jointime; + UINT8 splitscreenindex; + //player->mo stuff UINT8 hasmo; // Boolean @@ -351,9 +359,21 @@ typedef struct UINT8 version; // Different versions don't work UINT8 subversion; // Contains build version UINT8 localplayers; - UINT8 mode; + UINT8 needsdownload; + UINT8 challengenum; // Non-zero if trying to join with a password attempt + UINT8 challengeanswer[MD5_LEN]; // Join challenge } ATTRPACK clientconfig_pak; +typedef struct +{ + UINT8 challengenum; // Number to send back in join attempt + UINT8 question[MD5_LEN]; // Challenge data to be manipulated and answered with +} ATTRPACK joinchallenge_pak; + +#define SV_SPEEDMASK 0x03 +#define SV_DEDICATED 0x40 +#define SV_PASSWORD 0x80 + #define MAXSERVERNAME 32 #define MAXFILENEEDED 915 // This packet is too large @@ -366,7 +386,7 @@ typedef struct UINT8 gametype; UINT8 modifiedgame; UINT8 cheatsenabled; - UINT8 isdedicated; + UINT8 kartvars; // Previously isdedicated, now appropriated for our own nefarious purposes UINT8 fileneedednum; SINT8 adminplayer; tic_t time; @@ -445,15 +465,16 @@ typedef struct UINT8 resynchgot; // UINT8 textcmd[MAXTEXTCMD+1]; // 66049 bytes (wut??? 64k??? More like 257 bytes...) filetx_pak filetxpak; // 139 bytes - clientconfig_pak clientcfg; // 136 bytes + clientconfig_pak clientcfg; // 153 bytes + joinchallenge_pak joinchallenge; // 17 bytes serverinfo_pak serverinfo; // 1024 bytes serverrefuse_pak serverrefuse; // 65025 bytes (somehow I feel like those values are garbage...) askinfo_pak askinfo; // 61 bytes msaskinfo_pak msaskinfo; // 22 bytes - plrinfo playerinfo[MAXPLAYERS]; // 1152 bytes (I'd say 36~38) - plrconfig playerconfig[MAXPLAYERS]; // (up to) 896 bytes (welp they ARE) + plrinfo playerinfo[MAXPLAYERS]; // 576 bytes(?) + plrconfig playerconfig[MAXPLAYERS]; // (up to) 528 bytes(?) #ifdef NEWPING - UINT32 pingtable[MAXPLAYERS]; // 128 bytes + UINT32 pingtable[MAXPLAYERS+1]; // 68 bytes #endif } u; // This is needed to pack diff packet types data together } ATTRPACK doomdata_t; @@ -519,6 +540,7 @@ extern tic_t jointimeout; extern UINT16 pingmeasurecount; extern UINT32 realpingtable[MAXPLAYERS]; extern UINT32 playerpingtable[MAXPLAYERS]; +extern tic_t servermaxping; #endif extern consvar_t @@ -553,6 +575,7 @@ void CL_Reset(void); void CL_ClearPlayer(INT32 playernum); void CL_RemovePlayer(INT32 playernum, INT32 reason); void CL_UpdateServerList(boolean internetsearch, INT32 room); +boolean CL_Responder(event_t *ev); // Is there a game running boolean Playing(void); diff --git a/src/d_main.c b/src/d_main.c index 28f89f4f..84d5a6f3 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -111,6 +111,7 @@ UINT8 window_notinfocus = false; //static INT32 demosequence; static const char *pagename = "MAP1PIC"; static char *startupwadfiles[MAX_WADFILES]; +static char *startuppwads[MAX_WADFILES]; boolean devparm = false; // started game with -devparm @@ -203,6 +204,8 @@ static inline void D_ModifierKeyResponder(event_t *ev) case KEY_RCTRL: ctrldown |= 0x2; return; case KEY_LALT: altdown |= 0x1; return; case KEY_RALT: altdown |= 0x2; return; + case KEY_CAPSLOCK: capslock = !capslock; return; + default: return; } else if (ev->type == ev_keyup) switch (ev->data1) @@ -236,6 +239,9 @@ void D_ProcessEvents(void) if (M_ScreenshotResponder(ev)) continue; // ate the event + if (CL_Responder(ev)) + continue; + if (gameaction == ga_nothing && gamestate == GS_TITLESCREEN) { if (cht_Responder(ev)) @@ -824,12 +830,12 @@ void D_StartTitle(void) // // D_AddFile // -static void D_AddFile(const char *file) +static void D_AddFile(const char *file, char **filearray) { size_t pnumwadfiles; char *newfile; - for (pnumwadfiles = 0; startupwadfiles[pnumwadfiles]; pnumwadfiles++) + for (pnumwadfiles = 0; filearray[pnumwadfiles]; pnumwadfiles++) ; newfile = malloc(strlen(file) + 1); @@ -839,16 +845,16 @@ static void D_AddFile(const char *file) } strcpy(newfile, file); - startupwadfiles[pnumwadfiles] = newfile; + filearray[pnumwadfiles] = newfile; } -static inline void D_CleanFile(void) +static inline void D_CleanFile(char **filearray) { size_t pnumwadfiles; - for (pnumwadfiles = 0; startupwadfiles[pnumwadfiles]; pnumwadfiles++) + for (pnumwadfiles = 0; filearray[pnumwadfiles]; pnumwadfiles++) { - free(startupwadfiles[pnumwadfiles]); - startupwadfiles[pnumwadfiles] = NULL; + free(filearray[pnumwadfiles]); + filearray[pnumwadfiles] = NULL; } } @@ -908,9 +914,9 @@ static void IdentifyVersion(void) // Load the IWAD if (srb2wad2 != NULL && FIL_ReadFileOK(srb2wad2)) - D_AddFile(srb2wad2); + D_AddFile(srb2wad2, startupwadfiles); else if (srb2wad1 != NULL && FIL_ReadFileOK(srb2wad1)) - D_AddFile(srb2wad1); + D_AddFile(srb2wad1, startupwadfiles); else I_Error("SRB2.SRB/SRB2.WAD not found! Expected in %s, ss files: %s or %s\n", srb2waddir, srb2wad1, srb2wad2); @@ -927,12 +933,12 @@ static void IdentifyVersion(void) D_AddFile(va(pandf,srb2waddir,"patch.dta")); #endif - D_AddFile(va(pandf,srb2waddir,"gfx.kart")); - D_AddFile(va(pandf,srb2waddir,"textures.kart")); - D_AddFile(va(pandf,srb2waddir,"chars.kart")); - D_AddFile(va(pandf,srb2waddir,"maps.kart")); + D_AddFile(va(pandf,srb2waddir,"gfx.kart"), startupwadfiles); + D_AddFile(va(pandf,srb2waddir,"textures.kart"), startupwadfiles); + D_AddFile(va(pandf,srb2waddir,"chars.kart"), startupwadfiles); + D_AddFile(va(pandf,srb2waddir,"maps.kart"), startupwadfiles); #ifdef USE_PATCH_KART - D_AddFile(va(pandf,srb2waddir,"patch.kart")); + D_AddFile(va(pandf,srb2waddir,"patch.kart"), startupwadfiles); #endif #if !defined (HAVE_SDL) || defined (HAVE_MIXER) @@ -941,7 +947,7 @@ static void IdentifyVersion(void) const char *musicpath = va(pandf,srb2waddir,str);\ int ms = W_VerifyNMUSlumps(musicpath); \ if (ms == 1) \ - D_AddFile(musicpath); \ + D_AddFile(musicpath, startupwadfiles); \ else if (ms == 0) \ I_Error("File "str" has been modified with non-music/sound lumps"); \ } @@ -1006,9 +1012,12 @@ static inline void D_MakeTitleString(char *s) // void D_SRB2Main(void) { - INT32 p; + INT32 p, i; char srb2[82]; // srb2 title banner char title[82]; + lumpinfo_t *lumpinfo; + UINT16 wadnum; + char *name; INT32 pstartmap = 1; boolean autostart = false; @@ -1160,11 +1169,7 @@ void D_SRB2Main(void) const char *s = M_GetNextParm(); if (s) // Check for NULL? - { - if (!W_VerifyNMUSlumps(s)) - G_SetGameModified(true, false); - D_AddFile(s); - } + D_AddFile(s, startuppwads); } } } @@ -1214,13 +1219,13 @@ void D_SRB2Main(void) // load wad, including the main wad file CONS_Printf("W_InitMultipleFiles(): Adding IWAD and main PWADs.\n"); - if (!W_InitMultipleFiles(startupwadfiles)) + if (!W_InitMultipleFiles(startupwadfiles, false)) #ifdef _DEBUG CONS_Error("A WAD file was not found or not valid.\nCheck the log to see which ones.\n"); #else I_Error("A WAD file was not found or not valid.\nCheck the log to see which ones.\n"); #endif - D_CleanFile(); + D_CleanFile(startupwadfiles); mainwads = 0; @@ -1234,7 +1239,7 @@ void D_SRB2Main(void) mainwads++; W_VerifyFileMD5(mainwads, ASSET_HASH_GFX_KART); // gfx.kart mainwads++; W_VerifyFileMD5(mainwads, ASSET_HASH_TEXTURES_KART); // textures.kart mainwads++; W_VerifyFileMD5(mainwads, ASSET_HASH_CHARS_KART); // chars.kart - mainwads++; W_VerifyFileMD5(mainwads, ASSET_HASH_MAPS_KART); // maps.kart + mainwads++; W_VerifyFileMD5(mainwads, ASSET_HASH_MAPS_KART); // maps.kart -- 4 - If you touch this, make sure to touch up the majormods stuff below. #ifdef USE_PATCH_KART mainwads++; W_VerifyFileMD5(mainwads, ASSET_HASH_PATCH_KART); // patch.kart #endif @@ -1254,6 +1259,66 @@ void D_SRB2Main(void) mainwadstally = packetsizetally; + // + // search for maps + // + for (wadnum = 4; wadnum < 6; wadnum++) // fucking arbitrary numbers + { + lumpinfo = wadfiles[wadnum]->lumpinfo; + for (i = 0; i < wadfiles[wadnum]->numlumps; i++, lumpinfo++) + { + name = lumpinfo->name; + + if (name[0] == 'M' && name[1] == 'A' && name[2] == 'P') // Ignore the headers + { + INT16 num; + if (name[5] != '\0') + continue; + num = (INT16)M_MapNumber(name[3], name[4]); + + // we want to record whether this map exists. if it doesn't have a header, we can assume it's not relephant + if (num <= NUMMAPS && mapheaderinfo[num - 1]) + { + mapheaderinfo[num - 1]->menuflags |= LF2_EXISTSHACK; + } + } + } + } + + if (!W_InitMultipleFiles(startuppwads, true)) + CONS_Error("A PWAD file was not found or not valid.\nCheck the log to see which ones.\n"); + D_CleanFile(startuppwads); + + // + // search for maps... again. + // + for (wadnum = mainwads+1; wadnum < numwadfiles; wadnum++) + { + lumpinfo = wadfiles[wadnum]->lumpinfo; + for (i = 0; i < wadfiles[wadnum]->numlumps; i++, lumpinfo++) + { + name = lumpinfo->name; + + if (name[0] == 'M' && name[1] == 'A' && name[2] == 'P') // Ignore the headers + { + INT16 num; + if (name[5] != '\0') + continue; + num = (INT16)M_MapNumber(name[3], name[4]); + + // we want to record whether this map exists. if it doesn't have a header, we can assume it's not relephant + if (num <= NUMMAPS && mapheaderinfo[num - 1]) + { + if (mapheaderinfo[num - 1]->menuflags & LF2_EXISTSHACK) + G_SetGameModified(multiplayer, true); // oops, double-defined - no record attack privileges for you + mapheaderinfo[num - 1]->menuflags |= LF2_EXISTSHACK; + } + + CONS_Printf("%s\n", name); + } + } + } + cht_Init(); //---------------------------------------------------- READY SCREEN diff --git a/src/d_net.c b/src/d_net.c index 6702a60a..9f719967 100644 --- a/src/d_net.c +++ b/src/d_net.c @@ -821,10 +821,6 @@ static const char *packettypename[NUMPACKETTYPE] = "CLIENTMIS", "CLIENT2CMD", "CLIENT2MIS", - "CLIENT3CMD", - "CLIENT3MIS", - "CLIENT4CMD", - "CLIENT4MIS", "NODEKEEPALIVE", "NODEKEEPALIVEMIS", "SERVERTICS", @@ -841,6 +837,15 @@ static const char *packettypename[NUMPACKETTYPE] = "RESYNCHEND", "RESYNCHGET", + "CLIENT3CMD", + "CLIENT3MIS", + "CLIENT4CMD", + "CLIENT4MIS", + "BASICKEEPALIVE", + + "JOINCHALLENGE", + "DOWNLOADFILESOKAY", + "FILEFRAGMENT", "TEXTCMD", "TEXTCMD2", @@ -868,7 +873,7 @@ static void DebugPrintpacket(const char *header) break; case PT_CLIENTJOIN: fprintf(debugfile, " number %d mode %d\n", netbuffer->u.clientcfg.localplayers, - netbuffer->u.clientcfg.mode); + netbuffer->u.clientcfg.needsdownload); break; case PT_SERVERTICS: { diff --git a/src/d_net.h b/src/d_net.h index 9cc1bbd2..8e518e40 100644 --- a/src/d_net.h +++ b/src/d_net.h @@ -19,7 +19,7 @@ #define __D_NET__ // Max computers in a game -#define MAXNETNODES 16 +#define MAXNETNODES (MAXPLAYERS+4) #define BROADCASTADDR MAXNETNODES #define MAXSPLITSCREENPLAYERS 4 // Max number of players on a single computer #define NETSPLITSCREEN // Kart's splitscreen netgame feature diff --git a/src/d_netcmd.c b/src/d_netcmd.c index a59d535b..0522fd71 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -172,6 +172,7 @@ static void Got_Verification(UINT8 **cp, INT32 playernum); static void Got_Removal(UINT8 **cp, INT32 playernum); static void Command_Verify_f(void); static void Command_RemoveAdmin_f(void); +static void Command_ChangeJoinPassword_f(void); static void Command_MotD_f(void); static void Got_MotD_f(UINT8 **cp, INT32 playernum); @@ -381,6 +382,7 @@ consvar_t cv_kartdebughuddrop = {"kartdebughuddrop", "Off", CV_NETVAR|CV_CHEAT|C consvar_t cv_kartdebugcheckpoint = {"kartdebugcheckpoint", "Off", CV_NOSHOWHELP, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_kartdebugnodes = {"kartdebugnodes", "Off", CV_NOSHOWHELP, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_kartdebugcolorize = {"kartdebugcolorize", "Off", CV_NOSHOWHELP, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; static CV_PossibleValue_t votetime_cons_t[] = {{10, "MIN"}, {3600, "MAX"}, {0, NULL}}; consvar_t cv_votetime = {"votetime", "20", CV_NETVAR, votetime_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -438,6 +440,14 @@ consvar_t cv_jointimeout = {"jointimeout", "105", CV_CALL|CV_SAVE, nettimeout_co #ifdef NEWPING static CV_PossibleValue_t maxping_cons_t[] = {{0, "MIN"}, {1000, "MAX"}, {0, NULL}}; consvar_t cv_maxping = {"maxping", "800", CV_SAVE, maxping_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; + +static CV_PossibleValue_t pingtimeout_cons_t[] = {{8, "MIN"}, {120, "MAX"}, {0, NULL}}; +consvar_t cv_pingtimeout = {"pingtimeout", "10", CV_SAVE, pingtimeout_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; + +// show your ping on the HUD next to framerate. Defaults to warning only (shows up if your ping is > maxping) +static CV_PossibleValue_t showping_cons_t[] = {{0, "Off"}, {1, "Always"}, {2, "Warning"}, {0, NULL}}; +consvar_t cv_showping = {"showping", "Always", CV_SAVE, showping_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; + #endif // Intermission time Tails 04-19-2002 static CV_PossibleValue_t inttime_cons_t[] = {{0, "MIN"}, {3600, "MAX"}, {0, NULL}}; @@ -528,6 +538,8 @@ void D_RegisterServerCommands(void) RegisterNetXCmd(XD_PICKVOTE, Got_PickVotecmd); // Remote Administration + CV_RegisterVar(&cv_dummyjoinpassword); + COM_AddCommand("joinpassword", Command_ChangeJoinPassword_f); COM_AddCommand("password", Command_Changepassword_f); RegisterNetXCmd(XD_LOGIN, Got_Login); COM_AddCommand("login", Command_Login_f); // useful in dedicated to kick off remote admin @@ -667,6 +679,8 @@ void D_RegisterServerCommands(void) CV_RegisterVar(&cv_sleep); #ifdef NEWPING CV_RegisterVar(&cv_maxping); + CV_RegisterVar(&cv_pingtimeout); + CV_RegisterVar(&cv_showping); #endif #ifdef SEENAMES @@ -819,6 +833,8 @@ void D_RegisterClientCommands(void) //CV_RegisterVar(&cv_alwaysfreelook2); //CV_RegisterVar(&cv_chasefreelook); //CV_RegisterVar(&cv_chasefreelook2); + CV_RegisterVar(&cv_showfocuslost); + CV_RegisterVar(&cv_pauseifunfocused); // g_input.c CV_RegisterVar(&cv_turnaxis); @@ -3634,6 +3650,7 @@ static void D_MD5PasswordPass(const UINT8 *buffer, size_t len, const char *salt, if (len > 256-sl) len = 256-sl; + memcpy(tmpbuf, buffer, len); memmove(&tmpbuf[len], salt, sl); //strcpy(&tmpbuf[len], salt); @@ -3647,7 +3664,7 @@ static void D_MD5PasswordPass(const UINT8 *buffer, size_t len, const char *salt, } #define BASESALT "basepasswordstorage" -static UINT8 adminpassmd5[16]; +static UINT8 adminpassmd5[MD5_LEN]; static boolean adminpasswordset = false; void D_SetPassword(const char *pw) @@ -3686,7 +3703,7 @@ static void Command_Login_f(void) // If we have no MD5 support then completely disable XD_LOGIN responses for security. CONS_Alert(CONS_NOTICE, "Remote administration commands are not supported in this build.\n"); #else - XBOXSTATIC UINT8 finalmd5[16]; + XBOXSTATIC UINT8 finalmd5[MD5_LEN]; const char *pw; if (!netgame) @@ -3709,11 +3726,11 @@ static void Command_Login_f(void) D_MD5PasswordPass((const UINT8 *)pw, strlen(pw), BASESALT, &finalmd5); // Do the final pass to get the comparison the server will come up with - D_MD5PasswordPass(finalmd5, 16, va("PNUM%02d", consoleplayer), &finalmd5); + D_MD5PasswordPass(finalmd5, MD5_LEN, va("PNUM%02d", consoleplayer), &finalmd5); CONS_Printf(M_GetText("Sending login... (Notice only given if password is correct.)\n")); - SendNetXCmd(XD_LOGIN, finalmd5, 16); + SendNetXCmd(XD_LOGIN, finalmd5, MD5_LEN); #endif } @@ -3724,9 +3741,9 @@ static void Got_Login(UINT8 **cp, INT32 playernum) (void)cp; (void)playernum; #else - UINT8 sentmd5[16], finalmd5[16]; + UINT8 sentmd5[MD5_LEN], finalmd5[MD5_LEN]; - READMEM(*cp, sentmd5, 16); + READMEM(*cp, sentmd5, MD5_LEN); if (client) return; @@ -3738,9 +3755,9 @@ static void Got_Login(UINT8 **cp, INT32 playernum) } // Do the final pass to compare with the sent md5 - D_MD5PasswordPass(adminpassmd5, 16, va("PNUM%02d", playernum), &finalmd5); + D_MD5PasswordPass(adminpassmd5, MD5_LEN, va("PNUM%02d", playernum), &finalmd5); - if (!memcmp(sentmd5, finalmd5, 16)) + if (!memcmp(sentmd5, finalmd5, MD5_LEN)) { CONS_Printf(M_GetText("%s passed authentication.\n"), player_names[playernum]); COM_BufInsertText(va("promote %d\n", playernum)); // do this immediately @@ -3909,6 +3926,131 @@ static void Got_Removal(UINT8 **cp, INT32 playernum) CONS_Printf(M_GetText("You are no longer a server administrator.\n")); } +// Join password stuff +consvar_t cv_dummyjoinpassword = {"dummyjoinpassword", "", CV_HIDEN|CV_NOSHOWHELP|CV_PASSWORD, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; + +#define NUMJOINCHALLENGES 32 +static UINT8 joinpassmd5[MD5_LEN+1]; +boolean joinpasswordset = false; +static UINT8 joinpasschallenges[NUMJOINCHALLENGES][MD5_LEN]; +static tic_t joinpasschallengeson[NUMJOINCHALLENGES]; + +boolean D_IsJoinPasswordOn(void) +{ + return joinpasswordset; +} + +static inline void GetChallengeAnswer(UINT8 *question, UINT8 *passwordmd5, UINT8 *answer) +{ + D_MD5PasswordPass(question, MD5_LEN, (char *) passwordmd5, answer); +} + +void D_ComputeChallengeAnswer(UINT8 *question, const char *pw, UINT8 *answer) +{ + static UINT8 passwordmd5[MD5_LEN+1]; + + memset(passwordmd5, 0x00, MD5_LEN+1); + D_MD5PasswordPass((const UINT8 *)pw, strlen(pw), BASESALT, &passwordmd5); + GetChallengeAnswer(question, passwordmd5, answer); +} + +void D_SetJoinPassword(const char *pw) +{ + memset(joinpassmd5, 0x00, MD5_LEN+1); + D_MD5PasswordPass((const UINT8 *)pw, strlen(pw), BASESALT, &joinpassmd5); + joinpasswordset = true; +} + +boolean D_VerifyJoinPasswordChallenge(UINT8 num, UINT8 *answer) +{ + boolean passed = false; + + num %= NUMJOINCHALLENGES; + + //@TODO use a constant-time memcmp.... + if (joinpasschallengeson[num] > 0 && memcmp(answer, joinpasschallenges[num], MD5_LEN) == 0) + passed = true; + + // Wipe and reset the challenge so that it can't be tried against again, as a small measure against brute-force attacks. + memset(joinpasschallenges[num], 0x00, MD5_LEN); + joinpasschallengeson[num] = 0; + + return passed; +} + +void D_MakeJoinPasswordChallenge(UINT8 *num, UINT8 *question) +{ + size_t i; + + for (i = 0; i < NUMJOINCHALLENGES; i++) + { + (*num) = M_RandomKey(NUMJOINCHALLENGES); + + if (joinpasschallengeson[(*num)] == 0) + break; + } + + if (joinpasschallengeson[(*num)] > 0) + { + // Ugh, all challenges are (probably) taken. Let's find the oldest one and overwrite it. + tic_t oldesttic = INT32_MAX; + + for (i = 0; i < NUMJOINCHALLENGES; i++) + { + if (joinpasschallengeson[i] < oldesttic) + { + (*num) = i; + oldesttic = joinpasschallengeson[i]; + } + } + } + + joinpasschallengeson[(*num)] = I_GetTime(); + + memset(question, 0x00, MD5_LEN); + for (i = 0; i < MD5_LEN; i++) + question[i] = M_RandomByte(); + + // Store the answer in memory. What was the question again? + GetChallengeAnswer(question, joinpassmd5, joinpasschallenges[(*num)]); + + // This ensures that num is always non-zero and will be valid when used for the answer + if ((*num) == 0) + (*num) = NUMJOINCHALLENGES; +} + +// Remote Administration +static void Command_ChangeJoinPassword_f(void) +{ +#ifdef NOMD5 + // If we have no MD5 support then completely disable XD_LOGIN responses for security. + CONS_Alert(CONS_NOTICE, "Remote administration commands are not supported in this build.\n"); +#else + if (client) // cannot change remotely + { + CONS_Printf(M_GetText("Only the server can use this.\n")); + return; + } + + if (COM_Argc() != 2) + { + CONS_Printf(M_GetText("joinpassword : set a password to join the server\nUse -remove to disable the password.\n")); + return; + } + + if (strcmp(COM_Argv(1), "-remove") == 0) + { + joinpasswordset = false; + CONS_Printf(M_GetText("Join password removed.\n")); + } + else + { + D_SetJoinPassword(COM_Argv(1)); + CONS_Printf(M_GetText("Join password set.\n")); + } +#endif +} + static void Command_MotD_f(void) { size_t i, j; diff --git a/src/d_netcmd.h b/src/d_netcmd.h index c590eee6..166c5e00 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -126,7 +126,7 @@ extern consvar_t cv_karteliminatelast; extern consvar_t cv_votetime; extern consvar_t cv_kartdebugitem, cv_kartdebugamount, cv_kartdebugshrink, cv_kartdebugdistribution, cv_kartdebughuddrop; -extern consvar_t cv_kartdebugcheckpoint, cv_kartdebugnodes; +extern consvar_t cv_kartdebugcheckpoint, cv_kartdebugnodes, cv_kartdebugcolorize; extern consvar_t cv_itemfinder; @@ -145,6 +145,8 @@ extern consvar_t cv_specialrings, cv_powerstones, cv_matchboxes, cv_competitionb #ifdef NEWPING extern consvar_t cv_maxping; +extern consvar_t cv_pingtimeout; +extern consvar_t cv_showping; #endif extern consvar_t cv_skipmapcheck; @@ -246,6 +248,14 @@ void RemoveAdminPlayer(INT32 playernum); void ItemFinder_OnChange(void); void D_SetPassword(const char *pw); +extern consvar_t cv_dummyjoinpassword; +extern boolean joinpasswordset; +boolean D_IsJoinPasswordOn(void); +void D_ComputeChallengeAnswer(UINT8 *question, const char *pw, UINT8 *answer); +void D_SetJoinPassword(const char *pw); +boolean D_VerifyJoinPasswordChallenge(UINT8 num, UINT8 *answer); +void D_MakeJoinPasswordChallenge(UINT8 *num, UINT8 *question); + // used for the player setup menu UINT8 CanChangeSkin(INT32 playernum); diff --git a/src/d_player.h b/src/d_player.h index b430f20a..decd9655 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -32,13 +32,7 @@ // Extra abilities/settings for skins (combinable stuff) typedef enum { - SF_SUPER = 1, // Can turn super in singleplayer/co-op mode. - SF_SUPERANIMS = 1<<1, // If super, use the super sonic animations - SF_SUPERSPIN = 1<<2, // Should spin frames be played while super? - SF_HIRES = 1<<3, // Draw the sprite 2x as small? - SF_NOSKID = 1<<4, // No skid particles etc - SF_NOSPEEDADJUST = 1<<5, // Skin-specific version of disablespeedadjust - SF_RUNONWATER = 1<<6, // Run on top of water FOFs? + SF_HIRES = 1, // Draw the sprite 2x as small? } skinflags_t; //Primary and secondary skin abilities @@ -275,6 +269,7 @@ typedef enum k_nextcheck, // Next checkpoint distance; for p_user.c (was "pw_ncd") k_waypoint, // Waypoints. k_starpostwp, // Temporarily stores player waypoint for... some reason. Used when respawning and finishing. + k_starpostflip, // the last starpost we hit requires flipping? k_respawn, // Timer for the DEZ laser respawn effect k_dropdash, // Charge up for respawn Drop Dash @@ -354,6 +349,7 @@ typedef enum k_getsparks, // Disable drift sparks at low speed, JUST enough to give acceleration the actual headstart above speed k_jawztargetdelay, // Delay for Jawz target switching, to make it less twitchy k_spectatewait, // How long have you been waiting as a spectator + k_growcancel, // Hold the item button down to cancel Grow NUMKARTSTUFF } kartstufftype_t; @@ -571,6 +567,8 @@ typedef struct player_s UINT8 bot; tic_t jointime; // Timer when player joins game to change skin/color + + UINT8 splitscreenindex; #ifdef HWRENDER fixed_t fovadd; // adjust FOV for hw rendering #endif diff --git a/src/dehacked.c b/src/dehacked.c index 9e229f7e..4f41ac0c 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -3103,11 +3103,6 @@ static void readmaincfg(MYFILE *f) if (creditscutscene > 128) creditscutscene = 128; } - else if (fastcmp(word, "DISABLESPEEDADJUST")) - { - DEH_WriteUndoline(word, va("%d", disableSpeedAdjust), UNDO_NONE); - disableSpeedAdjust = (value || word2[0] == 'T' || word2[0] == 'Y'); - } else if (fastcmp(word, "NUMDEMOS")) { DEH_WriteUndoline(word, va("%d", numDemos), UNDO_NONE); @@ -7150,6 +7145,13 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_KARMAFIREWORK4", "S_KARMAFIREWORKTRAIL", + // Opaque smoke version, to prevent lag + "S_OPAQUESMOKE1", + "S_OPAQUESMOKE2", + "S_OPAQUESMOKE3", + "S_OPAQUESMOKE4", + "S_OPAQUESMOKE5", + #ifdef SEENAMES "S_NAMECHECK", #endif @@ -8134,89 +8136,164 @@ static const char *const ML_LIST[16] = { // This DOES differ from r_draw's Color_Names, unfortunately. // Also includes Super colors static const char *COLOR_ENUMS[] = { // Rejigged for Kart. - "NONE", // 00 // SKINCOLOR_NONE - "WHITE", // 01 // SKINCOLOR_WHITE - "SILVER", // 02 // SKINCOLOR_SILVER - "GREY", // 03 // SKINCOLOR_GREY - "NICKEL", // 04 // SKINCOLOR_NICKEL - "BLACK", // 05 // SKINCOLOR_BLACK - "SEPIA", // 06 // SKINCOLOR_SEPIA - "BEIGE", // 07 // SKINCOLOR_BEIGE - "BROWN", // 08 // SKINCOLOR_BROWN - "LEATHER", // 09 // SKINCOLOR_LEATHER - "SALMON", // 10 // SKINCOLOR_SALMON - "PINK", // 11 // SKINCOLOR_PINK - "ROSE", // 12 // SKINCOLOR_ROSE - "RUBY", // 13 // SKINCOLOR_RUBY - "RASPBERRY", // 14 // SKINCOLOR_RASPBERRY - "RED", // 15 // SKINCOLOR_RED - "CRIMSON", // 16 // SKINCOLOR_CRIMSON - "KETCHUP", // 17 // SKINCOLOR_KETCHUP - "DAWN", // 18 // SKINCOLOR_DAWN - "CREAMSICLE", // 19 // SKINCOLOR_CREAMSICLE - "ORANGE", // 20 // SKINCOLOR_ORANGE - "PUMPKIN", // 21 // SKINCOLOR_PUMPKIN - "ROSEWOOD", // 22 // SKINCOLOR_ROSEWOOD - "BURGUNDY", // 23 // SKINCOLOR_BURGUNDY - "TANGERINE", // 24 // SKINCOLOR_TANGERINE - "PEACH", // 25 // SKINCOLOR_PEACH - "CARAMEL", // 26 // SKINCOLOR_CARAMEL - "GOLD", // 27 // SKINCOLOR_GOLD - "BRONZE", // 28 // SKINCOLOR_BRONZE - "YELLOW", // 29 // SKINCOLOR_YELLOW - "MUSTARD", // 30 // SKINCOLOR_MUSTARD - "OLIVE", // 31 // SKINCOLOR_OLIVE - "VOMIT", // 32 // SKINCOLOR_VOMIT - "GARDEN", // 33 // SKINCOLOR_GARDEN - "LIME", // 34 // SKINCOLOR_LIME - "TEA", // 35 // SKINCOLOR_TEA - "PISTACHIO", // 36 // SKINCOLOR_PISTACHIO - "ROBOHOOD", // 37 // SKINCOLOR_ROBOHOOD - "MOSS", // 38 // SKINCOLOR_MOSS - "MINT", // 39 // SKINCOLOR_MINT - "GREEN", // 40 // SKINCOLOR_GREEN - "PINETREE", // 41 // SKINCOLOR_PINETREE - "EMERALD", // 42 // SKINCOLOR_EMERALD - "SWAMP", // 43 // SKINCOLOR_SWAMP - "DREAM", // 44 // SKINCOLOR_DREAM - "AQUA", // 45 // SKINCOLOR_AQUA - "TEAL", // 46 // SKINCOLOR_TEAL - "CYAN", // 47 // SKINCOLOR_CYAN - "JAWZ", // 48 // SKINCOLOR_JAWZ - "CERULEAN", // 49 // SKINCOLOR_CERULEAN - "NAVY", // 50 // SKINCOLOR_NAVY - "SLATE", // 51 // SKINCOLOR_SLATE - "STEEL", // 52 // SKINCOLOR_STEEL - "JET", // 53 // SKINCOLOR_JET - "SAPPHIRE", // 54 // SKINCOLOR_SAPPHIRE - "PERIWINKLE", // 55 // SKINCOLOR_PERIWINKLE - "BLUE", // 56 // SKINCOLOR_BLUE - "BLUEBERRY", // 57 // SKINCOLOR_BLUEBERRY - "DUSK", // 58 // SKINCOLOR_DUSK - "PURPLE", // 59 // SKINCOLOR_PURPLE - "LAVENDER", // 60 // SKINCOLOR_LAVENDER - "BYZANTIUM", // 61 // SKINCOLOR_BYZANTIUM - "POMEGRANATE", // 62 // SKINCOLOR_POMEGRANATE - "LILAC", // 63 // SKINCOLOR_LILAC + "NONE", // SKINCOLOR_NONE + "WHITE", // SKINCOLOR_WHITE + "SILVER", // SKINCOLOR_SILVER + "GREY", // SKINCOLOR_GREY + "NICKEL", // SKINCOLOR_NICKEL + "BLACK", // SKINCOLOR_BLACK + "FAIRY", // SKINCOLOR_FAIRY + "POPCORN", // SKINCOLOR_POPCORN + "SEPIA", // SKINCOLOR_SEPIA + "BEIGE", // SKINCOLOR_BEIGE + "BROWN", // SKINCOLOR_BROWN + "LEATHER", // SKINCOLOR_LEATHER + "SALMON", // SKINCOLOR_SALMON + "PINK", // SKINCOLOR_PINK + "ROSE", // SKINCOLOR_ROSE + "BRICK", // SKINCOLOR_BRICK + "RUBY", // SKINCOLOR_RUBY + "RASPBERRY", // SKINCOLOR_RASPBERRY + "CHERRY", // SKINCOLOR_CHERRY + "RED", // SKINCOLOR_RED + "CRIMSON", // SKINCOLOR_CRIMSON + "MAROON", // SKINCOLOR_MAROON + "FLAME", // SKINCOLOR_FLAME + "SCARLET", // SKINCOLOR_SCARLET + "KETCHUP", // SKINCOLOR_KETCHUP + "DAWN", // SKINCOLOR_DAWN + "SUNSET", // SKINCOLOR_SUNSET + "CREAMSICLE", // SKINCOLOR_CREAMSICLE + "ORANGE", // SKINCOLOR_ORANGE + "PUMPKIN", // SKINCOLOR_PUMPKIN + "ROSEWOOD", // SKINCOLOR_ROSEWOOD + "BURGUNDY", // SKINCOLOR_BURGUNDY + "TANGERINE", // SKINCOLOR_TANGERINE + "PEACH", // SKINCOLOR_PEACH + "CARAMEL", // SKINCOLOR_CARAMEL + "CREAM", // SKINCOLOR_CREAM + "GOLD", // SKINCOLOR_GOLD + "ROYAL", // SKINCOLOR_ROYAL + "BRONZE", // SKINCOLOR_BRONZE + "COPPER", // SKINCOLOR_COPPER + "YELLOW", // SKINCOLOR_YELLOW + "MUSTARD", // SKINCOLOR_MUSTARD + "OLIVE", // SKINCOLOR_OLIVE + "VOMIT", // SKINCOLOR_VOMIT + "GARDEN", // SKINCOLOR_GARDEN + "LIME", // SKINCOLOR_LIME + "HANDHELD", // SKINCOLOR_HANDHELD + "TEA", // SKINCOLOR_TEA + "PISTACHIO", // SKINCOLOR_PISTACHIO + "MOSS", // SKINCOLOR_MOSS + "CAMOUFLAGE", // SKINCOLOR_CAMOUFLAGE + "ROBOHOOD", // SKINCOLOR_ROBOHOOD + "MINT", // SKINCOLOR_MINT + "GREEN", // SKINCOLOR_GREEN + "PINETREE", // SKINCOLOR_PINETREE + "EMERALD", // SKINCOLOR_EMERALD + "SWAMP", // SKINCOLOR_SWAMP + "DREAM", // SKINCOLOR_DREAM + "PLAGUE", // SKINCOLOR_PLAGUE + "ALGAE", // SKINCOLOR_ALGAE + "CARIBBEAN", // SKINCOLOR_CARIBBEAN + "AQUA", // SKINCOLOR_AQUA + "TEAL", // SKINCOLOR_TEAL + "CYAN", // SKINCOLOR_CYAN + "JAWZ", // SKINCOLOR_JAWZ + "CERULEAN", // SKINCOLOR_CERULEAN + "NAVY", // SKINCOLOR_NAVY + "PLATINUM", // SKINCOLOR_PLATINUM + "SLATE", // SKINCOLOR_SLATE + "STEEL", // SKINCOLOR_STEEL + "RUST", // SKINCOLOR_RUST + "JET", // SKINCOLOR_JET + "SAPPHIRE", // SKINCOLOR_SAPPHIRE + "PERIWINKLE", // SKINCOLOR_PERIWINKLE + "BLUE", // SKINCOLOR_BLUE + "BLUEBERRY", // SKINCOLOR_BLUEBERRY + "NOVA", // SKINCOLOR_NOVA + "PASTEL", // SKINCOLOR_PASTEL + "MOONSLAM", // SKINCOLOR_MOONSLAM + "ULTRAVIOLET", // SKINCOLOR_ULTRAVIOLET + "DUSK", // SKINCOLOR_DUSK + "BUBBLEGUM", // SKINCOLOR_BUBBLEGUM + "PURPLE", // SKINCOLOR_PURPLE + "FUCHSIA", // SKINCOLOR_FUCHSIA + "TOXIC", // SKINCOLOR_TOXIC + "MAUVE", // SKINCOLOR_MAUVE + "LAVENDER", // SKINCOLOR_LAVENDER + "BYZANTIUM", // SKINCOLOR_BYZANTIUM + "POMEGRANATE", // SKINCOLOR_POMEGRANATE + "LILAC", // SKINCOLOR_LILAC - // Super special awesome Super flashing colors! - "SUPER1", // SKINCOLOR_SUPER1 - "SUPER2", // SKINCOLOR_SUPER2, - "SUPER3", // SKINCOLOR_SUPER3, - "SUPER4", // SKINCOLOR_SUPER4, - "SUPER5", // SKINCOLOR_SUPER5, - // Super Tails - "TSUPER1", // SKINCOLOR_TSUPER1, - "TSUPER2", // SKINCOLOR_TSUPER2, - "TSUPER3", // SKINCOLOR_TSUPER3, - "TSUPER4", // SKINCOLOR_TSUPER4, - "TSUPER5", // SKINCOLOR_TSUPER5, - // Super Knuckles - "KSUPER1", // SKINCOLOR_KSUPER1, - "KSUPER2", // SKINCOLOR_KSUPER2, - "KSUPER3", // SKINCOLOR_KSUPER3, - "KSUPER4", // SKINCOLOR_KSUPER4, - "KSUPER5" // SKINCOLOR_KSUPER5, + + + + + // Special super colors + // Super Sonic Yellow + "SUPER1", // SKINCOLOR_SUPER1 + "SUPER2", // SKINCOLOR_SUPER2, + "SUPER3", // SKINCOLOR_SUPER3, + "SUPER4", // SKINCOLOR_SUPER4, + "SUPER5", // SKINCOLOR_SUPER5, + + // Super Tails Orange + "TSUPER1", // SKINCOLOR_TSUPER1, + "TSUPER2", // SKINCOLOR_TSUPER2, + "TSUPER3", // SKINCOLOR_TSUPER3, + "TSUPER4", // SKINCOLOR_TSUPER4, + "TSUPER5", // SKINCOLOR_TSUPER5, + + // Super Knuckles Red + "KSUPER1", // SKINCOLOR_KSUPER1, + "KSUPER2", // SKINCOLOR_KSUPER2, + "KSUPER3", // SKINCOLOR_KSUPER3, + "KSUPER4", // SKINCOLOR_KSUPER4, + "KSUPER5", // SKINCOLOR_KSUPER5, + + // Hyper Sonic Pink + "PSUPER1", // SKINCOLOR_PSUPER1, + "PSUPER2", // SKINCOLOR_PSUPER2, + "PSUPER3", // SKINCOLOR_PSUPER3, + "PSUPER4", // SKINCOLOR_PSUPER4, + "PSUPER5", // SKINCOLOR_PSUPER5, + + // Hyper Sonic Blue + "BSUPER1", // SKINCOLOR_BSUPER1, + "BSUPER2", // SKINCOLOR_BSUPER2, + "BSUPER3", // SKINCOLOR_BSUPER3, + "BSUPER4", // SKINCOLOR_BSUPER4, + "BSUPER5", // SKINCOLOR_BSUPER5, + + // Aqua Super + "ASUPER1", // SKINCOLOR_ASUPER1, + "ASUPER2", // SKINCOLOR_ASUPER2, + "ASUPER3", // SKINCOLOR_ASUPER3, + "ASUPER4", // SKINCOLOR_ASUPER4, + "ASUPER5", // SKINCOLOR_ASUPER5, + + // Hyper Sonic Green + "GSUPER1", // SKINCOLOR_GSUPER1, + "GSUPER2", // SKINCOLOR_GSUPER2, + "GSUPER3", // SKINCOLOR_GSUPER3, + "GSUPER4", // SKINCOLOR_GSUPER4, + "GSUPER5", // SKINCOLOR_GSUPER5, + + // Hyper Sonic White + "WSUPER1", // SKINCOLOR_WSUPER1, + "WSUPER2", // SKINCOLOR_WSUPER2, + "WSUPER3", // SKINCOLOR_WSUPER3, + "WSUPER4", // SKINCOLOR_WSUPER4, + "WSUPER5", // SKINCOLOR_WSUPER5, + + // Creamy Super (Shadow?) + "CSUPER1", // SKINCOLOR_CSUPER1, + "CSUPER2", // SKINCOLOR_CSUPER2, + "CSUPER3", // SKINCOLOR_CSUPER3, + "CSUPER4", // SKINCOLOR_CSUPER4, + "CSUPER5" // SKINCOLOR_CSUPER5, }; static const char *const POWERS_LIST[] = { @@ -8263,6 +8340,7 @@ static const char *const KARTSTUFF_LIST[] = { "NEXTCHECK", "WAYPOINT", "STARPOSTWP", + "STARPOSTFLIP", "RESPAWN", "DROPDASH", @@ -8336,7 +8414,8 @@ static const char *const KARTSTUFF_LIST[] = { "ITEMBLINKMODE", "GETSPARKS", "JAWZTARGETDELAY", - "SPECTATEWAIT" + "SPECTATEWAIT", + "GROWCANCEL" }; #endif @@ -8561,13 +8640,7 @@ struct { {"RW_RAIL",RW_RAIL}, // Character flags (skinflags_t) - {"SF_SUPER",SF_SUPER}, - {"SF_SUPERANIMS",SF_SUPERANIMS}, - {"SF_SUPERSPIN",SF_SUPERSPIN}, {"SF_HIRES",SF_HIRES}, - {"SF_NOSKID",SF_NOSKID}, - {"SF_NOSPEEDADJUST",SF_NOSPEEDADJUST}, - {"SF_RUNONWATER",SF_RUNONWATER}, // Character abilities! // Primary @@ -9840,6 +9913,9 @@ static inline int lib_getenum(lua_State *L) } else if (fastcmp(word,"indirectitemcooldown")) { lua_pushinteger(L, indirectitemcooldown); return 1; + } else if (fastcmp(word,"hyubgone")) { + lua_pushinteger(L, hyubgone); + return 1; } else if (fastcmp(word,"thwompsactive")) { lua_pushboolean(L, thwompsactive); return 1; diff --git a/src/djgppdos/i_video.c b/src/djgppdos/i_video.c index 612c7221..7829acbb 100644 --- a/src/djgppdos/i_video.c +++ b/src/djgppdos/i_video.c @@ -94,6 +94,9 @@ void I_FinishUpdate (void) if (cv_ticrate.value) SCR_DisplayTicRate(); + if (cv_showping.value && netgame && consoleplayer != serverplayer) + SCR_DisplayLocalPing(); + //blast it to the screen // this code sucks //memcpy(dascreen,screens[0],screenwidth*screenheight); diff --git a/src/doomdef.h b/src/doomdef.h index 3126a7ca..a4a8ff22 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -150,9 +150,9 @@ extern FILE *logstream; // we use comprevision and compbranch instead. #else #define VERSION 100 // Game version -#define SUBVERSION 3 // more precise version number -#define VERSIONSTRING "v1.0.3 Netreplays" -#define VERSIONSTRINGW L"v1.0.3 Netreplays" +#define SUBVERSION 4 // more precise version number +#define VERSIONSTRING "v1.0.4 Netreplays" +#define VERSIONSTRINGW L"v1.0.4 Netreplays" // Hey! If you change this, add 1 to the MODVERSION below! // Otherwise we can't force updates! #endif @@ -221,7 +221,7 @@ extern FILE *logstream; // it's only for detection of the version the player is using so the MS can alert them of an update. // Only set it higher, not lower, obviously. // Note that we use this to help keep internal testing in check; this is why v2.1.0 is not version "1". -#define MODVERSION 3 +#define MODVERSION 4 // Filter consvars by version // To version config.cfg, MAJOREXECVERSION is set equal to MODVERSION automatically. @@ -244,7 +244,7 @@ extern FILE *logstream; // NOTE: it needs more than this to increase the number of players... #define MAXPLAYERS 16 -#define MAXSKINS 64 +#define MAXSKINS 128 #define PLAYERSMASK (MAXPLAYERS-1) #define MAXPLAYERNAME 21 @@ -256,6 +256,8 @@ typedef enum SKINCOLOR_GREY, SKINCOLOR_NICKEL, SKINCOLOR_BLACK, + SKINCOLOR_FAIRY, + SKINCOLOR_POPCORN, SKINCOLOR_SEPIA, SKINCOLOR_BEIGE, SKINCOLOR_BROWN, @@ -263,12 +265,18 @@ typedef enum SKINCOLOR_SALMON, SKINCOLOR_PINK, SKINCOLOR_ROSE, + SKINCOLOR_BRICK, SKINCOLOR_RUBY, SKINCOLOR_RASPBERRY, + SKINCOLOR_CHERRY, SKINCOLOR_RED, SKINCOLOR_CRIMSON, + SKINCOLOR_MAROON, + SKINCOLOR_FLAME, + SKINCOLOR_SCARLET, SKINCOLOR_KETCHUP, SKINCOLOR_DAWN, + SKINCOLOR_SUNSET, SKINCOLOR_CREAMSICLE, SKINCOLOR_ORANGE, SKINCOLOR_PUMPKIN, @@ -277,68 +285,130 @@ typedef enum SKINCOLOR_TANGERINE, SKINCOLOR_PEACH, SKINCOLOR_CARAMEL, + SKINCOLOR_CREAM, SKINCOLOR_GOLD, + SKINCOLOR_ROYAL, SKINCOLOR_BRONZE, + SKINCOLOR_COPPER, SKINCOLOR_YELLOW, SKINCOLOR_MUSTARD, SKINCOLOR_OLIVE, SKINCOLOR_VOMIT, SKINCOLOR_GARDEN, SKINCOLOR_LIME, + SKINCOLOR_HANDHELD, SKINCOLOR_TEA, SKINCOLOR_PISTACHIO, - SKINCOLOR_ROBOHOOD, SKINCOLOR_MOSS, + SKINCOLOR_CAMOUFLAGE, + SKINCOLOR_ROBOHOOD, SKINCOLOR_MINT, SKINCOLOR_GREEN, SKINCOLOR_PINETREE, SKINCOLOR_EMERALD, SKINCOLOR_SWAMP, SKINCOLOR_DREAM, + SKINCOLOR_PLAGUE, + SKINCOLOR_ALGAE, + SKINCOLOR_CARIBBEAN, SKINCOLOR_AQUA, SKINCOLOR_TEAL, SKINCOLOR_CYAN, SKINCOLOR_JAWZ, // Oni's torment SKINCOLOR_CERULEAN, SKINCOLOR_NAVY, + SKINCOLOR_PLATINUM, SKINCOLOR_SLATE, SKINCOLOR_STEEL, + SKINCOLOR_RUST, SKINCOLOR_JET, SKINCOLOR_SAPPHIRE, // sweet mother, i cannot weave - slender aphrodite has overcome me with longing for a girl SKINCOLOR_PERIWINKLE, SKINCOLOR_BLUE, SKINCOLOR_BLUEBERRY, + SKINCOLOR_NOVA, + SKINCOLOR_PASTEL, + SKINCOLOR_MOONSLAM, + SKINCOLOR_ULTRAVIOLET, SKINCOLOR_DUSK, + SKINCOLOR_BUBBLEGUM, SKINCOLOR_PURPLE, + SKINCOLOR_FUCHSIA, + SKINCOLOR_TOXIC, + SKINCOLOR_MAUVE, SKINCOLOR_LAVENDER, SKINCOLOR_BYZANTIUM, SKINCOLOR_POMEGRANATE, SKINCOLOR_LILAC, - // Careful! MAXSKINCOLORS cannot be greater than 0x40 -- Which it is now. + // "Careful! MAXSKINCOLORS cannot be greater than 0x40 -- Which it is now." + // (This comment is a dirty liar! This is only limited by the integer type, so 255 for UINT8.) MAXSKINCOLORS, // Super special awesome Super flashing colors! + // Super Sonic Yellow SKINCOLOR_SUPER1 = MAXSKINCOLORS, SKINCOLOR_SUPER2, SKINCOLOR_SUPER3, SKINCOLOR_SUPER4, SKINCOLOR_SUPER5, - // Super Tails + // Super Tails Orange SKINCOLOR_TSUPER1, SKINCOLOR_TSUPER2, SKINCOLOR_TSUPER3, SKINCOLOR_TSUPER4, SKINCOLOR_TSUPER5, - // Super Knuckles + // Super Knuckles Red SKINCOLOR_KSUPER1, SKINCOLOR_KSUPER2, SKINCOLOR_KSUPER3, SKINCOLOR_KSUPER4, SKINCOLOR_KSUPER5, + // Hyper Sonic Pink + SKINCOLOR_PSUPER1, + SKINCOLOR_PSUPER2, + SKINCOLOR_PSUPER3, + SKINCOLOR_PSUPER4, + SKINCOLOR_PSUPER5, + + // Hyper Sonic Blue + SKINCOLOR_BSUPER1, + SKINCOLOR_BSUPER2, + SKINCOLOR_BSUPER3, + SKINCOLOR_BSUPER4, + SKINCOLOR_BSUPER5, + + // Aqua Super + SKINCOLOR_ASUPER1, + SKINCOLOR_ASUPER2, + SKINCOLOR_ASUPER3, + SKINCOLOR_ASUPER4, + SKINCOLOR_ASUPER5, + + // Hyper Sonic Green + SKINCOLOR_GSUPER1, + SKINCOLOR_GSUPER2, + SKINCOLOR_GSUPER3, + SKINCOLOR_GSUPER4, + SKINCOLOR_GSUPER5, + + // Hyper Sonic White + SKINCOLOR_WSUPER1, + SKINCOLOR_WSUPER2, + SKINCOLOR_WSUPER3, + SKINCOLOR_WSUPER4, + SKINCOLOR_WSUPER5, + + // Creamy Super (Shadow?) + SKINCOLOR_CSUPER1, + SKINCOLOR_CSUPER2, + SKINCOLOR_CSUPER3, + SKINCOLOR_CSUPER4, + SKINCOLOR_CSUPER5, + MAXTRANSLATIONS } skincolors_t; @@ -471,13 +541,17 @@ INT32 I_GetKey(void); #define max(x, y) (((x) > (y)) ? (x) : (y)) #endif +#ifndef M_PIl +#define M_PIl 3.1415926535897932384626433832795029L +#endif + // Floating point comparison epsilons from float.h #ifndef FLT_EPSILON #define FLT_EPSILON 1.1920928955078125e-7f #endif #ifndef DBL_EPSILON -#define DBL_EPSILON 2.2204460492503131e-16 +#define DBL_EPSILON 2.2204460492503131e-16l #endif // An assert-type mechanism. diff --git a/src/doomstat.h b/src/doomstat.h index 9ae2726d..834b3a7c 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -57,7 +57,6 @@ extern boolean modifiedgame; extern boolean majormods; extern UINT16 mainwads; extern boolean savemoddata; // This mod saves time/emblem data. -extern boolean disableSpeedAdjust; // Don't alter the duration of player states if true extern boolean imcontinuing; // Temporary flag while continuing extern boolean metalrecording; @@ -468,6 +467,7 @@ extern boolean comeback; extern SINT8 battlewanted[4]; extern tic_t wantedcalcdelay; extern tic_t indirectitemcooldown; +extern tic_t hyubgone; extern tic_t mapreset; extern UINT8 nospectategrief; extern boolean thwompsactive; diff --git a/src/f_finale.c b/src/f_finale.c index 1426e50d..cdde54f3 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -611,7 +611,7 @@ void F_CreditDrawer(void) if (credits_pics[i].colorize != SKINCOLOR_NONE) { - colormap = R_GetTranslationColormap(TC_RAINBOW, credits_pics[i].colorize, 0); + colormap = R_GetTranslationColormap(TC_RAINBOW, credits_pics[i].colorize, GTC_MENUCACHE); sc = FRACUNIT; // quick hack so I don't have to add another field to credits_pics } @@ -1124,6 +1124,10 @@ void F_StartWaitingPlayers(void) finalecount = 0; randskin = M_RandomKey(numskins); + + if (waitcolormap) + Z_Free(waitcolormap); + waitcolormap = R_GetTranslationColormap(randskin, skins[randskin].prefcolor, 0); for (i = 0; i < 2; i++) diff --git a/src/g_game.c b/src/g_game.c index 19b062da..313156d3 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -93,7 +93,6 @@ boolean majormods = false; // Set if Lua/Gameplay SOC/replacement map has been a boolean savemoddata = false; UINT8 paused; UINT8 modeattacking = ATTACKING_NONE; -boolean disableSpeedAdjust = true; boolean imcontinuing = false; boolean runemeraldmanager = false; @@ -268,6 +267,7 @@ SINT8 pickedvote; // What vote the host rolls SINT8 battlewanted[4]; // WANTED players in battle, worth x2 points tic_t wantedcalcdelay; // Time before it recalculates WANTED tic_t indirectitemcooldown; // Cooldown before any more Shrink, SPB, or any other item that works indirectly is awarded +tic_t hyubgone; // Cooldown before hyudoro is allowed to be rerolled tic_t mapreset; // Map reset delay when enough players have joined an empty game UINT8 nospectategrief; // How many players need to be in-game to eliminate last; for preventing spectate griefing boolean thwompsactive; // Thwomps activate on lap 2 @@ -447,6 +447,9 @@ consvar_t cv_chatbacktint = {"chatbacktint", "On", CV_SAVE, CV_OnOff, NULL, 0, N static CV_PossibleValue_t consolechat_cons_t[] = {{0, "Window"}, {1, "Console"}, {2, "Window (Hidden)"}, {0, NULL}}; consvar_t cv_consolechat = {"chatmode", "Window", CV_SAVE, consolechat_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +// Pause game upon window losing focus +consvar_t cv_pauseifunfocused = {"pauseifunfocused", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; + // Display song credits consvar_t cv_songcredits = {"songcredits", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -2395,7 +2398,7 @@ void G_Ticker(boolean run) G_CopyTiccmd(cmd, &netcmds[buf][i], 1); // Use the leveltime sent in the player's ticcmd to determine control lag - cmd->latency = modeattacking ? 0 : min((leveltime & 0xFF) - cmd->latency, MAXPREDICTTICS-1); //@TODO add a cvar to allow setting this max + cmd->latency = modeattacking ? 0 : min(((leveltime & 0xFF) - cmd->latency) & 0xFF, MAXPREDICTTICS-1); //@TODO add a cvar to allow setting this max } } @@ -2590,6 +2593,7 @@ void G_PlayerReborn(INT32 player) UINT8 skincolor; INT32 skin; tic_t jointime; + UINT8 splitscreenindex; boolean spectator; INT16 bot; SINT8 pity; @@ -2604,6 +2608,7 @@ void G_PlayerReborn(INT32 player) INT32 bumper; INT32 comebackpoints; INT32 wanted; + INT32 respawnflip; boolean songcredit = false; score = players[player].score; @@ -2613,6 +2618,7 @@ void G_PlayerReborn(INT32 player) ctfteam = players[player].ctfteam; exiting = players[player].exiting; jointime = players[player].jointime; + splitscreenindex = players[player].splitscreenindex; spectator = players[player].spectator; pflags = (players[player].pflags & (PF_TIMEOVER|PF_FLIPCAM|PF_TAGIT|PF_TAGGED|PF_ANALOGMODE|PF_WANTSTOJOIN)); @@ -2644,6 +2650,7 @@ void G_PlayerReborn(INT32 player) starposty = players[player].starposty; starpostz = players[player].starpostz; starpostnum = players[player].starpostnum; + respawnflip = players[player].kartstuff[k_starpostflip]; //SRB2KART starpostangle = players[player].starpostangle; jumpfactor = players[player].jumpfactor; thokitem = players[player].thokitem; @@ -2709,6 +2716,7 @@ void G_PlayerReborn(INT32 player) p->pflags = pflags; p->ctfteam = ctfteam; p->jointime = jointime; + p->splitscreenindex = splitscreenindex; p->spectator = spectator; // save player config truth reborn @@ -2763,6 +2771,7 @@ void G_PlayerReborn(INT32 player) p->kartstuff[k_comebacktimer] = comebacktime; p->kartstuff[k_wanted] = wanted; p->kartstuff[k_eggmanblame] = -1; + p->kartstuff[k_starpostflip] = respawnflip; // Don't do anything immediately p->pflags |= PF_USEDOWN; @@ -5667,17 +5676,16 @@ void G_GhostTicker(void) INT32 type = -1; if (g->mo->skin) { - skin_t *skin = (skin_t *)g->mo->skin; switch (ziptic & EZT_THOKMASK) { case EZT_THOK: - type = skin->thokitem < 0 ? (UINT32)mobjinfo[MT_PLAYER].painchance : (UINT32)skin->thokitem; + type = (UINT32)mobjinfo[MT_PLAYER].painchance; break; case EZT_SPIN: - type = skin->spinitem < 0 ? (UINT32)mobjinfo[MT_PLAYER].damage : (UINT32)skin->spinitem; + type = (UINT32)mobjinfo[MT_PLAYER].damage; break; case EZT_REV: - type = skin->revitem < 0 ? (UINT32)mobjinfo[MT_PLAYER].raisestate : (UINT32)skin->revitem; + type = (UINT32)mobjinfo[MT_PLAYER].raisestate; break; } } diff --git a/src/g_game.h b/src/g_game.h index 4549044b..e5f94793 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -58,6 +58,7 @@ extern INT16 rw_maximums[NUM_WEAPONS]; // used in game menu extern consvar_t cv_chatwidth, cv_chatnotifications, cv_chatheight, cv_chattime, cv_consolechat, cv_chatbacktint, cv_chatspamprotection/*, cv_compactscoreboard*/; extern consvar_t cv_songcredits; +extern consvar_t cv_pauseifunfocused; //extern consvar_t cv_crosshair, cv_crosshair2, cv_crosshair3, cv_crosshair4; extern consvar_t cv_invertmouse/*, cv_alwaysfreelook, cv_chasefreelook, cv_mousemove*/; extern consvar_t cv_invertmouse2/*, cv_alwaysfreelook2, cv_chasefreelook2, cv_mousemove2*/; diff --git a/src/hardware/hw_bsp.c b/src/hardware/hw_bsp.c index 48393249..9e454bcd 100644 --- a/src/hardware/hw_bsp.c +++ b/src/hardware/hw_bsp.c @@ -201,7 +201,7 @@ static polyvertex_t *fracdivline(fdivline_t *bsp, polyvertex_t *v1, // (do not accept hit with the extensions) num = (v2x - v1x)*v2dy + (v1y - v2y)*v2dx; frac = num / den; - if (frac < 0.0 || frac > 1.0) + if (frac < 0.0l || frac > 1.0l) return NULL; // now get the frac along the BSP line diff --git a/src/hardware/hw_dll.h b/src/hardware/hw_dll.h index 6b9f4d53..46645278 100644 --- a/src/hardware/hw_dll.h +++ b/src/hardware/hw_dll.h @@ -61,9 +61,6 @@ typedef void (*I_Error_t) (const char *error, ...) FUNCIERROR; // ========================================================================== // Constants -#ifndef M_PIl -#define M_PIl 3.1415926535897932384626433832795029L -#endif #define DEGREE (0.017453292519943295769236907684883l) // 2*PI/360 void DBG_Printf(const char *lpFmt, ...) /*FUNCPRINTF*/; diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 3a8be6a0..ad90a518 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -2056,7 +2056,7 @@ EXPORT void HWRAPI(DrawMD2) (INT32 *gl_cmd_buffer, md2_frame_t *frame, FTransfor EXPORT void HWRAPI(SetTransform) (FTransform *stransform) { static boolean special_splitscreen; - float used_fov; + GLdouble used_fov; pglLoadIdentity(); if (stransform) { @@ -2088,7 +2088,7 @@ EXPORT void HWRAPI(SetTransform) (FTransform *stransform) pglLoadIdentity(); if (special_splitscreen) { - used_fov = atan(tan(used_fov*M_PI/360)*0.8)*360/M_PI; + used_fov = atan(tan(used_fov*M_PIl/360.0l)*0.8l)*360/M_PIl; GLPerspective(used_fov, 2*ASPECT_RATIO); } else diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 5959f825..12633ed4 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -74,6 +74,14 @@ patch_t *nightsnum[10]; // 0-9 patch_t *lt_font[LT_FONTSIZE]; patch_t *cred_font[CRED_FONTSIZE]; +// ping font +// Note: I'd like to adress that at this point we might *REALLY* want to work towards a common drawString function that can take any font we want because this is really turning into a MESS. :V -Lat' +patch_t *pingnum[10]; +patch_t *pinggfx[5]; // small ping graphic + +patch_t *framecounter; +patch_t *frameslash; // framerate stuff. Used in screen.c + static player_t *plr; boolean chat_on; // entering a chat message? static char w_chat[HU_MAXMSGLEN]; @@ -263,6 +271,8 @@ void HU_LoadGraphics(void) tallnum[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX); sprintf(buffer, "NGTNUM%d", i); nightsnum[i] = (patch_t *) W_CachePatchName(buffer, PU_HUDGFX); + sprintf(buffer, "PINGN%d", i); + pingnum[i] = (patch_t *) W_CachePatchName(buffer, PU_HUDGFX); } // minus for negative tallnums @@ -295,6 +305,17 @@ void HU_LoadGraphics(void) tinyemeraldpics[6] = W_CachePatchName("TEMER7", PU_HUDGFX); songcreditbg = W_CachePatchName("K_SONGCR", PU_HUDGFX); + + // cache ping gfx: + for (i = 0; i < 5; i++) + { + sprintf(buffer, "PINGGFX%d", i+1); + pinggfx[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX); + } + + // fps stuff + framecounter = W_CachePatchName("FRAMER", PU_HUDGFX); + frameslash = W_CachePatchName("FRAMESL", PU_HUDGFX);; } // Initialise Heads up @@ -757,44 +778,139 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) } } else - { + { const UINT8 color = players[playernum].skincolor; cstart = "\x83"; - if (color <= SKINCOLOR_SILVER || color == SKINCOLOR_SLATE) - cstart = "\x80"; // white - else if (color <= SKINCOLOR_BLACK || color == SKINCOLOR_JET) - cstart = "\x86"; // V_GRAYMAP - else if (color <= SKINCOLOR_LEATHER) - cstart = "\x8e"; // V_BROWNMAP - else if (color <= SKINCOLOR_ROSE || color == SKINCOLOR_LILAC) - cstart = "\x8d"; // V_PINKMAP - else if (color <= SKINCOLOR_KETCHUP) - cstart = "\x85"; // V_REDMAP - else if (color <= SKINCOLOR_TANGERINE) - cstart = "\x87"; // V_ORANGEMAP - else if (color <= SKINCOLOR_CARAMEL) - cstart = "\x8f"; // V_PEACHMAP - else if (color <= SKINCOLOR_BRONZE) - cstart = "\x8A"; // V_GOLDMAP - else if (color <= SKINCOLOR_OLIVE) - cstart = "\x82"; // V_YELLOWMAP - else if (color <= SKINCOLOR_PISTACHIO) - cstart = "\x8b"; // V_TEAMAP - else if (color <= SKINCOLOR_DREAM || color == SKINCOLOR_LIME) - cstart = "\x83"; // V_GREENMAP - else if (color <= SKINCOLOR_NAVY || color == SKINCOLOR_SAPPHIRE) - cstart = "\x88"; // V_SKYMAP - else if (color <= SKINCOLOR_STEEL) - cstart = "\x8c"; // V_STEELMAP - else if (color <= SKINCOLOR_BLUEBERRY) - cstart = "\x84"; // V_BLUEMAP - else if (color == SKINCOLOR_PURPLE) - cstart = "\x81"; // V_PURPLEMAP - else //if (color <= SKINCOLOR_POMEGRANATE) - cstart = "\x89"; // V_LAVENDERMAP - } + switch (color) + { + case SKINCOLOR_WHITE: + case SKINCOLOR_SILVER: + case SKINCOLOR_SLATE: + cstart = "\x80"; // White + break; + case SKINCOLOR_GREY: + case SKINCOLOR_NICKEL: + case SKINCOLOR_BLACK: + case SKINCOLOR_JET: + cstart = "\x86"; // V_GRAYMAP + break; + case SKINCOLOR_SEPIA: + case SKINCOLOR_BEIGE: + case SKINCOLOR_BROWN: + case SKINCOLOR_LEATHER: + case SKINCOLOR_RUST: + cstart = "\x8e"; // V_BROWNMAP + break; + case SKINCOLOR_FAIRY: + case SKINCOLOR_SALMON: + case SKINCOLOR_PINK: + case SKINCOLOR_ROSE: + case SKINCOLOR_BRICK: + case SKINCOLOR_BUBBLEGUM: + case SKINCOLOR_LILAC: + cstart = "\x8d"; // V_PINKMAP + break; + case SKINCOLOR_RUBY: + case SKINCOLOR_RASPBERRY: + case SKINCOLOR_CHERRY: + case SKINCOLOR_RED: + case SKINCOLOR_CRIMSON: + case SKINCOLOR_MAROON: + case SKINCOLOR_FLAME: + case SKINCOLOR_SCARLET: + case SKINCOLOR_KETCHUP: + cstart = "\x85"; // V_REDMAP + break; + case SKINCOLOR_DAWN: + case SKINCOLOR_SUNSET: + case SKINCOLOR_CREAMSICLE: + case SKINCOLOR_ORANGE: + case SKINCOLOR_PUMPKIN: + case SKINCOLOR_ROSEWOOD: + case SKINCOLOR_BURGUNDY: + case SKINCOLOR_TANGERINE: + cstart = "\x87"; // V_ORANGEMAP + break; + case SKINCOLOR_PEACH: + case SKINCOLOR_CARAMEL: + case SKINCOLOR_CREAM: + cstart = "\x8f"; // V_PEACHMAP + break; + case SKINCOLOR_GOLD: + case SKINCOLOR_ROYAL: + case SKINCOLOR_BRONZE: + case SKINCOLOR_COPPER: + cstart = "\x8A"; // V_GOLDMAP + break; + case SKINCOLOR_POPCORN: + case SKINCOLOR_YELLOW: + case SKINCOLOR_MUSTARD: + case SKINCOLOR_OLIVE: + cstart = "\x82"; // V_YELLOWMAP + break; + case SKINCOLOR_VOMIT: + case SKINCOLOR_GARDEN: + case SKINCOLOR_TEA: + case SKINCOLOR_PISTACHIO: + cstart = "\x8b"; // V_TEAMAP + break; + case SKINCOLOR_LIME: + case SKINCOLOR_HANDHELD: + case SKINCOLOR_MOSS: + case SKINCOLOR_CAMOUFLAGE: + case SKINCOLOR_ROBOHOOD: + case SKINCOLOR_MINT: + case SKINCOLOR_GREEN: + case SKINCOLOR_PINETREE: + case SKINCOLOR_EMERALD: + case SKINCOLOR_SWAMP: + case SKINCOLOR_DREAM: + case SKINCOLOR_PLAGUE: + case SKINCOLOR_ALGAE: + cstart = "\x83"; // V_GREENMAP + break; + case SKINCOLOR_CARIBBEAN: + case SKINCOLOR_AQUA: + case SKINCOLOR_TEAL: + case SKINCOLOR_CYAN: + case SKINCOLOR_JAWZ: + case SKINCOLOR_CERULEAN: + case SKINCOLOR_NAVY: + case SKINCOLOR_SAPPHIRE: + cstart = "\x88"; // V_SKYMAP + break; + case SKINCOLOR_PLATINUM: + case SKINCOLOR_STEEL: + cstart = "\x8c"; // V_STEELMAP + break; + case SKINCOLOR_PERIWINKLE: + case SKINCOLOR_BLUE: + case SKINCOLOR_BLUEBERRY: + case SKINCOLOR_NOVA: + cstart = "\x84"; // V_BLUEMAP + break; + case SKINCOLOR_ULTRAVIOLET: + case SKINCOLOR_PURPLE: + case SKINCOLOR_FUCHSIA: + cstart = "\x81"; // V_PURPLEMAP + break; + case SKINCOLOR_PASTEL: + case SKINCOLOR_MOONSLAM: + case SKINCOLOR_DUSK: + case SKINCOLOR_TOXIC: + case SKINCOLOR_MAUVE: + case SKINCOLOR_LAVENDER: + case SKINCOLOR_BYZANTIUM: + case SKINCOLOR_POMEGRANATE: + cstart = "\x89"; // V_LAVENDERMAP + break; + default: + break; + } + } + prefix = cstart; // Give admins and remote admins their symbols. @@ -1109,8 +1225,6 @@ static INT16 typelines = 1; // number of drawfill lines we need when drawing the // boolean HU_Responder(event_t *ev) { - INT32 c=0; - if (ev->type != ev_keydown) return false; @@ -1136,18 +1250,6 @@ boolean HU_Responder(event_t *ev) return false; } - c = (INT32)ev->data1; - - // capslock (now handled outside of chat on so that it works everytime......) - if (c && c == KEY_CAPSLOCK) // it's a toggle. - { - if (capslock) - capslock = false; - else - capslock = true; - return true; - } - #ifndef NONET if (!chat_on) { @@ -1175,6 +1277,7 @@ boolean HU_Responder(event_t *ev) } else // if chat_on { + INT32 c = (INT32)ev->data1; // Ignore modifier keys // Note that we do this here so users can still set @@ -1190,20 +1293,7 @@ boolean HU_Responder(event_t *ev) && ev->data1 != gamecontrol[gc_talkkey][1])) return false; - c = (INT32)ev->data1; - - // I know this looks very messy but this works. If it ain't broke, don't fix it! - // shift LETTERS to uppercase if we have capslock or are holding shift - if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) - { - if (shiftdown ^ capslock) - c = shiftxform[c]; - } - else // if we're holding shift we should still shift non letter symbols - { - if (shiftdown) - c = shiftxform[c]; - } + c = CON_ShiftChar(c); // pasting. pasting is cool. chat is a bit limited, though :( if (((c == 'v' || c == 'V') && ctrldown) && !CHAT_MUTE) @@ -1612,9 +1702,9 @@ static void HU_drawChatLog(INT32 offset) // draw arrows to indicate that we can (or not) scroll. if (chat_scroll > 0) - V_DrawThinString(chatx-9, ((justscrolledup) ? (chat_topy-1) : (chat_topy)), V_SNAPTOBOTTOM | V_SNAPTOLEFT | highlight, "\x1A"); // up arrow + V_DrawCharacter(chatx-9, ((justscrolledup) ? (chat_topy-1) : (chat_topy)), V_SNAPTOBOTTOM | V_SNAPTOLEFT | highlight | '\x1A', false); // up arrow if (chat_scroll < chat_maxscroll) - V_DrawThinString(chatx-9, chat_bottomy-((justscrolleddown) ? 5 : 6), V_SNAPTOBOTTOM | V_SNAPTOLEFT | highlight, "\x1B"); // down arrow + V_DrawCharacter(chatx-9, chat_bottomy-((justscrolleddown) ? 5 : 6), V_SNAPTOBOTTOM | V_SNAPTOLEFT | highlight | '\x1B', false); // down arrow justscrolleddown = false; justscrolledup = false; @@ -2181,6 +2271,7 @@ static void HU_DrawSongCredits(void) V_DrawRightAlignedThinString(cursongcredit.x, y, V_ALLOWLOWERCASE|V_6WIDTHSPACE|V_SNAPTOLEFT|(cursongcredit.trans<= 640) // how sad, we're using a shit resolution. - V_DrawSmallString(dx, y+4, V_ALLOWLOWERCASE, va("%dms", ping)); - - for (i=0; (i<3); i++) // Draw the ping bar - { - V_DrawFill(x+2 *(i-1), y+yoffset-4, 2, 8-yoffset, 31); - if (i < numbars) - V_DrawFill(x+2 *(i-1), y+yoffset-3, 1, 8-yoffset-1, barcolor); - - yoffset -= 2; - } + V_DrawScaledPatch(x, y, flags, pinggfx[gfxnum]); + if (servermaxping && ping > servermaxping && hu_tick < 4) // flash ping red if too high + V_DrawPingNum(x, y+9, flags, ping, colormap); + else + V_DrawPingNum(x, y+9, flags, ping, NULL); } // diff --git a/src/hu_stuff.h b/src/hu_stuff.h index f1ecb2ff..0f316bc7 100644 --- a/src/hu_stuff.h +++ b/src/hu_stuff.h @@ -80,7 +80,11 @@ extern boolean chat_on; extern patch_t *hu_font[HU_FONTSIZE], *kart_font[KART_FONTSIZE], *tny_font[HU_FONTSIZE]; // SRB2kart extern patch_t *tallnum[10]; +extern patch_t *pingnum[10]; +extern patch_t *pinggfx[5]; extern patch_t *nightsnum[10]; +extern patch_t *framecounter; +extern patch_t *frameslash; extern patch_t *lt_font[LT_FONTSIZE]; extern patch_t *cred_font[CRED_FONTSIZE]; extern patch_t *emeraldpics[7]; @@ -109,7 +113,7 @@ void HU_Drawer(void); char HU_dequeueChatChar(void); void HU_Erase(void); void HU_clearChatChars(void); -void HU_drawPing(INT32 x, INT32 y, INT32 ping, boolean notext); // Lat': Ping drawer for scoreboard. +void HU_drawPing(INT32 x, INT32 y, UINT32 ping, INT32 flags); // Lat': Ping drawer for scoreboard. //void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer); //void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, INT32 whiteplayer); void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, INT32 whiteplayer, INT32 hilicol); diff --git a/src/info.c b/src/info.c index 5701f1c9..d609bf55 100644 --- a/src/info.c +++ b/src/info.c @@ -3140,11 +3140,11 @@ state_t states[NUMSTATES] = {SPR_NULL, 0, 1, {A_FZBoomSmoke}, 1, 0, S_FZEROBOOM12}, // S_FZEROBOOM11 {SPR_NULL, 0, 1, {A_FZBoomSmoke}, 0, 0, S_NULL}, // S_FZEROBOOM12 - {SPR_SMOK, FF_TRANS30, 30, {NULL}, 0, 0, S_FZSLOWSMOKE2}, // S_FZSLOWSMOKE1 - {SPR_SMOK, FF_TRANS30|1, 30, {NULL}, 0, 0, S_FZSLOWSMOKE3}, // S_FZSLOWSMOKE2 - {SPR_SMOK, FF_TRANS30|2, 30, {NULL}, 0, 0, S_FZSLOWSMOKE4}, // S_FZSLOWSMOKE3 - {SPR_SMOK, FF_TRANS30|3, 30, {NULL}, 0, 0, S_FZSLOWSMOKE5}, // S_FZSLOWSMOKE4 - {SPR_SMOK, FF_TRANS30|4, 30, {NULL}, 0, 0, S_NULL}, // S_FZSLOWSMOKE5 + {SPR_SMOK, 0, 30, {NULL}, 0, 0, S_FZSLOWSMOKE2}, // S_FZSLOWSMOKE1 + {SPR_SMOK, 1, 30, {NULL}, 0, 0, S_FZSLOWSMOKE3}, // S_FZSLOWSMOKE2 + {SPR_SMOK, 2, 30, {NULL}, 0, 0, S_FZSLOWSMOKE4}, // S_FZSLOWSMOKE3 + {SPR_SMOK, 3, 30, {NULL}, 0, 0, S_FZSLOWSMOKE5}, // S_FZSLOWSMOKE4 + {SPR_SMOK, 4, 30, {NULL}, 0, 0, S_NULL}, // S_FZSLOWSMOKE5 // Various plants {SPR_SBUS, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SONICBUSH @@ -3394,6 +3394,13 @@ state_t states[NUMSTATES] = {SPR_FWRK, 3|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_KARMAFIREWORK1}, // S_KARMAFIREWORK4 {SPR_FWRK, 4|FF_FULLBRIGHT, TICRATE, {NULL}, 0, 0, S_NULL}, // S_KARMAFIREWORKTRAIL + // Opaque smoke + {SPR_SMOK, 0, 4, {NULL}, 0, 0, S_OPAQUESMOKE2}, // S_OPAQUESMOKE1 + {SPR_SMOK, 1, 5, {NULL}, 0, 0, S_OPAQUESMOKE3}, // S_OPAQUESMOKE2 + {SPR_SMOK, 2, 6, {NULL}, 0, 0, S_OPAQUESMOKE4}, // S_OPAQUESMOKE3 + {SPR_SMOK, 3, 7, {NULL}, 0, 0, S_OPAQUESMOKE5}, // S_OPAQUESMOKE4 + {SPR_SMOK, 4, 8, {NULL}, 0, 0, S_NULL}, // S_OPAQUESMOKE5 + #ifdef SEENAMES {SPR_NULL, 0, 1, {NULL}, 0, 0, S_NULL}, // S_NAMECHECK #endif @@ -15018,8 +15025,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_None, // deathsound 8, // speed - 8*FRACUNIT, // radius - 8*FRACUNIT, // height + 32*FRACUNIT, // radius + 64*FRACUNIT, // height 1, // display offset 100, // mass 0, // damage @@ -15574,7 +15581,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 1, // spawnhealth S_NULL, // seestate sfx_tossed, // seesound - 6*TICRATE, // reactiontime + 0, // reactiontime sfx_None, // attacksound S_NULL, // painstate 192*FRACUNIT, // painchance diff --git a/src/info.h b/src/info.h index 157c72e1..0e23a07c 100644 --- a/src/info.h +++ b/src/info.h @@ -4052,6 +4052,12 @@ typedef enum state S_KARMAFIREWORK4, S_KARMAFIREWORKTRAIL, + S_OPAQUESMOKE1, + S_OPAQUESMOKE2, + S_OPAQUESMOKE3, + S_OPAQUESMOKE4, + S_OPAQUESMOKE5, + #ifdef SEENAMES S_NAMECHECK, #endif diff --git a/src/k_kart.c b/src/k_kart.c index 7a5b7787..8a68cafe 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -43,218 +43,328 @@ // These should be within 14 characters to fit on the character select screen const char *KartColor_Names[MAXSKINCOLORS] = { - "None", // 00 // SKINCOLOR_NONE - "White", // 01 // SKINCOLOR_WHITE - "Silver", // 02 // SKINCOLOR_SILVER - "Grey", // 03 // SKINCOLOR_GREY - "Nickel", // 04 // SKINCOLOR_NICKEL - "Black", // 05 // SKINCOLOR_BLACK - "Sepia", // 06 // SKINCOLOR_SEPIA - "Beige", // 07 // SKINCOLOR_BEIGE - "Brown", // 08 // SKINCOLOR_BROWN - "Leather", // 09 // SKINCOLOR_LEATHER - "Salmon", // 10 // SKINCOLOR_SALMON - "Pink", // 11 // SKINCOLOR_PINK - "Rose", // 12 // SKINCOLOR_ROSE - "Ruby", // 13 // SKINCOLOR_RUBY - "Raspberry", // 14 // SKINCOLOR_RASPBERRY - "Red", // 15 // SKINCOLOR_RED - "Crimson", // 16 // SKINCOLOR_CRIMSON - "Ketchup", // 17 // SKINCOLOR_KETCHUP - "Dawn", // 18 // SKINCOLOR_DAWN - "Creamsicle", // 19 // SKINCOLOR_CREAMSICLE - "Orange", // 20 // SKINCOLOR_ORANGE - "Pumpkin", // 21 // SKINCOLOR_PUMPKIN - "Rosewood", // 22 // SKINCOLOR_ROSEWOOD - "Burgundy", // 23 // SKINCOLOR_BURGUNDY - "Tangerine", // 24 // SKINCOLOR_TANGERINE - "Peach", // 25 // SKINCOLOR_PEACH - "Caramel", // 26 // SKINCOLOR_CARAMEL - "Gold", // 27 // SKINCOLOR_GOLD - "Bronze", // 28 // SKINCOLOR_BRONZE - "Yellow", // 29 // SKINCOLOR_YELLOW - "Mustard", // 30 // SKINCOLOR_MUSTARD - "Olive", // 31 // SKINCOLOR_OLIVE - "Vomit", // 32 // SKINCOLOR_VOMIT - "Garden", // 33 // SKINCOLOR_GARDEN - "Lime", // 34 // SKINCOLOR_LIME - "Tea", // 35 // SKINCOLOR_TEA - "Pistachio", // 36 // SKINCOLOR_PISTACHIO - "Robo-Hood", // 37 // SKINCOLOR_ROBOHOOD - "Moss", // 38 // SKINCOLOR_MOSS - "Mint", // 39 // SKINCOLOR_MINT - "Green", // 40 // SKINCOLOR_GREEN - "Pinetree", // 41 // SKINCOLOR_PINETREE - "Emerald", // 42 // SKINCOLOR_EMERALD - "Swamp", // 43 // SKINCOLOR_SWAMP - "Dream", // 44 // SKINCOLOR_DREAM - "Aqua", // 45 // SKINCOLOR_AQUA - "Teal", // 46 // SKINCOLOR_TEAL - "Cyan", // 47 // SKINCOLOR_CYAN - "Jawz", // 48 // SKINCOLOR_JAWZ - "Cerulean", // 49 // SKINCOLOR_CERULEAN - "Navy", // 50 // SKINCOLOR_NAVY - "Slate", // 51 // SKINCOLOR_SLATE - "Steel", // 52 // SKINCOLOR_STEEL - "Jet", // 53 // SKINCOLOR_JET - "Sapphire", // 54 // SKINCOLOR_SAPPHIRE - "Periwinkle", // 55 // SKINCOLOR_PERIWINKLE - "Blue", // 56 // SKINCOLOR_BLUE - "Blueberry", // 57 // SKINCOLOR_BLUEBERRY - "Dusk", // 58 // SKINCOLOR_DUSK - "Purple", // 59 // SKINCOLOR_PURPLE - "Lavender", // 60 // SKINCOLOR_LAVENDER - "Byzantium", // 61 // SKINCOLOR_BYZANTIUM - "Pomegranate", // 62 // SKINCOLOR_POMEGRANATE - "Lilac" // 63 // SKINCOLOR_LILAC + "None", // SKINCOLOR_NONE + "White", // SKINCOLOR_WHITE + "Silver", // SKINCOLOR_SILVER + "Grey", // SKINCOLOR_GREY + "Nickel", // SKINCOLOR_NICKEL + "Black", // SKINCOLOR_BLACK + "Fairy", // SKINCOLOR_FAIRY + "Popcorn", // SKINCOLOR_POPCORN + "Sepia", // SKINCOLOR_SEPIA + "Beige", // SKINCOLOR_BEIGE + "Brown", // SKINCOLOR_BROWN + "Leather", // SKINCOLOR_LEATHER + "Salmon", // SKINCOLOR_SALMON + "Pink", // SKINCOLOR_PINK + "Rose", // SKINCOLOR_ROSE + "Brick", // SKINCOLOR_BRICK + "Ruby", // SKINCOLOR_RUBY + "Raspberry", // SKINCOLOR_RASPBERRY + "Cherry", // SKINCOLOR_CHERRY + "Red", // SKINCOLOR_RED + "Crimson", // SKINCOLOR_CRIMSON + "Maroon", // SKINCOLOR_MAROON + "Flame", // SKINCOLOR_FLAME + "Scarlet", // SKINCOLOR_SCARLET + "Ketchup", // SKINCOLOR_KETCHUP + "Dawn", // SKINCOLOR_DAWN + "Sunset", // SKINCOLOR_SUNSET + "Creamsicle", // SKINCOLOR_CREAMSICLE + "Orange", // SKINCOLOR_ORANGE + "Pumpkin", // SKINCOLOR_PUMPKIN + "Rosewood", // SKINCOLOR_ROSEWOOD + "Burgundy", // SKINCOLOR_BURGUNDY + "Tangerine", // SKINCOLOR_TANGERINE + "Peach", // SKINCOLOR_PEACH + "Caramel", // SKINCOLOR_CARAMEL + "Cream", // SKINCOLOR_CREAM + "Gold", // SKINCOLOR_GOLD + "Royal", // SKINCOLOR_ROYAL + "Bronze", // SKINCOLOR_BRONZE + "Copper", // SKINCOLOR_COPPER + "Yellow", // SKINCOLOR_YELLOW + "Mustard", // SKINCOLOR_MUSTARD + "Olive", // SKINCOLOR_OLIVE + "Vomit", // SKINCOLOR_VOMIT + "Garden", // SKINCOLOR_GARDEN + "Lime", // SKINCOLOR_LIME + "Handheld", // SKINCOLOR_HANDHELD + "Tea", // SKINCOLOR_TEA + "Pistachio", // SKINCOLOR_PISTACHIO + "Moss", // SKINCOLOR_MOSS + "Camouflage", // SKINCOLOR_CAMOUFLAGE + "Robo-Hood", // SKINCOLOR_ROBOHOOD + "Mint", // SKINCOLOR_MINT + "Green", // SKINCOLOR_GREEN + "Pinetree", // SKINCOLOR_PINETREE + "Emerald", // SKINCOLOR_EMERALD + "Swamp", // SKINCOLOR_SWAMP + "Dream", // SKINCOLOR_DREAM + "Plague", // SKINCOLOR_PLAGUE + "Algae", // SKINCOLOR_ALGAE + "Caribbean", // SKINCOLOR_CARIBBEAN + "Aqua", // SKINCOLOR_AQUA + "Teal", // SKINCOLOR_TEAL + "Cyan", // SKINCOLOR_CYAN + "Jawz", // SKINCOLOR_JAWZ + "Cerulean", // SKINCOLOR_CERULEAN + "Navy", // SKINCOLOR_NAVY + "Platinum", // SKINCOLOR_PLATINUM + "Slate", // SKINCOLOR_SLATE + "Steel", // SKINCOLOR_STEEL + "Rust", // SKINCOLOR_RUST + "Jet", // SKINCOLOR_JET + "Sapphire", // SKINCOLOR_SAPPHIRE + "Periwinkle", // SKINCOLOR_PERIWINKLE + "Blue", // SKINCOLOR_BLUE + "Blueberry", // SKINCOLOR_BLUEBERRY + "Nova", // SKINCOLOR_NOVA + "Pastel", // SKINCOLOR_PASTEL + "Moonslam", // SKINCOLOR_MOONSLAM + "Ultraviolet", // SKINCOLOR_ULTRAVIOLET + "Dusk", // SKINCOLOR_DUSK + "Bubblegum", // SKINCOLOR_BUBBLEGUM + "Purple", // SKINCOLOR_PURPLE + "Fuchsia", // SKINCOLOR_FUCHSIA + "Toxic", // SKINCOLOR_TOXIC + "Mauve", // SKINCOLOR_MAUVE + "Lavender", // SKINCOLOR_LAVENDER + "Byzantium", // SKINCOLOR_BYZANTIUM + "Pomegranate", // SKINCOLOR_POMEGRANATE + "Lilac" // SKINCOLOR_LILAC }; // Color_Opposite replacement; frame setting has not been changed from 8 for most, should be done later const UINT8 KartColor_Opposite[MAXSKINCOLORS*2] = { - SKINCOLOR_NONE,8, // 00 // SKINCOLOR_NONE - SKINCOLOR_BLACK,8, // 01 // SKINCOLOR_WHITE - SKINCOLOR_NICKEL,8, // 02 // SKINCOLOR_SILVER - SKINCOLOR_GREY,8, // 03 // SKINCOLOR_GREY - SKINCOLOR_SILVER,8, // 04 // SKINCOLOR_NICKEL - SKINCOLOR_WHITE,8, // 05 // SKINCOLOR_BLACK - SKINCOLOR_LEATHER,6, // 06 // SKINCOLOR_SEPIA - SKINCOLOR_BROWN,2, // 07 // SKINCOLOR_BEIGE - SKINCOLOR_BEIGE,8, // 08 // SKINCOLOR_BROWN - SKINCOLOR_SEPIA,8, // 09 // SKINCOLOR_LEATHER - SKINCOLOR_TEA,8, // 10 // SKINCOLOR_SALMON - SKINCOLOR_PISTACHIO,8, // 11 // SKINCOLOR_PINK - SKINCOLOR_MOSS,8, // 12 // SKINCOLOR_ROSE - SKINCOLOR_SAPPHIRE,8, // 13 // SKINCOLOR_RUBY - SKINCOLOR_MINT,8, // 14 // SKINCOLOR_RASPBERRY - SKINCOLOR_GREEN,6, // 15 // SKINCOLOR_RED - SKINCOLOR_PINETREE,6, // 16 // SKINCOLOR_CRIMSON - SKINCOLOR_MUSTARD,10, // 17 // SKINCOLOR_KETCHUP - SKINCOLOR_DUSK,8, // 18 // SKINCOLOR_DAWN - SKINCOLOR_PERIWINKLE,8, // 19 // SKINCOLOR_CREAMSICLE - SKINCOLOR_BLUE,8, // 20 // SKINCOLOR_ORANGE - SKINCOLOR_BLUEBERRY,8, // 21 // SKINCOLOR_PUMPKIN - SKINCOLOR_NAVY,6, // 22 // SKINCOLOR_ROSEWOOD - SKINCOLOR_JET,8, // 23 // SKINCOLOR_BURGUNDY - SKINCOLOR_LIME,8, // 24 // SKINCOLOR_TANGERINE - SKINCOLOR_CYAN,8, // 25 // SKINCOLOR_PEACH - SKINCOLOR_CERULEAN,8, // 26 // SKINCOLOR_CARAMEL - SKINCOLOR_SLATE,8, // 27 // SKINCOLOR_GOLD - SKINCOLOR_STEEL,8, // 28 // SKINCOLOR_BRONZE - SKINCOLOR_AQUA,8, // 29 // SKINCOLOR_YELLOW - SKINCOLOR_KETCHUP,8, // 30 // SKINCOLOR_MUSTARD - SKINCOLOR_TEAL,8, // 31 // SKINCOLOR_OLIVE - SKINCOLOR_ROBOHOOD,8, // 32 // SKINCOLOR_VOMIT - SKINCOLOR_LAVENDER,6, // 33 // SKINCOLOR_GARDEN - SKINCOLOR_TANGERINE,8, // 34 // SKINCOLOR_LIME - SKINCOLOR_SALMON,8, // 35 // SKINCOLOR_TEA - SKINCOLOR_PINK,6, // 36 // SKINCOLOR_PISTACHIO - SKINCOLOR_VOMIT,8, // 37 // SKINCOLOR_ROBOHOOD - SKINCOLOR_ROSE,8, // 38 // SKINCOLOR_MOSS - SKINCOLOR_RASPBERRY,8, // 39 // SKINCOLOR_MINT - SKINCOLOR_RED,8, // 40 // SKINCOLOR_GREEN - SKINCOLOR_CRIMSON,8, // 41 // SKINCOLOR_PINETREE - SKINCOLOR_PURPLE,8, // 42 // SKINCOLOR_EMERALD - SKINCOLOR_BYZANTIUM,8, // 43 // SKINCOLOR_SWAMP - SKINCOLOR_POMEGRANATE,8, // 44 // SKINCOLOR_DREAM - SKINCOLOR_YELLOW,8, // 45 // SKINCOLOR_AQUA - SKINCOLOR_OLIVE,8, // 46 // SKINCOLOR_TEAL - SKINCOLOR_PEACH,8, // 47 // SKINCOLOR_CYAN - SKINCOLOR_LILAC,10, // 48 // SKINCOLOR_JAWZ - SKINCOLOR_CARAMEL,8, // 49 // SKINCOLOR_CERULEAN - SKINCOLOR_ROSEWOOD,8, // 50 // SKINCOLOR_NAVY - SKINCOLOR_GOLD,10, // 51 // SKINCOLOR_SLATE - SKINCOLOR_BRONZE,10, // 52 // SKINCOLOR_STEEL - SKINCOLOR_BURGUNDY,8, // 53 // SKINCOLOR_JET - SKINCOLOR_RUBY,6, // 54 // SKINCOLOR_SAPPHIRE - SKINCOLOR_CREAMSICLE,8, // 55 // SKINCOLOR_PERIWINKLE - SKINCOLOR_ORANGE,8, // 56 // SKINCOLOR_BLUE - SKINCOLOR_PUMPKIN,8, // 57 // SKINCOLOR_BLUEBERRY - SKINCOLOR_DAWN,6, // 58 // SKINCOLOR_DUSK - SKINCOLOR_EMERALD,8, // 59 // SKINCOLOR_PURPLE - SKINCOLOR_GARDEN,6, // 60 // SKINCOLOR_LAVENDER - SKINCOLOR_SWAMP,8, // 61 // SKINCOLOR_BYZANTIUM - SKINCOLOR_DREAM,8, // 62 // SKINCOLOR_POMEGRANATE - SKINCOLOR_JAWZ,6 // 63 // SKINCOLOR_LILAC + SKINCOLOR_NONE,8, // SKINCOLOR_NONE + SKINCOLOR_BLACK,8, // SKINCOLOR_WHITE + SKINCOLOR_NICKEL,8, // SKINCOLOR_SILVER + SKINCOLOR_GREY,8, // SKINCOLOR_GREY + SKINCOLOR_SILVER,8, // SKINCOLOR_NICKEL + SKINCOLOR_WHITE,8, // SKINCOLOR_BLACK + SKINCOLOR_CAMOUFLAGE,8, // SKINCOLOR_FAIRY + SKINCOLOR_BUBBLEGUM,8, // SKINCOLOR_POPCORN + SKINCOLOR_LEATHER,6, // SKINCOLOR_SEPIA + SKINCOLOR_BROWN,2, // SKINCOLOR_BEIGE + SKINCOLOR_BEIGE,8, // SKINCOLOR_BROWN + SKINCOLOR_SEPIA,8, // SKINCOLOR_LEATHER + SKINCOLOR_TEA,8, // SKINCOLOR_SALMON + SKINCOLOR_PISTACHIO,8, // SKINCOLOR_PINK + SKINCOLOR_MOSS,8, // SKINCOLOR_ROSE + SKINCOLOR_RUST,8, // SKINCOLOR_BRICK + SKINCOLOR_SAPPHIRE,8, // SKINCOLOR_RUBY + SKINCOLOR_MINT,8, // SKINCOLOR_RASPBERRY + SKINCOLOR_HANDHELD,10, // SKINCOLOR_CHERRY + SKINCOLOR_GREEN,6, // SKINCOLOR_RED + SKINCOLOR_PINETREE,6, // SKINCOLOR_CRIMSON + SKINCOLOR_TOXIC,8, // SKINCOLOR_MAROON + SKINCOLOR_CARIBBEAN,10, // SKINCOLOR_FLAME + SKINCOLOR_ALGAE,10, // SKINCOLOR_SCARLET + SKINCOLOR_MUSTARD,10, // SKINCOLOR_KETCHUP + SKINCOLOR_DUSK,8, // SKINCOLOR_DAWN + SKINCOLOR_MOONSLAM,8, // SKINCOLOR_SUNSET + SKINCOLOR_PERIWINKLE,8, // SKINCOLOR_CREAMSICLE + SKINCOLOR_BLUE,8, // SKINCOLOR_ORANGE + SKINCOLOR_BLUEBERRY,8, // SKINCOLOR_PUMPKIN + SKINCOLOR_NAVY,6, // SKINCOLOR_ROSEWOOD + SKINCOLOR_JET,8, // SKINCOLOR_BURGUNDY + SKINCOLOR_LIME,8, // SKINCOLOR_TANGERINE + SKINCOLOR_CYAN,8, // SKINCOLOR_PEACH + SKINCOLOR_CERULEAN,8, // SKINCOLOR_CARAMEL + SKINCOLOR_COPPER,10, // SKINCOLOR_CREAM + SKINCOLOR_SLATE,8, // SKINCOLOR_GOLD + SKINCOLOR_PLATINUM,6, // SKINCOLOR_ROYAL + SKINCOLOR_STEEL,8, // SKINCOLOR_BRONZE + SKINCOLOR_CREAM,6, // SKINCOLOR_COPPER + SKINCOLOR_AQUA,8, // SKINCOLOR_YELLOW + SKINCOLOR_KETCHUP,8, // SKINCOLOR_MUSTARD + SKINCOLOR_TEAL,8, // SKINCOLOR_OLIVE + SKINCOLOR_ROBOHOOD,8, // SKINCOLOR_VOMIT + SKINCOLOR_LAVENDER,6, // SKINCOLOR_GARDEN + SKINCOLOR_TANGERINE,8, // SKINCOLOR_LIME + SKINCOLOR_CHERRY,8, // SKINCOLOR_HANDHELD + SKINCOLOR_SALMON,8, // SKINCOLOR_TEA + SKINCOLOR_PINK,6, // SKINCOLOR_PISTACHIO + SKINCOLOR_ROSE,8, // SKINCOLOR_MOSS + SKINCOLOR_FAIRY,10, // SKINCOLOR_CAMOUFLAGE + SKINCOLOR_VOMIT,8, // SKINCOLOR_ROBOHOOD + SKINCOLOR_RASPBERRY,8, // SKINCOLOR_MINT + SKINCOLOR_RED,8, // SKINCOLOR_GREEN + SKINCOLOR_CRIMSON,8, // SKINCOLOR_PINETREE + SKINCOLOR_PURPLE,8, // SKINCOLOR_EMERALD + SKINCOLOR_BYZANTIUM,8, // SKINCOLOR_SWAMP + SKINCOLOR_POMEGRANATE,8, // SKINCOLOR_DREAM + SKINCOLOR_NOVA,8, // SKINCOLOR_PLAGUE + SKINCOLOR_SCARLET,10, // SKINCOLOR_ALGAE + SKINCOLOR_FLAME,8, // SKINCOLOR_CARIBBEAN + SKINCOLOR_YELLOW,8, // SKINCOLOR_AQUA + SKINCOLOR_OLIVE,8, // SKINCOLOR_TEAL + SKINCOLOR_PEACH,8, // SKINCOLOR_CYAN + SKINCOLOR_LILAC,10, // SKINCOLOR_JAWZ + SKINCOLOR_CARAMEL,8, // SKINCOLOR_CERULEAN + SKINCOLOR_ROSEWOOD,8, // SKINCOLOR_NAVY + SKINCOLOR_ROYAL,8, // SKINCOLOR_PLATINUM + SKINCOLOR_GOLD,10, // SKINCOLOR_SLATE + SKINCOLOR_BRONZE,10, // SKINCOLOR_STEEL + SKINCOLOR_BRICK,10, // SKINCOLOR_RUST + SKINCOLOR_BURGUNDY,8, // SKINCOLOR_JET + SKINCOLOR_RUBY,6, // SKINCOLOR_SAPPHIRE + SKINCOLOR_CREAMSICLE,8, // SKINCOLOR_PERIWINKLE + SKINCOLOR_ORANGE,8, // SKINCOLOR_BLUE + SKINCOLOR_PUMPKIN,8, // SKINCOLOR_BLUEBERRY + SKINCOLOR_PLAGUE,10, // SKINCOLOR_NOVA + SKINCOLOR_FUCHSIA,11, // SKINCOLOR_PASTEL + SKINCOLOR_SUNSET,10, // SKINCOLOR_MOONSLAM + SKINCOLOR_MAUVE,10, // SKINCOLOR_ULTRAVIOLET + SKINCOLOR_DAWN,6, // SKINCOLOR_DUSK + SKINCOLOR_EMERALD,8, // SKINCOLOR_PURPLE + SKINCOLOR_PASTEL,11, // SKINCOLOR_FUCHSIA + SKINCOLOR_MAROON,8, // SKINCOLOR_TOXIC + SKINCOLOR_ULTRAVIOLET,8, // SKINCOLOR_MAUVE + SKINCOLOR_GARDEN,6, // SKINCOLOR_LAVENDER + SKINCOLOR_SWAMP,8, // SKINCOLOR_BYZANTIUM + SKINCOLOR_DREAM,8, // SKINCOLOR_POMEGRANATE + SKINCOLOR_JAWZ,6 // SKINCOLOR_LILAC }; -UINT8 colortranslations[MAXSKINCOLORS][16] = { +UINT8 colortranslations[MAXTRANSLATIONS][16] = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // SKINCOLOR_NONE - {120, 120, 120, 120, 0, 1, 3, 4, 6, 7, 10, 14, 18, 22, 25, 28}, // SKINCOLOR_WHITE - { 0, 1, 2, 4, 5, 7, 8, 10, 13, 15, 18, 20, 23, 25, 28, 30}, // SKINCOLOR_SILVER + {120, 120, 120, 120, 0, 2, 5, 8, 9, 11, 14, 17, 20, 22, 25, 28}, // SKINCOLOR_WHITE + { 0, 1, 2, 3, 5, 7, 9, 12, 13, 15, 18, 20, 23, 25, 27, 30}, // SKINCOLOR_SILVER { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31}, // SKINCOLOR_GREY - { 12, 14, 16, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}, // SKINCOLOR_NICKEL - { 16, 17, 19, 21, 22, 24, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31}, // SKINCOLOR_BLACK + { 3, 5, 8, 11, 15, 17, 19, 21, 23, 24, 25, 26, 27, 29, 30, 31}, // SKINCOLOR_NICKEL + { 4, 7, 11, 15, 20, 22, 24, 27, 28, 28, 28, 29, 29, 30, 30, 31}, // SKINCOLOR_BLACK + {120, 120, 121, 121, 122, 123, 10, 14, 16, 18, 20, 22, 24, 26, 28, 31}, // SKINCOLOR_FAIRY + {120, 96, 97, 98, 99, 71, 32, 11, 13, 16, 18, 21, 23, 26, 28, 31}, // SKINCOLOR_POPCORN { 0, 1, 3, 5, 7, 9, 34, 36, 38, 40, 42, 44, 60, 61, 62, 63}, // SKINCOLOR_SEPIA - { 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47}, // SKINCOLOR_BEIGE - { 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63}, // SKINCOLOR_BROWN - { 51, 52, 53, 55, 56, 57, 58, 60, 61, 63, 28, 28, 29, 29, 30, 31}, // SKINCOLOR_LEATHER - {120, 120, 120, 121, 121, 122, 122, 123, 124, 125, 126, 128, 129, 131, 133, 135}, // SKINCOLOR_SALMON + {120, 65, 67, 69, 32, 34, 36, 38, 40, 42, 44, 45, 46, 47, 62, 63}, // SKINCOLOR_BEIGE + { 67, 70, 73, 76, 48, 49, 51, 53, 54, 56, 58, 59, 61, 63, 29, 30}, // SKINCOLOR_BROWN + { 72, 76, 48, 51, 53, 55, 57, 59, 61, 63, 28, 28, 29, 29, 30, 31}, // SKINCOLOR_LEATHER + {120, 120, 120, 121, 121, 122, 123, 124, 126, 127, 129, 131, 133, 135, 137, 139}, // SKINCOLOR_SALMON {120, 121, 121, 122, 144, 145, 146, 147, 148, 149, 150, 151, 134, 136, 138, 140}, // SKINCOLOR_PINK {144, 145, 146, 147, 148, 149, 150, 151, 134, 135, 136, 137, 138, 139, 140, 141}, // SKINCOLOR_ROSE - {121, 122, 145, 146, 147, 149, 131, 132, 133, 134, 135, 197, 197, 198, 199, 255}, // SKINCOLOR_RUBY - {120, 121, 122, 123, 124, 125, 126, 127, 128, 130, 131, 133, 134, 136, 137, 139}, // SKINCOLOR_RASPBERRY - {125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140}, // SKINCOLOR_RED - {130, 131, 132, 133, 134, 136, 137, 138, 139, 139, 140, 140, 141, 141, 142, 143}, // SKINCOLOR_CRIMSON - {104, 113, 113, 85, 86, 88, 128, 129, 131, 133, 134, 136, 138, 139, 141, 143}, // SKINCOLOR_KETCHUP + { 64, 67, 70, 73, 146, 147, 148, 150, 118, 118, 119, 119, 156, 159, 141, 143}, // SKINCOLOR_BRICK + {120, 121, 144, 145, 147, 149, 132, 133, 134, 136, 198, 198, 199, 255, 30, 31}, // SKINCOLOR_RUBY + {120, 121, 122, 123, 124, 125, 126, 127, 128, 130, 131, 134, 136, 137, 139, 140}, // SKINCOLOR_RASPBERRY + {120, 65, 67, 69, 71, 124, 125, 127, 132, 133, 135, 136, 138, 139, 140, 141}, // SKINCOLOR_CHERRY + {122, 123, 124, 126, 129, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142}, // SKINCOLOR_RED + {123, 125, 128, 131, 133, 135, 136, 138, 140, 140, 141, 141, 142, 142, 143, 31}, // SKINCOLOR_CRIMSON + {123, 124, 126, 128, 132, 135, 137, 27, 28, 28, 28, 29, 29, 30, 30, 31}, // SKINCOLOR_MAROON + {120, 97, 112, 113, 113, 85, 87, 126, 149, 150, 151, 252, 253, 254, 255, 29}, // SKINCOLOR_FLAME + { 99, 113, 113, 84, 85, 87, 126, 128, 130, 196, 197, 198, 199, 240, 243, 246}, // SKINCOLOR_SCARLET + {103, 113, 113, 84, 85, 88, 127, 130, 131, 133, 134, 136, 138, 139, 141, 143}, // SKINCOLOR_KETCHUP {120, 121, 122, 123, 124, 147, 147, 148, 90, 91, 92, 93, 94, 95, 152, 154}, // SKINCOLOR_DAWN + { 98, 112, 113, 84, 85, 87, 89, 149, 150, 251, 252, 206, 238, 240, 243, 246}, // SKINCOLOR_SUNSET {120, 120, 80, 80, 81, 82, 83, 83, 84, 85, 86, 88, 89, 91, 93, 95}, // SKINCOLOR_CREAMSICLE { 80, 81, 82, 83, 84, 85, 86, 88, 89, 91, 94, 95, 154, 156, 158, 159}, // SKINCOLOR_ORANGE - { 84, 85, 86, 87, 88, 90, 92, 93, 94, 95, 152, 153, 154, 156, 157, 159}, // SKINCOLOR_PUMPKIN - { 90, 91, 92, 93, 94, 152, 153, 154, 155, 156, 157, 158, 159, 139, 141, 143}, // SKINCOLOR_ROSEWOOD - { 94, 95, 152, 153, 154, 156, 157, 159, 141, 141, 141, 142, 142, 143, 143, 31}, // SKINCOLOR_BURGUNDY + { 82, 83, 84, 85, 87, 89, 90, 92, 94, 152, 153, 155, 157, 159, 141, 142}, // SKINCOLOR_PUMPKIN + { 83, 85, 88, 90, 92, 94, 152, 153, 154, 156, 157, 159, 140, 141, 142, 143}, // SKINCOLOR_ROSEWOOD + { 84, 86, 89, 91, 152, 154, 155, 157, 158, 159, 140, 141, 142, 143, 31, 31}, // SKINCOLOR_BURGUNDY { 98, 98, 112, 112, 113, 113, 84, 85, 87, 89, 91, 93, 95, 153, 156, 159}, // SKINCOLOR_TANGERINE - { 64, 65, 67, 68, 70, 71, 73, 74, 76, 77, 79, 48, 50, 53, 56, 59}, // SKINCOLOR_PEACH + {120, 80, 66, 70, 72, 76, 148, 149, 150, 151, 153, 154, 156, 61, 62, 63}, // SKINCOLOR_PEACH { 64, 66, 68, 70, 72, 74, 76, 78, 48, 50, 52, 54, 56, 58, 60, 62}, // SKINCOLOR_CARAMEL + {120, 120, 96, 96, 97, 82, 84, 77, 50, 54, 57, 59, 61, 63, 29, 31}, // SKINCOLOR_CREAM {112, 112, 112, 113, 113, 114, 114, 115, 115, 116, 116, 117, 117, 118, 118, 119}, // SKINCOLOR_GOLD + { 97, 112, 113, 113, 114, 78, 53, 252, 252, 253, 253, 254, 255, 29, 30, 31}, // SKINCOLOR_ROYAL {112, 113, 114, 115, 116, 117, 118, 119, 156, 157, 158, 159, 141, 141, 142, 143}, // SKINCOLOR_BRONZE + {120, 99, 113, 114, 116, 117, 119, 61, 63, 28, 28, 29, 29, 30, 30, 31}, // SKINCOLOR_COPPER { 96, 97, 98, 100, 101, 102, 104, 113, 114, 115, 116, 117, 118, 119, 156, 159}, // SKINCOLOR_YELLOW { 96, 98, 99, 112, 113, 114, 114, 106, 106, 107, 107, 108, 108, 109, 110, 111}, // SKINCOLOR_MUSTARD {105, 105, 105, 106, 106, 107, 107, 108, 108, 109, 109, 110, 110, 111, 111, 31}, // SKINCOLOR_OLIVE {121, 144, 145, 72, 73, 84, 114, 115, 107, 108, 109, 183, 223, 207, 30, 246}, // SKINCOLOR_VOMIT { 98, 99, 112, 101, 113, 114, 106, 179, 180, 180, 181, 182, 183, 173, 174, 175}, // SKINCOLOR_GARDEN { 96, 97, 99, 100, 102, 104, 160, 162, 164, 166, 168, 171, 223, 223, 207, 31}, // SKINCOLOR_LIME + { 98, 104, 105, 105, 106, 167, 168, 169, 170, 171, 172, 173, 174, 175, 30, 31}, // SKINCOLOR_HANDHELD {120, 120, 176, 176, 176, 177, 177, 178, 178, 179, 179, 180, 180, 181, 182, 183}, // SKINCOLOR_TEA {120, 120, 176, 176, 177, 177, 178, 179, 165, 166, 167, 168, 169, 170, 171, 172}, // SKINCOLOR_PISTACHIO - {176, 176, 177, 178, 165, 166, 167, 167, 168, 169, 182, 182, 182, 183, 183, 183}, // SKINCOLOR_ROBOHOOD {178, 178, 178, 179, 179, 180, 181, 182, 183, 172, 172, 173, 173, 174, 174, 175}, // SKINCOLOR_MOSS + { 64, 66, 69, 32, 34, 37, 40, 182, 171, 172, 172, 173, 173, 174, 174, 175}, // SKINCOLOR_CAMOUFLAGE + {120, 176, 160, 165, 167, 168, 169, 182, 182, 171, 60, 61, 63, 29, 30, 31}, // SKINCOLOR_ROBOHOOD {120, 176, 176, 176, 177, 163, 164, 165, 167, 221, 221, 222, 223, 207, 207, 31}, // SKINCOLOR_MINT {160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175}, // SKINCOLOR_GREEN - {160, 161, 162, 164, 165, 167, 169, 170, 171, 171, 172, 173, 174, 175, 30, 31}, // SKINCOLOR_PINETREE + {161, 163, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 30, 30, 31}, // SKINCOLOR_PINETREE {160, 184, 184, 185, 185, 186, 186, 187, 187, 188, 188, 189, 189, 190, 191, 175}, // SKINCOLOR_EMERALD - {186, 187, 188, 188, 188, 189, 189, 190, 190, 191, 175, 175, 30, 30, 31, 31}, // SKINCOLOR_SWAMP + {160, 184, 185, 186, 187, 188, 189, 190, 191, 191, 29, 29, 30, 30, 31, 31}, // SKINCOLOR_SWAMP {120, 120, 80, 80, 81, 177, 162, 164, 228, 228, 204, 204, 205, 205, 206, 207}, // SKINCOLOR_DREAM + {176, 160, 184, 185, 186, 187, 188, 230, 230, 206, 206, 207, 28, 29, 30, 31}, // SKINCOLOR_PLAGUE + {208, 209, 210, 211, 213, 220, 216, 167, 168, 188, 188, 189, 190, 191, 30, 31}, // SKINCOLOR_ALGAE + {120, 176, 177, 160, 185, 220, 216, 217, 221, 230, 206, 206, 254, 255, 29, 31}, // SKINCOLOR_CARIBBEAN {120, 208, 208, 210, 212, 214, 220, 220, 220, 221, 221, 222, 222, 223, 223, 191}, // SKINCOLOR_AQUA {210, 213, 220, 220, 220, 216, 216, 221, 221, 221, 222, 222, 223, 223, 191, 31}, // SKINCOLOR_TEAL {120, 120, 208, 208, 209, 210, 211, 212, 213, 215, 216, 217, 218, 219, 222, 223}, // SKINCOLOR_CYAN {120, 120, 208, 209, 210, 226, 215, 216, 217, 229, 229, 205, 205, 206, 207, 31}, // SKINCOLOR_JAWZ {208, 209, 211, 213, 215, 216, 216, 217, 217, 218, 218, 219, 205, 206, 207, 207}, // SKINCOLOR_CERULEAN {211, 212, 213, 215, 216, 218, 219, 205, 206, 206, 207, 207, 28, 29, 30, 31}, // SKINCOLOR_NAVY + {120, 0, 0, 200, 200, 201, 11, 14, 17, 218, 222, 223, 238, 240, 243, 246}, // SKINCOLOR_PLATINUM {120, 120, 200, 200, 200, 201, 201, 201, 202, 202, 202, 203, 204, 205, 206, 207}, // SKINCOLOR_SLATE {120, 200, 200, 201, 201, 202, 202, 203, 203, 204, 204, 205, 205, 206, 207, 31}, // SKINCOLOR_STEEL + { 64, 66, 68, 70, 32, 34, 36, 203, 204, 205, 24, 25, 26, 28, 29, 31}, // SKINCOLOR_RUST {225, 226, 227, 228, 229, 205, 205, 206, 207, 207, 28, 28, 29, 29, 30, 31}, // SKINCOLOR_JET {208, 209, 211, 213, 215, 217, 229, 230, 232, 234, 236, 238, 240, 242, 244, 246}, // SKINCOLOR_SAPPHIRE - {120, 224, 225, 226, 226, 227, 228, 228, 229, 230, 231, 234, 235, 237, 239, 241}, // SKINCOLOR_PERIWINKLE - {224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239}, // SKINCOLOR_BLUE - {228, 229, 230, 231, 232, 233, 234, 235, 237, 238, 239, 240, 242, 243, 244, 245}, // SKINCOLOR_BLUEBERRY - {192, 192, 248, 249, 250, 251, 204, 204, 205, 205, 206, 206, 207, 29, 30, 31}, // SKINCOLOR_DUSK - {192, 192, 192, 193, 193, 194, 194, 195, 195, 196, 196, 197, 197, 198, 198, 199}, // SKINCOLOR_PURPLE - {248, 248, 248, 249, 249, 250, 250, 251, 251, 252, 252, 253, 253, 254, 254, 255}, // SKINCOLOR_LAVENDER - {192, 248, 249, 250, 251, 252, 253, 254, 255, 255, 29, 29, 30, 30, 31, 31}, // SKINCOLOR_BYZANTIUM + {120, 120, 224, 225, 226, 202, 227, 228, 229, 230, 231, 233, 235, 237, 239, 241}, // SKINCOLOR_PERIWINKLE + {224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 235, 236, 238, 242, 244, 246}, // SKINCOLOR_BLUE + {226, 228, 229, 230, 232, 233, 235, 237, 239, 240, 242, 244, 246, 31, 31, 31}, // SKINCOLOR_BLUEBERRY + {120, 112, 82, 83, 84, 124, 248, 228, 228, 204, 205, 206, 207, 29, 30, 31}, // SKINCOLOR_NOVA + {120, 208, 209, 210, 211, 226, 202, 249, 194, 195, 196, 197, 198, 199, 255, 30}, // SKINCOLOR_PASTEL + {120, 224, 201, 226, 202, 249, 250, 196, 197, 198, 199, 140, 141, 142, 143, 31}, // SKINCOLOR_MOONSLAM + {120, 64, 81, 122, 192, 249, 203, 221, 221, 219, 219, 223, 223, 191, 191, 31}, // SKINCOLOR_ULTRAVIOLET + {121, 145, 192, 249, 250, 251, 204, 204, 205, 205, 206, 206, 207, 29, 30, 31}, // SKINCOLOR_DUSK + {120, 96, 64, 121, 67, 144, 123, 192, 193, 194, 195, 196, 197, 198, 199, 30}, // SKINCOLOR_BUBBLEGUM + {121, 145, 192, 192, 193, 194, 195, 196, 196, 197, 197, 198, 198, 199, 30, 31}, // SKINCOLOR_PURPLE + {120, 122, 124, 125, 126, 150, 196, 197, 198, 198, 199, 199, 240, 242, 244, 246}, // SKINCOLOR_FUCHSIA + {120, 120, 176, 176, 177, 6, 8, 10, 249, 250, 196, 197, 198, 199, 143, 31}, // SKINCOLOR_TOXIC + { 96, 97, 98, 112, 113, 73, 146, 248, 249, 251, 205, 205, 206, 207, 29, 31}, // SKINCOLOR_MAUVE + {121, 145, 192, 248, 249, 250, 251, 252, 252, 253, 253, 254, 254, 255, 30, 31}, // SKINCOLOR_LAVENDER + {144, 248, 249, 250, 251, 252, 253, 254, 255, 255, 29, 29, 30, 30, 31, 31}, // SKINCOLOR_BYZANTIUM {144, 145, 146, 147, 148, 149, 150, 251, 251, 252, 252, 253, 254, 255, 29, 30}, // SKINCOLOR_POMEGRANATE {120, 120, 120, 121, 121, 122, 122, 123, 192, 248, 249, 250, 251, 252, 253, 254}, // SKINCOLOR_LILAC - /* Removed Colours - {120, 121, 123, 124, 126, 127, 129, 130, 132, 133, 135, 136, 138, 139, 141, 143}, // old SKINCOLOR_RUBY, removed for other colors - {224, 225, 226, 228, 229, 231, 232, 234, 235, 237, 238, 240, 241, 243, 244, 246}, // old SKINCOLOR_SAPPHIRE, removed for other colors - { 72, 73, 74, 75, 76, 77, 78, 79, 48, 49, 50, 51, 52, 53, 54, 55}, // old SKINCOLOR_CARAMEL, new Caramel was previously Shiny Caramel - {215, 216, 217, 218, 204, 205, 206, 237, 238, 239, 240, 241, 242, 243, 244, 245}, // old SKINCOLOR_NAVY, too similar to Jet - { 80, 81, 83, 85, 86, 88, 90, 91, 93, 95, 152, 153, 154, 156, 157, 159}, // SKINCOLOR_AMBER, removed for other colors - {160, 160, 160, 184, 184, 184, 185, 185, 185, 186, 187, 187, 188, 188, 189, 190}, // SKINCOLOR_JADE, removed for other colors - {224, 225, 226, 212, 213, 213, 214, 215, 220, 221, 172, 222, 173, 223, 174, 175}, // SKINCOLOR_FROST, merged into Aqua - { 96, 97, 99, 100, 102, 104, 105, 105, 106, 107, 107, 108, 109, 109, 110, 111}, // SKINCOLOR_CANARY, replaced with Mustard - {192, 193, 194, 195, 196, 197, 198, 199, 255, 255, 29, 29, 30, 30, 31, 31}, // SKINCOLOR_INDIGO, too similar to Byzantium - { 1, 145, 125, 73, 83, 114, 106, 180, 187, 168, 219, 205, 236, 206, 199, 255}, // SKINCOLOR_RAINBOW, is Vomit 2.0 - */ + {120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 96, 100, 104, 113, 116, 119}, // SKINCOLOR_SUPER1 + {120, 120, 120, 120, 120, 120, 120, 120, 96, 98, 101, 104, 113, 115, 117, 119}, // SKINCOLOR_SUPER2 + {120, 120, 120, 120, 120, 120, 96, 98, 100, 102, 104, 113, 114, 116, 117, 119}, // SKINCOLOR_SUPER3 + {120, 120, 120, 120, 96, 97, 99, 100, 102, 104, 113, 114, 115, 116, 117, 119}, // SKINCOLOR_SUPER4 + {120, 120, 96, 120, 120, 120, 120, 120, 104, 113, 114, 115, 116, 117, 118, 119}, // SKINCOLOR_SUPER5 + {120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 80, 82, 85, 115, 117, 119}, // SKINCOLOR_TSUPER1 + {120, 120, 120, 120, 120, 120, 120, 120, 80, 81, 83, 85, 115, 116, 117, 119}, // SKINCOLOR_TSUPER2 + {120, 120, 120, 120, 120, 120, 80, 81, 82, 83, 85, 115, 116, 117, 118, 119}, // SKINCOLOR_TSUPER3 + {120, 120, 120, 120, 80, 81, 82, 83, 84, 85, 115, 115, 116, 117, 118, 119}, // SKINCOLOR_TSUPER4 + {120, 120, 80, 80, 81, 82, 83, 84, 85, 115, 115, 116, 117, 117, 118, 119}, // SKINCOLOR_TSUPER5 + {120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 121, 123, 125, 127, 129, 132}, // SKINCOLOR_KSUPER1 + {120, 120, 120, 120, 120, 120, 120, 120, 121, 122, 124, 125, 127, 128, 130, 132}, // SKINCOLOR_KSUPER2 + {120, 120, 120, 120, 120, 120, 121, 122, 123, 124, 125, 127, 128, 129, 130, 132}, // SKINCOLOR_KSUPER3 + {120, 120, 120, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132}, // SKINCOLOR_KSUPER4 + {120, 120, 121, 121, 122, 123, 124, 125, 126, 126, 127, 128, 129, 130, 131, 132}, // SKINCOLOR_KSUPER5 + {120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 0, 122, 124, 248, 251, 255}, // SKINCOLOR_PSUPER1 + {120, 120, 120, 120, 120, 120, 120, 120, 0, 121, 122, 124, 248, 250, 252, 255}, // SKINCOLOR_PSUPER2 + {120, 120, 120, 120, 120, 120, 0, 121, 122, 123, 124, 248, 249, 251, 253, 255}, // SKINCOLOR_PSUPER3 + {120, 120, 120, 120, 0, 121, 122, 123, 124, 248, 249, 250, 251, 252, 253, 255}, // SKINCOLOR_PSUPER4 + {120, 120, 0, 121, 122, 123, 124, 248, 248, 249, 250, 251, 252, 253, 254, 255}, // SKINCOLOR_PSUPER5 + {120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 224, 225, 227, 228, 230, 232}, // SKINCOLOR_BSUPER1 + {120, 120, 120, 120, 120, 120, 120, 120, 224, 225, 226, 227, 228, 229, 230, 232}, // SKINCOLOR_BSUPER2 + {120, 120, 120, 120, 120, 120, 224, 224, 225, 226, 227, 228, 229, 230, 231, 232}, // SKINCOLOR_BSUPER3 + {120, 120, 120, 120, 224, 224, 225, 226, 226, 227, 228, 229, 229, 230, 231, 232}, // SKINCOLOR_BSUPER4 + {120, 120, 224, 224, 225, 225, 226, 227, 227, 228, 228, 229, 230, 230, 231, 232}, // SKINCOLOR_BSUPER5 + {120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 208, 210, 212, 215, 220, 222}, // SKINCOLOR_ASUPER1 + {120, 120, 120, 120, 120, 120, 120, 120, 208, 209, 211, 213, 215, 220, 221, 223}, // SKINCOLOR_ASUPER2 + {120, 120, 120, 120, 120, 120, 208, 209, 210, 211, 212, 213, 215, 220, 221, 223}, // SKINCOLOR_ASUPER3 + {120, 120, 120, 120, 208, 209, 210, 211, 212, 213, 214, 215, 220, 221, 222, 223}, // SKINCOLOR_ASUPER4 + {120, 120, 208, 208, 209, 210, 211, 211, 212, 213, 214, 215, 220, 221, 222, 223}, // SKINCOLOR_ASUPER5 + {120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 176, 160, 163, 167, 171, 175}, // SKINCOLOR_GSUPER1 + {120, 120, 120, 120, 120, 120, 120, 120, 176, 176, 160, 163, 166, 169, 172, 175}, // SKINCOLOR_GSUPER2 + {120, 120, 120, 120, 120, 120, 176, 176, 160, 162, 164, 166, 168, 170, 172, 175}, // SKINCOLOR_GSUPER3 + {120, 120, 120, 120, 176, 176, 176, 160, 161, 163, 165, 167, 169, 171, 173, 175}, // SKINCOLOR_GSUPER4 + {120, 120, 176, 176, 176, 160, 161, 163, 164, 166, 167, 169, 170, 172, 173, 175}, // SKINCOLOR_GSUPER5 + {120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120}, // SKINCOLOR_WSUPER1 + {120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 0, 4, 9}, // SKINCOLOR_WSUPER2 + {120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 0, 2, 4, 6, 8, 11}, // SKINCOLOR_WSUPER3 + {120, 120, 120, 120, 120, 120, 120, 0, 1, 3, 4, 6, 8, 9, 11, 13}, // SKINCOLOR_WSUPER4 + {120, 120, 120, 120, 0, 1, 2, 4, 5, 6, 8, 9, 10, 12, 13, 15}, // SKINCOLOR_WSUPER5 + {120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 96, 98, 99, 81, 73, 79}, // SKINCOLOR_CSUPER1 + {120, 120, 120, 120, 120, 120, 120, 120, 96, 97, 98, 81, 81, 71, 75, 79}, // SKINCOLOR_CSUPER2 + {120, 120, 120, 120, 120, 120, 96, 97, 98, 99, 81, 81, 70, 73, 76, 79}, // SKINCOLOR_CSUPER3 + {120, 120, 120, 120, 96, 96, 97, 98, 99, 81, 81, 70, 72, 74, 76, 79}, // SKINCOLOR_CSUPER4 + {120, 120, 96, 96, 97, 98, 98, 99, 81, 81, 69, 71, 73, 75, 77, 79}, // SKINCOLOR_CSUPER5 }; // Define for getting accurate color brightness readings according to how the human eye sees them. @@ -443,6 +553,7 @@ void K_RegisterKartStuff(void) CV_RegisterVar(&cv_kartdebugcheckpoint); CV_RegisterVar(&cv_kartdebugnodes); + CV_RegisterVar(&cv_kartdebugcolorize); } //} @@ -496,17 +607,17 @@ boolean K_IsPlayerWanted(player_t *player) static INT32 K_KartItemOddsRace[NUMKARTRESULTS][10] = { //P-Odds 0 1 2 3 4 5 6 7 8 9 - /*Sneaker*/ {20, 0, 0, 4, 6, 6, 0, 0, 0, 0 }, // Sneaker - /*Rocket Sneaker*/ { 0, 0, 0, 0, 0, 1, 3, 5, 3, 0 }, // Rocket Sneaker - /*Invincibility*/ { 0, 0, 0, 0, 0, 1, 4, 6,14, 0 }, // Invincibility - /*Banana*/ { 0,10, 4, 2, 1, 0, 0, 0, 0, 0 }, // Banana + /*Sneaker*/ {20, 0, 0, 4, 6, 7, 0, 0, 0, 0 }, // Sneaker + /*Rocket Sneaker*/ { 0, 0, 0, 0, 0, 1, 4, 5, 3, 0 }, // Rocket Sneaker + /*Invincibility*/ { 0, 0, 0, 0, 0, 1, 4, 6,10, 0 }, // Invincibility + /*Banana*/ { 0, 9, 4, 2, 1, 0, 0, 0, 0, 0 }, // Banana /*Eggman Monitor*/ { 0, 3, 2, 1, 0, 0, 0, 0, 0, 0 }, // Eggman Monitor - /*Orbinaut*/ { 0, 8, 6, 4, 2, 0, 0, 0, 0, 0 }, // Orbinaut + /*Orbinaut*/ { 0, 7, 6, 4, 2, 0, 0, 0, 0, 0 }, // Orbinaut /*Jawz*/ { 0, 0, 3, 2, 1, 1, 0, 0, 0, 0 }, // Jawz /*Mine*/ { 0, 0, 2, 2, 1, 0, 0, 0, 0, 0 }, // Mine /*Ballhog*/ { 0, 0, 0, 2, 1, 0, 0, 0, 0, 0 }, // Ballhog /*Self-Propelled Bomb*/ { 0, 0, 1, 2, 3, 4, 2, 2, 0,20 }, // Self-Propelled Bomb - /*Grow*/ { 0, 0, 0, 0, 0, 1, 3, 5, 3, 0 }, // Grow + /*Grow*/ { 0, 0, 0, 0, 0, 0, 2, 5, 7, 0 }, // Grow /*Shrink*/ { 0, 0, 0, 0, 0, 0, 0, 2, 0, 0 }, // Shrink /*Thunder Shield*/ { 0, 1, 2, 0, 0, 0, 0, 0, 0, 0 }, // Thunder Shield /*Hyudoro*/ { 0, 0, 0, 0, 1, 2, 1, 0, 0, 0 }, // Hyudoro @@ -556,6 +667,11 @@ static INT32 K_KartItemOddsBattle[NUMKARTRESULTS][6] = */ static void K_KartGetItemResult(player_t *player, SINT8 getitem) { + if (getitem == KITEM_SPB || getitem == KITEM_SHRINK) // Indirect items + indirectitemcooldown = 20*TICRATE; + if (getitem == KITEM_HYUDORO) // Hyudoro cooldown + hyubgone = 5*TICRATE; + switch (getitem) { // Special roulettes first, then the generic ones are handled by default @@ -583,10 +699,6 @@ static void K_KartGetItemResult(player_t *player, SINT8 getitem) player->kartstuff[k_itemtype] = KITEM_JAWZ; player->kartstuff[k_itemamount] = 2; break; - case KITEM_SPB: - case KITEM_SHRINK: // Indirect items - indirectitemcooldown = 20*TICRATE; - /* FALLTHRU */ default: if (getitem <= 0 || getitem >= NUMKARTRESULTS) // Sad (Fallback) { @@ -608,15 +720,16 @@ static void K_KartGetItemResult(player_t *player, SINT8 getitem) \return void */ -static INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed) +static INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed, boolean spbrush) { const INT32 distvar = (64*14); INT32 newodds; INT32 i; - UINT8 pingame = 0, pexiting = 0, pinvin = 0; + UINT8 pingame = 0, pexiting = 0; + boolean thunderisout = false; SINT8 first = -1, second = -1; INT32 secondist = 0; - boolean itemenabled[NUMKARTRESULTS] = { + boolean itemenabled[NUMKARTRESULTS-1] = { cv_sneaker.value, cv_rocketsneaker.value, cv_invincibility.value, @@ -631,6 +744,7 @@ static INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed) cv_shrink.value, cv_thundershield.value, cv_hyudoro.value, + cv_pogospring.value, cv_kitchensink.value, cv_triplesneaker.value, cv_triplebanana.value, @@ -640,7 +754,9 @@ static INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed) cv_dualjawz.value }; - if (!itemenabled[item] && !modeattacking) + I_Assert(item > KITEM_NONE); // too many off by one scenarioes. + + if (!itemenabled[item-1] && !modeattacking) return 0; if (G_BattleGametype()) @@ -648,21 +764,25 @@ static INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed) else newodds = K_KartItemOddsRace[item-1][pos]; + // Base multiplication to ALL item odds to simulate fractional precision + newodds *= 4; + for (i = 0; i < MAXPLAYERS; i++) { if (!playeringame[i] || players[i].spectator) continue; + if (!G_BattleGametype() || players[i].kartstuff[k_bumper]) pingame++; + if (players[i].exiting) pexiting++; + if (players[i].mo) { - if (players[i].kartstuff[k_itemtype] == KITEM_INVINCIBILITY - || players[i].kartstuff[k_itemtype] == KITEM_GROW - || players[i].kartstuff[k_invincibilitytimer] - || players[i].kartstuff[k_growshrinktimer] > 0) - pinvin++; + if (players[i].kartstuff[k_itemtype] == KITEM_THUNDERSHIELD) + thunderisout = true; + if (!G_BattleGametype()) { if (players[i].kartstuff[k_position] == 1 && first == -1) @@ -686,29 +806,29 @@ static INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed) // POWERITEMODDS handles all of the "frantic item" related functionality, for all of our powerful items. // First, it multiplies it by 2 if franticitems is true; easy-peasy. // Next, it multiplies it again if it's in SPB mode and 2nd needs to apply pressure to 1st. - // Then, it multiplies it further if there's less than 5 players in game. - // This is done to make low player count races more fair & interesting. (2P normal would be about halfway between 8P normal and 8P frantic) - // Lastly, it *divides* it by your mashed value, which was determined in K_KartItemRoulette, to punish those who are impatient. -#define POWERITEMODDS(odds) \ + // Then, it multiplies it further if the player count isn't equal to 8. + // This is done to make low player count races more interesting and high player count rates more fair. + // (2P normal would be about halfway between 8P normal and 8P frantic.) + // (This scaling is not done for SPB Rush, so that catchup strength is not weakened.) + // Lastly, it *divides* it by your mashed value, which was determined in K_KartItemRoulette, for lesser items needed in a pinch. + +#define PLAYERSCALING (8 - (spbrush ? 2 : pingame)) + +#define POWERITEMODDS(odds) {\ if (franticitems) \ odds <<= 1; \ - odds = FixedMul(odds<> FRACBITS; \ + odds = FixedMul(odds<> FRACBITS; \ if (mashed > 0) \ - odds = FixedDiv(odds<> FRACBITS \ + odds = FixedDiv(odds<> FRACBITS; \ +} + +#define COOLDOWNONSTART (leveltime < (30*TICRATE)+starttime) switch (item) { - case KITEM_INVINCIBILITY: - case KITEM_GROW: - if (pinvin >= max(1, (pingame+2) / 4)) - newodds = 0; - else - /* FALLTHRU */ case KITEM_ROCKETSNEAKER: case KITEM_JAWZ: - case KITEM_MINE: case KITEM_BALLHOG: - case KITEM_THUNDERSHIELD: case KRITEM_TRIPLESNEAKER: case KRITEM_TRIPLEBANANA: case KRITEM_TENFOLDBANANA: @@ -717,17 +837,34 @@ static INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed) case KRITEM_DUALJAWZ: POWERITEMODDS(newodds); break; + case KITEM_INVINCIBILITY: + case KITEM_MINE: + case KITEM_GROW: + if (COOLDOWNONSTART) + newodds = 0; + else + POWERITEMODDS(newodds); + break; case KITEM_SPB: - //POWERITEMODDS(newodds); if (((indirectitemcooldown > 0) || (pexiting > 0) || (secondist/distvar < 3)) && (pos != 9)) // Force SPB newodds = 0; else - newodds *= min((secondist/distvar)-4, 3); + newodds *= min((secondist/distvar)-4, 3); // POWERITEMODDS(newodds); break; case KITEM_SHRINK: - POWERITEMODDS(newodds); - if ((indirectitemcooldown > 0) || (pingame-1 <= pexiting)) + if ((indirectitemcooldown > 0) || (pingame-1 <= pexiting) || COOLDOWNONSTART) + newodds = 0; + else + POWERITEMODDS(newodds); + break; + case KITEM_THUNDERSHIELD: + if (thunderisout) + newodds = 0; + else + POWERITEMODDS(newodds); + case KITEM_HYUDORO: + if ((hyubgone > 0) || COOLDOWNONSTART) newodds = 0; break; default: @@ -761,9 +898,9 @@ static INT32 K_FindUseodds(player_t *player, fixed_t mashed, INT32 pingame, INT3 break; } - for (j = 0; j < NUMKARTRESULTS; j++) + for (j = 1; j < NUMKARTRESULTS; j++) { - if (K_KartGetItemOdds(i, j, mashed) > 0) + if (K_KartGetItemOdds(i, j, mashed, spbrush) > 0) { available = true; break; @@ -864,11 +1001,12 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) UINT8 pingame = 0; UINT8 roulettestop; INT32 useodds = 0; - INT32 spawnchance[NUMKARTRESULTS * NUMKARTODDS]; - INT32 chance = 0, numchoices = 0; + INT32 spawnchance[NUMKARTRESULTS]; + INT32 totalspawnchance = 0; INT32 bestbumper = 0; fixed_t mashed = 0; boolean dontforcespb = false; + boolean spbrush = false; // This makes the roulette cycle through items - if this is 0, you shouldn't be here. if (player->kartstuff[k_itemroulette]) @@ -961,25 +1099,27 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) return; } + if (G_RaceGametype()) + spbrush = (spbplace != -1 && player->kartstuff[k_position] == spbplace+1); + // Initializes existing spawnchance values - for (i = 0; i < (NUMKARTRESULTS * NUMKARTODDS); i++) + for (i = 0; i < NUMKARTRESULTS; i++) spawnchance[i] = 0; // Split into another function for a debug function below - useodds = K_FindUseodds(player, mashed, pingame, bestbumper, (spbplace != -1 && player->kartstuff[k_position] == spbplace+1), dontforcespb); - -#define SETITEMRESULT(itemnum) \ - for (chance = 0; chance < K_KartGetItemOdds(useodds, itemnum, mashed); chance++) \ - spawnchance[numchoices++] = itemnum + useodds = K_FindUseodds(player, mashed, pingame, bestbumper, spbrush, dontforcespb); for (i = 1; i < NUMKARTRESULTS; i++) - SETITEMRESULT(i); - -#undef SETITEMRESULT + spawnchance[i] = (totalspawnchance += K_KartGetItemOdds(useodds, i, mashed, spbrush)); // Award the player whatever power is rolled - if (numchoices > 0) - K_KartGetItemResult(player, spawnchance[P_RandomKey(numchoices)]); + if (totalspawnchance > 0) + { + totalspawnchance = P_RandomKey(totalspawnchance); + for (i = 0; i < NUMKARTRESULTS && spawnchance[i] <= totalspawnchance; i++); + + K_KartGetItemResult(player, i); + } else { player->kartstuff[k_itemtype] = KITEM_SAD; @@ -1053,7 +1193,7 @@ void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid) mobj_t *fx; fixed_t momdifx, momdify; fixed_t distx, disty; - fixed_t dot, p; + fixed_t dot, force; fixed_t mass1, mass2; if (!mobj1 || !mobj2) @@ -1111,6 +1251,31 @@ void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid) momdifx = mobj1->momx - mobj2->momx; momdify = mobj1->momy - mobj2->momy; + // Adds the OTHER player's momentum times a bunch, for the best chance of getting the correct direction + distx = (mobj1->x + mobj2->momx*3) - (mobj2->x + mobj1->momx*3); + disty = (mobj1->y + mobj2->momy*3) - (mobj2->y + mobj1->momy*3); + + if (distx == 0 && disty == 0) + // if there's no distance between the 2, they're directly on top of each other, don't run this + return; + + { // Normalize distance to the sum of the two objects' radii, since in a perfect world that would be the distance at the point of collision... + fixed_t dist = P_AproxDistance(distx, disty); + fixed_t nx = FixedDiv(distx, dist); + fixed_t ny = FixedDiv(disty, dist); + + dist = dist ? dist : 1; + distx = FixedMul(mobj1->radius+mobj2->radius, nx); + disty = FixedMul(mobj1->radius+mobj2->radius, ny); + + if (momdifx == 0 && momdify == 0) + { + // If there's no momentum difference, they're moving at exactly the same rate. Pretend they moved into each other. + momdifx = -nx; + momdify = -ny; + } + } + // if the speed difference is less than this let's assume they're going proportionately faster from each other if (P_AproxDistance(momdifx, momdify) < (25*mapobjectscale)) { @@ -1121,34 +1286,6 @@ void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid) momdify = FixedMul((25*mapobjectscale), normalisedy); } - // Adds the OTHER player's momentum, so that it reduces the chance of you being "inside" the other object - distx = (mobj1->x + mobj2->momx) - (mobj2->x + mobj1->momx); - disty = (mobj1->y + mobj2->momy) - (mobj2->y + mobj1->momy); - - { // Don't allow dist to get WAY too low, that it pushes you stupidly huge amounts, or backwards... - fixed_t dist = P_AproxDistance(distx, disty); - fixed_t nx = FixedDiv(distx, dist); - fixed_t ny = FixedDiv(disty, dist); - - if (P_AproxDistance(distx, disty) < (3*mobj1->radius)/4) - { - distx = FixedMul((3*mobj1->radius)/4, nx); - disty = FixedMul((3*mobj1->radius)/4, ny); - } - - if (P_AproxDistance(distx, disty) < (3*mobj2->radius)/4) - { - distx = FixedMul((3*mobj2->radius)/4, nx); - disty = FixedMul((3*mobj2->radius)/4, ny); - } - } - - if (distx == 0 && disty == 0) - { - // if there's no distance between the 2, they're directly on top of each other, don't run this - return; - } - dot = FixedMul(momdifx, distx) + FixedMul(momdify, disty); if (dot >= 0) @@ -1157,7 +1294,7 @@ void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid) return; } - p = FixedDiv(dot, FixedMul(distx, distx)+FixedMul(disty, disty)); + force = FixedDiv(dot, FixedMul(distx, distx)+FixedMul(disty, disty)); if (bounce == true && mass2 > 0) // Perform a Goomba Bounce. mobj1->momz = -mobj1->momz; @@ -1172,14 +1309,14 @@ void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid) if (mass2 > 0) { - mobj1->momx = mobj1->momx - FixedMul(FixedMul(FixedDiv(2*mass2, mass1 + mass2), p), distx); - mobj1->momy = mobj1->momy - FixedMul(FixedMul(FixedDiv(2*mass2, mass1 + mass2), p), disty); + mobj1->momx = mobj1->momx - FixedMul(FixedMul(FixedDiv(2*mass2, mass1 + mass2), force), distx); + mobj1->momy = mobj1->momy - FixedMul(FixedMul(FixedDiv(2*mass2, mass1 + mass2), force), disty); } if (mass1 > 0 && solid == false) { - mobj2->momx = mobj2->momx - FixedMul(FixedMul(FixedDiv(2*mass1, mass1 + mass2), p), -distx); - mobj2->momy = mobj2->momy - FixedMul(FixedMul(FixedDiv(2*mass1, mass1 + mass2), p), -disty); + mobj2->momx = mobj2->momx - FixedMul(FixedMul(FixedDiv(2*mass1, mass1 + mass2), force), -distx); + mobj2->momy = mobj2->momy - FixedMul(FixedMul(FixedDiv(2*mass1, mass1 + mass2), force), -disty); } // Do the bump fx when we've CONFIRMED we can bump. @@ -1282,11 +1419,23 @@ static void K_UpdateOffroad(player_t *player) player->kartstuff[k_offroad] = 0; } +// Adds gravity flipping to an object relative to its master and shifts the z coordinate accordingly. +void K_FlipFromObject(mobj_t *mo, mobj_t *master) +{ + mo->eflags = (mo->eflags & ~MFE_VERTICALFLIP)|(master->eflags & MFE_VERTICALFLIP); + mo->flags2 = (mo->flags2 & ~MF2_OBJECTFLIP)|(master->flags2 & MF2_OBJECTFLIP); + + if (mo->eflags & MFE_VERTICALFLIP) + mo->z += master->height - FixedMul(master->scale, mo->height); +} + // These have to go earlier than its sisters because of K_RespawnChecker... void K_MatchGenericExtraFlags(mobj_t *mo, mobj_t *master) { // flipping - mo->eflags = (mo->eflags & ~MFE_VERTICALFLIP)|(master->eflags & MFE_VERTICALFLIP); + // handle z shifting from there too. This is here since there's no reason not to flip us if needed when we do this anyway; + K_FlipFromObject(mo, master); + // visibility (usually for hyudoro) mo->flags2 = (mo->flags2 & ~MF2_DONTDRAW)|(master->flags2 & MF2_DONTDRAW); mo->eflags = (mo->eflags & ~MFE_DRAWONLYFORP1)|(master->eflags & MFE_DRAWONLYFORP1); @@ -1400,7 +1549,7 @@ void K_RespawnChecker(player_t *player) mo->eflags |= MFE_VERTICALFLIP; P_SetTarget(&mo->target, player->mo); mo->angle = newangle+ANGLE_90; - mo->momz = (8*FRACUNIT)*P_MobjFlip(player->mo); + mo->momz = (8<mo); P_SetScale(mo, (mo->destscale = FRACUNIT)); } } @@ -1975,12 +2124,19 @@ void K_SpinPlayer(player_t *player, mobj_t *source, INT32 type, mobj_t *inflicto static void K_RemoveGrowShrink(player_t *player) { player->kartstuff[k_growshrinktimer] = 0; - if (player->kartstuff[k_invincibilitytimer] == 0) - player->mo->color = player->skincolor; - player->mo->scalespeed = mapobjectscale/TICRATE; - player->mo->destscale = mapobjectscale; - if (cv_kartdebugshrink.value && !modeattacking && !player->bot) - player->mo->destscale = (6*player->mo->destscale)/8; + player->kartstuff[k_growcancel] = 0; + + if (player->mo && !P_MobjWasRemoved(player->mo)) + { + if (player->kartstuff[k_invincibilitytimer] == 0) + player->mo->color = player->skincolor; + + player->mo->scalespeed = mapobjectscale/TICRATE; + player->mo->destscale = mapobjectscale; + if (cv_kartdebugshrink.value && !modeattacking && !player->bot) + player->mo->destscale = (6*player->mo->destscale)/8; + } + P_RestoreMusic(player); } @@ -2108,6 +2264,7 @@ void K_ExplodePlayer(player_t *player, mobj_t *source, mobj_t *inflictor) // A b #ifdef HAVE_BLUA boolean force = false; // Used to check if Lua ShouldExplode should get us damaged reguardless of flashtics or heck knows what. UINT8 shouldForce = LUAh_ShouldExplode(player, inflictor, source); + if (P_MobjWasRemoved(player->mo)) return; // mobj was removed (in theory that shouldn't happen) if (shouldForce == 1) @@ -2118,6 +2275,7 @@ void K_ExplodePlayer(player_t *player, mobj_t *source, mobj_t *inflictor) // A b #else static const boolean force = false; #endif + if (G_BattleGametype()) { if (K_IsPlayerWanted(player)) @@ -2148,7 +2306,7 @@ void K_ExplodePlayer(player_t *player, mobj_t *source, mobj_t *inflictor) // A b if (source && source != player->mo && source->player) K_PlayHitEmSound(source); - player->mo->momz = 18*mapobjectscale; + player->mo->momz = 18*mapobjectscale*P_MobjFlip(player->mo); // please stop forgetting mobjflip checks!!!! player->mo->momx = player->mo->momy = 0; player->kartstuff[k_sneakertimer] = 0; @@ -2199,16 +2357,19 @@ void K_ExplodePlayer(player_t *player, mobj_t *source, mobj_t *inflictor) // A b } player->kartstuff[k_spinouttype] = 1; - player->kartstuff[k_spinouttimer] = 2*TICRATE+(TICRATE/2); + player->kartstuff[k_spinouttimer] = (3*TICRATE/2)+2; player->powers[pw_flashing] = K_GetKartFlashing(player); if (inflictor && inflictor->type == MT_SPBEXPLOSION && inflictor->extravalue1) { - player->kartstuff[k_spinouttimer] = ((3*player->kartstuff[k_spinouttimer])/2)+1; + player->kartstuff[k_spinouttimer] = ((5*player->kartstuff[k_spinouttimer])/2)+1; player->mo->momz *= 2; } + if (player->mo->eflags & MFE_UNDERWATER) + player->mo->momz = (117 * player->mo->momz) / 200; + if (player->mo->state != &states[S_KART_SPIN]) P_SetPlayerMobjState(player->mo, S_KART_SPIN); @@ -2385,12 +2546,14 @@ void K_SpawnKartExplosion(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 // Spawns the purely visual explosion void K_SpawnMineExplosion(mobj_t *source, UINT8 color) { - INT32 i, radius, height; - mobj_t *smoldering = P_SpawnMobj(source->x, source->y, source->z, MT_SMOLDERING); mobj_t *dust; mobj_t *truc; INT32 speed, speed2; + INT32 i, radius, height; + mobj_t *smoldering = P_SpawnMobj(source->x, source->y, source->z, MT_SMOLDERING); + K_MatchGenericExtraFlags(smoldering, source); + smoldering->tics = TICRATE*3; radius = source->radius>>FRACBITS; height = source->height>>FRACBITS; @@ -2401,6 +2564,7 @@ void K_SpawnMineExplosion(mobj_t *source, UINT8 color) for (i = 0; i < 32; i++) { dust = P_SpawnMobj(source->x, source->y, source->z, MT_SMOKE); + P_SetMobjState(dust, S_OPAQUESMOKE1); dust->angle = (ANGLE_180/16) * i; P_SetScale(dust, source->scale); dust->destscale = source->scale*10; @@ -2410,6 +2574,7 @@ void K_SpawnMineExplosion(mobj_t *source, UINT8 color) truc = P_SpawnMobj(source->x + P_RandomRange(-radius, radius)*FRACUNIT, source->y + P_RandomRange(-radius, radius)*FRACUNIT, source->z + P_RandomRange(0, height)*FRACUNIT, MT_BOOMEXPLODE); + K_MatchGenericExtraFlags(truc, source); P_SetScale(truc, source->scale); truc->destscale = source->scale*6; truc->scalespeed = source->scale/12; @@ -2417,7 +2582,9 @@ void K_SpawnMineExplosion(mobj_t *source, UINT8 color) truc->momx = P_RandomRange(-speed, speed)*FRACUNIT; truc->momy = P_RandomRange(-speed, speed)*FRACUNIT; speed = FixedMul(20*FRACUNIT, source->scale)>>FRACBITS; - truc->momz = P_RandomRange(-speed, speed)*FRACUNIT; + truc->momz = P_RandomRange(-speed, speed)*FRACUNIT*P_MobjFlip(truc); + if (truc->eflags & MFE_UNDERWATER) + truc->momz = (117 * truc->momz) / 200; truc->color = color; } @@ -2426,6 +2593,7 @@ void K_SpawnMineExplosion(mobj_t *source, UINT8 color) dust = P_SpawnMobj(source->x + P_RandomRange(-radius, radius)*FRACUNIT, source->y + P_RandomRange(-radius, radius)*FRACUNIT, source->z + P_RandomRange(0, height)*FRACUNIT, MT_SMOKE); + P_SetMobjState(dust, S_OPAQUESMOKE1); P_SetScale(dust, source->scale); dust->destscale = source->scale*10; dust->scalespeed = source->scale/12; @@ -2435,6 +2603,7 @@ void K_SpawnMineExplosion(mobj_t *source, UINT8 color) truc = P_SpawnMobj(source->x + P_RandomRange(-radius, radius)*FRACUNIT, source->y + P_RandomRange(-radius, radius)*FRACUNIT, source->z + P_RandomRange(0, height)*FRACUNIT, MT_BOOMPARTICLE); + K_MatchGenericExtraFlags(truc, source); P_SetScale(truc, source->scale); truc->destscale = source->scale*5; truc->scalespeed = source->scale/12; @@ -2443,9 +2612,11 @@ void K_SpawnMineExplosion(mobj_t *source, UINT8 color) truc->momy = P_RandomRange(-speed, speed)*FRACUNIT; speed = FixedMul(15*FRACUNIT, source->scale)>>FRACBITS; speed2 = FixedMul(45*FRACUNIT, source->scale)>>FRACBITS; - truc->momz = P_RandomRange(speed, speed2)*FRACUNIT; + truc->momz = P_RandomRange(speed, speed2)*FRACUNIT*P_MobjFlip(truc); if (P_RandomChance(FRACUNIT/2)) truc->momz = -truc->momz; + if (truc->eflags & MFE_UNDERWATER) + truc->momz = (117 * truc->momz) / 200; truc->tics = TICRATE*2; truc->color = color; } @@ -2717,7 +2888,8 @@ void K_SpawnBoostTrail(player_t *player) flame->fuse = TICRATE*2; flame->destscale = player->mo->scale; P_SetScale(flame, player->mo->scale); - flame->eflags = (flame->eflags & ~MFE_VERTICALFLIP)|(player->mo->eflags & MFE_VERTICALFLIP); // not K_MatchGenericExtraFlags so that a stolen sneaker can be seen + // not K_MatchGenericExtraFlags so that a stolen sneaker can be seen + K_FlipFromObject(flame, player->mo); flame->momx = 8; P_XYMovement(flame); @@ -2750,6 +2922,7 @@ void K_SpawnSparkleTrail(mobj_t *mo) fixed_t newz = mo->z + mo->momz + (P_RandomRange(0, mo->height>>FRACBITS)<target, mo); sparkle->destscale = mo->destscale; P_SetScale(sparkle, mo->scale); - sparkle->eflags = (sparkle->eflags & ~MFE_VERTICALFLIP)|(mo->eflags & MFE_VERTICALFLIP); // not K_MatchGenericExtraFlags so that a stolen invincibility can be seen sparkle->color = mo->color; //sparkle->colorized = mo->colorized; } @@ -2768,17 +2940,30 @@ void K_SpawnSparkleTrail(mobj_t *mo) void K_SpawnWipeoutTrail(mobj_t *mo, boolean translucent) { mobj_t *dust; + angle_t aoff; I_Assert(mo != NULL); I_Assert(!P_MobjWasRemoved(mo)); - dust = P_SpawnMobj(mo->x + (P_RandomRange(-25,25) * mo->scale), mo->y + (P_RandomRange(-25,25) * mo->scale), mo->z, MT_WIPEOUTTRAIL); + if (mo->player) + aoff = (mo->player->frameangle + ANGLE_180); + else + aoff = (mo->angle + ANGLE_180); + + if ((leveltime / 2) & 1) + aoff -= ANGLE_45; + else + aoff += ANGLE_45; + + dust = P_SpawnMobj(mo->x + FixedMul(24*mo->scale, FINECOSINE(aoff>>ANGLETOFINESHIFT)) + (P_RandomRange(-8,8) << FRACBITS), + mo->y + FixedMul(24*mo->scale, FINESINE(aoff>>ANGLETOFINESHIFT)) + (P_RandomRange(-8,8) << FRACBITS), + mo->z, MT_WIPEOUTTRAIL); P_SetTarget(&dust->target, mo); dust->angle = R_PointToAngle2(0,0,mo->momx,mo->momy); dust->destscale = mo->scale; P_SetScale(dust, mo->scale); - dust->eflags = (dust->eflags & ~MFE_VERTICALFLIP)|(mo->eflags & MFE_VERTICALFLIP); // not K_MatchGenericExtraFlags because hyudoro shouldn't be able to wipeout + K_FlipFromObject(dust, mo); if (translucent) // offroad effect { @@ -2844,10 +3029,6 @@ void K_DriftDustHandling(mobj_t *spawner) fixed_t spawny = P_RandomRange(-spawnrange, spawnrange)<x + spawnx, spawner->y + spawny, spawner->z, MT_DRIFTDUST); - if (spawner->eflags & MFE_VERTICALFLIP) - { - dust->z += spawner->height - dust->height; - } dust->momx = FixedMul(spawner->momx + (P_RandomRange(-speedrange, speedrange)<scale)/4); dust->momy = FixedMul(spawner->momy + (P_RandomRange(-speedrange, speedrange)<scale)/4); dust->momz = P_MobjFlip(spawner) * (P_RandomRange(1, 4) * (spawner->scale)); @@ -2880,7 +3061,8 @@ static mobj_t *K_FindLastTrailMobj(player_t *player) static mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t mapthing, INT32 defaultDir, INT32 altthrow) { mobj_t *mo; - INT32 dir, PROJSPEED; + INT32 dir; + fixed_t PROJSPEED; angle_t newangle; fixed_t newx, newy, newz; mobj_t *throwmo; @@ -2918,12 +3100,19 @@ static mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t map { if (altthrow == 2) // Kitchen sink throwing { +#if 0 if (player->kartstuff[k_throwdir] == 1) dir = 3; else if (player->kartstuff[k_throwdir] == -1) dir = 1; else dir = 2; +#else + if (player->kartstuff[k_throwdir] == 1) + dir = 2; + else + dir = 1; +#endif } else { @@ -2988,6 +3177,14 @@ static mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t map { // Shoot forward mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z + player->mo->height/2, mapthing); + //K_FlipFromObject(mo, player->mo); + // These are really weird so let's make it a very specific case to make SURE it works... + if (player->mo->eflags & MFE_VERTICALFLIP) + { + mo->z -= player->mo->height; + mo->flags2 |= MF2_OBJECTFLIP; + mo->eflags |= MFE_VERTICALFLIP; + } mo->threshold = 10; P_SetTarget(&mo->target, player->mo); @@ -2997,18 +3194,29 @@ static mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t map if (mo) { angle_t fa = player->mo->angle>>ANGLETOFINESHIFT; - INT32 HEIGHT = (20 + (dir*10))*mapobjectscale + player->mo->momz; + fixed_t HEIGHT = (20 + (dir*10))*mapobjectscale + (player->mo->momz*P_MobjFlip(player->mo)); - mo->momx = player->mo->momx + FixedMul(FINECOSINE(fa), (altthrow == 2 ? 2*PROJSPEED/3 : PROJSPEED)); - mo->momy = player->mo->momy + FixedMul(FINESINE(fa), (altthrow == 2 ? 2*PROJSPEED/3 : PROJSPEED)); - mo->momz = P_MobjFlip(player->mo) * HEIGHT; + P_SetObjectMomZ(mo, HEIGHT, false); + mo->momx = player->mo->momx + FixedMul(FINECOSINE(fa), PROJSPEED*dir); + mo->momy = player->mo->momy + FixedMul(FINESINE(fa), PROJSPEED*dir); - if (player->mo->eflags & MFE_VERTICALFLIP) - mo->eflags |= MFE_VERTICALFLIP; + mo->extravalue2 = dir; + + if (mo->eflags & MFE_UNDERWATER) + mo->momz = (117 * mo->momz) / 200; } + // this is the small graphic effect that plops in you when you throw an item: throwmo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z + player->mo->height/2, MT_FIREDITEM); P_SetTarget(&throwmo->target, player->mo); + // Ditto: + if (player->mo->eflags & MFE_VERTICALFLIP) + { + throwmo->z -= player->mo->height; + throwmo->flags2 |= MF2_OBJECTFLIP; + throwmo->eflags |= MFE_VERTICALFLIP; + } + throwmo->movecount = 0; // above player } else @@ -3034,9 +3242,7 @@ static mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t map } mo = P_SpawnMobj(newx, newy, newz, mapthing); // this will never return null because collision isn't processed here - - if (P_MobjFlip(player->mo) < 0) - mo->z = player->mo->z + player->mo->height - mo->height; + K_FlipFromObject(mo, player->mo); mo->threshold = 10; P_SetTarget(&mo->target, player->mo); @@ -3067,12 +3273,68 @@ static mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t map if (player->mo->eflags & MFE_VERTICALFLIP) mo->eflags |= MFE_VERTICALFLIP; + + if (mapthing == MT_SSMINE) + mo->extravalue1 = 49; // Pads the start-up length from 21 frames to a full 2 seconds } } return mo; } +void K_PuntMine(mobj_t *thismine, mobj_t *punter) +{ + angle_t fa = R_PointToAngle2(0, 0, punter->momx, punter->momy) >> ANGLETOFINESHIFT; + fixed_t z = 30*mapobjectscale + punter->momz; + fixed_t spd; + mobj_t *mine; + + if (!thismine || P_MobjWasRemoved(thismine)) + return; + + if (thismine->type == MT_SSMINE_SHIELD) // Create a new mine + { + mine = P_SpawnMobj(thismine->x, thismine->y, thismine->z, MT_SSMINE); + P_SetTarget(&mine->target, thismine->target); + mine->angle = thismine->angle; + mine->flags2 = thismine->flags2; + mine->floorz = thismine->floorz; + mine->ceilingz = thismine->ceilingz; + P_RemoveMobj(thismine); + } + else + mine = thismine; + + if (!mine || P_MobjWasRemoved(mine)) + return; + + switch (gamespeed) + { + case 0: + spd = 68*mapobjectscale; // Avg Speed is 34 + break; + case 2: + spd = 96*mapobjectscale; // Avg Speed is 48 + break; + default: + spd = 82*mapobjectscale; // Avg Speed is 41 + break; + } + + mine->flags |= MF_NOCLIPTHING; + + P_SetMobjState(mine, S_SSMINE_AIR1); + mine->threshold = 10; + mine->extravalue1 = 0; + mine->reactiontime = mine->info->reactiontime; + + mine->momx = punter->momx + FixedMul(FINECOSINE(fa), spd); + mine->momy = punter->momy + FixedMul(FINESINE(fa), spd); + mine->momz = P_MobjFlip(mine) * z; + + mine->flags &= ~MF_NOCLIPTHING; +} + #define THUNDERRADIUS 320 static void K_DoThunderShield(player_t *player) @@ -3242,6 +3504,7 @@ void K_DoSneaker(player_t *player, INT32 type) P_SetTarget(&overlay->target, cur); P_SetTarget(&cur->tracer, overlay); P_SetScale(overlay, (overlay->destscale = 3*cur->scale/4)); + K_FlipFromObject(overlay, cur); } cur = cur->hnext; } @@ -3252,6 +3515,7 @@ void K_DoSneaker(player_t *player, INT32 type) mobj_t *overlay = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_BOOSTFLAME); P_SetTarget(&overlay->target, player->mo); P_SetScale(overlay, (overlay->destscale = player->mo->scale)); + K_FlipFromObject(overlay, player->mo); } } @@ -3261,6 +3525,7 @@ void K_DoSneaker(player_t *player, INT32 type) { player->pflags |= PF_ATTACKDOWN; K_PlayBoostTaunt(player->mo); + player->powers[pw_flashing] = 0; // Stop flashing after boosting } } @@ -3286,11 +3551,15 @@ static void K_DoShrink(player_t *user) { // Start shrinking! K_DropItems(&players[i]); - players[i].mo->scalespeed = mapobjectscale/TICRATE; - players[i].mo->destscale = (6*mapobjectscale)/8; - if (cv_kartdebugshrink.value && !modeattacking && !players[i].bot) - players[i].mo->destscale = (6*players[i].mo->destscale)/8; - players[i].kartstuff[k_growshrinktimer] = -(200+(40*(MAXPLAYERS-players[i].kartstuff[k_position]))); + players[i].kartstuff[k_growshrinktimer] = -(20*TICRATE); + + if (players[i].mo && !P_MobjWasRemoved(players[i].mo)) + { + players[i].mo->scalespeed = mapobjectscale/TICRATE; + players[i].mo->destscale = (6*mapobjectscale)/8; + if (cv_kartdebugshrink.value && !modeattacking && !players[i].bot) + players[i].mo->destscale = (6*players[i].mo->destscale)/8; + } } // Grow should get taken away. @@ -3351,11 +3620,14 @@ void K_DoPogoSpring(mobj_t *mo, fixed_t vertispeed, UINT8 sound) thrust = 32<momz = FixedMul(FINESINE(ANGLE_22h>>ANGLETOFINESHIFT), FixedMul(thrust, vscale)); + mo->momz = P_MobjFlip(mo)*FixedMul(FINESINE(ANGLE_22h>>ANGLETOFINESHIFT), FixedMul(thrust, vscale)); } else mo->momz = FixedMul(vertispeed, vscale); + if (mo->eflags & MFE_UNDERWATER) + mo->momz = (117 * mo->momz) / 200; + if (sound) S_StartSound(mo, (sound == 1 ? sfx_kc2f : sfx_kpogos)); } @@ -3415,7 +3687,7 @@ void K_DropHnextList(player_t *player) mobjtype_t type; boolean orbit, ponground, dropall = true; - if (!work) + if (!work || P_MobjWasRemoved(work)) return; flip = P_MobjFlip(player->mo); @@ -3505,6 +3777,8 @@ void K_DropHnextList(player_t *player) dropwork->momx = player->mo->momx>>1; dropwork->momy = player->mo->momy>>1; dropwork->momz = 3*flip*mapobjectscale; + if (dropwork->eflags & MFE_UNDERWATER) + dropwork->momz = (117 * dropwork->momz) / 200; P_Thrust(dropwork, work->angle - ANGLE_90, 6*mapobjectscale); dropwork->movecount = 2; dropwork->movedir = work->angle - ANGLE_90; @@ -3552,7 +3826,7 @@ void K_DropItems(player_t *player) K_DropHnextList(player); - if (player->mo && player->kartstuff[k_itemamount]) + if (player->mo && !P_MobjWasRemoved(player->mo) && player->kartstuff[k_itemamount]) { mobj_t *drop = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z + player->mo->height/2, MT_FLOATINGITEM); P_SetScale(drop, drop->scale>>4); @@ -3563,6 +3837,8 @@ void K_DropItems(player_t *player) FixedAngle(P_RandomFixed()*180) + player->mo->angle + ANGLE_90, 16*mapobjectscale); drop->momz = P_MobjFlip(player->mo)*3*mapobjectscale; + if (drop->eflags & MFE_UNDERWATER) + drop->momz = (117 * drop->momz) / 200; drop->threshold = (thunderhack ? KITEM_THUNDERSHIELD : player->kartstuff[k_itemtype]); drop->movecount = player->kartstuff[k_itemamount]; @@ -3774,6 +4050,7 @@ static void K_MoveHeldObjects(player_t *player) targx = targ->x + P_ReturnThrustX(cur, ang + ANGLE_180, dist); targy = targ->y + P_ReturnThrustY(cur, ang + ANGLE_180, dist); targz = targ->z; + speed = FixedMul(R_PointToDist2(cur->x, cur->y, targx, targy), 3*FRACUNIT/4); if (P_IsObjectOnGround(targ)) targz = cur->floorz; @@ -3864,8 +4141,11 @@ static void K_MoveHeldObjects(player_t *player) { // bobbing, copy pasted from my kimokawaiii entry const fixed_t pi = (22<>ANGLETOFINESHIFT) & FINEMASK); + fixed_t sine = FixedMul(player->mo->scale, 8 * FINESINE((((2*pi*(4*TICRATE)) * leveltime)>>ANGLETOFINESHIFT) & FINEMASK)); targz = (player->mo->z + (player->mo->height/2)) + sine; + if (player->mo->eflags & MFE_VERTICALFLIP) + targz += (player->mo->height/2 - 32*player->mo->scale)*6; + } if (cur->tracer) @@ -3882,7 +4162,7 @@ static void K_MoveHeldObjects(player_t *player) } P_TeleportMove(cur, targx, targy, targz); - + K_FlipFromObject(cur, player->mo); // Update graviflip in real time thanks. num = (num+1) % 2; cur = cur->hnext; } @@ -4427,8 +4707,11 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->kartstuff[k_comebacktimer]) player->kartstuff[k_comebackmode] = 0; - if (P_IsObjectOnGround(player->mo) && player->mo->momz <= 0 && player->kartstuff[k_pogospring]) - player->kartstuff[k_pogospring] = 0; + if (P_IsObjectOnGround(player->mo) && player->kartstuff[k_pogospring]) + { + if (P_MobjFlip(player->mo)*player->mo->momz <= 0) + player->kartstuff[k_pogospring] = 0; + } if (cmd->buttons & BT_DRIFT) player->kartstuff[k_jmp] = 1; @@ -4685,6 +4968,7 @@ static void K_KartDrift(player_t *player, boolean onground) player->kartstuff[k_driftend] = 0; } + // Incease/decrease the drift value to continue drifting in that direction if (player->kartstuff[k_spinouttimer] == 0 && player->kartstuff[k_jmp] == 1 && onground && player->kartstuff[k_drift] != 0) { @@ -4714,7 +4998,7 @@ static void K_KartDrift(player_t *player, boolean onground) } // Disable drift-sparks until you're going fast enough - if (player->kartstuff[k_getsparks] == 0 || player->kartstuff[k_offroad]) + if (player->kartstuff[k_getsparks] == 0 || (player->kartstuff[k_offroad] && !player->kartstuff[k_invincibilitytimer] && !player->kartstuff[k_hyudorotimer] && !player->kartstuff[k_sneakertimer])) driftadditive = 0; if (player->speed > minspeed*2) player->kartstuff[k_getsparks] = 1; @@ -5019,6 +5303,18 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if (player->kartstuff[k_rocketsneakertimer] < 1) player->kartstuff[k_rocketsneakertimer] = 1; } + // Grow Canceling + else if (player->kartstuff[k_growshrinktimer] > 0) + { + if (cmd->buttons & BT_ATTACK) + { + player->kartstuff[k_growcancel]++; + if (player->kartstuff[k_growcancel] > 26) + K_RemoveGrowShrink(player); + } + else + player->kartstuff[k_growcancel] = 0; + } else if (player->kartstuff[k_itemamount] <= 0) { player->kartstuff[k_itemamount] = player->kartstuff[k_itemheld] = 0; @@ -5056,6 +5352,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) for (moloop = 0; moloop < 2; moloop++) { mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_ROCKETSNEAKER); + K_MatchGenericExtraFlags(mo, player->mo); mo->flags |= MF_NOCLIPTHING; mo->angle = player->mo->angle; mo->threshold = 10; @@ -5375,6 +5672,9 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if (player->kartstuff[k_itemtype] != KITEM_THUNDERSHIELD) player->kartstuff[k_curshield] = 0; + if (player->kartstuff[k_growshrinktimer] <= 0) + player->kartstuff[k_growcancel] = 0; + if (player->kartstuff[k_itemtype] == KITEM_SPB || player->kartstuff[k_itemtype] == KITEM_SHRINK || player->kartstuff[k_growshrinktimer] < 0) @@ -5440,43 +5740,46 @@ void K_MoveKartPlayer(player_t *player, boolean onground) } } - // Friction - if (!player->kartstuff[k_offroad]) + if (onground) { - if (player->speed > 0 && cmd->forwardmove == 0 && player->mo->friction == 59392) - player->mo->friction += 4608; - if (player->speed > 0 && cmd->forwardmove < 0 && player->mo->friction == 59392) - player->mo->friction += 1608; - } + // Friction + if (!player->kartstuff[k_offroad]) + { + if (player->speed > 0 && cmd->forwardmove == 0 && player->mo->friction == 59392) + player->mo->friction += 4608; + if (player->speed > 0 && cmd->forwardmove < 0 && player->mo->friction == 59392) + player->mo->friction += 1608; + } - // Karma ice physics - if (G_BattleGametype() && player->kartstuff[k_bumper] <= 0) - { - player->mo->friction += 1228; + // Karma ice physics + if (G_BattleGametype() && player->kartstuff[k_bumper] <= 0) + { + player->mo->friction += 1228; - if (player->mo->friction > FRACUNIT) - player->mo->friction = FRACUNIT; - if (player->mo->friction < 0) - player->mo->friction = 0; + if (player->mo->friction > FRACUNIT) + player->mo->friction = FRACUNIT; + if (player->mo->friction < 0) + player->mo->friction = 0; - player->mo->movefactor = FixedDiv(ORIG_FRICTION, player->mo->friction); + player->mo->movefactor = FixedDiv(ORIG_FRICTION, player->mo->friction); - if (player->mo->movefactor < FRACUNIT) - player->mo->movefactor = 19*player->mo->movefactor - 18*FRACUNIT; - else - player->mo->movefactor = FRACUNIT; //player->mo->movefactor = ((player->mo->friction - 0xDB34)*(0xA))/0x80; + if (player->mo->movefactor < FRACUNIT) + player->mo->movefactor = 19*player->mo->movefactor - 18*FRACUNIT; + else + player->mo->movefactor = FRACUNIT; //player->mo->movefactor = ((player->mo->friction - 0xDB34)*(0xA))/0x80; - if (player->mo->movefactor < 32) - player->mo->movefactor = 32; - } + if (player->mo->movefactor < 32) + player->mo->movefactor = 32; + } - // Wipeout slowdown - if (player->kartstuff[k_spinouttimer] && player->kartstuff[k_wipeoutslow]) - { - if (player->kartstuff[k_offroad]) - player->mo->friction -= 4912; - if (player->kartstuff[k_wipeoutslow] == 1) - player->mo->friction -= 9824; + // Wipeout slowdown + if (player->kartstuff[k_spinouttimer] && player->kartstuff[k_wipeoutslow]) + { + if (player->kartstuff[k_offroad]) + player->mo->friction -= 4912; + if (player->kartstuff[k_wipeoutslow] == 1) + player->mo->friction -= 9824; + } } K_KartDrift(player, onground); @@ -6436,6 +6739,8 @@ static void K_drawKartItem(void) //INT32 splitflags = K_calcSplitFlags(V_SNAPTOTOP|V_SNAPTOLEFT); const INT32 numberdisplaymin = ((!offset && stplyr->kartstuff[k_itemtype] == KITEM_ORBINAUT) ? 5 : 2); INT32 itembar = 0; + INT32 maxl = 0; // itembar's normal highest value + const INT32 barlength = (splitscreen > 1 ? 12 : 26); UINT8 localcolor = SKINCOLOR_NONE; SINT8 colormode = TC_RAINBOW; UINT8 *colmap = NULL; @@ -6544,6 +6849,8 @@ static void K_drawKartItem(void) else if (stplyr->kartstuff[k_rocketsneakertimer] > 1) { itembar = stplyr->kartstuff[k_rocketsneakertimer]; + maxl = (itemtime*3) - barlength; + if (leveltime & 1) localpatch = kp_rocketsneaker[offset]; else @@ -6551,6 +6858,12 @@ static void K_drawKartItem(void) } else if (stplyr->kartstuff[k_growshrinktimer] > 0) { + if (stplyr->kartstuff[k_growcancel]) + { + itembar = stplyr->kartstuff[k_growcancel]; + maxl = 26; + } + if (leveltime & 1) localpatch = kp_grow[offset]; else @@ -6676,7 +6989,7 @@ static void K_drawKartItem(void) } if (localcolor != SKINCOLOR_NONE) - colmap = R_GetTranslationColormap(colormode, localcolor, 0); + colmap = R_GetTranslationColormap(colormode, localcolor, GTC_CACHE); V_DrawScaledPatch(fx, fy, V_HUDTRANS|fflags, localbg); @@ -6702,8 +7015,6 @@ static void K_drawKartItem(void) // Extensible meter, currently only used for rocket sneaker... if (itembar && hudtrans) { - const INT32 barlength = (splitscreen > 1 ? 12 : 26); - const INT32 maxl = (itemtime*3) - barlength; // timer's normal highest value const INT32 fill = ((itembar*barlength)/maxl); const INT32 length = min(barlength, fill); const INT32 height = (offset ? 1 : 2); @@ -7171,7 +7482,7 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I if (netgame // don't draw it offline && tab[i].num != serverplayer) - HU_drawPing(x + ((i < 8) ? -19 : rightoffset + 13), y+2, playerpingtable[tab[i].num], false); + HU_drawPing(x + ((i < 8) ? -17 : rightoffset + 11), y-4, playerpingtable[tab[i].num], 0); STRBUFCPY(strtime, tab[i].name); @@ -7340,7 +7651,7 @@ static void K_drawKartSpeedometer(void) static void K_drawKartBumpersOrKarma(void) { - UINT8 *colormap = R_GetTranslationColormap(TC_DEFAULT, stplyr->skincolor, 0); + UINT8 *colormap = R_GetTranslationColormap(TC_DEFAULT, stplyr->skincolor, GTC_CACHE); INT32 splitflags = K_calcSplitFlags(V_SNAPTOBOTTOM|V_SNAPTOLEFT); INT32 fx = 0, fy = 0, fflags = 0; boolean flipstring = false; // same as laps, used for splitscreen @@ -7548,7 +7859,7 @@ static void K_drawKartPlayerCheck(void) else if (x > 306) x = 306; - colormap = R_GetTranslationColormap(TC_DEFAULT, players[i].mo->color, 0); + colormap = R_GetTranslationColormap(TC_DEFAULT, players[i].mo->color, GTC_CACHE); V_DrawMappedPatch(x, CHEK_Y, V_HUDTRANS|splitflags, kp_check[pnum], colormap); } } @@ -7640,8 +7951,12 @@ static void K_drawKartMinimapHead(mobj_t *mo, INT32 x, INT32 y, INT32 flags, pat else colormap = R_GetTranslationColormap(skin, mo->color, GTC_CACHE); V_DrawFixedPatch(amxpos, amypos, FRACUNIT, flags, facemmapprefix[skin], colormap); - if (mo->player && K_IsPlayerWanted(mo->player)) + if (mo->player + && ((G_RaceGametype() && mo->player->kartstuff[k_position] == spbplace) + || (G_BattleGametype() && K_IsPlayerWanted(mo->player)))) + { V_DrawFixedPatch(amxpos - (4<kartstuff[k_driftcharge] >= dsthree)) - colmap = R_GetTranslationColormap(TC_RAINBOW, (UINT8)(1 + (leveltime % (MAXSKINCOLORS-1))), 0); + colmap = R_GetTranslationColormap(TC_RAINBOW, (UINT8)(1 + (leveltime % (MAXSKINCOLORS-1))), GTC_CACHE); else if ((leveltime & 1) && (stplyr->kartstuff[k_driftcharge] >= dstwo)) - colmap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_KETCHUP, 0); + colmap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_KETCHUP, GTC_CACHE); else if ((leveltime & 1) && (stplyr->kartstuff[k_driftcharge] >= dsone)) - colmap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_SAPPHIRE, 0); + colmap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_SAPPHIRE, GTC_CACHE); else #endif // invincibility/grow/shrink! if (stplyr->mo->colorized && stplyr->mo->color) - colmap = R_GetTranslationColormap(TC_RAINBOW, stplyr->mo->color, 0); + colmap = R_GetTranslationColormap(TC_RAINBOW, stplyr->mo->color, GTC_CACHE); } V_DrawFixedPatch(x, y, scale, splitflags, kp_fpview[target], colmap); @@ -8185,7 +8500,7 @@ static void K_drawInput(void) else { UINT8 *colormap; - colormap = R_GetTranslationColormap(0, stplyr->skincolor, 0); + colormap = R_GetTranslationColormap(0, stplyr->skincolor, GTC_CACHE); V_DrawFixedPatch(x<kartstuff[k_lapanimation]; - UINT8 *colormap = R_GetTranslationColormap(TC_DEFAULT, stplyr->skincolor, 0); + UINT8 *colormap = R_GetTranslationColormap(TC_DEFAULT, stplyr->skincolor, GTC_CACHE); V_DrawFixedPatch((BASEVIDWIDTH/2 + (32*max(0, stplyr->kartstuff[k_lapanimation]-76)))*FRACUNIT, (48 - (32*max(0, progress-76)))*FRACUNIT, @@ -8310,6 +8625,7 @@ static void K_drawDistributionDebugger(void) INT32 i; INT32 x = -9, y = -9; boolean dontforcespb = false; + boolean spbrush = false; if (stplyr != &players[displayplayer]) // only for p1 return; @@ -8326,11 +8642,14 @@ static void K_drawDistributionDebugger(void) bestbumper = players[i].kartstuff[k_bumper]; } - useodds = K_FindUseodds(stplyr, 0, pingame, bestbumper, (spbplace != -1 && stplyr->kartstuff[k_position] == spbplace+1), dontforcespb); + if (G_RaceGametype()) + spbrush = (spbplace != -1 && stplyr->kartstuff[k_position] == spbplace+1); + + useodds = K_FindUseodds(stplyr, 0, pingame, bestbumper, spbrush, dontforcespb); for (i = 1; i < NUMKARTRESULTS; i++) { - const INT32 itemodds = K_KartGetItemOdds(useodds, i, 0); + const INT32 itemodds = K_KartGetItemOdds(useodds, i, 0, spbrush); if (itemodds <= 0) continue; @@ -8591,6 +8910,25 @@ void K_drawKartHUD(void) for (p = 0; p < MAXPLAYERS; p++) V_DrawString(8, 64+(8*p), V_YELLOWMAP, va("%d - %d (%dl)", p, playernode[p], players[p].cmd.latency)); } + + if (cv_kartdebugcolorize.value && stplyr->mo && stplyr->mo->skin) + { + INT32 x = 0, y = 0; + UINT8 c; + + for (c = 1; c < MAXSKINCOLORS; c++) + { + UINT8 *cm = R_GetTranslationColormap(TC_RAINBOW, c, GTC_CACHE); + V_DrawFixedPatch(x<>1, 0, facewantprefix[stplyr->skin], cm); + + x += 16; + if (x > BASEVIDWIDTH-16) + { + x = 0; + y += 16; + } + } + } } //} diff --git a/src/k_kart.h b/src/k_kart.h index dc37956a..2ba5d1bd 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -11,7 +11,7 @@ #define KART_FULLTURN 800 -UINT8 colortranslations[MAXSKINCOLORS][16]; +UINT8 colortranslations[MAXTRANSLATIONS][16]; extern const char *KartColor_Names[MAXSKINCOLORS]; extern const UINT8 KartColor_Opposite[MAXSKINCOLORS*2]; void K_RainbowColormap(UINT8 *dest_colormap, UINT8 skincolor); @@ -23,6 +23,7 @@ void K_RegisterKartStuff(void); boolean K_IsPlayerLosing(player_t *player); boolean K_IsPlayerWanted(player_t *player); void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid); +void K_FlipFromObject(mobj_t *mo, mobj_t *master); void K_MatchGenericExtraFlags(mobj_t *mo, mobj_t *master); void K_RespawnChecker(player_t *player); void K_KartMoveAnimation(player_t *player); @@ -41,6 +42,7 @@ void K_SpawnBoostTrail(player_t *player); void K_SpawnSparkleTrail(mobj_t *mo); void K_SpawnWipeoutTrail(mobj_t *mo, boolean translucent); void K_DriftDustHandling(mobj_t *spawner); +void K_PuntMine(mobj_t *mine, mobj_t *punter); void K_DoSneaker(player_t *player, INT32 type); void K_DoPogoSpring(mobj_t *mo, fixed_t vertispeed, UINT8 sound); void K_KillBananaChain(mobj_t *banana, mobj_t *inflictor, mobj_t *source); diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 36becc56..f6b2258c 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -639,19 +639,6 @@ static int lib_pCheckSolidLava(lua_State *L) return 1; } -static int lib_pCanRunOnWater(lua_State *L) -{ - player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); - ffloor_t *rover = *((ffloor_t **)luaL_checkudata(L, 2, META_FFLOOR)); - //HUDSAFE - if (!player) - return LUA_ErrInvalid(L, "player_t"); - if (!rover) - return LUA_ErrInvalid(L, "ffloor_t"); - lua_pushboolean(L, P_CanRunOnWater(player, rover)); - return 1; -} - static int lib_pSpawnShadowMobj(lua_State *L) { mobj_t *caster = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); @@ -2634,7 +2621,6 @@ static luaL_Reg lib[] = { {"P_InsideANonSolidFFloor",lib_pInsideANonSolidFFloor}, {"P_CheckDeathPitCollide",lib_pCheckDeathPitCollide}, {"P_CheckSolidLava",lib_pCheckSolidLava}, - {"P_CanRunOnWater",lib_pCanRunOnWater}, {"P_SpawnShadowMobj",lib_pSpawnShadowMobj}, // p_user diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index cd8e0392..fb6814b2 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -410,6 +410,24 @@ static int libd_drawPaddedNum(lua_State *L) return 0; } + +static int libd_drawPingNum(lua_State *L) +{ + INT32 x, y, flags, num; + const UINT8 *colormap = NULL; + HUDONLY + x = luaL_checkinteger(L, 1); + y = luaL_checkinteger(L, 2); + num = luaL_checkinteger(L, 3); + flags = luaL_optinteger(L, 4, 0); + flags &= ~V_PARAMMASK; // Don't let crashes happen. + if (!lua_isnoneornil(L, 5)) + colormap = *((UINT8 **)luaL_checkudata(L, 5, META_COLORMAP)); + + V_DrawPingNum(x, y, flags, num, colormap); + return 0; +} + static int libd_drawFill(lua_State *L) { INT32 x = luaL_optinteger(L, 1, 0); @@ -613,6 +631,7 @@ static luaL_Reg lib_draw[] = { {"drawScaled", libd_drawScaled}, {"drawNum", libd_drawNum}, {"drawPaddedNum", libd_drawPaddedNum}, + {"drawPingNum", libd_drawPingNum}, {"drawFill", libd_drawFill}, {"fadeScreen", libd_fadeScreen}, {"drawString", libd_drawString}, diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 5f136fc1..73d5ecbc 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -325,6 +325,8 @@ static int player_get(lua_State *L) lua_pushinteger(L, plr->bot); else if (fastcmp(field,"jointime")) lua_pushinteger(L, plr->jointime); + else if (fastcmp(field,"splitscreenindex")) + lua_pushinteger(L, plr->splitscreenindex); #ifdef HWRENDER else if (fastcmp(field,"fovadd")) lua_pushfixed(L, plr->fovadd); @@ -613,6 +615,8 @@ static int player_set(lua_State *L) return NOSET; else if (fastcmp(field,"jointime")) plr->jointime = (tic_t)luaL_checkinteger(L, 3); + else if (fastcmp(field,"splitscreenindex")) + return NOSET; #ifdef HWRENDER else if (fastcmp(field,"fovadd")) plr->fovadd = luaL_checkfixed(L, 3); @@ -739,6 +743,8 @@ static int ticcmd_get(lua_State *L) lua_pushinteger(L, cmd->buttons); else if (fastcmp(field,"driftturn")) lua_pushinteger(L, cmd->driftturn); + else if (fastcmp(field,"latency")) + lua_pushinteger(L, cmd->latency); else return NOFIELD; diff --git a/src/lua_script.c b/src/lua_script.c index 1f87d33e..28f02ca3 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -1020,7 +1020,7 @@ void LUA_Archive(void) for (i = 0; i < MAXPLAYERS; i++) { - if (!playeringame[i]) + if (!playeringame[i] && i > 0) // NEVER skip player 0, this is for dedi servs. continue; // all players in game will be archived, even if they just add a 0. ArchiveExtVars(&players[i], "player"); @@ -1056,7 +1056,7 @@ void LUA_UnArchive(void) for (i = 0; i < MAXPLAYERS; i++) { - if (!playeringame[i]) + if (!playeringame[i] && i > 0) // same here, this is to synch dediservs properly. continue; UnArchiveExtVars(&players[i]); } diff --git a/src/lua_skinlib.c b/src/lua_skinlib.c index 8fdd92a5..f44e97af 100644 --- a/src/lua_skinlib.c +++ b/src/lua_skinlib.c @@ -30,24 +30,10 @@ enum skin { skin_facerank, skin_facewant, skin_facemmap, - skin_ability, - skin_ability2, - skin_thokitem, - skin_spinitem, - skin_revitem, - skin_actionspd, - skin_mindash, - skin_maxdash, // SRB2kart skin_kartspeed, skin_kartweight, // - skin_normalspeed, - skin_runspeed, - skin_thrustfactor, - skin_accelstart, - skin_acceleration, - skin_jumpfactor, skin_starttranscolor, skin_prefcolor, skin_highresscale, @@ -64,24 +50,10 @@ static const char *const skin_opt[] = { "facerank", "facewant", "facemmap", - "ability", - "ability2", - "thokitem", - "spinitem", - "revitem", - "actionspd", - "mindash", - "maxdash", // SRB2kart "kartspeed", "kartweight", // - "normalspeed", - "runspeed", - "thrustfactor", - "accelstart", - "acceleration", - "jumpfactor", "starttranscolor", "prefcolor", "highresscale", @@ -139,30 +111,6 @@ static int skin_get(lua_State *L) break; lua_pushlstring(L, skin->facemmap, i); break; - case skin_ability: - lua_pushinteger(L, skin->ability); - break; - case skin_ability2: - lua_pushinteger(L, skin->ability2); - break; - case skin_thokitem: - lua_pushinteger(L, skin->thokitem); - break; - case skin_spinitem: - lua_pushinteger(L, skin->spinitem); - break; - case skin_revitem: - lua_pushinteger(L, skin->revitem); - break; - case skin_actionspd: - lua_pushfixed(L, skin->actionspd); - break; - case skin_mindash: - lua_pushfixed(L, skin->mindash); - break; - case skin_maxdash: - lua_pushfixed(L, skin->maxdash); - break; // SRB2kart case skin_kartspeed: lua_pushinteger(L, skin->kartspeed); @@ -171,24 +119,6 @@ static int skin_get(lua_State *L) lua_pushinteger(L, skin->kartweight); break; // - case skin_normalspeed: - lua_pushfixed(L, skin->normalspeed); - break; - case skin_runspeed: - lua_pushfixed(L, skin->runspeed); - break; - case skin_thrustfactor: - lua_pushinteger(L, skin->thrustfactor); - break; - case skin_accelstart: - lua_pushinteger(L, skin->accelstart); - break; - case skin_acceleration: - lua_pushinteger(L, skin->acceleration); - break; - case skin_jumpfactor: - lua_pushfixed(L, skin->jumpfactor); - break; case skin_starttranscolor: lua_pushinteger(L, skin->starttranscolor); break; diff --git a/src/m_menu.c b/src/m_menu.c index b0b8a1e5..0fc62233 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -399,6 +399,8 @@ static void Dummystaff_OnChange(void); // CONSOLE VARIABLES AND THEIR POSSIBLE VALUES GO HERE. // ========================================================================== +consvar_t cv_showfocuslost = {"showfocuslost", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL }; + static CV_PossibleValue_t map_cons_t[] = { {0,"MIN"}, {NUMMAPS, "MAX"}, @@ -948,14 +950,15 @@ static menuitem_t MP_MainMenu[] = static menuitem_t MP_ServerMenu[] = { - {IT_STRING|IT_CVAR, NULL, "Max. Player Count", &cv_maxplayers, 10}, - {IT_STRING|IT_CALL, NULL, "Room...", M_RoomMenu, 20}, - {IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Server Name", &cv_servername, 30}, + {IT_STRING|IT_CVAR, NULL, "Max. Player Count", &cv_maxplayers, 0}, + {IT_STRING|IT_CALL, NULL, "Room...", M_RoomMenu, 10}, + {IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Server Name", &cv_servername, 20}, + {IT_STRING|IT_CVAR|IT_CV_PASSWORD, NULL, "Password", &cv_dummyjoinpassword, 44}, - {IT_STRING|IT_CVAR, NULL, "Game Type", &cv_newgametype, 68}, - {IT_STRING|IT_CVAR, NULL, "Level", &cv_nextmap, 78}, + {IT_STRING|IT_CVAR, NULL, "Game Type", &cv_newgametype, 68}, + {IT_STRING|IT_CVAR, NULL, "Level", &cv_nextmap, 78}, - {IT_WHITESTRING|IT_CALL, NULL, "Start", M_StartServer, 130}, + {IT_WHITESTRING|IT_CALL, NULL, "Start", M_StartServer, 130}, }; #endif @@ -1316,6 +1319,9 @@ static menuitem_t OP_SoundOptionsMenu[] = {IT_STRING|IT_CVAR, NULL, "Powerup Warning", &cv_kartinvinsfx, 95}, {IT_KEYHANDLER|IT_STRING, NULL, "Sound Test", M_HandleSoundTest, 110}, + + {IT_STRING|IT_CVAR, NULL, "Play Music While Unfocused", &cv_playmusicifunfocused, 125}, + {IT_STRING|IT_CVAR, NULL, "Play SFX While Unfocused", &cv_playsoundifunfocused, 135}, }; /*static menuitem_t OP_DataOptionsMenu[] = @@ -1390,7 +1396,7 @@ static menuitem_t OP_HUDOptionsMenu[] = {IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "HUD Visibility", &cv_translucenthud, 20}, - {IT_STRING | IT_SUBMENU, NULL, "Online chat options...",&OP_ChatOptionsDef, 35}, + {IT_STRING | IT_SUBMENU, NULL, "Online HUD options...",&OP_ChatOptionsDef, 35}, {IT_STRING | IT_CVAR, NULL, "Background Glass", &cons_backcolor, 45}, {IT_STRING | IT_CVAR | IT_CV_SLIDER, @@ -1402,8 +1408,11 @@ static menuitem_t OP_HUDOptionsMenu[] = // highlight info - (GOOD HIGHLIGHT, WARNING HIGHLIGHT) - 105 (see M_DrawHUDOptions) {IT_STRING | IT_CVAR, NULL, "Console Text Size", &cv_constextsize, 120}, + + {IT_STRING | IT_CVAR, NULL, "Show \"FOCUS LOST\"", &cv_showfocuslost, 135}, }; +// Ok it's still called chatoptions but we'll put ping display in here to be clean static menuitem_t OP_ChatOptionsMenu[] = { // will ANYONE who doesn't know how to use the console want to touch this one? @@ -1417,6 +1426,8 @@ static menuitem_t OP_ChatOptionsMenu[] = {IT_STRING | IT_CVAR, NULL, "Chat Background Tint", &cv_chatbacktint, 50}, {IT_STRING | IT_CVAR, NULL, "Message Fadeout Time", &cv_chattime, 60}, {IT_STRING | IT_CVAR, NULL, "Spam Protection", &cv_chatspamprotection, 70}, + + {IT_STRING | IT_CVAR, NULL, "Local ping display", &cv_showping, 90}, // shows ping next to framerate if we want to. }; static menuitem_t OP_GameOptionsMenu[] = @@ -1469,15 +1480,16 @@ static menuitem_t OP_AdvServerOptionsMenu[] = {IT_STRING | IT_CVAR, NULL, "Attempts to resynchronise", &cv_resynchattempts, 40}, {IT_STRING | IT_CVAR, NULL, "Ping limit (ms)", &cv_maxping, 50}, - {IT_STRING | IT_CVAR, NULL, "Connection timeout (tics)", &cv_nettimeout, 60}, - {IT_STRING | IT_CVAR, NULL, "Join timeout (tics)", &cv_jointimeout, 70}, + {IT_STRING | IT_CVAR, NULL, "Ping timeout (s)", &cv_pingtimeout, 60}, + {IT_STRING | IT_CVAR, NULL, "Connection timeout (tics)", &cv_nettimeout, 70}, + {IT_STRING | IT_CVAR, NULL, "Join timeout (tics)", &cv_jointimeout, 80}, - {IT_STRING | IT_CVAR, NULL, "Max. file transfer send (KB)", &cv_maxsend, 90}, - {IT_STRING | IT_CVAR, NULL, "File transfer packet rate", &cv_downloadspeed, 100}, + {IT_STRING | IT_CVAR, NULL, "Max. file transfer send (KB)", &cv_maxsend, 100}, + {IT_STRING | IT_CVAR, NULL, "File transfer packet rate", &cv_downloadspeed, 110}, - {IT_STRING | IT_CVAR, NULL, "Log join addresses", &cv_showjoinaddress, 120}, - {IT_STRING | IT_CVAR, NULL, "Log resyncs", &cv_blamecfail, 130}, - {IT_STRING | IT_CVAR, NULL, "Log file transfers", &cv_noticedownload, 140}, + {IT_STRING | IT_CVAR, NULL, "Log join addresses", &cv_showjoinaddress, 130}, + {IT_STRING | IT_CVAR, NULL, "Log resyncs", &cv_blamecfail, 140}, + {IT_STRING | IT_CVAR, NULL, "Log file transfers", &cv_noticedownload, 150}, }; #endif @@ -2379,6 +2391,9 @@ static void M_NextOpt(void) { INT16 oldItemOn = itemOn; // prevent infinite loop + if ((currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_PASSWORD) + ((consvar_t *)currentMenu->menuitems[itemOn].itemaction)->value = 0; + do { if (itemOn + 1 > currentMenu->numitems - 1) @@ -2392,6 +2407,9 @@ static void M_PrevOpt(void) { INT16 oldItemOn = itemOn; // prevent infinite loop + if ((currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_PASSWORD) + ((consvar_t *)currentMenu->menuitems[itemOn].itemaction)->value = 0; + do { if (!itemOn) @@ -2678,8 +2696,11 @@ boolean M_Responder(event_t *ev) // BP: one of the more big hack i have never made if (routine && (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_CVAR) { - if ((currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_STRING) + if ((currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_STRING || (currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_PASSWORD) { + if (ch == KEY_TAB && (currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_PASSWORD) + ((consvar_t *)currentMenu->menuitems[itemOn].itemaction)->value ^= 1; + if (shiftdown && ch >= 32 && ch <= 127) ch = shiftxform[ch]; if (M_ChangeStringCvar(ch)) @@ -2880,7 +2901,7 @@ void M_Drawer(void) } // focus lost notification goes on top of everything, even the former everything - if (window_notinfocus) + if (window_notinfocus && cv_showfocuslost.value) { M_DrawTextBox((BASEVIDWIDTH/2) - (60), (BASEVIDHEIGHT/2) - (16), 13, 2); if (gamestate == GS_LEVEL && (P_AutoPause() || paused)) @@ -3453,7 +3474,7 @@ static void M_DrawMapEmblems(INT32 mapnum, INT32 x, INT32 y) if (emblem->collected) V_DrawSmallMappedPatch(x, y, 0, W_CachePatchName(M_GetEmblemPatch(emblem), PU_CACHE), - R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(emblem), GTC_CACHE)); + R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(emblem), GTC_MENUCACHE)); else V_DrawSmallScaledPatch(x, y, 0, W_CachePatchName("NEEDIT", PU_CACHE)); @@ -3553,6 +3574,8 @@ static void M_DrawGenericMenu(void) case IT_CVAR: { consvar_t *cv = (consvar_t *)currentMenu->menuitems[i].itemaction; + char asterisks[MAXSTRINGLENGTH+1]; + size_t sl; switch (currentMenu->menuitems[i].status & IT_CVARTYPE) { case IT_CV_SLIDER: @@ -3560,6 +3583,27 @@ static void M_DrawGenericMenu(void) case IT_CV_NOPRINT: // color use this case IT_CV_INVISSLIDER: // monitor toggles use this break; + case IT_CV_PASSWORD: + if (i == itemOn) + { + V_DrawRightAlignedThinString(x + MAXSTRINGLENGTH*8 + 10, y, V_ALLOWLOWERCASE, va(M_GetText("Tab: %s password"), cv->value ? "hide" : "show")); + } + + if (!cv->value || i != itemOn) + { + sl = strlen(cv->string); + memset(asterisks, '*', sl); + memset(asterisks + sl, 0, MAXSTRINGLENGTH+1-sl); + + M_DrawTextBox(x, y + 4, MAXSTRINGLENGTH, 1); + V_DrawString(x + 8, y + 12, V_ALLOWLOWERCASE, asterisks); + if (skullAnimCounter < 4 && i == itemOn) + V_DrawCharacter(x + 8 + V_StringWidth(asterisks, 0), y + 12, + '_' | 0x80, false); + y += 16; + break; + } + /* fallthru */ case IT_CV_STRING: M_DrawTextBox(x, y + 4, MAXSTRINGLENGTH, 1); V_DrawString(x + 8, y + 12, V_ALLOWLOWERCASE, cv->string); @@ -3767,7 +3811,7 @@ static void M_DrawPauseMenu(void) if (emblem->collected) V_DrawSmallMappedPatch(40, 44 + (i*8), 0, W_CachePatchName(M_GetEmblemPatch(emblem), PU_CACHE), - R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(emblem), GTC_CACHE)); + R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(emblem), GTC_MENUCACHE)); else V_DrawSmallScaledPatch(40, 44 + (i*8), 0, W_CachePatchName("NEEDIT", PU_CACHE)); @@ -5315,7 +5359,7 @@ static void M_DrawEmblemHints(void) { collected = recommendedflags; V_DrawMappedPatch(12, 12+(28*j), 0, W_CachePatchName(M_GetEmblemPatch(emblem), PU_CACHE), - R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(emblem), GTC_CACHE)); + R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(emblem), GTC_MENUCACHE)); } else { @@ -5658,7 +5702,7 @@ static void M_DrawLoadGameData(void) V_DrawScaledPatch(SP_LoadDef.x,144+8,0,W_CachePatchName(skins[savegameinfo[saveSlotSelected].skinnum].face, PU_CACHE)); else { - UINT8 *colormap = R_GetTranslationColormap(savegameinfo[saveSlotSelected].skinnum, savegameinfo[saveSlotSelected].skincolor, 0); + UINT8 *colormap = R_GetTranslationColormap(savegameinfo[saveSlotSelected].skinnum, savegameinfo[saveSlotSelected].skincolor, GTC_MENUCACHE); V_DrawMappedPatch(SP_LoadDef.x,144+8,0,W_CachePatchName(skins[savegameinfo[saveSlotSelected].skinnum].face, PU_CACHE), colormap); } @@ -6348,7 +6392,7 @@ static void M_DrawStatsMaps(int location) if (exemblem->collected) V_DrawSmallMappedPatch(295, y, 0, W_CachePatchName(M_GetExtraEmblemPatch(exemblem), PU_CACHE), - R_GetTranslationColormap(TC_DEFAULT, M_GetExtraEmblemColor(exemblem), GTC_CACHE)); + R_GetTranslationColormap(TC_DEFAULT, M_GetExtraEmblemColor(exemblem), GTC_MENUCACHE)); else V_DrawSmallScaledPatch(295, y, 0, W_CachePatchName("NEEDIT", PU_CACHE)); @@ -6483,7 +6527,7 @@ void M_DrawTimeAttackMenu(void) // Character face! if (W_CheckNumForName(skins[cv_chooseskin.value-1].facewant) != LUMPERROR) { - UINT8 *colormap = R_GetTranslationColormap(cv_chooseskin.value-1, cv_playercolor.value, 0); + UINT8 *colormap = R_GetTranslationColormap(cv_chooseskin.value-1, cv_playercolor.value, GTC_MENUCACHE); V_DrawMappedPatch(BASEVIDWIDTH-x - SHORT(facewantprefix[cv_chooseskin.value-1]->width), y, 0, facewantprefix[cv_chooseskin.value-1], colormap); } @@ -6608,7 +6652,7 @@ void M_DrawTimeAttackMenu(void) if (em->collected) V_DrawMappedPatch(BASEVIDWIDTH - 64 - 24, y+48, 0, W_CachePatchName(M_GetEmblemPatch(em), PU_CACHE), - R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(em), GTC_CACHE)); + R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(em), GTC_MENUCACHE)); else V_DrawScaledPatch(BASEVIDWIDTH - 64 - 24, y+48, 0, W_CachePatchName("NEEDIT", PU_CACHE)); @@ -6768,7 +6812,7 @@ static boolean M_QuitTimeAttackMenu(void) if (em->collected) V_DrawSmallMappedPatch(160+88, yHeight, 0, W_CachePatchName(M_GetEmblemPatch(em), PU_CACHE), - R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(em), GTC_CACHE)); + R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(em), GTC_MENUCACHE)); else V_DrawSmallScaledPatch(160+88, yHeight, 0, W_CachePatchName("NEEDIT", PU_CACHE)); @@ -7239,6 +7283,7 @@ static void M_DrawConnectMenu(void) { UINT16 i, j; const char *gt = "Unknown"; + const char *spd = ""; INT32 numPages = (serverlistcount+(SERVERS_PER_PAGE-1))/SERVERS_PER_PAGE; for (i = FIRSTSERVERLINE; i < min(localservercount, SERVERS_PER_PAGE)+FIRSTSERVERLINE; i++) @@ -7292,7 +7337,17 @@ static void M_DrawConnectMenu(void) V_DrawSmallString(currentMenu->x+46,S_LINEY(i)+8, globalflags, va("Players: %02d/%02d", serverlist[slindex].info.numberofplayer, serverlist[slindex].info.maxplayer)); - V_DrawSmallString(currentMenu->x+112, S_LINEY(i)+8, globalflags, va("Gametype: %s", gt)); + V_DrawSmallString(currentMenu->x+112, S_LINEY(i)+8, globalflags, gt); + + if (serverlist[slindex].info.gametype == GT_RACE) + { + spd = kartspeed_cons_t[serverlist[slindex].info.kartvars & SV_SPEEDMASK].strvalue; + + V_DrawSmallString(currentMenu->x+132, S_LINEY(i)+8, globalflags, va("(%s Speed)", spd)); + } + + if (serverlist[slindex].info.kartvars & SV_PASSWORD) + V_DrawFixedPatch((currentMenu->x - 9) << FRACBITS, (S_LINEY(i)) << FRACBITS, FRACUNIT, globalflags & (~V_ALLOWLOWERCASE), W_CachePatchName("SERVLOCK", PU_CACHE), NULL); MP_ConnectMenu[i+FIRSTSERVERLINE].status = IT_STRING | IT_CALL; } @@ -7527,6 +7582,11 @@ static void M_StartServer(INT32 choice) // Still need to reset devmode cv_debug = 0; + if (strlen(cv_dummyjoinpassword.string) > 0) + D_SetJoinPassword(cv_dummyjoinpassword.string); + else + joinpasswordset = false; + if (demoplayback) G_StopDemo(); if (metalrecording) @@ -7828,7 +7888,7 @@ Update the maxplayers label... if (!trans && i > cv_splitplayers.value) trans = V_TRANSLUCENT; - colmap = R_GetTranslationColormap(pskin, pcol, 0); + colmap = R_GetTranslationColormap(pskin, pcol, GTC_MENUCACHE); V_DrawFixedPatch(x< #endif +#define MD5_LEN 16 + /* The following contortions are an attempt to use the C preprocessor to determine an unsigned integral type that is 32 bits wide. An alternative approach is to use autoconf's AC_CHECK_SIZEOF macro, but diff --git a/src/p_enemy.c b/src/p_enemy.c index b01f9be6..6d5137c4 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -8640,6 +8640,7 @@ void A_LightningFollowPlayer(mobj_t *actor) else // else just teleport to player directly P_TeleportMove(actor, actor->target->x, actor->target->y, actor->target->z); + K_MatchGenericExtraFlags(actor, actor->target); // copy our target for graviflip actor->momx = actor->target->momx; actor->momy = actor->target->momy; actor->momz = actor->target->momz; // Give momentum since we don't teleport to our player literally every frame. diff --git a/src/p_inter.c b/src/p_inter.c index 425461d5..90e7a06f 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -141,6 +141,9 @@ boolean P_CanPickupItem(player_t *player, UINT8 weapon) || (weapon != 3 && player->kartstuff[k_itemamount]) || player->kartstuff[k_itemheld]) return false; + + if (weapon == 3 && player->kartstuff[k_itemtype] == KITEM_THUNDERSHIELD) + return false; // No stacking thunder shields! } } @@ -411,6 +414,12 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) player->kartstuff[k_roulettetype] = 2; } +#if 0 + // Eggbox snipe! + if (special->type == MT_EGGMANITEM && special->health > 1) + S_StartSound(toucher, sfx_bsnipe); +#endif + { mobj_t *poof = P_SpawnMobj(special->x, special->y, special->z, MT_EXPLODE); S_StartSound(poof, special->info->deathsound); @@ -1468,6 +1477,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) player->starpostz = special->z>>FRACBITS; player->starpostangle = special->angle; player->starpostnum = special->health; + player->kartstuff[k_starpostflip] = special->spawnpoint->options & MTF_OBJECTFLIP; // store flipping //S_StartSound(toucher, special->info->painsound); return; @@ -2952,66 +2962,6 @@ static void P_KillPlayer(player_t *player, mobj_t *source, INT32 damage) } } -/* -static inline void P_SuperDamage(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 damage) // SRB2kart - unused. -{ - fixed_t fallbackspeed; - angle_t ang; - - P_ForceFeed(player, 40, 10, TICRATE, 40 + min(damage, 100)*2); - - if (player->mo->eflags & MFE_VERTICALFLIP) - player->mo->z--; - else - player->mo->z++; - - if (player->mo->eflags & MFE_UNDERWATER) - P_SetObjectMomZ(player->mo, FixedDiv(10511*FRACUNIT,2600*FRACUNIT), false); - else - P_SetObjectMomZ(player->mo, FixedDiv(69*FRACUNIT,10*FRACUNIT), false); - - ang = R_PointToAngle2(inflictor->x, inflictor->y, player->mo->x, player->mo->y); - - // explosion and rail rings send you farther back, making it more difficult - // to recover - if (inflictor->flags2 & MF2_SCATTER && source) - { - fixed_t dist = P_AproxDistance(P_AproxDistance(source->x-player->mo->x, source->y-player->mo->y), source->z-player->mo->z); - - dist = FixedMul(128*FRACUNIT, inflictor->scale) - dist/4; - - if (dist < FixedMul(4*FRACUNIT, inflictor->scale)) - dist = FixedMul(4*FRACUNIT, inflictor->scale); - - fallbackspeed = dist; - } - else if (inflictor->flags2 & MF2_EXPLOSION) - { - if (inflictor->flags2 & MF2_RAILRING) - fallbackspeed = FixedMul(28*FRACUNIT, inflictor->scale); // 7x - else - fallbackspeed = FixedMul(20*FRACUNIT, inflictor->scale); // 5x - } - else if (inflictor->flags2 & MF2_RAILRING) - fallbackspeed = FixedMul(16*FRACUNIT, inflictor->scale); // 4x - else - fallbackspeed = FixedMul(4*FRACUNIT, inflictor->scale); // the usual amount of force - - P_InstaThrust(player->mo, ang, fallbackspeed); - - // SRB2kart - This shouldn't be reachable, but this frame is invalid. - //if (player->charflags & SF_SUPERANIMS) - // P_SetPlayerMobjState(player->mo, S_PLAY_SUPERHIT); - //else - P_SetPlayerMobjState(player->mo, player->mo->info->painstate); - - P_ResetPlayer(player); - - if (player->timeshit != UINT8_MAX) - ++player->timeshit; -} -*/ - void P_RemoveShield(player_t *player) { if (player->powers[pw_shield] & SH_FORCE) diff --git a/src/p_local.h b/src/p_local.h index 12d582aa..21fb3ddb 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -276,8 +276,6 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled void P_Attract(mobj_t *source, mobj_t *enemy, boolean nightsgrab); mobj_t *P_GetClosestAxis(mobj_t *source); -boolean P_CanRunOnWater(player_t *player, ffloor_t *rover); - void P_FlashPal(player_t *pl, UINT16 type, UINT16 duration); #define PAL_WHITE 1 #define PAL_MIXUP 2 diff --git a/src/p_map.c b/src/p_map.c index 41e5a455..256c9cef 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -747,6 +747,9 @@ static boolean PIT_CheckThing(mobj_t *thing) && !(tmthing->type == MT_ORBINAUT || tmthing->type == MT_JAWZ || tmthing->type == MT_JAWZ_DUD)) return true; + if (thing->player && thing->player->kartstuff[k_hyudorotimer]) + return true; // no interaction + if (thing->type == MT_PLAYER) { // Player Damage @@ -850,7 +853,7 @@ static boolean PIT_CheckThing(mobj_t *thing) if (thing->type == MT_PLAYER) { - S_StartSound(NULL, sfx_cgot); //let all players hear it. + S_StartSound(NULL, sfx_bsnipe); //let all players hear it. HU_SetCEchoFlags(0); HU_SetCEchoDuration(5); HU_DoCEcho(va("%s\\was hit by a kitchen sink.\\\\\\\\", player_names[thing->player-players])); @@ -912,6 +915,10 @@ static boolean PIT_CheckThing(mobj_t *thing) if (thing->type == MT_PLAYER) { + // Banana snipe! + if (tmthing->type == MT_BANANA && tmthing->health > 1) + S_StartSound(thing, sfx_bsnipe); + // Player Damage K_SpinPlayer(thing->player, tmthing->target, 0, tmthing, (tmthing->type == MT_BANANA || tmthing->type == MT_BANANA_SHIELD)); @@ -980,7 +987,12 @@ static boolean PIT_CheckThing(mobj_t *thing) if (thing->type == MT_PLAYER) { - P_KillMobj(tmthing, thing, thing); + // Bomb punting + if ((tmthing->state >= &states[S_SSMINE1] && tmthing->state <= &states[S_SSMINE4]) + || (tmthing->state >= &states[S_SSMINE_DEPLOY8] && tmthing->state <= &states[S_SSMINE_DEPLOY13])) + P_KillMobj(tmthing, thing, thing); + else + K_PuntMine(tmthing, thing); } else if (thing->type == MT_ORBINAUT || thing->type == MT_JAWZ || thing->type == MT_JAWZ_DUD || thing->type == MT_ORBINAUT_SHIELD || thing->type == MT_JAWZ_SHIELD) @@ -1021,6 +1033,9 @@ static boolean PIT_CheckThing(mobj_t *thing) && !(thing->type == MT_ORBINAUT || thing->type == MT_JAWZ || thing->type == MT_JAWZ_DUD)) return true; + if (tmthing->player && tmthing->player->kartstuff[k_hyudorotimer]) // I thought about doing this for just the objects below but figured it should apply to everything. + return true; // no interaction + if (thing->type == MT_ORBINAUT_SHIELD || thing->type == MT_JAWZ_SHIELD || thing->type == MT_ORBINAUT || thing->type == MT_JAWZ || thing->type == MT_JAWZ_DUD) { @@ -1056,6 +1071,10 @@ static boolean PIT_CheckThing(mobj_t *thing) if (tmthing->health <= 0 || thing->health <= 0) return true; + // Banana snipe! + if (thing->type == MT_BANANA && thing->health > 1) + S_StartSound(tmthing, sfx_bsnipe); + // Player Damage K_SpinPlayer(tmthing->player, thing->target, 0, tmthing, (thing->type == MT_BANANA || thing->type == MT_BANANA_SHIELD)); @@ -1079,7 +1098,12 @@ static boolean PIT_CheckThing(mobj_t *thing) if (tmthing->health <= 0 || thing->health <= 0) return true; - P_KillMobj(thing, tmthing, tmthing); + // Bomb punting + if ((thing->state >= &states[S_SSMINE1] && thing->state <= &states[S_SSMINE4]) + || (thing->state >= &states[S_SSMINE_DEPLOY8] && thing->state <= &states[S_SSMINE_DEPLOY13])) + P_KillMobj(thing, tmthing, tmthing); + else + K_PuntMine(thing, tmthing); } else if (thing->type == MT_MINEEXPLOSION && tmthing->player) { @@ -2090,7 +2114,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) continue; } - if (thing->player && (P_CheckSolidLava(thing, rover) || P_CanRunOnWater(thing->player, rover))) + if (thing->player && P_CheckSolidLava(thing, rover)) ; else if (thing->type == MT_SKIM && (rover->flags & FF_SWIMMABLE)) ; @@ -2763,8 +2787,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) thing->eflags |= MFE_JUSTSTEPPEDDOWN; } #ifdef ESLOPE - // HACK TO FIX DSZ2: apply only if slopes are involved - else if (tmceilingslope && tmceilingz < thingtop && thingtop - tmceilingz <= maxstep) + else if (tmceilingz < thingtop && thingtop - tmceilingz <= maxstep) { thing->z = (thing->ceilingz = thingtop = tmceilingz) - thing->height; thing->eflags |= MFE_JUSTSTEPPEDDOWN; @@ -2777,8 +2800,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) thing->eflags |= MFE_JUSTSTEPPEDDOWN; } #ifdef ESLOPE - // HACK TO FIX DSZ2: apply only if slopes are involved - else if (tmfloorslope && tmfloorz > thing->z && tmfloorz - thing->z <= maxstep) + else if (tmfloorz > thing->z && tmfloorz - thing->z <= maxstep) { thing->z = thing->floorz = tmfloorz; thing->eflags |= MFE_JUSTSTEPPEDDOWN; diff --git a/src/p_maputl.c b/src/p_maputl.c index 1be57399..c5a593d3 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -649,7 +649,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if (!(rover->flags & FF_EXISTS)) continue; - if (mobj->player && (P_CheckSolidLava(mobj, rover) || P_CanRunOnWater(mobj->player, rover))) + if (mobj->player && P_CheckSolidLava(mobj, rover)) ; else if (!((rover->flags & FF_BLOCKPLAYER && mobj->player) || (rover->flags & FF_BLOCKOTHERS && !mobj->player))) @@ -693,7 +693,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if (!(rover->flags & FF_EXISTS)) continue; - if (mobj->player && (P_CheckSolidLava(mobj, rover) || P_CanRunOnWater(mobj->player, rover))) + if (mobj->player && P_CheckSolidLava(mobj, rover)) ; else if (!((rover->flags & FF_BLOCKPLAYER && mobj->player) || (rover->flags & FF_BLOCKOTHERS && !mobj->player))) diff --git a/src/p_mobj.c b/src/p_mobj.c index 4be4afd9..484d34fb 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -167,58 +167,8 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state) I_Error("P_SetPlayerMobjState used for non-player mobj. Use P_SetMobjState instead!\n(Mobj type: %d, State: %d)", mobj->type, state); #endif - // Catch state changes for Super Sonic - /* // SRB2kart - don't need - if (player->powers[pw_super] && (player->charflags & SF_SUPERANIMS)) - { - switch (state) - { - case S_PLAY_STND: - case S_PLAY_TAP1: - case S_PLAY_TAP2: - case S_PLAY_GASP: - P_SetPlayerMobjState(mobj, S_PLAY_SUPERSTAND); - return true; - case S_PLAY_FALL1: - case S_PLAY_SPRING: - case S_PLAY_RUN1: - case S_PLAY_RUN2: - case S_PLAY_RUN3: - case S_PLAY_RUN4: - P_SetPlayerMobjState(mobj, S_PLAY_SUPERWALK1); - return true; - case S_PLAY_FALL2: - case S_PLAY_RUN5: - case S_PLAY_RUN6: - case S_PLAY_RUN7: - case S_PLAY_RUN8: - P_SetPlayerMobjState(mobj, S_PLAY_SUPERWALK2); - return true; - case S_PLAY_SPD1: - case S_PLAY_SPD2: - P_SetPlayerMobjState(mobj, S_PLAY_SUPERFLY1); - return true; - case S_PLAY_SPD3: - case S_PLAY_SPD4: - P_SetPlayerMobjState(mobj, S_PLAY_SUPERFLY2); - return true; - case S_PLAY_TEETER1: - case S_PLAY_TEETER2: - P_SetPlayerMobjState(mobj, S_PLAY_SUPERTEETER); - return true; - case S_PLAY_ATK1: - case S_PLAY_ATK2: - case S_PLAY_ATK3: - case S_PLAY_ATK4: - if (!(player->charflags & SF_SUPERSPIN)) - return true; - break; - default: - break; - } - } // You were in pain state after taking a hit, and you're moving out of pain state now? - else */if (mobj->state == &states[mobj->info->painstate] && player->powers[pw_flashing] == K_GetKartFlashing(player) && state != mobj->info->painstate) + if (mobj->state == &states[mobj->info->painstate] && player->powers[pw_flashing] == K_GetKartFlashing(player) && state != mobj->info->painstate) { // Start flashing, since you've landed. player->powers[pw_flashing] = K_GetKartFlashing(player)-1; @@ -260,51 +210,6 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state) st = &states[state]; mobj->state = st; mobj->tics = st->tics; - - // Adjust the player's animation speed to match their velocity. - if (!(disableSpeedAdjust || player->charflags & SF_NOSPEEDADJUST)) - { - fixed_t speed = FixedDiv(player->speed, FixedMul(mobj->scale, player->mo->movefactor)); // fixed_t speed = FixedDiv(player->speed, mobj->scale); - if (player->panim == PA_ROLL) - { - if (speed > 16<tics = 1; - else - mobj->tics = 2; - } - else if (player->panim == PA_FALL) - { - speed = FixedDiv(abs(mobj->momz), mobj->scale); - if (speed < 10<tics = 4; - else if (speed < 20<tics = 3; - else if (speed < 30<tics = 2; - else - mobj->tics = 1; - } - else if (P_IsObjectOnGround(mobj) || player->powers[pw_super]) // Only if on the ground or superflying. - { - if (player->panim == PA_WALK) - { - if (speed > 12<tics = 2; - else if (speed > 6<tics = 3; - else - mobj->tics = 4; - } - else if (player->panim == PA_RUN) - { - if (speed > 52<tics = 1; - else - mobj->tics = 2; - } - } - } - mobj->sprite = st->sprite; mobj->frame = st->frame; mobj->anim_duration = (UINT16)st->var2; // only used if FF_ANIMATE is set @@ -1404,11 +1309,14 @@ fixed_t P_GetMobjGravity(mobj_t *mo) break; case MT_BANANA: case MT_EGGMANITEM: + case MT_SSMINE: + case MT_SINK: + if (mo->extravalue2 > 0) + gravityadd *= mo->extravalue2; + /* FALLTHRU */ case MT_ORBINAUT: case MT_JAWZ: case MT_JAWZ_DUD: - case MT_SSMINE: - case MT_SINK: gravityadd = (5*gravityadd)/2; break; case MT_SIGN: @@ -2099,7 +2007,7 @@ static void P_AdjustMobjFloorZ_FFloors(mobj_t *mo, sector_t *sector, UINT8 motyp topheight = P_GetFOFTopZ(mo, sector, rover, mo->x, mo->y, NULL); bottomheight = P_GetFOFBottomZ(mo, sector, rover, mo->x, mo->y, NULL); - if (mo->player && (P_CheckSolidLava(mo, rover) || P_CanRunOnWater(mo->player, rover))) // only the player should be affected + if (mo->player && P_CheckSolidLava(mo, rover)) // only the player should be affected ; else if (motype != 0 && rover->flags & FF_SWIMMABLE) // "scenery" only continue; @@ -3222,27 +3130,6 @@ static boolean P_SceneryZMovement(mobj_t *mo) return true; } -// P_CanRunOnWater -// -// Returns true if player can waterrun on the 3D floor -// -boolean P_CanRunOnWater(player_t *player, ffloor_t *rover) -{ - fixed_t topheight = -#ifdef ESLOPE - *rover->t_slope ? P_GetZAt(*rover->t_slope, player->mo->x, player->mo->y) : -#endif - *rover->topheight; - - if (((player->charflags & SF_RUNONWATER) && player->mo->ceilingz-topheight >= player->mo->height) - && (rover->flags & FF_SWIMMABLE) && !(player->pflags & PF_SPINNING) && player->speed > FixedMul(player->runspeed, player->mo->scale) - && !(player->pflags & PF_SLIDING) - && abs(player->mo->z - topheight) < FixedMul(30*FRACUNIT, player->mo->scale)) - return true; - - return false; -} - // // P_MobjCheckWater // @@ -3399,8 +3286,8 @@ void P_MobjCheckWater(mobj_t *mobj) // skipping stone! if (p && p->kartstuff[k_waterskip] < 2 - && ((p->speed/2 > abs(mobj->momz)) // Going more forward than horizontal, so you can skip across the water. - || (p->speed > K_GetKartSpeed(p,false)/4 && p->kartstuff[k_waterskip])) // Already skipped once, so you can skip once more! + && ((p->speed/3 > abs(mobj->momz)) // Going more forward than horizontal, so you can skip across the water. + || (p->speed > K_GetKartSpeed(p,false)/3 && p->kartstuff[k_waterskip])) // Already skipped once, so you can skip once more! && ((!(mobj->eflags & MFE_VERTICALFLIP) && thingtop - mobj->momz > mobj->watertop) || ((mobj->eflags & MFE_VERTICALFLIP) && mobj->z - mobj->momz < mobj->waterbottom))) { @@ -6637,7 +6524,7 @@ void P_MobjThinker(mobj_t *mobj) case MT_SINK_SHIELD: if ((mobj->health > 0 && (!mobj->target || !mobj->target->player || mobj->target->player->health <= 0 || mobj->target->player->spectator)) - || (mobj->health <= 0 && mobj->z <= mobj->floorz) + || (mobj->health <= 0 && P_IsObjectOnGround(mobj)) || P_CheckDeathPitCollide(mobj)) // When in death state { P_RemoveMobj(mobj); @@ -6651,19 +6538,22 @@ void P_MobjThinker(mobj_t *mobj) fixed_t y = P_RandomRange(-35, 35)*mobj->scale; fixed_t z = P_RandomRange(0, 70)*mobj->scale; mobj_t *smoke = P_SpawnMobj(mobj->x + x, mobj->y + y, mobj->z + z, MT_SMOKE); + P_SetMobjState(smoke, S_OPAQUESMOKE1); + K_MatchGenericExtraFlags(smoke, mobj); smoke->scale = mobj->scale * 2; smoke->destscale = mobj->scale * 6; - smoke->momz = P_RandomRange(4, 9)*FRACUNIT; + smoke->momz = P_RandomRange(4, 9)*FRACUNIT*P_MobjFlip(smoke); } break; case MT_BOOMPARTICLE: { fixed_t x = P_RandomRange(-16, 16)*mobj->scale; fixed_t y = P_RandomRange(-16, 16)*mobj->scale; - fixed_t z = P_RandomRange(0, 32)*mobj->scale; + fixed_t z = P_RandomRange(0, 32)*mobj->scale*P_MobjFlip(mobj); if (leveltime % 2 == 0) { mobj_t *smoke = P_SpawnMobj(mobj->x + x, mobj->y + y, mobj->z + z, MT_BOSSEXPLODE); + K_MatchGenericExtraFlags(smoke, mobj); P_SetMobjState(smoke, S_QUICKBOOM1); smoke->scale = mobj->scale/2; smoke->destscale = mobj->scale; @@ -6672,6 +6562,8 @@ void P_MobjThinker(mobj_t *mobj) else { mobj_t *smoke = P_SpawnMobj(mobj->x + x, mobj->y + y, mobj->z + z, MT_SMOKE); + P_SetMobjState(smoke, S_OPAQUESMOKE1); + K_MatchGenericExtraFlags(smoke, mobj); smoke->scale = mobj->scale; smoke->destscale = mobj->scale*2; } @@ -6777,7 +6669,7 @@ void P_MobjThinker(mobj_t *mobj) } else if ((mobj->health > 0 && (!mobj->target || !mobj->target->player || !mobj->target->player->mo || mobj->target->player->health <= 0 || mobj->target->player->spectator)) - || (mobj->health <= 0 && mobj->z <= mobj->floorz) + || (mobj->health <= 0 && P_IsObjectOnGround(mobj)) || P_CheckDeathPitCollide(mobj)) // When in death state { P_RemoveMobj(mobj); @@ -7225,6 +7117,9 @@ void P_MobjThinker(mobj_t *mobj) y = mobj->target->y; z = mobj->target->z + (80*mapobjectscale); } + if (mobj->target->eflags & MFE_VERTICALFLIP) + z += mobj->target->height - FixedMul(mobj->target->scale, mobj->height); + P_TeleportMove(mobj, x, y, z); } break; @@ -7420,7 +7315,7 @@ void P_MobjThinker(mobj_t *mobj) case MT_BANANA: case MT_EGGMANITEM: case MT_SPB: - if (mobj->z <= mobj->floorz) + if (P_IsObjectOnGround(mobj)) { P_RemoveMobj(mobj); return; @@ -7433,7 +7328,7 @@ void P_MobjThinker(mobj_t *mobj) break; case MT_JAWZ: case MT_JAWZ_DUD: - if (mobj->z <= mobj->floorz) + if (P_IsObjectOnGround(mobj)) P_SetMobjState(mobj, mobj->info->xdeathstate); // fallthru case MT_JAWZ_SHIELD: @@ -7467,7 +7362,7 @@ void P_MobjThinker(mobj_t *mobj) /* FALLTHRU */ case MT_SMK_MOLE: mobj->flags2 ^= MF2_DONTDRAW; - if (mobj->z <= mobj->floorz) + if (P_IsObjectOnGround(mobj)) { P_RemoveMobj(mobj); return; @@ -7488,7 +7383,7 @@ void P_MobjThinker(mobj_t *mobj) } mobj->flags2 ^= MF2_DONTDRAW; - if (mobj->z <= mobj->floorz) + if (P_IsObjectOnGround(mobj)) { P_RemoveMobj(mobj); return; @@ -8157,7 +8052,7 @@ void P_MobjThinker(mobj_t *mobj) mobj->friction = ORIG_FRICTION/4; if (mobj->momx || mobj->momy) P_SpawnGhostMobj(mobj); - if (mobj->z <= mobj->floorz && mobj->health > 1) + if (P_IsObjectOnGround(mobj) && mobj->health > 1) { S_StartSound(mobj, mobj->info->activesound); mobj->momx = mobj->momy = 0; @@ -8177,7 +8072,7 @@ void P_MobjThinker(mobj_t *mobj) case MT_SINK: if (mobj->momx || mobj->momy) P_SpawnGhostMobj(mobj); - if (mobj->z <= mobj->floorz) + if (P_IsObjectOnGround(mobj)) { S_StartSound(mobj, mobj->info->deathsound); P_SetMobjState(mobj, S_NULL); @@ -8190,28 +8085,26 @@ void P_MobjThinker(mobj_t *mobj) mobj->color = mobj->target->player->skincolor; else mobj->color = SKINCOLOR_KETCHUP; + if (mobj->momx || mobj->momy) P_SpawnGhostMobj(mobj); - if (P_IsObjectOnGround(mobj)) + + if (P_IsObjectOnGround(mobj) && (mobj->state == &states[S_SSMINE_AIR1] || mobj->state == &states[S_SSMINE_AIR2])) { - if (mobj->state == &states[S_SSMINE_AIR1] || mobj->state == &states[S_SSMINE_AIR2]) - P_SetMobjState(mobj, S_SSMINE_DEPLOY1); - if (mobj->reactiontime >= mobj->info->reactiontime) + if (mobj->extravalue1 > 0) + mobj->extravalue1--; + else { mobj->momx = mobj->momy = 0; S_StartSound(mobj, mobj->info->activesound); - mobj->reactiontime--; + P_SetMobjState(mobj, S_SSMINE_DEPLOY1); } } - if (mobj->reactiontime && mobj->reactiontime < mobj->info->reactiontime) - { - mobj->reactiontime--; - if (!mobj->reactiontime) - P_KillMobj(mobj, NULL, NULL); - } + if ((mobj->state >= &states[S_SSMINE1] && mobj->state <= &states[S_SSMINE4]) || (mobj->state >= &states[S_SSMINE_DEPLOY8] && mobj->state <= &states[S_SSMINE_DEPLOY13])) A_GrenadeRing(mobj); + if (mobj->threshold > 0) mobj->threshold--; break; @@ -8355,6 +8248,7 @@ void P_MobjThinker(mobj_t *mobj) break; case MT_INSTASHIELDB: mobj->flags2 ^= MF2_DONTDRAW; + K_MatchGenericExtraFlags(mobj, mobj->target); /* FALLTHRU */ case MT_INSTASHIELDA: if (!mobj->target || !mobj->target->health || (mobj->target->player && !mobj->target->player->kartstuff[k_instashield])) @@ -8363,6 +8257,7 @@ void P_MobjThinker(mobj_t *mobj) return; } P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z); + K_MatchGenericExtraFlags(mobj, mobj->target); break; case MT_BATTLEPOINT: if (!mobj->target || P_MobjWasRemoved(mobj->target)) @@ -8383,7 +8278,7 @@ void P_MobjThinker(mobj_t *mobj) if (mobj->movefactor < mobj->target->height) mobj->movefactor = mobj->target->height; } - + K_MatchGenericExtraFlags(mobj, mobj->target); P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z + (mobj->target->height/2) + mobj->movefactor); break; case MT_THUNDERSHIELD: @@ -8508,6 +8403,10 @@ void P_MobjThinker(mobj_t *mobj) mobj->flags2 &= ~MF2_DONTDRAW; } + // Update mobj antigravity status: + mobj->eflags = (mobj->eflags & ~MFE_VERTICALFLIP)|(mobj->target->eflags & MFE_VERTICALFLIP); + mobj->flags2 = (mobj->flags2 & ~MF2_OBJECTFLIP)|(mobj->target->flags2 & MF2_OBJECTFLIP); + // Now for the wheels { const fixed_t rad = FixedMul(mobjinfo[MT_PLAYER].radius, mobj->target->scale); @@ -8529,6 +8428,7 @@ void P_MobjThinker(mobj_t *mobj) P_SetScale(cur, mobj->target->scale); cur->color = mobj->target->color; cur->colorized = true; + K_FlipFromObject(cur, mobj->target); if (mobj->flags2 & MF2_DONTDRAW) cur->flags2 |= MF2_DONTDRAW; @@ -11125,7 +11025,7 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing) if (mthing->options >> ZSHIFT) z -= ((mthing->options >> ZSHIFT) << FRACBITS); if (p->kartstuff[k_respawn]) - z -= 128*FRACUNIT; // Too late for v1, but for later: 128*mapobjectscale; + z -= 128*mapobjectscale; } else { @@ -11133,7 +11033,7 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing) if (mthing->options >> ZSHIFT) z += ((mthing->options >> ZSHIFT) << FRACBITS); if (p->kartstuff[k_respawn]) - z += 128*FRACUNIT; // Too late for v1, but for later: 128*mapobjectscale; + z += 128*mapobjectscale; } if (mthing->options & MTF_OBJECTFLIP) // flip the player! @@ -11194,7 +11094,14 @@ void P_MovePlayerToStarpost(INT32 playernum) #endif sector->ceilingheight; - z = (p->starpostz + 128) << FRACBITS; // Respawn off the ground + if (mobj->player->kartstuff[k_starpostflip]) + z = (p->starpostz<height; + else + z = (p->starpostz<starpostz + 128) << FRACBITS; // reverse gravity exists, pls + mobj->player->kartstuff[k_starpostflip] = 0; + if (z < floor) z = floor; else if (z > ceiling - mobjinfo[MT_PLAYER].height) diff --git a/src/p_saveg.c b/src/p_saveg.c index 52a35c37..c1a34b2a 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -249,6 +249,8 @@ static void P_NetArchivePlayers(void) WRITEUINT32(save_p, players[i].jointime); + WRITEUINT8(save_p, players[i].splitscreenindex); + WRITEUINT16(save_p, flags); if (flags & CAPSULE) @@ -426,6 +428,8 @@ static void P_NetUnArchivePlayers(void) players[i].jointime = READUINT32(save_p); + players[i].splitscreenindex = READUINT8(save_p); + flags = READUINT16(save_p); if (flags & CAPSULE) @@ -675,8 +679,6 @@ static void P_NetArchiveWorld(void) WRITEUINT16(put, 0xffff); - mld = W_CacheLumpNum(lastloadedmaplumpnum+ML_LINEDEFS, PU_CACHE); - msd = W_CacheLumpNum(lastloadedmaplumpnum+ML_SIDEDEFS, PU_CACHE); // do lines for (i = 0; i < numlines; i++, mld++, li++) { @@ -695,13 +697,13 @@ static void P_NetArchiveWorld(void) diff |= LD_S1TEXOFF; //SoM: 4/1/2000: Some textures are colormaps. Don't worry about invalid textures. if (R_CheckTextureNumForName(msd[li->sidenum[0]].toptexture) != -1 - && si->toptexture != R_TextureNumForName(msd[li->sidenum[0]].toptexture)) + && si->toptexture != R_TextureNumForName(msd[li->sidenum[0]].toptexture)) diff |= LD_S1TOPTEX; if (R_CheckTextureNumForName(msd[li->sidenum[0]].bottomtexture) != -1 - && si->bottomtexture != R_TextureNumForName(msd[li->sidenum[0]].bottomtexture)) + && si->bottomtexture != R_TextureNumForName(msd[li->sidenum[0]].bottomtexture)) diff |= LD_S1BOTTEX; if (R_CheckTextureNumForName(msd[li->sidenum[0]].midtexture) != -1 - && si->midtexture != R_TextureNumForName(msd[li->sidenum[0]].midtexture)) + && si->midtexture != R_TextureNumForName(msd[li->sidenum[0]].midtexture)) diff |= LD_S1MIDTEX; } if (li->sidenum[1] != 0xffff) @@ -710,13 +712,13 @@ static void P_NetArchiveWorld(void) if (si->textureoffset != SHORT(msd[li->sidenum[1]].textureoffset)<sidenum[1]].toptexture) != -1 - && si->toptexture != R_TextureNumForName(msd[li->sidenum[1]].toptexture)) + && si->toptexture != R_TextureNumForName(msd[li->sidenum[1]].toptexture)) diff2 |= LD_S2TOPTEX; if (R_CheckTextureNumForName(msd[li->sidenum[1]].bottomtexture) != -1 - && si->bottomtexture != R_TextureNumForName(msd[li->sidenum[1]].bottomtexture)) + && si->bottomtexture != R_TextureNumForName(msd[li->sidenum[1]].bottomtexture)) diff2 |= LD_S2BOTTEX; if (R_CheckTextureNumForName(msd[li->sidenum[1]].midtexture) != -1 - && si->midtexture != R_TextureNumForName(msd[li->sidenum[1]].midtexture)) + && si->midtexture != R_TextureNumForName(msd[li->sidenum[1]].midtexture)) diff2 |= LD_S2MIDTEX; if (diff2) diff |= LD_DIFF2; @@ -3313,6 +3315,7 @@ static void P_NetArchiveMisc(void) WRITEUINT32(save_p, wantedcalcdelay); WRITEUINT32(save_p, indirectitemcooldown); + WRITEUINT32(save_p, hyubgone); WRITEUINT32(save_p, mapreset); WRITEUINT8(save_p, nospectategrief); WRITEUINT8(save_p, thwompsactive); @@ -3421,6 +3424,7 @@ static inline boolean P_NetUnArchiveMisc(void) wantedcalcdelay = READUINT32(save_p); indirectitemcooldown = READUINT32(save_p); + hyubgone = READUINT32(save_p); mapreset = READUINT32(save_p); nospectategrief = READUINT8(save_p); thwompsactive = (boolean)READUINT8(save_p); diff --git a/src/p_setup.c b/src/p_setup.c index de250b1f..3e96b101 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3257,6 +3257,7 @@ boolean P_SetupLevel(boolean skipprecip) wantedcalcdelay = wantedfrequency*2; indirectitemcooldown = 0; + hyubgone = 0; mapreset = 0; nospectategrief = 0; thwompsactive = false; diff --git a/src/p_spec.c b/src/p_spec.c index 24f56c43..67bb7472 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -4247,13 +4247,14 @@ DoneSection2: player->starpostx = player->mo->x>>FRACBITS; player->starposty = player->mo->y>>FRACBITS; player->starpostz = player->mo->floorz>>FRACBITS; + player->kartstuff[k_starpostflip] = player->mo->flags2 & MF2_OBJECTFLIP; // store flipping player->starpostangle = player->mo->angle; //R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy); torn; a momentum-based guess is less likely to be wrong in general, but when it IS wrong, it fucks you over entirely... } else { // SRB2kart 200117 // Reset starposts (checkpoints) info - player->starpostangle = player->starpostx = player->starposty = player->starpostz = 0; + player->starpostangle = player->starpostx = player->starposty = player->starpostz = player->kartstuff[k_starpostflip] = 0; } if (P_IsLocalPlayer(player)) diff --git a/src/p_tick.c b/src/p_tick.c index b422e9d2..6fd2e09f 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -700,6 +700,8 @@ void P_Ticker(boolean run) if (indirectitemcooldown) indirectitemcooldown--; + if (hyubgone) + hyubgone--; if (G_BattleGametype()) { diff --git a/src/p_user.c b/src/p_user.c index 180a35b0..72949c92 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -172,7 +172,7 @@ boolean P_AutoPause(void) if (netgame || modeattacking || titledemo) return false; - return (menuactive || window_notinfocus); + return (menuactive || ( window_notinfocus && cv_pauseifunfocused.value )); } // @@ -3640,165 +3640,6 @@ static void P_DoFiring(player_t *player, ticcmd_t *cmd) // SRB2kart - unused. } */ -#if 0 -// -// P_DoSuperStuff() -// -// Handle related superform functionality. -// -static void P_DoSuperStuff(player_t *player) -{ - mobj_t *spark; - ticcmd_t *cmd = &player->cmd; - //if (player->mo->state >= &states[S_PLAY_SUPERTRANS1] && player->mo->state <= &states[S_PLAY_SUPERTRANS9]) - // return; // don't do anything right now, we're in the middle of transforming! - - if (player->pflags & PF_NIGHTSMODE) - return; // NiGHTS Super doesn't mix with normal super - - // Does player have all emeralds? If so, flag the "Ready For Super!" - /*if ((ALL7EMERALDS(emeralds) || ALL7EMERALDS(player->powers[pw_emeralds])) && player->health > 50) - player->pflags |= PF_SUPERREADY; - else - player->pflags &= ~PF_SUPERREADY;*/ - - if (player->powers[pw_super]) - { - // If you're super and not Sonic, de-superize! - if (!((ALL7EMERALDS(emeralds)) && (player->charflags & SF_SUPER)) && !(ALL7EMERALDS(player->powers[pw_emeralds]))) - { - player->powers[pw_super] = 0; - P_SetPlayerMobjState(player->mo, S_KART_STND1); - P_RestoreMusic(player); - P_SpawnShieldOrb(player); - - // Restore color - if (player->powers[pw_shield] & SH_FIREFLOWER) - { - player->mo->color = SKINCOLOR_WHITE; - G_GhostAddColor((INT32) (player - players), GHC_FIREFLOWER); - } - else - { - player->mo->color = player->skincolor; - G_GhostAddColor((INT32) (player - players), GHC_NORMAL); - } - - if (gametype != GT_COOP) - { - HU_SetCEchoFlags(0); - HU_SetCEchoDuration(5); - HU_DoCEcho(va("%s\\is no longer super.\\\\\\\\", player_names[player-players])); - } - return; - } - - // Deplete one ring every second while super - if ((leveltime % TICRATE == 0) && !(player->exiting)) - { - player->health--; - player->mo->health--; - } - - // future todo: a skin option for this, and possibly more colors - switch (player->skin) - { - case 1: /* Tails */ player->mo->color = SKINCOLOR_TSUPER1; break; - case 2: /* Knux */ player->mo->color = SKINCOLOR_KSUPER1; break; - default: /* everyone */ player->mo->color = SKINCOLOR_SUPER1; break; - } - player->mo->color += abs( ( (signed)( (unsigned)leveltime >> 1 ) % 9) - 4); - - if ((cmd->forwardmove != 0 || cmd->sidemove != 0 || player->pflags & (PF_CARRIED|PF_ROPEHANG|PF_ITEMHANG|PF_MACESPIN)) - && !(leveltime % TICRATE) && (player->mo->momx || player->mo->momy)) - { - spark = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_SUPERSPARK); - spark->destscale = player->mo->scale; - P_SetScale(spark, player->mo->scale); - } - - G_GhostAddColor((INT32) (player - players), GHC_SUPER); - - // Ran out of rings while super! - if (player->health <= 1 || player->exiting) - { - player->powers[pw_emeralds] = 0; // lost the power stones - P_SpawnGhostMobj(player->mo); - - player->powers[pw_super] = 0; - - // Restore color - if (player->powers[pw_shield] & SH_FIREFLOWER) - { - player->mo->color = SKINCOLOR_WHITE; - G_GhostAddColor((INT32) (player - players), GHC_FIREFLOWER); - } - else - { - player->mo->color = player->skincolor; - G_GhostAddColor((INT32) (player - players), GHC_NORMAL); - } - - if (gametype != GT_COOP) - player->powers[pw_flashing] = K_GetKartFlashing(player)-1; - -/* - if (player->mo->health > 0) - { - if ((player->pflags & PF_JUMPED) || (player->pflags & PF_SPINNING)) - P_SetPlayerMobjState(player->mo, S_PLAY_ATK1); - else if (player->panim == PA_RUN) - P_SetPlayerMobjState(player->mo, S_PLAY_SPD1); - else if (player->panim == PA_WALK) - P_SetPlayerMobjState(player->mo, S_PLAY_RUN1); - else - P_SetPlayerMobjState(player->mo, S_PLAY_STND); - - if (!player->exiting) - { - player->health = 1; - player->mo->health = 1; - } - } -*/ - - // Inform the netgame that the champion has fallen in the heat of battle. - if (gametype != GT_COOP) - { - S_StartSound(NULL, sfx_s3k66); //let all players hear it. - HU_SetCEchoFlags(0); - HU_SetCEchoDuration(5); - HU_DoCEcho(va("%s\\is no longer super.\\\\\\\\", player_names[player-players])); - } - - // Resume normal music if you're the console player - P_RestoreMusic(player); - - // If you had a shield, restore its visual significance. - P_SpawnShieldOrb(player); - } - } -} -#endif - -// -// P_SuperReady -// -// Returns true if player is ready to turn super, duh -// -/*boolean P_SuperReady(player_t *player) -{ - if ((player->pflags & PF_SUPERREADY) && !player->powers[pw_super] && !player->powers[pw_tailsfly] - && !(player->powers[pw_shield] & SH_NOSTACK) - && !player->powers[pw_invulnerability] - && !(maptol & TOL_NIGHTS) // don't turn 'regular super' in nights levels - && player->pflags & PF_JUMPED - && ((player->charflags & SF_SUPER) || ALL7EMERALDS(player->powers[pw_emeralds]))) - return true; - - return false; -}*/ - // // P_DoJump // @@ -6388,99 +6229,6 @@ void P_ElementalFireTrail(player_t *player) } } -/*static void P_SkidStuff(player_t *player) -{ - fixed_t pmx = player->rmomx + player->cmomx; - fixed_t pmy = player->rmomy + player->cmomy; - - // Knuckles glides into the dirt. - // SRB2kart - don't need - if (player->pflags & PF_GLIDING && player->skidtime) - { - // Fell off a ledge... - if (!onground) - { - player->skidtime = 0; - player->pflags &= ~(PF_GLIDING|PF_JUMPED); - P_SetPlayerMobjState(player->mo, S_PLAY_FALL1); - } - // Get up and brush yourself off, idiot. - else if (player->glidetime > 15) - { - P_ResetPlayer(player); - P_SetPlayerMobjState(player->mo, S_PLAY_STND); - player->mo->momx = player->cmomx; - player->mo->momy = player->cmomy; - } - // Didn't stop yet? Skid FOREVER! - else if (player->skidtime == 1) - player->skidtime = 3*TICRATE+1; - // Spawn a particle every 3 tics. - else if (!(player->skidtime % 3)) - { - mobj_t *particle = P_SpawnMobj(player->mo->x + P_RandomRange(-player->mo->radius, player->mo->radius), player->mo->y + P_RandomRange(-player->mo->radius, player->mo->radius), - player->mo->z + (player->mo->eflags & MFE_VERTICALFLIP ? player->mo->height - mobjinfo[MT_PARTICLE].height : 0), - MT_PARTICLE); - particle->tics = 10; - - particle->eflags |= player->mo->eflags & MFE_VERTICALFLIP; - P_SetScale(particle, player->mo->scale >> 2); - particle->destscale = player->mo->scale << 2; - particle->scalespeed = FixedMul(particle->scalespeed, player->mo->scale); // scale the scaling speed! - P_SetObjectMomZ(particle, FRACUNIT, false); - S_StartSound(player->mo, sfx_s3k7e); // the proper "Knuckles eats dirt" sfx. - } - } - // Skidding! - elseif (onground && !(player->mo->eflags & MFE_GOOWATER) && !(player->pflags & (PF_JUMPED|PF_SPINNING|PF_SLIDING)) && !(player->charflags & SF_NOSKID)) - { - if (player->skidtime) - { - // Spawn a particle every 3 tics. - if (!(player->skidtime % 3)) - { - mobj_t *particle = P_SpawnMobj(player->mo->x, player->mo->y, - player->mo->z + (player->mo->eflags & MFE_VERTICALFLIP ? player->mo->height - mobjinfo[MT_PARTICLE].height : 0), - MT_PARTICLE); - particle->tics = 10; - - particle->eflags |= player->mo->eflags & MFE_VERTICALFLIP; - P_SetScale(particle, player->mo->scale >> 2); - particle->destscale = player->mo->scale << 2; - particle->scalespeed = FixedMul(particle->scalespeed, player->mo->scale); // scale the scaling speed! - P_SetObjectMomZ(particle, FRACUNIT, false); - } - } - else if (P_AproxDistance(pmx, pmy) >= FixedMul(player->runspeed/2, player->mo->scale) // if you were moving faster than half your run speed last frame - && (player->mo->momx != pmx || player->mo->momy != pmy) // and you are moving differently this frame - && P_GetPlayerControlDirection(player) == 2) // and your controls are pointing in the opposite direction to your movement - { // check for skidding - angle_t mang = R_PointToAngle2(0,0,pmx,pmy); // movement angle - angle_t pang = R_PointToAngle2(pmx,pmy,player->mo->momx,player->mo->momy); // push angle - angle_t dang = mang - pang; // delta angle - - if (dang > ANGLE_180) // Make delta angle always positive, invert it if it's negative. - dang = InvAngle(dang); - - // If your push angle is more than this close to a full 180 degrees, trigger a skid. - if (dang > ANGLE_157h) - { - player->skidtime = (player->mo->movefactor == FRACUNIT) ? TICRATE/2 : (FixedDiv(35<<(FRACBITS-1), FixedSqrt(player->mo->movefactor)))>>FRACBITS; //player->skidtime = TICRATE/2; - S_StartSound(player->mo, sfx_skid); - if (player->panim != PA_WALK) - P_SetPlayerMobjState(player->mo, S_KART_WALK2); // SRB2kart - was S_PLAY_RUN4 - player->mo->tics = player->skidtime; - } - } - } - else { - if (player->skidtime) { - player->skidtime = 0; - S_StopSound(player->mo); - } - } -}*/ - // // P_MovePlayer static void P_MovePlayer(player_t *player) @@ -6668,7 +6416,7 @@ static void P_MovePlayer(player_t *player) //CONS_Printf("leftover turn (%s): %5d or %4d%%\n", // player_names[player-players], // (INT16) (cmd->angleturn - (player->mo->angle>>16)), - // (INT16) (cmd->angleturn - (player->mo->angle>>16)) * 100 / (angle_diff ?: 1)); + // (INT16) (cmd->angleturn - (player->mo->angle>>16)) * 100 / (angle_diff ? angle_diff : 1)); } } @@ -7660,12 +7408,14 @@ static void P_NukeAllPlayers(player_t *player) // void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius) { - const fixed_t ns = 60 << FRACBITS; + const fixed_t ns = 60 * mapobjectscale; mobj_t *mo; angle_t fa; thinker_t *think; INT32 i; + radius = FixedMul(radius, mapobjectscale); + for (i = 0; i < 16; i++) { fa = (i*(FINEANGLES/16)); diff --git a/src/r_draw.h b/src/r_draw.h index 9a81a7f5..900802ce 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -102,6 +102,8 @@ extern lumpnum_t viewborderlump[8]; // ------------------------------------------------ #define GTC_CACHE 1 +#define GTC_MENUCACHE GTC_CACHE +//@TODO Add a separate caching mechanism for menu colormaps distinct from in-level GTC_CACHE. For now this is still preferable to memory leaks... #define TC_DEFAULT -1 #define TC_BOSS -2 diff --git a/src/r_plane.c b/src/r_plane.c index 3c1fc30e..0ff97fcc 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -1051,7 +1051,7 @@ void R_DrawSinglePlane(visplane_t *pl) temp = P_GetZAt(pl->slope, pl->viewx, pl->viewy); zeroheight = FIXED_TO_FLOAT(temp); -#define ANG2RAD(angle) ((float)((angle)*M_PI)/ANGLE_180) +#define ANG2RAD(angle) ((float)((angle)*M_PIl)/ANGLE_180) // p is the texture origin in view space // Don't add in the offsets at this stage, because doing so can result in diff --git a/src/r_things.c b/src/r_things.c index 9816ca22..baba4211 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1322,6 +1322,7 @@ static void R_ProjectSprite(mobj_t *thing) return; scalestep = (yscale2 - yscale)/(x2 - x1); + scalestep = scalestep ? scalestep : 1; // The following two are alternate sorting methods which might be more applicable in some circumstances. TODO - maybe enable via MF2? // sortscale = max(yscale, yscale2); @@ -2543,23 +2544,6 @@ static void Sk_SetDefaultValue(skin_t *skin) skin->kartweight = 5; // - skin->normalspeed = 36<runspeed = 28<thrustfactor = 5; - skin->accelstart = 96; - skin->acceleration = 40; - - skin->ability = CA_NONE; - skin->ability2 = CA2_SPINDASH; - skin->jumpfactor = FRACUNIT; - skin->actionspd = 30<mindash = 15<maxdash = 90<thokitem = -1; - skin->spinitem = -1; - skin->revitem = -1; - skin->highresscale = FRACUNIT>>1; for (i = 0; i < sfx_skinsoundslot0; i++) @@ -2593,7 +2577,7 @@ void R_InitSkins(void) #ifdef SKINVALUES skin_cons_t[0].strvalue = skins[0].name; #endif - skin->flags = SF_SUPER|SF_SUPERANIMS|SF_SUPERSPIN; + skin->flags = 0; strcpy(skin->realname, "Sonic"); strcpy(skin->hudname, "SONIC"); @@ -2602,20 +2586,11 @@ void R_InitSkins(void) strncpy(skin->facemmap, "PLAYMMAP", 9); skin->prefcolor = SKINCOLOR_BLUE; - skin->ability = CA_THOK; - skin->actionspd = 60<kartspeed = 8; skin->kartweight = 2; // - skin->normalspeed = 36<runspeed = 28<thrustfactor = 5; - skin->accelstart = 96; - skin->acceleration = 40; - skin->spritedef.numframes = sprites[SPR_PLAY].numframes; skin->spritedef.spriteframes = sprites[SPR_PLAY].spriteframes; ST_LoadFaceGraphics(skin->facerank, skin->facewant, skin->facemmap, 0); @@ -2679,31 +2654,12 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum) if (player->mo) player->mo->skin = skin; - player->charability = (UINT8)skin->ability; - player->charability2 = (UINT8)skin->ability2; - player->charflags = (UINT32)skin->flags; - player->thokitem = skin->thokitem < 0 ? (UINT32)mobjinfo[MT_PLAYER].painchance : (UINT32)skin->thokitem; - player->spinitem = skin->spinitem < 0 ? (UINT32)mobjinfo[MT_PLAYER].damage : (UINT32)skin->spinitem; - player->revitem = skin->revitem < 0 ? (mobjtype_t)mobjinfo[MT_PLAYER].raisestate : (UINT32)skin->revitem; - - player->actionspd = skin->actionspd; - player->mindash = skin->mindash; - player->maxdash = skin->maxdash; - // SRB2kart player->kartspeed = skin->kartspeed; player->kartweight = skin->kartweight; - player->normalspeed = skin->normalspeed; - player->runspeed = skin->runspeed; - player->thrustfactor = skin->thrustfactor; - player->accelstart = skin->accelstart; - player->acceleration = skin->acceleration; - - player->jumpfactor = skin->jumpfactor; - /*if (!(cv_debug || devparm) && !(netgame || multiplayer || demoplayback || modeattacking)) { if (playernum == consoleplayer) @@ -2905,28 +2861,8 @@ void R_AddSkins(UINT16 wadnum) #define FULLPROCESS(field) else if (!stricmp(stoken, #field)) skin->field = get_number(value); // character type identification FULLPROCESS(flags) - //FULLPROCESS(ability) - //FULLPROCESS(ability2) - - //FULLPROCESS(thokitem) - //FULLPROCESS(spinitem) - //FULLPROCESS(revitem) #undef FULLPROCESS -#define GETSPEED(field) else if (!stricmp(stoken, #field)) skin->field = atoi(value)<field = atoi(value); - GETINT(thrustfactor) - GETINT(accelstart) - GETINT(acceleration) -#undef GETINT*/ - #define GETKARTSTAT(field) \ else if (!stricmp(stoken, #field)) \ { \ @@ -2944,8 +2880,6 @@ void R_AddSkins(UINT16 wadnum) else if (!stricmp(stoken, "prefcolor")) skin->prefcolor = K_GetKartColorByName(value); - //else if (!stricmp(stoken, "jumpfactor")) - //skin->jumpfactor = FLOAT_TO_FIXED(atof(value)); else if (!stricmp(stoken, "highresscale")) skin->highresscale = FLOAT_TO_FIXED(atof(value)); else @@ -3055,9 +2989,6 @@ next_token: HWR_AddPlayerMD2(numskins); #endif - if (skin->flags & SF_RUNONWATER) // this is literally the only way a skin can be a major mod... this might be a bit heavy handed - G_SetGameModified(multiplayer, true); - numskins++; } return; diff --git a/src/r_things.h b/src/r_things.h index 01d8fc07..6f48cc5b 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -83,29 +83,11 @@ typedef struct char hudname[SKINNAMESIZE+1]; // HUD name to display (officially exactly 5 characters long) char facerank[9], facewant[9], facemmap[9]; // Arbitrarily named patch lumps - UINT8 ability; // ability definition - UINT8 ability2; // secondary ability definition - INT32 thokitem; - INT32 spinitem; - INT32 revitem; - fixed_t actionspd; - fixed_t mindash; - fixed_t maxdash; - // SRB2kart UINT8 kartspeed; UINT8 kartweight; // - fixed_t normalspeed; // Normal ground - fixed_t runspeed; // Speed that you break into your run animation - - UINT8 thrustfactor; // Thrust = thrustfactor * acceleration - UINT8 accelstart; // Acceleration if speed = 0 - UINT8 acceleration; // Acceleration - - fixed_t jumpfactor; // multiple of standard jump height - // Definable color translation table UINT8 starttranscolor; UINT8 prefcolor; diff --git a/src/s_sound.c b/src/s_sound.c index 856aa045..2ddffa3f 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -57,6 +57,9 @@ static void GameMIDIMusic_OnChange(void); static void GameSounds_OnChange(void); static void GameDigiMusic_OnChange(void); +static void PlayMusicIfUnfocused_OnChange(void); +static void PlaySoundIfUnfocused_OnChange(void); + // commands for music and sound servers #ifdef MUSSERV consvar_t musserver_cmd = {"musserver_cmd", "musserver", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -110,6 +113,9 @@ consvar_t cv_gamemidimusic = {"midimusic", "On", CV_SAVE|CV_CALL|CV_NOINIT, CV_O #endif consvar_t cv_gamesounds = {"sounds", "On", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, GameSounds_OnChange, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_playmusicifunfocused = {"playmusicifunfocused", "No", CV_SAVE|CV_CALL|CV_NOINIT, CV_YesNo, PlayMusicIfUnfocused_OnChange, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_playsoundifunfocused = {"playsoundsifunfocused", "No", CV_SAVE|CV_CALL|CV_NOINIT, CV_YesNo, PlaySoundIfUnfocused_OnChange, 0, NULL, NULL, 0, 0, NULL}; + #define S_MAX_VOLUME 127 // when to clip out sounds @@ -270,6 +276,9 @@ void S_RegisterSoundStuff(void) CV_RegisterVar(&cv_gamemidimusic); #endif + CV_RegisterVar(&cv_playmusicifunfocused); + CV_RegisterVar(&cv_playsoundifunfocused); + COM_AddCommand("tunes", Command_Tunes_f); COM_AddCommand("restartaudio", Command_RestartAudio_f); @@ -1897,6 +1906,10 @@ static boolean S_PlayMusic(boolean looping) } S_InitMusicVolume(); // switch between digi and sequence volume + + if (window_notinfocus && !cv_playmusicifunfocused.value) + I_PauseSong(); + return true; } @@ -1978,6 +1991,24 @@ void S_ResumeAudio(void) I_ResumeCD(); } +void S_DisableSound(void) +{ + if (sound_started && !sound_disabled) + { + sound_disabled = true; + S_StopSounds(); + } +} + +void S_EnableSound(void) +{ + if (sound_started && sound_disabled) + { + sound_disabled = false; + S_InitSfxChannels(cv_soundvolume.value); + } +} + void S_SetMusicVolume(INT32 digvolume, INT32 seqvolume) { if (digvolume < 0) @@ -2156,15 +2187,11 @@ void GameSounds_OnChange(void) if (sound_disabled) { - sound_disabled = false; - S_InitSfxChannels(cv_soundvolume.value); - S_StartSound(NULL, sfx_strpst); + if (!( cv_playsoundifunfocused.value && window_notinfocus )) + S_EnableSound(); } else - { - sound_disabled = true; - S_StopSounds(); - } + S_DisableSound(); } void GameDigiMusic_OnChange(void) @@ -2251,3 +2278,28 @@ void GameMIDIMusic_OnChange(void) } } #endif + +static void PlayMusicIfUnfocused_OnChange(void) +{ + if (window_notinfocus) + { + if (cv_playmusicifunfocused.value) + I_PauseSong(); + else + I_ResumeSong(); + } +} + +static void PlaySoundIfUnfocused_OnChange(void) +{ + if (!cv_gamesounds.value) + return; + + if (window_notinfocus) + { + if (cv_playsoundifunfocused.value) + S_DisableSound(); + else + S_EnableSound(); + } +} diff --git a/src/s_sound.h b/src/s_sound.h index 1ad519c2..1c938681 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -33,6 +33,8 @@ extern consvar_t cv_gamedigimusic; extern consvar_t cv_gamemidimusic; #endif extern consvar_t cv_gamesounds; +extern consvar_t cv_playmusicifunfocused; +extern consvar_t cv_playsoundifunfocused; #ifdef SNDSERV extern consvar_t sndserver_cmd, sndserver_arg; @@ -169,6 +171,10 @@ void S_StopMusic(void); void S_PauseAudio(void); void S_ResumeAudio(void); +// Enable and disable sound effects +void S_EnableSound(void); +void S_DisableSound(void); + // // Updates music & sounds // diff --git a/src/screen.c b/src/screen.c index af6aed03..4de2abd0 100644 --- a/src/screen.c +++ b/src/screen.c @@ -403,7 +403,7 @@ void SCR_DisplayTicRate(void) tic_t i; tic_t ontic = I_GetTime(); tic_t totaltics = 0; - INT32 ticcntcolor = 0; + const UINT8 *ticcntcolor = NULL; for (i = lasttic + 1; i < TICRATE+lasttic && i < ontic; ++i) fpsgraph[i % TICRATE] = false; @@ -414,13 +414,36 @@ void SCR_DisplayTicRate(void) if (fpsgraph[i]) ++totaltics; - if (totaltics <= TICRATE/2) ticcntcolor = V_REDMAP; - else if (totaltics == TICRATE) ticcntcolor = V_GREENMAP; + if (totaltics <= TICRATE/2) ticcntcolor = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_SALMON, GTC_CACHE); + else if (totaltics == TICRATE) ticcntcolor = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_MINT, GTC_CACHE); - V_DrawString(vid.width-(24*vid.dupx), vid.height-(16*vid.dupy), + /*V_DrawString(vid.width-(24*vid.dupx), vid.height-(16*vid.dupy), V_YELLOWMAP|V_NOSCALESTART, "FPS"); V_DrawString(vid.width-(40*vid.dupx), vid.height-( 8*vid.dupy), - ticcntcolor|V_NOSCALESTART, va("%02d/%02u", totaltics, TICRATE)); + ticcntcolor|V_NOSCALESTART, va("%02d/%02u", totaltics, TICRATE));*/ + + // draw "FPS" + V_DrawFixedPatch(306< servermaxping)) // only show 2 (warning) if our ping is at a bad level + { + INT32 dispy = cv_ticrate.value ? 160 : 181; + HU_drawPing(307, dispy, ping, V_SNAPTORIGHT | V_SNAPTOBOTTOM); + } +} diff --git a/src/screen.h b/src/screen.h index 9ad254d3..5b4a8e58 100644 --- a/src/screen.h +++ b/src/screen.h @@ -180,5 +180,6 @@ FUNCMATH boolean SCR_IsAspectCorrect(INT32 width, INT32 height); // move out to main code for consistency void SCR_DisplayTicRate(void); +void SCR_DisplayLocalPing(void); #undef DNWH #endif //__SCREEN_H__ diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 2a77604d..9fbe57b3 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -64,7 +64,7 @@ #include "../m_menu.h" #include "../d_main.h" #include "../s_sound.h" -#include "../i_sound.h" // midi pause/unpause +#include "../i_sound.h" // midi pause/unpause #include "../i_joy.h" #include "../st_stuff.h" #include "../g_game.h" @@ -615,9 +615,13 @@ static void Impl_HandleWindowEvent(SDL_WindowEvent evt) { // Tell game we got focus back, resume music if necessary window_notinfocus = false; + if (!paused) I_ResumeSong(); //resume it + if (cv_gamesounds.value) + S_EnableSound(); + if (!firsttimeonmouse) { if (cv_usemouse.value) I_StartupMouse(); @@ -630,7 +634,10 @@ static void Impl_HandleWindowEvent(SDL_WindowEvent evt) { // Tell game we lost focus, pause music window_notinfocus = true; - I_PauseSong(); + if (!cv_playmusicifunfocused.value) + I_PauseSong(); + if (!cv_playsoundifunfocused.value) + S_DisableSound(); if (!disable_mouse) { @@ -1327,6 +1334,7 @@ void I_UpdateNoBlit(void) // from PrBoom's src/SDL/i_video.c static inline boolean I_SkipFrame(void) { +#if 0 static boolean skip = false; if (rendermode != render_soft) @@ -1345,6 +1353,8 @@ static inline boolean I_SkipFrame(void) default: return false; } +#endif + return false; } // @@ -1361,6 +1371,9 @@ void I_FinishUpdate(void) if (cv_ticrate.value) SCR_DisplayTicRate(); + if (cv_showping.value && netgame && consoleplayer != serverplayer) + SCR_DisplayLocalPing(); + if (rendermode == render_soft && screens[0]) { SDL_Rect rect; diff --git a/src/sdl12/i_video.c b/src/sdl12/i_video.c index 69cf5ca9..a2a20c61 100644 --- a/src/sdl12/i_video.c +++ b/src/sdl12/i_video.c @@ -1343,6 +1343,9 @@ void I_FinishUpdate(void) if (cv_ticrate.value) SCR_DisplayTicRate(); + if (cv_showping.value && netgame && consoleplayer != serverplayer) + SCR_DisplayLocalPing(); + if (render_soft == rendermode && screens[0]) { SDL_Rect *dstrect = NULL; diff --git a/src/sounds.c b/src/sounds.c index a3bc8bf4..61fddb76 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -815,6 +815,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"chain", false, 255, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // Mementos Reaper {"mkuma", false, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // Trigger Happy Havoc Monokuma {"toada", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Arid Sands Toad scream + {"bsnipe", false, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // Banana sniping {"itfree", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // :shitsfree: {"dbgsal", false, 255, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // Debug notification diff --git a/src/sounds.h b/src/sounds.h index 4c341d49..bb46ea9d 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -890,6 +890,7 @@ typedef enum sfx_chain, sfx_mkuma, sfx_toada, + sfx_bsnipe, sfx_itfree, sfx_dbgsal, diff --git a/src/v_video.c b/src/v_video.c index 2a16ee47..1f5020dd 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -1342,8 +1342,8 @@ void V_DrawCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed) V_DrawScaledPatch(x, y, flags, hu_font[c]); } -// Writes a single character for the chat. (draw WHITE if bit 7 set) -// Essentially the same as the above but it's small or big depending on what resolution you've chosen to huge.. +// Writes a single character for the chat (half scaled). (draw WHITE if bit 7 set) +// 16/02/19: Scratch the scaling thing, chat doesn't work anymore under 2x res -Lat' // void V_DrawChatCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed, UINT8 *colormap) { @@ -1359,13 +1359,11 @@ void V_DrawChatCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed, UI if (c < 0 || c >= HU_FONTSIZE || !hu_font[c]) return; - w = (vid.width < 640 ) ? (SHORT(hu_font[c]->width)/2) : (SHORT(hu_font[c]->width)); // use normal sized characters if we're using a terribly low resolution. + w = SHORT(hu_font[c]->width)/2; if (x + w > vid.width) return; - V_DrawFixedPatch(x*FRACUNIT, y*FRACUNIT, (vid.width < 640) ? (FRACUNIT) : (FRACUNIT/2), flags, hu_font[c], colormap); - - + V_DrawFixedPatch(x*FRACUNIT, y*FRACUNIT, FRACUNIT/2, flags, hu_font[c], colormap); } // Precompile a wordwrapped string to any given width. @@ -2021,6 +2019,28 @@ void V_DrawPaddedTallNum(INT32 x, INT32 y, INT32 flags, INT32 num, INT32 digits) } while (--digits); } +// Draws a number using the PING font thingy. +// TODO: Merge number drawing functions into one with "font name" selection. + +void V_DrawPingNum(INT32 x, INT32 y, INT32 flags, INT32 num, const UINT8 *colormap) +{ + INT32 w = SHORT(pingnum[0]->width); // this SHOULD always be 5 but I guess custom graphics exist. + + if (flags & V_NOSCALESTART) + w *= vid.dupx; + + if (num < 0) + num = -num; + + // draw the number + do + { + x -= (w-1); // Oni wanted their outline to intersect. + V_DrawFixedPatch(x<