diff --git a/.travis.yml b/.travis.yml index 4648ae56..a9f4ddfb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -57,49 +57,6 @@ matrix: - gcc-4.8 compiler: gcc-4.8 #gcc-4.8 (Ubuntu 4.8.5-2ubuntu1~14.04.1) 4.8.5 - - os: linux - addons: - apt: - sources: - - ubuntu-toolchain-r-test - packages: - - libsdl2-mixer-dev - - libpng-dev - - libgl1-mesa-dev - - libgme-dev - - p7zip-full - - gcc-4.9 - compiler: gcc-4.9 - #gcc-4.9 (Ubuntu 4.9.3-8ubuntu2~14.04) 4.9.3 - - os: linux - addons: - apt: - sources: - - ubuntu-toolchain-r-test - packages: - - libsdl2-mixer-dev - - libpng-dev - - libgl1-mesa-dev - - libgme-dev - - p7zip-full - - gcc-5 - compiler: gcc-5 - #gcc-5 (Ubuntu 5.3.0-3ubuntu1~14.04) 5.3.0 20151204 - - os: linux - addons: - apt: - sources: - - ubuntu-toolchain-r-test - packages: - - libsdl2-mixer-dev - - libpng-dev - - libgl1-mesa-dev - - libgme-dev - - p7zip-full - - gcc-6 - compiler: gcc-6 - env: WFLAGS="-Wno-tautological-compare" - #gcc-6 (Ubuntu 6.1.1-3ubuntu11~14.04.1) 6.1.1 20160511 - os: linux addons: apt: diff --git a/bin/Mingw/Debug/.gitignore b/bin/Mingw/Debug/.gitignore index 834f313e..3458ff76 100644 --- a/bin/Mingw/Debug/.gitignore +++ b/bin/Mingw/Debug/.gitignore @@ -1,3 +1,4 @@ *.exe *.mo r_opengl.dll +*.bat diff --git a/bin/Mingw/Release/.gitignore b/bin/Mingw/Release/.gitignore index 834f313e..3458ff76 100644 --- a/bin/Mingw/Release/.gitignore +++ b/bin/Mingw/Release/.gitignore @@ -1,3 +1,4 @@ *.exe *.mo r_opengl.dll +*.bat diff --git a/src/Makefile b/src/Makefile index 7cb1233c..17f38d01 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,3 +1,4 @@ + # GNU Make makefile for SRB2 ############################################################################# # Copyright (C) 1998-2000 by DooM Legacy Team. @@ -426,7 +427,8 @@ endif ifdef PROFILEMODE # build with profiling information - CFLAGS:=-pg $(CFLAGS) + CFLAGS+=-pg + LDFLAGS+=-pg endif ifdef ZDEBUG diff --git a/src/android/i_cdmus.c b/src/android/i_cdmus.c index c5aac8f1..426bc5dc 100644 --- a/src/android/i_cdmus.c +++ b/src/android/i_cdmus.c @@ -8,7 +8,7 @@ UINT8 cdaudio_started = 0; -consvar_t cd_volume = {"cd_volume","31",CV_SAVE,soundvolume_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cd_volume = {"cd_volume","18",CV_SAVE,soundvolume_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cdUpdate = {"cd_update","1",CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; diff --git a/src/command.c b/src/command.c index a1f0a46b..305a5eee 100644 --- a/src/command.c +++ b/src/command.c @@ -1088,32 +1088,42 @@ static void Setvalue(consvar_t *var, const char *valstr, boolean stealth) if (var->PossibleValue[0].strvalue && !stricmp(var->PossibleValue[0].strvalue, "MIN")) // bounded cvar { +#define MINVAL 0 +#define MAXVAL 1 INT32 i; - // search for maximum - for (i = 1; var->PossibleValue[i].strvalue; i++) - if (!stricmp(var->PossibleValue[i].strvalue, "MAX")) - break; + #ifdef PARANOIA - if (!var->PossibleValue[i].strvalue) + if (!var->PossibleValue[MAXVAL].strvalue) I_Error("Bounded cvar \"%s\" without maximum!\n", var->name); #endif - if ((v != INT32_MIN && v < var->PossibleValue[0].value) || !stricmp(valstr, "MIN")) + // search for other + for (i = MAXVAL+1; var->PossibleValue[i].strvalue; i++) + if (!stricmp(var->PossibleValue[i].strvalue, valstr)) + { + var->value = var->PossibleValue[i].value; + var->string = var->PossibleValue[i].strvalue; + goto finish; + } + + if ((v != INT32_MIN && v < var->PossibleValue[MINVAL].value) || !stricmp(valstr, "MIN")) { - v = var->PossibleValue[0].value; - valstr = var->PossibleValue[0].strvalue; + v = var->PossibleValue[MINVAL].value; + valstr = var->PossibleValue[MINVAL].strvalue; override = true; overrideval = v; } - else if ((v != INT32_MIN && v > var->PossibleValue[i].value) || !stricmp(valstr, "MAX")) + else if ((v != INT32_MIN && v > var->PossibleValue[MAXVAL].value) || !stricmp(valstr, "MAX")) { - v = var->PossibleValue[i].value; - valstr = var->PossibleValue[i].strvalue; + v = var->PossibleValue[MAXVAL].value; + valstr = var->PossibleValue[MAXVAL].strvalue; override = true; overrideval = v; } if (v == INT32_MIN) goto badinput; +#undef MINVAL +#undef MAXVAL } else { @@ -1453,7 +1463,6 @@ void CV_AddValue(consvar_t *var, INT32 increment) if (var->PossibleValue) { -#define MINVAL 0 if (var == &cv_nextmap) { // Special case for the nextmap variable, used only directly from the menu @@ -1478,33 +1487,52 @@ void CV_AddValue(consvar_t *var, INT32 increment) } if (newvalue == oldvalue) - gt = -1; // don't loop forever if there's none of a certain gametype + break; // don't loop forever if there's none of a certain gametype if(!mapheaderinfo[newvalue]) continue; // Don't allocate the header. That just makes memory usage skyrocket. - } while (newvalue != oldvalue && !M_CanShowLevelInList(newvalue, gt)); + } while (!M_CanShowLevelInList(newvalue, gt)); var->value = newvalue + 1; var->func(); return; } } +#define MINVAL 0 +#define MAXVAL 1 else if (var->PossibleValue[MINVAL].strvalue && !strcmp(var->PossibleValue[MINVAL].strvalue, "MIN")) - { - // search the next to last - for (max = 0; var->PossibleValue[max+1].strvalue; max++) - ; + { // SRB2Kart +#ifdef PARANOIA + if (!var->PossibleValue[MAXVAL].strvalue) + I_Error("Bounded cvar \"%s\" without maximum!\n", var->name); +#endif - if (newvalue < var->PossibleValue[MINVAL].value) // add the max+1 - newvalue += var->PossibleValue[max].value - var->PossibleValue[MINVAL].value + 1; + if (newvalue < var->PossibleValue[MINVAL].value || newvalue > var->PossibleValue[MAXVAL].value) + { + INT32 currentindice = -1, newindice; + for (max = MAXVAL+1; var->PossibleValue[max].strvalue; max++) + if (var->PossibleValue[max].value == var->value) + currentindice = max; - newvalue = var->PossibleValue[MINVAL].value + (newvalue - var->PossibleValue[MINVAL].value) - % (var->PossibleValue[max].value - var->PossibleValue[MINVAL].value + 1); + if (currentindice == -1 && max != MAXVAL+1) + newindice = ((increment > 0) ? MAXVAL : max) + increment; + else + newindice = currentindice + increment; - CV_SetValue(var, newvalue); -#undef MINVAL + if (newindice >= max || newindice <= MAXVAL) + { + newvalue = var->PossibleValue[((increment > 0) ? MINVAL : MAXVAL)].value; + CV_SetValue(var, newvalue); + } + else + CV_Set(var, var->PossibleValue[newindice].strvalue); + } + else + CV_SetValue(var, newvalue); } +#undef MINVAL +#undef MAXVAL else { INT32 currentindice = -1, newindice; @@ -1514,8 +1542,6 @@ void CV_AddValue(consvar_t *var, INT32 increment) if (var->PossibleValue[max].value == var->value) currentindice = max; - max--; - if (var == &cv_chooseskin) { // Special case for the chooseskin variable, used only directly from the menu @@ -1578,7 +1604,7 @@ void CV_AddValue(consvar_t *var, INT32 increment) var->value); #endif - newindice = (currentindice + increment + max + 1) % (max+1); + newindice = (currentindice + increment + max) % max; CV_Set(var, var->PossibleValue[newindice].strvalue); } } diff --git a/src/console.c b/src/console.c index c0f12055..212e6c8d 100644 --- a/src/console.c +++ b/src/console.c @@ -139,6 +139,21 @@ static CV_PossibleValue_t backcolor_cons_t[] = {{0, "White"}, {1, "Gray"}, {2, {0, NULL}}; consvar_t cons_backcolor = {"con_backcolor", "Green", CV_CALL|CV_SAVE, backcolor_cons_t, CONS_backcolor_Change, 0, NULL, NULL, 0, 0, NULL}; +static CV_PossibleValue_t menuhighlight_cons_t[] = +{ + {0, "Game type"}, + {V_YELLOWMAP, "Always yellow"}, + {V_PURPLEMAP, "Always purple"}, + {V_GREENMAP, "Always green"}, + {V_BLUEMAP, "Always blue"}, + {V_REDMAP, "Always red"}, + {V_GRAYMAP, "Always gray"}, + {V_ORANGEMAP, "Always orange"}, + {V_SKYMAP, "Always sky-blue"}, + {0, NULL} +}; +consvar_t cons_menuhighlight = {"menuhighlight", "Game type", CV_SAVE, menuhighlight_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; + static void CON_Print(char *msg); // @@ -227,13 +242,7 @@ static void CONS_Bind_f(void) // Font colormap colors // TODO: This could probably be improved somehow... // These colormaps are 99% identical, with just a few changed bytes -UINT8 *yellowmap; -UINT8 *purplemap; -UINT8 *lgreenmap; -UINT8 *bluemap; -UINT8 *graymap; -UINT8 *redmap; -UINT8 *orangemap; +UINT8 *yellowmap, *purplemap, *greenmap, *bluemap, *graymap, *redmap, *orangemap, *skymap; // Console BG color UINT8 *consolebgmap = NULL; @@ -278,39 +287,34 @@ static void CONS_backcolor_Change(void) static void CON_SetupColormaps(void) { INT32 i; + UINT8 *memorysrc = (UINT8 *)Z_Malloc((256*8), PU_STATIC, NULL); - yellowmap = (UINT8 *)Z_Malloc(256, PU_STATIC, NULL); - graymap = (UINT8 *)Z_Malloc(256, PU_STATIC, NULL); - purplemap = (UINT8 *)Z_Malloc(256, PU_STATIC, NULL); - lgreenmap = (UINT8 *)Z_Malloc(256, PU_STATIC, NULL); - bluemap = (UINT8 *)Z_Malloc(256, PU_STATIC, NULL); - redmap = (UINT8 *)Z_Malloc(256, PU_STATIC, NULL); - orangemap = (UINT8 *)Z_Malloc(256, PU_STATIC, NULL); + purplemap = memorysrc; + yellowmap = (purplemap+256); + greenmap = (yellowmap+256); + bluemap = (greenmap+256); + redmap = (bluemap+256); + graymap = (redmap+256); + orangemap = (graymap+256); + skymap = (orangemap+256); // setup the other colormaps, for console text // these don't need to be aligned, unless you convert the // V_DrawMappedPatch() into optimised asm. - for (i = 0; i < 256; i++) - { - yellowmap[i] = (UINT8)i; // remap each color to itself... - graymap[i] = (UINT8)i; - purplemap[i] = (UINT8)i; - lgreenmap[i] = (UINT8)i; - bluemap[i] = (UINT8)i; - redmap[i] = (UINT8)i; - orangemap[i] = (UINT8)i; - } + for (i = 0; i < (256*8); i++, ++memorysrc) + *memorysrc = (UINT8)(i & 0xFF); // remap each color to itself... // SRB2Kart: Different console font, new colors - yellowmap[120] = (UINT8)103; purplemap[120] = (UINT8)194; - lgreenmap[120] = (UINT8)162; + yellowmap[120] = (UINT8)103; + greenmap[120] = (UINT8)162; bluemap[120] = (UINT8)228; graymap[120] = (UINT8)10; - redmap[120] = (UINT8)126; - orangemap[120] = (UINT8)85; + redmap[120] = (UINT8)126; // battle + orangemap[120] = (UINT8)85; // record attack + skymap[120] = (UINT8)214; // race // Init back colormap CON_SetupBackColormap(); @@ -367,6 +371,7 @@ void CON_Init(void) CV_RegisterVar(&cons_height); CV_RegisterVar(&cons_backpic); CV_RegisterVar(&cons_backcolor); + CV_RegisterVar(&cons_menuhighlight); COM_AddCommand("bind", CONS_Bind_f); } else @@ -1032,7 +1037,17 @@ boolean CON_Responder(event_t *ev) else if (key == KEY_KPADSLASH) key = '/'; - if (shiftdown) + // capslock + if (key == KEY_CAPSLOCK) // it's a toggle. + { + if (capslock) + capslock = false; + else + capslock = true; + return true; + } + + if (capslock ^ shiftdown) // gets capslock to work because capslock is cool key = shiftxform[key]; // enter a char into the command prompt @@ -1040,7 +1055,7 @@ boolean CON_Responder(event_t *ev) return true; // even if key can't be printed, eat it anyway // add key to cmd line here - if (key >= 'A' && key <= 'Z' && !shiftdown) //this is only really necessary for dedicated servers + if (key >= 'A' && key <= 'Z' && !(shiftdown ^ capslock)) //this is only really necessary for dedicated servers key = key + 'a' - 'A'; if (input_sel != input_cur) @@ -1427,7 +1442,7 @@ static void CON_DrawHudlines(void) if (con_hudlines <= 0) return; - if (chat_on) + if (chat_on && OLDCHAT) y = charheight; // leave place for chat input in the first row of text else y = 0; @@ -1620,6 +1635,6 @@ void CON_Drawer(void) if (con_curlines > 0) CON_DrawConsole(); else if (gamestate == GS_LEVEL || gamestate == GS_INTERMISSION || gamestate == GS_CUTSCENE || gamestate == GS_CREDITS - || gamestate == GS_VOTING) + || gamestate == GS_VOTING || gamestate == GS_EVALUATION || gamestate == GS_WAITINGPLAYERS) CON_DrawHudlines(); } diff --git a/src/console.h b/src/console.h index 8cf6483f..896214c9 100644 --- a/src/console.h +++ b/src/console.h @@ -36,9 +36,9 @@ extern INT32 con_clearlines; // lines of top of screen to refresh extern boolean con_hudupdate; // hud messages have changed, need refresh extern UINT32 con_scalefactor; // console text scale factor -extern consvar_t cons_backcolor; +extern consvar_t cons_backcolor, cons_menuhighlight; -extern UINT8 *yellowmap, *purplemap, *lgreenmap, *bluemap, *graymap, *redmap, *orangemap; +extern UINT8 *yellowmap, *purplemap, *greenmap, *bluemap, *graymap, *redmap, *orangemap, *skymap; // Console bg color (auto updated to match) extern UINT8 *consolebgmap; diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 5aa10587..13650c59 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -443,8 +443,7 @@ static void ExtraDataTicker(void) DEBFILE(va("player %d kicked [gametic=%u] reason as follows:\n", i, gametic)); } CONS_Alert(CONS_WARNING, M_GetText("Got unknown net command [%s]=%d (max %d)\n"), sizeu1(curpos - bufferstart), *curpos, bufferstart[0]); - D_FreeTextcmd(gametic); - return; + break; } } } @@ -1166,7 +1165,7 @@ static inline void CL_DrawConnectionStatus(void) INT32 ccstime = I_GetTime(); // Draw background fade - V_DrawFadeScreen(); + V_DrawFadeScreen(0xFF00, 16); // Draw the bottom box. M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT-24-8, 32, 1); @@ -2145,7 +2144,8 @@ static void CL_ConnectToServer(boolean viams) } while (!(cl_mode == CL_CONNECTED && (client || (server && nodewaited <= pnumnodes)))); - F_StartWaitingPlayers(); + if (netgame) + F_StartWaitingPlayers(); DEBFILE(va("Synchronisation Finished\n")); displayplayer = consoleplayer; @@ -2431,6 +2431,9 @@ static void CL_RemovePlayer(INT32 playernum) } } + if (K_IsPlayerWanted(&players[playernum])) + K_CalculateBattleWanted(); + if (gametype == GT_CTF) P_PlayerFlagBurst(&players[playernum], false); // Don't take the flag with you! @@ -2491,7 +2494,7 @@ static void CL_RemovePlayer(INT32 playernum) if (G_TagGametype()) //Check if you still have a game. Location flexible. =P P_CheckSurvivors(); else if (G_BattleGametype()) // SRB2Kart - K_CheckBalloons(); + K_CheckBumpers(); else if (G_RaceGametype()) P_CheckRacers(); } @@ -3424,7 +3427,7 @@ void SV_StopServer(void) localtextcmd3[0] = 0; localtextcmd4[0] = 0; - for (i = 0; i < BACKUPTICS; i++) + for (i = firstticstosend; i < firstticstosend + BACKUPTICS; i++) D_Clearticcmd(i); consoleplayer = 0; @@ -3706,7 +3709,8 @@ static void HandlePacketFromAwayNode(SINT8 node) if (client) { maketic = gametic = neededtic = (tic_t)LONG(netbuffer->u.servercfg.gametic); - gametype = netbuffer->u.servercfg.gametype; + if ((gametype = netbuffer->u.servercfg.gametype) >= NUMGAMETYPES) + I_Error("Bad gametype in cliserv!"); modifiedgame = netbuffer->u.servercfg.modifiedgame; for (j = 0; j < MAXPLAYERS; j++) adminplayers[j] = netbuffer->u.servercfg.adminplayers[j]; diff --git a/src/d_main.c b/src/d_main.c index 01d8bf2f..6c3f9a42 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -125,17 +125,19 @@ INT32 postimgparam3; postimg_t postimgtype4 = postimg_none; INT32 postimgparam4; #ifdef _XBOX -boolean nomidimusic = true, nosound = true; +//boolean nomidimusic = false; +boolean nosound = true; boolean nodigimusic = true; #else -boolean nomidimusic = false, nosound = false; +//boolean nomidimusic = false; +boolean nosound = false; boolean nodigimusic = false; // No fmod-based music #endif // These variables are only true if // the respective sound system is initialized // and active, but no sounds/music should play. -boolean music_disabled = false; +//boolean music_disabled = false; boolean sound_disabled = false; boolean digital_disabled = false; @@ -184,6 +186,7 @@ void D_PostEvent_end(void) {}; UINT8 shiftdown = 0; // 0x1 left, 0x2 right UINT8 ctrldown = 0; // 0x1 left, 0x2 right UINT8 altdown = 0; // 0x1 left, 0x2 right +boolean capslock = 0; // jeez i wonder what this does. // // D_ModifierKeyResponder // Sets global shift/ctrl/alt variables, never actually eats events @@ -294,15 +297,15 @@ static void D_Display(void) { // set for all later wipedefindex = gamestate; // wipe_xxx_toblack - if (gamestate == GS_INTERMISSION) + if (gamestate == GS_TITLESCREEN && wipegamestate != GS_INTRO) + wipedefindex = wipe_timeattack_toblack; + else if (gamestate == GS_INTERMISSION) { if (intertype == int_spec) // Special Stage wipedefindex = wipe_specinter_toblack; else //if (intertype != int_coop) // Multiplayer wipedefindex = wipe_multinter_toblack; } - else if (gamestate == GS_VOTING) - wipedefindex = wipe_multinter_toblack; if (rendermode != render_none) { @@ -316,6 +319,12 @@ static void D_Display(void) F_RunWipe(wipedefs[wipedefindex], gamestate != GS_TIMEATTACK); } + if (wipegamestate == GS_LEVEL && rendermode != render_none) + { + V_SetPaletteLump("PLAYPAL"); // Reset the palette + R_ReInitColormaps(0); + } + F_WipeStartScreen(); } } @@ -367,6 +376,7 @@ static void D_Display(void) case GS_EVALUATION: F_GameEvaluationDrawer(); + HU_Erase(); HU_Drawer(); break; @@ -382,12 +392,19 @@ static void D_Display(void) case GS_TITLESCREEN: F_TitleScreenDrawer(); + if (wipe) + wipedefindex = wipe_titlescreen_toblack; break; case GS_WAITINGPLAYERS: // The clientconnect drawer is independent... - // I don't think HOM from nothing drawing is independent... - F_WaitingPlayersDrawer(); + if (netgame) + { + // I don't think HOM from nothing drawing is independent... + F_WaitingPlayersDrawer(); + HU_Erase(); + HU_Drawer(); + } case GS_DEDICATEDSERVER: case GS_NULL: break; @@ -527,7 +544,7 @@ static void D_Display(void) wipegamestate = gamestate; // draw pause pic - if (paused && cv_showhud.value && (!menuactive || netgame)) + if (paused && cv_showhud.value) { INT32 py; patch_t *patch; @@ -813,9 +830,9 @@ void D_StartTitle(void) F_StartTitleScreen(); CON_ToggleOff(); - // Reset the palette - if (rendermode != render_none) - V_SetPaletteLump("PLAYPAL"); + // Reset the palette -- SRB2Kart: actually never mind let's do this in the middle of every fade + /*if (rendermode != render_none) + V_SetPaletteLump("PLAYPAL");*/ } // @@ -943,6 +960,10 @@ static void IdentifyVersion(void) D_AddFile(va(pandf,srb2waddir,"maps.kart")); D_AddFile(va(pandf,srb2waddir,"sounds.kart")); +#ifdef USE_PATCH_KART + D_AddFile(va(pandf,srb2waddir,"patch.kart")); +#endif + #if !defined (HAVE_SDL) || defined (HAVE_MIXER) { #if defined (DC) && 0 @@ -1153,15 +1174,6 @@ void D_SRB2Main(void) if (M_CheckParm("-password") && M_IsNextParm()) D_SetPassword(M_GetNextParm()); - else - { - size_t z; - char junkpw[25]; - for (z = 0; z < 24; z++) - junkpw[z] = (char)(rand() & 64)+32; - junkpw[24] = '\0'; - D_SetPassword(junkpw); - } // add any files specified on the command line with -file wadfile // to the wad list @@ -1241,25 +1253,23 @@ void D_SRB2Main(void) #ifndef DEVELOP // md5s last updated 12/14/14 // Check MD5s of autoloaded files - W_VerifyFileMD5(0, ASSET_HASH_SRB2_SRB); // srb2.srb/srb2.wad - W_VerifyFileMD5(1, ASSET_HASH_GFX_DTA); // gfx.kart - W_VerifyFileMD5(2, ASSET_HASH_CHARS_DTA); // chars.kart - W_VerifyFileMD5(3, ASSET_HASH_MAPS_DTA); // maps.kart - // sounds.kart - since music is large, we'll ignore it for now. - + mainwads = 0; + W_VerifyFileMD5(mainwads, ASSET_HASH_SRB2_SRB); mainwads++; // srb2.srb/srb2.wad #ifdef USE_PATCH_DTA - W_VerifyFileMD5(4, ASSET_HASH_PATCH_DTA); // patch.dta + W_VerifyFileMD5(mainwads, ASSET_HASH_PATCH_DTA); mainwads++; // patch.dta +#endif + W_VerifyFileMD5(mainwads, ASSET_HASH_GFX_KART); mainwads++; // gfx.kart + W_VerifyFileMD5(mainwads, ASSET_HASH_CHARS_KART); mainwads++; // chars.kart + W_VerifyFileMD5(mainwads, ASSET_HASH_MAPS_KART); mainwads++; // maps.kart + //W_VerifyFileMD5(mainwads, ASSET_HASH_SOUNDS_KART); mainwads++; // sounds.kart - doesn't trigger modifiedgame, doesn't need an MD5...? +#ifdef USE_PATCH_KART + W_VerifyFileMD5(mainwads, ASSET_HASH_PATCH_KART); mainwads++; // patch.kart #endif // don't check music.dta because people like to modify it, and it doesn't matter if they do // ...except it does if they slip maps in there, and that's what W_VerifyNMUSlumps is for. #endif //ifndef DEVELOP - mainwads = 4; // there are 4 wads not to unload -#ifdef USE_PATCH_DTA - ++mainwads; // patch.dta adds one more -#endif - cht_Init(); //---------------------------------------------------- READY SCREEN @@ -1326,7 +1336,7 @@ void D_SRB2Main(void) if (dedicated) { nosound = true; - nomidimusic = nodigimusic = true; + /*nomidimusic = */nodigimusic = true; } else { @@ -1335,17 +1345,17 @@ void D_SRB2Main(void) if (M_CheckParm("-nosound")) nosound = true; if (M_CheckParm("-nomusic")) // combines -nomidimusic and -nodigmusic - nomidimusic = nodigimusic = true; + /*nomidimusic = */nodigimusic = true; else { - if (M_CheckParm("-nomidimusic")) - nomidimusic = true; ; // WARNING: DOS version initmusic in I_StartupSound + /*if (M_CheckParm("-nomidimusic")) + nomidimusic = true; ; // WARNING: DOS version initmusic in I_StartupSound*/ if (M_CheckParm("-nodigmusic")) nodigimusic = true; // WARNING: DOS version initmusic in I_StartupSound } I_StartupSound(); I_InitMusic(); - S_Init(cv_soundvolume.value, cv_digmusicvolume.value, cv_midimusicvolume.value); + S_Init(cv_soundvolume.value, cv_digmusicvolume.value);//, cv_midimusicvolume.value); CONS_Printf("ST_Init(): Init status bar.\n"); ST_Init(); diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 81fd0da9..9b635cb0 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -109,10 +109,12 @@ static void Color4_OnChange(void); static void DummyConsvar_OnChange(void); static void SoundTest_OnChange(void); +static void BaseNumLaps_OnChange(void); static void KartFrantic_OnChange(void); static void KartSpeed_OnChange(void); static void KartMirror_OnChange(void); static void KartComeback_OnChange(void); +static void KartEliminateLast_OnChange(void); #ifdef NETGAME_DEVMODE static void Fishcake_OnChange(void); @@ -220,7 +222,7 @@ static CV_PossibleValue_t competitionboxes_cons_t[] = {{0, "Normal"}, {1, "Rando static CV_PossibleValue_t matchboxes_cons_t[] = {{0, "Normal"}, {1, "Random"}, {2, "Non-Random"}, {3, "None"}, {0, NULL}}; -static CV_PossibleValue_t chances_cons_t[] = {{0, "MIN"}, {9, "MAX"}, {0, NULL}}; +//static CV_PossibleValue_t chances_cons_t[] = {{0, "MIN"}, {9, "MAX"}, {0, NULL}}; static CV_PossibleValue_t match_scoring_cons_t[] = {{0, "Normal"}, {1, "Classic"}, {0, NULL}}; static CV_PossibleValue_t pause_cons_t[] = {{0, "Server"}, {1, "All"}, {0, NULL}}; @@ -244,7 +246,7 @@ consvar_t cv_competitionboxes = {"competitionboxes", "Random", CV_NETVAR|CV_CHEA #ifdef SEENAMES static CV_PossibleValue_t seenames_cons_t[] = {{0, "Off"}, {1, "Colorless"}, {2, "Team"}, {3, "Ally/Foe"}, {0, NULL}}; -consvar_t cv_seenames = {"seenames", "Ally/Foe", CV_SAVE, seenames_cons_t, 0, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_seenames = {"seenames", "Off", CV_SAVE, seenames_cons_t, 0, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_allowseenames = {"allowseenames", "Yes", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; #endif @@ -271,26 +273,15 @@ INT32 cv_debug; consvar_t cv_usemouse = {"use_mouse", "Off", CV_SAVE|CV_CALL,usemouse_cons_t, I_StartupMouse, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_usemouse2 = {"use_mouse2", "Off", CV_SAVE|CV_CALL,usemouse_cons_t, I_StartupMouse2, 0, NULL, NULL, 0, 0, NULL}; -#if defined (DC) || defined (_XBOX) || defined (WMINPUT) || defined (_WII) //joystick 1 and 2 consvar_t cv_usejoystick = {"use_joystick", "1", CV_SAVE|CV_CALL, usejoystick_cons_t, I_InitJoystick, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_usejoystick2 = {"use_joystick2", "2", CV_SAVE|CV_CALL, usejoystick_cons_t, I_InitJoystick2, 0, NULL, NULL, 0, 0, NULL}; -#elif defined (PSP) || defined (GP2X) || defined (_NDS) //only one joystick -consvar_t cv_usejoystick = {"use_joystick", "1", CV_SAVE|CV_CALL, usejoystick_cons_t, - I_InitJoystick, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_usejoystick2 = {"use_joystick2", "0", CV_SAVE|CV_CALL, usejoystick_cons_t, - I_InitJoystick2, 0, NULL, NULL, 0, 0, NULL}; -#else //all esle, no joystick -consvar_t cv_usejoystick = {"use_joystick", "0", CV_SAVE|CV_CALL, usejoystick_cons_t, - I_InitJoystick, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_usejoystick2 = {"use_joystick2", "0", CV_SAVE|CV_CALL, usejoystick_cons_t, - I_InitJoystick2, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_usejoystick3 = {"use_joystick3", "0", CV_SAVE|CV_CALL, usejoystick_cons_t, +consvar_t cv_usejoystick3 = {"use_joystick3", "3", CV_SAVE|CV_CALL, usejoystick_cons_t, I_InitJoystick3, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_usejoystick4 = {"use_joystick4", "0", CV_SAVE|CV_CALL, usejoystick_cons_t, +consvar_t cv_usejoystick4 = {"use_joystick4", "4", CV_SAVE|CV_CALL, usejoystick_cons_t, I_InitJoystick4, 0, NULL, NULL, 0, 0, NULL}; -#endif + #if (defined (LJOYSTICK) || defined (HAVE_SDL)) #ifdef LJOYSTICK consvar_t cv_joyport = {"joyport", "/dev/js0", CV_SAVE, joyport_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -315,7 +306,7 @@ consvar_t cv_matchboxes = {"matchboxes", "Normal", CV_NETVAR|CV_CHEAT, matchboxe consvar_t cv_specialrings = {"specialrings", "On", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_powerstones = {"powerstones", "On", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_recycler = {"tv_recycler", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +/*consvar_t cv_recycler = {"tv_recycler", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_teleporters = {"tv_teleporter", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_superring = {"tv_superring", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_supersneakers = {"tv_supersneaker", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -326,45 +317,56 @@ consvar_t cv_ringshield = {"tv_ringshield", "5", CV_NETVAR|CV_CHEAT, chanc consvar_t cv_forceshield = {"tv_forceshield", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_bombshield = {"tv_bombshield", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_1up = {"tv_1up", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_eggmanbox = {"tv_eggman", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_eggmanbox = {"tv_eggman", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};*/ // SRB2kart -consvar_t cv_magnet = {"magnets", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_boo = {"boos", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_mushroom = {"mushrooms", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_triplemushroom = {"triplemushrooms", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_megashroom = {"megashrooms", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_goldshroom = {"goldshrooms", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_star = {"stars", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_triplebanana = {"triplebananas", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_fakeitem = {"fakeitems", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_banana = {"bananas", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_greenshell = {"greenshells", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_redshell = {"redshells", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_laserwisp = {"laserwisps", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_triplegreenshell = {"triplegreenshells", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_bobomb = {"bobombs", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_blueshell = {"blueshells", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_jaws = {"jaws", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_fireflower = {"fireflowers", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_tripleredshell = {"tripleredshells", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_lightning = {"lightning", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_feather = {"feathers", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_sneaker = {"sneaker", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_rocketsneaker = {"rocketsneaker", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_invincibility = {"invincibility", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_banana = {"banana", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_eggmanmonitor = {"eggmanmonitor", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_orbinaut = {"orbinaut", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_jawz = {"jawz", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_mine = {"mine", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_ballhog = {"ballhog", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_selfpropelledbomb = {"selfpropelledbomb", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_grow = {"grow", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_shrink = {"shrink", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_thundershield = {"thundershield", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_hyudoro = {"hyudoro", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_pogospring = {"pogospring", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; + +consvar_t cv_triplesneaker = {"triplesneaker", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_triplebanana = {"triplebanana", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_tripleorbinaut = {"tripleorbinaut", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_dualjawz = {"dualjawz", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_karthud = {"karthud", "Default", CV_SAVE|CV_CALL, karthud_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; static CV_PossibleValue_t kartminimap_cons_t[] = {{0, "MIN"}, {10, "MAX"}, {0, NULL}}; consvar_t cv_kartminimap = {"kartminimap", "4", CV_SAVE, kartminimap_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_kartcheck = {"kartcheck", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; -static CV_PossibleValue_t kartstarsfx_cons_t[] = {{0, "Music"}, {1, "SMK"}, {0, NULL}}; -consvar_t cv_kartstarsfx = {"kartstarsfx", "SMK", CV_SAVE, kartstarsfx_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +static CV_PossibleValue_t kartinvinsfx_cons_t[] = {{0, "Music"}, {1, "SFX"}, {0, NULL}}; +consvar_t cv_kartinvinsfx = {"kartinvinsfx", "SFX", CV_SAVE, kartinvinsfx_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_kartspeed = {"kartspeed", "Normal", CV_NETVAR|CV_CALL|CV_NOINIT, kartspeed_cons_t, KartSpeed_OnChange, 0, NULL, NULL, 0, 0, NULL}; -static CV_PossibleValue_t kartballoons_cons_t[] = {{1, "MIN"}, {12, "MAX"}, {0, NULL}}; -consvar_t cv_kartballoons = {"kartballoons", "3", CV_NETVAR|CV_CHEAT, kartballoons_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +static CV_PossibleValue_t kartbumpers_cons_t[] = {{1, "MIN"}, {12, "MAX"}, {0, NULL}}; +consvar_t cv_kartbumpers = {"kartbumpers", "3", CV_NETVAR|CV_CHEAT, kartbumpers_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_kartfrantic = {"kartfrantic", "Off", CV_NETVAR|CV_CHEAT|CV_CALL|CV_NOINIT, CV_OnOff, KartFrantic_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_kartcomeback = {"kartcomeback", "On", CV_NETVAR|CV_CHEAT|CV_CALL|CV_NOINIT, CV_OnOff, KartComeback_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_kartmirror = {"kartmirror", "Off", CV_NETVAR|CV_CHEAT|CV_CALL|CV_NOINIT, CV_OnOff, KartMirror_OnChange, 0, NULL, NULL, 0, 0, NULL}; -static CV_PossibleValue_t speedometer_cons_t[] = {{0, "Off"}, {1, "Kilometers"}, {2, "Miles"}, {3, "Fracunits"}, {0, NULL}}; -consvar_t cv_speedometer = {"speedometer", "Off", CV_SAVE, speedometer_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; // use tics in display +static CV_PossibleValue_t kartspeedometer_cons_t[] = {{0, "Off"}, {1, "Kilometers"}, {2, "Miles"}, {3, "Fracunits"}, {0, NULL}}; +consvar_t cv_kartspeedometer = {"kartdisplayspeed", "Off", CV_SAVE, kartspeedometer_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; // use tics in display +static CV_PossibleValue_t kartvoices_cons_t[] = {{0, "Never"}, {1, "Tasteful"}, {2, "Meme"}, {0, NULL}}; +consvar_t cv_kartvoices = {"kartvoices", "Tasteful", CV_SAVE, kartvoices_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; + +// this might be a debug or it might be an undocumented regular feature +consvar_t cv_karteliminatelast = {"karteliminatelast", "Yes", CV_NETVAR|CV_CHEAT|CV_CALL, CV_OnOff, KartEliminateLast_OnChange, 0, NULL, NULL, 0, 0, NULL}; + +static CV_PossibleValue_t kartdebugitem_cons_t[] = {{-1, "MIN"}, {NUMKARTITEMS-1, "MAX"}, {0, NULL}}; +consvar_t cv_kartdebugitem = {"kartdebugitem", "0", CV_NETVAR|CV_CHEAT, kartdebugitem_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +static CV_PossibleValue_t kartdebugamount_cons_t[] = {{1, "MIN"}, {255, "MAX"}, {0, NULL}}; +consvar_t cv_kartdebugamount = {"kartdebugamount", "1", CV_NETVAR|CV_CHEAT, kartdebugamount_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_kartdebugcheckpoint = {"kartdebugcheckpoint", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_kartdebugshrink = {"kartdebugshrink", "Off", CV_NETVAR|CV_CHEAT, 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}; @@ -403,10 +405,11 @@ consvar_t cv_pointlimit = {"pointlimit", "0", CV_NETVAR|CV_CALL|CV_NOINIT, point static CV_PossibleValue_t timelimit_cons_t[] = {{0, "MIN"}, {30, "MAX"}, {0, NULL}}; consvar_t cv_timelimit = {"timelimit", "0", CV_NETVAR|CV_CALL|CV_NOINIT, timelimit_cons_t, TimeLimit_OnChange, 0, NULL, NULL, 0, 0, NULL}; -static CV_PossibleValue_t numlaps_cons_t[] = {{0, "MIN"}, {50, "MAX"}, {0, NULL}}; +static CV_PossibleValue_t numlaps_cons_t[] = {{1, "MIN"}, {50, "MAX"}, {0, NULL}}; consvar_t cv_numlaps = {"numlaps", "3", CV_NETVAR|CV_CALL|CV_NOINIT, numlaps_cons_t, NumLaps_OnChange, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_usemapnumlaps = {"usemaplaps", "Yes", CV_NETVAR|CV_CHEAT, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; +static CV_PossibleValue_t basenumlaps_cons_t[] = {{1, "MIN"}, {50, "MAX"}, {0, "Map default"}, {0, NULL}}; +consvar_t cv_basenumlaps = {"basenumlaps", "Map default", CV_NETVAR|CV_CALL|CV_CHEAT, basenumlaps_cons_t, BaseNumLaps_OnChange, 0, NULL, NULL, 0, 0, NULL}; // log elemental hazards -- not a netvar, is local to current player consvar_t cv_hazardlog = {"hazardlog", "Yes", 0, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -429,7 +432,7 @@ consvar_t cv_maxping = {"maxping", "0", CV_SAVE, CV_Unsigned, NULL, 0, NULL, NUL static CV_PossibleValue_t inttime_cons_t[] = {{0, "MIN"}, {3600, "MAX"}, {0, NULL}}; consvar_t cv_inttime = {"inttime", "20", CV_NETVAR, inttime_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -static CV_PossibleValue_t advancemap_cons_t[] = {{0, "Off"}, {1, "Next"}, {2, "Random"}, {3, "Vote"}, {0, NULL}}; +static CV_PossibleValue_t advancemap_cons_t[] = {{0, "Same"}, {1, "Next"}, {2, "Random"}, {3, "Vote"}, {0, NULL}}; consvar_t cv_advancemap = {"advancemap", "Vote", CV_NETVAR, advancemap_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; static CV_PossibleValue_t playersforexit_cons_t[] = {{0, "One"}, {1, "All"}, {0, NULL}}; consvar_t cv_playersforexit = {"playersforexit", "One", CV_NETVAR, playersforexit_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -442,6 +445,7 @@ consvar_t cv_mute = {"mute", "Off", CV_NETVAR|CV_CALL, CV_OnOff, Mute_OnChange, consvar_t cv_sleep = {"cpusleep", "-1", CV_SAVE, sleeping_cons_t, NULL, -1, NULL, NULL, 0, 0, NULL}; INT16 gametype = GT_RACE; // SRB2kart +boolean forceresetplayers = false; UINT8 splitscreen = 0; boolean circuitmap = true; // SRB2kart INT32 adminplayers[MAXPLAYERS]; @@ -579,7 +583,7 @@ void D_RegisterServerCommands(void) CV_RegisterVar(&cv_friendlyfire); CV_RegisterVar(&cv_pointlimit); CV_RegisterVar(&cv_numlaps); - CV_RegisterVar(&cv_usemapnumlaps); + CV_RegisterVar(&cv_basenumlaps); CV_RegisterVar(&cv_hazardlog); @@ -603,7 +607,7 @@ void D_RegisterServerCommands(void) CV_RegisterVar(&cv_competitionboxes); CV_RegisterVar(&cv_matchboxes); - CV_RegisterVar(&cv_recycler); + /*CV_RegisterVar(&cv_recycler); CV_RegisterVar(&cv_teleporters); CV_RegisterVar(&cv_superring); CV_RegisterVar(&cv_supersneakers); @@ -614,7 +618,7 @@ void D_RegisterServerCommands(void) CV_RegisterVar(&cv_forceshield); CV_RegisterVar(&cv_bombshield); CV_RegisterVar(&cv_1up); - CV_RegisterVar(&cv_eggmanbox); + CV_RegisterVar(&cv_eggmanbox);*/ K_RegisterKartStuff(); // SRB2kart @@ -776,6 +780,13 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_usegamma); // m_menu.c + CV_RegisterVar(&cv_chatheight); + CV_RegisterVar(&cv_chatwidth); + CV_RegisterVar(&cv_chattime); + CV_RegisterVar(&cv_chatspamprotection); + CV_RegisterVar(&cv_consolechat); + CV_RegisterVar(&cv_chatnotifications); + CV_RegisterVar(&cv_chatbacktint); CV_RegisterVar(&cv_crosshair); CV_RegisterVar(&cv_crosshair2); CV_RegisterVar(&cv_crosshair3); @@ -858,7 +869,7 @@ void D_RegisterClientCommands(void) // s_sound.c CV_RegisterVar(&cv_soundvolume); CV_RegisterVar(&cv_digmusicvolume); - CV_RegisterVar(&cv_midimusicvolume); + //CV_RegisterVar(&cv_midimusicvolume); CV_RegisterVar(&cv_numChannels); // i_cdmus.c @@ -1152,7 +1163,7 @@ UINT8 CanChangeSkin(INT32 playernum) return true; // Can change skin during initial countdown. - if (leveltime < 4*TICRATE) + if (leveltime < starttime) return true; if (G_TagGametype()) @@ -1875,6 +1886,8 @@ void D_MapChange(INT32 mapnum, INT32 newgametype, boolean pultmode, boolean rese static char buf[2+MAX_WADPATH+1+4]; static char *buf_p = buf; + forceresetplayers = false; + // The supplied data are assumed to be good. I_Assert(delay >= 0 && delay <= 2); @@ -1955,16 +1968,22 @@ void D_MapChange(INT32 mapnum, INT32 newgametype, boolean pultmode, boolean rese void D_SetupVote(void) { - char buf[8]; - char *p = buf; + UINT8 buf[6*2]; // five UINT16 maps (at twice the width of a UINT8), and two gametypes + UINT8 *p = buf; INT32 i; + UINT8 secondgt = G_SometimesGetDifferentGametype(); - for (i = 0; i < 4; i++) + WRITEUINT8(p, gametype); + WRITEUINT8(p, secondgt); + + for (i = 0; i < 5; i++) { - if (i == 3) - WRITEUINT16(p, G_RandMap(G_TOLFlag(gametype), prevmap, true, false)); + if (i == 2) // sometimes a different gametype + WRITEUINT16(p, G_RandMap(G_TOLFlag(secondgt), prevmap, false, false, 0, true)); + else if (i >= 3) // unknown-random and force-unknown MAP HELL + WRITEUINT16(p, G_RandMap(G_TOLFlag(gametype), prevmap, true, false, (i-2), (i < 4))); else - WRITEUINT16(p, G_RandMap(G_TOLFlag(gametype), prevmap, false, false)); + WRITEUINT16(p, G_RandMap(G_TOLFlag(gametype), prevmap, false, false, 0, true)); } SendNetXCmd(XD_SETUPVOTE, buf, p - buf); @@ -1990,7 +2009,9 @@ void D_PickVote(void) char* p = buf; SINT8 temppicks[MAXPLAYERS]; SINT8 templevels[MAXPLAYERS]; + SINT8 votecompare = -1; UINT8 numvotes = 0, key = 0; + boolean force = true; INT32 i; for (i = 0; i < MAXPLAYERS; i++) @@ -2002,6 +2023,10 @@ void D_PickVote(void) temppicks[numvotes] = i; templevels[numvotes] = votes[i]; numvotes++; + if (votecompare == -1) + votecompare = votes[i]; + else if (votes[i] != votecompare) + force = false; } } @@ -2010,7 +2035,10 @@ void D_PickVote(void) if (numvotes > 0) { WRITESINT8(p, temppicks[key]); - WRITESINT8(p, templevels[key]); + if (force && templevels[key] == 3 && numvotes > 1) + WRITESINT8(p, 4); + else + WRITESINT8(p, templevels[key]); } else { @@ -2102,7 +2130,6 @@ static void Command_Map_f(void) // Don't do any variable setting here. Wait until you get your // map packet first to avoid sending the same info twice! newgametype = gametype_cons_t[j].value; - break; } @@ -2120,26 +2147,23 @@ static void Command_Map_f(void) } } + if (!(i = COM_CheckParm("-force")) && newgametype == gametype) // SRB2Kart + newresetplayers = false; // if not forcing and gametypes is the same + // don't use a gametype the map doesn't support - if (cv_debug || COM_CheckParm("-force") || cv_skipmapcheck.value) + if (cv_debug || i || cv_skipmapcheck.value) ; // The player wants us to trek on anyway. Do so. // G_TOLFlag handles both multiplayer gametype and ignores it for !multiplayer // Alternatively, bail if the map header is completely missing anyway. - else if (!mapheaderinfo[newmapnum-1] - || !(mapheaderinfo[newmapnum-1]->typeoflevel & G_TOLFlag(newgametype))) + else { - char gametypestring[32] = "Single Player"; - - if (multiplayer) - for (i = 0; gametype_cons_t[i].strvalue != NULL; i++) - if (gametype_cons_t[i].value == newgametype) - { - strcpy(gametypestring, gametype_cons_t[i].strvalue); - break; - } - - CONS_Alert(CONS_WARNING, M_GetText("%s doesn't support %s mode!\n(Use -force to override)\n"), mapname, gametypestring); - return; + if (!mapheaderinfo[newmapnum-1] + || !(mapheaderinfo[newmapnum-1]->typeoflevel & G_TOLFlag(newgametype))) + { + CONS_Alert(CONS_WARNING, M_GetText("%s doesn't support %s mode!\n(Use -force to override)\n"), mapname, + (multiplayer ? gametype_cons_t[newgametype].strvalue : "Single Player")); + return; + } } // Prevent warping to locked levels @@ -2225,6 +2249,9 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum) emeralds = 0; } + if (modeattacking) // i remember moving this here in internal fixed a heisenbug so + SetPlayerSkinByNum(0, cv_chooseskin.value-1); + #ifdef HAVE_BLUA LUAh_MapChange(); #endif @@ -2236,15 +2263,6 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum) if (timingdemo) G_DoneLevelLoad(); - if (modeattacking) - { - SetPlayerSkinByNum(0, cv_chooseskin.value-1); - players[0].skincolor = cv_playercolor.value; // srb2kart - - // a copy of color - if (players[0].mo) - players[0].mo->color = players[0].skincolor; - } if (metalrecording) G_BeginMetal(); if (demorecording) // Okay, level loaded, character spawned and skinned, @@ -2344,7 +2362,7 @@ static void Command_Suicide(void) return; } - /*if (!G_RaceGametype()) // srb2kart: not necessary, suiciding makes you lose a balloon in battle, so it's not desirable to use as a way to escape a hit + /*if (!G_RaceGametype()) // srb2kart: not necessary, suiciding makes you lose a bumper in battle, so it's not desirable to use as a way to escape a hit { CONS_Printf(M_GetText("You may only use this in co-op, race, and competition!\n")); return; @@ -2511,18 +2529,12 @@ static void Command_Teamchange_f(void) return; } - if (G_GametypeHasTeams()) - { - if (NetPacket.packet.newteam == (unsigned)players[consoleplayer].ctfteam || - (players[consoleplayer].spectator && !NetPacket.packet.newteam)) - error = true; - } - else if (G_GametypeHasSpectators()) - { - if ((players[consoleplayer].spectator && !NetPacket.packet.newteam) || - (!players[consoleplayer].spectator && NetPacket.packet.newteam == 3)) - error = true; - } + if (players[consoleplayer].spectator) + error = !(NetPacket.packet.newteam || (players[consoleplayer].pflags & PF_WANTSTOJOIN)); // :lancer: + else if (G_GametypeHasTeams()) + error = (NetPacket.packet.newteam == (unsigned)players[consoleplayer].ctfteam); + else if (G_GametypeHasSpectators() && !players[consoleplayer].spectator) + error = (NetPacket.packet.newteam == 3); #ifdef PARANOIA else I_Error("Invalid gametype after initial checks!"); @@ -2608,18 +2620,12 @@ static void Command_Teamchange2_f(void) return; } - if (G_GametypeHasTeams()) - { - if (NetPacket.packet.newteam == (unsigned)players[secondarydisplayplayer].ctfteam || - (players[secondarydisplayplayer].spectator && !NetPacket.packet.newteam)) - error = true; - } - else if (G_GametypeHasSpectators()) - { - if ((players[secondarydisplayplayer].spectator && !NetPacket.packet.newteam) || - (!players[secondarydisplayplayer].spectator && NetPacket.packet.newteam == 3)) - error = true; - } + if (players[secondarydisplayplayer].spectator) + error = !(NetPacket.packet.newteam || (players[secondarydisplayplayer].pflags & PF_WANTSTOJOIN)); + else if (G_GametypeHasTeams()) + error = (NetPacket.packet.newteam == (unsigned)players[secondarydisplayplayer].ctfteam); + else if (G_GametypeHasSpectators() && !players[secondarydisplayplayer].spectator) + error = (NetPacket.packet.newteam == 3); #ifdef PARANOIA else I_Error("Invalid gametype after initial checks!"); @@ -2705,18 +2711,12 @@ static void Command_Teamchange3_f(void) return; } - if (G_GametypeHasTeams()) - { - if (NetPacket.packet.newteam == (unsigned)players[thirddisplayplayer].ctfteam || - (players[thirddisplayplayer].spectator && !NetPacket.packet.newteam)) - error = true; - } - else if (G_GametypeHasSpectators()) - { - if ((players[thirddisplayplayer].spectator && !NetPacket.packet.newteam) || - (!players[thirddisplayplayer].spectator && NetPacket.packet.newteam == 3)) - error = true; - } + if (players[thirddisplayplayer].spectator) + error = !(NetPacket.packet.newteam || (players[thirddisplayplayer].pflags & PF_WANTSTOJOIN)); + else if (G_GametypeHasTeams()) + error = (NetPacket.packet.newteam == (unsigned)players[thirddisplayplayer].ctfteam); + else if (G_GametypeHasSpectators() && !players[thirddisplayplayer].spectator) + error = (NetPacket.packet.newteam == 3); #ifdef PARANOIA else I_Error("Invalid gametype after initial checks!"); @@ -2802,18 +2802,12 @@ static void Command_Teamchange4_f(void) return; } - if (G_GametypeHasTeams()) - { - if (NetPacket.packet.newteam == (unsigned)players[fourthdisplayplayer].ctfteam || - (players[fourthdisplayplayer].spectator && !NetPacket.packet.newteam)) - error = true; - } - else if (G_GametypeHasSpectators()) - { - if ((players[fourthdisplayplayer].spectator && !NetPacket.packet.newteam) || - (!players[fourthdisplayplayer].spectator && NetPacket.packet.newteam == 3)) - error = true; - } + if (players[fourthdisplayplayer].spectator) + error = !(NetPacket.packet.newteam || (players[fourthdisplayplayer].pflags & PF_WANTSTOJOIN)); + else if (G_GametypeHasTeams()) + error = (NetPacket.packet.newteam == (unsigned)players[fourthdisplayplayer].ctfteam); + else if (G_GametypeHasSpectators() && !players[fourthdisplayplayer].spectator) + error = (NetPacket.packet.newteam == 3); #ifdef PARANOIA else I_Error("Invalid gametype after initial checks!"); @@ -3013,24 +3007,23 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum) } // Prevent multiple changes in one go. - if (G_TagGametype()) + if (players[playernum].spectator && !(players[playernum].pflags & PF_WANTSTOJOIN) && !NetPacket.packet.newteam) + return; + else if (G_TagGametype()) { if (((players[playernum].pflags & PF_TAGIT) && NetPacket.packet.newteam == 1) || (!(players[playernum].pflags & PF_TAGIT) && NetPacket.packet.newteam == 2) || - (players[playernum].spectator && NetPacket.packet.newteam == 0) || (!players[playernum].spectator && NetPacket.packet.newteam == 3)) return; } else if (G_GametypeHasTeams()) { - if ((NetPacket.packet.newteam && (NetPacket.packet.newteam == (unsigned)players[playernum].ctfteam)) || - (players[playernum].spectator && !NetPacket.packet.newteam)) + if (NetPacket.packet.newteam && (NetPacket.packet.newteam == (unsigned)players[playernum].ctfteam)) return; } else if (G_GametypeHasSpectators()) { - if ((players[playernum].spectator && !NetPacket.packet.newteam) || - (!players[playernum].spectator && NetPacket.packet.newteam == 3)) + if (!players[playernum].spectator && NetPacket.packet.newteam == 3) return; } else @@ -3102,19 +3095,26 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum) } //Safety first! - if (players[playernum].mo) + // (not respawning spectators here...) + if (!players[playernum].spectator) { - if (!players[playernum].spectator) - P_DamageMobj(players[playernum].mo, NULL, NULL, 10000); - else + if (players[playernum].mo) { - P_RemoveMobj(players[playernum].mo); - players[playernum].mo = NULL; - players[playernum].playerstate = PST_REBORN; + //if (!players[playernum].spectator) + P_DamageMobj(players[playernum].mo, NULL, NULL, 10000); + /*else + { + if (players[playernum].mo) + { + P_RemoveMobj(players[playernum].mo); + players[playernum].mo = NULL; + } + players[playernum].playerstate = PST_REBORN; + }*/ } + else + players[playernum].playerstate = PST_REBORN; } - else - players[playernum].playerstate = PST_REBORN; //Now that we've done our error checking and killed the player //if necessary, put the player on the correct team/status. @@ -3128,7 +3128,7 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum) } else if (NetPacket.packet.newteam != 3) // .newteam == 1 or 2. { - players[playernum].spectator = false; + players[playernum].pflags |= PF_WANTSTOJOIN; //players[playernum].spectator = false; players[playernum].pflags &= ~PF_TAGGED;//Just in case. if (NetPacket.packet.newteam == 1) //Make the player IT. @@ -3138,7 +3138,7 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum) } else // Just join the game. { - players[playernum].spectator = false; + players[playernum].pflags |= PF_WANTSTOJOIN; //players[playernum].spectator = false; //If joining after hidetime in normal tag, default to being IT. if (gametype == GT_TAG && (leveltime > (hidetime * TICRATE))) @@ -3158,7 +3158,7 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum) else { players[playernum].ctfteam = NetPacket.packet.newteam; - players[playernum].spectator = false; + players[playernum].pflags |= PF_WANTSTOJOIN; //players[playernum].spectator = false; } } else if (G_GametypeHasSpectators()) @@ -3166,7 +3166,7 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum) if (!NetPacket.packet.newteam) players[playernum].spectator = true; else - players[playernum].spectator = false; + players[playernum].pflags |= PF_WANTSTOJOIN; //players[playernum].spectator = false; } if (NetPacket.packet.autobalance) @@ -3198,7 +3198,9 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum) CONS_Printf(M_GetText("%s switched to the %c%s%c.\n"), player_names[playernum], '\x84', M_GetText("Blue Team"), '\x80'); } else if (NetPacket.packet.newteam == 3) - CONS_Printf(M_GetText("%s entered the game.\n"), player_names[playernum]); + /*CONS_Printf(M_GetText("%s entered the game.\n"), player_names[playernum])*/; + else if (players[playernum].pflags & PF_WANTSTOJOIN) + players[playernum].pflags &= ~PF_WANTSTOJOIN; else CONS_Printf(M_GetText("%s became a spectator.\n"), player_names[playernum]); @@ -3221,10 +3223,18 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum) } } + if (gamestate != GS_LEVEL) + return; + // Clear player score and rings if a spectator. if (players[playernum].spectator) { - //players[playernum].score = 0; // SRB2kart + if (G_BattleGametype()) // SRB2kart + { + players[playernum].marescore = 0; + if (K_IsPlayerWanted(&players[playernum])) + K_CalculateBattleWanted(); + } players[playernum].health = 1; if (players[playernum].mo) players[playernum].mo->health = 1; @@ -3234,7 +3244,7 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum) if (G_TagGametype()) P_CheckSurvivors(); else if (G_BattleGametype()) - K_CheckBalloons(); // SRB2Kart + K_CheckBumpers(); // SRB2Kart else if (G_RaceGametype()) P_CheckRacers(); // also SRB2Kart } @@ -3271,10 +3281,12 @@ static void D_MD5PasswordPass(const UINT8 *buffer, size_t len, const char *salt, #define BASESALT "basepasswordstorage" static UINT8 adminpassmd5[16]; +static boolean adminpasswordset = false; void D_SetPassword(const char *pw) { D_MD5PasswordPass((const UINT8 *)pw, strlen(pw), BASESALT, &adminpassmd5); + adminpasswordset = true; } // Remote Administration @@ -3346,6 +3358,12 @@ static void Got_Login(UINT8 **cp, INT32 playernum) if (client) return; + if (!adminpasswordset) + { + CONS_Printf(M_GetText("Password from %s failed (no password set).\n"), player_names[playernum]); + return; + } + // Do the final pass to compare with the sent md5 D_MD5PasswordPass(adminpassmd5, 16, va("PNUM%02d", playernum), &finalmd5); @@ -4026,27 +4044,12 @@ static void Command_ModDetails_f(void) // static void Command_ShowGametype_f(void) { - INT32 j; - const char *gametypestr = NULL; - - if (!(netgame || multiplayer)) // print "Single player" instead of "Co-op" + if (!(netgame || multiplayer)) // print "Single player" instead of "Race" { - CONS_Printf(M_GetText("Current gametype is %s\n"), M_GetText("Single player")); + CONS_Printf(M_GetText("Current gametype is %s\n"), "Single Player"); return; } - // find name string for current gametype - for (j = 0; gametype_cons_t[j].strvalue; j++) - { - if (gametype_cons_t[j].value == gametype) - { - gametypestr = gametype_cons_t[j].strvalue; - break; - } - } - if (gametypestr) - CONS_Printf(M_GetText("Current gametype is %s\n"), gametypestr); - else // string for current gametype was not found above (should never happen) - CONS_Printf(M_GetText("Unknown gametype set (%d)\n"), gametype); + CONS_Printf(M_GetText("Current gametype is %s\n"), gametype_cons_t[gametype].strvalue); } /** Plays the intro. @@ -4179,20 +4182,9 @@ static void TimeLimit_OnChange(void) */ void D_GameTypeChanged(INT32 lastgametype) { - if (netgame) - { - INT32 j; - const char *oldgt = NULL, *newgt = NULL; - for (j = 0; gametype_cons_t[j].strvalue; j++) - { - if (gametype_cons_t[j].value == lastgametype) - oldgt = gametype_cons_t[j].strvalue; - if (gametype_cons_t[j].value == gametype) - newgt = gametype_cons_t[j].strvalue; - } - if (oldgt && newgt) - CONS_Printf(M_GetText("Gametype was changed from %s to %s\n"), oldgt, newgt); - } + if (multiplayer) + CONS_Printf(M_GetText("Gametype was changed from %s to %s\n"), gametype_cons_t[lastgametype].strvalue, gametype_cons_t[gametype].strvalue); + // Only do the following as the server, not as remote admin. // There will always be a server, and this only needs to be done once. if (server && (multiplayer || netgame)) @@ -4268,7 +4260,7 @@ void D_GameTypeChanged(INT32 lastgametype) // When swapping to a gametype that supports spectators, // make everyone a spectator initially. - /*if (!splitscreen && (G_GametypeHasSpectators())) + /*if (G_GametypeHasSpectators()) { INT32 i; for (i = 0; i < MAXPLAYERS; i++) @@ -4596,6 +4588,7 @@ static void Got_ExitLevelcmd(UINT8 **cp, INT32 playernum) static void Got_SetupVotecmd(UINT8 **cp, INT32 playernum) { INT32 i; + UINT8 gt, secondgt; if (playernum != serverplayer && !IsPlayerAdmin(playernum)) { @@ -4611,13 +4604,19 @@ static void Got_SetupVotecmd(UINT8 **cp, INT32 playernum) return; } - for (i = 0; i < 4; i++) + gt = (UINT8)READUINT8(*cp); + secondgt = (UINT8)READUINT8(*cp); + + for (i = 0; i < 5; i++) { - votelevels[i] = (INT16)READUINT16(*cp); - if (!mapheaderinfo[votelevels[i]]) - P_AllocMapHeader(votelevels[i]); + votelevels[i][0] = (UINT16)READUINT16(*cp); + votelevels[i][1] = gt; + if (!mapheaderinfo[votelevels[i][0]]) + P_AllocMapHeader(votelevels[i][0]); } + votelevels[2][1] = secondgt; + G_SetGamestate(GS_VOTING); Y_StartVote(); } @@ -4742,7 +4741,7 @@ static void Command_RestartAudio_f(void) I_SetSfxVolume(cv_soundvolume.value); I_SetDigMusicVolume(cv_digmusicvolume.value); - I_SetMIDIMusicVolume(cv_midimusicvolume.value); + //I_SetMIDIMusicVolume(cv_midimusicvolume.value); if (Playing()) // Gotta make sure the player is in a level P_RestoreMusic(&players[consoleplayer]); @@ -5207,26 +5206,73 @@ static void Command_ShowTime_f(void) } // SRB2Kart: On change messages +static void BaseNumLaps_OnChange(void) +{ + if (gamestate == GS_LEVEL) + { + if (cv_basenumlaps.value) + CONS_Printf(M_GetText("Number of laps will be changed to %d next round.\n"), cv_basenumlaps.value); + else + CONS_Printf(M_GetText("Number of laps will be changed to map defaults next round.\n")); + } +} + + static void KartFrantic_OnChange(void) { - if ((boolean)cv_kartfrantic.value != franticitems && gamestate == GS_LEVEL) + if ((boolean)cv_kartfrantic.value != franticitems && gamestate == GS_LEVEL && leveltime > starttime) CONS_Printf(M_GetText("Frantic items will be turned %s next round.\n"), cv_kartfrantic.value ? M_GetText("on") : M_GetText("off")); + else + { + CONS_Printf(M_GetText("Frantic items has been turned %s.\n"), cv_kartfrantic.value ? M_GetText("on") : M_GetText("off")); + franticitems = (boolean)cv_kartfrantic.value; + } } static void KartSpeed_OnChange(void) { - if ((UINT8)cv_kartspeed.value != gamespeed && G_RaceGametype() && gamestate == GS_LEVEL) - CONS_Printf(M_GetText("Game speed will be changed to \"%s\" next round.\n"), cv_kartspeed.string); + if (G_RaceGametype()) + { + if ((UINT8)cv_kartspeed.value != gamespeed && gamestate == GS_LEVEL && leveltime > starttime) + CONS_Printf(M_GetText("Game speed will be changed to \"%s\" next round.\n"), cv_kartspeed.string); + else + { + CONS_Printf(M_GetText("Game speed has been changed to \"%s\".\n"), cv_kartspeed.string); + gamespeed = (UINT8)cv_kartspeed.value; + } + } } static void KartMirror_OnChange(void) { - if ((boolean)cv_kartmirror.value != mirrormode && G_RaceGametype() && gamestate == GS_LEVEL) - CONS_Printf(M_GetText("Mirror Mode will be turned %s next round.\n"), cv_kartmirror.value ? M_GetText("on") : M_GetText("off")); + if (G_RaceGametype()) + { + if ((boolean)cv_kartmirror.value != mirrormode && gamestate == GS_LEVEL /*&& leveltime > starttime*/) + CONS_Printf(M_GetText("Mirrored tracks will be turned %s next round.\n"), cv_kartmirror.value ? M_GetText("on") : M_GetText("off")); + else + { + CONS_Printf(M_GetText("Mirrored tracks has been turned %s.\n"), cv_kartmirror.value ? M_GetText("on") : M_GetText("off")); + mirrormode = (boolean)cv_kartmirror.value; + } + } } static void KartComeback_OnChange(void) { - if ((boolean)cv_kartcomeback.value != comeback && G_BattleGametype() && gamestate == GS_LEVEL) - CONS_Printf(M_GetText("Karma Comeback will be turned %s next round.\n"), cv_kartcomeback.value ? M_GetText("on") : M_GetText("off")); -} \ No newline at end of file + if (G_BattleGametype()) + { + if ((boolean)cv_kartcomeback.value != comeback && gamestate == GS_LEVEL && leveltime > starttime) + CONS_Printf(M_GetText("Karma Comeback will be turned %s next round.\n"), cv_kartcomeback.value ? M_GetText("on") : M_GetText("off")); + else + { + CONS_Printf(M_GetText("Karma Comeback has been turned %s.\n"), cv_kartcomeback.value ? M_GetText("on") : M_GetText("off")); + comeback = (boolean)cv_kartcomeback.value; + } + } +} + +static void KartEliminateLast_OnChange(void) +{ + if (G_RaceGametype() && cv_karteliminatelast.value) + P_CheckRacers(); +} diff --git a/src/d_netcmd.h b/src/d_netcmd.h index ad957ed7..b2a57bc0 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -77,7 +77,7 @@ extern consvar_t cv_friendlyfire; extern consvar_t cv_pointlimit; extern consvar_t cv_timelimit; extern consvar_t cv_numlaps; -extern consvar_t cv_usemapnumlaps; +extern consvar_t cv_basenumlaps; extern UINT32 timelimitintics; extern consvar_t cv_allowexitlevel; @@ -103,31 +103,37 @@ extern consvar_t cv_pause; extern consvar_t cv_restrictskinchange, cv_allowteamchange, cv_respawntime; -extern consvar_t cv_teleporters, cv_superring, cv_supersneakers, cv_invincibility; +/*extern consvar_t cv_teleporters, cv_superring, cv_supersneakers, cv_invincibility; extern consvar_t cv_jumpshield, cv_watershield, cv_ringshield, cv_forceshield, cv_bombshield; extern consvar_t cv_1up, cv_eggmanbox; -extern consvar_t cv_recycler; +extern consvar_t cv_recycler;*/ // SRB2kart items -extern consvar_t cv_magnet, cv_boo, cv_mushroom, cv_triplemushroom, cv_megashroom; -extern consvar_t cv_goldshroom, cv_star, cv_triplebanana, cv_fakeitem, cv_banana; -extern consvar_t cv_greenshell, cv_redshell, cv_laserwisp, cv_triplegreenshell, cv_bobomb; -extern consvar_t cv_blueshell, cv_jaws, cv_fireflower, cv_tripleredshell, cv_lightning; -extern consvar_t cv_feather; +extern consvar_t cv_sneaker, cv_rocketsneaker, cv_invincibility, cv_banana; +extern consvar_t cv_eggmanmonitor, cv_orbinaut, cv_jawz, cv_mine; +extern consvar_t cv_ballhog, cv_selfpropelledbomb, cv_grow, cv_shrink; +extern consvar_t cv_thundershield, cv_hyudoro, cv_pogospring; + +extern consvar_t cv_triplesneaker, cv_triplebanana, cv_tripleorbinaut, cv_dualjawz; extern consvar_t cv_karthud; extern consvar_t cv_kartminimap; extern consvar_t cv_kartcheck; -extern consvar_t cv_kartstarsfx; +extern consvar_t cv_kartinvinsfx; extern consvar_t cv_kartspeed; -extern consvar_t cv_kartballoons; +extern consvar_t cv_kartbumpers; extern consvar_t cv_kartfrantic; extern consvar_t cv_kartcomeback; extern consvar_t cv_kartmirror; -extern consvar_t cv_speedometer; +extern consvar_t cv_kartspeedometer; +extern consvar_t cv_kartvoices; + +extern consvar_t cv_karteliminatelast; extern consvar_t cv_votetime; +extern consvar_t cv_kartdebugitem, cv_kartdebugamount, cv_kartdebugcheckpoint, cv_kartdebugshrink; + extern consvar_t cv_itemfinder; extern consvar_t cv_inttime, cv_advancemap, cv_playersforexit; diff --git a/src/d_player.h b/src/d_player.h index 2ca419d9..95d703ef 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -108,8 +108,8 @@ typedef enum // Did you get a time-over? PF_TIMEOVER = 1<<10, - // Ready for Super? - PF_SUPERREADY = 1<<11, + // SRB2Kart: Spectator that wants to join + PF_WANTSTOJOIN = 1<<11, // Character action status PF_JUMPED = 1<<12, @@ -230,93 +230,109 @@ typedef enum NUMPOWERS } powertype_t; +typedef enum +{ + KITEM_SAD = -1, + KITEM_NONE = 0, + KITEM_SNEAKER, + KITEM_ROCKETSNEAKER, + KITEM_INVINCIBILITY, + KITEM_BANANA, + KITEM_EGGMAN, + KITEM_ORBINAUT, + KITEM_JAWZ, + KITEM_MINE, + KITEM_BALLHOG, + KITEM_SPB, + KITEM_GROW, + KITEM_SHRINK, + KITEM_THUNDERSHIELD, + KITEM_HYUDORO, + KITEM_POGOSPRING, + KITEM_KITCHENSINK, + + NUMKARTITEMS, + + // Additional roulette numbers, only used for K_KartGetItemResult + KRITEM_TRIPLESNEAKER = NUMKARTITEMS, + KRITEM_TRIPLEBANANA, + KRITEM_TENFOLDBANANA, + KRITEM_TRIPLEORBINAUT, + KRITEM_QUADORBINAUT, + KRITEM_DUALJAWZ, + + NUMKARTRESULTS +} kartitems_t; + //{ SRB2kart - kartstuff typedef enum { // Basic gameplay things k_position, // Used for Kart positions, mostly for deterministic stuff k_oldposition, // Used for taunting when you pass someone - k_positiondelay, // Prevents player from taunting continuously if two people were neck-and-neck + k_positiondelay, // Used for position number, so it can grow when passing/being passed k_prevcheck, // Previous checkpoint distance; for p_user.c (was "pw_pcd") 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_lakitu, // Timer for Lakitu to carry and drop the player + k_respawn, // Timer for the DEZ laser respawn effect k_throwdir, // Held dir of controls; 1 = forward, 0 = none, -1 = backward (was "player->heldDir") - k_lapanimation, // Used to make a swoopy lap lakitu, maybe other effects in the future + k_lapanimation, // Used to show the lap start wing logo animation k_cardanimation, // Used to determine the position of some full-screen Battle Mode graphics k_voices, // Used to stop the player saying more voices than it should k_tauntvoices, // Used to specifically stop taunt voice spam + k_instashield, // Instashield no-damage animation timer - k_boosting, // Determines if you're currently shroom-boosting - k_floorboost, // Prevents Mushroom sounds for a breif duration when triggered by a floor panel - k_spinout, // Separate confirmation to prevent endless wipeout loops + k_floorboost, // Prevents Sneaker sounds for a breif duration when triggered by a floor panel k_spinouttype, // Determines whether to thrust forward or not while spinning out; 0 = move forwards, 1 = stay still k_drift, // Drifting Left or Right, plus a bigger counter = sharper turn k_driftend, // Drift has ended, used to adjust character angle after drift k_driftcharge, // Charge your drift so you can release a burst of speed k_driftboost, // Boost you get from drifting - k_boostcharge, // Charge-up for boosting at the start of the race, or when Lakitu drops you + k_boostcharge, // Charge-up for boosting at the start of the race, or when dropping from respawn k_jmp, // In Mario Kart, letting go of the jump button stops the drift k_offroad, // In Super Mario Kart, going offroad has lee-way of about 1 second before you start losing speed + k_pogospring, // Pogo spring bounce effect k_brakestop, // Wait until you've made a complete stop for a few tics before letting brake go in reverse. + k_waterskip, // Water skipping counter k_itemroulette, // Used for the roulette when deciding what item to give you (was "pw_kartitem") k_roulettetype, // Used for the roulette, for deciding type (currently only used for Battle, to give you better items from Karma items) - k_itemclose, // Used to animate the item window closing (was "pw_psychic") + + // Item held stuff + k_itemtype, // KITEM_ constant for item number + k_itemamount, // Amount of said item + k_itemheld, // Are you holding an item? // Some items use timers for their duration or effects - k_magnettimer, // Duration of Magnet's item-break and item box pull - k_bootimer, // Duration of the boo offroad effect itself - k_bootaketimer, // You are stealing an item, this is your timer - k_boostolentimer, // You are being stolen from, this is your timer - k_mushroomtimer, // Duration of the Mushroom Boost itself - k_growshrinktimer, // > 0 = Big, < 0 = small - k_squishedtimer, // Squished frame timer - k_goldshroomtimer, // Gold Mushroom duration timer - k_startimer, // Invincibility timer - k_spinouttimer, // Spin-out from a banana peel or oil slick (was "pw_bananacam") - k_laserwisptimer, // The duration and relative angle of the laser - k_justbumped, // Prevent players from endlessly bumping into each other - k_deathsentence, // 30 seconds to live... (Blue Shell murder timer (not actually 30 sec, I just couldn't help the FF reference :p)) - k_poweritemtimer, // Battle mode, how long before you're allowed another power item (Star, Megashroom) - k_comebacktimer, // Battle mode, how long before you become a bomb after death - - // Each item needs its own power slot, for the HUD and held use - // *** ADDING A NEW ITEM? ADD IT TO K_DoBooSteal PLEASE!! -Salt *** - k_magnet, // 0x1 = Magnet in inventory - k_boo, // 0x1 = Boo in inventory - k_mushroom, // 0x1 = 1 Mushroom in inventory, 0x2 = 2 Mushrooms in inventory - // 0x4 = 3 Mushrooms in inventory - k_megashroom, // 0x1 = Mega Mushroom in inventory - k_goldshroom, // 0x1 = Gold Mushroom in inventory - k_star, // 0x1 = Star in inventory - k_triplebanana, // 0x1 = 1 Banana following, 0x2 = 2 Bananas following - // 0x4 = 3 Bananas following, 0x8 = Triple Banana in inventory - k_fakeitem, // 0x1 = Fake Item being held, 0x2 = Fake Item in inventory - k_banana, // 0x1 = Banana being held, 0x2 = Banana in inventory - k_greenshell, // 0x1 = Green Shell being held, 0x2 = Green Shell in inventory - k_redshell, // 0x1 = Red Shell being held, 0x2 = Red Shell in inventory - k_laserwisp, // 0x1 = Laser Wisp in inventory - k_triplegreenshell, // 0x1 = 1 Green Shell orbiting, 0x2 = 2 Green Shells orbiting - // 0x4 = 3 Green Shells orbiting, 0x8 = Triple Green Shell in inventory - k_bobomb, // 0x1 = Bob-omb being held, 0x2 = Bob-omb in inventory - k_blueshell, // 0x1 = Blue Shell in inventory - k_jaws, // 0x1 = 1 Jaws orbiting, 0x2 = 2 Jaws orbiting, - // 0x4 = 2x Jaws in inventory - k_fireflower, // 0x1 = Fire Flower in inventory - k_tripleredshell, // 0x1 = 1 Red Shell orbiting, 0x2 = 2 Red Shells orbiting - // 0x4 = 3 Red Shells orbiting, 0x8 = Triple Red Shell in inventory - k_lightning, // 0x1 = Lightning in inventory - k_feather, // 0x1 = Feather in inventory, 0x2 = Player is feather jumping - k_kitchensink, // 0x1 = Sink in inventory + //k_thunderanim, // Duration of Thunder Shield's use animation + k_curshield, // 0 = no shield, 1 = thunder shield + k_hyudorotimer, // Duration of the Hyudoro offroad effect itself + k_stealingtimer, // You are stealing an item, this is your timer + k_stolentimer, // You are being stolen from, this is your timer + k_sneakertimer, // Duration of the Sneaker Boost itself + k_growshrinktimer, // > 0 = Big, < 0 = small + k_squishedtimer, // Squished frame timer + k_rocketsneakertimer, // Rocket Sneaker duration timer + k_invincibilitytimer, // Invincibility timer + k_deathsentence, // 30 seconds to live... (SPB murder timer (not actually 30 sec, I just couldn't help the FF reference :p)) + k_eggmanheld, // Eggman monitor held, separate from k_itemheld so it doesn't stop you from getting items + k_eggmanexplode, // Fake item recieved, explode in a few seconds + k_eggmanblame, // Fake item recieved, who set this fake + k_bananadrag, // After a second of holding a banana behind you, you start to slow down + k_spinouttimer, // Spin-out from a banana peel or oil slick (was "pw_bananacam") + k_wipeoutslow, // Timer before you slowdown when getting wiped out + k_justbumped, // Prevent players from endlessly bumping into each other + k_comebacktimer, // Battle mode, how long before you become a bomb after death + k_sadtimer, // How long you've been sad // Battle Mode vars - k_balloon, // Number of balloons left - k_comebackpoints, // Number of times you've bombed or gave an item to someone; once it's 3 it gets set back to 0 and you're given a balloon + k_bumper, // Number of bumpers left + k_comebackpoints, // Number of times you've bombed or gave an item to someone; once it's 3 it gets set back to 0 and you're given a bumper k_comebackmode, // 0 = bomb, 1 = item + k_wanted, // Timer for determining WANTED status, lowers when hitting people, prevents the game turning into Camp Lazlo NUMKARTSTUFF } kartstufftype_t; @@ -511,7 +527,7 @@ typedef struct player_s tic_t startedtime; // Time which you started this mare with. tic_t finishedtime; // Time it took you to finish the mare (used for display) INT16 finishedrings; // The rings you had left upon finishing the mare - UINT32 marescore; // score for this nights stage + UINT32 marescore; // SRB2Kart: Battle score UINT32 lastmarescore; // score for the last mare UINT8 lastmare; // previous mare INT32 maxlink; // maximum link obtained diff --git a/src/dehacked.c b/src/dehacked.c index ffd572a4..28f20332 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1824,8 +1824,10 @@ static actionpointer_t actionpointers[] = {{A_RemoteAction}, "A_REMOTEACTION"}, {{A_ToggleFlameJet}, "A_TOGGLEFLAMEJET"}, {{A_ItemPop}, "A_ITEMPOP"}, // SRB2kart - {{A_RedShellChase}, "A_REDSHELLCHASE"}, // SRB2kart - {{A_BobombExplode}, "A_BOBOMBEXPLODE"}, // SRB2kart + {{A_JawzChase}, "A_JAWZCHASE"}, // SRB2kart + {{A_JawzExplode}, "A_JAWZEXPLODE"}, // SRB2kart + {{A_MineExplode}, "A_MINEEXPLODE"}, // SRB2kart + {{A_BallhogExplode}, "A_BALLHOGEXPLODE"}, // SRB2kart {{A_OrbitNights}, "A_ORBITNIGHTS"}, {{A_GhostMe}, "A_GHOSTME"}, {{A_SetObjectState}, "A_SETOBJECTSTATE"}, @@ -3182,6 +3184,14 @@ static void readwipes(MYFILE *f) else if (fastcmp(pword, "FINAL")) wipeoffset = wipe_specinter_final; } + else if (fastncmp(word, "VOTING_", 10)) + { + pword = word + 10; + if (fastcmp(pword, "TOBLACK")) + wipeoffset = wipe_specinter_toblack; + else if (fastcmp(pword, "FINAL")) + wipeoffset = wipe_specinter_final; + } else if (fastncmp(word, "MULTINTER_", 10)) { pword = word + 10; @@ -5807,15 +5817,9 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_FIREBALL2", "S_FIREBALL3", "S_FIREBALL4", - "S_FIREBALL5", - "S_FIREBALL6", - "S_FIREBALL7", "S_FIREBALLEXP1", "S_FIREBALLEXP2", "S_FIREBALLEXP3", - "S_FIREBALLEXP4", - "S_FIREBALLEXP5", - "S_FIREBALLEXP6", "S_SHELL", "S_SHELL1", "S_SHELL2", @@ -6243,9 +6247,9 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_DRIFTDUST3", "S_DRIFTDUST4", - // Magnet Burst + // Thunder Shield Burst - // Mushroom Fire Trail + // Sneaker Fire Trail "S_KARTFIRE1", "S_KARTFIRE2", "S_KARTFIRE3", @@ -6255,7 +6259,33 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_KARTFIRE7", "S_KARTFIRE8", - //{ Fake Item + // Invincibility Sparks + "S_KARTINVULN_SMALL1", + "S_KARTINVULN_SMALL2", + "S_KARTINVULN_SMALL3", + "S_KARTINVULN_SMALL4", + "S_KARTINVULN_SMALL5", + + "S_KARTINVULN_LARGE1", + "S_KARTINVULN_LARGE2", + "S_KARTINVULN_LARGE3", + "S_KARTINVULN_LARGE4", + "S_KARTINVULN_LARGE5", + + // Invincibility flash overlay + "S_INVULNFLASH1", + "S_INVULNFLASH2", + "S_INVULNFLASH3", + "S_INVULNFLASH4", + + // Wipeout dust trail + "S_WIPEOUTTRAIL1", + "S_WIPEOUTTRAIL2", + "S_WIPEOUTTRAIL3", + "S_WIPEOUTTRAIL4", + "S_WIPEOUTTRAIL5", + + //{ Eggman Monitor "S_FAKEITEM1", "S_FAKEITEM2", "S_FAKEITEM3", @@ -6284,81 +6314,79 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit //} // Banana - "S_BANANAITEM", - "S_DEADBANANA", + "S_BANANA", + "S_BANANA_DEAD", - //{ Green Shell - "S_TRIPLEGREENSHIELD1", - "S_TRIPLEGREENSHIELD2", - "S_TRIPLEGREENSHIELD3", - "S_TRIPLEGREENSHIELD4", - "S_TRIPLEGREENSHIELD5", - "S_TRIPLEGREENSHIELD6", - "S_TRIPLEGREENSHIELD7", - "S_TRIPLEGREENSHIELD8", - "S_GREENSHIELD1", - "S_GREENSHIELD2", - "S_GREENSHIELD3", - "S_GREENSHIELD4", - "S_GREENSHIELD5", - "S_GREENSHIELD6", - "S_GREENSHIELD7", - "S_GREENSHIELD8", - "S_GREENITEM1", - "S_GREENITEM2", - "S_GREENITEM3", - "S_GREENITEM4", - "S_GREENITEM5", - "S_GREENITEM6", - "S_GREENITEM7", - "S_GREENITEM8", - "S_DEADGREEN", + //{ Orbinaut + "S_ORBINAUT1", + "S_ORBINAUT2", + "S_ORBINAUT3", + "S_ORBINAUT4", + "S_ORBINAUT5", + "S_ORBINAUT6", + "S_ORBINAUT_DEAD", + "S_ORBINAUT_SHIELD1", + "S_ORBINAUT_SHIELD2", + "S_ORBINAUT_SHIELD3", + "S_ORBINAUT_SHIELD4", + "S_ORBINAUT_SHIELD5", + "S_ORBINAUT_SHIELD6", + "S_ORBINAUT_SHIELDDEAD", //} - //{ Red Shell - "S_TRIPLEREDSHIELD1", - "S_TRIPLEREDSHIELD2", - "S_TRIPLEREDSHIELD3", - "S_TRIPLEREDSHIELD4", - "S_TRIPLEREDSHIELD5", - "S_TRIPLEREDSHIELD6", - "S_TRIPLEREDSHIELD7", - "S_TRIPLEREDSHIELD8", - "S_REDSHIELD1", - "S_REDSHIELD2", - "S_REDSHIELD3", - "S_REDSHIELD4", - "S_REDSHIELD5", - "S_REDSHIELD6", - "S_REDSHIELD7", - "S_REDSHIELD8", - "S_REDITEM1", - "S_REDITEM2", - "S_REDITEM3", - "S_REDITEM4", - "S_REDITEM5", - "S_REDITEM6", - "S_REDITEM7", - "S_REDITEM8", - "S_DEADRED", + //{ Jawz + "S_JAWZ1", + "S_JAWZ2", + "S_JAWZ3", + "S_JAWZ4", + "S_JAWZ5", + "S_JAWZ6", + "S_JAWZ7", + "S_JAWZ8", + "S_JAWZ_DUD1", + "S_JAWZ_DUD2", + "S_JAWZ_DUD3", + "S_JAWZ_DUD4", + "S_JAWZ_DUD5", + "S_JAWZ_DUD6", + "S_JAWZ_DUD7", + "S_JAWZ_DUD8", + "S_JAWZ_SHIELD1", + "S_JAWZ_SHIELD2", + "S_JAWZ_SHIELD3", + "S_JAWZ_SHIELD4", + "S_JAWZ_SHIELD5", + "S_JAWZ_SHIELD6", + "S_JAWZ_SHIELD7", + "S_JAWZ_SHIELD8", + "S_JAWZ_DEAD1", + "S_JAWZ_DEAD2", //} - "S_FIRETRAIL1", - "S_FIRETRAIL2", - "S_FIRETRAIL3", - "S_FIRETRAIL4", - "S_FIRETRAIL5", - "S_FIRETRAIL6", - "S_FIRETRAIL7", - "S_FIRETRAIL8", - "S_FIRETRAIL9", - - // Bob-omb - "S_BOMBSHIELD", - "S_BOMBITEM", - "S_BOMBAIR", - "S_BOMBEXPLODE", - "S_BOMBEXPLOSION1", - "S_BOMBEXPLOSION2", + // Special Stage Mine + "S_SSMINE1", + "S_SSMINE2", + "S_SSMINE3", + "S_SSMINE4", + "S_SSMINE_SHIELD1", + "S_SSMINE_SHIELD2", + "S_SSMINE_AIR1", + "S_SSMINE_AIR2", + "S_SSMINE_DEPLOY1", + "S_SSMINE_DEPLOY2", + "S_SSMINE_DEPLOY3", + "S_SSMINE_DEPLOY4", + "S_SSMINE_DEPLOY5", + "S_SSMINE_DEPLOY6", + "S_SSMINE_DEPLOY7", + "S_SSMINE_DEPLOY8", + "S_SSMINE_DEPLOY9", + "S_SSMINE_DEPLOY10", + "S_SSMINE_DEPLOY11", + "S_SSMINE_DEPLOY12", + "S_SSMINE_DEPLOY13", + "S_SSMINE_EXPLODE", + "S_MINEEXPLOSION1", + "S_MINEEXPLOSION2", // New explosion "S_QUICKBOOM1", @@ -6383,33 +6411,85 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_SLOWBOOM9", "S_SLOWBOOM10", - // Blue Shell - Blue Lightning for now... + // Ballhog + "S_BALLHOG1", + "S_BALLHOG2", + "S_BALLHOG3", + "S_BALLHOG4", + "S_BALLHOG5", + "S_BALLHOG6", + "S_BALLHOG7", + "S_BALLHOG8", + "S_BALLHOG_DEAD", + "S_BALLHOGBOOM1", + "S_BALLHOGBOOM2", + "S_BALLHOGBOOM3", + "S_BALLHOGBOOM4", + "S_BALLHOGBOOM5", + "S_BALLHOGBOOM6", + "S_BALLHOGBOOM7", + "S_BALLHOGBOOM8", + "S_BALLHOGBOOM9", + "S_BALLHOGBOOM10", + "S_BALLHOGBOOM11", + "S_BALLHOGBOOM12", + "S_BALLHOGBOOM13", + "S_BALLHOGBOOM14", + "S_BALLHOGBOOM15", + "S_BALLHOGBOOM16", + + // Self-Propelled Bomb - just an explosion for now... "S_BLUELIGHTNING1", "S_BLUELIGHTNING2", "S_BLUELIGHTNING3", "S_BLUELIGHTNING4", "S_BLUEEXPLODE", - // Lightning + // Grow/shrink beams "S_LIGHTNING1", "S_LIGHTNING2", "S_LIGHTNING3", "S_LIGHTNING4", + // Thunder Shield + "S_THUNDERSHIELD1", + "S_THUNDERSHIELD2", + "S_THUNDERSHIELD3", + "S_THUNDERSHIELD4", + "S_THUNDERSHIELD5", + "S_THUNDERSHIELD6", + "S_THUNDERSHIELD7", + "S_THUNDERSHIELD8", + "S_THUNDERSHIELD9", + "S_THUNDERSHIELD10", + "S_THUNDERSHIELD11", + "S_THUNDERSHIELD12", + "S_THUNDERSHIELD13", + "S_THUNDERSHIELD14", + "S_THUNDERSHIELD15", + "S_THUNDERSHIELD16", + "S_THUNDERSHIELD17", + "S_THUNDERSHIELD18", + "S_THUNDERSHIELD19", + "S_THUNDERSHIELD20", + "S_THUNDERSHIELD21", + "S_THUNDERSHIELD22", + "S_THUNDERSHIELD23", + "S_THUNDERSHIELD24", + // The legend "S_SINK", "S_SINKTRAIL1", "S_SINKTRAIL2", "S_SINKTRAIL3", - // Battle Mode balloon - "S_BATTLEBALLOON1", - "S_BATTLEBALLOON2", - "S_BATTLEBALLOON3", + // Battle Mode bumper + "S_BATTLEBUMPER1", + "S_BATTLEBUMPER2", + "S_BATTLEBUMPER3", - // Lakitu - "S_LAKITU1", - "S_LAKITU2", + // DEZ respawn laser + "S_DEZLASER", // Pokey "S_POKEY1", @@ -6489,15 +6569,22 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_DOOD_BOX4", "S_DOOD_BOX5", - // D00Dkart - Diddy Kong Racing Balloon + // D00Dkart - Diddy Kong Racing Bumper "S_DOOD_BALLOON", - // D00Dkart - Big Ring - "S_DOOD_RING1", - "S_DOOD_RING2", - "S_DOOD_RING3", - "S_DOOD_RING4", - "S_DOOD_RING5", + // Chaotix Big Ring + "S_BIGRING01", + "S_BIGRING02", + "S_BIGRING03", + "S_BIGRING04", + "S_BIGRING05", + "S_BIGRING06", + "S_BIGRING07", + "S_BIGRING08", + "S_BIGRING09", + "S_BIGRING10", + "S_BIGRING11", + "S_BIGRING12", // SNES Objects "S_SNES_DONUTBUSH1", @@ -6569,28 +6656,38 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_FIREDITEM3", "S_FIREDITEM4", + "S_INSTASHIELDA1", // No damage instashield effect + "S_INSTASHIELDA2", + "S_INSTASHIELDA3", + "S_INSTASHIELDA4", + "S_INSTASHIELDA5", + "S_INSTASHIELDA6", + "S_INSTASHIELDA7", + "S_INSTASHIELDB1", + "S_INSTASHIELDB2", + "S_INSTASHIELDB3", + "S_INSTASHIELDB4", + "S_INSTASHIELDB5", + "S_INSTASHIELDB6", + "S_INSTASHIELDB7", + "S_PLAYERARROW", // Above player arrow - "S_PLAYERARROW_MUSHROOM", - "S_PLAYERARROW_GREENSHELL", - "S_PLAYERARROW_BANANA", - "S_PLAYERARROW_FAKEITEM", - "S_PLAYERARROW_BOO", - "S_PLAYERARROW_FEATHER", - "S_PLAYERARROW_REDSHELL", - "S_PLAYERARROW_BOBOMB", - "S_PLAYERARROW_FIREFLOWER", - "S_PLAYERARROW_TRIPLEGREENSHELL", - "S_PLAYERARROW_TRIPLEBANANA", - "S_PLAYERARROW_TRIPLEREDSHELL", - "S_PLAYERARROW_STAR", - "S_PLAYERARROW_MEGASHROOM", - "S_PLAYERARROW_KITCHENSINK", - "S_PLAYERARROW_EMPTY", - "S_PLAYERARROW_ROULETTE", + "S_PLAYERARROW_BOX", + "S_PLAYERARROW_ITEM", + "S_PLAYERARROW_NUMBER", + "S_PLAYERARROW_X", + "S_PLAYERARROW_WANTED1", + "S_PLAYERARROW_WANTED2", + "S_PLAYERARROW_WANTED3", + "S_PLAYERARROW_WANTED4", + "S_PLAYERARROW_WANTED5", + "S_PLAYERARROW_WANTED6", + "S_PLAYERARROW_WANTED7", "S_PLAYERBOMB", // Player bomb overlay "S_PLAYERITEM", // Player item overlay - "S_PLAYERBOMB_WHEEL", + + "S_KARMAWHEEL", // Karma player wheels #ifdef SEENAMES "S_NAMECHECK", @@ -7109,52 +7206,50 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_RANDOMITEM", "MT_RANDOMITEMPOP", - "MT_MUSHROOMTRAIL", + "MT_SNEAKERTRAIL", + "MT_SPARKLETRAIL", + "MT_INVULNFLASH", + "MT_WIPEOUTTRAIL", "MT_DRIFT", "MT_DRIFTDUST", "MT_FAKESHIELD", "MT_FAKEITEM", - "MT_TRIPLEBANANASHIELD1", // Banana Stuff - "MT_TRIPLEBANANASHIELD2", - "MT_TRIPLEBANANASHIELD3", - "MT_BANANASHIELD", - "MT_BANANAITEM", + "MT_BANANA", // Banana Stuff + "MT_BANANA_SHIELD", - "MT_TRIPLEGREENSHIELD1", // Green shell stuff - "MT_TRIPLEGREENSHIELD2", - "MT_TRIPLEGREENSHIELD3", - "MT_GREENSHIELD", - "MT_GREENITEM", - "MT_FIRETRAIL", + "MT_ORBINAUT", // Orbinaut stuff + "MT_ORBINAUT_SHIELD", - "MT_TRIPLEREDSHIELD1", // Red shell stuff - "MT_TRIPLEREDSHIELD2", - "MT_TRIPLEREDSHIELD3", - "MT_REDSHIELD", - "MT_REDITEM", - "MT_REDITEMDUD", + "MT_JAWZ", // Jawz stuff + "MT_JAWZ_DUD", + "MT_JAWZ_SHIELD", - "MT_BOMBSHIELD", // Bob-omb stuff - "MT_BOMBITEM", - "MT_BOMBEXPLOSION", - "MT_BOMBEXPLOSIONSOUND", + "MT_SSMINE_SHIELD", // Special Stage Mine stuff + "MT_SSMINE", + "MT_MINEEXPLOSION", + "MT_MINEEXPLOSIONSOUND", "MT_SMOLDERING", // New explosion "MT_BOOMEXPLODE", "MT_BOOMPARTICLE", - "MT_BLUELIGHTNING", // Lightning stuff + "MT_BALLHOG", // Ballhog + "MT_BALLHOGBOOM", + + "MT_BLUELIGHTNING", // Grow/shrink stuff "MT_BLUEEXPLOSION", "MT_LIGHTNING", + "MT_THUNDERSHIELD", // Thunder Shield stuff + "MT_SINK", // Kitchen Sink Stuff "MT_SINKTRAIL", - "MT_BATTLEBALLOON", // Battle Mode balloon + "MT_BATTLEBUMPER", // Battle Mode bumper - "MT_LAKITU", + "MT_DEZLASER", "MT_POKEY", // Huh, thought this was a default asset for some reason, guess not. @@ -7190,7 +7285,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_DOOD_FLOWER4", "MT_DOOD_BOX", "MT_DOOD_BALLOON", - "MT_DOOD_RING", + "MT_BIGRING", "MT_SNES_DONUTBUSH1", "MT_SNES_DONUTBUSH2", @@ -7225,7 +7320,14 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_FIREDITEM", + "MT_INSTASHIELDA", + "MT_INSTASHIELDB", + "MT_PLAYERARROW", + "MT_PLAYERWANTED", + + "MT_KARMAHITBOX", + "MT_KARMAWHEEL", #ifdef SEENAMES "MT_NAMECHECK", @@ -7350,8 +7452,8 @@ static const char *const PLAYERFLAG_LIST[] = { // Did you get a time-over? "TIMEOVER", - // Ready for Super? - "SUPERREADY", + // SRB2Kart: spectator that wants to join + "WANTSTOJOIN", // Character action status "JUMPED", @@ -7429,64 +7531,64 @@ static const char *COLOR_ENUMS[] = { // Rejigged for Kart. "SILVER", // 03 // SKINCOLOR_SILVER "CLOUDY", // 04 // SKINCOLOR_CLOUDY "GREY", // 05 // SKINCOLOR_GREY - "DARKGREY", // 06 // SKINCOLOR_DARKGREY + "NICKEL", // 06 // SKINCOLOR_NICKEL "BLACK", // 07 // SKINCOLOR_BLACK "SALMON", // 08 // SKINCOLOR_SALMON "PINK", // 09 // SKINCOLOR_PINK - "LIGHTRED", // 10 // SKINCOLOR_LIGHTRED - "SHINYRED", // 11 // SKINCOLOR_SHINYRED + "ROSE", // 10 // SKINCOLOR_ROSE + "RASPBERRY", // 11 // SKINCOLOR_RASPBERRY "RED", // 12 // SKINCOLOR_RED - "DARKPINK", // 13 // SKINCOLOR_DARKPINK - "DARKRED", // 14 // SKINCOLOR_DARKRED + "RUBY", // 13 // SKINCOLOR_RUBY + "CRIMSON", // 14 // SKINCOLOR_CRIMSON "DAWN", // 15 // SKINCOLOR_DAWN - "ORANGE", // 16 // SKINCOLOR_ORANGE - "SHINYORANGE", // 17 // SKINCOLOR_SHINYORANGE - "DARKORANGE", // 18 // SKINCOLOR_DARKORANGE - "GOLDENBROWN", // 19 // SKINCOLOR_GOLDENBROWN - "ROSEWOOD", // 20 // SKINCOLOR_ROSEWOOD - "DARKROSEWOOD", // 21 // SKINCOLOR_DARKROSEWOOD + "CREAMSICLE", // 16 // SKINCOLOR_CREAMSICLE + "ORANGE", // 17 // SKINCOLOR_ORANGE + "PUMPKIN", // 18 // SKINCOLOR_PUMPKIN + "ROSEWOOD", // 19 // SKINCOLOR_ROSEWOOD + "BURGUNDY", // 20 // SKINCOLOR_BURGUNDY + "BRONZE", // 21 // SKINCOLOR_BRONZE "SEPIA", // 22 // SKINCOLOR_SEPIA "BEIGE", // 23 // SKINCOLOR_BEIGE "BROWN", // 24 // SKINCOLOR_BROWN "LEATHER", // 25 // SKINCOLOR_LEATHER - "YELLOW", // 26 // SKINCOLOR_YELLOW - "PEACH", // 27 // SKINCOLOR_PEACH - "LIGHTORANGE", // 28 // SKINCOLOR_LIGHTORANGE - "CARAMEL", // 29 // SKINCOLOR_CARAMEL - "GOLD", // 30 // SKINCOLOR_GOLD - "SHINYCARAMEL", // 31 // SKINCOLOR_SHINYCARAMEL - "VOMIT", // 32 // SKINCOLOR_VOMIT - "GARDEN", // 33 // SKINCOLOR_GARDEN - "LIGHTARMY", // 34 // SKINCOLOR_LIGHTARMY - "ARMY", // 35 // SKINCOLOR_ARMY - "PISTACHIO", // 36 // SKINCOLOR_PISTACHIO - "ROBOHOOD", // 37 // SKINCOLOR_ROBOHOOD - "OLIVE", // 38 // SKINCOLOR_OLIVE - "DARKARMY", // 39 // SKINCOLOR_DARKARMY - "LIGHTGREEN", // 40 // SKINCOLOR_LIGHTGREEN - "UGLYGREEN", // 41 // SKINCOLOR_UGLYGREEN - "NEONGREEN", // 42 // SKINCOLOR_NEONGREEN - "GREEN", // 43 // SKINCOLOR_GREEN - "DARKGREEN", // 44 // SKINCOLOR_DARKGREEN + "PEACH", // 26 // SKINCOLOR_PEACH + "CARAMEL", // 27 // SKINCOLOR_CARAMEL + "TANGERINE", // 28 // SKINCOLOR_TANGERINE + "GOLD", // 29 // SKINCOLOR_GOLD + "VOMIT", // 30 // SKINCOLOR_VOMIT + "YELLOW", // 31 // SKINCOLOR_YELLOW + "CANARY", // 32 // SKINCOLOR_CANARY + "OLIVE", // 33 // SKINCOLOR_OLIVE + "GARDEN", // 34 // SKINCOLOR_GARDEN + "LIME", // 35 // SKINCOLOR_LIME + "TEA", // 36 // SKINCOLOR_TEA + "ARMY", // 37 // SKINCOLOR_ARMY + "PISTACHIO", // 38 // SKINCOLOR_PISTACHIO + "MOSS", // 39 // SKINCOLOR_MOSS + "MINT", // 40 // SKINCOLOR_MINT + "GREEN", // 41 // SKINCOLOR_GREEN + "ROBOHOOD", // 42 // SKINCOLOR_ROBOHOOD + "PINETREE", // 43 // SKINCOLOR_PINETREE + "EMERALD", // 44 // SKINCOLOR_EMERALD "SWAMP", // 45 // SKINCOLOR_SWAMP - "FROST", // 46 // SKINCOLOR_FROST - "SLATE", // 47 // SKINCOLOR_SLATE - "LIGHTBLUE", // 48 // SKINCOLOR_LIGHTBLUE - "CYAN", // 49 // SKINCOLOR_CYAN - "CERULEAN", // 50 // SKINCOLOR_CERULEAN - "TURQUOISE", // 51 // SKINCOLOR_TURQUOISE - "TEAL", // 52 // SKINCOLOR_TEAL - "STEELBLUE", // 53 // SKINCOLOR_STEELBLUE - "BLUE", // 54 // SKINCOLOR_BLUE - "SHINYBLUE", // 55 // SKINCOLOR_SHINYBLUE + "AQUA", // 46 // SKINCOLOR_AQUA + "TEAL", // 47 // SKINCOLOR_TEAL + "CYAN", // 48 // SKINCOLOR_CYAN + "CERULEAN", // 49 // SKINCOLOR_CERULEAN + "SLATE", // 50 // SKINCOLOR_SLATE + "STEEL", // 51 // SKINCOLOR_STEEL + "PERIWINKLE", // 52 // SKINCOLOR_PERIWINKLE + "BLUE", // 53 // SKINCOLOR_BLUE + "SAPPHIRE", // 54 // SKINCOLOR_SAPPHIRE + "BLUEBERRY", // 55 // SKINCOLOR_BLUEBERRY "NAVY", // 56 // SKINCOLOR_NAVY - "DARKBLUE", // 57 // SKINCOLOR_DARKBLUE - "JETBLACK", // 58 // SKINCOLOR_JETBLACK - "LILAC", // 59 // SKINCOLOR_LILAC - "PURPLE", // 60 // SKINCOLOR_PURPLE - "LAVENDER", // 61 // SKINCOLOR_LAVENDER + "JET", // 57 // SKINCOLOR_JET + "DUSK", // 58 // SKINCOLOR_DUSK + "PURPLE", // 59 // SKINCOLOR_PURPLE + "LAVENDER", // 60 // SKINCOLOR_LAVENDER + "INDIGO", // 61 // SKINCOLOR_INDIGO "BYZANTIUM", // 62 // SKINCOLOR_BYZANTIUM - "INDIGO", // 63 // SKINCOLOR_INDIGO + "LILAC", // 63 // SKINCOLOR_LILAC // Super special awesome Super flashing colors! "SUPER1", // SKINCOLOR_SUPER1 @@ -7551,17 +7653,16 @@ static const char *const KARTSTUFF_LIST[] = { "NEXTCHECK", "WAYPOINT", "STARPOSTWP", - "LAKITU", + "RESPAWN", "THROWDIR", "LAPANIMATION", "CARDANIMATION", "VOICES", "TAUNTVOICES", + "INSTASHIELD", - "BOOSTING", "FLOORBOOST", - "SPINOUT", "SPINOUTTYPE", "DRIFT", @@ -7571,53 +7672,42 @@ static const char *const KARTSTUFF_LIST[] = { "BOOSTCHARGE", "JMP", "OFFROAD", + "POGOSPRING", "BRAKESTOP", + "WATERSKIP", "ITEMROULETTE", "ROULETTETYPE", - "ITEMCLOSE", - "MAGNETTIMER", - "BOOTIMER", - "BOOTAKETIMER", - "BOOSTOLENTIMER", - "MUSHROOMTIMER", + "ITEMTYPE", + "ITEMAMOUNT", + "ITEMHELD", + + //"THUNDERANIM", + "CURSHIELD", + "HYUDOROTIMER", + "STEALINGTIMER", + "STOLENTIMER", + "SNEAKERTIMER", "GROWSHRINKTIMER", "SQUISHEDTIMER", - "GOLDSHROOMTIMER", - "STARTIMER", - "SPINOUTTIMER", - "LASERWISPTIMER", - "JUSTBUMPED", + "ROCKETSNEAKERTIMER", + "INVINCIBILITYTIMER", "DEATHSENTENCE", - "POWERITEMTIMER", + "EGGMANHELD", + "EGGMANEXPLODE", + "EGGMANBLAME", + "BANANADRAG", + "SPINOUTTIMER", + "WIPEOUTSLOW", + "JUSTBUMPED", "COMEBACKTIMER", + "SADTIMER", - "MAGNET", - "BOO", - "MUSHROOM", - "MEGASHROOM", - "GOLDSHROOM", - "STAR", - "TRIPLEBANANA", - "FAKEITEM", - "BANANA", - "GREENSHELL", - "REDSHELL", - "LASERWISP", - "TRIPLEGREENSHELL", - "BOBOMB", - "BLUESHELL", - "JAWS", - "FIREFLOWER", - "TRIPLEREDSHELL", - "LIGHTNING", - "FEATHER", - "KITCHENSINK", - - "BALLOON", + "BUMPER", "COMEBACKPOINTS", - "COMEBACKMODE" + "COMEBACKMODE", + "WANTED", }; static const char *const HUDITEMS_LIST[] = { diff --git a/src/djgppdos/i_cdmus.c b/src/djgppdos/i_cdmus.c index f707add5..2a629ca1 100644 --- a/src/djgppdos/i_cdmus.c +++ b/src/djgppdos/i_cdmus.c @@ -50,7 +50,7 @@ static boolean wasPlaying; static int cdVolume=0; // current cd volume (0-31) // 0-31 like Music & Sfx, though CD hardware volume is 0-255. -consvar_t cd_volume = {"cd_volume","31",CV_SAVE,soundvolume_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cd_volume = {"cd_volume","18",CV_SAVE,soundvolume_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; // allow Update for next/loop track // some crap cd drivers take up to diff --git a/src/doomdata.h b/src/doomdata.h index e916a151..1b91c94d 100644 --- a/src/doomdata.h +++ b/src/doomdata.h @@ -207,8 +207,8 @@ typedef struct #define ZSHIFT 4 -extern const char *Color_Names[MAXSKINCOLORS]; -extern const UINT8 Color_Opposite[MAXSKINCOLORS*2]; +//extern const char *Color_Names[MAXSKINCOLORS]; +//extern const UINT8 Color_Opposite[MAXSKINCOLORS*2]; #define NUMMAPS 1035 diff --git a/src/doomdef.h b/src/doomdef.h index 175838c0..2e4f45b2 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -161,6 +161,9 @@ extern FILE *logstream; // Comment or uncomment this as necessary. //#define USE_PATCH_DTA +// Kart has it's own, as well. +#define USE_PATCH_KART + // Modification options // If you want to take advantage of the Master Server's ability to force clients to update // to the latest version, fill these out. Otherwise, just comment out UPDATE_ALERT and leave @@ -234,64 +237,64 @@ typedef enum SKINCOLOR_SILVER, SKINCOLOR_CLOUDY, SKINCOLOR_GREY, - SKINCOLOR_DARKGREY, + SKINCOLOR_NICKEL, SKINCOLOR_BLACK, SKINCOLOR_SALMON, SKINCOLOR_PINK, - SKINCOLOR_LIGHTRED, - SKINCOLOR_SHINYRED, + SKINCOLOR_ROSE, + SKINCOLOR_RASPBERRY, SKINCOLOR_RED, - SKINCOLOR_DARKPINK, - SKINCOLOR_DARKRED, + SKINCOLOR_RUBY, + SKINCOLOR_CRIMSON, SKINCOLOR_DAWN, + SKINCOLOR_CREAMSICLE, SKINCOLOR_ORANGE, - SKINCOLOR_SHINYORANGE, - SKINCOLOR_DARKORANGE, - SKINCOLOR_GOLDENBROWN, + SKINCOLOR_PUMPKIN, SKINCOLOR_ROSEWOOD, - SKINCOLOR_DARKROSEWOOD, + SKINCOLOR_BURGUNDY, + SKINCOLOR_BRONZE, SKINCOLOR_SEPIA, SKINCOLOR_BEIGE, SKINCOLOR_BROWN, SKINCOLOR_LEATHER, - SKINCOLOR_YELLOW, SKINCOLOR_PEACH, - SKINCOLOR_LIGHTORANGE, SKINCOLOR_CARAMEL, + SKINCOLOR_TANGERINE, SKINCOLOR_GOLD, - SKINCOLOR_SHINYCARAMEL, SKINCOLOR_VOMIT, + SKINCOLOR_YELLOW, + SKINCOLOR_CANARY, + SKINCOLOR_OLIVE, SKINCOLOR_GARDEN, - SKINCOLOR_LIGHTARMY, + SKINCOLOR_LIME, + SKINCOLOR_TEA, SKINCOLOR_ARMY, SKINCOLOR_PISTACHIO, - SKINCOLOR_ROBOHOOD, - SKINCOLOR_OLIVE, - SKINCOLOR_DARKARMY, - SKINCOLOR_LIGHTGREEN, - SKINCOLOR_UGLYGREEN, - SKINCOLOR_NEONGREEN, + SKINCOLOR_MOSS, + SKINCOLOR_MINT, SKINCOLOR_GREEN, - SKINCOLOR_DARKGREEN, + SKINCOLOR_ROBOHOOD, + SKINCOLOR_PINETREE, + SKINCOLOR_EMERALD, SKINCOLOR_SWAMP, - SKINCOLOR_FROST, - SKINCOLOR_SLATE, - SKINCOLOR_LIGHTBLUE, + SKINCOLOR_AQUA, + SKINCOLOR_TEAL, SKINCOLOR_CYAN, SKINCOLOR_CERULEAN, - SKINCOLOR_TURQUOISE, - SKINCOLOR_TEAL, - SKINCOLOR_STEELBLUE, + SKINCOLOR_SLATE, + SKINCOLOR_STEEL, + SKINCOLOR_PERIWINKLE, SKINCOLOR_BLUE, - SKINCOLOR_SHINYBLUE, + SKINCOLOR_SAPPHIRE, // sweet mother, i cannot weave – slender aphrodite has overcome me with longing for a girl + SKINCOLOR_BLUEBERRY, SKINCOLOR_NAVY, - SKINCOLOR_DARKBLUE, - SKINCOLOR_JETBLACK, - SKINCOLOR_LILAC, + SKINCOLOR_JET, + SKINCOLOR_DUSK, SKINCOLOR_PURPLE, SKINCOLOR_LAVENDER, - SKINCOLOR_BYZANTIUM, SKINCOLOR_INDIGO, + SKINCOLOR_BYZANTIUM, + SKINCOLOR_LILAC, // Careful! MAXSKINCOLORS cannot be greater than 0x40 -- Which it is now. MAXSKINCOLORS, @@ -434,6 +437,7 @@ extern INT32 cv_debug; // Modifier key variables, accessible anywhere extern UINT8 shiftdown, ctrldown, altdown; +extern boolean capslock; // if we ever make our alloc stuff... #define ZZ_Alloc(x) Z_Malloc(x, PU_STATIC, NULL) @@ -540,4 +544,8 @@ extern const char *compdate, *comptime, *comprevision, *compbranch; /// \note Required for proper collision with moving sloped surfaces that have sector specials on them. #define SECTORSPECIALSAFTERTHINK +/// SRB2Kart: Camera always has noclip. +/// \note Kind of problematic. If we decide to keep this on, we'll need serious map changes. +//#define NOCLIPCAM + #endif // __DOOMDEF__ diff --git a/src/doomstat.h b/src/doomstat.h index ea5151b1..09cd7ca7 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -80,15 +80,18 @@ extern INT16 gametype; extern UINT8 splitscreen; extern boolean circuitmap; // Does this level have 'circuit mode'? extern boolean fromlevelselect; +extern boolean forceresetplayers; // ======================================== // Internal parameters for sound rendering. // ======================================== -extern boolean nomidimusic; // defined in d_main.c +//extern boolean nomidimusic; // defined in d_main.c +#define nomidimusic true extern boolean nosound; extern boolean nodigimusic; -extern boolean music_disabled; +//extern boolean music_disabled; +#define music_disabled false extern boolean sound_disabled; extern boolean digital_disabled; @@ -303,21 +306,19 @@ enum TypeOfLevel }; // Gametypes -enum GameType +enum GameType // SRB2Kart { - GT_COOP = 0, // also used in single player - GT_COMPETITION, // Classic "Race" - GT_RACE, + GT_RACE = 0, // also used in record attack + GT_MATCH, // battle, but renaming would be silly + NUMGAMETYPES, - GT_MATCH, + // the following have been left in on account of just not wanting to deal with removing all the checks for them + GT_COOP, + GT_COMPETITION, GT_TEAMMATCH, - GT_TAG, GT_HIDEANDSEEK, - - GT_CTF, // capture the flag - - NUMGAMETYPES + GT_CTF }; // If you alter this list, update gametype_cons_t in m_menu.c @@ -409,12 +410,17 @@ extern UINT16 spacetimetics; extern UINT16 extralifetics; // SRB2kart -extern INT32 bootime; -extern INT32 boostealtime; -extern INT32 mushroomtime; +extern tic_t introtime; +extern tic_t starttime; +extern INT32 hyudorotime; +extern INT32 stealtime; +extern INT32 sneakertime; extern INT32 itemtime; extern INT32 comebacktime; extern INT32 bumptime; +extern INT32 wipeoutslowtime; +extern INT32 wantedreduce; +extern INT32 wantedfrequency; extern UINT8 introtoplay; extern UINT8 creditscutscene; @@ -445,15 +451,18 @@ extern boolean franticitems; extern boolean mirrormode; extern boolean comeback; -extern tic_t lightningcooldown; -extern tic_t blueshellincoming; -extern UINT8 blueshellplayer; +extern SINT8 battlewanted[4]; +extern tic_t wantedcalcdelay; +extern tic_t indirectitemcooldown; +extern tic_t spbincoming; +extern UINT8 spbplayer; +extern tic_t mapreset; extern boolean legitimateexit; extern boolean comebackshowninfo; extern tic_t curlap, bestlap; -extern INT16 votelevels[4]; +extern INT16 votelevels[5][2]; extern SINT8 votes[MAXPLAYERS]; extern SINT8 pickedvote; diff --git a/src/f_finale.c b/src/f_finale.c index 9f5dc1dc..ab79fa78 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -528,6 +528,7 @@ static const char *credits[] = { "\"Nev3r\"", "\"Ritz\"", "\"Spherallic\"", + "\"DirkTheHusky\"", "", "\1Produced By", "Kart Krew", @@ -593,7 +594,7 @@ void F_CreditDrawer(void) UINT16 i; fixed_t y = (80< vid.height) + if (((y>>FRACBITS) * vid.dupy) > vid.height) break; } @@ -685,13 +686,20 @@ boolean F_CreditResponder(event_t *event) break; } - /*if (!(timesBeaten) && !(netgame || multiplayer)) - return false;*/ - if (event->type != ev_keydown) return false; - if (key != KEY_ESCAPE && key != KEY_ENTER && key != KEY_SPACE && key != KEY_BACKSPACE) + if (key == KEY_DOWNARROW || key == KEY_SPACE) + { + if (!timetonext && !finalecount) + animtimer += 7; + return false; + } + + /*if (!(timesBeaten) && !(netgame || multiplayer)) + return false;*/ + + if (key != KEY_ESCAPE && key != KEY_ENTER && key != KEY_BACKSPACE) return false; if (keypressed) @@ -906,36 +914,52 @@ void F_TitleScreenDrawer(void) if (modeattacking) return; // We likely came here from retrying. Don't do a damn thing. - if (finalecount < 50) - V_DrawFill(0, 0, 320, 200, 31); - else - // Draw that sky! - F_SkyScroll(titlescrollspeed); - - // Don't draw outside of the title screewn, or if the patch isn't there. + // Don't draw outside of the title screen, or if the patch isn't there. if (!ttbanner || (gamestate != GS_TITLESCREEN && gamestate != GS_WAITINGPLAYERS)) - return; - - V_DrawSmallScaledPatch(84, 36, 0, ttbanner); - - if (finalecount < 20) { - if (finalecount >= 10) + F_SkyScroll(titlescrollspeed); + return; + } + + if (finalecount < 50) + { + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); + + V_DrawSmallScaledPatch(84, 36, 0, ttbanner); + + if (finalecount >= 20) + V_DrawSmallScaledPatch(84, 87, 0, ttkart); + else if (finalecount >= 10) V_DrawSciencePatch((84<>1; + + F_SkyScroll(titlescrollspeed); - // Checkers, only need to be drawn after the whiteout, but we can do it here because it won't be seen before anyway V_DrawSciencePatch(0, 0 - FixedMul(40<= 50 && finalecount < 55) - { - V_DrawFill(0, 0, 320, 200, 120); - V_DrawSmallScaledPatch(84, 36, 0, ttkflash); + if (transval) + V_DrawFadeScreen(120, 10 - transval); + + V_DrawSmallScaledPatch(84, 36, 0, ttbanner); + + V_DrawSmallScaledPatch(84, 87, 0, ttkart); + + if (!transval) + return; + + V_DrawSmallScaledPatch(84, 36, transval<>1))<>1))<width / 2, 150<scene[scenenum].fadecolor) { - V_DrawFill(0,0,BASEVIDWIDTH,BASEVIDHEIGHT,cutscenes[cutnum]->scene[scenenum].fadecolor); + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, cutscenes[cutnum]->scene[scenenum].fadecolor); F_WipeEndScreen(); F_RunWipe(cutscenes[cutnum]->scene[scenenum].fadeinid, true); @@ -1306,7 +1330,7 @@ void F_CutsceneDrawer(void) F_WipeStartScreen(); } } - V_DrawFill(0,0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); if (cutscenes[cutnum]->scene[scenenum].picname[picnum][0] != '\0') { diff --git a/src/f_finale.h b/src/f_finale.h index 933ef379..1eb9fb33 100644 --- a/src/f_finale.h +++ b/src/f_finale.h @@ -82,6 +82,7 @@ enum wipe_level_toblack, wipe_intermission_toblack, + wipe_voting_toblack, wipe_continuing_toblack, wipe_titlescreen_toblack, wipe_timeattack_toblack, @@ -98,6 +99,7 @@ enum wipe_level_final, wipe_intermission_final, + wipe_voting_final, wipe_continuing_final, wipe_titlescreen_final, wipe_timeattack_final, @@ -111,9 +113,10 @@ enum wipe_specinter_final, wipe_multinter_final, - NUMWIPEDEFS + NUMWIPEDEFS, + WIPEFINALSHIFT = wipe_level_final - wipe_level_toblack }; -#define WIPEFINALSHIFT 13 + extern UINT8 wipedefs[NUMWIPEDEFS]; #endif diff --git a/src/f_wipe.c b/src/f_wipe.c index ed5736cb..ad0a2740 100644 --- a/src/f_wipe.c +++ b/src/f_wipe.c @@ -46,8 +46,9 @@ UINT8 wipedefs[NUMWIPEDEFS] = { 99, // wipe_credits_intermediate (0) 0, // wipe_level_toblack - UINT8_MAX, // wipe_intermission_toblack - UINT8_MAX, // wipe_continuing_toblack + UINT8_MAX, // wipe_intermission_toblack + 0, // wipe_voting_toblack, + UINT8_MAX, // wipe_continuing_toblack 3, // wipe_titlescreen_toblack 0, // wipe_timeattack_toblack 99, // wipe_credits_toblack @@ -56,12 +57,13 @@ UINT8 wipedefs[NUMWIPEDEFS] = { UINT8_MAX, // wipe_intro_toblack (hardcoded) UINT8_MAX, // wipe_cutscene_toblack (hardcoded) - 0, // wipe_specinter_toblack - 0, // wipe_multinter_toblack - 0, // wipe_speclevel_towhite + UINT8_MAX, // wipe_specinter_toblack + UINT8_MAX, // wipe_multinter_toblack + 99, // wipe_speclevel_towhite - 0, // wipe_level_final + 3, // wipe_level_final 0, // wipe_intermission_final + 0, // wipe_voting_final 0, // wipe_continuing_final 3, // wipe_titlescreen_final 0, // wipe_timeattack_final diff --git a/src/g_game.c b/src/g_game.c index 9386681a..db686873 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -95,7 +95,7 @@ boolean imcontinuing = false; boolean runemeraldmanager = false; // menu demo things -UINT8 numDemos = 3; +UINT8 numDemos = 0; //3; -- i'm FED UP of losing my skincolour to a broken demo. change this back when we make new ones UINT32 demoDelayTime = 15*TICRATE; UINT32 demoIdleTime = 3*TICRATE; @@ -132,7 +132,7 @@ boolean useNightsSS = false; UINT8 skincolor_redteam = SKINCOLOR_RED; UINT8 skincolor_blueteam = SKINCOLOR_BLUE; UINT8 skincolor_redring = SKINCOLOR_RED; -UINT8 skincolor_bluering = SKINCOLOR_STEELBLUE; +UINT8 skincolor_bluering = SKINCOLOR_STEEL; tic_t countdowntimer = 0; boolean countdowntimeup = false; @@ -207,12 +207,17 @@ UINT16 spacetimetics = 11*TICRATE + (TICRATE/2); UINT16 extralifetics = 4*TICRATE; // SRB2kart -INT32 bootime = 7*TICRATE; -INT32 boostealtime = TICRATE/2; -INT32 mushroomtime = TICRATE + (TICRATE/3); +tic_t introtime = 108+5; // plus 5 for white fade +tic_t starttime = 6*TICRATE + (3*TICRATE/4); +INT32 hyudorotime = 7*TICRATE; +INT32 stealtime = TICRATE/2; +INT32 sneakertime = TICRATE + (TICRATE/3); INT32 itemtime = 8*TICRATE; INT32 comebacktime = 10*TICRATE; INT32 bumptime = 6; +INT32 wipeoutslowtime = 20; +INT32 wantedreduce = 5*TICRATE; +INT32 wantedfrequency = 10*TICRATE; INT32 gameovertics = 15*TICRATE; @@ -248,21 +253,24 @@ boolean franticitems; // Frantic items currently enabled? boolean comeback; // Battle Mode's karma comeback is on/off // Voting system -INT16 votelevels[4]; // Levels that were rolled by the host +INT16 votelevels[5][2]; // Levels that were rolled by the host SINT8 votes[MAXPLAYERS]; // Each player's vote SINT8 pickedvote; // What vote the host rolls -// Server-sided variables -tic_t lightningcooldown; // Cooldown before any more lightning/blue shell is awarded -tic_t blueshellincoming; // Timer before blue shell hits, can switch targets at this point -UINT8 blueshellplayer; // Player num that used the last blue shell +// Server-sided, synched variables +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 spbincoming; // Timer before SPB hits, can switch targets at this point +UINT8 spbplayer; // Player num that used the last SPB +tic_t mapreset; // Map reset delay when enough players have joined an empty game -// Client-sided variables (NEVER use in anything that needs to be synced with other players) +// Client-sided, unsynched variables (NEVER use in anything that needs to be synced with other players) boolean legitimateexit; // Did this client actually finish the match? boolean comebackshowninfo; // Have you already seen the "ATTACK OR PROTECT" message? tic_t curlap; // Current lap time tic_t bestlap; // Best lap time -static INT16 randmapbuffer[NUMMAPS]; // Buffer for maps RandMap is allowed to roll +static INT16 randmapbuffer[NUMMAPS+1]; // Buffer for maps RandMap is allowed to roll tic_t hidetime; @@ -307,13 +315,6 @@ static struct { // Your naming conventions are stupid and useless. // There is no conflict here. -typedef struct demoghost { - UINT8 checksum[16]; - UINT8 *buffer, *p, color; - UINT16 version; - mobj_t oldmo, *mo; - struct demoghost *next; -} demoghost; demoghost *ghosts = NULL; boolean precache = true; // if true, load all graphics at start @@ -397,6 +398,33 @@ static CV_PossibleValue_t joyaxis_cons_t[] = {{0, "None"}, #endif #endif +// don't mind me putting these here, I was lazy to figure out where else I could put those without blowing up the compiler. + +// chat timer thingy +static CV_PossibleValue_t chattime_cons_t[] = {{5, "MIN"}, {999, "MAX"}, {0, NULL}}; +consvar_t cv_chattime = {"chattime", "8", CV_SAVE, chattime_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; + +// chatwidth +static CV_PossibleValue_t chatwidth_cons_t[] = {{64, "MIN"}, {150, "MAX"}, {0, NULL}}; +consvar_t cv_chatwidth = {"chatwidth", "150", CV_SAVE, chatwidth_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; + +// chatheight +static CV_PossibleValue_t chatheight_cons_t[] = {{6, "MIN"}, {22, "MAX"}, {0, NULL}}; +consvar_t cv_chatheight = {"chatheight", "8", CV_SAVE, chatheight_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; + +// chat notifications (do you want to hear beeps? I'd understand if you didn't.) +consvar_t cv_chatnotifications = {"chatnotifications", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; + +// chat spam protection (why would you want to disable that???) +consvar_t cv_chatspamprotection = {"chatspamprotection", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; + +// minichat text background +consvar_t cv_chatbacktint = {"chatbacktint", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; + +// old shit console chat. (mostly exists for stuff like terminal, not because I cared if anyone liked the old chat.) +static CV_PossibleValue_t consolechat_cons_t[] = {{0, "Window"}, {1, "Console"}, {0, NULL}}; +consvar_t cv_consolechat = {"chatmode", "Window", CV_SAVE, consolechat_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; + consvar_t cv_crosshair = {"crosshair", "Cross", CV_SAVE, crosshair_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_crosshair2 = {"crosshair2", "Cross", CV_SAVE, crosshair_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_crosshair3 = {"crosshair3", "Cross", CV_SAVE, crosshair_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -1163,7 +1191,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) INT32 laim, th, tspeed, forward, side, axis; //i const INT32 speed = 1; // these ones used for multiple conditions - boolean turnleft, turnright, invertmouse, mouseaiming, lookaxis, analogjoystickmove, gamepadjoystickmove, kbl, rd; + boolean turnleft, turnright, invertmouse, mouseaiming, lookaxis, usejoystick, analogjoystickmove, gamepadjoystickmove, kbl, rd; player_t *player; camera_t *thiscam; angle_t lang; @@ -1260,6 +1288,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) break; } + usejoystick = (analogjoystickmove || gamepadjoystickmove); turnright = InputDown(gc_turnright, ssplayer); turnleft = InputDown(gc_turnleft, ssplayer); @@ -1320,8 +1349,8 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) cmd->driftturn = (INT16)(cmd->driftturn - (mousex*(mirrormode ? -1 : 1)*8)); } - // Bounce pad strafing - if (!demoplayback && ((player->pflags & PF_FORCESTRAFE) || (player->kartstuff[k_feather] & 2))) + // Speed bump strafing + if (!demoplayback && ((player->pflags & PF_FORCESTRAFE) || (player->kartstuff[k_pogospring]))) { if (turnright) side += sidemove[1]; @@ -1334,42 +1363,23 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) } } - //{ SRB2kart - Drift support - // limit turning to angleturn[1] to stop mouselook letting you look too fast - if (cmd->angleturn > angleturn[1]) - cmd->angleturn = angleturn[1]; - else if (cmd->angleturn < -angleturn[1]) - cmd->angleturn = -angleturn[1]; - - if (cmd->driftturn > angleturn[1]) - cmd->driftturn = angleturn[1]; - else if (cmd->driftturn < -angleturn[1]) - cmd->driftturn = -angleturn[1]; - - if (player->mo) - cmd->angleturn = K_GetKartTurnValue(player, cmd->angleturn); - - // SRB2kart - no additional angle if not moving - if ((player->mo && player->speed > 0) || (leveltime > 140 && cmd->buttons & BT_ACCELERATE && cmd->buttons & BT_BRAKE) || (player->spectator || objectplacing)) - lang += (cmd->angleturn<<16); - if (player->spectator || objectplacing) // SRB2Kart: spectators need special controls { - if (InputDown(gc_accelerate, ssplayer) || (cv_usejoystick.value && axis > 0)) + if (InputDown(gc_accelerate, ssplayer) || (usejoystick && axis > 0)) cmd->buttons |= BT_ACCELERATE; - if (InputDown(gc_brake, ssplayer) || (cv_usejoystick.value && axis > 0)) + if (InputDown(gc_brake, ssplayer) || (usejoystick && axis > 0)) cmd->buttons |= BT_BRAKE; axis = JoyAxis(AXISAIM, ssplayer); - if (InputDown(gc_aimforward, ssplayer) || (gamepadjoystickmove && axis < 0) || (analogjoystickmove && axis < 0)) + if (InputDown(gc_aimforward, ssplayer) || (usejoystick && axis < 0)) forward += forwardmove[1]; - if (InputDown(gc_aimbackward, ssplayer) || (gamepadjoystickmove && axis > 0) || (analogjoystickmove && axis > 0)) + if (InputDown(gc_aimbackward, ssplayer) || (usejoystick && axis > 0)) forward -= forwardmove[1]; } else { // forward with key or button // SRB2kart - we use an accel/brake instead of forward/backward. axis = JoyAxis(AXISMOVE, ssplayer); - if (InputDown(gc_accelerate, ssplayer) || (gamepadjoystickmove && axis > 0) || player->kartstuff[k_mushroomtimer]) + if (InputDown(gc_accelerate, ssplayer) || (gamepadjoystickmove && axis > 0) || player->kartstuff[k_sneakertimer]) { cmd->buttons |= BT_ACCELERATE; forward = forwardmove[1]; // 50 @@ -1398,20 +1408,20 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) // But forward/backward IS used for aiming. axis = JoyAxis(AXISAIM, ssplayer); - if (InputDown(gc_aimforward, ssplayer) || (cv_usejoystick.value && axis < 0)) + if (InputDown(gc_aimforward, ssplayer) || (usejoystick && axis < 0)) cmd->buttons |= BT_FORWARD; - if (InputDown(gc_aimbackward, ssplayer) || (cv_usejoystick.value && axis > 0)) + if (InputDown(gc_aimbackward, ssplayer) || (usejoystick && axis > 0)) cmd->buttons |= BT_BACKWARD; } // fire with any button/key axis = JoyAxis(AXISFIRE, ssplayer); - if (InputDown(gc_fire, ssplayer) || (cv_usejoystick.value && axis > 0)) + if (InputDown(gc_fire, ssplayer) || (usejoystick && axis > 0)) cmd->buttons |= BT_ATTACK; // drift with any button/key axis = JoyAxis(AXISDRIFT, ssplayer); - if (InputDown(gc_drift, ssplayer) || (cv_usejoystick.value && axis > 0)) + if (InputDown(gc_drift, ssplayer) || (usejoystick && axis > 0)) cmd->buttons |= BT_DRIFT; // Lua scriptable buttons @@ -1508,6 +1518,29 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) cmd->sidemove = (SINT8)(cmd->sidemove + side); } + //{ SRB2kart - Drift support + // Not grouped with the rest of turn stuff because it needs to know what buttons you're pressing for rubber-burn turn + // limit turning to angleturn[1] to stop mouselook letting you look too fast + if (cmd->angleturn > angleturn[1]) + cmd->angleturn = angleturn[1]; + else if (cmd->angleturn < -angleturn[1]) + cmd->angleturn = -angleturn[1]; + + if (cmd->driftturn > angleturn[1]) + cmd->driftturn = angleturn[1]; + else if (cmd->driftturn < -angleturn[1]) + cmd->driftturn = -angleturn[1]; + + if (player->mo) + cmd->angleturn = K_GetKartTurnValue(player, cmd->angleturn); + + // SRB2kart - no additional angle if not moving + if (((player->mo && player->speed > 0) // Moving + || (leveltime > starttime && (cmd->buttons & BT_ACCELERATE && cmd->buttons & BT_BRAKE)) // Rubber-burn turn + || (player->spectator || objectplacing)) // Not a physical player + && !(player->kartstuff[k_spinouttimer] && player->kartstuff[k_sneakertimer])) // Spinning and boosting cancels out spinout + lang += (cmd->angleturn<<16); + cmd->angleturn = (INT16)(lang >> 16); if (!hu_stopped) @@ -1811,7 +1844,7 @@ boolean G_Responder(event_t *ev) // SRB2Kart: Ehhh, who cares, Mario Kart's designed around screen-cheating anyway /*if (gametype != GT_RACE) { - if (players[consoleplayer].kartstuff[k_balloon] > 0) + if (players[consoleplayer].kartstuff[k_bumper] > 0) continue; }*/ @@ -1902,7 +1935,7 @@ boolean G_Responder(event_t *ev) else if (gamestate == GS_GAMEEND || gamestate == GS_EVALUATION || gamestate == GS_CREDITS) return true; - else if (gamestate == GS_INTERMISSION || gamestate == GS_VOTING) + else if (gamestate == GS_INTERMISSION || gamestate == GS_VOTING || gamestate == GS_WAITINGPLAYERS) if (HU_Responder(ev)) return true; // chat ate the event @@ -2158,7 +2191,9 @@ void G_Ticker(boolean run) F_TitleScreenTicker(run); break; case GS_WAITINGPLAYERS: - F_WaitingPlayersTicker(); + if (netgame) + F_WaitingPlayersTicker(); + HU_Ticker(); break; case GS_DEDICATEDSERVER: @@ -2168,6 +2203,11 @@ void G_Ticker(boolean run) if (run) { + if (G_GametypeHasSpectators() + && (gamestate == GS_LEVEL || gamestate == GS_INTERMISSION || gamestate == GS_VOTING // definitely good + || gamestate == GS_WAITINGPLAYERS)) // definitely a problem if we don't do it at all in this gamestate, but might need more protection? + K_CheckSpectateStatus(); + if (pausedelay) pausedelay--; @@ -2220,19 +2260,33 @@ static inline void G_PlayerFinishLevel(INT32 player) p->starpostnum = 0; p->starpostcount = 0; - if (rendermode == render_soft) - V_SetPaletteLump(GetPalette()); // Reset the palette - // SRB2kart: Increment the "matches played" counter. if (player == consoleplayer) { - if (legitimateexit && !demoplayback) // (yes you're allowed to unlock stuff this way when the game is modified) + if (legitimateexit && !demoplayback && !mapreset) // (yes you're allowed to unlock stuff this way when the game is modified) { - matchesplayed++; - if (M_UpdateUnlockablesAndExtraEmblems(true)) + UINT8 i = 0; + + if (netgame) { - S_StartSound(NULL, sfx_ncitem); - G_SaveGameData(true); // only save if unlocked something + // check to see if there's anyone else at all + for (; i < MAXPLAYERS; i++) + { + if (i == consoleplayer) + continue; + if (playeringame[i] && !stplyr->spectator) + break; + } + } + + if (i != MAXPLAYERS) // Not FREE PLAY + { + matchesplayed++; + if (M_UpdateUnlockablesAndExtraEmblems(true)) + { + S_StartSound(NULL, sfx_ncitem); + G_SaveGameData(true); // only save if unlocked something + } } } @@ -2247,7 +2301,7 @@ static inline void G_PlayerFinishLevel(INT32 player) void G_PlayerReborn(INT32 player) { player_t *p; - INT32 score; + INT32 score, marescore; INT32 lives; INT32 continues; UINT8 charability; @@ -2292,11 +2346,12 @@ void G_PlayerReborn(INT32 player) // SRB2kart INT32 starpostwp; - INT32 offroad; - INT32 balloon; + INT32 bumper; INT32 comebackpoints; + INT32 wanted; score = players[player].score; + marescore = players[player].marescore; lives = players[player].lives; continues = players[player].continues; ctfteam = players[player].ctfteam; @@ -2349,14 +2404,15 @@ void G_PlayerReborn(INT32 player) // SRB2kart starpostwp = players[player].kartstuff[k_starpostwp]; - offroad = players[player].kartstuff[k_offroad]; - balloon = players[player].kartstuff[k_balloon]; + bumper = players[player].kartstuff[k_bumper]; comebackpoints = players[player].kartstuff[k_comebackpoints]; + wanted = players[player].kartstuff[k_wanted]; p = &players[player]; memset(p, 0, sizeof (*p)); p->score = score; + p->marescore = marescore; p->lives = lives; p->continues = continues; p->pflags = pflags; @@ -2407,11 +2463,10 @@ void G_PlayerReborn(INT32 player) // SRB2kart p->kartstuff[k_starpostwp] = starpostwp; // TODO: get these out of kartstuff, it causes desync - p->kartstuff[k_offroad] = offroad; - - p->kartstuff[k_balloon] = balloon; + p->kartstuff[k_bumper] = bumper; p->kartstuff[k_comebackpoints] = comebackpoints; p->kartstuff[k_comebacktimer] = comebacktime; + p->kartstuff[k_wanted] = wanted; // Don't do anything immediately p->pflags |= PF_USEDOWN; @@ -2423,7 +2478,7 @@ void G_PlayerReborn(INT32 player) p->panim = PA_IDLE; // standing animation if ((netgame || multiplayer) && !p->spectator) - p->powers[pw_flashing] = K_GetKartFlashing()-1; // Babysitting deterrent + p->powers[pw_flashing] = K_GetKartFlashing(p)-1; // Babysitting deterrent if (p-players == consoleplayer) { @@ -2437,14 +2492,14 @@ void G_PlayerReborn(INT32 player) P_RestoreMusic(p); - if (leveltime > 157 && !p->spectator) - p->kartstuff[k_lakitu] = 48; // Lakitu Spawner + if (leveltime > (starttime + (TICRATE/2)) && !p->spectator) + p->kartstuff[k_respawn] = 48; // Respawn effect if (gametype == GT_COOP) P_FindEmerald(); // scan for emeralds to hunt for // Reset Nights score and max link to 0 on death - p->marescore = p->maxlink = 0; + p->maxlink = 0; // If NiGHTS, find lowest mare to start with. p->mare = P_FindLowestMare(); @@ -2956,7 +3011,7 @@ void G_ExitLevel(void) CV_SetValue(&cv_teamscramble, cv_scrambleonchange.value); } - if (gametype != GT_COOP) + if (netgame || multiplayer) CONS_Printf(M_GetText("The round has ended.\n")); // Remove CEcho text on round end. @@ -3025,7 +3080,7 @@ boolean G_GametypeHasSpectators(void) #if 0 return (gametype != GT_COOP && gametype != GT_COMPETITION && gametype != GT_RACE); #else - return true; + return (!splitscreen);//true; #endif } @@ -3039,6 +3094,42 @@ boolean G_BattleGametype(void) return (gametype == GT_MATCH); } +// +// G_SometimesGetDifferentGametype +// +// I pity the fool who adds more gametypes later, because it'll require some element of randomisation which needs to be synched... +// Although given this only gets called for the host, you could probably get away with M_Random. +// +INT16 G_SometimesGetDifferentGametype(void) +{ + if (randmapbuffer[NUMMAPS] != -1) + return gametype; + + randmapbuffer[NUMMAPS] = gametype; + + if (gametype == GT_MATCH) + return GT_RACE; + return GT_MATCH; +} + +// +// G_GetGametypeColor +// +// Pretty and consistent ^u^ +// See also M_GetGametypeColor. +// +UINT8 G_GetGametypeColor(INT16 gt) +{ + if (modeattacking // == ATTACKING_RECORD + || gamestate == GS_TIMEATTACK) + return orangemap[120]; + if (gt == GT_MATCH) + return redmap[120]; + if (gt == GT_RACE) + return skymap[120]; + return 247; // FALLBACK +} + // // G_RaceGametype // @@ -3108,12 +3199,15 @@ static INT32 TOLMaps(INT16 tolflags) * has those flags. * \author Graue */ -INT16 G_RandMap(INT16 tolflags, INT16 pprevmap, boolean dontadd, boolean ignorebuffer) +static INT16 *okmaps = NULL; +INT16 G_RandMap(INT16 tolflags, INT16 pprevmap, boolean dontadd, boolean ignorebuffer, UINT8 maphell, boolean callagainsoon) { - INT16 *okmaps = Z_Malloc(NUMMAPS * sizeof(INT16), PU_STATIC, NULL); INT32 numokmaps = 0; INT16 ix, bufx; + if (!okmaps) + okmaps = Z_Malloc(NUMMAPS * sizeof(INT16), PU_STATIC, NULL); + // Find all the maps that are ok and and put them in an array. for (ix = 0; ix < NUMMAPS; ix++) { @@ -3124,12 +3218,14 @@ INT16 G_RandMap(INT16 tolflags, INT16 pprevmap, boolean dontadd, boolean ignoreb if ((mapheaderinfo[ix]->typeoflevel & tolflags) != tolflags || ix == pprevmap - || (M_MapLocked(ix+1) && !dedicated)) + || (!dedicated && M_MapLocked(ix+1)) + || (!maphell && (mapheaderinfo[ix]->menuflags & LF2_HIDEINMENU)) // this is bad + || ((maphell == 2) && !(mapheaderinfo[ix]->menuflags & LF2_HIDEINMENU))) // gasp isokmap = false; if (!ignorebuffer) { - for (bufx = 0; bufx < NUMMAPS; bufx++) + for (bufx = 0; bufx < (maphell ? 3 : NUMMAPS); bufx++) { if (randmapbuffer[bufx] == -1) // Rest of buffer SHOULD be empty break; @@ -3148,10 +3244,12 @@ INT16 G_RandMap(INT16 tolflags, INT16 pprevmap, boolean dontadd, boolean ignoreb if (numokmaps == 0) { if (!ignorebuffer) - return G_RandMap(tolflags, pprevmap, dontadd, true); // If there's no matches, (An incredibly silly function chain, buuut... :V) + return G_RandMap(tolflags, pprevmap, dontadd, true, maphell, callagainsoon); // If there's no matches, (An incredibly silly function chain, buuut... :V) + if (maphell) + return G_RandMap(tolflags, pprevmap, dontadd, true, maphell-1, callagainsoon); ix = 0; // Sorry, none match. You get MAP01. - for (bufx = 0; bufx < NUMMAPS; bufx++) + for (bufx = 0; bufx < NUMMAPS+1; bufx++) randmapbuffer[bufx] = -1; // if we're having trouble finding a map we should probably clear it } else @@ -3159,13 +3257,17 @@ INT16 G_RandMap(INT16 tolflags, INT16 pprevmap, boolean dontadd, boolean ignoreb ix = okmaps[M_RandomKey(numokmaps)]; if (!dontadd) { - for (bufx = NUMMAPS; bufx > 0; bufx--) + for (bufx = NUMMAPS-1; bufx > 0; bufx--) randmapbuffer[bufx] = randmapbuffer[bufx-1]; randmapbuffer[0] = ix; } } - Z_Free(okmaps); + if (!callagainsoon) + { + Z_Free(okmaps); + okmaps = NULL; + } return ix; } @@ -3175,7 +3277,7 @@ INT16 G_RandMap(INT16 tolflags, INT16 pprevmap, boolean dontadd, boolean ignoreb // static void G_DoCompleted(void) { - INT32 i; + INT32 i, j = 0; boolean gottoken = false; tokenlist = 0; // Reset the list @@ -3189,7 +3291,20 @@ static void G_DoCompleted(void) for (i = 0; i < MAXPLAYERS; i++) if (playeringame[i]) + { + // SRB2Kart: exitlevel shouldn't get you the points + if (!players[i].exiting && !(players[i].pflags & PF_TIMEOVER)) + { + players[i].pflags |= PF_TIMEOVER; + if (P_IsLocalPlayer(&players[i])) + j++; + } G_PlayerFinishLevel(i); // take away cards and stuff + } + + // play some generic music if there's no win/cool/lose music going on (for exitlevel commands) + if (G_RaceGametype() && j == splitscreen+1 && (cv_inttime.value > 0)) + S_ChangeMusicInternal("racent", true); if (automapactive) AM_Stop(); @@ -3230,6 +3345,9 @@ static void G_DoCompleted(void) else cm = (INT16)(mapheaderinfo[cm]->nextlevel-1); + if (cm == 1100-1) // !!! WHENEVER WE GET GRAND PRIX, GO TO AWARDS MAP INSTEAD !!! + cm = cm+1; + if (cm >= NUMMAPS || cm < 0) // out of range (either 1100-1102 or error) { cm = nextmap; //Start the loop again so that the error checking below is executed. @@ -3292,7 +3410,7 @@ static void G_DoCompleted(void) if (randmapbuffer[TOLMaps(G_TOLFlag(gametype))-4] != -1) // we're getting pretty full, so lets clear it { - for (i = 0; i < NUMMAPS; i++) + for (i = 0; i < NUMMAPS+1; i++) randmapbuffer[i] = -1; } @@ -3301,7 +3419,7 @@ static void G_DoCompleted(void) if (cv_advancemap.value == 0) // Stay on same map. nextmap = prevmap; else if (cv_advancemap.value == 2) // Go to random map. - nextmap = G_RandMap(G_TOLFlag(gametype), prevmap, false, false); + nextmap = G_RandMap(G_TOLFlag(gametype), prevmap, false, false, 0, false); } // We are committed to this map now. @@ -3343,19 +3461,39 @@ void G_AfterIntermission(void) // void G_NextLevel(void) { - if ((cv_advancemap.value == 3 && gamestate != GS_VOTING) - && !modeattacking && !skipstats && (multiplayer || netgame)) - gameaction = ga_startvote; - else - gameaction = ga_worlddone; + if (gamestate != GS_VOTING) + { + if ((cv_advancemap.value == 3) && !modeattacking && !skipstats && (multiplayer || netgame)) + { + UINT8 i; + for (i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i] && !players[i].spectator) + { + gameaction = ga_startvote; + return; + } + } + } + + forceresetplayers = false; + } + + gameaction = ga_worlddone; } static void G_DoWorldDone(void) { if (server) { - // SRB2kart: don't reset player between maps - D_MapChange(nextmap+1, gametype, ultimatemode, false, 0, false, false); + // SRB2Kart + D_MapChange(nextmap+1, + gametype, + ultimatemode, + forceresetplayers, + 0, + false, + false); } gameaction = ga_nothing; @@ -3387,6 +3525,7 @@ static void G_DoStartContinue(void) { I_Assert(!netgame && !multiplayer); + legitimateexit = false; G_PlayerFinishLevel(consoleplayer); // take away cards and stuff F_StartContinue(); @@ -3944,9 +4083,16 @@ void G_DeferedInitNew(boolean pultmode, const char *mapname, INT32 pickedchar, U if (demoplayback) COM_BufAddText("stopdemo\n"); + + while (ghosts) + { + demoghost *next = ghosts->next; + Z_Free(ghosts); + ghosts = next; + } ghosts = NULL; - for (i = 0; i < NUMMAPS; i++) + for (i = 0; i < NUMMAPS+1; i++) randmapbuffer[i] = -1; // this leave the actual game if needed @@ -4000,11 +4146,12 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean if (!demoplayback && !netgame) // Netgame sets random seed elsewhere, demo playback sets seed just before us! P_SetRandSeed(M_RandomizedSeed()); // Use a more "Random" random seed - if (resetplayer) + //SRB2Kart - Score is literally the only thing you SHOULDN'T reset at all times + //if (resetplayer) { // Clear a bunch of variables tokenlist = token = sstimer = redscore = bluescore = lastmap = 0; - countdown = countdown2 = 0; + countdown = countdown2 = mapreset = 0; for (i = 0; i < MAXPLAYERS; i++) { @@ -4013,6 +4160,7 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean players[i].starpostx = players[i].starposty = players[i].starpostz = 0; players[i].starpostcount = 0; // srb2kart +#if 0 if (netgame || multiplayer) { players[i].lives = cv_startinglives.value; @@ -4029,13 +4177,23 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean players[i].continues = 1; } + players[i].xtralife = 0; +#else + players[i].lives = 1; // SRB2Kart +#endif + // The latter two should clear by themselves, but just in case players[i].pflags &= ~(PF_TAGIT|PF_TAGGED|PF_FULLSTASIS); // Clear cheatcodes too, just in case. players[i].pflags &= ~(PF_GODMODE|PF_NOCLIP|PF_INVIS); - players[i].score = players[i].xtralife = 0; + players[i].marescore = 0; + + if (resetplayer) // SRB2Kart + { + players[i].score = 0; + } } // Reset unlockable triggers @@ -4837,6 +4995,7 @@ void G_GhostTicker(void) p->next = g->next; else ghosts = g->next; + Z_Free(g); continue; } p = g; @@ -5569,8 +5728,7 @@ void G_DoPlayDemo(char *defdemoname) memset(playeringame,0,sizeof(playeringame)); playeringame[0] = true; P_SetRandSeed(randseed); - //G_InitNew(false, G_BuildMapName(gamemap), false, true); // resetplayer needs to be false to retain score - G_InitNew(false, G_BuildMapName(gamemap), true, true); // ...but uh, for demos? doing that makes them start in different positions depending on the last demo you watched + G_InitNew(false, G_BuildMapName(gamemap), true, true); // Doesn't matter whether you reset or not here, given changes to resetplayer. // Set skin SetPlayerSkin(0, skin); @@ -5780,29 +5938,28 @@ void G_AddGhost(char *defdemoname) mthing = playerstarts[0]; I_Assert(mthing); { // A bit more complex than P_SpawnPlayer because ghosts aren't solid and won't just push themselves out of the ceiling. - fixed_t x,y,z; - sector_t *sector; - x = mthing->x << FRACBITS; - y = mthing->y << FRACBITS; - sector = R_PointInSubsector(x, y)->sector; + fixed_t z,f,c; + gh->mo = P_SpawnMobj(mthing->x << FRACBITS, mthing->y << FRACBITS, 0, MT_GHOST); + gh->mo->angle = FixedAngle(mthing->angle*FRACUNIT); + f = gh->mo->floorz; + c = gh->mo->ceilingz - mobjinfo[MT_PLAYER].height; if (!!(mthing->options & MTF_AMBUSH) ^ !!(mthing->options & MTF_OBJECTFLIP)) { - z = sector->ceilingheight - mobjinfo[MT_PLAYER].height; + z = c; if (mthing->options >> ZSHIFT) z -= ((mthing->options >> ZSHIFT) << FRACBITS); - if (z < sector->floorheight) - z = sector->floorheight; + if (z < f) + z = f; } else { - z = sector->floorheight; + z = f; if (mthing->options >> ZSHIFT) z += ((mthing->options >> ZSHIFT) << FRACBITS); - if (z > sector->ceilingheight - mobjinfo[MT_PLAYER].height) - z = sector->ceilingheight - mobjinfo[MT_PLAYER].height; + if (z > c) + z = c; } - gh->mo = P_SpawnMobj(x, y, z, MT_GHOST); - gh->mo->angle = FixedAngle(mthing->angle*FRACUNIT); + gh->mo->z = z; } gh->mo->state = states+S_KART_STND1; // SRB2kart - was S_PLAY_STND gh->mo->sprite = gh->mo->state->sprite; @@ -6000,8 +6157,13 @@ boolean G_CheckDemoStatus(void) { boolean saved; - if(ghosts) // ... ... ... - ghosts = NULL; // :) + while (ghosts) + { + demoghost *next = ghosts->next; + Z_Free(ghosts); + ghosts = next; + } + ghosts = NULL; // DO NOT end metal sonic demos here diff --git a/src/g_game.h b/src/g_game.h index f59641fb..ad099bf2 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -54,6 +54,7 @@ extern tic_t timeinmap; // Ticker for time spent in level (used for levelcard di extern INT16 rw_maximums[NUM_WEAPONS]; // used in game menu +extern consvar_t cv_chatwidth, cv_chatnotifications, cv_chatheight, cv_chattime, cv_consolechat, cv_chatspamprotection, cv_chatbacktint; extern consvar_t cv_crosshair, cv_crosshair2, cv_crosshair3, cv_crosshair4; extern consvar_t cv_invertmouse, cv_alwaysfreelook, cv_mousemove; extern consvar_t cv_turnaxis,cv_moveaxis,cv_brakeaxis,cv_aimaxis,cv_lookaxis,cv_fireaxis,cv_driftaxis; @@ -167,6 +168,17 @@ void G_WriteMetalTic(mobj_t *metal); void G_SaveMetal(UINT8 **buffer); void G_LoadMetal(UINT8 **buffer); +// Your naming conventions are stupid and useless. +// There is no conflict here. +typedef struct demoghost { + UINT8 checksum[16]; + UINT8 *buffer, *p, color; + UINT16 version; + mobj_t oldmo, *mo; + struct demoghost *next; +} demoghost; +extern demoghost *ghosts; + void G_DoPlayDemo(char *defdemoname); void G_TimeDemo(const char *name); void G_AddGhost(char *defdemoname); @@ -183,6 +195,8 @@ boolean G_GametypeUsesLives(void); boolean G_GametypeHasTeams(void); boolean G_GametypeHasSpectators(void); boolean G_BattleGametype(void); +INT16 G_SometimesGetDifferentGametype(void); +UINT8 G_GetGametypeColor(INT16 gt); boolean G_RaceGametype(void); boolean G_TagGametype(void); void G_ExitLevel(void); @@ -236,6 +250,6 @@ FUNCMATH INT32 G_TicsToMilliseconds(tic_t tics); // Don't split up TOL handling INT16 G_TOLFlag(INT32 pgametype); -INT16 G_RandMap(INT16 tolflags, INT16 pprevmap, boolean dontadd, boolean ignorebuffer); +INT16 G_RandMap(INT16 tolflags, INT16 pprevmap, boolean dontadd, boolean ignorebuffer, UINT8 maphell, boolean callagainsoon); #endif diff --git a/src/g_input.c b/src/g_input.c index 2822cc29..6b0dd7b6 100644 --- a/src/g_input.c +++ b/src/g_input.c @@ -1208,6 +1208,7 @@ static const char *gamecontrolname[num_gamecontrols] = "scores", "console", "pause", + "systemmenu", "custom1", "custom2", "custom3", diff --git a/src/g_input.h b/src/g_input.h index 7e49fff3..6bbadf3e 100644 --- a/src/g_input.h +++ b/src/g_input.h @@ -114,6 +114,7 @@ typedef enum gc_scores, gc_console, gc_pause, + gc_systemmenu, gc_custom1, // Lua scriptable gc_custom2, // Lua scriptable gc_custom3, // Lua scriptable diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index c142e74c..f1949325 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -209,7 +209,7 @@ void HWR_DrawFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, // if it's meant to cover the whole screen, black out the rest // cx and cy are possibly *slightly* off from float maths // This is done before here compared to software because we directly alter cx and cy to centre - if (cx >= -0.1f && cx <= 0.1f && SHORT(gpatch->width) == BASEVIDWIDTH && cy >= -0.1f && cy <= 0.1f && SHORT(gpatch->height) == BASEVIDHEIGHT) + /*if (cx >= -0.1f && cx <= 0.1f && SHORT(gpatch->width) == BASEVIDWIDTH && cy >= -0.1f && cy <= 0.1f && SHORT(gpatch->height) == BASEVIDHEIGHT) { // Need to temporarily cache the real patch to get the colour of the top left pixel patch_t *realpatch = W_CacheLumpNumPwad(gpatch->wadnum, gpatch->lumpnum, PU_STATIC); @@ -217,7 +217,7 @@ void HWR_DrawFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, const UINT8 *source = (const UINT8 *)(column) + 3; HWR_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0])); Z_Free(realpatch); - } + }*/ // centre screen if (vid.width != BASEVIDWIDTH * vid.dupx) { @@ -292,9 +292,9 @@ void HWR_DrawFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, { FSurfaceInfo Surf; Surf.FlatColor.s.red = Surf.FlatColor.s.green = Surf.FlatColor.s.blue = 0xff; - if (alphalevel == 13) Surf.FlatColor.s.alpha = softwaretranstogl_lo[cv_translucenthud.value]; - else if (alphalevel == 14) Surf.FlatColor.s.alpha = softwaretranstogl[cv_translucenthud.value]; - else if (alphalevel == 15) Surf.FlatColor.s.alpha = softwaretranstogl_hi[cv_translucenthud.value]; + if (alphalevel == 13) Surf.FlatColor.s.alpha = softwaretranstogl_lo[hudtrans]; + else if (alphalevel == 14) Surf.FlatColor.s.alpha = softwaretranstogl[hudtrans]; + else if (alphalevel == 15) Surf.FlatColor.s.alpha = softwaretranstogl_hi[hudtrans]; else Surf.FlatColor.s.alpha = softwaretranstogl[10-alphalevel]; flags |= PF_Modulated; HWD.pfnDrawPolygon(&Surf, v, 4, flags); @@ -357,7 +357,7 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal // if it's meant to cover the whole screen, black out the rest // cx and cy are possibly *slightly* off from float maths // This is done before here compared to software because we directly alter cx and cy to centre - if (cx >= -0.1f && cx <= 0.1f && SHORT(gpatch->width) == BASEVIDWIDTH && cy >= -0.1f && cy <= 0.1f && SHORT(gpatch->height) == BASEVIDHEIGHT) + /*if (cx >= -0.1f && cx <= 0.1f && SHORT(gpatch->width) == BASEVIDWIDTH && cy >= -0.1f && cy <= 0.1f && SHORT(gpatch->height) == BASEVIDHEIGHT) { // Need to temporarily cache the real patch to get the colour of the top left pixel patch_t *realpatch = W_CacheLumpNumPwad(gpatch->wadnum, gpatch->lumpnum, PU_STATIC); @@ -365,7 +365,7 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal const UINT8 *source = (const UINT8 *)(column) + 3; HWR_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0])); Z_Free(realpatch); - } + }*/ // centre screen if (vid.width != BASEVIDWIDTH * vid.dupx) { @@ -446,9 +446,9 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal { FSurfaceInfo Surf; Surf.FlatColor.s.red = Surf.FlatColor.s.green = Surf.FlatColor.s.blue = 0xff; - if (alphalevel == 13) Surf.FlatColor.s.alpha = softwaretranstogl_lo[cv_translucenthud.value]; - else if (alphalevel == 14) Surf.FlatColor.s.alpha = softwaretranstogl[cv_translucenthud.value]; - else if (alphalevel == 15) Surf.FlatColor.s.alpha = softwaretranstogl_hi[cv_translucenthud.value]; + if (alphalevel == 13) Surf.FlatColor.s.alpha = softwaretranstogl_lo[hudtrans]; + else if (alphalevel == 14) Surf.FlatColor.s.alpha = softwaretranstogl[hudtrans]; + else if (alphalevel == 15) Surf.FlatColor.s.alpha = softwaretranstogl_hi[hudtrans]; else Surf.FlatColor.s.alpha = softwaretranstogl[10-alphalevel]; flags |= PF_Modulated; HWD.pfnDrawPolygon(&Surf, v, 4, flags); @@ -576,29 +576,33 @@ void HWR_DrawFlatFill (INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum // | /| // |/ | // 0--1 -void HWR_FadeScreenMenuBack(UINT32 color, INT32 height) +void HWR_FadeScreenMenuBack(UINT16 color, UINT8 strength) { - FOutVector v[4]; - FSurfaceInfo Surf; + FOutVector v[4]; + FSurfaceInfo Surf; - // setup some neat-o translucency effect - if (!height) //cool hack 0 height is full height - height = vid.height; + v[0].x = v[3].x = -1.0f; + v[2].x = v[1].x = 1.0f; + v[0].y = v[1].y = -1.0f; + v[2].y = v[3].y = 1.0f; + v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; - v[0].x = v[3].x = -1.0f; - v[2].x = v[1].x = 1.0f; - v[0].y = v[1].y = 1.0f-((height<<1)/(float)vid.height); - v[2].y = v[3].y = 1.0f; - v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; + v[0].sow = v[3].sow = 0.0f; + v[2].sow = v[1].sow = 1.0f; + v[0].tow = v[1].tow = 1.0f; + v[2].tow = v[3].tow = 0.0f; - v[0].sow = v[3].sow = 0.0f; - v[2].sow = v[1].sow = 1.0f; - v[0].tow = v[1].tow = 1.0f; - v[2].tow = v[3].tow = 0.0f; - - Surf.FlatColor.rgba = UINT2RGBA(color); - Surf.FlatColor.s.alpha = (UINT8)((0xff/2) * ((float)height / vid.height)); //calum: varies console alpha - HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest); + if (color & 0xFF00) // Do COLORMAP fade. + { + Surf.FlatColor.rgba = UINT2RGBA(0x01010160); + Surf.FlatColor.s.alpha = (strength*8); + } + else // Do TRANSMAP** fade. + { + Surf.FlatColor.rgba = pLocalPalette[color].rgba; + Surf.FlatColor.s.alpha = (UINT8)(strength*25.5f); + } + HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest); } // Draw the console background with translucency support @@ -900,6 +904,210 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color) PF_Modulated|PF_NoTexture|PF_NoDepthTest); } + +// -------------------+ +// HWR_DrawConsoleFill : draw flat coloured transparent rectangle because that's cool, and hw sucks less than sw for that. +// -------------------+ +void HWR_DrawConsoleFill(INT32 x, INT32 y, INT32 w, INT32 h, UINT32 color, INT32 options) +{ + FOutVector v[4]; + FSurfaceInfo Surf; + float fx, fy, fw, fh; + + if (w < 0 || h < 0) + return; // consistency w/ software + +// 3--2 +// | /| +// |/ | +// 0--1 + + fx = (float)x; + fy = (float)y; + fw = (float)w; + fh = (float)h; + + if (!(options & V_NOSCALESTART)) + { + float dupx = (float)vid.dupx, dupy = (float)vid.dupy; + + if (x == 0 && y == 0 && w == BASEVIDWIDTH && h == BASEVIDHEIGHT) + { + RGBA_t rgbaColour = V_GetColor(color); + FRGBAFloat clearColour; + clearColour.red = (float)rgbaColour.s.red / 255; + clearColour.green = (float)rgbaColour.s.green / 255; + clearColour.blue = (float)rgbaColour.s.blue / 255; + clearColour.alpha = 1; + HWD.pfnClearBuffer(true, false, &clearColour); + return; + } + + fx *= dupx; + fy *= dupy; + fw *= dupx; + fh *= dupy; + + if (vid.width != BASEVIDWIDTH * vid.dupx) + { + if (options & V_SNAPTORIGHT) + fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)); + else if (!(options & V_SNAPTOLEFT)) + fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 2; + } + if (vid.height != BASEVIDHEIGHT * dupy) + { + // same thing here + if (options & V_SNAPTOBOTTOM) + fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)); + else if (!(options & V_SNAPTOTOP)) + fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 2; + } + } + + if (fx >= vid.width || fy >= vid.height) + return; + if (fx < 0) + { + fw += fx; + fx = 0; + } + if (fy < 0) + { + fh += fy; + fy = 0; + } + + if (fw <= 0 || fh <= 0) + return; + if (fx + fw > vid.width) + fw = (float)vid.width - fx; + if (fy + fh > vid.height) + fh = (float)vid.height - fy; + + fx = -1 + fx / (vid.width / 2); + fy = 1 - fy / (vid.height / 2); + fw = fw / (vid.width / 2); + fh = fh / (vid.height / 2); + + v[0].x = v[3].x = fx; + v[2].x = v[1].x = fx + fw; + v[0].y = v[1].y = fy; + v[2].y = v[3].y = fy - fh; + + //Hurdler: do we still use this argb color? if not, we should remove it + v[0].argb = v[1].argb = v[2].argb = v[3].argb = 0xff00ff00; //; + v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; + + v[0].sow = v[3].sow = 0.0f; + v[2].sow = v[1].sow = 1.0f; + v[0].tow = v[1].tow = 0.0f; + v[2].tow = v[3].tow = 1.0f; + + Surf.FlatColor.rgba = UINT2RGBA(color); + Surf.FlatColor.s.alpha = 0x80; + + HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest); +} + +// -----------------+ +// HWR_DrawDiag : draw flat coloured rectangle, with no texture +// -----------------+ +void HWR_DrawDiag(INT32 x, INT32 y, INT32 wh, INT32 color) +{ + FOutVector v[4]; + FSurfaceInfo Surf; + float fx, fy, fw, fh, fwait = 0; + + if (wh < 0) + return; // consistency w/ software + +// 3--2 +// | /| +// |/ | +// 0--1 + + fx = (float)x; + fy = (float)y; + fw = fh = (float)wh; + + if (!(color & V_NOSCALESTART)) + { + float dupx = (float)vid.dupx, dupy = (float)vid.dupy; + + fx *= dupx; + fy *= dupy; + fw *= dupx; + fh *= dupy; + + if (vid.width != BASEVIDWIDTH * vid.dupx) + { + if (color & V_SNAPTORIGHT) + fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)); + else if (!(color & V_SNAPTOLEFT)) + fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 2; + } + if (vid.height != BASEVIDHEIGHT * dupy) + { + // same thing here + if (color & V_SNAPTOBOTTOM) + fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)); + else if (!(color & V_SNAPTOTOP)) + fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 2; + } + } + + if (fx >= vid.width || fy >= vid.height) + return; + if (fx < 0) + { + fw += fx; + fx = 0; + } + if (fy < 0) + { + fh += fy; + fy = 0; + } + + if (fw <= 0 || fh <= 0) + return; + if (fx + fw > vid.width) + { + fwait = fw - ((float)vid.width - fx); + fw = (float)vid.width - fx; + } + if (fy + fh > vid.height) + fh = (float)vid.height - fy; + + fx = -1 + fx / (vid.width / 2); + fy = 1 - fy / (vid.height / 2); + fw = fw / (vid.width / 2); + fh = fh / (vid.height / 2); + + v[0].x = v[3].x = fx; + v[2].x = v[1].x = fx + fw; + v[0].y = v[1].y = fy; + v[3].y = fy - fh; + v[2].y = fy - fwait; + + //Hurdler: do we still use this argb color? if not, we should remove it + v[0].argb = v[1].argb = v[2].argb = v[3].argb = 0xff00ff00; //; + v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; + + v[0].sow = v[3].sow = 0.0f; + v[2].sow = v[1].sow = 1.0f; + v[0].tow = v[1].tow = 0.0f; + v[2].tow = v[3].tow = 1.0f; + + Surf.FlatColor = V_GetColor(color); + + HWD.pfnDrawPolygon(&Surf, v, 4, + PF_Modulated|PF_NoTexture|PF_NoDepthTest); +} + + + #ifdef HAVE_PNG #ifndef _MSC_VER diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c index eeb5afbd..ee0cca74 100644 --- a/src/hardware/hw_light.c +++ b/src/hardware/hw_light.c @@ -499,23 +499,46 @@ light_t *t_lspr[NUMSPRITES] = &lspr[NOLIGHT], //"SPRG", &lspr[NOLIGHT], //"BSPR", + &lspr[NOLIGHT], //"RNDM", - &lspr[NOLIGHT], //"SPRK", &lspr[NOLIGHT], //"KFRE", &lspr[NOLIGHT], //"DRIF", - &lspr[NOLIGHT], //"FAKE", - &lspr[NOLIGHT], //"DFAK", + &lspr[NOLIGHT], //"DSMO", + + &lspr[NOLIGHT], //"FITM", &lspr[NOLIGHT], //"BANA", - &lspr[NOLIGHT], //"DBAN", &lspr[NOLIGHT], //"GSHE", - &lspr[NOLIGHT], //"GSTR", - &lspr[NOLIGHT], //"DGSH", &lspr[NOLIGHT], //"RSHE", - &lspr[NOLIGHT], //"RSTR", - &lspr[NOLIGHT], //"DRSH", - &lspr[NOLIGHT], //"BOMB", + &lspr[NOLIGHT], //"SSMN", &lspr[NOLIGHT], //"BLIG", - &lspr[NOLIGHT], //"LIGH" + &lspr[NOLIGHT], //"LIGH", + &lspr[NOLIGHT], //"SINK", + &lspr[NOLIGHT], //"SITR", + &lspr[NOLIGHT], //"KBLN", + + &lspr[NOLIGHT], //"LAKI", + + &lspr[NOLIGHT], //"POKE", + &lspr[NOLIGHT], //"AUDI", + &lspr[NOLIGHT], //"DECO", + &lspr[NOLIGHT], //"DOOD", + &lspr[NOLIGHT], //"SNES", + &lspr[NOLIGHT], //"GBAS", + &lspr[NOLIGHT], //"SPRS", + &lspr[NOLIGHT], //"BUZB", + &lspr[NOLIGHT], //"CHOM", + &lspr[NOLIGHT], //"SACO", + &lspr[NOLIGHT], //"CRAB", + &lspr[NOLIGHT], //"SHAD", + + &lspr[NOLIGHT], //"BUMP", + &lspr[NOLIGHT], //"FLEN", + &lspr[NOLIGHT], //"CLAS", + &lspr[NOLIGHT], //"PSHW", + + &lspr[NOLIGHT], //"ARRO", + + &lspr[NOLIGHT], //"PBOM" // Free slots &lspr[NOLIGHT], diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 7996cf32..e67ede23 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -59,7 +59,7 @@ struct hwdriver_s hwdriver; // ========================================================================== -static void HWR_AddSprites(sector_t *sec); +static void HWR_AddSprites(sector_t *sec, UINT8 ssplayer); static void HWR_ProjectSprite(mobj_t *thing); #ifdef HWPRECIP static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing); @@ -2186,27 +2186,34 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) } else if (drawtextured) { -#ifdef ESLOPE // P.S. this is better-organized than the old version - fixed_t offs = sides[(newline ? newline : rover->master)->sidenum[0]].rowoffset; - grTex = HWR_GetTexture(texnum); - - wallVerts[3].t = (*rover->topheight - h + offs) * grTex->scaleY; - wallVerts[2].t = (*rover->topheight - hS + offs) * grTex->scaleY; - wallVerts[0].t = (*rover->topheight - l + offs) * grTex->scaleY; - wallVerts[1].t = (*rover->topheight - lS + offs) * grTex->scaleY; -#else - grTex = HWR_GetTexture(texnum); + fixed_t texturevpeg; + // Wow, how was this missing from OpenGL for so long? + // ...Oh well, anyway, Lower Unpegged now changes pegging of FOFs like in software + // -- Monster Iestyn 26/06/18 if (newline) { - wallVerts[3].t = wallVerts[2].t = (*rover->topheight - h + sides[newline->sidenum[0]].rowoffset) * grTex->scaleY; - wallVerts[0].t = wallVerts[1].t = (h - l + (*rover->topheight - h + sides[newline->sidenum[0]].rowoffset)) * grTex->scaleY; + texturevpeg = sides[newline->sidenum[0]].rowoffset; + if (newline->flags & ML_DONTPEGBOTTOM) + texturevpeg -= *rover->topheight - *rover->bottomheight; } else { - wallVerts[3].t = wallVerts[2].t = (*rover->topheight - h + sides[rover->master->sidenum[0]].rowoffset) * grTex->scaleY; - wallVerts[0].t = wallVerts[1].t = (h - l + (*rover->topheight - h + sides[rover->master->sidenum[0]].rowoffset)) * grTex->scaleY; + texturevpeg = sides[rover->master->sidenum[0]].rowoffset; + if (gr_linedef->flags & ML_DONTPEGBOTTOM) + texturevpeg -= *rover->topheight - *rover->bottomheight; } + + grTex = HWR_GetTexture(texnum); + +#ifdef ESLOPE + wallVerts[3].t = (*rover->topheight - h + texturevpeg) * grTex->scaleY; + wallVerts[2].t = (*rover->topheight - hS + texturevpeg) * grTex->scaleY; + wallVerts[0].t = (*rover->topheight - l + texturevpeg) * grTex->scaleY; + wallVerts[1].t = (*rover->topheight - lS + texturevpeg) * grTex->scaleY; +#else + wallVerts[3].t = wallVerts[2].t = (*rover->topheight - h + texturevpeg) * grTex->scaleY; + wallVerts[0].t = wallVerts[1].t = (*rover->topheight - l + texturevpeg) * grTex->scaleY; #endif wallVerts[0].s = wallVerts[3].s = cliplow * grTex->scaleX; @@ -3234,7 +3241,7 @@ static void HWR_AddPolyObjectPlanes(void) // : Draw one or more line segments. // Notes : Sets gr_cursectorlight to the light of the parent sector, to modulate wall textures // -----------------+ -static void HWR_Subsector(size_t num) +static void HWR_Subsector(size_t num, UINT8 ssplayer) { INT16 count; seg_t *line; @@ -3602,7 +3609,7 @@ static void HWR_Subsector(size_t num) { // draw sprites first, coz they are clipped to the solidsegs of // subsectors more 'in front' - HWR_AddSprites(gr_frontsector); + HWR_AddSprites(gr_frontsector, ssplayer); //Hurdler: at this point validcount must be the same, but is not because // gr_frontsector doesn't point anymore to sub->sector due to @@ -3654,7 +3661,7 @@ static boolean HWR_CheckHackBBox(fixed_t *bb) // BP: big hack for a test in lighning ref : 1249753487AB fixed_t *hwbbox; -static void HWR_RenderBSPNode(INT32 bspnum) +static void HWR_RenderBSPNode(INT32 bspnum, UINT8 ssplayer) { /*//GZDoom code if(bspnum == -1) @@ -3694,12 +3701,12 @@ static void HWR_RenderBSPNode(INT32 bspnum) if (bspnum == -1) { //*(gr_drawsubsector_p++) = 0; - HWR_Subsector(0); + HWR_Subsector(0, ssplayer); } else { //*(gr_drawsubsector_p++) = bspnum&(~NF_SUBSECTOR); - HWR_Subsector(bspnum&(~NF_SUBSECTOR)); + HWR_Subsector(bspnum&(~NF_SUBSECTOR), ssplayer); } return; } @@ -3711,14 +3718,14 @@ static void HWR_RenderBSPNode(INT32 bspnum) hwbbox = bsp->bbox[side]; // Recursively divide front space. - HWR_RenderBSPNode(bsp->children[side]); + HWR_RenderBSPNode(bsp->children[side], ssplayer); // Possibly divide back space. if (HWR_CheckBBox(bsp->bbox[side^1])) { // BP: big hack for a test in lighning ref : 1249753487AB hwbbox = bsp->bbox[side^1]; - HWR_RenderBSPNode(bsp->children[side^1]); + HWR_RenderBSPNode(bsp->children[side^1], ssplayer); } } @@ -5110,7 +5117,7 @@ static void HWR_DrawSprites(void) // During BSP traversal, this adds sprites by sector. // -------------------------------------------------------------------------- static UINT8 sectorlight; -static void HWR_AddSprites(sector_t *sec) +static void HWR_AddSprites(sector_t *sec, UINT8 ssplayer) { mobj_t *thing; #ifdef HWPRECIP @@ -5140,6 +5147,25 @@ static void HWR_AddSprites(sector_t *sec) if (thing->sprite == SPR_NULL || thing->flags2 & MF2_DONTDRAW) continue; + if (splitscreen) + { + if (thing->eflags & MFE_DRAWONLYFORP1) + if (ssplayer != 1) + continue; + + if (thing->eflags & MFE_DRAWONLYFORP2) + if (ssplayer != 2) + continue; + + if (thing->eflags & MFE_DRAWONLYFORP3 && splitscreen > 1) + if (ssplayer != 3) + continue; + + if (thing->eflags & MFE_DRAWONLYFORP4 && splitscreen > 2) + if (ssplayer != 4) + continue; + } + approx_dist = P_AproxDistance(viewx-thing->x, viewy-thing->y); if (approx_dist <= limit_dist) @@ -5150,8 +5176,31 @@ static void HWR_AddSprites(sector_t *sec) { // Draw everything in sector, no checks for (thing = sec->thinglist; thing; thing = thing->snext) - if (!(thing->sprite == SPR_NULL || thing->flags2 & MF2_DONTDRAW)) - HWR_ProjectSprite(thing); + { + if (thing->sprite == SPR_NULL || thing->flags2 & MF2_DONTDRAW) + continue; + + if (splitscreen) + { + if (thing->eflags & MFE_DRAWONLYFORP1) + if (ssplayer != 1) + continue; + + if (thing->eflags & MFE_DRAWONLYFORP2) + if (ssplayer != 2) + continue; + + if (thing->eflags & MFE_DRAWONLYFORP3 && splitscreen > 1) + if (ssplayer != 3) + continue; + + if (thing->eflags & MFE_DRAWONLYFORP4 && splitscreen > 2) + if (ssplayer != 4) + continue; + } + + HWR_ProjectSprite(thing); + } } #ifdef HWPRECIP @@ -5347,7 +5396,10 @@ static void HWR_ProjectSprite(mobj_t *thing) } heightsec = thing->subsector->sector->heightsec; - phs = players[displayplayer].mo->subsector->sector->heightsec; + if (viewplayer->mo && viewplayer->mo->subsector) + phs = viewplayer->mo->subsector->sector->heightsec; + else + phs = -1; if (heightsec != -1 && phs != -1) // only clip things which are in special sectors { @@ -5388,23 +5440,15 @@ static void HWR_ProjectSprite(mobj_t *thing) else if (thing->color) { // New colormap stuff for skins Tails 06-07-2002 - if (thing->skin && thing->sprite == SPR_PLAY) // This thing is a player! + if (thing->colorized) + vis->colormap = R_GetTranslationColormap(TC_RAINBOW, thing->color, GTC_CACHE); + else if (thing->skin && thing->sprite == SPR_PLAY) // This thing is a player! { - if (thing->colorized) - vis->colormap = R_GetTranslationColormap(TC_STARMAN, thing->color, GTC_CACHE); - else - { - size_t skinnum = (skin_t*)thing->skin-skins; - vis->colormap = R_GetTranslationColormap((INT32)skinnum, thing->color, GTC_CACHE); - } + size_t skinnum = (skin_t*)thing->skin-skins; + vis->colormap = R_GetTranslationColormap((INT32)skinnum, thing->color, GTC_CACHE); } else - { - if (vis->mobj && vis->mobj->colorized) - vis->colormap = R_GetTranslationColormap(TC_STARMAN, vis->mobj->color ? vis->mobj->color : SKINCOLOR_CYAN, GTC_CACHE); - else - vis->colormap = R_GetTranslationColormap(TC_DEFAULT, vis->mobj->color ? vis->mobj->color : SKINCOLOR_CYAN, GTC_CACHE); - } + vis->colormap = R_GetTranslationColormap(TC_DEFAULT, thing->color, GTC_CACHE); } else vis->colormap = colormaps; @@ -5666,13 +5710,31 @@ void HWR_RenderSkyboxView(INT32 viewnumber, player_t *player) { const float fpov = FIXED_TO_FLOAT(cv_grfov.value+player->fovadd); postimg_t *type; + UINT8 ssplayer = 0; - if (splitscreen && player == &players[secondarydisplayplayer]) - type = &postimgtype2; - else if (splitscreen > 1 && player == &players[thirddisplayplayer]) - type = &postimgtype3; - else if (splitscreen > 2 && player == &players[fourthdisplayplayer]) - type = &postimgtype4; + if (splitscreen) + { + if (player == &players[secondarydisplayplayer]) + { + type = &postimgtype2; + ssplayer = 2; + } + else if (splitscreen > 1 && player == &players[thirddisplayplayer]) + { + type = &postimgtype3; + ssplayer = 3; + } + else if (splitscreen > 2 && player == &players[fourthdisplayplayer]) + { + type = &postimgtype4; + ssplayer = 4; + } + else + { + type = &postimgtype; + ssplayer = 1; + } + } else type = &postimgtype; @@ -5789,7 +5851,7 @@ if (0) validcount++; - HWR_RenderBSPNode((INT32)numnodes-1); + HWR_RenderBSPNode((INT32)numnodes-1, ssplayer); // Make a viewangle int so we can render things based on mouselook if (player == &players[consoleplayer]) @@ -5806,18 +5868,18 @@ if (0) { dup_viewangle += ANGLE_90; HWR_ClearClipSegs(); - HWR_RenderBSPNode((INT32)numnodes-1); //left + HWR_RenderBSPNode((INT32)numnodes-1, ssplayer); //left dup_viewangle += ANGLE_90; if (((INT32)aimingangle > ANGLE_45 || (INT32)aimingangle<-ANGLE_45)) { HWR_ClearClipSegs(); - HWR_RenderBSPNode((INT32)numnodes-1); //back + HWR_RenderBSPNode((INT32)numnodes-1, ssplayer); //back } dup_viewangle += ANGLE_90; HWR_ClearClipSegs(); - HWR_RenderBSPNode((INT32)numnodes-1); //right + HWR_RenderBSPNode((INT32)numnodes-1, ssplayer); //right dup_viewangle += ANGLE_90; } @@ -5881,17 +5943,35 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player) { const float fpov = FIXED_TO_FLOAT(cv_grfov.value+player->fovadd); postimg_t *type; + UINT8 ssplayer = 0; const boolean skybox = (skyboxmo[0] && cv_skybox.value); // True if there's a skybox object and skyboxes are on FRGBAFloat ClearColor; - if (splitscreen && player == &players[secondarydisplayplayer]) - type = &postimgtype2; - else if (splitscreen > 1 && player == &players[thirddisplayplayer]) - type = &postimgtype3; - else if (splitscreen > 2 && player == &players[fourthdisplayplayer]) - type = &postimgtype4; + if (splitscreen) + { + if (player == &players[secondarydisplayplayer]) + { + type = &postimgtype2; + ssplayer = 2; + } + else if (splitscreen > 1 && player == &players[thirddisplayplayer]) + { + type = &postimgtype3; + ssplayer = 3; + } + else if (splitscreen > 2 && player == &players[fourthdisplayplayer]) + { + type = &postimgtype4; + ssplayer = 4; + } + else + { + type = &postimgtype; + ssplayer = 1; + } + } else type = &postimgtype; @@ -6019,7 +6099,7 @@ if (0) validcount++; - HWR_RenderBSPNode((INT32)numnodes-1); + HWR_RenderBSPNode((INT32)numnodes-1, ssplayer); // Make a viewangle int so we can render things based on mouselook if (player == &players[consoleplayer]) @@ -6036,18 +6116,18 @@ if (0) { dup_viewangle += ANGLE_90; HWR_ClearClipSegs(); - HWR_RenderBSPNode((INT32)numnodes-1); //left + HWR_RenderBSPNode((INT32)numnodes-1, ssplayer); //left dup_viewangle += ANGLE_90; if (((INT32)aimingangle > ANGLE_45 || (INT32)aimingangle<-ANGLE_45)) { HWR_ClearClipSegs(); - HWR_RenderBSPNode((INT32)numnodes-1); //back + HWR_RenderBSPNode((INT32)numnodes-1, ssplayer); //back } dup_viewangle += ANGLE_90; HWR_ClearClipSegs(); - HWR_RenderBSPNode((INT32)numnodes-1); //right + HWR_RenderBSPNode((INT32)numnodes-1, ssplayer); //right dup_viewangle += ANGLE_90; } diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index fce17062..f74814f0 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -33,7 +33,7 @@ void HWR_Shutdown(void); void HWR_clearAutomap(void); void HWR_drawAMline(const fline_t *fl, INT32 color); -void HWR_FadeScreenMenuBack(UINT32 color, INT32 height); +void HWR_FadeScreenMenuBack(UINT16 color, UINT8 strength); void HWR_DrawConsoleBack(UINT32 color, INT32 height); void HWR_RenderSkyboxView(INT32 viewnumber, player_t *player); void HWR_RenderPlayerView(INT32 viewnumber, player_t *player); @@ -46,12 +46,13 @@ void HWR_SetViewSize(void); void HWR_DrawPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option); void HWR_DrawFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t scale, INT32 option, const UINT8 *colormap); void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t scale, INT32 option, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h); -void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, INT32 option, fixed_t scale, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h); void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipmap, boolean makebitmap); void HWR_CreatePlanePolygons(INT32 bspnum); void HWR_CreateStaticLightmaps(INT32 bspnum); void HWR_PrepLevelCache(size_t pnumtextures); void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color); +void HWR_DrawConsoleFill(INT32 x, INT32 y, INT32 w, INT32 h, UINT32 color, INT32 options); // Lat: separate flags from color since color needs to be an uint to work right. +void HWR_DrawDiag(INT32 x, INT32 y, INT32 wh, INT32 color); void HWR_DrawPic(INT32 x,INT32 y,lumpnum_t lumpnum); void HWR_AddCommands(void); diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 963b6fdb..2446b023 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -33,6 +33,7 @@ #include "hw_drv.h" #include "hw_light.h" #include "hw_md2.h" +#include "../d_main.h" #include "../r_bsp.h" #include "../r_main.h" #include "../m_misc.h" @@ -41,6 +42,7 @@ #include "../r_things.h" #include "../r_draw.h" #include "../p_tick.h" +#include "../k_kart.h" // colortranslations #include "hw_main.h" #include "../v_video.h" @@ -69,6 +71,10 @@ #endif #endif +#ifndef errno +#include "errno.h" +#endif + #define NUMVERTEXNORMALS 162 float avertexnormals[NUMVERTEXNORMALS][3] = { {-0.525731f, 0.000000f, 0.850651f}, @@ -290,7 +296,8 @@ static md2_model_t *md2_readModel(const char *filename) if (model == NULL) return 0; - file = fopen(filename, "rb"); + //Filename checking fixed ~Monster Iestyn and Golden + file = fopen(va("%s"PATHSEP"%s", srb2home, filename), "rb"); if (!file) { free(model); @@ -479,7 +486,8 @@ static GrTextureFormat_t PNG_Load(const char *filename, int *w, int *h, GLPatch_ #endif #endif png_FILE_p png_FILE; - char *pngfilename = va("md2/%s", filename); + //Filename checking fixed ~Monster Iestyn and Golden + char *pngfilename = va("%s"PATHSEP"md2"PATHSEP"%s", srb2home, filename); FIL_ForceExtension(pngfilename, ".png"); png_FILE = fopen(pngfilename, "rb"); @@ -607,7 +615,8 @@ static GrTextureFormat_t PCX_Load(const char *filename, int *w, int *h, size_t pw, ph, size, ptr = 0; INT32 ch, rep; FILE *file; - char *pcxfilename = va("md2/%s", filename); + //Filename checking fixed ~Monster Iestyn and Golden + char *pcxfilename = va("%s"PATHSEP"md2"PATHSEP"%s", srb2home, filename); FIL_ForceExtension(pcxfilename, ".pcx"); file = fopen(pcxfilename, "rb"); @@ -796,12 +805,13 @@ void HWR_InitMD2(void) md2_models[i].error = false; } - // read the kmd2.dat file - f = fopen("kmd2.dat", "rt"); + // read the md2.dat file + //Filename checking fixed ~Monster Iestyn and Golden + f = fopen(va("%s"PATHSEP"%s", srb2home, "kmd2.dat"), "rt"); if (!f) { - CONS_Printf("%s", M_GetText("Error while loading kmd2.dat\n")); + CONS_Printf("%s %s\n", M_GetText("Error while loading kmd2.dat:"), strerror(errno)); nomd2s = true; return; } @@ -862,8 +872,9 @@ void HWR_AddPlayerMD2(int skin) // For MD2's that were added after startup CONS_Printf("AddPlayerMD2()...\n"); - // read the kmd2.dat file - f = fopen("kmd2.dat", "rt"); + // read the md2.dat file + //Filename checking fixed ~Monster Iestyn and Golden + f = fopen(va("%s"PATHSEP"%s", srb2home, "kmd2.dat"), "rt"); if (!f) { @@ -907,8 +918,9 @@ void HWR_AddSpriteMD2(size_t spritenum) // For MD2s that were added after startu if (spritenum == SPR_PLAY) // Handled already NEWMD2: Per sprite, per-skin check return; - // Read the kmd2.dat file - f = fopen("kmd2.dat", "rt"); + // Read the md2.dat file + //Filename checking fixed ~Monster Iestyn and Golden + f = fopen(va("%s"PATHSEP"%s", srb2home, "kmd2.dat"), "rt"); if (!f) { @@ -938,6 +950,7 @@ spritemd2found: static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, GLMipmap_t *grmip, INT32 skinnum, skincolors_t color) { + UINT8 i; UINT16 w = gpatch->width, h = gpatch->height; UINT32 size = w*h; RGBA_t *image, *blendimage, *cur, blendcolor; @@ -963,252 +976,46 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, image = gpatch->mipmap.grInfo.data; blendimage = blendgpatch->mipmap.grInfo.data; - switch (color) + // Average all of the translation's colors { - case SKINCOLOR_IVORY: - blendcolor = V_GetColor(0); - break; - case SKINCOLOR_WHITE: - blendcolor = V_GetColor(3); - break; - case SKINCOLOR_SILVER: - blendcolor = V_GetColor(7); - break; - case SKINCOLOR_CLOUDY: - blendcolor = V_GetColor(13); - break; - case SKINCOLOR_GREY: - blendcolor = V_GetColor(15); - break; - case SKINCOLOR_DARKGREY: - blendcolor = V_GetColor(23); - break; - case SKINCOLOR_BLACK: - blendcolor = V_GetColor(27); - break; - case SKINCOLOR_SALMON: - blendcolor = V_GetColor(123); - break; - case SKINCOLOR_PINK: - blendcolor = V_GetColor(147); - break; - case SKINCOLOR_LIGHTRED: - blendcolor = V_GetColor(127); - break; - case SKINCOLOR_SHINYRED: - blendcolor = V_GetColor(130); - break; - case SKINCOLOR_RED: - blendcolor = V_GetColor(132); - break; - case SKINCOLOR_DARKPINK: - blendcolor = V_GetColor(151); - break; - case SKINCOLOR_DARKRED: - blendcolor = V_GetColor(139); - break; - case SKINCOLOR_DAWN: - blendcolor = V_GetColor(89); - break; - case SKINCOLOR_ORANGE: - blendcolor = V_GetColor(87); - break; - case SKINCOLOR_SHINYORANGE: - blendcolor = V_GetColor(91); - break; - case SKINCOLOR_DARKORANGE: - blendcolor = V_GetColor(95); - break; - case SKINCOLOR_GOLDENBROWN: - blendcolor = V_GetColor(119); - break; - case SKINCOLOR_ROSEWOOD: - blendcolor = V_GetColor(155); - break; - case SKINCOLOR_DARKROSEWOOD: - blendcolor = V_GetColor(159); - break; - case SKINCOLOR_SEPIA: - blendcolor = V_GetColor(37); - break; - case SKINCOLOR_BEIGE: - blendcolor = V_GetColor(39); - break; - case SKINCOLOR_BROWN: - blendcolor = V_GetColor(55); - break; - case SKINCOLOR_LEATHER: - blendcolor = V_GetColor(61); - break; - case SKINCOLOR_YELLOW: - blendcolor = V_GetColor(104); - break; - case SKINCOLOR_PEACH: - blendcolor = V_GetColor(71); - break; - case SKINCOLOR_LIGHTORANGE: - blendcolor = V_GetColor(83); - break; - case SKINCOLOR_CARAMEL: - blendcolor = V_GetColor(79); - break; - case SKINCOLOR_GOLD: - blendcolor = V_GetColor(115); - break; - case SKINCOLOR_SHINYCARAMEL: - blendcolor = V_GetColor(78); - break; - case SKINCOLOR_VOMIT: - blendcolor = V_GetColor(114); - break; - case SKINCOLOR_GARDEN: - blendcolor = V_GetColor(179); - break; - case SKINCOLOR_LIGHTARMY: - blendcolor = V_GetColor(177); - break; - case SKINCOLOR_ARMY: - blendcolor = V_GetColor(179); - break; - case SKINCOLOR_PISTACHIO: - blendcolor = V_GetColor(166); - break; - case SKINCOLOR_ROBOHOOD: - blendcolor = V_GetColor(182); - break; - case SKINCOLOR_OLIVE: - blendcolor = V_GetColor(108); - break; - case SKINCOLOR_DARKARMY: - blendcolor = V_GetColor(183); - break; - case SKINCOLOR_LIGHTGREEN: - blendcolor = V_GetColor(163); - break; - case SKINCOLOR_UGLYGREEN: - blendcolor = V_GetColor(185); - break; - case SKINCOLOR_NEONGREEN: - blendcolor = V_GetColor(187); - break; - case SKINCOLOR_GREEN: - blendcolor = V_GetColor(167); - break; - case SKINCOLOR_DARKGREEN: - blendcolor = V_GetColor(171); - break; - case SKINCOLOR_SWAMP: - blendcolor = V_GetColor(190); - break; - case SKINCOLOR_FROST: - blendcolor = V_GetColor(215); - break; - case SKINCOLOR_SLATE: - blendcolor = V_GetColor(201); - break; - case SKINCOLOR_LIGHTBLUE: - blendcolor = V_GetColor(227); - break; - case SKINCOLOR_CYAN: - blendcolor = V_GetColor(213); - break; - case SKINCOLOR_CERULEAN: - blendcolor = V_GetColor(217); - break; - case SKINCOLOR_TURQUOISE: - blendcolor = V_GetColor(220); - break; - case SKINCOLOR_TEAL: - blendcolor = V_GetColor(221); - break; - case SKINCOLOR_STEELBLUE: - blendcolor = V_GetColor(203); - break; - case SKINCOLOR_BLUE: - blendcolor = V_GetColor(231); - break; - case SKINCOLOR_SHINYBLUE: - blendcolor = V_GetColor(234); - break; - case SKINCOLOR_NAVY: - blendcolor = V_GetColor(206); - break; - case SKINCOLOR_DARKBLUE: - blendcolor = V_GetColor(238); - break; - case SKINCOLOR_JETBLACK: - blendcolor = V_GetColor(207); - break; - case SKINCOLOR_LILAC: - blendcolor = V_GetColor(123); - break; - case SKINCOLOR_PURPLE: - blendcolor = V_GetColor(195); - break; - case SKINCOLOR_LAVENDER: - blendcolor = V_GetColor(251); - break; - case SKINCOLOR_BYZANTIUM: - blendcolor = V_GetColor(254); - break; - case SKINCOLOR_INDIGO: - blendcolor = V_GetColor(199); - break; + UINT16 r, g, b; + UINT8 div = 0; - case SKINCOLOR_SUPER1: - blendcolor = V_GetColor(97); - break; - case SKINCOLOR_SUPER2: - blendcolor = V_GetColor(100); - break; - case SKINCOLOR_SUPER3: - blendcolor = V_GetColor(103); - break; - case SKINCOLOR_SUPER4: - blendcolor = V_GetColor(113); - break; - case SKINCOLOR_SUPER5: - blendcolor = V_GetColor(116); - break; + blendcolor = V_GetColor(colortranslations[color][0]); + r = (UINT16)blendcolor.s.red; + g = (UINT16)blendcolor.s.green; + b = (UINT16)blendcolor.s.blue; - case SKINCOLOR_TSUPER1: - blendcolor = V_GetColor(81); - break; - case SKINCOLOR_TSUPER2: - blendcolor = V_GetColor(82); - break; - case SKINCOLOR_TSUPER3: - blendcolor = V_GetColor(84); - break; - case SKINCOLOR_TSUPER4: - blendcolor = V_GetColor(85); - break; - case SKINCOLOR_TSUPER5: - blendcolor = V_GetColor(87); - break; + for (i = 1; i < 16; i++) + { + RGBA_t nextcolor = V_GetColor(colortranslations[color][i]); + UINT8 mul = 1; + // Weight these shades more. Indices 1-9 weren't randomly picked, they are commonly used on sprites and are generally what the colors "look" like + if (i >= 1 && i <= 9) + mul++; + // The mid & dark tons on the minimap icons get weighted even harder + if (i == 4 || i == 6) + mul += 2; + // And the shade between them, why not + if (i == 5) + mul++; + r += (UINT16)(nextcolor.s.red)*mul; + g += (UINT16)(nextcolor.s.green)*mul; + b += (UINT16)(nextcolor.s.blue)*mul; + div += mul; + } - case SKINCOLOR_KSUPER1: - blendcolor = V_GetColor(122); - break; - case SKINCOLOR_KSUPER2: - blendcolor = V_GetColor(123); - break; - case SKINCOLOR_KSUPER3: - blendcolor = V_GetColor(124); - break; - case SKINCOLOR_KSUPER4: - blendcolor = V_GetColor(125); - break; - case SKINCOLOR_KSUPER5: - blendcolor = V_GetColor(126); - break; - default: - blendcolor = V_GetColor(247); - break; + // This shouldn't happen. + if (div < 1) + div = 1; + + blendcolor.s.red = (UINT8)(r/div); + blendcolor.s.green = (UINT8)(g/div); + blendcolor.s.blue = (UINT8)(b/div); } - // starman support, could theoretically support boss ones too - if (skinnum == TC_STARMAN) + // rainbow support, could theoretically support boss ones too + if (skinnum == TC_RAINBOW) { while (size--) { @@ -1490,7 +1297,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr) if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) { if (spr->mobj->colorized) - skinnum = TC_STARMAN; + skinnum = TC_RAINBOW; else { skinnum = (INT32)((skin_t*)spr->mobj->skin-skins); @@ -1524,7 +1331,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr) frame = (spr->mobj->frame & FF_FRAMEMASK) % md2->model->header.numFrames; buff = md2->model->glCommandBuffer; curr = &md2->model->frames[frame]; - if (cv_grmd2.value == 1) + if (cv_grmd2.value == 1 && tics <= durs) { // frames are handled differently for states with FF_ANIMATE, so get the next frame differently for the interpolation if (spr->mobj->frame & FF_ANIMATE) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index c3c04bed..36b2812e 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -76,6 +76,7 @@ patch_t *cred_font[CRED_FONTSIZE]; static player_t *plr; boolean chat_on; // entering a chat message? static char w_chat[HU_MAXMSGLEN]; +static UINT32 c_input = 0; // let's try to make the chat input less shitty. static boolean headsupactive = false; boolean hu_showscores; // draw rankings static char hu_tick; @@ -336,6 +337,76 @@ void HU_Start(void) //====================================================================== #ifndef NONET + +// EVERY CHANGE IN THIS SCRIPT IS LOL XD! BY VINCYTM + +static UINT32 chat_nummsg_log = 0; +static UINT32 chat_nummsg_min = 0; +static UINT32 chat_scroll = 0; +static tic_t chat_scrolltime = 0; + +static UINT32 chat_maxscroll = 0; // how far can we scroll? + +//static chatmsg_t chat_mini[CHAT_BUFSIZE]; // Display the last few messages sent. +//static chatmsg_t chat_log[CHAT_BUFSIZE]; // Keep every message sent to us in memory so we can scroll n shit, it's cool. + +static char chat_log[CHAT_BUFSIZE][255]; // hold the last 48 or so messages in that log. +static char chat_mini[8][255]; // display up to 8 messages that will fade away / get overwritten +static tic_t chat_timers[8]; + +static boolean chat_scrollmedown = false; // force instant scroll down on the chat log. Happens when you open it / send a message. + +// remove text from minichat table + +static INT16 addy = 0; // use this to make the messages scroll smoothly when one fades away + +static void HU_removeChatText_Mini(void) +{ + // MPC: Don't create new arrays, just iterate through an existing one + UINT32 i; + for(i=0;i= CHAT_BUFSIZE) + HU_removeChatText_Log(); + + strcpy(chat_log[chat_nummsg_log], text); + chat_nummsg_log++; + + if (chat_nummsg_min >= 8) + HU_removeChatText_Mini(); + + strcpy(chat_mini[chat_nummsg_min], text); + chat_timers[chat_nummsg_min] = TICRATE*cv_chattime.value; + chat_nummsg_min++; +} + /** Runs a say command, sending an ::XD_SAY message. * A say command consists of a signed 8-bit integer for the target, an * unsigned 8-bit flag variable, and then the message itself. @@ -364,14 +435,14 @@ static void DoSayCommand(SINT8 target, size_t usedargs, UINT8 flags) numwords = COM_Argc() - usedargs; I_Assert(numwords > 0); - if (cv_mute.value && !(server || IsPlayerAdmin(consoleplayer))) + if (cv_mute.value && !(server || IsPlayerAdmin(consoleplayer))) // TODO: Per Player mute. { - CONS_Alert(CONS_NOTICE, M_GetText("The chat is muted. You can't say anything at the moment.\n")); + HU_AddChatText(va("%s>ERROR: The chat is muted. You can't say anything.", "\x85")); return; } // Only servers/admins can CSAY. - if(!server && IsPlayerAdmin(consoleplayer)) + if(!server && !(IsPlayerAdmin(consoleplayer))) flags &= ~HU_CSAY; // We handle HU_SERVER_SAY, not the caller. @@ -390,6 +461,52 @@ static void DoSayCommand(SINT8 target, size_t usedargs, UINT8 flags) strlcat(msg, COM_Argv(ix + usedargs), msgspace); } + if (strlen(msg) > 4 && strnicmp(msg, "/pm", 3) == 0) // used /pm + { + // what we're gonna do now is check if the node exists + // with that logic, characters 4 and 5 are our numbers: + int spc = 1; // used if nodenum[1] is a space. + char *nodenum = (char*) malloc(3); + strncpy(nodenum, msg+3, 5); + // check for undesirable characters in our "number" + if (((nodenum[0] < '0') || (nodenum[0] > '9')) || ((nodenum[1] < '0') || (nodenum[1] > '9'))) + { + // check if nodenum[1] is a space + if (nodenum[1] == ' ') + spc = 0; + // let it slide + else + { + HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm \'."); + return; + } + } + // I'm very bad at C, I swear I am, additional checks eww! + if (spc != 0) + { + if (msg[5] != ' ') + { + HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm \'."); + return; + } + } + + target = atoi((const char*) nodenum); // turn that into a number + //CONS_Printf("%d\n", target); + + // check for target player, if it doesn't exist then we can't send the message! + if (playeringame[target]) // player exists + target++; // even though playernums are from 0 to 31, target is 1 to 32, so up that by 1 to have it work! + else + { + HU_AddChatText(va("\x82NOTICE: \x80Player %d does not exist.", target)); // same + return; + } + buf[0] = target; + const char *newmsg = msg+5+spc; + memcpy(msg, newmsg, 252); + } + SendNetXCmd(XD_SAY, buf, strlen(msg) + 1 + msg-buf); } @@ -473,6 +590,7 @@ static void Command_CSay_f(void) DoSayCommand(0, 1, HU_CSAY); } +static tic_t stop_spamming_you_cunt[MAXPLAYERS]; /** Receives a message, processing an ::XD_SAY command. * \sa DoSayCommand @@ -494,7 +612,7 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) msg = (char *)*p; SKIPSTRING(*p); - if ((cv_mute.value || flags & (HU_CSAY|HU_SERVER_SAY)) && playernum != serverplayer && !IsPlayerAdmin(playernum)) + if ((cv_mute.value || flags & (HU_CSAY|HU_SERVER_SAY)) && playernum != serverplayer && !(IsPlayerAdmin(playernum))) { CONS_Alert(CONS_WARNING, cv_mute.value ? M_GetText("Illegal say command received from %s while muted\n") : M_GetText("Illegal csay command received from non-admin %s\n"), @@ -532,11 +650,30 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) } } + int spam_eatmsg = 0; + + // before we do anything, let's verify the guy isn't spamming, get this easier on us. + + //if (stop_spamming_you_cunt[playernum] != 0 && cv_chatspamprotection.value && !(flags & HU_CSAY)) + if (stop_spamming_you_cunt[playernum] != 0 && consoleplayer != playernum && cv_chatspamprotection.value && !(flags & HU_CSAY)) + { + CONS_Debug(DBG_NETPLAY,"Received SAY cmd too quickly from Player %d (%s), assuming as spam and blocking message.\n", playernum+1, player_names[playernum]); + stop_spamming_you_cunt[playernum] = 4; + spam_eatmsg = 1; + } + else + stop_spamming_you_cunt[playernum] = 4; // you can hold off for 4 tics, can you? + + // run the lua hook even if we were supposed to eat the msg, netgame consistency goes first. + #ifdef HAVE_BLUA - if (LUAh_PlayerMsg(playernum, target, flags, msg)) + if (LUAh_PlayerMsg(playernum, target, flags, msg, spam_eatmsg)) return; #endif + if (spam_eatmsg) + return; // don't proceed if we were supposed to eat the message. + // If it's a CSAY, just CECHO and be done with it. if (flags & HU_CSAY) { @@ -576,19 +713,24 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) || target == 0 // To everyone || consoleplayer == target-1) // To you { - const char *cstart = "", *cend = "", *adminchar = "~", *remotechar = "@", *fmt; + const char *prefix = "", *cstart = "", *cend = "", *adminchar = "\x82~\x83", *remotechar = "\x82@\x83", *fmt, *fmt2; char *tempchar = NULL; // In CTF and team match, color the player's name. if (G_GametypeHasTeams()) { - cend = "\x80"; + cend = ""; if (players[playernum].ctfteam == 1) // red cstart = "\x85"; else if (players[playernum].ctfteam == 2) // blue cstart = "\x84"; + } + // player is a spectator? + if (players[playernum].spectator) + cstart = "\x86"; // grey name + // Give admins and remote admins their symbols. if (playernum == serverplayer) tempchar = (char *)Z_Calloc(strlen(cstart) + strlen(adminchar) + 1, PU_STATIC, NULL); @@ -596,11 +738,11 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) tempchar = (char *)Z_Calloc(strlen(cstart) + strlen(remotechar) + 1, PU_STATIC, NULL); if (tempchar) { - strcat(tempchar, cstart); if (playernum == serverplayer) strcat(tempchar, adminchar); else strcat(tempchar, remotechar); + strcat(tempchar, cstart); cstart = tempchar; } @@ -609,21 +751,55 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) // name, color end, and the message itself. // '\4' makes the message yellow and beeps; '\3' just beeps. if (action) - fmt = "\4* %s%s%s \x82%s\n"; + { + fmt = "\3* %s%s%s%s \x82%s\n"; // don't make /me yellow, yellow will be for mentions and PMs! + fmt2 = "* %s%s%s%s \x82%s"; + } else if (target == 0) // To everyone - fmt = "\3<%s%s%s> %s\n"; + { + fmt = "\3%s\x83<%s%s%s\x83>\x80 %s\n"; + fmt2 = "%s\x83<%s%s%s\x83>\x80 %s"; + } else if (target-1 == consoleplayer) // To you - fmt = "\3*%s%s%s* %s\n"; + { + prefix = "\x82[PM]"; + cstart = "\x82"; + fmt = "\4%s<%s%s>%s\x80 %s\n"; // make this yellow, however. + fmt2 = "%s<%s%s>%s\x80 %s"; + } else if (target > 0) // By you, to another player { // Use target's name. dispname = player_names[target-1]; - fmt = "\3->*%s%s%s* %s\n"; + /*fmt = "\3\x82[TO]\x80%s%s%s* %s\n"; + fmt2 = "\x82[TO]\x80%s%s%s* %s";*/ + prefix = "\x82[TO]"; + cstart = "\x82"; + fmt = "\4%s<%s%s>%s\x80 %s\n"; // make this yellow, however. + fmt2 = "%s<%s%s>%s\x80 %s"; + } else // To your team - fmt = "\3>>%s%s%s<< (team) %s\n"; + { + if (players[playernum].ctfteam == 1) // red + prefix = "\x85[TEAM]"; + else if (players[playernum].ctfteam == 2) // blue + prefix = "\x84[TEAM]"; + else + prefix = "\x83"; // makes sure this doesn't implode if you sayteam on non-team gamemodes + + fmt = "\3%s<%s%s>\x80%s %s\n"; + fmt2 = "%s<%s%s>\x80%s %s"; + + } + + HU_AddChatText(va(fmt2, prefix, cstart, dispname, cend, msg)); // add it reguardless, in case we decide to change our mind about our chat type. + + if OLDCHAT + CONS_Printf(fmt, prefix, cstart, dispname, cend, msg); + else + CON_LogMessage(va(fmt, prefix, cstart, dispname, cend, msg)); // save to log.txt - CONS_Printf(fmt, cstart, dispname, cend, msg); if (tempchar) Z_Free(tempchar); } @@ -650,19 +826,48 @@ static inline boolean HU_keyInChatString(char *s, char ch) l = strlen(s); if (l < HU_MAXMSGLEN - 1) { - s[l++] = ch; - s[l]=0; + if (c_input >= strlen(s)) // don't do anything complicated + { + s[l++] = ch; + s[l]=0; + } + else + { + + // move everything past c_input for new characters: + UINT32 m = HU_MAXMSGLEN-1; + for (;(m>=c_input);m--) + { + if (s[m]) + s[m+1] = (s[m]); + } + s[c_input] = ch; // and replace this. + } + c_input++; return true; } return false; } else if (ch == KEY_BACKSPACE) { - l = strlen(s); - if (l) - s[--l] = 0; - else + if (c_input <= 0) return false; + size_t i = c_input; + if (!s[i-1]) + return false; + + if (i >= strlen(s)-1) + { + s[strlen(s)-1] = 0; + c_input--; + return false; + } + + for (; (i < HU_MAXMSGLEN); i++) + { + s[i-1] = s[i]; + } + c_input--; } else if (ch != KEY_ENTER) return false; // did not eat key @@ -686,95 +891,125 @@ void HU_Ticker(void) hu_showscores = false; } -#define QUEUESIZE 256 static boolean teamtalk = false; -static char chatchars[QUEUESIZE]; -static INT32 head = 0, tail = 0; - -// -// HU_dequeueChatChar -// -char HU_dequeueChatChar(void) -{ - char c; - - if (head != tail) - { - c = chatchars[tail]; - tail = (tail + 1) & (QUEUESIZE-1); - } - else - c = 0; - - return c; -} +// WHY DO YOU OVERCOMPLICATE EVERYTHING????????? // // -static void HU_queueChatChar(char c) +static void HU_queueChatChar(INT32 c) { // send automaticly the message (no more chat char) if (c == KEY_ENTER) { char buf[2+256]; size_t ci = 2; - + char *msg = &buf[2]; do { - c = HU_dequeueChatChar(); + c = w_chat[-2+ci++]; if (!c || (c >= ' ' && !(c & 0x80))) // copy printable characters and terminating '\0' only. - buf[ci++]=c; + buf[ci-1]=c; } while (c); + size_t i = 0; + for (;(iERROR: The chat is muted. You can't say anything.", "\x85")); return; } + INT32 target = 0; + + if (strlen(msg) > 4 && strnicmp(msg, "/pm", 3) == 0) // used /pm + { + // what we're gonna do now is check if the node exists + // with that logic, characters 4 and 5 are our numbers: + + // teamtalk can't send PMs, just don't send it, else everyone would be able to see it, and no one wants to see your sex RP sicko. + if (teamtalk) + { + HU_AddChatText(va("%sCannot send sayto in Say-Team.", "\x85")); + return; + } + + int spc = 1; // used if nodenum[1] is a space. + char *nodenum = (char*) malloc(3); + strncpy(nodenum, msg+3, 5); + // check for undesirable characters in our "number" + if (((nodenum[0] < '0') || (nodenum[0] > '9')) || ((nodenum[1] < '0') || (nodenum[1] > '9'))) + { + // check if nodenum[1] is a space + if (nodenum[1] == ' ') + spc = 0; + // let it slide + else + { + HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm \'."); + return; + } + } + // I'm very bad at C, I swear I am, additional checks eww! + if (spc != 0) + { + if (msg[5] != ' ') + { + HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm \'."); + return; + } + } + + target = atoi((const char*) nodenum); // turn that into a number + //CONS_Printf("%d\n", target); + + // check for target player, if it doesn't exist then we can't send the message! + if (playeringame[target]) // player exists + target++; // even though playernums are from 0 to 31, target is 1 to 32, so up that by 1 to have it work! + else + { + HU_AddChatText(va("\x82NOTICE: \x80Player %d does not exist.", target)); // same + return; + } + // we need to get rid of the /pm + const char *newmsg = msg+5+spc; + memcpy(msg, newmsg, 255); + } if (ci > 3) // don't send target+flags+empty message. { if (teamtalk) buf[0] = -1; // target else - buf[0] = 0; // target + buf[0] = target; + buf[1] = 0; // flags SendNetXCmd(XD_SAY, buf, 2 + strlen(&buf[2]) + 1); } return; } - - if (((head + 1) & (QUEUESIZE-1)) == tail) - CONS_Printf(M_GetText("[Message unsent]\n")); // message not sent - else - { - if (c == KEY_BACKSPACE) - { - if (tail != head) - head = (head - 1) & (QUEUESIZE-1); - } - else - { - chatchars[head] = c; - head = (head + 1) & (QUEUESIZE-1); - } - } } void HU_clearChatChars(void) { - while (tail != head) - HU_queueChatChar(KEY_BACKSPACE); + size_t i = 0; + for (;itype != ev_keydown) return false; @@ -785,13 +1020,14 @@ boolean HU_Responder(event_t *ev) { // enter chat mode if ((ev->data1 == gamecontrol[gc_talkkey][0] || ev->data1 == gamecontrol[gc_talkkey][1]) - && netgame && (!cv_mute.value || server || IsPlayerAdmin(consoleplayer))) + && netgame && (!cv_mute.value || server || (IsPlayerAdmin(consoleplayer)))) { if (cv_mute.value && !(server || IsPlayerAdmin(consoleplayer))) return false; chat_on = true; w_chat[0] = 0; teamtalk = false; + chat_scrollmedown = true; return true; } if ((ev->data1 == gamecontrol[gc_teamkey][0] || ev->data1 == gamecontrol[gc_teamkey][1]) @@ -802,11 +1038,13 @@ boolean HU_Responder(event_t *ev) chat_on = true; w_chat[0] = 0; teamtalk = true; + chat_scrollmedown = true; return true; } } else // if chat_on { + // Ignore modifier keys // Note that we do this here so users can still set // their chat keys to one of these, if they so desire. @@ -815,19 +1053,96 @@ boolean HU_Responder(event_t *ev) || ev->data1 == KEY_LALT || ev->data1 == KEY_RALT) return true; - c = (UINT8)ev->data1; + c = (INT32)ev->data1; + + // capslock + if (c && c == KEY_CAPSLOCK) // it's a toggle. + { + if (capslock) + capslock = false; + else + capslock = true; + return true; + } // use console translations - if (shiftdown) + if (shiftdown ^ capslock) c = shiftxform[c]; - if (HU_keyInChatString(w_chat,c)) - HU_queueChatChar(c); - if (c == KEY_ENTER) - chat_on = false; - else if (c == KEY_ESCAPE) - chat_on = false; + // TODO: make chat behave like the console, so that we can go back and edit stuff when we fuck up. + // pasting. pasting is cool. chat is a bit limited, though :( + if ((c == 'v' || c == 'V') && ctrldown) + { + const char *paste = I_ClipboardPaste(); + + // create a dummy string real quickly + + if (paste == NULL) + return true; + + size_t chatlen = strlen(w_chat); + size_t pastelen = strlen(paste); + if (chatlen+pastelen > HU_MAXMSGLEN) + return true; // we can't paste this!! + + if (c_input >= strlen(w_chat)) // add it at the end of the string. + { + memcpy(&w_chat[chatlen], paste, pastelen); // copy all of that. + c_input += pastelen; + /*size_t i = 0; + for (;i=c_input;i--) + { + if (w_chat[i]) + w_chat[i+pastelen] = w_chat[i]; + + } + memcpy(&w_chat[c_input], paste, pastelen); // copy all of that. + c_input += pastelen; + return true; + } + } + + if (HU_keyInChatString(w_chat,c)) + { + HU_queueChatChar(c); + } + if (c == KEY_ENTER) + { + chat_on = false; + c_input = 0; // reset input cursor + chat_scrollmedown = true; // you hit enter, so you might wanna autoscroll to see what you just sent. :) + } + else if (c == KEY_ESCAPE) + { + chat_on = false; + c_input = 0; // reset input cursor + } + else if ((c == KEY_UPARROW || c == KEY_MOUSEWHEELUP) && chat_scroll > 0) // CHAT SCROLLING YAYS! + { + chat_scroll--; + justscrolledup = true; + chat_scrolltime = 4; + } + else if ((c == KEY_DOWNARROW || c == KEY_MOUSEWHEELDOWN) && chat_scroll < chat_maxscroll && chat_maxscroll > 0) + { + chat_scroll++; + justscrolleddown = true; + chat_scrolltime = 4; + } + else if (c == KEY_LEFTARROW && c_input != 0) // i said go back + c_input--; + else if (c == KEY_RIGHTARROW && c_input < strlen(w_chat)) + c_input++; return true; } return false; @@ -837,12 +1152,496 @@ boolean HU_Responder(event_t *ev) // HEADS UP DRAWING //====================================================================== +// Gets string colormap, used for 0x80 color codes +// +static UINT8 *CHAT_GetStringColormap(INT32 colorflags) // pasted from video.c, sorry for the mess. +{ + switch ((colorflags & V_CHARCOLORMASK) >> V_CHARCOLORSHIFT) + { + case 1: // 0x81, purple + return purplemap; + case 2: // 0x82, yellow + return yellowmap; + case 3: // 0x83, lgreen + return greenmap; + case 4: // 0x84, blue + return bluemap; + case 5: // 0x85, red + return redmap; + case 6: // 0x86, gray + return graymap; + case 7: // 0x87, orange + return orangemap; + case 8: // 0x88, sky + return skymap; + default: // reset + return NULL; + } +} + +// Precompile a wordwrapped string to any given width. +// This is a muuuch better method than V_WORDWRAP. +// again stolen and modified a bit from video.c, don't mind me, will need to rearrange this one day. +// this one is simplified for the chat drawer. +static char *CHAT_WordWrap(INT32 x, INT32 w, INT32 option, const char *string) +{ + int c; + size_t chw, i, lastusablespace = 0; + size_t slen; + char *newstring = Z_StrDup(string); + INT32 charwidth = 4; + + slen = strlen(string); + x = 0; + + for (i = 0; i < slen; ++i) + { + c = newstring[i]; + if ((UINT8)c >= 0x80 && (UINT8)c <= 0x89) //color parsing! -Inuyasha 2.16.09 + continue; + + if (c == '\n') + { + x = 0; + lastusablespace = 0; + continue; + } + + if (!(option & V_ALLOWLOWERCASE)) + c = toupper(c); + c -= HU_FONTSTART; + + if (c < 0 || c >= HU_FONTSIZE || !hu_font[c]) + { + chw = charwidth; + lastusablespace = i; + } + else + chw = charwidth; + + x += chw; + + if (lastusablespace != 0 && x > w) + { + //CONS_Printf("Wrap at index %d\n", i); + newstring[lastusablespace] = '\n'; + i = lastusablespace+1; + lastusablespace = 0; + x = 0; + } + } + return newstring; +} + +// 30/7/18: chaty is now the distance at which the lowest point of the chat will be drawn if that makes any sense. + +INT16 chatx = 13, chaty = 169; // let's use this as our coordinates, shh + +// chat stuff by VincyTM LOL XD! + +// HU_DrawMiniChat + +static void HU_drawMiniChat(void) +{ + if (!chat_nummsg_min) + return; // needless to say it's useless to do anything if we don't have anything to draw. + + INT32 x = chatx+2; + INT32 charwidth = 4, charheight = 6; + INT32 dx = 0, dy = 0; + size_t i = chat_nummsg_min; + boolean prev_linereturn = false; // a hack to prevent double \n while I have no idea why they happen in the first place. + + INT32 msglines = 0; + // process all messages once without rendering anything or doing anything fancy so that we know how many lines each message has... + + for (; i>0; i--) + { + const char *msg = CHAT_WordWrap(x+2, cv_chatwidth.value-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_mini[i-1]); + size_t j = 0; + INT32 linescount = 0; + + while(msg[j]) // iterate through msg + { + if (msg[j] < HU_FONTSTART) // don't draw + { + if (msg[j] == '\n') // get back down. + { + ++j; + if (!prev_linereturn) + { + linescount += 1; + dx = 0; + } + prev_linereturn = true; + continue; + } + else if (msg[j] & 0x80) // stolen from video.c, nice. + { + ++j; + continue; + } + + ++j; + } + else + { + j++; + } + prev_linereturn = false; + dx += charwidth; + if (dx >= cv_chatwidth.value) + { + dx = 0; + linescount += 1; + } + } + dy = 0; + dx = 0; + msglines += linescount+1; + } + + INT32 y = chaty - charheight*(msglines+1) - (cv_kartspeedometer.value ? 16 : 0); + dx = 0; + dy = 0; + i = 0; + prev_linereturn = false; + + for (; i<=(chat_nummsg_min-1); i++) // iterate through our hot messages + { + INT32 clrflag = 0; + INT32 timer = ((cv_chattime.value*TICRATE)-chat_timers[i]) - cv_chattime.value*TICRATE+9; // see below... + INT32 transflag = (timer >= 0 && timer <= 9) ? (timer*V_10TRANS) : 0; // you can make bad jokes out of this one. + size_t j = 0; + const char *msg = CHAT_WordWrap(x+2, cv_chatwidth.value-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_mini[i]); // get the current message, and word wrap it. + + while(msg[j]) // iterate through msg + { + if (msg[j] < HU_FONTSTART) // don't draw + { + if (msg[j] == '\n') // get back down. + { + ++j; + if (!prev_linereturn) + { + dy += charheight; + dx = 0; + } + prev_linereturn = true; + continue; + } + else if (msg[j] & 0x80) // stolen from video.c, nice. + { + clrflag = ((msg[j] & 0x7f) << V_CHARCOLORSHIFT) & V_CHARCOLORMASK; + ++j; + continue; + } + + ++j; + } + else + { + UINT8 *colormap = CHAT_GetStringColormap(clrflag); + + if (cv_chatbacktint.value) // on request of wolfy + V_DrawFillConsoleMap(x + dx + 2, y+dy, charwidth, charheight, 239|V_SNAPTOBOTTOM|V_SNAPTOLEFT); + + V_DrawChatCharacter(x + dx + 2, y+dy, msg[j++] |V_SNAPTOBOTTOM|V_SNAPTOLEFT|transflag, !cv_allcaps.value, colormap); + } + + dx += charwidth; + prev_linereturn = false; + if (dx >= cv_chatwidth.value) + { + dx = 0; + dy += charheight; + } + } + dy += charheight; + dx = 0; + } + + // decrement addy and make that shit smooth: + addy /= 2; + +} + +// HU_DrawUpArrow +// You see, we don't have arrow graphics in 2.1 and I'm too lazy to include a 2 bytes file for it. + +static void HU_DrawUpArrow(INT32 x, INT32 y, INT32 options) +{ + // Ok I'm super lazy so let's make this as the worst draw function: + V_DrawFill(x+2, y, 1, 1, 103|options); + V_DrawFill(x+1, y+1, 3, 1, 103|options); + V_DrawFill(x, y+2, 5, 1, 103|options); // that's the yellow part, I swear + + V_DrawFill(x+3, y, 1, 1, 26|options); + V_DrawFill(x+4, y+1, 1, 1, 26|options); + V_DrawFill(x+5, y+2, 1, 1, 26|options); + V_DrawFill(x, y+3, 6, 1, 26|options); // that's the black part. no racism intended. i swear. +} + +// HU_DrawDownArrow +// Should we talk about anime waifus to pass the time? This feels retarded. + +static void HU_DrawDownArrow(INT32 x, INT32 y, INT32 options) +{ + // Ok I'm super lazy so let's make this as the worst draw function: + V_DrawFill(x, y, 6, 1, 26|options); + V_DrawFill(x, y+1, 5, 1, 26|options); + V_DrawFill(x+1, y+2, 3, 1, 26|options); + V_DrawFill(x+2, y+3, 1, 1, 26|options); // that's the black part. no racism intended. i swear. + + V_DrawFill(x, y, 5, 1, 103|options); + V_DrawFill(x+1, y+1, 3, 1, 103|options); + V_DrawFill(x+2, y+2, 1, 1, 103|options); // that's the yellow part, I swear +} + +// HU_DrawChatLog +// TODO: fix dumb word wrapping issues + +static void HU_drawChatLog(INT32 offset) +{ + + // before we do anything, make sure that our scroll position isn't "illegal"; + if (chat_scroll > chat_maxscroll) + chat_scroll = chat_maxscroll; + + INT32 charwidth = 4, charheight = 6; + INT32 x = chatx+2, y = chaty - offset*charheight - (chat_scroll*charheight) - cv_chatheight.value*charheight - 12 - (cv_kartspeedometer.value ? 16 : 0), dx = 0, dy = 0; + UINT32 i = 0; + INT32 chat_topy = y + chat_scroll*charheight; + INT32 chat_bottomy = chat_topy + cv_chatheight.value*charheight; + boolean atbottom = false; + + V_DrawFillConsoleMap(chatx, chat_topy, cv_chatwidth.value, cv_chatheight.value*charheight +2, 239|V_SNAPTOBOTTOM|V_SNAPTOLEFT); // log box + + for (i=0; i= chat_topy) && (y+dy < (chat_bottomy))) + { + UINT8 *colormap = CHAT_GetStringColormap(clrflag); + V_DrawChatCharacter(x + dx + 2, y+dy+2, msg[j++] |V_SNAPTOBOTTOM|V_SNAPTOLEFT, !cv_allcaps.value, colormap); + } + else + j++; // don't forget to increment this or we'll get stuck in the limbo. + } + + dx += charwidth; + if (dx >= cv_chatwidth.value-charwidth-2 && i= HU_FONTSTART) // end of message shouldn't count, nor should invisible characters!!!! + { + dx = 0; + dy += charheight; + } + } + dy += charheight; + dx = 0; + } + + if (((chat_scroll >= chat_maxscroll) || (chat_scrollmedown)) && !(justscrolleddown || justscrolledup || chat_scrolltime)) // was already at the bottom of the page before new maxscroll calculation and was NOT scrolling. + { + atbottom = true; // we should scroll + } + chat_scrollmedown = false; + + // getmaxscroll through a lazy hack. We do all these loops, so let's not do more loops that are gonna lag the game more. :P + chat_maxscroll = (dy/charheight); // welcome to C, we don't know what min() and max() are. + if (chat_maxscroll <= (UINT32)cv_chatheight.value) + chat_maxscroll = 0; + else + chat_maxscroll -= cv_chatheight.value; + + // if we're not bound by the time, autoscroll for next frame: + if (atbottom) + chat_scroll = chat_maxscroll; + + // draw arrows to indicate that we can (or not) scroll. + + if (chat_scroll > 0) + HU_DrawUpArrow(chatx-8, ((justscrolledup) ? (chat_topy-1) : (chat_topy)), V_SNAPTOBOTTOM | V_SNAPTOLEFT); + if (chat_scroll < chat_maxscroll) + HU_DrawDownArrow(chatx-8, chat_bottomy-((justscrolleddown) ? 3 : 4), V_SNAPTOBOTTOM | V_SNAPTOLEFT); + + justscrolleddown = false; + justscrolledup = false; +} + // // HU_DrawChat // // Draw chat input // + +static INT16 typelines = 1; // number of drawfill lines we need. it's some weird hack and might be one frame off but I'm lazy to make another loop. static void HU_DrawChat(void) +{ + INT32 charwidth = 4, charheight = 6; + INT32 t = 0, c = 0, y = chaty - (typelines*charheight) - (cv_kartspeedometer.value ? 16 : 0); + UINT32 i = 0; + const char *ntalk = "Say: ", *ttalk = "Team: "; + const char *talk = ntalk; + + if (teamtalk) + { + talk = ttalk; +#if 0 + if (players[consoleplayer].ctfteam == 1) + t = 0x500; // Red + else if (players[consoleplayer].ctfteam == 2) + t = 0x400; // Blue +#endif + } + + V_DrawFillConsoleMap(chatx, y-1, cv_chatwidth.value, (typelines*charheight), 239 | V_SNAPTOBOTTOM | V_SNAPTOLEFT); + + while (talk[i]) + { + if (talk[i] < HU_FONTSTART) + ++i; + else + V_DrawChatCharacter(chatx + c + 2, y, talk[i++] |V_SNAPTOBOTTOM|V_SNAPTOLEFT, !cv_allcaps.value, NULL); + + c += charwidth; + } + + i = 0; + typelines = 1; + + if ((strlen(w_chat) == 0 || c_input == 0) && hu_tick < 4) + V_DrawChatCharacter(chatx + 2 + c, y+1, '_' |V_SNAPTOBOTTOM|V_SNAPTOLEFT|t, !cv_allcaps.value, NULL); + + while (w_chat[i]) + { + boolean skippedline = false; + if (c_input == (i+1)) + { + int cursorx = (c+charwidth < cv_chatwidth.value-charwidth) ? (chatx + 2 + c+charwidth) : (chatx+1); // we may have to go down. + int cursory = (cursorx != chatx+1) ? (y) : (y+charheight); + if (hu_tick < 4) + V_DrawChatCharacter(cursorx, cursory+1, '_' |V_SNAPTOBOTTOM|V_SNAPTOLEFT|t, !cv_allcaps.value, NULL); + + if (cursorx == chatx+1) // a weirdo hack + { + typelines += 1; + skippedline = true; + } + + } + + //Hurdler: isn't it better like that? + if (w_chat[i] < HU_FONTSTART) + ++i; + else + V_DrawChatCharacter(chatx + c + 2, y, w_chat[i++] | V_SNAPTOBOTTOM|V_SNAPTOLEFT | t, !cv_allcaps.value, NULL); + + c += charwidth; + if (c > cv_chatwidth.value-(charwidth*2) && !skippedline) + { + c = 0; + y += charheight; + typelines += 1; + } + } + + // handle /pm list. + if (strnicmp(w_chat, "/pm", 3) == 0 && vid.width >= 400 && !teamtalk) // 320x200 unsupported kthxbai + { + i = 0; + INT32 count = 0; + INT32 p_dispy = chaty - charheight -1; + for(i=0; (i '9'))) || ((w_chat[4] != 0) && (((w_chat[4] < '0') || (w_chat[4] > '9'))))) && (w_chat[4] != ' ')) + break; + + + char *nodenum = (char*) malloc(3); + strncpy(nodenum, w_chat+3, 4); + UINT32 n = atoi((const char*) nodenum); // turn that into a number + // special cases: + + if ((n == 0) && !(w_chat[4] == '0')) + { + if (!(i<10)) + continue; + } + else if ((n == 1) && !(w_chat[3] == '0')) + { + if (!((i == 1) || ((i >= 10) && (i <= 19)))) + continue; + } + else if ((n == 2) && !(w_chat[3] == '0')) + { + if (!((i == 2) || ((i >= 20) && (i <= 29)))) + continue; + } + else if ((n == 3) && !(w_chat[3] == '0')) + { + if (!((i == 3) || ((i >= 30) && (i <= 31)))) + continue; + } + else // general case. + { + if (i != n) + continue; + } + } + + if (playeringame[i]) + { + char name[MAXPLAYERNAME+1]; + strlcpy(name, player_names[i], 7); // shorten name to 7 characters. + V_DrawFillConsoleMap(chatx+ cv_chatwidth.value + 2, p_dispy- (6*count), 48, 6, 239 | V_SNAPTOBOTTOM | V_SNAPTOLEFT); // fill it like the chat so the text doesn't become hard to read because of the hud. + V_DrawSmallString(chatx+ cv_chatwidth.value + 4, p_dispy- (6*count), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, va("\x82%d\x80 - %s", i, name)); + count++; + } + } + if (count == 0) // no results. + { + V_DrawFillConsoleMap(chatx-50, p_dispy- (6*count), 48, 6, 239 | V_SNAPTOBOTTOM | V_SNAPTOLEFT); // fill it like the chat so the text doesn't become hard to read because of the hud. + V_DrawSmallString(chatx-48, p_dispy- (6*count), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, "NO RESULT."); + } + } + + HU_drawChatLog(typelines-1); // typelines is the # of lines we're typing. If there's more than 1 then the log should scroll up to give us more space. + +} + +// why the fuck would you use this... + +static void HU_DrawChat_Old(void) { INT32 t = 0, c = 0, y = HU_INPUTY; size_t i = 0; @@ -850,7 +1649,6 @@ static void HU_DrawChat(void) const char *talk = ntalk; INT32 charwidth = 8 * con_scalefactor; //SHORT(hu_font['A'-HU_FONTSTART]->width) * con_scalefactor; INT32 charheight = 8 * con_scalefactor; //SHORT(hu_font['A'-HU_FONTSTART]->height) * con_scalefactor; - if (teamtalk) { talk = ttalk; @@ -877,9 +1675,20 @@ static void HU_DrawChat(void) c += charwidth; } + if ((strlen(w_chat) == 0 || c_input == 0) && hu_tick < 4) + V_DrawCharacter(HU_INPUTX+c, y+2*con_scalefactor, '_' |cv_constextsize.value | V_NOSCALESTART|t, !cv_allcaps.value); + i = 0; while (w_chat[i]) { + + if (c_input == (i+1) && hu_tick < 4) + { + int cursorx = (HU_INPUTX+c+charwidth < vid.width) ? (HU_INPUTX + c + charwidth) : (HU_INPUTX); // we may have to go down. + int cursory = (cursorx != HU_INPUTX) ? (y) : (y+charheight); + V_DrawCharacter(cursorx, cursory+2*con_scalefactor, '_' |cv_constextsize.value | V_NOSCALESTART|t, !cv_allcaps.value); + } + //Hurdler: isn't it better like that? if (w_chat[i] < HU_FONTSTART) { @@ -899,12 +1708,8 @@ static void HU_DrawChat(void) y += charheight; } } - - if (hu_tick < 4) - V_DrawCharacter(HU_INPUTX + c, y, '_' | cv_constextsize.value |V_NOSCALESTART|t, !cv_allcaps.value); } - // draw the Crosshair, at the exact center of the view. // // Crosshairs are pre-cached at HU_Init @@ -1121,23 +1926,6 @@ static void HU_DrawCEcho(void) --cechotimer; } -static void HU_drawGametype(void) -{ - INT32 i = 0; - - for (i = 0; gametype_cons_t[i].strvalue; i++) - { - if (gametype_cons_t[i].value == gametype) - { - if (splitscreen) - V_DrawString(4, 184, 0, gametype_cons_t[i].strvalue); - else - V_DrawString(4, 192, 0, gametype_cons_t[i].strvalue); - return; - } - } -} - // // demo info stuff // @@ -1175,7 +1963,43 @@ void HU_Drawer(void) { // draw chat string plus cursor if (chat_on) - HU_DrawChat(); + { + // count down the scroll timer. + if (chat_scrolltime > 0) + chat_scrolltime--; + if (!OLDCHAT) + HU_DrawChat(); + else + HU_DrawChat_Old(); // why the fuck......................... + } + else + { + chat_scrolltime = 0; // do scroll anyway. + typelines = 1; // make sure that the chat doesn't have a weird blinking huge ass square if we typed a lot last time. + if (!OLDCHAT) + HU_drawMiniChat(); // draw messages in a cool fashion. + } + + if (netgame) // would handle that in hu_drawminichat, but it's actually kinda awkward when you're typing a lot of messages. (only handle that in netgames duh) + { + size_t i = 0; + + // handle spam while we're at it: + for(; (i 0) + stop_spamming_you_cunt[i]--; + } + + // handle chat timers + for (i=0; (i 0) + chat_timers[i]--; + else + HU_removeChatText_Mini(); + } + } if (cechotimer) HU_DrawCEcho(); @@ -1187,7 +2011,7 @@ void HU_Drawer(void) || gamestate == GS_INTERMISSION || gamestate == GS_CUTSCENE || gamestate == GS_CREDITS || gamestate == GS_EVALUATION || gamestate == GS_GAMEEND - || gamestate == GS_VOTING) // SRB2kart + || gamestate == GS_VOTING || gamestate == GS_WAITINGPLAYERS) // SRB2kart return; // draw multiplayer rankings @@ -1220,7 +2044,7 @@ void HU_Drawer(void) if (cv_crosshair2.value && !camera2.chase && !players[secondarydisplayplayer].spectator) HU_DrawCrosshair2(); - + if (cv_crosshair3.value && !camera3.chase && !players[thirddisplayplayer].spectator) HU_DrawCrosshair3(); @@ -1319,113 +2143,142 @@ void HU_Erase(void) // IN-LEVEL MULTIPLAYER RANKINGS //====================================================================== +// +// HU_drawPing +// +void HU_drawPing(INT32 x, INT32 y, INT32 ping, boolean notext) +{ + UINT8 numbars = 1; // how many ping bars do we draw? + UINT8 barcolor = 128; // color we use for the bars (green, yellow or red) + SINT8 i = 0; + SINT8 yoffset = 6; + if (ping < 128) + { + numbars = 3; + barcolor = 184; + } + else if (ping < 256) + { + numbars = 2; // Apparently ternaries w/ multiple statements don't look good in C so I decided against it. + barcolor = 103; + } + + INT32 dx = x+1 - (V_SmallStringWidth(va("%dms", ping), V_ALLOWLOWERCASE)/2); + if (!notext || vid.width >= 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; + } +} + // // HU_DrawTabRankings // -void HU_DrawTabRankings(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) { - INT32 i; + INT32 i, j, rightoffset = 240; const UINT8 *colormap; //this function is designed for 9 or less score lines only - I_Assert(scorelines <= 9); + //I_Assert(scorelines <= 9); -- not today bitch, kart fixed it up - V_DrawFill(1, 26, 318, 1, 0); //Draw a horizontal line because it looks nice! + V_DrawFill(1, 26, 318, 1, 0); // Draw a horizontal line because it looks nice! + if (scorelines > 8) + { + V_DrawFill(160, 26, 1, 154, 0); // Draw a vertical line to separate the two sides. + V_DrawFill(1, 180, 318, 1, 0); // And a horizontal line near the bottom. + rightoffset = 156; + } for (i = 0; i < scorelines; i++) { - if (players[tab[i].num].spectator) + char strtime[MAXPLAYERNAME+1]; + + if (players[tab[i].num].spectator || !players[tab[i].num].mo) continue; //ignore them. + if (!splitscreen) // don't draw it on splitscreen, + { + if (!(tab[i].num == serverplayer)) + HU_drawPing(x+ 253, y+2, playerpingtable[tab[i].num], false); + } + + if (scorelines > 8) + strlcpy(strtime, tab[i].name, 6); + else + STRBUFCPY(strtime, tab[i].name); + V_DrawString(x + 20, y, - ((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0) - | ((players[tab[i].num].health > 0) ? 0 : V_60TRANS) - | V_ALLOWLOWERCASE, tab[i].name); + ((tab[i].num == whiteplayer) + ? hilicol|V_ALLOWLOWERCASE + : V_ALLOWLOWERCASE), + strtime); - // Draw emeralds - if (!players[tab[i].num].powers[pw_super] - || ((leveltime/7) & 1)) + if (players[tab[i].num].mo->color) { - HU_DrawEmeralds(x-12,y+2,tab[i].emeralds); - } - - if (players[tab[i].num].health <= 0) - V_DrawSmallTranslucentPatch (x, y-4, V_80TRANS, livesback); - else - V_DrawSmallScaledPatch (x, y-4, 0, livesback); - - if (tab[i].color == 0) - { - colormap = colormaps; - if (players[tab[i].num].powers[pw_super]) - V_DrawSmallScaledPatch(x, y-4, 0, superprefix[players[tab[i].num].skin]); + colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo->color, GTC_CACHE); + if (players[tab[i].num].mo->colorized) + colormap = R_GetTranslationColormap(TC_RAINBOW, players[tab[i].num].mo->color, GTC_CACHE); else + colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo->color, GTC_CACHE); + + V_DrawSmallMappedPatch(x, y-4, 0, faceprefix[players[tab[i].num].skin], colormap); + if (G_BattleGametype() && players[tab[i].num].kartstuff[k_bumper] > 0) { - if (players[tab[i].num].health <= 0) - V_DrawSmallTranslucentPatch(x, y-4, V_80TRANS, faceprefix[players[tab[i].num].skin]); - else - V_DrawSmallScaledPatch(x, y-4, 0, faceprefix[players[tab[i].num].skin]); - } - } - else - { - if (players[tab[i].num].powers[pw_super]) - { - colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo ? players[tab[i].num].mo->color : tab[i].color, GTC_CACHE); - V_DrawSmallMappedPatch (x, y-4, 0, superprefix[players[tab[i].num].skin], colormap); - } - else - { - colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo ? players[tab[i].num].mo->color : tab[i].color, GTC_CACHE); - if (players[tab[i].num].health <= 0) - V_DrawSmallTranslucentMappedPatch (x, y-4, V_80TRANS, faceprefix[players[tab[i].num].skin], colormap); - else - V_DrawSmallMappedPatch (x, y-4, 0, faceprefix[players[tab[i].num].skin], colormap); + INT32 bumperx = x-5; + for (j = 0; j < players[tab[i].num].kartstuff[k_bumper]; j++) + { + bumperx -= 3; + V_DrawSmallMappedPatch(bumperx, y+6, 0, W_CachePatchName("K_BLNICO", PU_CACHE), colormap); + } } } - if (G_GametypeUsesLives()) //show lives - V_DrawRightAlignedString(x, y+4, V_ALLOWLOWERCASE|((players[tab[i].num].health > 0) ? 0 : V_60TRANS), va("%dx", players[tab[i].num].lives)); - else if (G_TagGametype() && players[tab[i].num].pflags & PF_TAGIT) - { - if (players[tab[i].num].health <= 0) - V_DrawSmallTranslucentPatch(x-32, y-4, V_60TRANS, tagico); - else - V_DrawSmallScaledPatch(x-32, y-4, 0, tagico); - } + if (G_BattleGametype() && players[tab[i].num].kartstuff[k_bumper] <= 0) + V_DrawSmallScaledPatch(x-2, y-4, 0, W_CachePatchName("K_NOBLNS", PU_CACHE)); if (G_RaceGametype()) { - if (circuitmap) +#define timestring(time) va("%i:%02i.%02i", G_TicsToMinutes(time, true), G_TicsToSeconds(time), G_TicsToCentiseconds(time)) + if (players[tab[i].num].exiting) { - if (players[tab[i].num].exiting) - V_DrawRightAlignedString(x+240, y, V_YELLOWMAP, va("%d:%02d.%02d", - players[tab[i].num].realtime/(60*TICRATE), - players[tab[i].num].realtime/TICRATE % 60, - players[tab[i].num].realtime % TICRATE)); - //V_DrawRightAlignedString(x+240, y, 0, va("%i:%02i.%02i", G_TicsToMinutes(players[tab[i].num].realtime,true), G_TicsToSeconds(players[tab[i].num].realtime), G_TicsToCentiseconds(players[tab[i].num].realtime))); - else - V_DrawRightAlignedString(x+240, y, 0, va("(CP%02d) %d:%02d.%02d", - tab[i].count, - players[tab[i].num].starposttime/(60*TICRATE), - players[tab[i].num].starposttime/TICRATE % 60, - (int)((players[tab[i].num].starposttime % TICRATE) * (100.00f/TICRATE)))); - //V_DrawRightAlignedString(x+240, y, ((players[tab[i].num].health > 0) ? 0 : V_60TRANS), va("%u", tab[i].count)); + V_DrawRightAlignedString(x, y-4, hilicol, "FIN"); + V_DrawRightAlignedString(x+rightoffset, y, hilicol, timestring(players[tab[i].num].realtime)); + } + else if (players[tab[i].num].pflags & PF_TIMEOVER) + V_DrawRightAlignedThinString(x+rightoffset, y-1, 0, "TIME OVER..."); + else if (circuitmap) + { + V_DrawRightAlignedString(x, y-4, 0, "Lap"); + V_DrawRightAlignedString(x, y+4, 0, va("%d", tab[i].count)); + V_DrawRightAlignedString(x+rightoffset, y, 0, timestring(players[tab[i].num].starposttime)); } else - V_DrawRightAlignedString(x+240, y, ((players[tab[i].num].health > 0) ? 0 : V_60TRANS), va("%i:%02i.%02i", G_TicsToMinutes(tab[i].count,true), G_TicsToSeconds(tab[i].count), G_TicsToCentiseconds(tab[i].count))); + V_DrawRightAlignedString(x+rightoffset, y, 0, timestring(tab[i].count)); +#undef timestring } else - V_DrawRightAlignedString(x+240, y, ((players[tab[i].num].health > 0) ? 0 : V_60TRANS), va("%u", tab[i].count)); + V_DrawRightAlignedString(x+rightoffset, y, 0, va("%u", tab[i].count)); y += 16; + if (i == 7) + { + y = 32; + x += BASEVIDWIDTH/2; + } } } // // HU_DrawTeamTabRankings // -void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer) +/*void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer) { INT32 i,x,y; INT32 redplayers = 0, blueplayers = 0; @@ -1493,6 +2346,11 @@ void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer) V_DrawSmallMappedPatch (x, y-4, 0, faceprefix[players[tab[i].num].skin], colormap); } V_DrawRightAlignedThinString(x+120, y-1, ((players[tab[i].num].health > 0) ? 0 : V_TRANSLUCENT), va("%u", tab[i].count)); + if (!splitscreen) + { + if (!(tab[i].num == serverplayer)) + HU_drawPing(x+ 113, y+2, playerpingtable[tab[i].num], false); + } } } @@ -1515,6 +2373,8 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline continue; //ignore them. strlcpy(name, tab[i].name, 9); + if (!(tab[i].num == serverplayer)) + HU_drawPing(x+ 113, y+2, playerpingtable[tab[i].num], false); V_DrawString(x + 20, y, ((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0) | ((players[tab[i].num].health > 0) ? 0 : V_TRANSLUCENT) @@ -1586,7 +2446,7 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline x += BASEVIDWIDTH/2; } } -} +}*/ // // HU_DrawEmeralds @@ -1682,12 +2542,22 @@ static void HU_DrawRankings(void) { patch_t *p; playersort_t tab[MAXPLAYERS]; - INT32 i, j, scorelines; + INT32 i, j, scorelines, hilicol, numplayersingame = 0; boolean completed[MAXPLAYERS]; - UINT32 whiteplayer; + UINT32 whiteplayer = MAXPLAYERS; + + if (cons_menuhighlight.value) + hilicol = cons_menuhighlight.value; + else if (modeattacking) + hilicol = V_ORANGEMAP; + else + hilicol = ((gametype == GT_RACE) ? V_SKYMAP : V_REDMAP); // draw the current gametype in the lower right - HU_drawGametype(); + if (modeattacking) + V_DrawString(4, 188, hilicol, "Record Attack"); + else + V_DrawString(4, 188, hilicol, gametype_cons_t[gametype].strvalue); if (G_GametypeHasTeams()) { @@ -1712,29 +2582,32 @@ static void HU_DrawRankings(void) { if (cv_timelimit.value && timelimitintics > 0) { - INT32 timeval = (timelimitintics+1-leveltime)/TICRATE; + UINT32 timeval = (timelimitintics + starttime + 1 - leveltime); + if (timeval > timelimitintics+1) + timeval = timelimitintics; + timeval /= TICRATE; - if (leveltime <= timelimitintics) + if (leveltime <= (timelimitintics + starttime)) { V_DrawCenteredString(64, 8, 0, "TIME LEFT"); - V_DrawCenteredString(64, 16, 0, va("%u", timeval)); + V_DrawCenteredString(64, 16, hilicol, va("%u", timeval)); } // overtime - if ((leveltime > (timelimitintics + TICRATE/2)) && cv_overtime.value) + if (!players[consoleplayer].exiting && (leveltime > (timelimitintics + starttime + TICRATE/2)) && cv_overtime.value) { V_DrawCenteredString(64, 8, 0, "TIME LEFT"); - V_DrawCenteredString(64, 16, 0, "OVERTIME"); + V_DrawCenteredString(64, 16, hilicol, "OVERTIME"); } } if (cv_pointlimit.value > 0) { V_DrawCenteredString(256, 8, 0, "POINT LIMIT"); - V_DrawCenteredString(256, 16, 0, va("%d", cv_pointlimit.value)); + V_DrawCenteredString(256, 16, hilicol, va("%d", cv_pointlimit.value)); } } - else if (gametype == GT_COOP) + /*else if (gametype == GT_COOP) { INT32 totalscore = 0; for (i = 0; i < MAXPLAYERS; i++) @@ -1745,19 +2618,23 @@ static void HU_DrawRankings(void) V_DrawCenteredString(256, 8, 0, "TOTAL SCORE"); V_DrawCenteredString(256, 16, 0, va("%u", totalscore)); - } + }*/ else { if (circuitmap) { - V_DrawCenteredString(64, 8, 0, "NUMBER OF LAPS"); - V_DrawCenteredString(64, 16, 0, va("%d", cv_numlaps.value)); + V_DrawCenteredString(64, 8, 0, "LAP COUNT"); + V_DrawCenteredString(64, 16, hilicol, va("%d", cv_numlaps.value)); } + + V_DrawCenteredString(256, 8, 0, "GAME SPEED"); + V_DrawCenteredString(256, 16, hilicol, cv_kartspeed.string); } // When you play, you quickly see your score because your name is displayed in white. // When playing back a demo, you quickly see who's the view. - whiteplayer = demoplayback ? displayplayer : consoleplayer; + if (!splitscreen) + whiteplayer = demoplayback ? displayplayer : consoleplayer; scorelines = 0; memset(completed, 0, sizeof (completed)); @@ -1766,83 +2643,63 @@ static void HU_DrawRankings(void) for (i = 0; i < MAXPLAYERS; i++) { tab[i].num = -1; - tab[i].name = 0; + tab[i].name = NULL; + tab[i].count = INT32_MAX; - if (G_RaceGametype() && !circuitmap) - tab[i].count = INT32_MAX; - } - - for (j = 0; j < MAXPLAYERS; j++) - { - if (!playeringame[j] || players[j].spectator) + if (!playeringame[i] || players[i].spectator) continue; - for (i = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i] && !players[i].spectator) - { - if (G_RaceGametype()) - { - if (circuitmap) - { - if ((unsigned)players[i].laps+1 >= tab[scorelines].count && completed[i] == false) - { - tab[scorelines].count = players[i].laps+1; - tab[scorelines].num = i; - tab[scorelines].color = players[i].skincolor; - tab[scorelines].name = player_names[i]; - } - } - else - { - if (players[i].realtime <= tab[scorelines].count && completed[i] == false) - { - tab[scorelines].count = players[i].realtime; - tab[scorelines].num = i; - tab[scorelines].color = players[i].skincolor; - tab[scorelines].name = player_names[i]; - } - } - } - else if (gametype == GT_COMPETITION) - { - // todo put something more fitting for the gametype here, such as current - // number of categories led - if (players[i].score >= tab[scorelines].count && completed[i] == false) - { - tab[scorelines].count = players[i].score; - tab[scorelines].num = i; - tab[scorelines].color = players[i].skincolor; - tab[scorelines].name = player_names[i]; - tab[scorelines].emeralds = players[i].powers[pw_emeralds]; - } - } - else - { - if (players[i].score >= tab[scorelines].count && completed[i] == false) - { - tab[scorelines].count = players[i].score; - tab[scorelines].num = i; - tab[scorelines].color = players[i].skincolor; - tab[scorelines].name = player_names[i]; - tab[scorelines].emeralds = players[i].powers[pw_emeralds]; - } - } - } - } - completed[tab[scorelines].num] = true; - scorelines++; + numplayersingame++; } - if (scorelines > 20) - scorelines = 20; //dont draw past bottom of screen, show the best only + if (netgame && numplayersingame <= 1) + K_drawKartFreePlay(leveltime); - if (G_GametypeHasTeams()) - HU_DrawTeamTabRankings(tab, whiteplayer); //separate function for Spazzo's silly request - else if (scorelines <= 9) - HU_DrawTabRankings(40, 32, tab, scorelines, whiteplayer); - else - HU_DrawDualTabRankings(32, 32, tab, scorelines, whiteplayer); + for (j = 0; j < numplayersingame; j++) + { + UINT8 lowestposition = MAXPLAYERS; + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i] || players[i].spectator || completed[i]) + continue; + + if (players[i].kartstuff[k_position] >= lowestposition) + continue; + + tab[scorelines].num = i; + lowestposition = players[i].kartstuff[k_position]; + } + + i = tab[scorelines].num; + + completed[i] = true; + + tab[scorelines].name = player_names[i]; + + if (G_RaceGametype()) + { + if (circuitmap) + tab[scorelines].count = players[i].laps+1; + else + tab[scorelines].count = players[i].realtime; + } + else + tab[scorelines].count = players[i].marescore; + + scorelines++; + +#if MAXPLAYERS > 16 + if (scorelines > 16) + break; //dont draw past bottom of screen, show the best only +#endif + } + + /*if (G_GametypeHasTeams()) + HU_DrawTeamTabRankings(tab, whiteplayer); //separate function for Spazzo's silly request -- gotta fix this up later + else if (scorelines > 10)*/ + HU_DrawTabRankings(((scorelines > 8) ? 32 : 40), 32, tab, scorelines, whiteplayer, hilicol); + /*else + HU_DrawDualTabRankings(32, 32, tab, scorelines, whiteplayer);*/ // draw spectators in a ticker across the bottom if (!splitscreen && G_GametypeHasSpectators()) diff --git a/src/hu_stuff.h b/src/hu_stuff.h index 08d69b8d..90ffeb42 100644 --- a/src/hu_stuff.h +++ b/src/hu_stuff.h @@ -21,7 +21,7 @@ //------------------------------------ // heads up font //------------------------------------ -#define HU_FONTSTART '\x1E' // the first font character +#define HU_FONTSTART '\x19' // the first font character #define HU_FONTEND '~' #define HU_FONTSIZE (HU_FONTEND - HU_FONTSTART + 1) @@ -55,8 +55,6 @@ typedef struct { UINT32 count; INT32 num; - INT32 color; - INT32 emeralds; const char *name; } playersort_t; @@ -80,6 +78,13 @@ extern patch_t *tagico; extern patch_t *tallminus; extern patch_t *iconprefix[MAXSKINS]; +#define CHAT_BUFSIZE 64 // that's enough messages, right? We'll delete the older ones when that gets out of hand. + +#define OLDCHAT (cv_consolechat.value || dedicated || vid.width < 640) + +// some functions +void HU_AddChatText(const char *text); + // set true when entering a chat message extern boolean chat_on; @@ -104,9 +109,12 @@ void HU_Drawer(void); char HU_dequeueChatChar(void); void HU_Erase(void); void HU_clearChatChars(void); -void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, INT32 whiteplayer); +void HU_drawPing(INT32 x, INT32 y, INT32 ping, boolean notext); // 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); +//void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer); +//void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, INT32 whiteplayer); void HU_DrawEmeralds(INT32 x, INT32 y, INT32 pemeralds); INT32 HU_CreateTeamScoresTbl(playersort_t *tab, UINT32 dmtotals[]); diff --git a/src/i_joy.h b/src/i_joy.h index 316011fc..00302eb0 100644 --- a/src/i_joy.h +++ b/src/i_joy.h @@ -50,7 +50,7 @@ struct JoyType_s }; typedef struct JoyType_s JoyType_t; /** \brief Joystick info - for palyer 1 and 2's joystick/gamepad + for palyer[sic] 1-4's joystick/gamepad */ extern JoyType_t Joystick, Joystick2, Joystick3, Joystick4; diff --git a/src/info.c b/src/info.c index 27383773..c642b67e 100644 --- a/src/info.c +++ b/src/info.c @@ -55,11 +55,12 @@ char sprnames[NUMSPRITES + 1][5] = "GWLR","SRBA","SRBB","SRBC","SRBD","SRBE","SRBF","SRBG","SRBH","SRBI", "SRBJ","SRBK","SRBL","SRBM","SRBN","SRBO", //SRB2kart Sprites - "SPRG","BSPR","RNDM","RPOP","KFRE","DRIF","DUST","FITM","DFAK","BANA", - "DBAN","GSHE","DGSH","RSHE","DRSH","BOMB","KRBM","BLIG","LIGH","SINK", - "SITR","KBLN","LAKI","POKE","AUDI","DECO","DOOD","SNES","GBAS","SPRS", - "BUZB","CHOM","SACO","CRAB","SHAD","BUMP","FLEN","CLAS","PSHW","ARRO", - "PBOM" + "SPRG","BSPR","RNDM","RPOP","KFRE","KINV","KINF","WIPD","DRIF","DUST", + "FITM","BANA","ORBN","JAWZ","SSMN","KRBM","BHOG","BHBM","BLIG","LIGH", + "THNS","SINK","SITR","KBLN","DEZL","POKE","AUDI","DECO","DOOD","SNES", + "GBAS","SPRS","BUZB","CHOM","SACO","CRAB","SHAD","BRNG","BUMP","FLEN", + "CLAS","PSHW","ISTA","ISTB","ARRO","ITEM","ITMO","ITMI","ITMN","WANT", + "PBOM","VIEW" }; // Doesn't work with g++, needs actionf_p1 (don't modify this comment) @@ -2125,19 +2126,13 @@ state_t states[NUMSTATES] = {SPR_FFWR, 3, 3, {NULL}, 0, 0, S_FIREFLOWER1}, // S_FIREFLOWER4 // Thrown Mario Fireball - {SPR_FBLL, FF_FULLBRIGHT, 3, {NULL}, MT_FIRETRAIL, 0, S_FIREBALL2}, // S_FIREBALL1 - {SPR_FBLL, FF_FULLBRIGHT|1, 3, {NULL}, MT_FIRETRAIL, 0, S_FIREBALL3}, // S_FIREBALL2 - {SPR_FBLL, FF_FULLBRIGHT|2, 3, {NULL}, MT_FIRETRAIL, 0, S_FIREBALL4}, // S_FIREBALL3 - {SPR_FBLL, FF_FULLBRIGHT|3, 3, {NULL}, MT_FIRETRAIL, 0, S_FIREBALL5}, // S_FIREBALL4 - {SPR_FBLL, FF_FULLBRIGHT|4, 3, {NULL}, MT_FIRETRAIL, 0, S_FIREBALL6}, // S_FIREBALL5 - {SPR_FBLL, FF_FULLBRIGHT|5, 3, {NULL}, MT_FIRETRAIL, 0, S_FIREBALL7}, // S_FIREBALL6 - {SPR_FBLL, FF_FULLBRIGHT|6, 3, {NULL}, MT_FIRETRAIL, 0, S_FIREBALL1}, // S_FIREBALL7 - {SPR_FBLL, FF_FULLBRIGHT|7, 3, {NULL}, 0, 0, S_FIREBALLEXP2}, // S_FIREBALLEXP1 - {SPR_FBLL, FF_FULLBRIGHT|8, 3, {NULL}, 0, 0, S_FIREBALLEXP3}, // S_FIREBALLEXP2 - {SPR_FBLL, FF_FULLBRIGHT|9, 3, {NULL}, 0, 0, S_FIREBALLEXP4}, // S_FIREBALLEXP3 - {SPR_FBLL, FF_FULLBRIGHT|10, 3, {NULL}, 0, 0, S_FIREBALLEXP5}, // S_FIREBALLEXP4 - {SPR_FBLL, FF_FULLBRIGHT|11, 3, {NULL}, 0, 0, S_FIREBALLEXP6}, // S_FIREBALLEXP5 - {SPR_FBLL, FF_FULLBRIGHT|12, 3, {NULL}, 0, 0, S_NULL}, // S_FIREBALLEXP6 + {SPR_FBLL, FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_FIREBALL2}, // S_FIREBALL1 + {SPR_FBLL, FF_FULLBRIGHT|1, 3, {NULL}, 0, 0, S_FIREBALL3}, // S_FIREBALL2 + {SPR_FBLL, FF_FULLBRIGHT|2, 3, {NULL}, 0, 0, S_FIREBALL4}, // S_FIREBALL3 + {SPR_FBLL, FF_FULLBRIGHT|3, 3, {NULL}, 0, 0, S_FIREBALL1}, // S_FIREBALL4 + {SPR_FBLL, FF_FULLBRIGHT|4, 3, {NULL}, 0, 0, S_FIREBALLEXP2}, // S_FIREBALLEXP1 + {SPR_FBLL, FF_FULLBRIGHT|5, 3, {NULL}, 0, 0, S_FIREBALLEXP3}, // S_FIREBALLEXP2 + {SPR_FBLL, FF_FULLBRIGHT|6, 3, {NULL}, 0, 0, S_NULL}, // S_FIREBALLEXP3 // Turtle Shell {SPR_SHLL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SHELL @@ -2540,43 +2535,43 @@ state_t states[NUMSTATES] = {SPR_BSPR, 2, 1, {NULL}, 0, 0, S_BDIAG8}, // S_BDIAG7 {SPR_BSPR, 1, 1, {NULL}, 0, 0, S_BDIAG1}, // S_BDIAG8 - {SPR_RNDM, 0, 3, {NULL}, 0, 0, S_RANDOMITEM2}, // S_RANDOMITEM1 - {SPR_RNDM, 1, 3, {NULL}, 0, 0, S_RANDOMITEM3}, // S_RANDOMITEM2 - {SPR_RNDM, 2, 3, {NULL}, 0, 0, S_RANDOMITEM4}, // S_RANDOMITEM3 - {SPR_RNDM, 3, 3, {NULL}, 0, 0, S_RANDOMITEM5}, // S_RANDOMITEM4 - {SPR_RNDM, 4, 3, {NULL}, 0, 0, S_RANDOMITEM6}, // S_RANDOMITEM5 - {SPR_RNDM, 5, 3, {NULL}, 0, 0, S_RANDOMITEM7}, // S_RANDOMITEM6 - {SPR_RNDM, 6, 3, {NULL}, 0, 0, S_RANDOMITEM8}, // S_RANDOMITEM7 - {SPR_RNDM, 7, 3, {NULL}, 0, 0, S_RANDOMITEM9}, // S_RANDOMITEM8 - {SPR_RNDM, 8, 3, {NULL}, 0, 0, S_RANDOMITEM10}, // S_RANDOMITEM9 - {SPR_RNDM, 9, 3, {NULL}, 0, 0, S_RANDOMITEM11}, // S_RANDOMITEM10 - {SPR_RNDM, 10, 3, {NULL}, 0, 0, S_RANDOMITEM12}, // S_RANDOMITEM11 - {SPR_RNDM, 11, 3, {NULL}, 0, 0, S_RANDOMITEM13}, // S_RANDOMITEM12 - {SPR_RNDM, 12, 3, {NULL}, 0, 0, S_RANDOMITEM14}, // S_RANDOMITEM13 - {SPR_RNDM, 13, 3, {NULL}, 0, 0, S_RANDOMITEM15}, // S_RANDOMITEM14 - {SPR_RNDM, 14, 3, {NULL}, 0, 0, S_RANDOMITEM16}, // S_RANDOMITEM15 - {SPR_RNDM, 15, 3, {NULL}, 0, 0, S_RANDOMITEM17}, // S_RANDOMITEM16 - {SPR_RNDM, 16, 3, {NULL}, 0, 0, S_RANDOMITEM18}, // S_RANDOMITEM17 - {SPR_RNDM, 17, 3, {NULL}, 0, 0, S_RANDOMITEM19}, // S_RANDOMITEM18 - {SPR_RNDM, 18, 3, {NULL}, 0, 0, S_RANDOMITEM20}, // S_RANDOMITEM19 - {SPR_RNDM, 19, 3, {NULL}, 0, 0, S_RANDOMITEM21}, // S_RANDOMITEM20 - {SPR_RNDM, 20, 3, {NULL}, 0, 0, S_RANDOMITEM22}, // S_RANDOMITEM21 - {SPR_RNDM, 21, 3, {NULL}, 0, 0, S_RANDOMITEM23}, // S_RANDOMITEM22 - {SPR_RNDM, 22, 3, {NULL}, 0, 0, S_RANDOMITEM24}, // S_RANDOMITEM23 - {SPR_RNDM, 23, 3, {NULL}, 0, 0, S_RANDOMITEM1}, // S_RANDOMITEM24 - {SPR_RNDM, 0, 1, {A_ItemPop}, 0, 0, S_NULL}, // S_DEADRANDOMITEM + {SPR_RNDM, 0|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_RANDOMITEM2}, // S_RANDOMITEM1 + {SPR_RNDM, 1|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_RANDOMITEM3}, // S_RANDOMITEM2 + {SPR_RNDM, 2|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_RANDOMITEM4}, // S_RANDOMITEM3 + {SPR_RNDM, 3|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_RANDOMITEM5}, // S_RANDOMITEM4 + {SPR_RNDM, 4|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_RANDOMITEM6}, // S_RANDOMITEM5 + {SPR_RNDM, 5|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_RANDOMITEM7}, // S_RANDOMITEM6 + {SPR_RNDM, 6|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_RANDOMITEM8}, // S_RANDOMITEM7 + {SPR_RNDM, 7|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_RANDOMITEM9}, // S_RANDOMITEM8 + {SPR_RNDM, 8|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_RANDOMITEM10}, // S_RANDOMITEM9 + {SPR_RNDM, 9|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_RANDOMITEM11}, // S_RANDOMITEM10 + {SPR_RNDM, 10|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_RANDOMITEM12}, // S_RANDOMITEM11 + {SPR_RNDM, 11|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_RANDOMITEM13}, // S_RANDOMITEM12 + {SPR_RNDM, 12|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_RANDOMITEM14}, // S_RANDOMITEM13 + {SPR_RNDM, 13|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_RANDOMITEM15}, // S_RANDOMITEM14 + {SPR_RNDM, 14|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_RANDOMITEM16}, // S_RANDOMITEM15 + {SPR_RNDM, 15|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_RANDOMITEM17}, // S_RANDOMITEM16 + {SPR_RNDM, 16|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_RANDOMITEM18}, // S_RANDOMITEM17 + {SPR_RNDM, 17|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_RANDOMITEM19}, // S_RANDOMITEM18 + {SPR_RNDM, 18|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_RANDOMITEM20}, // S_RANDOMITEM19 + {SPR_RNDM, 19|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_RANDOMITEM21}, // S_RANDOMITEM20 + {SPR_RNDM, 20|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_RANDOMITEM22}, // S_RANDOMITEM21 + {SPR_RNDM, 21|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_RANDOMITEM23}, // S_RANDOMITEM22 + {SPR_RNDM, 22|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_RANDOMITEM24}, // S_RANDOMITEM23 + {SPR_RNDM, 23|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_RANDOMITEM1}, // S_RANDOMITEM24 + {SPR_RNDM, 0|FF_FULLBRIGHT, 1, {A_ItemPop}, 0, 0, S_NULL}, // S_DEADRANDOMITEM {SPR_RPOP, FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_RANDOMITEMPOP2}, // S_RANDOMITEMPOP1 {SPR_RPOP, FF_FULLBRIGHT|1, 5, {NULL}, 0, 0, S_RANDOMITEMPOP3}, // S_RANDOMITEMPOP2 {SPR_RPOP, FF_FULLBRIGHT|2, 5, {NULL}, 0, 0, S_RANDOMITEMPOP4}, // S_RANDOMITEMPOP3 {SPR_RPOP, FF_FULLBRIGHT|3, 5, {NULL}, 0, 0, S_NULL}, // S_RANDOMITEMPOP4 - {SPR_DRIF, 0, 2, {NULL}, 0, 0, S_DRIFTSPARK2}, // S_DRIFTSPARK1 - {SPR_DRIF, 1, 2, {NULL}, 0, 0, S_DRIFTSPARK3}, // S_DRIFTSPARK2 - {SPR_DRIF, 2, 2, {NULL}, 0, 0, S_DRIFTSPARK1}, // S_DRIFTSPARK3 - {SPR_DRIF, 3, 2, {NULL}, 0, 0, S_DRIFTSPARK5}, // S_DRIFTSPARK4 - {SPR_DRIF, 4, 2, {NULL}, 0, 0, S_DRIFTSPARK6}, // S_DRIFTSPARK5 - {SPR_DRIF, 5, 2, {NULL}, 0, 0, S_DRIFTSPARK4}, // S_DRIFTSPARK6 + {SPR_DRIF, 0|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_DRIFTSPARK2}, // S_DRIFTSPARK1 + {SPR_DRIF, 1|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_DRIFTSPARK3}, // S_DRIFTSPARK2 + {SPR_DRIF, 2|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_DRIFTSPARK1}, // S_DRIFTSPARK3 + {SPR_DRIF, 3|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_DRIFTSPARK5}, // S_DRIFTSPARK4 + {SPR_DRIF, 4|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_DRIFTSPARK6}, // S_DRIFTSPARK5 + {SPR_DRIF, 5|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_DRIFTSPARK4}, // S_DRIFTSPARK6 {SPR_DUST, 0, 3, {NULL}, 0, 0, S_DRIFTDUST2}, // S_DRIFTDUST1 {SPR_DUST, 1, 3, {NULL}, 0, 0, S_DRIFTDUST3}, // S_DRIFTDUST2 @@ -2592,148 +2587,222 @@ state_t states[NUMSTATES] = {SPR_KFRE, FF_FULLBRIGHT|5, 2, {NULL}, 0, 0, S_KARTFIRE8}, // S_KARTFIRE7 {SPR_KFRE, FF_FULLBRIGHT|6, 2, {NULL}, 0, 0, S_NULL}, // S_KARTFIRE8 - {SPR_FITM, 0, 3, {NULL}, 0, 0, S_FAKEITEM2}, // S_FAKEITEM1 - {SPR_FITM, 1, 3, {NULL}, 0, 0, S_FAKEITEM3}, // S_FAKEITEM2 - {SPR_FITM, 2, 3, {NULL}, 0, 0, S_FAKEITEM4}, // S_FAKEITEM3 - {SPR_FITM, 3, 3, {NULL}, 0, 0, S_FAKEITEM5}, // S_FAKEITEM4 - {SPR_FITM, 4, 3, {NULL}, 0, 0, S_FAKEITEM6}, // S_FAKEITEM5 - {SPR_FITM, 5, 3, {NULL}, 0, 0, S_FAKEITEM7}, // S_FAKEITEM6 - {SPR_FITM, 6, 3, {NULL}, 0, 0, S_FAKEITEM8}, // S_FAKEITEM7 - {SPR_FITM, 7, 3, {NULL}, 0, 0, S_FAKEITEM9}, // S_FAKEITEM8 - {SPR_FITM, 8, 3, {NULL}, 0, 0, S_FAKEITEM10}, // S_FAKEITEM9 - {SPR_FITM, 9, 3, {NULL}, 0, 0, S_FAKEITEM11}, // S_FAKEITEM10 - {SPR_FITM, 10, 3, {NULL}, 0, 0, S_FAKEITEM12}, // S_FAKEITEM11 - {SPR_FITM, 11, 3, {NULL}, 0, 0, S_FAKEITEM13}, // S_FAKEITEM12 - {SPR_FITM, 12, 3, {NULL}, 0, 0, S_FAKEITEM14}, // S_FAKEITEM13 - {SPR_FITM, 13, 3, {NULL}, 0, 0, S_FAKEITEM15}, // S_FAKEITEM14 - {SPR_FITM, 14, 3, {NULL}, 0, 0, S_FAKEITEM16}, // S_FAKEITEM15 - {SPR_FITM, 15, 3, {NULL}, 0, 0, S_FAKEITEM17}, // S_FAKEITEM16 - {SPR_FITM, 16, 3, {NULL}, 0, 0, S_FAKEITEM18}, // S_FAKEITEM17 - {SPR_FITM, 17, 3, {NULL}, 0, 0, S_FAKEITEM19}, // S_FAKEITEM18 - {SPR_FITM, 18, 3, {NULL}, 0, 0, S_FAKEITEM20}, // S_FAKEITEM19 - {SPR_FITM, 19, 3, {NULL}, 0, 0, S_FAKEITEM21}, // S_FAKEITEM20 - {SPR_FITM, 20, 3, {NULL}, 0, 0, S_FAKEITEM22}, // S_FAKEITEM21 - {SPR_FITM, 21, 3, {NULL}, 0, 0, S_FAKEITEM23}, // S_FAKEITEM22 // ***** - {SPR_FITM, 22, 3, {NULL}, 0, 0, S_FAKEITEM24}, // S_FAKEITEM23 // ***** - {SPR_FITM, 23, 3, {NULL}, 0, 0, S_FAKEITEM1}, // S_FAKEITEM24 // ***** - {SPR_DFAK, 0, 175, {NULL}, 0, 0, S_FAKEITEM1}, // S_DEADFAKEITEM + {SPR_KINV, FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_KARTINVULN_SMALL2}, // S_KARTINVULN_SMALL1 + {SPR_KINV, FF_FULLBRIGHT|1, 1, {NULL}, 0, 0, S_KARTINVULN_SMALL3}, // S_KARTINVULN_SMALL2 + {SPR_KINV, FF_FULLBRIGHT|2, 1, {NULL}, 0, 0, S_KARTINVULN_SMALL4}, // S_KARTINVULN_SMALL3 + {SPR_KINV, FF_FULLBRIGHT|3, 1, {NULL}, 0, 0, S_KARTINVULN_SMALL5}, // S_KARTINVULN_SMALL4 + {SPR_KINV, FF_FULLBRIGHT|4, 1, {NULL}, 0, 0, S_NULL}, // S_KARTINVULN_SMALL5 - {SPR_BANA, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BANANAITEM - {SPR_DBAN, 0, 175, {NULL}, 0, 0, S_NULL}, // S_DEADBANANA + {SPR_KINV, FF_FULLBRIGHT|1, 1, {NULL}, 0, 0, S_KARTINVULN_LARGE2}, // S_KARTINVULN_LARGE1 + {SPR_KINV, FF_FULLBRIGHT|2, 1, {NULL}, 0, 0, S_KARTINVULN_LARGE3}, // S_KARTINVULN_LARGE2 + {SPR_KINV, FF_FULLBRIGHT|5, 1, {NULL}, 0, 0, S_KARTINVULN_LARGE4}, // S_KARTINVULN_LARGE3 + {SPR_KINV, FF_FULLBRIGHT|6, 1, {NULL}, 0, 0, S_KARTINVULN_LARGE5}, // S_KARTINVULN_LARGE4 + {SPR_KINV, FF_FULLBRIGHT|7, 1, {NULL}, 0, 0, S_NULL}, // S_KARTINVULN_LARGE5 - {SPR_GSHE, 0, 1, {NULL}, 0, 0, S_TRIPLEGREENSHIELD2}, // S_TRIPLEGREENSHIELD1 - {SPR_GSHE, 1, 1, {NULL}, 0, 0, S_TRIPLEGREENSHIELD3}, // S_TRIPLEGREENSHIELD2 - {SPR_GSHE, 2, 1, {NULL}, 0, 0, S_TRIPLEGREENSHIELD4}, // S_TRIPLEGREENSHIELD3 - {SPR_GSHE, 3, 1, {NULL}, 0, 0, S_TRIPLEGREENSHIELD5}, // S_TRIPLEGREENSHIELD4 - {SPR_GSHE, 4, 1, {NULL}, 0, 0, S_TRIPLEGREENSHIELD6}, // S_TRIPLEGREENSHIELD5 - {SPR_GSHE, 5, 1, {NULL}, 0, 0, S_TRIPLEGREENSHIELD7}, // S_TRIPLEGREENSHIELD6 - {SPR_GSHE, 6, 1, {NULL}, 0, 0, S_TRIPLEGREENSHIELD8}, // S_TRIPLEGREENSHIELD7 - {SPR_GSHE, 7, 1, {NULL}, 0, 0, S_TRIPLEGREENSHIELD1}, // S_TRIPLEGREENSHIELD8 - {SPR_GSHE, 0, 1, {NULL}, 0, 0, S_GREENSHIELD2}, // S_GREENSHIELD1 - {SPR_GSHE, 1, 1, {NULL}, 0, 0, S_GREENSHIELD3}, // S_GREENSHIELD2 - {SPR_GSHE, 2, 1, {NULL}, 0, 0, S_GREENSHIELD4}, // S_GREENSHIELD3 - {SPR_GSHE, 3, 1, {NULL}, 0, 0, S_GREENSHIELD5}, // S_GREENSHIELD4 - {SPR_GSHE, 4, 1, {NULL}, 0, 0, S_GREENSHIELD6}, // S_GREENSHIELD5 - {SPR_GSHE, 5, 1, {NULL}, 0, 0, S_GREENSHIELD7}, // S_GREENSHIELD6 - {SPR_GSHE, 6, 1, {NULL}, 0, 0, S_GREENSHIELD8}, // S_GREENSHIELD7 - {SPR_GSHE, 7, 1, {NULL}, 0, 0, S_GREENSHIELD1}, // S_GREENSHIELD8 - {SPR_GSHE, 0, 1, {NULL}, 0, 0, S_GREENITEM2}, // S_GREENITEM1 - {SPR_GSHE, 1, 1, {NULL}, 0, 0, S_GREENITEM3}, // S_GREENITEM2 - {SPR_GSHE, 2, 1, {NULL}, 0, 0, S_GREENITEM4}, // S_GREENITEM3 - {SPR_GSHE, 3, 1, {NULL}, 0, 0, S_GREENITEM5}, // S_GREENITEM4 - {SPR_GSHE, 4, 1, {NULL}, 0, 0, S_GREENITEM6}, // S_GREENITEM5 - {SPR_GSHE, 5, 1, {NULL}, 0, 0, S_GREENITEM7}, // S_GREENITEM6 - {SPR_GSHE, 6, 1, {NULL}, 0, 0, S_GREENITEM8}, // S_GREENITEM7 - {SPR_GSHE, 7, 1, {NULL}, 0, 0, S_GREENITEM1}, // S_GREENITEM8 - {SPR_DGSH, 0, 175, {NULL}, 0, 0, S_NULL}, // S_DEADGREEN + {SPR_KINF, FF_FULLBRIGHT|FF_TRANS90, 1, {NULL}, 0, 0, S_INVULNFLASH2}, // S_INVULNFLASH1 + {SPR_NULL, FF_FULLBRIGHT|FF_TRANS90, 1, {NULL}, 0, 0, S_INVULNFLASH3}, // S_INVULNFLASH2 + {SPR_KINF, FF_FULLBRIGHT|FF_TRANS90|1, 1, {NULL}, 0, 0, S_INVULNFLASH4}, // S_INVULNFLASH3 + {SPR_NULL, FF_FULLBRIGHT|FF_TRANS90, 1, {NULL}, 0, 0, S_INVULNFLASH1}, // S_INVULNFLASH4 - {SPR_RSHE, 0, 1, {NULL}, 0, 0, S_TRIPLEREDSHIELD2}, // S_TRIPLEREDSHIELD1 - {SPR_RSHE, 1, 1, {NULL}, 0, 0, S_TRIPLEREDSHIELD3}, // S_TRIPLEREDSHIELD2 - {SPR_RSHE, 2, 1, {NULL}, 0, 0, S_TRIPLEREDSHIELD4}, // S_TRIPLEREDSHIELD3 - {SPR_RSHE, 3, 1, {NULL}, 0, 0, S_TRIPLEREDSHIELD5}, // S_TRIPLEREDSHIELD4 - {SPR_RSHE, 4, 1, {NULL}, 0, 0, S_TRIPLEREDSHIELD6}, // S_TRIPLEREDSHIELD5 - {SPR_RSHE, 5, 1, {NULL}, 0, 0, S_TRIPLEREDSHIELD7}, // S_TRIPLEREDSHIELD6 - {SPR_RSHE, 6, 1, {NULL}, 0, 0, S_TRIPLEREDSHIELD8}, // S_TRIPLEREDSHIELD7 - {SPR_RSHE, 7, 1, {NULL}, 0, 0, S_TRIPLEREDSHIELD1}, // S_TRIPLEREDSHIELD8 - {SPR_RSHE, 0, 1, {NULL}, 0, 0, S_REDSHIELD2}, // S_REDSHIELD1 - {SPR_RSHE, 1, 1, {NULL}, 0, 0, S_REDSHIELD3}, // S_REDSHIELD2 - {SPR_RSHE, 2, 1, {NULL}, 0, 0, S_REDSHIELD4}, // S_REDSHIELD3 - {SPR_RSHE, 3, 1, {NULL}, 0, 0, S_REDSHIELD5}, // S_REDSHIELD4 - {SPR_RSHE, 4, 1, {NULL}, 0, 0, S_REDSHIELD6}, // S_REDSHIELD5 - {SPR_RSHE, 5, 1, {NULL}, 0, 0, S_REDSHIELD7}, // S_REDSHIELD6 - {SPR_RSHE, 6, 1, {NULL}, 0, 0, S_REDSHIELD8}, // S_REDSHIELD7 - {SPR_RSHE, 7, 1, {NULL}, 0, 0, S_REDSHIELD1}, // S_REDSHIELD8 - {SPR_RSHE, 0, 1, {A_RedShellChase}, 0, 0, S_REDITEM2}, // S_REDITEM1 - {SPR_RSHE, 1, 1, {A_RedShellChase}, 0, 0, S_REDITEM3}, // S_REDITEM2 - {SPR_RSHE, 2, 1, {A_RedShellChase}, 0, 0, S_REDITEM4}, // S_REDITEM3 - {SPR_RSHE, 3, 1, {A_RedShellChase}, 0, 0, S_REDITEM5}, // S_REDITEM4 - {SPR_RSHE, 4, 1, {A_RedShellChase}, 0, 0, S_REDITEM6}, // S_REDITEM5 - {SPR_RSHE, 5, 1, {A_RedShellChase}, 0, 0, S_REDITEM7}, // S_REDITEM6 - {SPR_RSHE, 6, 1, {A_RedShellChase}, 0, 0, S_REDITEM8}, // S_REDITEM7 - {SPR_RSHE, 7, 1, {A_RedShellChase}, 0, 0, S_REDITEM1}, // S_REDITEM8 - {SPR_DRSH, 0, 175, {NULL}, 0, 0, S_NULL}, // S_DEADRED + {SPR_WIPD, 0, 3, {NULL}, 0, 0, S_WIPEOUTTRAIL2}, // S_WIPEOUTTRAIL1 + {SPR_WIPD, 1, 3, {NULL}, 0, 0, S_WIPEOUTTRAIL3}, // S_WIPEOUTTRAIL2 + {SPR_WIPD, 2, 3, {NULL}, 0, 0, S_WIPEOUTTRAIL4}, // S_WIPEOUTTRAIL3 + {SPR_WIPD, 3, 3, {NULL}, 0, 0, S_WIPEOUTTRAIL5}, // S_WIPEOUTTRAIL4 + {SPR_WIPD, 4, 3, {NULL}, 0, 0, S_NULL}, // S_WIPEOUTTRAIL5 - {SPR_FBLL, 13, 3, {NULL}, 0, 0, S_FIRETRAIL2}, // S_FIRETRAIL1 - {SPR_FBLL, 14, 3, {NULL}, 0, 0, S_FIRETRAIL3}, // S_FIRETRAIL2 - {SPR_FBLL, 15, 3, {NULL}, 0, 0, S_FIRETRAIL4}, // S_FIRETRAIL3 - {SPR_FBLL, 16, 3, {NULL}, 0, 0, S_FIRETRAIL5}, // S_FIRETRAIL4 - {SPR_FBLL, 17, 3, {NULL}, 0, 0, S_FIRETRAIL6}, // S_FIRETRAIL5 - {SPR_FBLL, 18, 3, {NULL}, 0, 0, S_FIRETRAIL7}, // S_FIRETRAIL6 - {SPR_FBLL, 19, 3, {NULL}, 0, 0, S_FIRETRAIL8}, // S_FIRETRAIL7 - {SPR_FBLL, 20, 3, {NULL}, 0, 0, S_FIRETRAIL9}, // S_FIRETRAIL8 - {SPR_FBLL, 21, 3, {NULL}, 0, 0, S_NULL}, // S_FIRETRAIL9 + {SPR_FITM, FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_FAKEITEM2}, // S_FAKEITEM1 + {SPR_FITM, 1|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_FAKEITEM3}, // S_FAKEITEM2 + {SPR_FITM, 2|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_FAKEITEM4}, // S_FAKEITEM3 + {SPR_FITM, 3|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_FAKEITEM5}, // S_FAKEITEM4 + {SPR_FITM, 4|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_FAKEITEM6}, // S_FAKEITEM5 + {SPR_FITM, 5|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_FAKEITEM7}, // S_FAKEITEM6 + {SPR_FITM, 6|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_FAKEITEM8}, // S_FAKEITEM7 + {SPR_FITM, 7|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_FAKEITEM9}, // S_FAKEITEM8 + {SPR_FITM, 8|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_FAKEITEM10}, // S_FAKEITEM9 + {SPR_FITM, 9|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_FAKEITEM11}, // S_FAKEITEM10 + {SPR_FITM, 10|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_FAKEITEM12}, // S_FAKEITEM11 + {SPR_FITM, 11|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_FAKEITEM13}, // S_FAKEITEM12 + {SPR_FITM, 12|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_FAKEITEM14}, // S_FAKEITEM13 + {SPR_FITM, 13|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_FAKEITEM15}, // S_FAKEITEM14 + {SPR_FITM, 14|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_FAKEITEM16}, // S_FAKEITEM15 + {SPR_FITM, 15|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_FAKEITEM17}, // S_FAKEITEM16 + {SPR_FITM, 16|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_FAKEITEM18}, // S_FAKEITEM17 + {SPR_FITM, 17|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_FAKEITEM19}, // S_FAKEITEM18 + {SPR_FITM, 18|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_FAKEITEM20}, // S_FAKEITEM19 + {SPR_FITM, 19|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_FAKEITEM21}, // S_FAKEITEM20 + {SPR_FITM, 20|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_FAKEITEM22}, // S_FAKEITEM21 + {SPR_FITM, 21|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_FAKEITEM23}, // S_FAKEITEM22 // ***** + {SPR_FITM, 22|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_FAKEITEM24}, // S_FAKEITEM23 // ***** + {SPR_FITM, 23|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_FAKEITEM1}, // S_FAKEITEM24 // ***** + {SPR_FITM, FF_FULLBRIGHT, 175, {NULL}, 0, 0, S_FAKEITEM1}, // S_DEADFAKEITEM - {SPR_BOMB, 0, 1, {NULL}, 0, 0, S_BOMBSHIELD}, // S_BOMBSHIELD - {SPR_BOMB, 0, 1, {A_GrenadeRing}, 0, 0, S_BOMBITEM}, // S_BOMBITEM - {SPR_BOMB, 0, 1, {NULL}, 0, 0, S_BOMBAIR}, // S_BOMBAIR - {SPR_BOMB, 0, 1, {A_BobombExplode}, MT_BOMBEXPLOSION, 0, S_NULL}, // S_BOMBEXPLODE - {SPR_NULL, 0, 6, {NULL}, 0, 0, S_BOMBEXPLOSION2}, // S_BOMBEXPLOSION1 - {SPR_NULL, 1, 22, {A_ForceStop}, 0, 0, S_NULL}, // S_BOMBEXPLOSION2 + {SPR_BANA, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BANANA + {SPR_BANA, 0, 175, {NULL}, 0, 0, S_NULL}, // S_BANANA_DEAD - {SPR_KRBM, 0, 1, {NULL}, 0, 0, S_QUICKBOOM2}, // S_QUICKBOOM1 - {SPR_KRBM, 1, 1, {NULL}, 0, 0, S_QUICKBOOM3}, // S_QUICKBOOM2 - {SPR_KRBM, 2, 1, {NULL}, 0, 0, S_QUICKBOOM4}, // S_QUICKBOOM3 - {SPR_KRBM, 3, 1, {NULL}, 0, 0, S_QUICKBOOM5}, // S_QUICKBOOM4 - {SPR_KRBM, 4, 1, {NULL}, 0, 0, S_QUICKBOOM6}, // S_QUICKBOOM5 - {SPR_KRBM, 5, 1, {NULL}, 0, 0, S_QUICKBOOM7}, // S_QUICKBOOM6 - {SPR_KRBM, 6, 1, {NULL}, 0, 0, S_QUICKBOOM8}, // S_QUICKBOOM7 - {SPR_KRBM, 7, 2, {NULL}, 0, 0, S_QUICKBOOM9}, // S_QUICKBOOM8 - {SPR_KRBM, 8, 2, {NULL}, 0, 0, S_QUICKBOOM10}, // S_QUICKBOOM9 - {SPR_KRBM, 9, 2, {NULL}, 0, 0, S_NULL}, // S_QUICKBOOM10 + {SPR_ORBN, 0, 1, {NULL}, 0, 0, S_ORBINAUT2}, // S_ORBINAUT1 + {SPR_ORBN, 1, 1, {NULL}, 0, 0, S_ORBINAUT3}, // S_ORBINAUT2 + {SPR_ORBN, 2, 1, {NULL}, 0, 0, S_ORBINAUT4}, // S_ORBINAUT3 + {SPR_ORBN, 3, 1, {NULL}, 0, 0, S_ORBINAUT5}, // S_ORBINAUT4 + {SPR_ORBN, 4, 1, {NULL}, 0, 0, S_ORBINAUT6}, // S_ORBINAUT5 + {SPR_ORBN, 5, 1, {NULL}, 0, 0, S_ORBINAUT1}, // S_ORBINAUT6 + {SPR_ORBN, 0, 175, {NULL}, 0, 0, S_NULL}, // S_ORBINAUT_DEAD + {SPR_ORBN, 6, 3, {NULL}, 0, 0, S_ORBINAUT_SHIELD2}, // S_ORBINAUT_SHIELD1 + {SPR_ORBN, 7, 3, {NULL}, 0, 0, S_ORBINAUT_SHIELD3}, // S_ORBINAUT_SHIELD2 + {SPR_ORBN, 8, 3, {NULL}, 0, 0, S_ORBINAUT_SHIELD4}, // S_ORBINAUT_SHIELD3 + {SPR_ORBN, 9, 3, {NULL}, 0, 0, S_ORBINAUT_SHIELD5}, // S_ORBINAUT_SHIELD4 + {SPR_ORBN, 10, 3, {NULL}, 0, 0, S_ORBINAUT_SHIELD6}, // S_ORBINAUT_SHIELD5 + {SPR_ORBN, 11, 3, {NULL}, 0, 0, S_ORBINAUT_SHIELD1}, // S_ORBINAUT_SHIELD6 + {SPR_ORBN, 6, 175, {NULL}, 0, 0, S_NULL}, // S_ORBINAUT_SHIELDDEAD - {SPR_KRBM, 0, 3, {NULL}, 0, 0, S_SLOWBOOM2}, // S_SLOWBOOM1 - {SPR_KRBM, 1, 3, {NULL}, 0, 0, S_SLOWBOOM3}, // S_SLOWBOOM2 - {SPR_KRBM, 2, 3, {NULL}, 0, 0, S_SLOWBOOM4}, // S_SLOWKBOOM3 - {SPR_KRBM, 3, 3, {NULL}, 0, 0, S_SLOWBOOM5}, // S_SLOWBOOM4 - {SPR_KRBM, 4, 3, {NULL}, 0, 0, S_SLOWBOOM6}, // S_SLOWBOOM5 - {SPR_KRBM, 5, 3, {NULL}, 0, 0, S_SLOWBOOM7}, // S_SLOWBOOM6 - {SPR_KRBM, 6, 3, {NULL}, 0, 0, S_SLOWBOOM8}, // S_SLOWBOOM7 - {SPR_KRBM, 7, 5, {NULL}, 0, 0, S_SLOWBOOM9}, // S_SLOWBOOM8 - {SPR_KRBM, 8, 5, {NULL}, 0, 0, S_SLOWBOOM10}, // S_SLOWBOOM9 - {SPR_KRBM, 9, 5, {NULL}, 0, 0, S_NULL}, // S_SLOWBOOM10 + {SPR_JAWZ, 0, 1, {A_JawzChase}, 0, 0, S_JAWZ2}, // S_JAWZ1 + {SPR_JAWZ, 4, 1, {A_JawzChase}, 0, 0, S_JAWZ3}, // S_JAWZ2 + {SPR_JAWZ, 1, 1, {A_JawzChase}, 0, 0, S_JAWZ4}, // S_JAWZ3 + {SPR_JAWZ, 4, 1, {A_JawzChase}, 0, 0, S_JAWZ5}, // S_JAWZ4 + {SPR_JAWZ, 2, 1, {A_JawzChase}, 0, 0, S_JAWZ6}, // S_JAWZ5 + {SPR_JAWZ, 4, 1, {A_JawzChase}, 0, 0, S_JAWZ7}, // S_JAWZ6 + {SPR_JAWZ, 3, 1, {A_JawzChase}, 0, 0, S_JAWZ8}, // S_JAWZ7 + {SPR_JAWZ, 4, 1, {A_JawzChase}, 0, 0, S_JAWZ1}, // S_JAWZ8 + + {SPR_JAWZ, 0, 1, {NULL}, 0, 0, S_JAWZ_DUD2}, // S_JAWZ_DUD1 + {SPR_JAWZ, 4, 1, {NULL}, 0, 0, S_JAWZ_DUD3}, // S_JAWZ_DUD2 + {SPR_JAWZ, 1, 1, {NULL}, 0, 0, S_JAWZ_DUD4}, // S_JAWZ_DUD3 + {SPR_JAWZ, 4, 1, {NULL}, 0, 0, S_JAWZ_DUD5}, // S_JAWZ_DUD4 + {SPR_JAWZ, 2, 1, {NULL}, 0, 0, S_JAWZ_DUD6}, // S_JAWZ_DUD5 + {SPR_JAWZ, 4, 1, {NULL}, 0, 0, S_JAWZ_DUD7}, // S_JAWZ_DUD6 + {SPR_JAWZ, 3, 1, {NULL}, 0, 0, S_JAWZ_DUD8}, // S_JAWZ_DUD7 + {SPR_JAWZ, 4, 1, {NULL}, 0, 0, S_JAWZ_DUD1}, // S_JAWZ_DUD8 + + {SPR_JAWZ, 0, 1, {NULL}, 0, 0, S_JAWZ_SHIELD2}, // S_JAWZ_SHIELD1 + {SPR_JAWZ, 4, 1, {NULL}, 0, 0, S_JAWZ_SHIELD3}, // S_JAWZ_SHIELD2 + {SPR_JAWZ, 1, 1, {NULL}, 0, 0, S_JAWZ_SHIELD4}, // S_JAWZ_SHIELD3 + {SPR_JAWZ, 4, 1, {NULL}, 0, 0, S_JAWZ_SHIELD5}, // S_JAWZ_SHIELD4 + {SPR_JAWZ, 2, 1, {NULL}, 0, 0, S_JAWZ_SHIELD6}, // S_JAWZ_SHIELD5 + {SPR_JAWZ, 4, 1, {NULL}, 0, 0, S_JAWZ_SHIELD7}, // S_JAWZ_SHIELD6 + {SPR_JAWZ, 3, 1, {NULL}, 0, 0, S_JAWZ_SHIELD8}, // S_JAWZ_SHIELD7 + {SPR_JAWZ, 4, 1, {NULL}, 0, 0, S_JAWZ_SHIELD1}, // S_JAWZ_SHIELD8 + + {SPR_JAWZ, 5, 175, {NULL}, 0, 0, S_JAWZ_DEAD2}, // S_JAWZ_DEAD1 + {SPR_NULL, 0, 1, {A_JawzExplode}, 0, 0, S_NULL}, // S_JAWZ_DEAD2 + + {SPR_SSMN, 0, 30, {NULL}, 0, 0, S_SSMINE2}, // S_SSMINE1 + {SPR_SSMN, 3, 3, {NULL}, 0, 0, S_SSMINE3}, // S_SSMINE2 + {SPR_SSMN, 2, 3, {NULL}, 0, 0, S_SSMINE4}, // S_SSMINE3 + {SPR_SSMN, 1, 3, {NULL}, 0, 0, S_SSMINE1}, // S_SSMINE4 + {SPR_SSMN, 4, 1, {NULL}, 0, 0, S_SSMINE_SHIELD2}, // S_SSMINE_SHIELD1 + {SPR_SSMN, 5, 1, {NULL}, 0, 0, S_SSMINE_SHIELD1}, // S_SSMINE_SHIELD2 + {SPR_SSMN, 4, 1, {NULL}, 0, 0, S_SSMINE_AIR2}, // S_SSMINE_AIR1 + {SPR_SSMN, 5, 1, {NULL}, 0, 0, S_SSMINE_AIR1}, // S_SSMINE_AIR2 + {SPR_SSMN, 6, 3, {NULL}, 0, 0, S_SSMINE_DEPLOY2}, // S_SSMINE_DEPLOY1 + {SPR_SSMN, 7, 5, {NULL}, 0, 0, S_SSMINE_DEPLOY3}, // S_SSMINE_DEPLOY2 + {SPR_SSMN, 8, 7, {NULL}, 0, 0, S_SSMINE_DEPLOY4}, // S_SSMINE_DEPLOY3 + {SPR_SSMN, 9, 1, {NULL}, 0, 0, S_SSMINE_DEPLOY5}, // S_SSMINE_DEPLOY4 + {SPR_SSMN, 10, 1, {NULL}, 0, 0, S_SSMINE_DEPLOY6}, // S_SSMINE_DEPLOY5 + {SPR_SSMN, 9, 1, {NULL}, 0, 0, S_SSMINE_DEPLOY7}, // S_SSMINE_DEPLOY6 + {SPR_SSMN, 10, 3, {NULL}, 0, 0, S_SSMINE_DEPLOY8}, // S_SSMINE_DEPLOY7 + {SPR_SSMN, 11, 1, {A_PlaySound}, sfx_cdfm39, 1, S_SSMINE_DEPLOY9}, // S_SSMINE_DEPLOY8 + {SPR_SSMN, 10, 1, {NULL}, 0, 0, S_SSMINE_DEPLOY10}, // S_SSMINE_DEPLOY9 + {SPR_SSMN, 11, 3, {NULL}, 0, 0, S_SSMINE_DEPLOY11}, // S_SSMINE_DEPLOY10 + {SPR_SSMN, 12, 3, {NULL}, 0, 0, S_SSMINE_DEPLOY12}, // S_SSMINE_DEPLOY11 + {SPR_SSMN, 13, 3, {NULL}, 0, 0, S_SSMINE_DEPLOY13}, // S_SSMINE_DEPLOY12 + {SPR_SSMN, 14, 3, {NULL}, 0, 0, S_SSMINE1}, // S_SSMINE_DEPLOY13 + {SPR_SSMN, 3, 1, {A_MineExplode}, MT_MINEEXPLOSION, 0, S_NULL}, // S_SSMINE_EXPLODE + {SPR_NULL, 0, 6, {NULL}, 0, 0, S_MINEEXPLOSION2}, // S_MINEEXPLOSION1 + {SPR_NULL, 1, 22, {A_ForceStop}, 0, 0, S_NULL}, // S_MINEEXPLOSION2 + + {SPR_KRBM, FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_QUICKBOOM2}, // S_QUICKBOOM1 + {SPR_KRBM, FF_FULLBRIGHT|1, 1, {NULL}, 0, 0, S_QUICKBOOM3}, // S_QUICKBOOM2 + {SPR_KRBM, FF_FULLBRIGHT|2, 1, {NULL}, 0, 0, S_QUICKBOOM4}, // S_QUICKBOOM3 + {SPR_KRBM, FF_FULLBRIGHT|3, 1, {NULL}, 0, 0, S_QUICKBOOM5}, // S_QUICKBOOM4 + {SPR_KRBM, FF_FULLBRIGHT|4, 1, {NULL}, 0, 0, S_QUICKBOOM6}, // S_QUICKBOOM5 + {SPR_KRBM, FF_FULLBRIGHT|5, 1, {NULL}, 0, 0, S_QUICKBOOM7}, // S_QUICKBOOM6 + {SPR_KRBM, FF_FULLBRIGHT|6, 1, {NULL}, 0, 0, S_QUICKBOOM8}, // S_QUICKBOOM7 + {SPR_KRBM, FF_FULLBRIGHT|7, 2, {NULL}, 0, 0, S_QUICKBOOM9}, // S_QUICKBOOM8 + {SPR_KRBM, FF_FULLBRIGHT|8, 2, {NULL}, 0, 0, S_QUICKBOOM10}, // S_QUICKBOOM9 + {SPR_KRBM, FF_FULLBRIGHT|9, 2, {NULL}, 0, 0, S_NULL}, // S_QUICKBOOM10 + + {SPR_KRBM, FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_SLOWBOOM2}, // S_SLOWBOOM1 + {SPR_KRBM, FF_FULLBRIGHT|1, 3, {NULL}, 0, 0, S_SLOWBOOM3}, // S_SLOWBOOM2 + {SPR_KRBM, FF_FULLBRIGHT|2, 3, {NULL}, 0, 0, S_SLOWBOOM4}, // S_SLOWKBOOM3 + {SPR_KRBM, FF_FULLBRIGHT|3, 3, {NULL}, 0, 0, S_SLOWBOOM5}, // S_SLOWBOOM4 + {SPR_KRBM, FF_FULLBRIGHT|4, 3, {NULL}, 0, 0, S_SLOWBOOM6}, // S_SLOWBOOM5 + {SPR_KRBM, FF_FULLBRIGHT|5, 3, {NULL}, 0, 0, S_SLOWBOOM7}, // S_SLOWBOOM6 + {SPR_KRBM, FF_FULLBRIGHT|6, 3, {NULL}, 0, 0, S_SLOWBOOM8}, // S_SLOWBOOM7 + {SPR_KRBM, FF_FULLBRIGHT|7, 5, {NULL}, 0, 0, S_SLOWBOOM9}, // S_SLOWBOOM8 + {SPR_KRBM, FF_FULLBRIGHT|8, 5, {NULL}, 0, 0, S_SLOWBOOM10}, // S_SLOWBOOM9 + {SPR_KRBM, FF_FULLBRIGHT|9, 5, {NULL}, 0, 0, S_NULL}, // S_SLOWBOOM10 + + {SPR_BHOG, 0, 3, {A_PlaySound}, sfx_s1bd, 1, S_BALLHOG2}, // S_BALLHOG1 + {SPR_BHOG, FF_FULLBRIGHT|1, 1, {NULL}, 0, 0, S_BALLHOG3}, // S_BALLHOG2 + {SPR_BHOG, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_BALLHOG4}, // S_BALLHOG3 + {SPR_BHOG, FF_FULLBRIGHT|3, 3, {NULL}, 0, 0, S_BALLHOG5}, // S_BALLHOG4 + {SPR_BHOG, FF_FULLBRIGHT|4, 3, {NULL}, 0, 0, S_BALLHOG6}, // S_BALLHOG5 + {SPR_BHOG, 5, 2, {NULL}, 0, 0, S_BALLHOG7}, // S_BALLHOG6 + {SPR_BHOG, 6, 1, {NULL}, 0, 0, S_BALLHOG8}, // S_BALLHOG7 + {SPR_BHOG, 7, 1, {NULL}, 0, 0, S_BALLHOG1}, // S_BALLHOG8 + {SPR_NULL, 0, 1, {A_BallhogExplode}, 0, 0, S_NULL}, // S_BALLHOG_DEAD + {SPR_BHBM, FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_BALLHOGBOOM2}, // S_BALLHOGBOOM1 + {SPR_BHBM, FF_FULLBRIGHT|1, 1, {NULL}, 0, 0, S_BALLHOGBOOM3}, // S_BALLHOGBOOM2 + {SPR_BHBM, FF_FULLBRIGHT|2, 1, {NULL}, 0, 0, S_BALLHOGBOOM4}, // S_BALLHOGBOOM3 + {SPR_BHBM, FF_FULLBRIGHT|3, 1, {NULL}, 0, 0, S_BALLHOGBOOM5}, // S_BALLHOGBOOM4 + {SPR_BHBM, FF_FULLBRIGHT|4, 1, {NULL}, 0, 0, S_BALLHOGBOOM6}, // S_BALLHOGBOOM5 + {SPR_BHBM, FF_FULLBRIGHT|5, 1, {NULL}, 0, 0, S_BALLHOGBOOM7}, // S_BALLHOGBOOM6 + {SPR_BHBM, FF_FULLBRIGHT|6, 1, {NULL}, 0, 0, S_BALLHOGBOOM8}, // S_BALLHOGBOOM7 + {SPR_BHBM, FF_FULLBRIGHT|7, 1, {NULL}, 0, 0, S_BALLHOGBOOM9}, // S_BALLHOGBOOM8 + {SPR_BHBM, FF_FULLBRIGHT|8, 1, {NULL}, 0, 0, S_BALLHOGBOOM10}, // S_BALLHOGBOOM9 + {SPR_BHBM, FF_FULLBRIGHT|9, 1, {NULL}, 0, 0, S_BALLHOGBOOM11}, // S_BALLHOGBOOM10 + {SPR_BHBM, FF_FULLBRIGHT|10, 1, {NULL}, 0, 0, S_BALLHOGBOOM12}, // S_BALLHOGBOOM11 + {SPR_BHBM, FF_FULLBRIGHT|11, 1, {NULL}, 0, 0, S_BALLHOGBOOM13}, // S_BALLHOGBOOM12 + {SPR_BHBM, FF_FULLBRIGHT|12, 1, {NULL}, 0, 0, S_BALLHOGBOOM14}, // S_BALLHOGBOOM13 + {SPR_BHBM, FF_FULLBRIGHT|13, 1, {NULL}, 0, 0, S_BALLHOGBOOM15}, // S_BALLHOGBOOM14 + {SPR_BHBM, FF_FULLBRIGHT|14, 1, {NULL}, 0, 0, S_BALLHOGBOOM16}, // S_BALLHOGBOOM15 + {SPR_BHBM, FF_FULLBRIGHT|15, 1, {NULL}, 0, 0, S_NULL}, // S_BALLHOGBOOM16 {SPR_BLIG, 0, 2, {NULL}, 0, 0, S_BLUELIGHTNING2}, // S_BLUELIGHTNING1 {SPR_BLIG, 1, 2, {NULL}, 0, 0, S_BLUELIGHTNING3}, // S_BLUELIGHTNING2 {SPR_BLIG, 2, 2, {NULL}, 0, 0, S_BLUELIGHTNING4}, // S_BLUELIGHTNING3 {SPR_BLIG, 3, 2, {NULL}, 0, 0, S_NULL}, // S_BLUELIGHTNING4 - {SPR_BOMB, 0, 1, {A_BobombExplode}, MT_BLUEEXPLOSION, 0, S_NULL}, // S_BLUEEXPLODE + {SPR_SSMN, 0, 1, {A_MineExplode}, MT_BLUEEXPLOSION, 0, S_NULL}, // S_BLUEEXPLODE {SPR_LIGH, 0, 2, {NULL}, 0, 0, S_LIGHTNING2}, // S_LIGHTNING1 {SPR_LIGH, 1, 2, {NULL}, 0, 0, S_LIGHTNING3}, // S_LIGHTNING2 {SPR_LIGH, 2, 2, {NULL}, 0, 0, S_LIGHTNING4}, // S_LIGHTNING3 {SPR_LIGH, 3, 2, {NULL}, 0, 0, S_NULL}, // S_LIGHTNING4 + {SPR_THNS, 0, 2, {NULL}, 0, 0, S_THUNDERSHIELD2}, // S_THUNDERSHIELD1 + {SPR_THNS, 1, 2, {NULL}, 0, 0, S_THUNDERSHIELD3}, // S_THUNDERSHIELD2 + {SPR_THNS, 2, 2, {NULL}, 0, 0, S_THUNDERSHIELD4}, // S_THUNDERSHIELD3 + {SPR_THNS, 3, 2, {NULL}, 0, 0, S_THUNDERSHIELD5}, // S_THUNDERSHIELD4 + {SPR_THNS, 4, 2, {NULL}, 0, 0, S_THUNDERSHIELD6}, // S_THUNDERSHIELD5 + {SPR_THNS, 5, 2, {NULL}, 0, 0, S_THUNDERSHIELD7}, // S_THUNDERSHIELD6 + {SPR_THNS, 6, 2, {NULL}, 0, 0, S_THUNDERSHIELD8}, // S_THUNDERSHIELD7 + {SPR_THNS, 7, 2, {NULL}, 0, 0, S_THUNDERSHIELD9}, // S_THUNDERSHIELD8 + {SPR_THNS, 8, 2, {NULL}, 0, 0, S_THUNDERSHIELD10}, // S_THUNDERSHIELD9 + {SPR_THNS, 9, 2, {NULL}, 0, 0, S_THUNDERSHIELD11}, // S_THUNDERSHIELD10 + {SPR_THNS, 10, 2, {NULL}, 0, 0, S_THUNDERSHIELD12}, // S_THUNDERSHIELD11 + {SPR_THNS, 11, 2, {NULL}, 0, 0, S_THUNDERSHIELD13}, // S_THUNDERSHIELD12 + {SPR_THNS, 8, 2, {NULL}, 0, 0, S_THUNDERSHIELD14}, // S_THUNDERSHIELD13 + {SPR_THNS, 7, 2, {NULL}, 0, 0, S_THUNDERSHIELD15}, // S_THUNDERSHIELD14 + {SPR_THNS, 6, 2, {NULL}, 0, 0, S_THUNDERSHIELD16}, // S_THUNDERSHIELD15 + {SPR_THNS, 5, 2, {NULL}, 0, 0, S_THUNDERSHIELD17}, // S_THUNDERSHIELD16 + {SPR_THNS, 4, 2, {NULL}, 0, 0, S_THUNDERSHIELD18}, // S_THUNDERSHIELD17 + {SPR_THNS, 3, 2, {NULL}, 0, 0, S_THUNDERSHIELD19}, // S_THUNDERSHIELD18 + {SPR_THNS, 2, 2, {NULL}, 0, 0, S_THUNDERSHIELD20}, // S_THUNDERSHIELD19 + {SPR_THNS, 1, 2, {NULL}, 0, 0, S_THUNDERSHIELD21}, // S_THUNDERSHIELD20 + {SPR_THNS, 0, 2, {NULL}, 0, 0, S_THUNDERSHIELD22}, // S_THUNDERSHIELD21 + {SPR_THNS, 9, 2, {NULL}, 0, 0, S_THUNDERSHIELD23}, // S_THUNDERSHIELD22 + {SPR_THNS, 10, 2, {NULL}, 0, 0, S_THUNDERSHIELD24}, // S_THUNDERSHIELD23 + {SPR_THNS, 11, 2, {NULL}, 0, 0, S_THUNDERSHIELD1}, // S_THUNDERSHIELD24 + {SPR_SINK, 0, 4, {A_SmokeTrailer}, MT_SINKTRAIL, 0, S_SINK}, // S_SINK {SPR_SITR, 0, 1, {NULL}, 0, 0, S_SINKTRAIL2}, // S_SINKTRAIL1 {SPR_SITR, 1, 5, {NULL}, 0, 0, S_SINKTRAIL3}, // S_SINKTRAIL2 {SPR_SITR, 2, 3, {NULL}, 0, 0, S_NULL}, // S_SINKTRAIL3 - {SPR_KBLN, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_BATTLEBALLOON1}, // S_BATTLEBALLOON1 - {SPR_KBLN, FF_FULLBRIGHT|1, -1, {NULL}, 0, 0, S_BATTLEBALLOON2}, // S_BATTLEBALLOON2 - {SPR_KBLN, FF_FULLBRIGHT|2, -1, {NULL}, 0, 0, S_BATTLEBALLOON3}, // S_BATTLEBALLOON3 + {SPR_KBLN, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_BATTLEBUMPER1}, // S_BATTLEBUMPER1 + {SPR_KBLN, FF_FULLBRIGHT|1, -1, {NULL}, 0, 0, S_BATTLEBUMPER2}, // S_BATTLEBUMPER2 + {SPR_KBLN, FF_FULLBRIGHT|2, -1, {NULL}, 0, 0, S_BATTLEBUMPER3}, // S_BATTLEBUMPER3 - {SPR_LAKI, 0, 64, {NULL}, 1, 0, S_LAKITU2}, // S_LAKITU1 - {SPR_LAKI, 1, 35, {NULL}, 0, 0, S_NULL}, // S_LAKITU2 + {SPR_DEZL, FF_FULLBRIGHT|FF_PAPERSPRITE, 8, {NULL}, 0, 0, S_NULL}, // S_DEZLASER {SPR_POKE, 0, 2, {A_MoveAbsolute}, 0, 2, S_POKEY2}, // S_POKEY1 {SPR_POKE, 1, 2, {A_MoveAbsolute}, 0, 2, S_POKEY3}, // S_POKEY2 @@ -2812,12 +2881,20 @@ state_t states[NUMSTATES] = {SPR_DOOD, 11, -1, {NULL}, 0, 0, S_NULL}, // S_DOOD_BALLOON - {SPR_DOOD, 12, 4, {NULL}, 0, 0, S_DOOD_RING2}, // S_DOOD_RING1 - {SPR_DOOD, 13, 4, {NULL}, 0, 0, S_DOOD_RING3}, // S_DOOD_RING2 - {SPR_DOOD, 14, 4, {NULL}, 0, 0, S_DOOD_RING4}, // S_DOOD_RING3 - {SPR_DOOD, 15, 4, {NULL}, 0, 0, S_DOOD_RING5}, // S_DOOD_RING4 - {SPR_DOOD, 16, 4, {NULL}, 0, 0, S_DOOD_RING1}, // S_DOOD_RING5 + {SPR_BRNG, 0, 2, {NULL}, 0, 0, S_BIGRING02}, // S_BIGRING01 + {SPR_BRNG, 1, 2, {NULL}, 0, 0, S_BIGRING03}, // S_BIGRING02 + {SPR_BRNG, 2, 2, {NULL}, 0, 0, S_BIGRING04}, // S_BIGRING03 + {SPR_BRNG, 3, 2, {NULL}, 0, 0, S_BIGRING05}, // S_BIGRING04 + {SPR_BRNG, 4, 2, {NULL}, 0, 0, S_BIGRING06}, // S_BIGRING05 + {SPR_BRNG, 5, 2, {NULL}, 0, 0, S_BIGRING07}, // S_BIGRING06 + {SPR_BRNG, 6, 2, {NULL}, 0, 0, S_BIGRING08}, // S_BIGRING05 + {SPR_BRNG, 7, 2, {NULL}, 0, 0, S_BIGRING09}, // S_BIGRING05 + {SPR_BRNG, 8, 2, {NULL}, 0, 0, S_BIGRING10}, // S_BIGRING05 + {SPR_BRNG, 9, 2, {NULL}, 0, 0, S_BIGRING11}, // S_BIGRING10 + {SPR_BRNG, 10, 2, {NULL}, 0, 0, S_BIGRING12}, // S_BIGRING11 + {SPR_BRNG, 11, 2, {NULL}, 0, 0, S_BIGRING01}, // S_BIGRING12 + {SPR_SNES, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SNES_DONUTBUSH1 {SPR_SNES, 1, -1, {NULL}, 0, 0, S_NULL}, // S_SNES_DONUTBUSH2 {SPR_SNES, 2, -1, {NULL}, 0, 0, S_NULL}, // S_SNES_DONUTBUSH3 @@ -2885,29 +2962,41 @@ state_t states[NUMSTATES] = {SPR_PSHW, FF_FULLBRIGHT|2, 3, {NULL}, 0, 0, S_FIREDITEM4}, // S_FIREDITEM3 {SPR_PSHW, FF_FULLBRIGHT|3, 3, {NULL}, 0, 0, S_NULL}, // S_FIREDITEM4 + {SPR_ISTA, FF_FULLBRIGHT|FF_TRANS30, 2, {NULL}, 0, 0, S_INSTASHIELDA2}, // S_INSTASHIELDA1 + {SPR_ISTA, FF_FULLBRIGHT|FF_TRANS30|1, 2, {NULL}, 0, 0, S_INSTASHIELDA3}, // S_INSTASHIELDA2 + {SPR_ISTA, FF_FULLBRIGHT|FF_TRANS30|2, 2, {NULL}, 0, 0, S_INSTASHIELDA4}, // S_INSTASHIELDA3 + {SPR_ISTA, FF_FULLBRIGHT|FF_TRANS30|3, 2, {NULL}, 0, 0, S_INSTASHIELDA5}, // S_INSTASHIELDA4 + {SPR_ISTA, FF_FULLBRIGHT|FF_TRANS30|4, 2, {NULL}, 0, 0, S_INSTASHIELDA6}, // S_INSTASHIELDA5 + {SPR_ISTA, FF_FULLBRIGHT|FF_TRANS30|5, 2, {NULL}, 0, 0, S_INSTASHIELDA7}, // S_INSTASHIELDA6 + {SPR_ISTA, FF_FULLBRIGHT|FF_TRANS30|6, 2, {NULL}, 0, 0, S_NULL}, // S_INSTASHIELDA7 + + {SPR_ISTB, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_INSTASHIELDB2}, // S_INSTASHIELDB1 + {SPR_ISTB, FF_FULLBRIGHT|1, 2, {NULL}, 0, 0, S_INSTASHIELDB3}, // S_INSTASHIELDB2 + {SPR_ISTB, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_INSTASHIELDB4}, // S_INSTASHIELDB3 + {SPR_ISTB, FF_FULLBRIGHT|3, 2, {NULL}, 0, 0, S_INSTASHIELDB5}, // S_INSTASHIELDB4 + {SPR_ISTB, FF_FULLBRIGHT|4, 2, {NULL}, 0, 0, S_INSTASHIELDB6}, // S_INSTASHIELDB5 + {SPR_ISTB, FF_FULLBRIGHT|5, 2, {NULL}, 0, 0, S_INSTASHIELDB7}, // S_INSTASHIELDB6 + {SPR_ISTB, FF_FULLBRIGHT|6, 2, {NULL}, 0, 0, S_NULL}, // S_INSTASHIELDB7 + // Above player arrow {SPR_ARRO, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_PLAYERARROW - {SPR_ARRO, FF_FULLBRIGHT|1, -1, {NULL}, 0, 0, S_NULL}, // S_PLAYERARROW_MUSHROOM - {SPR_ARRO, FF_FULLBRIGHT|2, -1, {NULL}, 0, 0, S_NULL}, // S_PLAYERARROW_GREENSHELL - {SPR_ARRO, FF_FULLBRIGHT|3, -1, {NULL}, 0, 0, S_NULL}, // S_PLAYERARROW_BANANA - {SPR_ARRO, FF_FULLBRIGHT|4, -1, {NULL}, 0, 0, S_NULL}, // S_PLAYERARROW_FAKEITEM - {SPR_ARRO, FF_FULLBRIGHT|5, -1, {NULL}, 0, 0, S_NULL}, // S_PLAYERARROW_BOO - {SPR_ARRO, FF_FULLBRIGHT|6, -1, {NULL}, 0, 0, S_NULL}, // S_PLAYERARROW_FEATHER - {SPR_ARRO, FF_FULLBRIGHT|7, -1, {NULL}, 0, 0, S_NULL}, // S_PLAYERARROW_REDSHELL - {SPR_ARRO, FF_FULLBRIGHT|8, -1, {NULL}, 0, 0, S_NULL}, // S_PLAYERARROW_BOBOMB - {SPR_ARRO, FF_FULLBRIGHT|9, -1, {NULL}, 0, 0, S_NULL}, // S_PLAYERARROW_FIREFLOWER - {SPR_ARRO, FF_FULLBRIGHT|10, -1, {NULL}, 0, 0, S_NULL}, // S_PLAYERARROW_TRIPLEGREENSHELL - {SPR_ARRO, FF_FULLBRIGHT|11, -1, {NULL}, 0, 0, S_NULL}, // S_PLAYERARROW_TRIPLEBANANA - {SPR_ARRO, FF_FULLBRIGHT|12, -1, {NULL}, 0, 0, S_NULL}, // S_PLAYERARROW_TRIPLEREDSHELL - {SPR_ARRO, FF_FULLBRIGHT|13, -1, {NULL}, 0, 0, S_NULL}, // S_PLAYERARROW_STAR - {SPR_ARRO, FF_FULLBRIGHT|14, -1, {NULL}, 0, 0, S_NULL}, // S_PLAYERARROW_MEGASHROOM - {SPR_ARRO, FF_FULLBRIGHT|15, -1, {NULL}, 0, 0, S_NULL}, // S_PLAYERARROW_KITCHENSINK - {SPR_ARRO, FF_FULLBRIGHT|16, -1, {NULL}, 0, 0, S_NULL}, // S_PLAYERARROW_EMPTY - {SPR_ARRO, FF_FULLBRIGHT|FF_ANIMATE|1, -1, {NULL}, 5, 3, S_NULL}, // S_PLAYERARROW_ROULETTE + {SPR_ARRO, FF_FULLBRIGHT|1, -1, {NULL}, 0, 0, S_NULL}, // S_PLAYERARROW_BOX + {SPR_ITEM, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_PLAYERARROW_ITEM + {SPR_ITMN, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_PLAYERARROW_NUMBER + {SPR_ITMN, FF_FULLBRIGHT|10, 2, {NULL}, 0, 0, S_NULL}, // S_PLAYERARROW_X + {SPR_WANT, FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_PLAYERARROW_WANTED2}, // S_PLAYERARROW_WANTED1 + {SPR_WANT, FF_FULLBRIGHT|1, 1, {NULL}, 0, 0, S_PLAYERARROW_WANTED3}, // S_PLAYERARROW_WANTED2 + {SPR_WANT, FF_FULLBRIGHT|2, 3, {NULL}, 0, 0, S_PLAYERARROW_WANTED4}, // S_PLAYERARROW_WANTED3 + {SPR_WANT, FF_FULLBRIGHT|3, 1, {NULL}, 0, 0, S_PLAYERARROW_WANTED5}, // S_PLAYERARROW_WANTED4 + {SPR_WANT, FF_FULLBRIGHT|4, 3, {NULL}, 0, 0, S_PLAYERARROW_WANTED6}, // S_PLAYERARROW_WANTED5 + {SPR_WANT, FF_FULLBRIGHT|5, 1, {NULL}, 0, 0, S_PLAYERARROW_WANTED7}, // S_PLAYERARROW_WANTED6 + {SPR_WANT, FF_FULLBRIGHT|6, 3, {NULL}, 0, 0, S_PLAYERARROW_WANTED1}, // S_PLAYERARROW_WANTED7 + {SPR_PBOM, FF_ANIMATE, -1, {NULL}, 3, 3, S_NULL}, // S_PLAYERBOMB {SPR_RNDM, FF_ANIMATE, -1, {NULL}, 23, 3, S_NULL}, // S_PLAYERITEM - {SPR_PBOM, 4, -1, {NULL}, 0, 0, S_NULL}, // S_PLAYERWHEEL + + {SPR_PBOM, 4, -1, {NULL}, 0, 0, S_NULL}, // S_KARMAWHEEL #ifdef SEENAMES {SPR_NULL, 0, 1, {NULL}, 0, 0, S_NULL}, // S_NAMECHECK @@ -12004,7 +12093,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = { // MT_FIREBALL -1, // doomednum S_FIREBALL1, // spawnstate - 140, // spawnhealth + 1000, // spawnhealth S_FIREBALLEXP1, // seestate sfx_None, // seesound 8, // reactiontime @@ -12016,15 +12105,15 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_FIREBALLEXP1, // missilestate S_FIREBALLEXP1, // deathstate S_FIREBALLEXP1, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16*FRACUNIT, // radius - 32*FRACUNIT, // height + sfx_mario1, // deathsound + 10*FRACUNIT, // speed + 4*FRACUNIT, // radius + 8*FRACUNIT, // height 0, // display offset 100, // mass 1, // damage sfx_None, // activesound - MF_SHOOTABLE|MF_BOUNCE, // flags + MF_NOBLOCKMAP|MF_FIRE|MF_MISSILE, // flags S_NULL // raisestate }, @@ -13021,7 +13110,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // speed 16*FRACUNIT, // radius 48*FRACUNIT, // height - 0, // display offset + -1, // display offset 1000, // mass 8, // damage sfx_None, // activesound @@ -14293,14 +14382,14 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 16*FRACUNIT, // radius 32*FRACUNIT, // height 0, // display offset - MT_SPARK, // mass + MT_EXPLODE, // mass 0, // damage sfx_None, // activesound MF_NOCLIP, // flags S_NULL // raisestate }, - { // MT_MUSHROOMTRAIL + { // MT_SNEAKERTRAIL -1, // doomednum S_KARTFIRE1, // spawnstate 1, // spawnhealth @@ -14327,6 +14416,87 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_SPARKLETRAIL + -1, // doomednum + S_KARTINVULN_SMALL1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 8, // speed + 14*FRACUNIT, // radius + 14*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags + S_NULL // raisestate + }, + + { // MT_INVULNFLASH + -1, // doomednum + S_INVULNFLASH1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 8, // speed + 8*FRACUNIT, // radius + 8*FRACUNIT, // height + 1, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + + { // MT_WIPEOUTTRAIL + -1, // doomednum + S_WIPEOUTTRAIL1, // spawnstate + 1, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 8, // speed + 14*FRACUNIT, // radius + 14*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags + S_NULL // raisestate + }, + { // MT_DRIFT -1, // doomednum S_DRIFTSPARK1, // spawnstate @@ -14396,7 +14566,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // missilestate S_DEADFAKEITEM, // deathstate S_NULL, // xdeathstate - sfx_None, // deathsound + sfx_kc2e, // deathsound 8, // speed 16*FRACUNIT, // radius 32*FRACUNIT, // height @@ -14404,7 +14574,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_None, // activesound - MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY, // flags + MF_SPECIAL|MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY, // flags S_NULL // raisestate }, @@ -14423,7 +14593,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // missilestate S_DEADFAKEITEM, // deathstate S_NULL, // xdeathstate - sfx_None, // deathsound + sfx_kc2e, // deathsound 0, // speed 16*FRACUNIT, // radius 32*FRACUNIT, // height @@ -14431,121 +14601,13 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_fake, // activesound - MF_SHOOTABLE, // flags + MF_SPECIAL|MF_BOUNCE|MF_SHOOTABLE, // flags S_NULL // raisestate }, - { // MT_TRIPLEBANANASHIELD1 + { // MT_BANANA -1, // doomednum - S_BANANAITEM, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_DEADBANANA, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - k_banana, // speed - 16*FRACUNIT, // radius - 32*FRACUNIT, // height - 0, // display offset - 100, // mass - 1, // damage - sfx_None, // activesound - MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY, // flags - S_NULL // raisestate - }, - - { // MT_TRIPLEBANANASHIELD2 - -1, // doomednum - S_BANANAITEM, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_DEADBANANA, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - k_banana, // speed - 16*FRACUNIT, // radius - 32*FRACUNIT, // height - 0, // display offset - 100, // mass - 1, // damage - sfx_None, // activesound - MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY, // flags - S_NULL // raisestate - }, - - { // MT_TRIPLEBANANASHIELD3 - -1, // doomednum - S_BANANAITEM, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_DEADBANANA, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - k_banana, // speed - 16*FRACUNIT, // radius - 32*FRACUNIT, // height - 0, // display offset - 100, // mass - 1, // damage - sfx_None, // activesound - MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY, // flags - S_NULL // raisestate - }, - - { // MT_BANANASHIELD - -1, // doomednum - S_BANANAITEM, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_DEADBANANA, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - k_banana, // speed - 16*FRACUNIT, // radius - 32*FRACUNIT, // height - 0, // display offset - 100, // mass - 1, // damage - sfx_None, // activesound - MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY, // flags - S_NULL // raisestate - }, - - { // MT_BANANAITEM - -1, // doomednum - S_BANANAITEM, // spawnstate + S_BANANA, // spawnstate 2, // spawnhealth S_NULL, // seestate sfx_tossed, // seesound @@ -14556,7 +14618,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate - S_DEADBANANA, // deathstate + S_BANANA_DEAD, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed @@ -14566,13 +14628,13 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_peel, // activesound - MF_SHOOTABLE, // flags + MF_BOUNCE|MF_SHOOTABLE, // flags S_NULL // raisestate }, - { // MT_TRIPLEGREENSHIELD1 + { // MT_BANANA_SHIELD -1, // doomednum - S_TRIPLEGREENSHIELD1, // spawnstate + S_BANANA, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -14583,12 +14645,12 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate - S_DEADGREEN, // deathstate + S_BANANA_DEAD, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound - 10*FRACUNIT, // speed - 16*FRACUNIT, // radius - 32*FRACUNIT, // height + 0, // speed + 10*FRACUNIT, // radius + 24*FRACUNIT, // height 0, // display offset 100, // mass 1, // damage @@ -14597,117 +14659,36 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_TRIPLEGREENSHIELD2 + { // MT_ORBINAUT -1, // doomednum - S_TRIPLEGREENSHIELD4, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_DEADGREEN, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 10*FRACUNIT, // speed - 16*FRACUNIT, // radius - 32*FRACUNIT, // height - 0, // display offset - 100, // mass - 1, // damage - sfx_None, // activesound - MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY, // flags - S_NULL // raisestate - }, - - { // MT_TRIPLEGREENSHIELD3 - -1, // doomednum - S_TRIPLEGREENSHIELD7, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_DEADGREEN, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 10*FRACUNIT, // speed - 16*FRACUNIT, // radius - 32*FRACUNIT, // height - 0, // display offset - 100, // mass - 1, // damage - sfx_None, // activesound - MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY, // flags - S_NULL // raisestate - }, - - { // MT_GREENSHIELD - -1, // doomednum - S_GREENSHIELD1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_DEADGREEN, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - k_greenshell, // speed - 16*FRACUNIT, // radius - 32*FRACUNIT, // height - 0, // display offset - 100, // mass - 1, // damage - sfx_None, // activesound - MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY, // flags - S_NULL // raisestate - }, - - { // MT_GREENITEM - -1, // doomednum - S_GREENITEM1, // spawnstate + S_ORBINAUT1, // spawnstate 7, // spawnhealth S_NULL, // seestate sfx_tossed, // seesound 8, // reactiontime - sfx_mario1, // attacksound + sfx_s3k49, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate - S_DEADGREEN, // deathstate + S_ORBINAUT_DEAD,// deathstate S_NULL, // xdeathstate - sfx_shbrk, // deathsound + sfx_s3k5d, // deathsound 64*FRACUNIT, // speed 16*FRACUNIT, // radius 32*FRACUNIT, // height 0, // display offset 100, // mass 1, // damage - sfx_grnshl, // activesound + sfx_s3k96, // activesound MF_SHOOTABLE|MF_BOUNCE, // flags S_NULL // raisestate }, - { // MT_FIRETRAIL + { // MT_ORBINAUT_SHIELD -1, // doomednum - S_FIRETRAIL1, // spawnstate + S_ORBINAUT_SHIELD1, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -14718,37 +14699,10 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate - S_NULL, // deathstate + S_ORBINAUT_SHIELDDEAD, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound - 8, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 0, // display offset - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_SCENERY, // flags - S_NULL // raisestate - }, - - { // MT_TRIPLEREDSHIELD1 - -1, // doomednum - S_TRIPLEREDSHIELD2, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_DEADRED, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 10*FRACUNIT, // speed + 10*FRACUNIT, // speed 16*FRACUNIT, // radius 32*FRACUNIT, // height 0, // display offset @@ -14759,90 +14713,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_TRIPLEREDSHIELD2 + { // MT_JAWZ -1, // doomednum - S_TRIPLEREDSHIELD5, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_DEADRED, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 10*FRACUNIT, // speed - 16*FRACUNIT, // radius - 32*FRACUNIT, // height - 0, // display offset - 100, // mass - 1, // damage - sfx_None, // activesound - MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY, // flags - S_NULL // raisestate - }, - - { // MT_TRIPLEREDSHIELD3 - -1, // doomednum - S_TRIPLEREDSHIELD8, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_DEADRED, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 10*FRACUNIT, // speed - 16*FRACUNIT, // radius - 32*FRACUNIT, // height - 0, // display offset - 100, // mass - 1, // damage - sfx_None, // activesound - MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY, // flags - S_NULL // raisestate - }, - - { // MT_REDSHIELD - -1, // doomednum - S_REDSHIELD1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_DEADRED, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - k_redshell, // speed - 16*FRACUNIT, // radius - 32*FRACUNIT, // height - 0, // display offset - 100, // mass - 1, // damage - sfx_None, // activesound - MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY, // flags - S_NULL // raisestate - }, - - { // MT_REDITEM - -1, // doomednum - S_REDITEM1, // spawnstate + S_JAWZ1, // spawnstate 1, // spawnhealth S_NULL, // seestate sfx_tossed, // seesound @@ -14853,23 +14726,23 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate - S_DEADRED, // deathstate - S_NULL, // xdeathstate - sfx_shbrk, // deathsound + S_JAWZ_DEAD1, // deathstate + S_JAWZ_DEAD2, // xdeathstate + sfx_s3k5d, // deathsound 7*FRACUNIT, // speed 16*FRACUNIT, // radius 32*FRACUNIT, // height 0, // display offset 100, // mass 1, // damage - sfx_redshl, // activesound + sfx_s3kc0s, // activesound MF_SHOOTABLE, // flags S_NULL // raisestate }, - { // MT_REDITEMDUD + { // MT_JAWZ_DUD -1, // doomednum - S_REDITEM1, // spawnstate + S_JAWZ_DUD1, // spawnstate 1, // spawnhealth S_NULL, // seestate sfx_tossed, // seesound @@ -14880,37 +14753,37 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate - S_DEADRED, // deathstate - S_NULL, // xdeathstate - sfx_shbrk, // deathsound + S_JAWZ_DEAD1, // deathstate + S_JAWZ_DEAD2, // xdeathstate + sfx_s3k5d, // deathsound 56*FRACUNIT, // speed 16*FRACUNIT, // radius 32*FRACUNIT, // height 0, // display offset 100, // mass 1, // damage - sfx_redshl, // activesound + sfx_s3kc0s, // activesound MF_SHOOTABLE, // flags S_NULL // raisestate }, - { // MT_BOMBSHIELD + { // MT_JAWZ_SHIELD -1, // doomednum - S_BOMBSHIELD, // spawnstate + S_JAWZ_SHIELD1, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate - 256*FRACUNIT, // painchance + 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate - S_BOMBEXPLODE, // deathstate - S_NULL, // xdeathstate + S_JAWZ_DEAD1, // deathstate + S_JAWZ_DEAD2, // xdeathstate sfx_None, // deathsound - k_bobomb, // speed + 10*FRACUNIT, // speed 16*FRACUNIT, // radius 32*FRACUNIT, // height 0, // display offset @@ -14921,36 +14794,63 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_BOMBITEM + { // MT_SSMINE + -1, // doomednum + S_SSMINE_AIR1, // spawnstate + 1, // spawnhealth + S_NULL, // seestate + sfx_tossed, // seesound + 6*TICRATE, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 288*FRACUNIT, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_SSMINE_EXPLODE, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 24*FRACUNIT, // height + 0, // display offset + 100, // mass + 1, // damage + sfx_s3k5c, // activesound + MF_BOUNCE|MF_SHOOTABLE, // flags + S_NULL // raisestate + }, + + { // MT_SSMINE_SHIELD -1, // doomednum - S_BOMBAIR, // spawnstate - 1, // spawnhealth + S_SSMINE_SHIELD1, // spawnstate + 1000, // spawnhealth S_NULL, // seestate - sfx_tossed, // seesound - 105, // reactiontime + sfx_None, // seesound + 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate - 288*FRACUNIT, // painchance + 320*FRACUNIT, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate - S_BOMBEXPLODE, // deathstate + S_SSMINE_EXPLODE, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound - 0, // speed + 10*FRACUNIT, // speed 16*FRACUNIT, // radius - 24*FRACUNIT, // height + 32*FRACUNIT, // height 0, // display offset 100, // mass 1, // damage - sfx_bomb, // activesound - MF_BOUNCE|MF_SHOOTABLE, // flags + sfx_None, // activesound + MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY, // flags S_NULL // raisestate }, - { // MT_BOMBEXPLOSION + { // MT_MINEEXPLOSION -1, // doomednum - S_BOMBEXPLOSION1, // spawnstate + S_MINEEXPLOSION1, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -14975,7 +14875,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_BOMBEXPLOSIONSOUND + { // MT_MINEEXPLOSIONSOUND -1, // doomednum S_INVISIBLE, // spawnstate 100, // spawnhealth @@ -15083,6 +14983,60 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_BALLHOG + -1, // doomednum + S_BALLHOG1, // spawnstate + 140, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_BALLHOG_DEAD, // deathstate + S_NULL, // xdeathstate + sfx_hogbom, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 32*FRACUNIT, // height + 0, // display offset + 100, // mass + 1, // damage + sfx_None, // activesound + MF_SHOOTABLE|MF_BOUNCE, // flags + S_NULL // raisestate + }, + + { // MT_BALLHOGBOOM + -1, // doomednum + S_BALLHOGBOOM1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 32*FRACUNIT, // height + 0, // display offset + 100, // mass + 1, // damage + sfx_None, // activesound + MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOCLIPTHING, // flags + S_NULL // raisestate + }, + { // MT_BLUELIGHTNING -1, // doomednum S_BLUELIGHTNING1, // spawnstate @@ -15123,7 +15077,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate - S_BOMBEXPLODE, // deathstate + S_SSMINE_EXPLODE, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed @@ -15164,12 +15118,39 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_THUNDERSHIELD + -1, // doomednum + S_THUNDERSHIELD1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 8, // speed + 16*FRACUNIT, // radius + 56*FRACUNIT, // height + 1, // display offset + 16, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + { // MT_SINK -1, // doomednum S_SINK, // spawnstate 105, // spawnhealth S_NULL, // seestate - sfx_None, // seesound + sfx_tossed, // seesound 8, // reactiontime sfx_None, // attacksound 256*FRACUNIT, // painstate @@ -15179,7 +15160,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate - sfx_shbrk, // deathsound + sfx_s3k5d, // deathsound 0, // speed 16*FRACUNIT, // radius 24*FRACUNIT, // height @@ -15187,7 +15168,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_bomb, // activesound - MF_BOUNCE|MF_FLOAT|MF_NOCLIPTHING|MF_MISSILE|MF_SHOOTABLE, // flags + MF_BOUNCE|MF_SHOOTABLE, // flags S_NULL // raisestate }, @@ -15218,9 +15199,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_BATTLEBALLOON + { // MT_BATTLEBUMPER -1, // doomednum - S_BATTLEBALLOON1,// spawnstate + S_BATTLEBUMPER1,// spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -15245,9 +15226,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_LAKITU + { // MT_DEZLASER -1, // doomednum - S_LAKITU1, // spawnstate + S_DEZLASER, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -15262,13 +15243,13 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_None, // deathsound 8, // speed - 64*FRACUNIT, // radius - 57*FRACUNIT, // height - 0, // display offset + 42*FRACUNIT, // radius + 8*FRACUNIT, // height + 1, // display offset 16, // mass 0, // damage sfx_None, // activesound - MF_NOGRAVITY, // flags + MF_NOBLOCKMAP|MF_NOCLIPHEIGHT|MF_NOCLIPTHING|MF_NOGRAVITY|MF_SCENERY, // flags S_NULL // raisestate }, @@ -16055,9 +16036,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_DOOD_RING + { // MT_BIGRING 2808, // doomednum - S_DOOD_RING1, // spawnstate + S_BIGRING01, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -16072,13 +16053,13 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed - 1048576, // radius - 2097152, // height + 26*FRACUNIT, // radius + 62*FRACUNIT, // height 0, // display offset 100, // mass 0, // damage sfx_None, // activesound - 33554944, // flags + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOGRAVITY|MF_SCENERY, // flags S_NULL // raisestate }, @@ -16105,7 +16086,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 0, // damage sfx_None, // activesound - MF_NOGRAVITY|MF_SCENERY, // flags + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOTHINK, // flags S_NULL // raisestate }, @@ -16132,7 +16113,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 0, // damage sfx_None, // activesound - MF_NOGRAVITY|MF_SCENERY, // flags + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOTHINK, // flags S_NULL // raisestate }, @@ -16159,7 +16140,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 0, // damage sfx_None, // activesound - MF_NOGRAVITY|MF_SCENERY, // flags + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOTHINK, // flags S_NULL // raisestate }, @@ -16730,6 +16711,60 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_INSTASHIELDA + -1, // doomednum + S_INSTASHIELDA1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 8, // speed + 8*FRACUNIT, // radius + 8*FRACUNIT, // height + 1, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT, // flags + S_NULL // raisestate + }, + + { // MT_INSTASHIELDB + -1, // doomednum + S_INSTASHIELDB1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 8, // speed + 8*FRACUNIT, // radius + 8*FRACUNIT, // height + 2, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT, // flags + S_NULL // raisestate + }, + { // MT_PLAYERARROW -1, // doomednum S_PLAYERARROW, // spawnstate @@ -16757,6 +16792,87 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_PLAYERWANTED + -1, // doomednum + S_PLAYERARROW_WANTED1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 8, // speed + 36*FRACUNIT, // radius + 37*FRACUNIT, // height + 0, // display offset + 16, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags + S_NULL // raisestate + }, + + { // MT_KARMAHITBOX + -1, // doomednum + S_PLAYERBOMB, // spawnstate + 1000, // spawnhealth + S_PLAYERITEM, // seestate + sfx_kc2e, // seesound + 8, // reactiontime + sfx_s3k4e, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 26*FRACUNIT, // radius + 52*FRACUNIT, // height + -1, // display offset + 0, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL|MF_NOCLIPHEIGHT|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + + { // MT_KARMAWHEEL + -1, // doomednum + S_KARMAWHEEL, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 8*FRACUNIT, // radius + 16*FRACUNIT, // height + 0, // display offset + 0, // mass + 0, // damage + sfx_None, // activesound + MF_NOTHINK|MF_NOCLIP|MF_NOCLIPHEIGHT, // flags + S_NULL // raisestate + }, + // ============================================================================================================================// #ifdef SEENAMES diff --git a/src/info.h b/src/info.h index a223beca..98d628b3 100644 --- a/src/info.h +++ b/src/info.h @@ -164,8 +164,10 @@ void A_DualAction(); void A_RemoteAction(); void A_ToggleFlameJet(); void A_ItemPop(); // SRB2kart -void A_RedShellChase(); // SRB2kart -void A_BobombExplode(); // SRB2kart +void A_JawzChase(); // SRB2kart +void A_JawzExplode(); // SRB2kart +void A_MineExplode(); // SRB2kart +void A_BallhogExplode(); // SRB2kart void A_OrbitNights(); void A_GhostMe(); void A_SetObjectState(); @@ -580,28 +582,30 @@ typedef enum sprite SPR_RNDM, // Random Item Box SPR_RPOP, // Random Item Box Pop - SPR_KFRE, // Mushroom fire trail + SPR_KFRE, // Sneaker fire trail + SPR_KINV, // Invincibility sparkle trail + SPR_KINF, // Invincibility flash + SPR_WIPD, // Wipeout dust trail SPR_DRIF, // Drift Sparks SPR_DUST, // Drift Dust // Kart Items - SPR_FITM, // Fake Item box - SPR_DFAK, // Dead Fake Item + SPR_FITM, // Eggman Monitor SPR_BANA, // Banana Peel - SPR_DBAN, // Dead Banana Peel - SPR_GSHE, // Green Shell - SPR_DGSH, // Dead Green Shell - SPR_RSHE, // Red Shell - SPR_DRSH, // Dead Red Shell - SPR_BOMB, // Bob-omb - SPR_KRBM, - SPR_BLIG, // Blue Lightning - SPR_LIGH, // Lightning + SPR_ORBN, // Orbinaut + SPR_JAWZ, // Jawz + SPR_SSMN, // SS Mine + SPR_KRBM, // SS Mine BOOM + SPR_BHOG, // Ballhog + SPR_BHBM, // Ballhog BOOM + SPR_BLIG, // Self-Propelled Bomb + SPR_LIGH, // Grow/shrink beams (Metallic Maddness) + SPR_THNS, // Thunder Shield SPR_SINK, // Kitchen Sink SPR_SITR, // Kitchen Sink Trail - SPR_KBLN, // Battle Mode Balloon + SPR_KBLN, // Battle Mode Bumper - SPR_LAKI, // Lakitu + SPR_DEZL, // DEZ Laser respawn // Additional Kart Objects SPR_POKE, // Pokey @@ -616,16 +620,26 @@ typedef enum sprite SPR_SACO, // Sapphire Coast Fauna SPR_CRAB, // Crystal Abyss mobs SPR_SHAD, // TD shadows + SPR_BRNG, // Chaotix Big Ring SPR_BUMP, // Player/shell bump SPR_FLEN, // Shell hit graphics stuff SPR_CLAS, // items clash SPR_PSHW, // thrown indicator + SPR_ISTA, // instashield layer A + SPR_ISTB, // instashield layer B SPR_ARRO, // player arrows + SPR_ITEM, + SPR_ITMO, + SPR_ITMI, + SPR_ITMN, + SPR_WANT, SPR_PBOM, // player bomb + SPR_VIEW, // First person view sprites; this is a sprite so that it can be replaced by a specialized MD2 draw! + SPR_FIRSTFREESLOT, SPR_LASTFREESLOT = SPR_FIRSTFREESLOT + NUMSPRITEFREESLOTS - 1, NUMSPRITES @@ -2647,15 +2661,9 @@ typedef enum state S_FIREBALL2, S_FIREBALL3, S_FIREBALL4, - S_FIREBALL5, - S_FIREBALL6, - S_FIREBALL7, S_FIREBALLEXP1, S_FIREBALLEXP2, S_FIREBALLEXP3, - S_FIREBALLEXP4, - S_FIREBALLEXP5, - S_FIREBALLEXP6, S_SHELL, S_SHELL1, S_SHELL2, @@ -3085,7 +3093,7 @@ typedef enum state // Magnet Burst - // Mushroom Fire Trail + // Sneaker Fire Trail S_KARTFIRE1, S_KARTFIRE2, S_KARTFIRE3, @@ -3095,7 +3103,33 @@ typedef enum state S_KARTFIRE7, S_KARTFIRE8, - //{ Fake Item + // Invincibility Sparks + S_KARTINVULN_SMALL1, + S_KARTINVULN_SMALL2, + S_KARTINVULN_SMALL3, + S_KARTINVULN_SMALL4, + S_KARTINVULN_SMALL5, + + S_KARTINVULN_LARGE1, + S_KARTINVULN_LARGE2, + S_KARTINVULN_LARGE3, + S_KARTINVULN_LARGE4, + S_KARTINVULN_LARGE5, + + // Invincibility flash + S_INVULNFLASH1, + S_INVULNFLASH2, + S_INVULNFLASH3, + S_INVULNFLASH4, + + // Wipeout dust trail + S_WIPEOUTTRAIL1, + S_WIPEOUTTRAIL2, + S_WIPEOUTTRAIL3, + S_WIPEOUTTRAIL4, + S_WIPEOUTTRAIL5, + + //{ Eggman Monitor S_FAKEITEM1, S_FAKEITEM2, S_FAKEITEM3, @@ -3124,81 +3158,79 @@ typedef enum state //} // Banana - S_BANANAITEM, - S_DEADBANANA, + S_BANANA, + S_BANANA_DEAD, - //{ Green Shell - S_TRIPLEGREENSHIELD1, - S_TRIPLEGREENSHIELD2, - S_TRIPLEGREENSHIELD3, - S_TRIPLEGREENSHIELD4, - S_TRIPLEGREENSHIELD5, - S_TRIPLEGREENSHIELD6, - S_TRIPLEGREENSHIELD7, - S_TRIPLEGREENSHIELD8, - S_GREENSHIELD1, - S_GREENSHIELD2, - S_GREENSHIELD3, - S_GREENSHIELD4, - S_GREENSHIELD5, - S_GREENSHIELD6, - S_GREENSHIELD7, - S_GREENSHIELD8, - S_GREENITEM1, - S_GREENITEM2, - S_GREENITEM3, - S_GREENITEM4, - S_GREENITEM5, - S_GREENITEM6, - S_GREENITEM7, - S_GREENITEM8, - S_DEADGREEN, + //{ Orbinaut + S_ORBINAUT1, + S_ORBINAUT2, + S_ORBINAUT3, + S_ORBINAUT4, + S_ORBINAUT5, + S_ORBINAUT6, + S_ORBINAUT_DEAD, + S_ORBINAUT_SHIELD1, + S_ORBINAUT_SHIELD2, + S_ORBINAUT_SHIELD3, + S_ORBINAUT_SHIELD4, + S_ORBINAUT_SHIELD5, + S_ORBINAUT_SHIELD6, + S_ORBINAUT_SHIELDDEAD, //} - //{ Red Shell - S_TRIPLEREDSHIELD1, - S_TRIPLEREDSHIELD2, - S_TRIPLEREDSHIELD3, - S_TRIPLEREDSHIELD4, - S_TRIPLEREDSHIELD5, - S_TRIPLEREDSHIELD6, - S_TRIPLEREDSHIELD7, - S_TRIPLEREDSHIELD8, - S_REDSHIELD1, - S_REDSHIELD2, - S_REDSHIELD3, - S_REDSHIELD4, - S_REDSHIELD5, - S_REDSHIELD6, - S_REDSHIELD7, - S_REDSHIELD8, - S_REDITEM1, - S_REDITEM2, - S_REDITEM3, - S_REDITEM4, - S_REDITEM5, - S_REDITEM6, - S_REDITEM7, - S_REDITEM8, - S_DEADRED, + //{ Jawz + S_JAWZ1, + S_JAWZ2, + S_JAWZ3, + S_JAWZ4, + S_JAWZ5, + S_JAWZ6, + S_JAWZ7, + S_JAWZ8, + S_JAWZ_DUD1, + S_JAWZ_DUD2, + S_JAWZ_DUD3, + S_JAWZ_DUD4, + S_JAWZ_DUD5, + S_JAWZ_DUD6, + S_JAWZ_DUD7, + S_JAWZ_DUD8, + S_JAWZ_SHIELD1, + S_JAWZ_SHIELD2, + S_JAWZ_SHIELD3, + S_JAWZ_SHIELD4, + S_JAWZ_SHIELD5, + S_JAWZ_SHIELD6, + S_JAWZ_SHIELD7, + S_JAWZ_SHIELD8, + S_JAWZ_DEAD1, + S_JAWZ_DEAD2, //} - S_FIRETRAIL1, - S_FIRETRAIL2, - S_FIRETRAIL3, - S_FIRETRAIL4, - S_FIRETRAIL5, - S_FIRETRAIL6, - S_FIRETRAIL7, - S_FIRETRAIL8, - S_FIRETRAIL9, - - // Bob-omb - S_BOMBSHIELD, - S_BOMBITEM, - S_BOMBAIR, - S_BOMBEXPLODE, - S_BOMBEXPLOSION1, - S_BOMBEXPLOSION2, + // Special Stage Mine + S_SSMINE1, + S_SSMINE2, + S_SSMINE3, + S_SSMINE4, + S_SSMINE_SHIELD1, + S_SSMINE_SHIELD2, + S_SSMINE_AIR1, + S_SSMINE_AIR2, + S_SSMINE_DEPLOY1, + S_SSMINE_DEPLOY2, + S_SSMINE_DEPLOY3, + S_SSMINE_DEPLOY4, + S_SSMINE_DEPLOY5, + S_SSMINE_DEPLOY6, + S_SSMINE_DEPLOY7, + S_SSMINE_DEPLOY8, + S_SSMINE_DEPLOY9, + S_SSMINE_DEPLOY10, + S_SSMINE_DEPLOY11, + S_SSMINE_DEPLOY12, + S_SSMINE_DEPLOY13, + S_SSMINE_EXPLODE, + S_MINEEXPLOSION1, + S_MINEEXPLOSION2, // New explosion S_QUICKBOOM1, @@ -3223,33 +3255,85 @@ typedef enum state S_SLOWBOOM9, S_SLOWBOOM10, - // Blue Shell - Blue Lightning for now... + // Ballhog + S_BALLHOG1, + S_BALLHOG2, + S_BALLHOG3, + S_BALLHOG4, + S_BALLHOG5, + S_BALLHOG6, + S_BALLHOG7, + S_BALLHOG8, + S_BALLHOG_DEAD, + S_BALLHOGBOOM1, + S_BALLHOGBOOM2, + S_BALLHOGBOOM3, + S_BALLHOGBOOM4, + S_BALLHOGBOOM5, + S_BALLHOGBOOM6, + S_BALLHOGBOOM7, + S_BALLHOGBOOM8, + S_BALLHOGBOOM9, + S_BALLHOGBOOM10, + S_BALLHOGBOOM11, + S_BALLHOGBOOM12, + S_BALLHOGBOOM13, + S_BALLHOGBOOM14, + S_BALLHOGBOOM15, + S_BALLHOGBOOM16, + + // Self-Propelled Bomb - just an explosion for now... S_BLUELIGHTNING1, S_BLUELIGHTNING2, S_BLUELIGHTNING3, S_BLUELIGHTNING4, S_BLUEEXPLODE, - // Lightning + // Grow/Shrink S_LIGHTNING1, S_LIGHTNING2, S_LIGHTNING3, S_LIGHTNING4, + // Thunder Shield + S_THUNDERSHIELD1, + S_THUNDERSHIELD2, + S_THUNDERSHIELD3, + S_THUNDERSHIELD4, + S_THUNDERSHIELD5, + S_THUNDERSHIELD6, + S_THUNDERSHIELD7, + S_THUNDERSHIELD8, + S_THUNDERSHIELD9, + S_THUNDERSHIELD10, + S_THUNDERSHIELD11, + S_THUNDERSHIELD12, + S_THUNDERSHIELD13, + S_THUNDERSHIELD14, + S_THUNDERSHIELD15, + S_THUNDERSHIELD16, + S_THUNDERSHIELD17, + S_THUNDERSHIELD18, + S_THUNDERSHIELD19, + S_THUNDERSHIELD20, + S_THUNDERSHIELD21, + S_THUNDERSHIELD22, + S_THUNDERSHIELD23, + S_THUNDERSHIELD24, + // The legend S_SINK, S_SINKTRAIL1, S_SINKTRAIL2, S_SINKTRAIL3, - // Battle Mode balloons - S_BATTLEBALLOON1, - S_BATTLEBALLOON2, - S_BATTLEBALLOON3, + // Battle Mode bumpers + S_BATTLEBUMPER1, + S_BATTLEBUMPER2, + S_BATTLEBUMPER3, - // Lakitu - S_LAKITU1, - S_LAKITU2, + // DEZ Laser respawn + S_DEZLASER, // Pokey S_POKEY1, @@ -3329,15 +3413,22 @@ typedef enum state S_DOOD_BOX4, S_DOOD_BOX5, - // D00Dkart - Diddy Kong Racing Balloon + // D00Dkart - Diddy Kong Racing Bumper S_DOOD_BALLOON, - // D00Dkart - Big Ring - S_DOOD_RING1, - S_DOOD_RING2, - S_DOOD_RING3, - S_DOOD_RING4, - S_DOOD_RING5, + // Chaotix Big Ring + S_BIGRING01, + S_BIGRING02, + S_BIGRING03, + S_BIGRING04, + S_BIGRING05, + S_BIGRING06, + S_BIGRING07, + S_BIGRING08, + S_BIGRING09, + S_BIGRING10, + S_BIGRING11, + S_BIGRING12, // SNES Objects S_SNES_DONUTBUSH1, @@ -3409,28 +3500,38 @@ typedef enum state S_FIREDITEM3, S_FIREDITEM4, + S_INSTASHIELDA1, // No damage instashield effect + S_INSTASHIELDA2, + S_INSTASHIELDA3, + S_INSTASHIELDA4, + S_INSTASHIELDA5, + S_INSTASHIELDA6, + S_INSTASHIELDA7, + S_INSTASHIELDB1, + S_INSTASHIELDB2, + S_INSTASHIELDB3, + S_INSTASHIELDB4, + S_INSTASHIELDB5, + S_INSTASHIELDB6, + S_INSTASHIELDB7, + S_PLAYERARROW, // Above player arrow - S_PLAYERARROW_MUSHROOM, - S_PLAYERARROW_GREENSHELL, - S_PLAYERARROW_BANANA, - S_PLAYERARROW_FAKEITEM, - S_PLAYERARROW_BOO, - S_PLAYERARROW_FEATHER, - S_PLAYERARROW_REDSHELL, - S_PLAYERARROW_BOBOMB, - S_PLAYERARROW_FIREFLOWER, - S_PLAYERARROW_TRIPLEGREENSHELL, - S_PLAYERARROW_TRIPLEBANANA, - S_PLAYERARROW_TRIPLEREDSHELL, - S_PLAYERARROW_STAR, - S_PLAYERARROW_MEGASHROOM, - S_PLAYERARROW_KITCHENSINK, - S_PLAYERARROW_EMPTY, - S_PLAYERARROW_ROULETTE, + S_PLAYERARROW_BOX, + S_PLAYERARROW_ITEM, + S_PLAYERARROW_NUMBER, + S_PLAYERARROW_X, + S_PLAYERARROW_WANTED1, + S_PLAYERARROW_WANTED2, + S_PLAYERARROW_WANTED3, + S_PLAYERARROW_WANTED4, + S_PLAYERARROW_WANTED5, + S_PLAYERARROW_WANTED6, + S_PLAYERARROW_WANTED7, S_PLAYERBOMB, S_PLAYERITEM, - S_PLAYERWHEEL, + + S_KARMAWHEEL, #ifdef SEENAMES S_NAMECHECK, @@ -3966,52 +4067,50 @@ typedef enum mobj_type MT_RANDOMITEM, MT_RANDOMITEMPOP, - MT_MUSHROOMTRAIL, + MT_SNEAKERTRAIL, + MT_SPARKLETRAIL, + MT_INVULNFLASH, + MT_WIPEOUTTRAIL, MT_DRIFT, MT_DRIFTDUST, MT_FAKESHIELD, MT_FAKEITEM, - MT_TRIPLEBANANASHIELD1, // Banana Stuff - MT_TRIPLEBANANASHIELD2, - MT_TRIPLEBANANASHIELD3, - MT_BANANASHIELD, - MT_BANANAITEM, + MT_BANANA, // Banana Stuff + MT_BANANA_SHIELD, - MT_TRIPLEGREENSHIELD1, // Green shell stuff - MT_TRIPLEGREENSHIELD2, - MT_TRIPLEGREENSHIELD3, - MT_GREENSHIELD, - MT_GREENITEM, - MT_FIRETRAIL, + MT_ORBINAUT, // Orbinaut stuff + MT_ORBINAUT_SHIELD, - MT_TRIPLEREDSHIELD1, // Red shell stuff - MT_TRIPLEREDSHIELD2, - MT_TRIPLEREDSHIELD3, - MT_REDSHIELD, - MT_REDITEM, - MT_REDITEMDUD, + MT_JAWZ, // Jawz stuff + MT_JAWZ_DUD, + MT_JAWZ_SHIELD, - MT_BOMBSHIELD, // Bob-omb stuff - MT_BOMBITEM, - MT_BOMBEXPLOSION, - MT_BOMBEXPLOSIONSOUND, + MT_SSMINE, // Mine stuff + MT_SSMINE_SHIELD, + MT_MINEEXPLOSION, + MT_MINEEXPLOSIONSOUND, MT_SMOLDERING, // New explosion MT_BOOMEXPLODE, MT_BOOMPARTICLE, - MT_BLUELIGHTNING, // Lightning stuff + MT_BALLHOG, // Ballhog + MT_BALLHOGBOOM, + + MT_BLUELIGHTNING, // Grow/shrink stuff MT_BLUEEXPLOSION, MT_LIGHTNING, + MT_THUNDERSHIELD, // Thunder Shield stuff + MT_SINK, // Kitchen Sink Stuff MT_SINKTRAIL, - MT_BATTLEBALLOON, // Battle Mode balloons + MT_BATTLEBUMPER, // Battle Mode bumpers - MT_LAKITU, + MT_DEZLASER, MT_POKEY, // Huh, thought this was a default asset for some reason, guess not. @@ -4047,7 +4146,7 @@ typedef enum mobj_type MT_DOOD_FLOWER4, MT_DOOD_BOX, MT_DOOD_BALLOON, - MT_DOOD_RING, + MT_BIGRING, MT_SNES_DONUTBUSH1, MT_SNES_DONUTBUSH2, @@ -4082,7 +4181,14 @@ typedef enum mobj_type MT_FIREDITEM, + MT_INSTASHIELDA, + MT_INSTASHIELDB, + MT_PLAYERARROW, + MT_PLAYERWANTED, + + MT_KARMAHITBOX, + MT_KARMAWHEEL, #ifdef SEENAMES MT_NAMECHECK, diff --git a/src/k_kart.c b/src/k_kart.c index e80772f2..6a7efffc 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -17,6 +17,7 @@ #include "v_video.h" #include "z_zone.h" #include "m_misc.h" +#include "m_cond.h" #include "k_kart.h" #include "f_finale.h" @@ -25,9 +26,11 @@ // franticitems is Frantic Mode items, bool // mirrormode is Mirror Mode (duh), bool // comeback is Battle Mode's karma comeback, also bool -// lightningcooldown is timer before anyone's allowed another lightning/blue shell -// blueshellincoming is the timer before k_deathsentence is cast on the player in 1st -// blueshellplayer is the last player who fired one +// battlewanted is an array of the WANTED player nums, -1 for no player in that slot +// indirectitemcooldown is timer before anyone's allowed another Shrink/SPB +// spbincoming is the timer before k_deathsentence is cast on the player in 1st +// spbplayer is the last player who fired a SPB +// mapreset is set when enough players fill an empty server //{ SRB2kart Color Code @@ -45,143 +48,217 @@ const char *KartColor_Names[MAXSKINCOLORS] = "Silver", // 03 // SKINCOLOR_SILVER "Cloudy", // 04 // SKINCOLOR_CLOUDY "Grey", // 05 // SKINCOLOR_GREY - "Dark Grey", // 06 // SKINCOLOR_DARKGREY + "Nickel", // 06 // SKINCOLOR_NICKEL "Black", // 07 // SKINCOLOR_BLACK "Salmon", // 08 // SKINCOLOR_SALMON "Pink", // 09 // SKINCOLOR_PINK - "Light Red", // 10 // SKINCOLOR_LIGHTRED - "Shiny Red", // 11 // SKINCOLOR_SHINYRED + "Rose", // 10 // SKINCOLOR_ROSE + "Raspberry", // 11 // SKINCOLOR_RASPBERRY "Red", // 12 // SKINCOLOR_RED - "Dark Pink", // 13 // SKINCOLOR_DARKPINK - "Dark Red", // 14 // SKINCOLOR_DARKRED + "Ruby", // 13 // SKINCOLOR_RUBY + "Crimson", // 14 // SKINCOLOR_CRIMSON "Dawn", // 15 // SKINCOLOR_DAWN - "Orange", // 16 // SKINCOLOR_ORANGE - "Shiny Orange", // 17 // SKINCOLOR_SHINYORANGE - "Dark Orange", // 18 // SKINCOLOR_DARKORANGE - "Golden Brown", // 19 // SKINCOLOR_GOLDENBROWN - "Rosewood", // 20 // SKINCOLOR_ROSEWOOD - "Dark Rosewood", // 21 // SKINCOLOR_DARKROSEWOOD + "Creamsicle", // 16 // SKINCOLOR_CREAMSICLE + "Orange", // 17 // SKINCOLOR_ORANGE + "Pumpkin", // 18 // SKINCOLOR_PUMPKIN + "Rosewood", // 19 // SKINCOLOR_ROSEWOOD + "Burgundy", // 20 // SKINCOLOR_BURGUNDY + "Bronze", // 21 // SKINCOLOR_BRONZE "Sepia", // 22 // SKINCOLOR_SEPIA "Beige", // 23 // SKINCOLOR_BEIGE "Brown", // 24 // SKINCOLOR_BROWN "Leather", // 25 // SKINCOLOR_LEATHER - "Yellow", // 26 // SKINCOLOR_YELLOW - "Peach", // 27 // SKINCOLOR_PEACH - "Light Orange", // 28 // SKINCOLOR_LIGHTORANGE - "Caramel", // 29 // SKINCOLOR_CARAMEL - "Gold", // 30 // SKINCOLOR_GOLD - "Shiny Caramel", // 31 // SKINCOLOR_SHINYCARAMEL - "Vomit", // 32 // SKINCOLOR_VOMIT - "Garden", // 33 // SKINCOLOR_GARDEN - "Light Army", // 34 // SKINCOLOR_LIGHTARMY - "Army", // 35 // SKINCOLOR_ARMY - "Pistachio", // 36 // SKINCOLOR_PISTACHIO - "Robo-Hood", // 37 // SKINCOLOR_ROBOHOOD - "Olive", // 38 // SKINCOLOR_OLIVE - "Dark Army", // 39 // SKINCOLOR_DARKARMY - "Light Green", // 40 // SKINCOLOR_LIGHTGREEN - "Ugly Green", // 41 // SKINCOLOR_UGLYGREEN - "Neon Green", // 42 // SKINCOLOR_NEONGREEN - "Green", // 43 // SKINCOLOR_GREEN - "Dark Green", // 44 // SKINCOLOR_DARKGREEN + "Peach", // 26 // SKINCOLOR_PEACH + "Caramel", // 27 // SKINCOLOR_CARAMEL + "Tangerine", // 28 // SKINCOLOR_TANGERINE + "Gold", // 29 // SKINCOLOR_GOLD + "Vomit", // 30 // SKINCOLOR_VOMIT + "Yellow", // 31 // SKINCOLOR_YELLOW + "Canary", // 32 // SKINCOLOR_CANARY + "Olive", // 33 // SKINCOLOR_OLIVE + "Garden", // 34 // SKINCOLOR_GARDEN + "Lime", // 35 // SKINCOLOR_LIME + "Tea", // 36 // SKINCOLOR_TEA + "Army", // 37 // SKINCOLOR_ARMY + "Pistachio", // 38 // SKINCOLOR_PISTACHIO + "Moss", // 39 // SKINCOLOR_MOSS + "Mint", // 40 // SKINCOLOR_MINT + "Green", // 41 // SKINCOLOR_GREEN + "Robo-Hood", // 42 // SKINCOLOR_ROBOHOOD + "Pinetree", // 43 // SKINCOLOR_PINETREE + "Emerald", // 44 // SKINCOLOR_EMERALD "Swamp", // 45 // SKINCOLOR_SWAMP - "Frost", // 46 // SKINCOLOR_FROST - "Slate", // 47 // SKINCOLOR_SLATEBLUE - "Light Blue", // 48 // SKINCOLOR_LIGHTBLUE - "Cyan", // 49 // SKINCOLOR_CYAN - "Cerulean", // 50 // SKINCOLOR_CERULEAN - "Turquoise", // 51 // SKINCOLOR_TURQUOISE - "Teal", // 52 // SKINCOLOR_TEAL - "Steel Blue", // 53 // SKINCOLOR_STEELBLUE - "Blue", // 54 // SKINCOLOR_BLUE - "Shiny Blue", // 55 // SKINCOLOR_SHINYBLUE + "Aqua", // 46 // SKINCOLOR_AQUA + "Teal", // 47 // SKINCOLOR_TEAL + "Cyan", // 48 // SKINCOLOR_CYAN + "Cerulean", // 49 // SKINCOLOR_CERULEAN + "Slate", // 50 // SKINCOLOR_SLATE + "Steel", // 51 // SKINCOLOR_STEEL + "Periwinkle", // 52 // SKINCOLOR_PERIWINKLE + "Blue", // 53 // SKINCOLOR_BLUE + "Sapphire", // 54 // SKINCOLOR_SAPPHIRE + "Blueberry", // 55 // SKINCOLOR_BLUEBERRY "Navy", // 56 // SKINCOLOR_NAVY - "Dark Blue", // 57 // SKINCOLOR_DARKBLUE - "Jet Black", // 58 // SKINCOLOR_JETBLACK - "Lilac", // 59 // SKINCOLOR_LILAC - "Purple", // 60 // SKINCOLOR_PURPLE - "Lavender", // 61 // SKINCOLOR_LAVENDER + "Jet", // 57 // SKINCOLOR_JET + "Dusk", // 58 // SKINCOLOR_DUSK + "Purple", // 59 // SKINCOLOR_PURPLE + "Lavender", // 60 // SKINCOLOR_LAVENDER + "Indigo", // 61 // SKINCOLOR_INDIGO "Byzantium", // 62 // SKINCOLOR_BYZANTIUM - "Indigo" // 63 // SKINCOLOR_INDIGO + "Lilac" // 63 // 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_IVORY + SKINCOLOR_NICKEL,8, // 02 // SKINCOLOR_WHITE + SKINCOLOR_GREY,8, // 03 // SKINCOLOR_SILVER + SKINCOLOR_CLOUDY,8, // 04 // SKINCOLOR_CLOUDY + SKINCOLOR_SILVER,8, // 05 // SKINCOLOR_GREY + SKINCOLOR_WHITE,8, // 06 // SKINCOLOR_NICKEL + SKINCOLOR_IVORY,8, // 07 // SKINCOLOR_BLACK + SKINCOLOR_TEA,8, // 08 // SKINCOLOR_SALMON + SKINCOLOR_ARMY,8, // 09 // SKINCOLOR_PINK + SKINCOLOR_MOSS,8, // 10 // SKINCOLOR_ROSE + SKINCOLOR_MINT,10, // 11 // SKINCOLOR_RASPBERRY + SKINCOLOR_GREEN,8, // 12 // SKINCOLOR_RED + SKINCOLOR_EMERALD,6, // 13 // SKINCOLOR_RUBY + SKINCOLOR_PINETREE,6, // 14 // SKINCOLOR_CRIMSON + SKINCOLOR_DUSK,8, // 15 // SKINCOLOR_DAWN + SKINCOLOR_PERIWINKLE,8, // 16 // SKINCOLOR_CREAMSICLE + SKINCOLOR_BLUE,8, // 17 // SKINCOLOR_ORANGE + SKINCOLOR_BLUEBERRY,8, // 18 // SKINCOLOR_PUMPKIN + SKINCOLOR_NAVY,8, // 19 // SKINCOLOR_ROSEWOOD + SKINCOLOR_JET,8, // 20 // SKINCOLOR_BURGUNDY + SKINCOLOR_STEEL,8, // 21 // SKINCOLOR_BRONZE + SKINCOLOR_LEATHER,6, // 22 // SKINCOLOR_SEPIA + SKINCOLOR_BROWN,2, // 23 // SKINCOLOR_BEIGE + SKINCOLOR_BEIGE,8, // 24 // SKINCOLOR_BROWN + SKINCOLOR_SEPIA,8, // 25 // SKINCOLOR_LEATHER + SKINCOLOR_SLATE,8, // 26 // SKINCOLOR_PEACH + SKINCOLOR_TEAL,8, // 27 // SKINCOLOR_CARAMEL + SKINCOLOR_LIME,8, // 28 // SKINCOLOR_TANGERINE + SKINCOLOR_LAVENDER,6, // 29 // SKINCOLOR_GOLD + SKINCOLOR_ROBOHOOD,8, // 30 // SKINCOLOR_VOMIT + SKINCOLOR_BYZANTIUM,8, // 31 // SKINCOLOR_YELLOW + SKINCOLOR_PURPLE,8, // 32 // SKINCOLOR_CANARY + SKINCOLOR_INDIGO,8, // 33 // SKINCOLOR_OLIVE + SKINCOLOR_AQUA,8, // 34 // SKINCOLOR_GARDEN + SKINCOLOR_TANGERINE,8, // 35 // SKINCOLOR_LIME + SKINCOLOR_SALMON,8, // 36 // SKINCOLOR_TEA + SKINCOLOR_PINK,6, // 37 // SKINCOLOR_ARMY + SKINCOLOR_CYAN,8, // 38 // SKINCOLOR_PISTACHIO + SKINCOLOR_ROSE,8, // 39 // SKINCOLOR_MOSS + SKINCOLOR_RASPBERRY,6, // 40 // SKINCOLOR_MINT + SKINCOLOR_RED,8, // 41 // SKINCOLOR_GREEN + SKINCOLOR_VOMIT,8, // 42 // SKINCOLOR_ROBOHOOD + SKINCOLOR_CRIMSON,8, // 43 // SKINCOLOR_PINETREE + SKINCOLOR_RUBY,8, // 44 // SKINCOLOR_EMERALD + SKINCOLOR_SAPPHIRE,8, // 45 // SKINCOLOR_SWAMP + SKINCOLOR_GARDEN,10, // 46 // SKINCOLOR_AQUA + SKINCOLOR_CARAMEL,8, // 47 // SKINCOLOR_TEAL + SKINCOLOR_PISTACHIO,6, // 48 // SKINCOLOR_CYAN + SKINCOLOR_LILAC,8, // 49 // SKINCOLOR_CERULEAN + SKINCOLOR_PEACH,8, // 50 // SKINCOLOR_SLATE + SKINCOLOR_BRONZE,10, // 51 // SKINCOLOR_STEEL + SKINCOLOR_CREAMSICLE,8, // 52 // SKINCOLOR_PERIWINKLE + SKINCOLOR_ORANGE,8, // 53 // SKINCOLOR_BLUE + SKINCOLOR_SWAMP,8, // 54 // SKINCOLOR_SAPPHIRE + SKINCOLOR_PUMPKIN,8, // 55 // SKINCOLOR_BLUEBERRY + SKINCOLOR_ROSEWOOD,8, // 56 // SKINCOLOR_NAVY + SKINCOLOR_BURGUNDY,6, // 57 // SKINCOLOR_JET + SKINCOLOR_DAWN,8, // 58 // SKINCOLOR_DUSK + SKINCOLOR_CANARY,8, // 59 // SKINCOLOR_PURPLE + SKINCOLOR_GOLD,10, // 60 // SKINCOLOR_LAVENDER + SKINCOLOR_OLIVE,8, // 61 // SKINCOLOR_INDIGO + SKINCOLOR_YELLOW,8, // 62 // SKINCOLOR_BYZANTIUM + SKINCOLOR_CERULEAN,8 // 63 // SKINCOLOR_LILAC }; UINT8 colortranslations[MAXSKINCOLORS][16] = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // SKINCOLOR_NONE - {120, 120, 120, 120, 0, 0, 0, 0, 1, 1, 2, 2, 4, 6, 8, 10}, // SKINCOLOR_IVORY - { 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7}, // SKINCOLOR_WHITE - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, // SKINCOLOR_SILVER + {120, 120, 120, 120, 0, 1, 3, 4, 6, 7, 10, 14, 18, 22, 25, 28}, // SKINCOLOR_IVORY + {120, 120, 0, 1, 3, 4, 6, 7, 9, 11, 13, 16, 19, 23, 26, 29}, // SKINCOLOR_WHITE + { 0, 1, 3, 5, 6, 8, 10, 11, 13, 15, 16, 18, 20, 24, 27, 30}, // SKINCOLOR_SILVER { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31}, // SKINCOLOR_CLOUDY - { 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23}, // SKINCOLOR_GREY - { 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}, // SKINCOLOR_DARKGREY - { 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31, 31}, // SKINCOLOR_BLACK - {120, 120, 121, 121, 122, 122, 123, 123, 124, 124, 125, 125, 126, 126, 127, 127}, // SKINCOLOR_SALMON - {144, 144, 145, 145, 146, 146, 147, 147, 148, 148, 149, 149, 150, 150, 151, 151}, // SKINCOLOR_PINK - {120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135}, // SKINCOLOR_LIGHTRED - {120, 121, 123, 124, 126, 127, 129, 130, 132, 133, 135, 136, 138, 139, 141, 143}, // SKINCOLOR_SHINYRED + { 8, 9, 10, 12, 13, 15, 16, 19, 19, 20, 21, 23, 25, 27, 29, 31}, // SKINCOLOR_GREY + { 16, 16, 17, 18, 19, 20, 21, 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 + {120, 120, 120, 121, 121, 122, 122, 123, 124, 125, 126, 128, 129, 131, 133, 135}, // SKINCOLOR_SALMON + {121, 121, 121, 121, 121, 122, 144, 145, 146, 147, 148, 149, 150, 150, 150, 151}, // SKINCOLOR_PINK + {144, 145, 146, 147, 148, 149, 150, 151, 134, 135, 136, 137, 138, 139, 140, 141}, // SKINCOLOR_ROSE + {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 - {144, 145, 146, 147, 148, 149, 150, 151, 134, 135, 136, 137, 138, 139, 140, 141}, // SKINCOLOR_DARKPINK - {136, 136, 137, 137, 138, 138, 139, 139, 140, 140, 141, 141, 142, 142, 143, 143}, // SKINCOLOR_DARKRED - {120, 121, 122, 123, 124, 147, 88, 89, 149, 91, 92, 151, 94, 95, 152, 153}, // SKINCOLOR_DAWN - { 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95}, // SKINCOLOR_ORANGE - { 80, 81, 83, 85, 86, 88, 90, 91, 93, 95, 152, 153, 154, 156, 157, 159}, // SKINCOLOR_SHINYORANGE - { 88, 89, 90, 91, 92, 93, 94, 95, 152, 153, 154, 155, 156, 157, 158, 159}, // SKINCOLOR_DARKORANGE - {112, 113, 114, 115, 116, 117, 118, 119, 156, 156, 157, 157, 158, 158, 159, 159}, // SKINCOLOR_GOLDENBROWN - {152, 152, 153, 153, 154, 154, 155, 155, 156, 156, 157, 157, 158, 158, 159, 159}, // SKINCOLOR_ROSEWOOD - {152, 153, 154, 155, 156, 157, 158, 159, 139, 140, 141, 142, 143, 31, 31, 31}, // SKINCOLOR_DARKROSEWOOD - { 3, 5, 7, 32, 9, 34, 36, 37, 39, 42, 45, 59, 60, 61, 62, 63}, // SKINCOLOR_SEPIA + {120, 121, 144, 146, 149, 132, 132, 133, 134, 135, 197, 197, 198, 198, 199, 255}, // SKINCOLOR_RUBY + {130, 131, 132, 133, 134, 136, 137, 138, 139, 139, 140, 140, 141, 141, 142, 143}, // SKINCOLOR_CRIMSON + {120, 121, 122, 123, 124, 147, 147, 148, 90, 91, 92, 93, 94, 95, 152, 154}, // SKINCOLOR_DAWN + {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 + {112, 113, 114, 115, 116, 117, 118, 119, 156, 157, 158, 159, 141, 141, 142, 143}, // SKINCOLOR_BRONZE + { 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 - { 57, 58, 59, 59, 60, 60, 61, 61, 62, 62, 63, 63, 28, 29, 30, 31}, // SKINCOLOR_LEATHER - { 97, 98, 99, 100, 101, 102, 103, 104, 113, 113, 114, 115, 115, 115, 116, 117}, // SKINCOLOR_YELLOW - { 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79}, // SKINCOLOR_PEACH - { 80, 80, 81, 81, 82, 82, 83, 83, 84, 84, 85, 85, 86, 86, 87, 87}, // SKINCOLOR_LIGHTORANGE - { 72, 73, 74, 75, 76, 77, 78, 79, 48, 49, 50, 51, 52, 53, 54, 55}, // SKINCOLOR_CARAMEL - {112, 112, 113, 113, 114, 114, 115, 115, 116, 116, 117, 117, 118, 118, 119, 119}, // SKINCOLOR_GOLD - { 64, 66, 68, 70, 72, 74, 76, 78, 48, 50, 52, 54, 56, 58, 60, 62}, // SKINCOLOR_SHINYCARAMEL + { 51, 52, 53, 55, 56, 57, 58, 60, 61, 63, 28, 28, 29, 29, 30, 31}, // SKINCOLOR_LEATHER + { 64, 65, 67, 68, 70, 71, 73, 74, 76, 77, 79, 48, 50, 53, 56, 59}, // SKINCOLOR_PEACH + { 64, 66, 68, 70, 72, 74, 76, 78, 48, 50, 52, 54, 56, 58, 60, 62}, // SKINCOLOR_CARAMEL + { 98, 98, 112, 112, 113, 113, 84, 85, 87, 89, 91, 93, 95, 153, 156, 159}, // SKINCOLOR_TANGERINE + {112, 112, 112, 113, 113, 114, 114, 115, 115, 116, 116, 117, 117, 118, 118, 119}, // SKINCOLOR_GOLD {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, 181, 182, 172, 183, 173, 174, 175}, // SKINCOLOR_GARDEN - {176, 176, 176, 176, 177, 177, 177, 177, 178, 178, 178, 178, 179, 179, 179, 179}, // SKINCOLOR_LIGHTARMY - {176, 176, 177, 177, 178, 178, 179, 179, 180, 180, 181, 181, 182, 182, 183, 183}, // SKINCOLOR_ARMY - {176, 176, 177, 177, 178, 178, 179, 179, 166, 167, 168, 169, 170, 171, 172, 173}, // SKINCOLOR_PISTACHIO - {177, 177, 178, 178, 165, 165, 167, 167, 182, 182, 171, 171, 183, 183, 173, 173}, // SKINCOLOR_ROBOHOOD - {105, 105, 106, 106, 107, 107, 108, 108, 109, 109, 110, 110, 111, 111, 31, 31}, // SKINCOLOR_OLIVE - {176, 177, 178, 179, 170, 181, 182, 183, 173, 173, 174, 174, 175, 175, 31, 31}, // SKINCOLOR_DARKARMY - {160, 160, 161, 161, 162, 162, 163, 163, 164, 164, 165, 165, 166, 166, 167, 167}, // SKINCOLOR_LIGHTGREEN - {184, 184, 184, 184, 185, 185, 185, 185, 186, 186, 186, 186, 187, 187, 187, 187}, // SKINCOLOR_UGLYGREEN - {184, 184, 185, 185, 186, 186, 187, 187, 188, 188, 189, 189, 190, 190, 191, 191}, // SKINCOLOR_NEONGREEN + { 96, 97, 98, 100, 101, 102, 104, 113, 114, 115, 116, 117, 118, 119, 156, 159}, // SKINCOLOR_YELLOW + { 96, 97, 99, 100, 102, 104, 105, 105, 106, 107, 107, 108, 109, 109, 110, 111}, // SKINCOLOR_CANARY + {105, 105, 105, 106, 106, 107, 107, 108, 108, 109, 109, 110, 110, 111, 111, 31}, // SKINCOLOR_OLIVE + { 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 + {120, 120, 176, 176, 176, 177, 177, 178, 178, 179, 180, 180, 181, 181, 182, 183}, // SKINCOLOR_TEA + {176, 176, 176, 177, 177, 178, 178, 179, 179, 180, 180, 181, 181, 182, 182, 183}, // SKINCOLOR_ARMY + {120, 120, 176, 176, 177, 177, 178, 179, 165, 166, 167, 168, 169, 170, 171, 172}, // SKINCOLOR_PISTACHIO + {178, 178, 178, 179, 179, 180, 181, 182, 183, 172, 172, 173, 173, 174, 174, 175}, // SKINCOLOR_MOSS + {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 - {168, 168, 169, 169, 170, 170, 171, 171, 172, 172, 173, 173, 174, 174, 175, 175}, // SKINCOLOR_DARKGREEN - {187, 187, 188, 188, 189, 189, 190, 190, 191, 191, 175, 175, 30, 30, 31, 31}, // SKINCOLOR_SWAMP - {224, 225, 226, 212, 213, 213, 214, 215, 220, 221, 172, 222, 173, 223, 174, 175}, // SKINCOLOR_FROST - {200, 200, 200, 200, 201, 201, 201, 201, 202, 202, 202, 202, 203, 203, 203, 203}, // SKINCOLOR_SLATE - {224, 224, 225, 225, 226, 226, 227, 227, 228, 228, 229, 229, 230, 230, 231, 231}, // SKINCOLOR_LIGHTBLUE - {208, 208, 209, 210, 210, 211, 212, 213, 213, 214, 215, 216, 216, 217, 218, 219}, // SKINCOLOR_CYAN - {216, 216, 216, 216, 217, 217, 217, 217, 218, 218, 218, 218, 219, 219, 219, 219}, // SKINCOLOR_CERULEAN - {208, 208, 209, 210, 210, 211, 212, 213, 213, 214, 215, 220, 220, 221, 222, 223}, // SKINCOLOR_TURQOISE - {220, 220, 220, 220, 221, 221, 221, 221, 222, 222, 222, 222, 223, 223, 223, 223}, // SKINCOLOR_TEAL - {200, 200, 201, 201, 202, 202, 203, 203, 204, 204, 205, 205, 206, 206, 207, 207}, // SKINCOLOR_STEELBLUE + {176, 176, 177, 178, 165, 166, 167, 167, 168, 169, 182, 182, 182, 183, 183, 183}, // SKINCOLOR_ROBOHOOD + {160, 161, 162, 164, 165, 167, 169, 170, 171, 171, 172, 173, 174, 175, 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 + {120, 208, 208, 210, 212, 214, 220, 220, 220, 221, 221, 222, 222, 223, 223, 191}, // SKINCOLOR_AQUA + {210, 213, 220, 220, 220, 221, 221, 221, 221, 222, 222, 222, 223, 223, 191, 31}, // SKINCOLOR_TEAL + {120, 208, 209, 210, 211, 212, 213, 215, 216, 216, 216, 217, 217, 218, 218, 219}, // SKINCOLOR_CYAN + {208, 209, 211, 213, 215, 216, 216, 217, 217, 218, 218, 219, 205, 206, 207, 207}, // SKINCOLOR_CERULEAN + {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 + {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 - {224, 225, 226, 228, 229, 231, 232, 234, 235, 237, 238, 240, 241, 243, 244, 246}, // SKINCOLOR_SHINYBLUE - {200, 201, 202, 203, 204, 205, 206, 238, 239, 240, 241, 242, 243, 244, 245, 246}, // SKINCOLOR_NAVY - {231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246}, // SKINCOLOR_DARKBLUE - {200, 201, 202, 203, 204, 205, 206, 207, 28, 28, 29, 29, 30, 30, 31, 31}, // SKINCOLOR_JETBLACK - {120, 120, 121, 121, 122, 122, 123, 123, 192, 192, 248, 248, 249, 249, 250, 250}, // SKINCOLOR_LILAC - {192, 192, 193, 193, 194, 194, 195, 195, 196, 196, 197, 197, 198, 198, 199, 199}, // SKINCOLOR_PURPLE - {248, 248, 249, 249, 250, 250, 251, 251, 252, 252, 253, 253, 254, 254, 255, 255}, // SKINCOLOR_LAVENDER - {192, 248, 249, 250, 251, 252, 253, 254, 255, 255, 29, 29, 30, 30, 31, 31}, // SKINCOLOR_BYZANTIUM + {208, 209, 211, 213, 215, 217, 229, 230, 232, 234, 236, 238, 240, 242, 244, 246}, // SKINCOLOR_SAPPHIRE + {228, 229, 230, 231, 232, 233, 234, 235, 237, 238, 239, 240, 242, 243, 244, 245}, // SKINCOLOR_BLUEBERRY + {215, 216, 217, 218, 204, 205, 206, 237, 238, 239, 240, 241, 242, 243, 244, 245}, // SKINCOLOR_NAVY + {200, 201, 202, 203, 204, 205, 206, 207, 28, 28, 29, 29, 30, 30, 31, 31}, // SKINCOLOR_JET + {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, 193, 194, 195, 196, 197, 198, 199, 255, 255, 29, 29, 30, 30, 31, 31}, // SKINCOLOR_INDIGO + {192, 248, 249, 250, 251, 252, 253, 254, 255, 255, 29, 29, 30, 30, 31, 31}, // SKINCOLOR_BYZANTIUM + {120, 120, 120, 121, 121, 122, 122, 123, 192, 248, 249, 250, 251, 252, 253, 254}, // SKINCOLOR_LILAC /* Removed Colours - {192, 192, 248, 249, 250, 251, 229, 204, 230, 205, 206, 239, 240, 241, 242, 243}, // SKINCOLOR_DUSK - { 1, 145, 125, 73, 83, 114, 106, 180, 187, 168, 219, 205, 236, 206, 199, 255}, // SKINCOLOR_RAINBOW + {120, 121, 123, 124, 126, 127, 129, 130, 132, 133, 135, 136, 138, 139, 141, 143}, // SKINCOLOR_RUBY, removed for other colors + { 80, 81, 83, 85, 86, 88, 90, 91, 93, 95, 152, 153, 154, 156, 157, 159}, // SKINCOLOR_AMBER, removed for other colors + {224, 225, 226, 228, 229, 231, 232, 234, 235, 237, 238, 240, 241, 243, 244, 246}, // SKINCOLOR_SAPPHIRE, 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 + { 72, 73, 74, 75, 76, 77, 78, 79, 48, 49, 50, 51, 52, 53, 54, 55}, // SKINCOLOR_CARAMEL, new Caramel was previously Shiny Caramel + { 1, 145, 125, 73, 83, 114, 106, 180, 187, 168, 219, 205, 236, 206, 199, 255}, // SKINCOLOR_RAINBOW, is Vomit 2.0 */ }; -/** \brief Generates the starman colourmaps that are used when a player has the invincibility power +/** \brief Generates the rainbow colourmaps that are used when a player has the invincibility power \param dest_colormap colormap to populate \param skincolor translation color */ -void K_StarmanColormap(UINT8 *dest_colormap, UINT8 skincolor) +void K_RainbowColormap(UINT8 *dest_colormap, UINT8 skincolor) { INT32 i, j; RGBA_t color; @@ -250,9 +327,9 @@ void K_GenerateKartColormap(UINT8 *dest_colormap, INT32 skinnum, UINT8 color) return; } - else if (skinnum == TC_STARMAN) + else if (skinnum == TC_RAINBOW) { - K_StarmanColormap(dest_colormap, color); + K_RainbowColormap(dest_colormap, color); return; } @@ -296,38 +373,44 @@ UINT8 K_GetKartColorByName(const char *name) void K_RegisterKartStuff(void) { - CV_RegisterVar(&cv_magnet); - CV_RegisterVar(&cv_boo); - CV_RegisterVar(&cv_mushroom); - CV_RegisterVar(&cv_triplemushroom); - CV_RegisterVar(&cv_megashroom); - CV_RegisterVar(&cv_goldshroom); - CV_RegisterVar(&cv_star); - CV_RegisterVar(&cv_triplebanana); - CV_RegisterVar(&cv_fakeitem); + CV_RegisterVar(&cv_sneaker); + CV_RegisterVar(&cv_rocketsneaker); + CV_RegisterVar(&cv_invincibility); CV_RegisterVar(&cv_banana); - CV_RegisterVar(&cv_greenshell); - CV_RegisterVar(&cv_redshell); - CV_RegisterVar(&cv_laserwisp); - CV_RegisterVar(&cv_triplegreenshell); - CV_RegisterVar(&cv_bobomb); - CV_RegisterVar(&cv_blueshell); - CV_RegisterVar(&cv_jaws); - CV_RegisterVar(&cv_fireflower); - CV_RegisterVar(&cv_tripleredshell); - CV_RegisterVar(&cv_lightning); - CV_RegisterVar(&cv_feather); + CV_RegisterVar(&cv_eggmanmonitor); + CV_RegisterVar(&cv_orbinaut); + CV_RegisterVar(&cv_jawz); + CV_RegisterVar(&cv_mine); + CV_RegisterVar(&cv_ballhog); + CV_RegisterVar(&cv_selfpropelledbomb); + CV_RegisterVar(&cv_grow); + CV_RegisterVar(&cv_shrink); + CV_RegisterVar(&cv_thundershield); + CV_RegisterVar(&cv_hyudoro); + CV_RegisterVar(&cv_pogospring); + + CV_RegisterVar(&cv_triplesneaker); + CV_RegisterVar(&cv_triplebanana); + CV_RegisterVar(&cv_tripleorbinaut); + CV_RegisterVar(&cv_dualjawz); CV_RegisterVar(&cv_kartminimap); CV_RegisterVar(&cv_kartcheck); - CV_RegisterVar(&cv_kartstarsfx); + CV_RegisterVar(&cv_kartinvinsfx); CV_RegisterVar(&cv_kartspeed); - CV_RegisterVar(&cv_kartballoons); + CV_RegisterVar(&cv_kartbumpers); CV_RegisterVar(&cv_kartfrantic); CV_RegisterVar(&cv_kartcomeback); CV_RegisterVar(&cv_kartmirror); - CV_RegisterVar(&cv_speedometer); + CV_RegisterVar(&cv_kartspeedometer); + CV_RegisterVar(&cv_kartvoices); + CV_RegisterVar(&cv_karteliminatelast); CV_RegisterVar(&cv_votetime); + + CV_RegisterVar(&cv_kartdebugitem); + CV_RegisterVar(&cv_kartdebugamount); + CV_RegisterVar(&cv_kartdebugcheckpoint); + CV_RegisterVar(&cv_kartdebugshrink); } //} @@ -342,8 +425,10 @@ boolean K_IsPlayerLosing(player_t *player) for (i = 0; i < MAXPLAYERS; i++) { - if (playeringame[i] && !players[i].spectator) - pcount++; + if (!playeringame[i] || players[i].spectator) + continue; + if (players[i].kartstuff[k_position] > pcount) + pcount = players[i].kartstuff[k_position]; } if (pcount <= 1) @@ -356,151 +441,126 @@ boolean K_IsPlayerLosing(player_t *player) return (player->kartstuff[k_position] > winningpos); } +boolean K_IsPlayerWanted(player_t *player) +{ + UINT8 i; + if (!(G_BattleGametype())) + return false; + for (i = 0; i < 4; i++) + { + if (battlewanted[i] == -1) + break; + if (player == &players[battlewanted[i]]) + return true; + } + return false; +} + //{ SRB2kart Roulette Code - Position Based -#define NUMKARTITEMS 19 -#define NUMKARTODDS 40 +#define NUMKARTODDS 80 // Less ugly 2D arrays -static INT32 K_KartItemOddsDistance_Retro[NUMKARTITEMS][9] = +static INT32 K_KartItemOddsRace[NUMKARTRESULTS][9] = { //P-Odds 0 1 2 3 4 5 6 7 8 - /*Magnet*/ { 0, 1, 2, 0, 0, 0, 0, 0, 0 }, // Magnet - /*Boo*/ { 0, 0, 2, 2, 1, 0, 0, 0, 0 }, // Boo - /*Mushroom*/ {20, 0, 0, 3, 7, 6, 0, 0, 0 }, // Mushroom - /*Triple Mushroom*/ { 0, 0, 0, 0, 3, 8, 7, 4, 0 }, // Triple Mushroom - /*Mega Mushroom*/ { 0, 0, 0, 0, 0, 0, 1, 1, 2 }, // Mega Mushroom - /*Gold Mushroom*/ { 0, 0, 0, 0, 0, 3, 5, 4, 0 }, // Gold Mushroom - /*Star*/ { 0, 0, 0, 0, 0, 1, 6, 9,18 }, // Star - - /*Triple Banana*/ { 0, 0, 1, 1, 0, 0, 0, 0, 0 }, // Triple Banana - /*Fake Item*/ { 0, 4, 2, 1, 0, 0, 0, 0, 0 }, // Fake Item + /*Sneaker*/ {20, 0, 0, 3, 6, 6, 0, 0, 0 }, // Sneaker + /*Rocket Sneaker*/ { 0, 0, 0, 0, 0, 2, 5, 4, 0 }, // Rocket Sneaker + /*Invincibility*/ { 0, 0, 0, 0, 0, 1, 5, 6,16 }, // Invincibility /*Banana*/ { 0, 9, 4, 2, 1, 0, 0, 0, 0 }, // Banana - /*Green Shell*/ { 0, 6, 4, 3, 2, 0, 0, 0, 0 }, // Green Shell - /*Red Shell*/ { 0, 0, 3, 2, 2, 1, 0, 0, 0 }, // Red Shell - /*Triple Green Shell*/ { 0, 0, 0, 1, 1, 1, 0, 0, 0 }, // Triple Green Shell - /*Bob-omb*/ { 0, 0, 1, 2, 1, 0, 0, 0, 0 }, // Bob-omb - /*Blue Shell*/ { 0, 0, 1, 2, 4, 3, 1, 0, 0 }, // Blue Shell - /*Fire Flower*/ { 0, 0, 1, 2, 1, 0, 0, 0, 0 }, // Fire Flower - /*Triple Red Shell*/ { 0, 0, 0, 1, 1, 0, 0, 0, 0 }, // Triple Red Shell - /*Lightning*/ { 0, 0, 0, 0, 0, 0, 1, 2, 0 }, // Lightning - - /*Feather*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0 } // Feather + /*Eggman Monitor*/ { 0, 4, 3, 2, 0, 0, 0, 0, 0 }, // Eggman Monitor + /*Orbinaut*/ { 0, 6, 5, 4, 2, 0, 0, 0, 0 }, // Orbinaut + /*Jawz*/ { 0, 0, 3, 2, 2, 1, 0, 0, 0 }, // Jawz + /*Mine*/ { 0, 0, 1, 2, 1, 0, 0, 0, 0 }, // Mine + /*Ballhog*/ { 0, 0, 1, 2, 1, 0, 0, 0, 0 }, // Ballhog + /*Self-Propelled Bomb*/ { 0, 0, 1, 1, 1, 2, 2, 3, 2 }, // Self-Propelled Bomb + /*Grow*/ { 0, 0, 0, 0, 0, 1, 3, 6, 4 }, // Grow + /*Shrink*/ { 0, 0, 0, 0, 0, 0, 0, 1, 0 }, // Shrink + /*Thunder Shield*/ { 0, 1, 2, 0, 0, 0, 0, 0, 0 }, // Thunder Shield + /*Hyudoro*/ { 0, 0, 0, 0, 1, 2, 1, 0, 0 }, // Hyudoro + /*Pogo Spring*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Pogo Spring + /*Kitchen Sink*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Kitchen Sink + /*Sneaker x3*/ { 0, 0, 0, 0, 3, 6, 5, 3, 0 }, // Sneaker x3 + /*Banana x3*/ { 0, 0, 1, 1, 0, 0, 0, 0, 0 }, // Banana x3 + /*Banana x10*/ { 0, 0, 0, 0, 1, 0, 0, 0, 0 }, // Banana x10 + /*Orbinaut x3*/ { 0, 0, 0, 1, 1, 0, 0, 0, 0 }, // Orbinaut x3 + /*Orbinaut x4*/ { 0, 0, 0, 0, 0, 1, 1, 0, 0 }, // Orbinaut x4 + /*Jawz x2*/ { 0, 0, 0, 1, 1, 0, 0, 0, 0 } // Jawz x2 }; -static INT32 K_KartItemOddsBalloons[NUMKARTITEMS][6] = +static INT32 K_KartItemOddsBattle[NUMKARTRESULTS][6] = { - //P-Odds 0 1 2 3 4 5 - /*Magnet*/ { 0, 0, 0, 0, 0, 0 }, // Magnet - /*Boo*/ { 0, 0, 1, 1, 0, 0 }, // Boo - /*Mushroom*/ { 3, 1, 2, 2, 0, 2 }, // Mushroom - /*Triple Mushroom*/ { 3, 0, 0, 0, 0, 2 }, // Triple Mushroom - /*Mega Mushroom*/ { 4, 2, 0, 0, 0, 2 }, // Mega Mushroom - /*Gold Mushroom*/ { 0, 0, 0, 0, 0, 0 }, // Gold Mushroom - /*Star*/ { 4, 2, 1, 0, 0, 2 }, // Star - - /*Triple Banana*/ { 0, 2, 2, 1, 1, 2 }, // Triple Banana - /*Fake Item*/ { 0, 0, 2, 2, 3, 0 }, // Fake Item - /*Banana*/ { 0, 0, 2, 3, 6, 0 }, // Banana - /*Green Shell*/ { 0, 0, 3, 5,10, 0 }, // Green Shell - /*Red Shell*/ { 3, 3, 2, 1, 0, 2 }, // Red Shell - /*Triple Green Shell*/ { 0, 3, 1, 1, 0, 2 }, // Triple Green Shell - /*Bob-omb*/ { 0, 3, 2, 1, 0, 2 }, // Bob-omb - /*Blue Shell*/ { 0, 0, 0, 0, 0, 0 }, // Blue Shell - /*Fire Flower*/ { 0, 2, 1, 1, 0, 2 }, // Fire Flower - /*Triple Red Shell*/ { 3, 2, 0, 0, 0, 2 }, // Triple Red Shell - /*Lightning*/ { 0, 0, 0, 0, 0, 0 }, // Lightning - - /*Feather*/ { 0, 0, 1, 2, 0, 0 } // Feather + //P-Odds 0 1 2 3 + /*Sneaker*/ { 2, 2, 2, 2 }, // Sneaker + /*Rocket Sneaker*/ { 0, 0, 0, 0 }, // Rocket Sneaker + /*Invincibility*/ { 4, 2, 1, 2 }, // Invincibility + /*Banana*/ { 0, 0, 2, 0 }, // Banana + /*Eggman Monitor*/ { 0, 0, 1, 0 }, // Eggman Monitor + /*Orbinaut*/ { 0, 1, 5, 0 }, // Orbinaut + /*Jawz*/ { 1, 3, 2, 2 }, // Jawz + /*Mine*/ { 1, 3, 2, 2 }, // Mine + /*Ballhog*/ { 1, 2, 1, 2 }, // Ballhog + /*Self-Propelled Bomb*/ { 0, 0, 0, 0 }, // Self-Propelled Bomb + /*Grow*/ { 4, 2, 0, 2 }, // Grow + /*Shrink*/ { 0, 0, 0, 0 }, // Shrink + /*Thunder Shield*/ { 0, 0, 0, 0 }, // Thunder Shield + /*Hyudoro*/ { 0, 0, 1, 0 }, // Hyudoro + /*Pogo Spring*/ { 0, 0, 1, 0 }, // Pogo Spring + /*Kitchen Sink*/ { 0, 0, 0, 0 }, // Kitchen Sink + /*Sneaker x3*/ { 2, 0, 0, 2 }, // Sneaker x3 + /*Banana x3*/ { 0, 1, 1, 1 }, // Banana x3 + /*Banana x10*/ { 1, 0, 0, 1 }, // Banana x10 + /*Orbinaut x3*/ { 0, 1, 1, 1 }, // Orbinaut x3 + /*Orbinaut x4*/ { 1, 1, 0, 1 }, // Orbinaut x4 + /*Jawz x2*/ { 3, 2, 0, 2 } // Jawz x2 }; /** \brief Item Roulette for Kart \param player player \param getitem what item we're looking for - \param retrokart whether or not we're getting old or new item odds \return void */ -static void K_KartGetItemResult(player_t *player, fixed_t getitem, boolean retrokart) +static void K_KartGetItemResult(player_t *player, SINT8 getitem) { switch (getitem) { - case 1: // Magnet - player->kartstuff[k_magnet] = 1; + // Special roulettes first, then the generic ones are handled by default + case KRITEM_TRIPLESNEAKER: // Sneaker x3 + player->kartstuff[k_itemtype] = KITEM_SNEAKER; + player->kartstuff[k_itemamount] = 3; break; - case 2: // Boo - player->kartstuff[k_boo] = 1; + case KRITEM_TRIPLEBANANA: // Banana x3 + player->kartstuff[k_itemtype] = KITEM_BANANA; + player->kartstuff[k_itemamount] = 3; break; - case 4: // Triple Mushroom - player->kartstuff[k_mushroom] = 4; + case KRITEM_TENFOLDBANANA: // Banana x10 + player->kartstuff[k_itemtype] = KITEM_BANANA; + player->kartstuff[k_itemamount] = 10; break; - case 5: // Mega Mushroom - player->kartstuff[k_megashroom] = 1; + case KRITEM_TRIPLEORBINAUT: // Orbinaut x3 + player->kartstuff[k_itemtype] = KITEM_ORBINAUT; + player->kartstuff[k_itemamount] = 3; break; - case 6: // Gold Mushroom - player->kartstuff[k_goldshroom] = 1; + case KRITEM_QUADORBINAUT: // Orbinaut x4 + player->kartstuff[k_itemtype] = KITEM_ORBINAUT; + player->kartstuff[k_itemamount] = 4; break; - case 7: // Star - player->kartstuff[k_star] = 1; + case KRITEM_DUALJAWZ: // Jawz x2 + player->kartstuff[k_itemtype] = KITEM_JAWZ; + player->kartstuff[k_itemamount] = 2; break; - case 8: // Triple Banana - player->kartstuff[k_triplebanana] |= 8; - break; - case 9: // Fake Item - player->kartstuff[k_fakeitem] |= 2; - break; - case 10: // Banana - player->kartstuff[k_banana] |= 2; - break; - case 11: // Green Shell - player->kartstuff[k_greenshell] |= 2; - break; - case 12: // Red Shell - player->kartstuff[k_redshell] |= 2; - break; - case 13: // Triple Green Shell - or - Laser Wisp - if (retrokart) - player->kartstuff[k_triplegreenshell] |= 8; + default: + if (getitem <= 0 || getitem >= NUMKARTRESULTS) // Sad (Fallback) + { + if (getitem != 0) + CONS_Printf("ERROR: P_KartGetItemResult - Item roulette gave bad item (%d) :(\n", getitem); + player->kartstuff[k_itemtype] = KITEM_SAD; + } else - player->kartstuff[k_laserwisp] = 1; - break; - case 14: // Bob-omb - or - 3x Orbinaut (Triple Green Shell) - if (retrokart) - player->kartstuff[k_bobomb] |= 2; - else - player->kartstuff[k_triplegreenshell] |= 8; - break; - case 15: // Blue Shell - or - Specialstage Mines (Bob-omb) - if (retrokart) - player->kartstuff[k_blueshell] = 1; - else - player->kartstuff[k_bobomb] |= 2; - lightningcooldown = 20*TICRATE; - break; - case 16: // Fire Flower - or - Deton (Blue Shell) - if (retrokart) - player->kartstuff[k_fireflower] = 1; - else - player->kartstuff[k_blueshell] |= 4; - break; - case 17: // Triple Red Shell - or - 2x Jaws - if (retrokart) - player->kartstuff[k_tripleredshell] |= 8; - else - player->kartstuff[k_jaws] = 1; - break; - case 18: // Lightning - player->kartstuff[k_lightning] = 1; - lightningcooldown = 20*TICRATE; - break; - case 19: // Feather - player->kartstuff[k_feather] |= 1; - break; - default: // Mushroom - Doing it here as a fail-safe - if (getitem != 3) - CONS_Printf("ERROR: P_KartGetItemResult - Item roulette gave bad item (%d), giving Mushroom instead.\n", getitem); - player->kartstuff[k_mushroom] = 1; + player->kartstuff[k_itemtype] = getitem; + player->kartstuff[k_itemamount] = 1; break; } } @@ -512,45 +572,181 @@ static void K_KartGetItemResult(player_t *player, fixed_t getitem, boolean retro \return void */ -static INT32 K_KartGetItemOdds(INT32 pos, INT32 itemnum, boolean mashed) +static INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed) { + const INT32 distvar = (64*14); INT32 newodds; + INT32 i; + UINT8 pingame = 0, pexiting = 0, pinvin = 0; + SINT8 first = -1, second = -1; + INT32 secondist = 0; if (G_BattleGametype()) - newodds = K_KartItemOddsBalloons[itemnum-1][pos]; + newodds = K_KartItemOddsBattle[item-1][pos]; else - newodds = K_KartItemOddsDistance_Retro[itemnum-1][pos]; + newodds = K_KartItemOddsRace[item-1][pos]; - if (itemnum == 1 || itemnum == 4 || itemnum == 5 || itemnum == 6 - || itemnum == 7 || itemnum == 8 || itemnum == 12 || itemnum == 13 || itemnum == 14 || itemnum == 15 - || itemnum == 16 || itemnum == 17 || itemnum == 18) // Powerful items! + for (i = 0; i < MAXPLAYERS; i++) { - if (franticitems) - newodds *= 2; - if (mashed) - newodds /= 2; + if (!playeringame[i] || players[i].spectator) + continue; + + pingame++; + if (players[i].exiting) + pexiting++; + if (players[i].mo) + { + if (players[i].kartstuff[k_position] == 1 && first == -1) + first = i; + if (players[i].kartstuff[k_position] == 2 && second == -1) + second = i; + 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 (first != -1 && second != -1) // calculate 2nd's distance from 1st, for SPB + { + secondist = P_AproxDistance(P_AproxDistance(players[first].mo->x - players[second].mo->x, + players[first].mo->y - players[second].mo->y), + players[first].mo->z - players[second].mo->z) / mapheaderinfo[gamemap-1]->mobj_scale; + if (franticitems) + secondist = (15*secondist/14); + if (pingame < 6 && !G_BattleGametype()) + secondist = ((28+(6-pingame))*secondist/28); + } + + // 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. + // 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. (1v1s are basically the same as franticitems false in a normal race) + // Lastly, it *divides* it by your mashed value, which was determined in K_KartItemRoulette, to punish those who are impatient. + // The last two are very fractional and complicated, very sorry! +#define POWERITEMODDS(odds) \ + if (franticitems) \ + odds *= 2; \ + if (pingame < 6 && !G_BattleGametype()) \ + odds = FixedMul(odds*FRACUNIT, FRACUNIT+min((6-pingame)*(FRACUNIT/25), FRACUNIT))/FRACUNIT; \ + if (mashed > 0) \ + odds = FixedDiv(odds*FRACUNIT, mashed+FRACUNIT)/FRACUNIT \ + + switch (item) + { + case KITEM_SNEAKER: + if ((!cv_sneaker.value) && (!modeattacking)) newodds = 0; + break; + case KITEM_ROCKETSNEAKER: + POWERITEMODDS(newodds); + if (!cv_rocketsneaker.value) newodds = 0; + break; + case KITEM_INVINCIBILITY: + POWERITEMODDS(newodds); + if ((!cv_invincibility.value) || (pinvin > 2)) newodds = 0; + break; + case KITEM_BANANA: + if (!cv_banana.value) newodds = 0; + break; + case KITEM_EGGMAN: + if (!cv_eggmanmonitor.value) newodds = 0; + break; + case KITEM_ORBINAUT: + if (!cv_orbinaut.value) newodds = 0; + break; + case KITEM_JAWZ: + POWERITEMODDS(newodds); + if (!cv_jawz.value) newodds = 0; + break; + case KITEM_MINE: + POWERITEMODDS(newodds); + if (!cv_mine.value) newodds = 0; + break; + case KITEM_BALLHOG: + POWERITEMODDS(newodds); + if (!cv_ballhog.value) newodds = 0; + break; + case KITEM_SPB: + POWERITEMODDS(newodds); + if ((!cv_selfpropelledbomb.value) + || (indirectitemcooldown > 0) + || (pexiting > 0) + || (secondist/distvar < (4+gamespeed))) + newodds = 0; + newodds *= min((secondist/distvar)-(3+gamespeed), 3); + break; + case KITEM_GROW: + POWERITEMODDS(newodds); + if ((!cv_grow.value) || (pinvin > 2)) newodds = 0; + break; + case KITEM_SHRINK: + POWERITEMODDS(newodds); + if ((!cv_shrink.value) + || (indirectitemcooldown > 0) + || (pingame-1 <= pexiting)) newodds = 0; + break; + case KITEM_THUNDERSHIELD: + POWERITEMODDS(newodds); + if (!cv_thundershield.value) newodds = 0; + break; + case KITEM_HYUDORO: + if (!cv_hyudoro.value) newodds = 0; + break; + case KITEM_POGOSPRING: + if (!cv_pogospring.value) newodds = 0; + break; + case KITEM_KITCHENSINK: + newodds = 0; // Not obtained via normal means. + break; + case KRITEM_TRIPLESNEAKER: + POWERITEMODDS(newodds); + if (!cv_triplesneaker.value) newodds = 0; + break; + case KRITEM_TRIPLEBANANA: + POWERITEMODDS(newodds); + if (!cv_triplebanana.value) newodds = 0; + break; + case KRITEM_TENFOLDBANANA: + POWERITEMODDS(newodds); + if (!cv_triplebanana.value) newodds = 0; + break; + case KRITEM_TRIPLEORBINAUT: + POWERITEMODDS(newodds); + if (!cv_tripleorbinaut.value) newodds = 0; + break; + case KRITEM_QUADORBINAUT: + POWERITEMODDS(newodds); + if (!cv_tripleorbinaut.value) newodds = 0; + break; + case KRITEM_DUALJAWZ: + POWERITEMODDS(newodds); + if (!cv_dualjawz.value) newodds = 0; + break; + default: + break; + } +#undef POWERITEMODDS + return newodds; } //{ SRB2kart Roulette Code - Distance Based, no waypoints -static void K_KartItemRouletteByDistance(player_t *player, ticcmd_t *cmd) +static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) { + const INT32 distvar = (64*14); INT32 i; - INT32 pingame = 0, pexiting = 0; - INT32 roulettestop; - INT32 prandom; + UINT8 pingame = 0; + UINT8 roulettestop; INT32 pdis = 0, useodds = 0; - INT32 spawnchance[NUMKARTITEMS * NUMKARTODDS]; + INT32 spawnchance[NUMKARTRESULTS * NUMKARTODDS]; INT32 chance = 0, numchoices = 0; - INT32 distvar = (64*14); - INT32 avgballoon = 0; - INT32 secondist = 0; - SINT8 first = -1; - SINT8 second = -1; - boolean mashed = false; + INT32 bestbumper = 0; + boolean oddsvalid[9]; + UINT8 disttable[14]; + UINT8 distlen = 0; + fixed_t mashed = 0; // This makes the roulette cycle through items - if this is 0, you shouldn't be here. if (player->kartstuff[k_itemroulette]) @@ -558,147 +754,196 @@ static void K_KartItemRouletteByDistance(player_t *player, ticcmd_t *cmd) else return; - // This makes the roulette produce the random noises. - if ((player->kartstuff[k_itemroulette] % 3) == 1 && P_IsLocalPlayer(player)) - S_StartSound(NULL,sfx_mkitm1 + ((player->kartstuff[k_itemroulette] / 3) % 8)); - - roulettestop = (TICRATE*1) + (3*(pingame - player->kartstuff[k_position])); - - // If the roulette finishes or the player presses BT_ATTACK, stop the roulette and calculate the item. - // I'm returning via the exact opposite, however, to forgo having another bracket embed. Same result either way, I think. - // Finally, if you get past this check, now you can actually start calculating what item you get. - if ((cmd->buttons & BT_ATTACK) && player->kartstuff[k_itemroulette] >= roulettestop) - mashed = true; // Mashing halves your chances for the good items - else if (!(player->kartstuff[k_itemroulette] >= (TICRATE*3))) - return; - - if (cmd->buttons & BT_ATTACK) - player->pflags |= PF_ATTACKDOWN; - - // Initializes existing spawnchance values - for (i = 0; i < (NUMKARTITEMS * NUMKARTODDS); i++) - spawnchance[i] = 0; - // Gotta check how many players are active at this moment. for (i = 0; i < MAXPLAYERS; i++) { if (!playeringame[i] || players[i].spectator) continue; pingame++; - if (players[i].exiting) - pexiting++; - if (players[i].kartstuff[k_balloon] > 0) - avgballoon += players[i].kartstuff[k_balloon]; + if (players[i].kartstuff[k_bumper] > bestbumper) + bestbumper = players[i].kartstuff[k_bumper]; } - if (pingame) - avgballoon /= pingame; + // This makes the roulette produce the random noises. + if ((player->kartstuff[k_itemroulette] % 3) == 1 && P_IsLocalPlayer(player)) + S_StartSound(NULL, sfx_mkitm1 + ((player->kartstuff[k_itemroulette] / 3) % 8)); + + roulettestop = (TICRATE*1) + (3*(pingame - player->kartstuff[k_position])); + + // If the roulette finishes or the player presses BT_ATTACK, stop the roulette and calculate the item. + // I'm returning via the exact opposite, however, to forgo having another bracket embed. Same result either way, I think. + // Finally, if you get past this check, now you can actually start calculating what item you get. + if ((cmd->buttons & BT_ATTACK) && !(player->kartstuff[k_eggmanheld] || player->kartstuff[k_itemheld]) && player->kartstuff[k_itemroulette] >= roulettestop) + { + // Mashing reduces your chances for the good items + mashed = FixedDiv((player->kartstuff[k_itemroulette])*FRACUNIT, ((TICRATE*3)+roulettestop)*FRACUNIT) - FRACUNIT; + } + else if (!(player->kartstuff[k_itemroulette] >= (TICRATE*3))) + return; + + if (cmd->buttons & BT_ATTACK) + player->pflags |= PF_ATTACKDOWN; + + if (player->kartstuff[k_roulettetype] == 2) // Fake items + { + player->kartstuff[k_eggmanexplode] = 4*TICRATE; + player->kartstuff[k_itemroulette] = 0; + player->kartstuff[k_roulettetype] = 0; + if (P_IsLocalPlayer(player)) + S_StartSound(NULL, sfx_mkitmE); + return; + } + + if (cv_kartdebugitem.value != 0) + { + K_KartGetItemResult(player, cv_kartdebugitem.value); + player->kartstuff[k_itemamount] = cv_kartdebugamount.value; + player->kartstuff[k_itemroulette] = 0; + player->kartstuff[k_roulettetype] = 0; + if (P_IsLocalPlayer(player)) + S_StartSound(NULL, sfx_dbgsal); + return; + } + + // Initializes existing spawnchance values + for (i = 0; i < (NUMKARTRESULTS * NUMKARTODDS); i++) + spawnchance[i] = 0; + + for (i = 0; i < 9; i++) + { + INT32 j; + boolean available = false; + + if (G_BattleGametype() && i > 5) + { + oddsvalid[i] = false; + break; + } + + for (j = 0; j < NUMKARTRESULTS; j++) + { + if (K_KartGetItemOdds(i, j, mashed) > 0) + { + available = true; + break; + } + } + + oddsvalid[i] = available; + } for (i = 0; i < MAXPLAYERS; i++) { - if (playeringame[i] && !players[i].spectator && players[i].mo) - { - if (players[i].kartstuff[k_position] < player->kartstuff[k_position]) - pdis += P_AproxDistance(P_AproxDistance(players[i].mo->x - player->mo->x, - players[i].mo->y - player->mo->y), - players[i].mo->z - player->mo->z) / mapheaderinfo[gamemap-1]->mobj_scale - * (pingame - players[i].kartstuff[k_position]) - / ((pingame - 1) * (pingame + 1) / 3); - if (players[i].kartstuff[k_position] == 1 && first == -1) - first = i; - if (players[i].kartstuff[k_position] == 2 && second == -1) - second = i; - } + if (playeringame[i] && !players[i].spectator && players[i].mo + && players[i].kartstuff[k_position] < player->kartstuff[k_position]) + pdis += P_AproxDistance(P_AproxDistance(players[i].mo->x - player->mo->x, + players[i].mo->y - player->mo->y), + players[i].mo->z - player->mo->z) / mapheaderinfo[gamemap-1]->mobj_scale + * (pingame - players[i].kartstuff[k_position]) + / ((pingame - 1) * (pingame + 1) / 3); } - if (first != -1 && second != -1 && !secondist) // calculate 2nd's distance from 1st, for blue shell - secondist = P_AproxDistance(P_AproxDistance(players[first].mo->x - players[second].mo->x, - players[first].mo->y - players[second].mo->y), - players[first].mo->z - players[second].mo->z) / mapheaderinfo[gamemap-1]->mobj_scale - * (pingame - 1) - / ((pingame - 1) * (pingame + 1) / 3); - - player->kartstuff[k_itemclose] = 0; // Reset the item window closer. +#define SETUPDISTTABLE(odds, num) \ + for (i = num; i; --i) disttable[distlen++] = odds if (G_BattleGametype()) // Battle Mode { - if (player->kartstuff[k_roulettetype] == 1) - useodds = 5; + if (oddsvalid[0]) SETUPDISTTABLE(0,1); + if (oddsvalid[1]) SETUPDISTTABLE(1,1); + if (oddsvalid[2]) SETUPDISTTABLE(2,1); + + if (player->kartstuff[k_roulettetype] == 1 && oddsvalid[3]) // Player-controlled "Karma" items + useodds = 3; else { - useodds = (player->kartstuff[k_balloon]-avgballoon)+2; // 0 is two balloons below average, 2 is average, 4 is two balloons above average - if (useodds > 4) - useodds = 4; - if (useodds < 0) - useodds = 0; + SINT8 wantedpos = (player->kartstuff[k_bumper]-bestbumper)+2; // 0 is two bumpers below best player's bumper count, 2 is best player's bumper count + if (K_IsPlayerWanted(player)) + wantedpos--; + if (wantedpos > 2) + wantedpos = 2; + if (wantedpos < 0) + wantedpos = 0; + useodds = disttable[(wantedpos * distlen) / 3]; } } else { - if (franticitems) // Frantic items make the distances between everyone artifically higher :P - { + if (oddsvalid[1]) SETUPDISTTABLE(1,1); + if (oddsvalid[2]) SETUPDISTTABLE(2,1); + if (oddsvalid[3]) SETUPDISTTABLE(3,1); + if (oddsvalid[4]) SETUPDISTTABLE(4,2); + if (oddsvalid[5]) SETUPDISTTABLE(5,2); + if (oddsvalid[6]) SETUPDISTTABLE(6,3); + if (oddsvalid[7]) SETUPDISTTABLE(7,3); + if (oddsvalid[8]) SETUPDISTTABLE(8,1); + + if (franticitems) // Frantic items make the distances between everyone artifically higher, for crazier items pdis = (15*pdis/14); - secondist = (15*pdis/14); + if (pingame < 6 && !G_BattleGametype()) + pdis = ((28+(6-pingame))*pdis/28); + + if (pingame == 1 && oddsvalid[0]) // Record Attack, or just alone + useodds = 0; + else if (pdis <= 0) // (64*14) * 0 = 0 + useodds = disttable[0]; + else if (pdis > distvar * ((12 * distlen) / 14)) // (64*14) * 12 = 10752 + useodds = disttable[distlen-1]; + else + { + for (i = 1; i < 12; i++) + { + if (pdis <= distvar * ((i * distlen) / 14)) + { + useodds = disttable[((i * distlen) / 14)]; + break; + } + } } - if (pingame == 1) useodds = 0; // Record Attack, or just alone - else if (pdis <= distvar * 0) useodds = 1; // (64*14) * 0 = 0 - else if (pdis <= distvar * 1) useodds = 2; // (64*14) * 1 = 896 - else if (pdis <= distvar * 2) useodds = 3; // (64*14) * 2 = 1792 - else if (pdis <= distvar * 4) useodds = 4; // (64*14) * 4 = 3584 - else if (pdis <= distvar * 6) useodds = 5; // (64*14) * 6 = 5376 - else if (pdis <= distvar * 9) useodds = 6; // (64*14) * 9 = 8064 - else if (pdis <= distvar * 12) useodds = 7; // (64*14) * 12 = 10752 - else useodds = 8; } - //CONS_Printf("%d %d\n", secondist, distvar*2); +#undef SETUPDISTTABLE + + //CONS_Printf("Got useodds %d. (position: %d, distance: %d)\n", useodds, player->kartstuff[k_position], pdis); #define SETITEMRESULT(pos, itemnum) \ for (chance = 0; chance < K_KartGetItemOdds(pos, itemnum, mashed); chance++) \ spawnchance[numchoices++] = itemnum - // Check the game type to differentiate odds. - //if (gametype == GT_RETRO) - //{ - if (cv_magnet.value) SETITEMRESULT(useodds, 1); // Magnet - if (cv_boo.value) SETITEMRESULT(useodds, 2); // Boo - if (cv_mushroom.value || modeattacking) SETITEMRESULT(useodds, 3); // Mushroom - if (cv_triplemushroom.value) SETITEMRESULT(useodds, 4); // Triple Mushroom - if (cv_megashroom.value && !player->kartstuff[k_poweritemtimer]) SETITEMRESULT(useodds, 5); // Mega Mushroom - if (cv_goldshroom.value) SETITEMRESULT(useodds, 6); // Gold Mushroom - if (cv_star.value && !player->kartstuff[k_poweritemtimer]) SETITEMRESULT(useodds, 7); // Star - if (cv_triplebanana.value) SETITEMRESULT(useodds, 8); // Triple Banana - if (cv_fakeitem.value) SETITEMRESULT(useodds, 9); // Fake Item - if (cv_banana.value) SETITEMRESULT(useodds, 10); // Banana - if (cv_greenshell.value) SETITEMRESULT(useodds, 11); // Green Shell - if (cv_redshell.value) SETITEMRESULT(useodds, 12); // Red Shell - if (cv_triplegreenshell.value) SETITEMRESULT(useodds, 13); // Triple Green Shell - if (cv_bobomb.value) SETITEMRESULT(useodds, 14); // Bob-omb - if (cv_blueshell.value && pexiting == 0 - && (secondist > distvar*4) && !lightningcooldown) SETITEMRESULT(useodds, 15); // Blue Shell - if (cv_fireflower.value) SETITEMRESULT(useodds, 16); // Fire Flower - if (cv_tripleredshell.value) SETITEMRESULT(useodds, 17); // Triple Red Shell - if (cv_lightning.value && pingame > pexiting && !lightningcooldown) SETITEMRESULT(useodds, 18); // Lightning - if (cv_feather.value) SETITEMRESULT(useodds, 19); // Feather + SETITEMRESULT(useodds, KITEM_SNEAKER); // Sneaker + SETITEMRESULT(useodds, KITEM_ROCKETSNEAKER); // Rocket Sneaker + SETITEMRESULT(useodds, KITEM_INVINCIBILITY); // Invincibility + SETITEMRESULT(useodds, KITEM_BANANA); // Banana + SETITEMRESULT(useodds, KITEM_EGGMAN); // Eggman Monitor + SETITEMRESULT(useodds, KITEM_ORBINAUT); // Orbinaut + SETITEMRESULT(useodds, KITEM_JAWZ); // Jawz + SETITEMRESULT(useodds, KITEM_MINE); // Mine + SETITEMRESULT(useodds, KITEM_BALLHOG); // Ballhog + SETITEMRESULT(useodds, KITEM_SPB); // Self-Propelled Bomb + SETITEMRESULT(useodds, KITEM_GROW); // Grow + SETITEMRESULT(useodds, KITEM_SHRINK); // Shrink + SETITEMRESULT(useodds, KITEM_THUNDERSHIELD); // Thunder Shield + SETITEMRESULT(useodds, KITEM_HYUDORO); // Hyudoro + SETITEMRESULT(useodds, KITEM_POGOSPRING); // Pogo Spring + //SETITEMRESULT(useodds, KITEM_KITCHENSINK); // Kitchen Sink - prandom = P_RandomKey(numchoices); - - // Award the player whatever power is rolled - if (numchoices > 0) - K_KartGetItemResult(player, spawnchance[prandom], true); - else - CONS_Printf("ERROR: P_KartItemRoulette - There were no choices given by the roulette (useodds = %d).\n", useodds); - //} - /*else if (gametype == GT_NEO) - { - - } - else - CONS_Printf("ERROR: P_KartItemRoulette - There's no applicable game type!\n"); - */ + SETITEMRESULT(useodds, KRITEM_TRIPLESNEAKER); // Sneaker x3 + SETITEMRESULT(useodds, KRITEM_TRIPLEBANANA); // Banana x3 + SETITEMRESULT(useodds, KRITEM_TENFOLDBANANA); // Banana x10 + SETITEMRESULT(useodds, KRITEM_TRIPLEORBINAUT); // Orbinaut x3 + SETITEMRESULT(useodds, KRITEM_QUADORBINAUT); // Orbinaut x4 + SETITEMRESULT(useodds, KRITEM_DUALJAWZ); // Jawz x2 #undef SETITEMRESULT + // Award the player whatever power is rolled + if (numchoices > 0) + K_KartGetItemResult(player, spawnchance[P_RandomKey(numchoices)]); + else + { + player->kartstuff[k_itemtype] = KITEM_SAD; + player->kartstuff[k_itemamount] = 1; + } + player->kartstuff[k_itemroulette] = 0; // Since we're done, clear the roulette number player->kartstuff[k_roulettetype] = 0; // This too @@ -710,11 +955,46 @@ static void K_KartItemRouletteByDistance(player_t *player, ticcmd_t *cmd) //{ SRB2kart p_user.c Stuff +static fixed_t K_GetMobjWeight(mobj_t *mobj, mobj_t *against) +{ + fixed_t weight = 5<type) + { + case MT_PLAYER: + if (!mobj->player) + break; + if (against->player && !against->player->kartstuff[k_spinouttimer] && mobj->player->kartstuff[k_spinouttimer]) + weight = 0; // Do not bump + else + weight = (mobj->player->kartweight)<player) + weight = (against->player->kartweight)<player) + weight = (against->player->kartweight+3)<player && mobj2->player->playerstate != PST_LIVE)) return; - if ((mobj1->player && mobj1->player->kartstuff[k_lakitu]) - || (mobj2->player && mobj2->player->kartstuff[k_lakitu])) + if ((mobj1->player && mobj1->player->kartstuff[k_respawn]) + || (mobj2->player && mobj2->player->kartstuff[k_respawn])) return; // Don't bump if you've recently bumped - if ((mobj1->player && mobj1->player->kartstuff[k_justbumped]) - || (mobj2->player && mobj1->player->kartstuff[k_justbumped])) + if (mobj1->player && mobj1->player->kartstuff[k_justbumped]) { - if (mobj1->player) - mobj1->player->kartstuff[k_justbumped] = bumptime; - if (mobj2->player) - mobj2->player->kartstuff[k_justbumped] = bumptime; + mobj1->player->kartstuff[k_justbumped] = bumptime; return; } - S_StartSound(mobj1, sfx_s3k49); - - fx = P_SpawnMobj(mobj1->x/2 + mobj2->x/2, mobj1->y/2 + mobj2->y/2, mobj1->z/2 + mobj2->z/2, MT_BUMP); - if (mobj1->eflags & MFE_VERTICALFLIP) - fx->eflags |= MFE_VERTICALFLIP; - else - fx->eflags &= ~MFE_VERTICALFLIP; - fx->scale = mobj1->scale; - - if (bounce == true) // Perform a Goomba Bounce. - mobj1->momz = -mobj1->momz; - else + if (mobj2->player && mobj2->player->kartstuff[k_justbumped]) { - fixed_t newz = mobj1->momz; - mobj1->momz = mobj2->momz; - if (solid == false) - mobj2->momz = newz; + mobj2->player->kartstuff[k_justbumped] = bumptime; + return; } - mass1 = mass2 = 5*FRACUNIT; + mass1 = K_GetMobjWeight(mobj1, mobj2); - if (mobj1->player) - mass1 = (mobj1->player->kartweight)*FRACUNIT; - - if (mobj2->player) - mass2 = (mobj2->player->kartweight)*FRACUNIT; - else if (solid == true) + if (solid == true && mass1 > 0) mass2 = mass1; + else + mass2 = K_GetMobjWeight(mobj2, mobj1); momdifx = mobj1->momx - mobj2->momx; momdify = mobj1->momy - mobj2->momy; @@ -783,8 +1043,19 @@ void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid) momdify = FixedMul((25*mapheaderinfo[gamemap-1]->mobj_scale), normalisedy); } - distx = mobj1->x - mobj2->x; - disty = mobj1->y - mobj2->y; + /*if (mass1 == 0 && mass2 > 0) + { + nobumpx = mobj2->momx; + nobumpy = mobj2->momy; + } + else if (mass2 == 0 && mass1 > 0) + { + nobumpx = mobj1->momx; + nobumpy = mobj1->momy; + }*/ + + distx = (mobj1->x + mobj2->momx) - (mobj2->x + mobj1->momx); + disty = (mobj1->y + mobj2->momy) - (mobj2->y + mobj1->momy); if (distx == 0 && disty == 0) { @@ -802,15 +1073,39 @@ void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid) p = FixedDiv(dot, FixedMul(distx, distx)+FixedMul(disty, disty)); - 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); + if (bounce == true && mass2 > 0) // Perform a Goomba Bounce. + mobj1->momz = -mobj1->momz; + else + { + fixed_t newz = mobj1->momz; + if (mass2 > 0) + mobj1->momz = mobj2->momz; + if (mass1 > 0 && solid == false) + mobj2->momz = newz; + } - if (solid == false) + 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); + } + + 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); } + // Do the bump fx when we've CONFIRMED we can bump. + S_StartSound(mobj1, sfx_s3k49); + + fx = P_SpawnMobj(mobj1->x/2 + mobj2->x/2, mobj1->y/2 + mobj2->y/2, mobj1->z/2 + mobj2->z/2, MT_BUMP); + if (mobj1->eflags & MFE_VERTICALFLIP) + fx->eflags |= MFE_VERTICALFLIP; + else + fx->eflags &= ~MFE_VERTICALFLIP; + fx->scale = mobj1->scale; + // Because this is done during collision now, rmomx and rmomy need to be recalculated // so that friction doesn't immediately decide to stop the player if they're at a standstill // Also set justbumped here @@ -819,6 +1114,11 @@ void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid) mobj1->player->rmomx = mobj1->momx - mobj1->player->cmomx; mobj1->player->rmomy = mobj1->momy - mobj1->player->cmomy; mobj1->player->kartstuff[k_justbumped] = bumptime; + if (mobj1->player->kartstuff[k_spinouttimer]) + { + mobj1->player->kartstuff[k_wipeoutslow] += wipeoutslowtime+1; + mobj1->player->kartstuff[k_spinouttimer] += wipeoutslowtime+1; + } } if (mobj2->player) @@ -826,6 +1126,11 @@ void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid) mobj2->player->rmomx = mobj2->momx - mobj2->player->cmomx; mobj2->player->rmomy = mobj2->momy - mobj2->player->cmomy; mobj2->player->kartstuff[k_justbumped] = bumptime; + if (mobj2->player->kartstuff[k_spinouttimer]) + { + mobj2->player->kartstuff[k_wipeoutslow] += wipeoutslowtime+1; + mobj2->player->kartstuff[k_spinouttimer] += wipeoutslowtime+1; + } } } @@ -894,7 +1199,7 @@ static void K_UpdateOffroad(player_t *player) // A higher kart weight means you can stay offroad for longer without losing speed offroad = (1872 + 5*156 - kartweight*156)*offroadstrength; - //if (player->kartstuff[k_growshrinktimer] > 1) // megashroom slows down half as fast + //if (player->kartstuff[k_growshrinktimer] > 1) // grow slows down half as fast // offroad /= 2; player->kartstuff[k_offroad] += offroad; @@ -907,51 +1212,59 @@ static void K_UpdateOffroad(player_t *player) player->kartstuff[k_offroad] = 0; } -/** \brief Calculates the lakitu timer and drop-boosting +/** \brief Calculates the respawn timer and drop-boosting \param player player object passed from K_KartPlayerThink \return void */ -void K_LakituChecker(player_t *player) +void K_RespawnChecker(player_t *player) { ticcmd_t *cmd = &player->cmd; - if (player->kartstuff[k_lakitu] == 44) - { - mobj_t *mo; - angle_t newangle; - fixed_t newx; - fixed_t newy; - fixed_t newz; - newangle = player->mo->angle; - newx = player->mo->x + P_ReturnThrustX(player->mo, newangle, 0); - newy = player->mo->y + P_ReturnThrustY(player->mo, newangle, 0); - if (player->mo->eflags & MFE_VERTICALFLIP) - newz = player->mo->z - 128*(mapheaderinfo[gamemap-1]->mobj_scale); - else - newz = player->mo->z + 64*(mapheaderinfo[gamemap-1]->mobj_scale); - mo = P_SpawnMobj(newx, newy, newz, MT_LAKITU); - if (mo) - { - if (player->mo->eflags & MFE_VERTICALFLIP) - mo->eflags |= MFE_VERTICALFLIP; - mo->angle = newangle+ANGLE_180; - P_SetTarget(&mo->target, player->mo); - } - } + if (player->spectator) + return; - if (player->kartstuff[k_lakitu] > 3) + if (player->kartstuff[k_respawn] > 3) { - player->kartstuff[k_lakitu]--; + player->kartstuff[k_respawn]--; player->mo->momz = 0; player->powers[pw_flashing] = 2; player->powers[pw_nocontrol] = 2; - if (leveltime % 15 == 0) - S_StartSound(player->mo, sfx_lkt3); + if (leveltime % 8 == 0) + { + INT32 i; + if (!mapreset) + S_StartSound(player->mo, sfx_s3kcas); + + for (i = 0; i < 8; i++) + { + mobj_t *mo; + angle_t newangle; + fixed_t newx, newy, newz; + + newangle = FixedAngle(((360/8)*i)*FRACUNIT); + newx = player->mo->x + P_ReturnThrustX(player->mo, newangle, 31*player->mo->scale); + newy = player->mo->y + P_ReturnThrustY(player->mo, newangle, 31*player->mo->scale); + if (player->mo->eflags & MFE_VERTICALFLIP) + newz = player->mo->z + player->mo->height; + else + newz = player->mo->z; + + mo = P_SpawnMobj(newx, newy, newz, MT_DEZLASER); + if (mo) + { + if (player->mo->eflags & MFE_VERTICALFLIP) + mo->eflags |= MFE_VERTICALFLIP; + P_SetTarget(&mo->target, player->mo); + mo->angle = newangle+ANGLE_90; + mo->momz = (8*FRACUNIT)*P_MobjFlip(player->mo); + } + } + } } - // That's enough pointless fishing for now. - if (player->kartstuff[k_lakitu] > 0 && player->kartstuff[k_lakitu] <= 3) + + if (player->kartstuff[k_respawn] > 0 && player->kartstuff[k_respawn] <= 3) { if (!P_IsObjectOnGround(player->mo)) { @@ -961,15 +1274,15 @@ void K_LakituChecker(player_t *player) if (cmd->buttons & BT_ACCELERATE) { player->powers[pw_flashing] = 0; - player->kartstuff[k_lakitu] = 0; + player->kartstuff[k_respawn] = 0; } } else { - player->kartstuff[k_lakitu]--; + player->kartstuff[k_respawn]--; // Quick! You only have three tics to boost! if (cmd->buttons & BT_ACCELERATE) - K_DoMushroom(player, true); + K_DoSneaker(player, true); } } } @@ -1027,51 +1340,91 @@ void K_KartMoveAnimation(player_t *player) } } +static void K_TauntVoiceTimers(player_t *player) +{ + if (!player) + return; + + player->kartstuff[k_tauntvoices] = 6*TICRATE; + player->kartstuff[k_voices] = 4*TICRATE; +} + +static void K_RegularVoiceTimers(player_t *player) +{ + if (!player) + return; + + player->kartstuff[k_voices] = 4*TICRATE; + + if (player->kartstuff[k_tauntvoices] < 4*TICRATE) + player->kartstuff[k_tauntvoices] = 4*TICRATE; +} + static void K_PlayTauntSound(mobj_t *source) { +#if 1 + sfxenum_t pick = P_RandomKey(4); // Gotta roll the RNG every time this is called for sync reasons + boolean tasteful = (!source->player || !source->player->kartstuff[k_tauntvoices]); + + if (cv_kartvoices.value && (tasteful || cv_kartvoices.value == 2)) + S_StartSound(source, sfx_taunt1+pick); + + if (!tasteful) + return; + + K_TauntVoiceTimers(source->player); +#else if (source->player && source->player->kartstuff[k_tauntvoices]) // Prevents taunt sounds from playing every time the button is pressed return; S_StartSound(source, sfx_taunt1+P_RandomKey(4)); - if (source->player) - { - source->player->kartstuff[k_tauntvoices] = 6*TICRATE; - source->player->kartstuff[k_voices] = 3*TICRATE; - } + K_TauntVoiceTimers(source->player); +#endif } static void K_PlayOvertakeSound(mobj_t *source) { - if (source->player && source->player->kartstuff[k_voices]) // Prevents taunt sounds from playing every time the button is pressed +#if 1 + boolean tasteful = (!source->player || !source->player->kartstuff[k_voices]); + + if (!G_RaceGametype()) // Only in race return; // 4 seconds from before race begins, 10 seconds afterwards - if (leveltime < 14*TICRATE) + if (leveltime < starttime+(10*TICRATE)) + return; + + if (cv_kartvoices.value && (tasteful || cv_kartvoices.value == 2)) + S_StartSound(source, sfx_slow); + + if (!tasteful) + return; + + K_RegularVoiceTimers(source->player); +#else + if (source->player && source->player->kartstuff[k_voices]) // Prevents taunt sounds from playing every time the button is pressed + return; + + if (!G_RaceGametype()) // Only in race + return; + + // 4 seconds from before race begins, 10 seconds afterwards + if (leveltime < starttime+(10*TICRATE)) return; S_StartSound(source, sfx_slow); - if (source->player) - { - source->player->kartstuff[k_voices] = 3*TICRATE; - - if (source->player->kartstuff[k_tauntvoices] < 3*TICRATE) - source->player->kartstuff[k_tauntvoices] = 3*TICRATE; - } + K_RegularVoiceTimers(source->player); +#endif } static void K_PlayHitEmSound(mobj_t *source) { - S_StartSound(source, sfx_hitem); + if (cv_kartvoices.value) + S_StartSound(source, sfx_hitem); - if (source->player) - { - source->player->kartstuff[k_voices] = 3*TICRATE; - - if (source->player->kartstuff[k_tauntvoices] < 3*TICRATE) - source->player->kartstuff[k_tauntvoices] = 3*TICRATE; - } + K_RegularVoiceTimers(source->player); } void K_MomentumToFacing(player_t *player) @@ -1082,7 +1435,9 @@ void K_MomentumToFacing(player_t *player) dangle = InvAngle(dangle); // If you aren't on the ground or are moving in too different of a direction don't do this - if (!P_IsObjectOnGround(player->mo) || dangle > ANGLE_90) + if (player->mo->eflags & MFE_JUSTHITFLOOR) + ; // Just hit floor ALWAYS redirects + else if (!P_IsObjectOnGround(player->mo) || dangle > ANGLE_90) return; P_Thrust(player->mo, player->mo->angle, player->speed - FixedMul(player->speed, player->mo->friction)); @@ -1096,30 +1451,26 @@ static fixed_t K_GetKartBoostPower(player_t *player, boolean speed) fixed_t boostpower = FRACUNIT; fixed_t boostvalue = 0; - // Offroad is separate, it's difficult to factor it in with a variable value anyway. - if (!(player->kartstuff[k_startimer] || player->kartstuff[k_bootimer] || player->kartstuff[k_mushroomtimer]) - && player->kartstuff[k_offroad] >= 0 && speed) - boostpower = FixedDiv(boostpower, player->kartstuff[k_offroad] + FRACUNIT); + if (player->kartstuff[k_spinouttimer] && player->kartstuff[k_wipeoutslow] == 1) // Slow down after you've been bumped + return 0; - if (player->kartstuff[k_growshrinktimer] > 1 - && (player->kartstuff[k_growshrinktimer] > ((itemtime + TICRATE*2) - 25) - || player->kartstuff[k_growshrinktimer] <= 26)) - { // Mega Mushroom - Mid-size - if (speed) - { - boostvalue = max(boostvalue, FRACUNIT/8); // + 12.5% - } - } - if (player->kartstuff[k_growshrinktimer] < ((itemtime + TICRATE*2) - 25) - && player->kartstuff[k_growshrinktimer] > 26) - { // Mega Mushroom + // Offroad is separate, it's difficult to factor it in with a variable value anyway. + if (!(player->kartstuff[k_invincibilitytimer] || player->kartstuff[k_hyudorotimer] || player->kartstuff[k_sneakertimer]) + && player->kartstuff[k_offroad] >= 0 && speed) + boostpower = FixedDiv(boostpower, player->kartstuff[k_offroad] + FRACUNIT); + + if (player->kartstuff[k_bananadrag] > TICRATE) + boostpower = 4*boostpower/5; + + if (player->kartstuff[k_growshrinktimer] > 0) + { // Grow if (speed) { boostvalue = max(boostvalue, FRACUNIT/5); // + 20% } } - if (player->kartstuff[k_startimer]) - { // Star + if (player->kartstuff[k_invincibilitytimer]) + { // Invincibility if (speed) boostvalue = max(boostvalue, 3*(FRACUNIT/8)); // + 37.5% else @@ -1132,8 +1483,8 @@ static fixed_t K_GetKartBoostPower(player_t *player, boolean speed) else boostvalue = max(boostvalue, 4*FRACUNIT); // + 400% } - if (player->kartstuff[k_mushroomtimer]) - { // Mushroom + if (player->kartstuff[k_sneakertimer]) + { // Sneaker if (speed) { switch (gamespeed) @@ -1166,6 +1517,9 @@ fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower) UINT8 kartspeed = player->kartspeed; fixed_t finalspeed; + if (doboostpower && !player->kartstuff[k_pogospring] && !P_IsObjectOnGround(player->mo)) + return (75*mapheaderinfo[gamemap-1]->mobj_scale); // air speed cap + switch (gamespeed) { case 0: @@ -1179,7 +1533,7 @@ fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower) break; } - if (G_BattleGametype() && player->kartstuff[k_balloon] <= 0) + if (G_BattleGametype() && player->kartstuff[k_bumper] <= 0) kartspeed = 1; k_speed += kartspeed*3; // 153 - 177 @@ -1196,7 +1550,7 @@ fixed_t K_GetKartAccel(player_t *player) fixed_t k_accel = 32; // 36; UINT8 kartspeed = player->kartspeed; - if (G_BattleGametype() && player->kartstuff[k_balloon] <= 0) + if (G_BattleGametype() && player->kartstuff[k_bumper] <= 0) kartspeed = 1; //k_accel += 3 * (9 - kartspeed); // 36 - 60 @@ -1205,15 +1559,13 @@ fixed_t K_GetKartAccel(player_t *player) return FixedMul(k_accel, K_GetKartBoostPower(player, false)); } -UINT16 K_GetKartFlashing(void) +UINT16 K_GetKartFlashing(player_t *player) { - UINT16 tics = flashingtics; - if (G_BattleGametype()) - { - tics *= 2; - //tics += (3*TICRATE/8) * (player->kartspeed-1); - } - return tics; + UINT16 tics = flashingtics; + if (G_BattleGametype()) + tics *= 2; + tics += (flashingtics/8) * (player->kartspeed); + return tics; } fixed_t K_3dKartMovement(player_t *player, boolean onground, fixed_t forwardmove) @@ -1225,18 +1577,22 @@ fixed_t K_3dKartMovement(player_t *player, boolean onground, fixed_t forwardmove if (!onground) return 0; // If the player isn't on the ground, there is no change in speed - if (forwardmove <= 0 && player->kartstuff[k_brakestop] < 6) // Don't start reversing with brakes until you've made a stop first - { - if (player->speed < 8*FRACUNIT) - player->kartstuff[k_brakestop]++; - return 0; - } - else if (forwardmove > 0) - player->kartstuff[k_brakestop] = 0; - // ACCELCODE!!!1!11! oldspeed = R_PointToDist2(0, 0, player->rmomx, player->rmomy); // FixedMul(P_AproxDistance(player->rmomx, player->rmomy), player->mo->scale); newspeed = FixedDiv(FixedDiv(FixedMul(oldspeed, accelmax - p_accel) + FixedMul(p_speed, p_accel), accelmax), ORIG_FRICTION); + + if (player->kartstuff[k_pogospring]) // Pogo Spring minimum/maximum thrust + { + const fixed_t hscale = mapheaderinfo[gamemap-1]->mobj_scale + (mapheaderinfo[gamemap-1]->mobj_scale - player->mo->scale); + const fixed_t minspeed = 24*hscale; + const fixed_t maxspeed = 36*hscale; + + if (newspeed > maxspeed && player->kartstuff[k_pogospring] == 2) + newspeed = maxspeed; + if (newspeed < minspeed) + newspeed = minspeed; + } + finalspeed = newspeed - oldspeed; // forwardmove is: @@ -1259,100 +1615,165 @@ fixed_t K_3dKartMovement(player_t *player, boolean onground, fixed_t forwardmove return finalspeed; } -void K_SpinPlayer(player_t *player, mobj_t *source) +void K_DoInstashield(player_t *player) { + mobj_t *layera; + mobj_t *layerb; + + if (player->kartstuff[k_instashield] > 0) + return; + + player->kartstuff[k_instashield] = 15; // length of instashield animation + S_StartSound(player->mo, sfx_cdpcm9); + + layera = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_INSTASHIELDA); + P_SetTarget(&layera->target, player->mo); + + layerb = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_INSTASHIELDB); + P_SetTarget(&layerb->target, player->mo); +} + +void K_SpinPlayer(player_t *player, mobj_t *source, INT32 type, boolean trapitem) +{ + UINT8 scoremultiply = 1; + if (!trapitem && G_BattleGametype()) + { + if (K_IsPlayerWanted(player)) + scoremultiply = 3; + else if (player->kartstuff[k_bumper] == 1) + scoremultiply = 2; + } + if (player->health <= 0) return; - if (player->powers[pw_flashing] > 0 || player->kartstuff[k_squishedtimer] > 0 || (player->kartstuff[k_spinouttimer] > 0 && player->kartstuff[k_spinout] > 0) - || player->kartstuff[k_startimer] > 0 || player->kartstuff[k_growshrinktimer] > 0 || player->kartstuff[k_bootimer] > 0 - || (G_BattleGametype() && ((player->kartstuff[k_balloon] <= 0 && player->kartstuff[k_comebacktimer]) || player->kartstuff[k_comebackmode] == 1))) + if (player->powers[pw_flashing] > 0 || player->kartstuff[k_squishedtimer] > 0 || player->kartstuff[k_spinouttimer] > 0 + || player->kartstuff[k_invincibilitytimer] > 0 || player->kartstuff[k_growshrinktimer] > 0 || player->kartstuff[k_hyudorotimer] > 0 + || (G_BattleGametype() && ((player->kartstuff[k_bumper] <= 0 && player->kartstuff[k_comebacktimer]) || player->kartstuff[k_comebackmode] == 1))) + { + K_DoInstashield(player); return; + } if (source && source != player->mo && source->player) K_PlayHitEmSound(source); - player->kartstuff[k_mushroomtimer] = 0; + //player->kartstuff[k_sneakertimer] = 0; player->kartstuff[k_driftboost] = 0; if (G_BattleGametype()) { if (source && source->player && player != source->player) - P_AddPlayerScore(source->player, 1); - - if (player->kartstuff[k_balloon] > 0) { - if (player->kartstuff[k_balloon] == 1) - CONS_Printf(M_GetText("%s lost all of their balloons!\n"), player_names[player-players]); - player->kartstuff[k_balloon]--; + P_AddPlayerScore(source->player, scoremultiply); + if (!trapitem) + { + source->player->kartstuff[k_wanted] -= wantedreduce; + player->kartstuff[k_wanted] -= (wantedreduce/2); + } } - K_CheckBalloons(); + if (player->kartstuff[k_bumper] > 0) + { + if (player->kartstuff[k_bumper] == 1) + { + mobj_t *karmahitbox = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_KARMAHITBOX); // Player hitbox is too small!! + P_SetTarget(&karmahitbox->target, player->mo); + karmahitbox->destscale = player->mo->scale; + P_SetScale(karmahitbox, player->mo->scale); + CONS_Printf(M_GetText("%s lost all of their bumpers!\n"), player_names[player-players]); + } + player->kartstuff[k_bumper]--; + if (K_IsPlayerWanted(player)) + K_CalculateBattleWanted(); + } + + K_CheckBumpers(); } player->kartstuff[k_comebacktimer] = comebacktime; + player->kartstuff[k_spinouttype] = type; + if (player->kartstuff[k_spinouttype] <= 0) { - if (player->kartstuff[k_spinouttype] == 0) - player->kartstuff[k_spinouttimer] = 3*TICRATE/2; // Explosion/Banana Wipeout - else - player->kartstuff[k_spinouttimer] = 3*TICRATE/2; // Oil Slick Wipeout + player->kartstuff[k_spinouttimer] = 3*TICRATE/2; // Banana Spinout - // At Wipeout, playerspeed is increased to 1/4 their regular speed, moving them forward + // At spinout, player speed is increased to 1/4 their regular speed, moving them forward if (player->speed < K_GetKartSpeed(player, true)/4) P_InstaThrust(player->mo, player->mo->angle, FixedMul(K_GetKartSpeed(player, true)/4, player->mo->scale)); S_StartSound(player->mo, sfx_slip); } else - player->kartstuff[k_spinouttimer] = 1*TICRATE; // ? Whipeout + player->kartstuff[k_spinouttimer] = TICRATE+20; // Wipeout - player->powers[pw_flashing] = K_GetKartFlashing(); - - player->kartstuff[k_spinout] = player->kartstuff[k_spinouttimer]; + player->powers[pw_flashing] = K_GetKartFlashing(player); if (player->mo->state != &states[S_KART_SPIN]) P_SetPlayerMobjState(player->mo, S_KART_SPIN); - player->kartstuff[k_spinouttype] = 0; - + player->kartstuff[k_instashield] = 15; return; } void K_SquishPlayer(player_t *player, mobj_t *source) { + UINT8 scoremultiply = 1; + if (G_BattleGametype()) + { + if (K_IsPlayerWanted(player)) + scoremultiply = 3; + else if (player->kartstuff[k_bumper] == 1) + scoremultiply = 2; + } + if (player->health <= 0) return; - if (player->powers[pw_flashing] > 0 || player->kartstuff[k_squishedtimer] > 0 || player->kartstuff[k_startimer] > 0 - || player->kartstuff[k_growshrinktimer] > 0 || player->kartstuff[k_bootimer] > 0 - || (G_BattleGametype() && ((player->kartstuff[k_balloon] <= 0 && player->kartstuff[k_comebacktimer]) || player->kartstuff[k_comebackmode] == 1))) + if (player->powers[pw_flashing] > 0 || player->kartstuff[k_squishedtimer] > 0 || player->kartstuff[k_invincibilitytimer] > 0 + || player->kartstuff[k_growshrinktimer] > 0 || player->kartstuff[k_hyudorotimer] > 0 + || (G_BattleGametype() && ((player->kartstuff[k_bumper] <= 0 && player->kartstuff[k_comebacktimer]) || player->kartstuff[k_comebackmode] == 1))) + { + K_DoInstashield(player); return; + } - player->kartstuff[k_mushroomtimer] = 0; + player->kartstuff[k_sneakertimer] = 0; player->kartstuff[k_driftboost] = 0; if (G_BattleGametype()) { if (source && source->player && player != source->player) - P_AddPlayerScore(source->player, 1); - - if (player->kartstuff[k_balloon] > 0) { - if (player->kartstuff[k_balloon] == 1) - CONS_Printf(M_GetText("%s lost all of their balloons!\n"), player_names[player-players]); - player->kartstuff[k_balloon]--; + P_AddPlayerScore(source->player, scoremultiply); + source->player->kartstuff[k_wanted] -= wantedreduce; + player->kartstuff[k_wanted] -= (wantedreduce/2); } - K_CheckBalloons(); + if (player->kartstuff[k_bumper] > 0) + { + if (player->kartstuff[k_bumper] == 1) + { + mobj_t *karmahitbox = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_KARMAHITBOX); // Player hitbox is too small!! + P_SetTarget(&karmahitbox->target, player->mo); + karmahitbox->destscale = player->mo->scale; + P_SetScale(karmahitbox, player->mo->scale); + CONS_Printf(M_GetText("%s lost all of their bumpers!\n"), player_names[player-players]); + } + player->kartstuff[k_bumper]--; + if (K_IsPlayerWanted(player)) + K_CalculateBattleWanted(); + } + + K_CheckBumpers(); } player->kartstuff[k_comebacktimer] = comebacktime; - player->kartstuff[k_squishedtimer] = 1*TICRATE; + player->kartstuff[k_squishedtimer] = 2*TICRATE; - player->powers[pw_flashing] = K_GetKartFlashing(); + player->powers[pw_flashing] = K_GetKartFlashing(player); player->mo->flags |= MF_NOCLIP; @@ -1361,63 +1782,75 @@ void K_SquishPlayer(player_t *player, mobj_t *source) P_PlayRinglossSound(player->mo); + player->kartstuff[k_instashield] = 15; return; } void K_ExplodePlayer(player_t *player, mobj_t *source) // A bit of a hack, we just throw the player up higher here and extend their spinout timer { + UINT8 scoremultiply = 1; + if (G_BattleGametype()) + { + if (K_IsPlayerWanted(player)) + scoremultiply = 3; + else if (player->kartstuff[k_bumper] == 1) + scoremultiply = 2; + } + if (player->health <= 0) return; - if (player->powers[pw_flashing] > 0 || player->kartstuff[k_squishedtimer] > 0 || (player->kartstuff[k_spinouttimer] > 0 && player->kartstuff[k_spinout] > 0) - || player->kartstuff[k_startimer] > 0 || player->kartstuff[k_growshrinktimer] > 0 || player->kartstuff[k_bootimer] > 0 - || (G_BattleGametype() && ((player->kartstuff[k_balloon] <= 0 && player->kartstuff[k_comebacktimer]) || player->kartstuff[k_comebackmode] == 1))) + if (player->powers[pw_flashing] > 0 || player->kartstuff[k_squishedtimer] > 0 || player->kartstuff[k_spinouttimer] > 0 + || player->kartstuff[k_invincibilitytimer] > 0 || player->kartstuff[k_growshrinktimer] > 0 || player->kartstuff[k_hyudorotimer] > 0 + || (G_BattleGametype() && ((player->kartstuff[k_bumper] <= 0 && player->kartstuff[k_comebacktimer]) || player->kartstuff[k_comebackmode] == 1))) + { + K_DoInstashield(player); return; + } player->mo->momz = 18*(mapheaderinfo[gamemap-1]->mobj_scale); player->mo->momx = player->mo->momy = 0; - player->kartstuff[k_mushroomtimer] = 0; + player->kartstuff[k_sneakertimer] = 0; player->kartstuff[k_driftboost] = 0; if (G_BattleGametype()) { if (source && source->player && player != source->player) { - if (source->player->kartstuff[k_balloon] <= 0) - { - source->player->kartstuff[k_comebackpoints] += 2; - if (netgame && cv_hazardlog.value) - CONS_Printf(M_GetText("%s bombed %s!\n"), player_names[source->player-players], player_names[player-players]); - if (source->player->kartstuff[k_comebackpoints] >= 3) - K_StealBalloon(source->player, player, true); - } - P_AddPlayerScore(source->player, 1); + P_AddPlayerScore(source->player, scoremultiply); + source->player->kartstuff[k_wanted] -= wantedreduce; + player->kartstuff[k_wanted] -= (wantedreduce/2); } - if (player->kartstuff[k_balloon] > 0) + if (player->kartstuff[k_bumper] > 0) { - if (player->kartstuff[k_balloon] == 1) - CONS_Printf(M_GetText("%s lost all of their balloons!\n"), player_names[player-players]); - player->kartstuff[k_balloon]--; + if (player->kartstuff[k_bumper] == 1) + { + mobj_t *karmahitbox = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_KARMAHITBOX); // Player hitbox is too small!! + P_SetTarget(&karmahitbox->target, player->mo); + karmahitbox->destscale = player->mo->scale; + P_SetScale(karmahitbox, player->mo->scale); + CONS_Printf(M_GetText("%s lost all of their bumpers!\n"), player_names[player-players]); + } + player->kartstuff[k_bumper]--; + if (K_IsPlayerWanted(player)) + K_CalculateBattleWanted(); } - K_CheckBalloons(); + K_CheckBumpers(); } player->kartstuff[k_comebacktimer] = comebacktime; player->kartstuff[k_spinouttype] = 1; player->kartstuff[k_spinouttimer] = 2*TICRATE+(TICRATE/2); - player->kartstuff[k_spinout] = player->kartstuff[k_spinouttimer]; - player->powers[pw_flashing] = K_GetKartFlashing(); + player->powers[pw_flashing] = K_GetKartFlashing(player); if (player->mo->state != &states[S_KART_SPIN]) P_SetPlayerMobjState(player->mo, S_KART_SPIN); - player->kartstuff[k_spinouttype] = 0; - P_PlayRinglossSound(player->mo); if (P_IsLocalPlayer(player)) @@ -1426,12 +1859,13 @@ void K_ExplodePlayer(player_t *player, mobj_t *source) // A bit of a hack, we ju quake.time = 5; } + player->kartstuff[k_instashield] = 15; return; } -void K_StealBalloon(player_t *player, player_t *victim, boolean force) +void K_StealBumper(player_t *player, player_t *victim, boolean force) { - INT32 newballoon; + INT32 newbumper; angle_t newangle, diff; fixed_t newx, newy; mobj_t *newmo; @@ -1442,61 +1876,65 @@ void K_StealBalloon(player_t *player, player_t *victim, boolean force) if (player->health <= 0 || victim->health <= 0) return; - if (force) - ; - else + if (!force) { - if (victim->kartstuff[k_balloon] <= 0) // || player->kartstuff[k_balloon] >= cv_kartballoons.value+2 + if (victim->kartstuff[k_bumper] <= 0) // || player->kartstuff[k_bumper] >= cv_kartbumpers.value+2 return; - if ((player->powers[pw_flashing] > 0 || player->kartstuff[k_squishedtimer] > 0 || (player->kartstuff[k_spinouttimer] > 0 && player->kartstuff[k_spinout] > 0) - || player->kartstuff[k_startimer] > 0 || player->kartstuff[k_growshrinktimer] > 0 || player->kartstuff[k_bootimer] > 0 - || (player->kartstuff[k_balloon] <= 0 && player->kartstuff[k_comebacktimer])) - || (victim->powers[pw_flashing] > 0 || victim->kartstuff[k_squishedtimer] > 0 || (victim->kartstuff[k_spinouttimer] > 0 && victim->kartstuff[k_spinout] > 0) - || victim->kartstuff[k_startimer] > 0 || victim->kartstuff[k_growshrinktimer] > 0 || victim->kartstuff[k_bootimer] > 0)) + if (player->kartstuff[k_squishedtimer] > 0 || player->kartstuff[k_spinouttimer] > 0) return; + + if (victim->powers[pw_flashing] > 0 || victim->kartstuff[k_squishedtimer] > 0 || victim->kartstuff[k_spinouttimer] > 0 + || victim->kartstuff[k_invincibilitytimer] > 0 || victim->kartstuff[k_growshrinktimer] > 0 || victim->kartstuff[k_hyudorotimer] > 0) + { + K_DoInstashield(victim); + return; + } } if (netgame) { - if (player->kartstuff[k_balloon] <= 0) + if (player->kartstuff[k_bumper] <= 0) CONS_Printf(M_GetText("%s is back in the game!\n"), player_names[player-players]); else if (cv_hazardlog.value) - CONS_Printf(M_GetText("%s stole a balloon from %s!\n"), player_names[player-players], player_names[victim-players]); + CONS_Printf(M_GetText("%s stole a bumper from %s!\n"), player_names[player-players], player_names[victim-players]); } - newballoon = player->kartstuff[k_balloon]; - if (newballoon <= 1) + newbumper = player->kartstuff[k_bumper]; + if (newbumper <= 1) diff = 0; else - diff = FixedAngle(360*FRACUNIT/newballoon); + diff = FixedAngle(360*FRACUNIT/newbumper); newangle = player->mo->angle; newx = player->mo->x + P_ReturnThrustX(player->mo, newangle + ANGLE_180, 64*FRACUNIT); newy = player->mo->y + P_ReturnThrustY(player->mo, newangle + ANGLE_180, 64*FRACUNIT); - newmo = P_SpawnMobj(newx, newy, player->mo->z, MT_BATTLEBALLOON); - newmo->threshold = newballoon; + newmo = P_SpawnMobj(newx, newy, player->mo->z, MT_BATTLEBUMPER); + newmo->threshold = newbumper; P_SetTarget(&newmo->tracer, victim->mo); P_SetTarget(&newmo->target, player->mo); - newmo->angle = (diff * (newballoon-1)); + newmo->angle = (diff * (newbumper-1)); newmo->color = victim->skincolor; - if (newballoon+1 < 2) - P_SetMobjState(newmo, S_BATTLEBALLOON3); - else if (newballoon+1 < 3) - P_SetMobjState(newmo, S_BATTLEBALLOON2); + if (newbumper+1 < 2) + P_SetMobjState(newmo, S_BATTLEBUMPER3); + else if (newbumper+1 < 3) + P_SetMobjState(newmo, S_BATTLEBUMPER2); else - P_SetMobjState(newmo, S_BATTLEBALLOON1); + P_SetMobjState(newmo, S_BATTLEBUMPER1); - player->kartstuff[k_balloon]++; + S_StartSound(player->mo, sfx_3db06); + + player->kartstuff[k_bumper]++; player->kartstuff[k_comebackpoints] = 0; - player->powers[pw_flashing] = K_GetKartFlashing(); + player->powers[pw_flashing] = K_GetKartFlashing(player); player->kartstuff[k_comebacktimer] = comebacktime; - /*victim->powers[pw_flashing] = K_GetKartFlashing(); + /*victim->powers[pw_flashing] = K_GetKartFlashing(victim); victim->kartstuff[k_comebacktimer] = comebacktime;*/ + victim->kartstuff[k_instashield] = 15; return; } @@ -1585,7 +2023,7 @@ void K_SpawnKartExplosion(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 } // Spawns the purely visual explosion -void K_SpawnBobombExplosion(mobj_t *source, UINT8 color) +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); @@ -1715,6 +2153,18 @@ static mobj_t *K_SpawnKartMissile(mobj_t *source, mobjtype_t type, angle_t angle th->momx = FixedMul(finalspeed, FINECOSINE(an>>ANGLETOFINESHIFT)); th->momy = FixedMul(finalspeed, FINESINE(an>>ANGLETOFINESHIFT)); + if (type == MT_ORBINAUT) + { + if (source && source->player) + th->color = source->player->skincolor; + else + th->color = SKINCOLOR_CLOUDY; + } + else if (type == MT_JAWZ || type == MT_JAWZ_DUD) + { + S_StartSound(th, th->info->activesound); + } + x = x + P_ReturnThrustX(source, an, source->radius + th->radius); y = y + P_ReturnThrustY(source, an, source->radius + th->radius); throwmo = P_SpawnMobj(x, y, z, MT_FIREDITEM); @@ -1739,12 +2189,12 @@ void K_SpawnBoostTrail(player_t *player) I_Assert(!P_MobjWasRemoved(player->mo)); if (!P_IsObjectOnGround(player->mo) - || player->kartstuff[k_bootimer] != 0 - || (G_BattleGametype() && player->kartstuff[k_balloon] <= 0 && player->kartstuff[k_comebacktimer])) + || player->kartstuff[k_hyudorotimer] != 0 + || (G_BattleGametype() && player->kartstuff[k_bumper] <= 0 && player->kartstuff[k_comebacktimer])) return; if (player->mo->eflags & MFE_VERTICALFLIP) - ground = player->mo->ceilingz - FixedMul(mobjinfo[MT_MUSHROOMTRAIL].height, player->mo->scale); + ground = player->mo->ceilingz - FixedMul(mobjinfo[MT_SNEAKERTRAIL].height, player->mo->scale); else ground = player->mo->floorz; @@ -1762,10 +2212,10 @@ void K_SpawnBoostTrail(player_t *player) { ground = P_GetZAt(player->mo->standingslope, newx, newy); if (player->mo->eflags & MFE_VERTICALFLIP) - ground -= FixedMul(mobjinfo[MT_MUSHROOMTRAIL].height, player->mo->scale); + ground -= FixedMul(mobjinfo[MT_SNEAKERTRAIL].height, player->mo->scale); } #endif - flame = P_SpawnMobj(newx, newy, ground, MT_MUSHROOMTRAIL); + flame = P_SpawnMobj(newx, newy, ground, MT_SNEAKERTRAIL); P_SetTarget(&flame->target, player->mo); flame->angle = travelangle; @@ -1789,6 +2239,56 @@ void K_SpawnBoostTrail(player_t *player) } } +void K_SpawnSparkleTrail(mobj_t *mo) +{ + const INT32 rad = (mo->radius*2)>>FRACBITS; + mobj_t *sparkle; + INT32 i; + + I_Assert(mo != NULL); + I_Assert(!P_MobjWasRemoved(mo)); + + for (i = 0; i < 3; i++) + { + fixed_t newx = mo->x + mo->momx + (P_RandomRange(-rad, rad)<y + mo->momy + (P_RandomRange(-rad, rad)<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); + sparkle->color = mo->color; + //sparkle->colorized = mo->colorized; + } + + P_SetMobjState(sparkle, S_KARTINVULN_LARGE1); +} + +void K_SpawnWipeoutTrail(mobj_t *mo, boolean translucent) +{ + mobj_t *dust; + + I_Assert(mo != NULL); + I_Assert(!P_MobjWasRemoved(mo)); + + dust = P_SpawnMobj(mo->x + (P_RandomRange(-25,25)<y + (P_RandomRange(-25,25)<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); + + if (translucent) + dust->flags2 |= MF2_SHADOW; +} + // K_DriftDustHandling // Parameters: // spawner: The map object that is spawning the drift dust @@ -1806,20 +2306,24 @@ void K_DriftDustHandling(mobj_t *spawner) if (spawner->player) { - angle_t playerangle; - - if (spawner->player->speed < 5<player->cmd.forwardmove < 0) + if (spawner->player->pflags & PF_SKIDDOWN) { - playerangle = spawner->angle+ANGLE_180; + anglediff = abs(spawner->angle - spawner->player->frameangle); + if (leveltime % 6 == 0) + S_StartSound(spawner, sfx_screec); // repeated here because it doesn't always happen to be within the range when this is the case } else { - playerangle = spawner->angle; + angle_t playerangle = spawner->angle; + + if (spawner->player->speed < 5<player->cmd.forwardmove < 0) + playerangle += ANGLE_180; + + anglediff = abs(playerangle - R_PointToAngle2(0, 0, spawner->player->rmomx, spawner->player->rmomy)); } - anglediff = abs(playerangle - R_PointToAngle2(0, 0, spawner->player->rmomx, spawner->player->rmomy)); } else { @@ -1838,25 +2342,73 @@ 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)<momy = FixedMul(spawner->momy + (P_RandomRange(-speedrange, speedrange)<momz = P_MobjFlip(spawner) * P_RandomRange(1, 4)<scale = spawner->scale/2; dust->destscale = spawner->scale * 3; + if (leveltime % 6 == 0) - { S_StartSound(spawner, sfx_screec); - } + + // Now time for a bunch of flag shit, groooooaann... + if (spawner->flags2 & MF2_DONTDRAW) + dust->flags2 |= MF2_DONTDRAW; + else + dust->flags2 &= ~MF2_DONTDRAW; + + if (spawner->eflags & MFE_VERTICALFLIP) + dust->eflags |= MFE_VERTICALFLIP; + else + dust->eflags &= ~MFE_VERTICALFLIP; + + if (spawner->eflags & MFE_DRAWONLYFORP1) + dust->eflags |= MFE_DRAWONLYFORP1; + else + dust->eflags &= ~MFE_DRAWONLYFORP1; + + if (spawner->eflags & MFE_DRAWONLYFORP2) + dust->eflags |= MFE_DRAWONLYFORP2; + else + dust->eflags &= ~MFE_DRAWONLYFORP2; + + if (spawner->eflags & MFE_DRAWONLYFORP3) + dust->eflags |= MFE_DRAWONLYFORP3; + else + dust->eflags &= ~MFE_DRAWONLYFORP3; + + if (spawner->eflags & MFE_DRAWONLYFORP4) + dust->eflags |= MFE_DRAWONLYFORP4; + else + dust->eflags &= ~MFE_DRAWONLYFORP4; } } -static mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t mapthing, INT32 defaultDir, boolean bobombthrow) +static mobj_t *K_FindLastTrailMobj(player_t *player) +{ + mobj_t *trail; + + if (!player || !(trail = player->mo) || !player->mo->hnext || !player->mo->hnext->health) + return NULL; + + while (trail->hnext && !P_MobjWasRemoved(trail->hnext) && trail->hnext->health) + { + trail = trail->hnext; + } + + return trail; +} + +static mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t mapthing, INT32 defaultDir, boolean minethrow) { mobj_t *mo; INT32 dir, PROJSPEED; angle_t newangle; - fixed_t newx; - fixed_t newy; + fixed_t newx, newy, newz; mobj_t *throwmo; if (!player) @@ -1876,11 +2428,11 @@ static mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t map break; } - if (bobombthrow) + if (minethrow) { if (player->kartstuff[k_throwdir] == 1) dir = 2; - else if (player->kartstuff[k_throwdir] == -1) + else if (player->kartstuff[k_throwdir] == -1 && mapthing != MT_SINK) dir = -1; else dir = 1; @@ -1893,9 +2445,9 @@ static mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t map dir = defaultDir; } - if (missile) + if (missile) // Shootables { - if (mapthing == MT_FIREBALL) // Messy + if (mapthing == MT_BALLHOG) // Messy { if (dir == -1) { @@ -1916,7 +2468,7 @@ static mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t map K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + 0x06000000, 0, PROJSPEED); } } - else // Shells + else { if (dir == -1) { @@ -1932,6 +2484,8 @@ static mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t map } else { + player->kartstuff[k_bananadrag] = 0; // RESET timer, for multiple bananas + if (dir == 1 || dir == 2) { // Shoot forward @@ -1966,15 +2520,27 @@ static mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t map } else { - fixed_t dropradius = FixedHypot(player->mo->radius, player->mo->radius) + FixedHypot(mobjinfo[mapthing].radius, mobjinfo[mapthing].radius); + mobj_t *lasttrail = K_FindLastTrailMobj(player); - // Drop it directly behind you. - newangle = player->mo->angle; + if (lasttrail) + { + newx = lasttrail->x; + newy = lasttrail->y; + newz = lasttrail->z; + } + else + { + // Drop it directly behind you. + fixed_t dropradius = FixedHypot(player->mo->radius, player->mo->radius) + FixedHypot(mobjinfo[mapthing].radius, mobjinfo[mapthing].radius); - newx = player->mo->x + P_ReturnThrustX(player->mo, newangle + ANGLE_180, dropradius); - newy = player->mo->y + P_ReturnThrustY(player->mo, newangle + ANGLE_180, dropradius); + newangle = player->mo->angle; - mo = P_SpawnMobj(newx, newy, player->mo->z, mapthing); + newx = player->mo->x + P_ReturnThrustX(player->mo, newangle + ANGLE_180, dropradius); + newy = player->mo->y + P_ReturnThrustY(player->mo, newangle + ANGLE_180, dropradius); + newz = player->mo->z; + } + + mo = P_SpawnMobj(newx, newy, newz, mapthing); if (P_MobjFlip(player->mo) < 0) mo->z = player->mo->z + player->mo->height - mo->height; @@ -2011,22 +2577,24 @@ static mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t map } } } + return mo; } -static void K_DoMagnet(player_t *player) +static void K_DoThunderShield(player_t *player) { S_StartSound(player->mo, sfx_s3k45); - player->kartstuff[k_magnettimer] = 35; + //player->kartstuff[k_thunderanim] = 35; P_NukeEnemies(player->mo, player->mo, RING_DIST/4); } -static void K_DoBooSteal(player_t *player) +static void K_DoHyudoroSteal(player_t *player) { INT32 i, numplayers = 0; INT32 playerswappable[MAXPLAYERS]; INT32 stealplayer = -1; // The player that's getting stolen from INT32 prandom = 0; + boolean sink = P_RandomChance(FRACUNIT/64); for (i = 0; i < MAXPLAYERS; i++) { @@ -2034,28 +2602,13 @@ static void K_DoBooSteal(player_t *player) && player != &players[i] && !players[i].exiting && !players[i].spectator // Player in-game // Can steal from this player - && ((G_RaceGametype() && players[i].kartstuff[k_position] < player->kartstuff[k_position]) - || (G_BattleGametype() && players[i].kartstuff[k_balloon] > 0)) + && (G_RaceGametype() //&& players[i].kartstuff[k_position] < player->kartstuff[k_position]) + || (G_BattleGametype() && players[i].kartstuff[k_bumper] > 0)) // Has an item - && (players[i].kartstuff[k_magnet] - || players[i].kartstuff[k_mushroom] - || players[i].kartstuff[k_megashroom] - || players[i].kartstuff[k_goldshroom] - || players[i].kartstuff[k_star] - || players[i].kartstuff[k_banana] & 2 - || players[i].kartstuff[k_triplebanana] & 8 - || players[i].kartstuff[k_fakeitem] & 2 - || players[i].kartstuff[k_greenshell] & 2 - || players[i].kartstuff[k_triplegreenshell] & 8 - || players[i].kartstuff[k_redshell] & 2 - || players[i].kartstuff[k_tripleredshell] & 8 - || players[i].kartstuff[k_bobomb] & 2 - || players[i].kartstuff[k_lightning] - || players[i].kartstuff[k_blueshell] - || players[i].kartstuff[k_fireflower] - || players[i].kartstuff[k_feather] & 1 - || players[i].kartstuff[k_boo])) // Stealing boos with boos? sounds like fun + && (players[i].kartstuff[k_itemtype] + && players[i].kartstuff[k_itemamount] + && !players[i].kartstuff[k_itemheld])) { playerswappable[numplayers] = i; numplayers++; @@ -2063,12 +2616,22 @@ static void K_DoBooSteal(player_t *player) } prandom = P_RandomFixed(); + S_StartSound(player->mo, sfx_s3k92); - if ((G_RaceGametype() && player->kartstuff[k_position] == 1) || numplayers == 0) // No-one can be stolen from? Get longer invisibility for nothing + if (sink && numplayers > 0) // BEHOLD THE KITCHEN SINK { - player->kartstuff[k_bootimer] = bootime; - player->kartstuff[k_bootaketimer] = boostealtime; - player->kartstuff[k_boo] = 0; + player->kartstuff[k_hyudorotimer] = hyudorotime; + player->kartstuff[k_stealingtimer] = stealtime; + + player->kartstuff[k_itemtype] = KITEM_KITCHENSINK; + player->kartstuff[k_itemamount] = 1; + player->kartstuff[k_itemheld] = 0; + return; + } + else if ((G_RaceGametype() && player->kartstuff[k_position] == 1) || numplayers == 0) // No-one can be stolen from? Oh well... + { + player->kartstuff[k_hyudorotimer] = hyudorotime; + player->kartstuff[k_stealingtimer] = stealtime; return; } else if (numplayers == 1) // With just 2 players, we just need to set the other player to be the one to steal from @@ -2082,110 +2645,29 @@ static void K_DoBooSteal(player_t *player) if (stealplayer > -1) // Now here's where we do the stealing, has to be done here because we still know the player we're stealing from { - player->kartstuff[k_bootimer] = bootime; - player->kartstuff[k_bootaketimer] = boostealtime; - player->kartstuff[k_boo] = 0; - players[stealplayer].kartstuff[k_boostolentimer] = boostealtime; + player->kartstuff[k_hyudorotimer] = hyudorotime; + player->kartstuff[k_stealingtimer] = stealtime; + players[stealplayer].kartstuff[k_stolentimer] = stealtime; - if (players[stealplayer].kartstuff[k_star]) - { - player->kartstuff[k_star] = players[stealplayer].kartstuff[k_star]; - players[stealplayer].kartstuff[k_star] = 0; - } - else if (players[stealplayer].kartstuff[k_mushroom]) - { - player->kartstuff[k_mushroom] = players[stealplayer].kartstuff[k_mushroom]; - players[stealplayer].kartstuff[k_mushroom] = 0; - } - else if (players[stealplayer].kartstuff[k_goldshroom]) - { - player->kartstuff[k_goldshroom] = players[stealplayer].kartstuff[k_goldshroom]; - players[stealplayer].kartstuff[k_goldshroom] = 0; - } - else if (players[stealplayer].kartstuff[k_megashroom]) - { - player->kartstuff[k_megashroom] = players[stealplayer].kartstuff[k_megashroom]; - players[stealplayer].kartstuff[k_megashroom] = 0; - } - else if (players[stealplayer].kartstuff[k_lightning]) - { - player->kartstuff[k_lightning] = players[stealplayer].kartstuff[k_lightning]; - players[stealplayer].kartstuff[k_lightning] = 0; - } - else if (players[stealplayer].kartstuff[k_blueshell]) - { - player->kartstuff[k_blueshell] = players[stealplayer].kartstuff[k_blueshell]; - players[stealplayer].kartstuff[k_blueshell] = 0; - } - else if (players[stealplayer].kartstuff[k_greenshell] & 2) - { - player->kartstuff[k_greenshell] |= 2; - players[stealplayer].kartstuff[k_greenshell] &= ~2; - } - else if (players[stealplayer].kartstuff[k_triplegreenshell] & 8) - { - player->kartstuff[k_triplegreenshell] |= 8; - players[stealplayer].kartstuff[k_triplegreenshell] &= ~8; - } - else if (players[stealplayer].kartstuff[k_redshell] & 2) - { - player->kartstuff[k_redshell] |= 2; - players[stealplayer].kartstuff[k_redshell] &= ~2; - } - else if (players[stealplayer].kartstuff[k_tripleredshell] & 8) - { - player->kartstuff[k_tripleredshell] |= 8; - players[stealplayer].kartstuff[k_tripleredshell] &= ~8; - } - else if (players[stealplayer].kartstuff[k_banana] & 2) - { - player->kartstuff[k_banana] |= 2; - players[stealplayer].kartstuff[k_banana] &= ~2; - } - else if (players[stealplayer].kartstuff[k_triplebanana] & 8) - { - player->kartstuff[k_triplebanana] |= 8; - players[stealplayer].kartstuff[k_triplebanana] &= ~8; - } - else if (players[stealplayer].kartstuff[k_fakeitem] & 2) - { - player->kartstuff[k_fakeitem] |= 2; - players[stealplayer].kartstuff[k_fakeitem] &= ~2; - } - else if (players[stealplayer].kartstuff[k_bobomb] & 2) - { - player->kartstuff[k_bobomb] |= 2; - players[stealplayer].kartstuff[k_bobomb] &= ~2; - } - else if (players[stealplayer].kartstuff[k_magnet]) - { - player->kartstuff[k_magnet] = players[stealplayer].kartstuff[k_magnet]; - players[stealplayer].kartstuff[k_magnet] = 0; - } - else if (players[stealplayer].kartstuff[k_fireflower]) - { - player->kartstuff[k_fireflower] = players[stealplayer].kartstuff[k_fireflower]; - players[stealplayer].kartstuff[k_fireflower] = 0; - } - else if (players[stealplayer].kartstuff[k_feather] & 1) - { - player->kartstuff[k_feather] |= 1; - players[stealplayer].kartstuff[k_feather] &= ~1; - } - else if (players[stealplayer].kartstuff[k_boo]) - { - player->kartstuff[k_boo] = players[stealplayer].kartstuff[k_boo]; - players[stealplayer].kartstuff[k_boo] = 0; - } + player->kartstuff[k_itemtype] = players[stealplayer].kartstuff[k_itemtype]; + player->kartstuff[k_itemamount] = players[stealplayer].kartstuff[k_itemamount]; + player->kartstuff[k_itemheld] = 0; + + players[stealplayer].kartstuff[k_itemtype] = KITEM_NONE; + players[stealplayer].kartstuff[k_itemamount] = 0; + players[stealplayer].kartstuff[k_itemheld] = 0; + + if (P_IsLocalPlayer(&players[stealplayer]) && !splitscreen) + S_StartSound(NULL, sfx_s3k92); } } -void K_DoMushroom(player_t *player, boolean doPFlag) +void K_DoSneaker(player_t *player, boolean doPFlag) { if (!player->kartstuff[k_floorboost] || player->kartstuff[k_floorboost] == 3) - S_StartSound(player->mo, sfx_mush); + S_StartSound(player->mo, sfx_cdfm01); - player->kartstuff[k_mushroomtimer] = mushroomtime; + player->kartstuff[k_sneakertimer] = sneakertime; if (doPFlag) player->pflags |= PF_ATTACKDOWN; @@ -2193,54 +2675,45 @@ void K_DoMushroom(player_t *player, boolean doPFlag) K_PlayTauntSound(player->mo); } -static void K_DoLightning(player_t *player) +static void K_DoShrink(player_t *player) { - mobj_t *mo; - thinker_t *think; INT32 i; - S_StartSound(player->mo, sfx_bkpoof); // Sound the BANG! + + S_StartSound(player->mo, sfx_kc46); // Sound the BANG! player->pflags |= PF_ATTACKDOWN; for (i = 0; i < MAXPLAYERS; i++) { - if (playeringame[i]) - P_FlashPal(&players[i], PAL_NUKE, 10); - } + /*if (playeringame[i]) + P_FlashPal(&players[i], PAL_NUKE, 10);*/ - for (think = thinkercap.next; think != &thinkercap; think = think->next) - { - if (think->function.acp1 != (actionf_p1)P_MobjThinker) - continue; // not a mobj thinker - - mo = (mobj_t *)think; - - if (mo->player && !mo->player->spectator - && mo->player->kartstuff[k_position] < player->kartstuff[k_position]) - P_DamageMobj(mo, player->mo, player->mo, 64); - else - continue; + if (playeringame[i] && players[i].mo && !player->spectator + && players[i].kartstuff[k_position] < player->kartstuff[k_position]) + P_DamageMobj(players[i].mo, player->mo, player->mo, 64); } K_PlayTauntSound(player->mo); } -static void K_DoBlueShell(player_t *victim, player_t *source) +static void K_DoSPB(player_t *victim, player_t *source) { - INT32 i; + //INT32 i; S_StartSound(victim->mo, sfx_bkpoof); // Sound the BANG! - for (i = 0; i < MAXPLAYERS; i++) + /*for (i = 0; i < MAXPLAYERS; i++) { if (playeringame[i]) P_FlashPal(&players[i], PAL_NUKE, 10); - } + }*/ if (victim->mo && !victim->spectator) P_DamageMobj(victim->mo, source->mo, source->mo, 65); } -void K_DoBouncePad(mobj_t *mo, fixed_t vertispeed) +void K_DoPogoSpring(mobj_t *mo, fixed_t vertispeed, boolean mute) { + const fixed_t vscale = mapheaderinfo[gamemap-1]->mobj_scale + (mo->scale - mapheaderinfo[gamemap-1]->mobj_scale); + if (mo->player && mo->player->spectator) return; @@ -2267,26 +2740,320 @@ void K_DoBouncePad(mobj_t *mo, fixed_t vertispeed) thrust = 48< 72<player->kartstuff[k_mushroomtimer]) - thrust = FixedMul(thrust, 5*FRACUNIT/4); - else if (mo->player->kartstuff[k_startimer]) - thrust = FixedMul(thrust, 9*FRACUNIT/8); - mo->momz = FixedMul(FINESINE(ANGLE_22h>>ANGLETOFINESHIFT), FixedMul(thrust, mo->scale)); + if (mo->player->kartstuff[k_pogospring] != 2) + { + if (mo->player->kartstuff[k_sneakertimer]) + thrust = FixedMul(thrust, 5*FRACUNIT/4); + else if (mo->player->kartstuff[k_invincibilitytimer]) + thrust = FixedMul(thrust, 9*FRACUNIT/8); + } } else { - thrust = P_AproxDistance(mo->momx,mo->momy); - if (thrust < 8< 16<momx, mo->momy)/2, 5*FRACUNIT/2); + if (thrust < 16<momz = FixedMul(FINESINE(ANGLE_22h>>ANGLETOFINESHIFT), FixedMul(thrust, mo->scale)); + if (thrust > 32<momz = FixedMul(FINESINE(ANGLE_22h>>ANGLETOFINESHIFT), FixedMul(thrust, vscale)); } else - mo->momz = FixedMul(vertispeed, mo->scale); + mo->momz = FixedMul(vertispeed, vscale); - S_StartSound(mo, sfx_boing); + if (!mute) + S_StartSound(mo, sfx_kc2f); +} + +void K_KillBananaChain(mobj_t *banana, mobj_t *inflictor, mobj_t *source) +{ + mobj_t *cachenext; + +killnext: + cachenext = banana->hnext; + + if (banana->health) + { + if (banana->eflags & MFE_VERTICALFLIP) + banana->z -= banana->height; + else + banana->z += banana->height; + + S_StartSound(banana, banana->info->deathsound); + P_KillMobj(banana, inflictor, source); + + P_SetObjectMomZ(banana, 8*FRACUNIT, false); + if (inflictor) + P_InstaThrust(banana, R_PointToAngle2(inflictor->x, inflictor->y, banana->x, banana->y)+ANGLE_90, 16*FRACUNIT); + } + + if ((banana = cachenext)) + goto killnext; +} + +// Just for firing/dropping items. +void K_CleanHnextList(mobj_t *work) +{ + mobj_t *nextwork; + + if (!work) + return; + + work = work->hnext; + + while (work && !P_MobjWasRemoved(work)) + { + nextwork = work->hnext; + + P_RemoveMobj(work); + + work = nextwork; + } +} + +// Ditto. +void K_UpdateHnextList(player_t *player) +{ + mobj_t *work = player->mo, *nextwork; + + if (!work) + return; + + work = work->hnext; + + while (work && !P_MobjWasRemoved(work)) + { + nextwork = work->hnext; + + if (work->movedir > 0 && work->movedir > (UINT16)player->kartstuff[k_itemamount]) + P_RemoveMobj(work); + + work = nextwork; + } +} + +// When an item in the hnext chain dies. +void K_RepairOrbitChain(mobj_t *orbit) +{ + mobj_t *cachenext = orbit->hnext; + + // First, repair the chain + if (orbit->hnext && orbit->hnext->health && !P_MobjWasRemoved(orbit->hnext)) + { + P_SetTarget(&orbit->hnext->hprev, orbit->hprev); + P_SetTarget(&orbit->hnext, NULL); + } + + if (orbit->hprev && orbit->hprev->health && !P_MobjWasRemoved(orbit->hprev)) + { + P_SetTarget(&orbit->hprev->hnext, cachenext); + P_SetTarget(&orbit->hprev, NULL); + } + + // Then recount to make sure item amount is correct + if (orbit->target && orbit->target->player) + { + INT32 num = 0; + + mobj_t *cur = orbit->target->hnext; + mobj_t *prev = NULL; + + while (cur && !P_MobjWasRemoved(cur)) + { + prev = cur; + cur = cur->hnext; + if (++num > orbit->target->player->kartstuff[k_itemamount]) + P_RemoveMobj(prev); + else + prev->movedir = num; + } + + if (orbit->target->player->kartstuff[k_itemamount] != num) + orbit->target->player->kartstuff[k_itemamount] = num; + } +} + +// Move the hnext chain! +static void K_MoveHeldObjects(player_t *player) +{ + if (!player->mo) + return; + + if (!player->mo->hnext) + { + player->kartstuff[k_bananadrag] = 0; + if (player->kartstuff[k_eggmanheld]) + player->kartstuff[k_eggmanheld] = 0; + else if (player->kartstuff[k_itemheld]) + { + player->kartstuff[k_itemamount] = player->kartstuff[k_itemheld] = 0; + player->kartstuff[k_itemtype] = KITEM_NONE; + } + return; + } + + if (P_MobjWasRemoved(player->mo->hnext)) + { + // we need this here too because this is done in afterthink - pointers are cleaned up at the START of each tic... + P_SetTarget(&player->mo->hnext, NULL); + player->kartstuff[k_bananadrag] = 0; + if (player->kartstuff[k_eggmanheld]) + player->kartstuff[k_eggmanheld] = 0; + else if (player->kartstuff[k_itemheld]) + { + player->kartstuff[k_itemamount] = player->kartstuff[k_itemheld] = 0; + player->kartstuff[k_itemtype] = KITEM_NONE; + } + return; + } + + switch (player->mo->hnext->type) + { + case MT_ORBINAUT_SHIELD: // Kart orbit items + case MT_JAWZ_SHIELD: + { + mobj_t *cur = player->mo->hnext; + + player->kartstuff[k_bananadrag] = 0; // Just to make sure + + while (cur && !P_MobjWasRemoved(cur)) + { + const fixed_t radius = FixedHypot(player->mo->radius, player->mo->radius) + FixedHypot(cur->radius, cur->radius); // mobj's distance from its Target, or Radius. + fixed_t z; + + if (!cur->health) + { + cur = cur->hnext; + continue; + } + + cur->color = player->skincolor; + + cur->angle -= ANGLE_90; + cur->angle += FixedAngle(cur->info->speed); + + // If the player is on the ceiling, then flip your items as well. + if (player && player->mo->eflags & MFE_VERTICALFLIP) + cur->eflags |= MFE_VERTICALFLIP; + else + cur->eflags &= ~MFE_VERTICALFLIP; + + // Shrink your items if the player shrunk too. + P_SetScale(cur, (cur->destscale = player->mo->scale)); + + if (P_MobjFlip(cur) > 0) + z = player->mo->z; + else + z = player->mo->z + player->mo->height - cur->height; + + cur->flags |= MF_NOCLIPTHING; // temporarily make them noclip other objects so they can't hit anyone while in the player + P_TeleportMove(cur, player->mo->x, player->mo->y, z); + cur->momx = FixedMul(FINECOSINE(cur->angle>>ANGLETOFINESHIFT), radius); + cur->momy = FixedMul(FINESINE(cur->angle>>ANGLETOFINESHIFT), radius); + cur->flags &= ~MF_NOCLIPTHING; + if (!P_TryMove(cur, player->mo->x + cur->momx, player->mo->y + cur->momy, true)) + P_SlideMove(cur, true); + if (P_IsObjectOnGround(player->mo)) + { + if (P_MobjFlip(cur) > 0) + { + if (cur->floorz > player->mo->z - cur->height) + z = cur->floorz; + } + else + { + if (cur->ceilingz < player->mo->z + player->mo->height + cur->height) + z = cur->ceilingz - cur->height; + } + } + cur->z = z; + cur->momx = cur->momy = 0; + cur->angle += ANGLE_90; + + cur = cur->hnext; + } + } + break; + case MT_BANANA_SHIELD: // Kart trailing items + case MT_SSMINE_SHIELD: + case MT_FAKESHIELD: + { + mobj_t *cur = player->mo->hnext; + mobj_t *targ = player->mo; + + if (P_IsObjectOnGround(player->mo) && player->speed > 0) + { + player->kartstuff[k_bananadrag]++; + if (player->kartstuff[k_bananadrag] > TICRATE) + { + K_SpawnWipeoutTrail(player->mo, true); + if (leveltime % 6 == 0) + S_StartSound(player->mo, sfx_cdfm70); + } + } + + while (cur && !P_MobjWasRemoved(cur)) + { + const fixed_t radius = FixedHypot(targ->radius, targ->radius) + FixedHypot(cur->radius, cur->radius); + angle_t ang; + fixed_t targx; + fixed_t targy; + fixed_t targz; + fixed_t speed; + fixed_t dist = radius/2; + + cur->flags &= ~MF_NOCLIPTHING; + + if (!cur->health) + { + cur = cur->hnext; + continue; + } + + if (cur != player->mo->hnext) + { + targ = cur->hprev; + dist = radius/4; + } + + if (!targ || P_MobjWasRemoved(targ)) + continue; + + ang = targ->angle; + 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; + + cur->angle = R_PointToAngle2(cur->x, cur->y, targx, targy); + + /*if (P_IsObjectOnGround(player->mo) && player->speed > 0 && player->kartstuff[k_bananadrag] > TICRATE + && P_RandomChance(min(FRACUNIT/2, FixedDiv(player->speed, K_GetKartSpeed(player, false))/2))) + { + if (leveltime & 1) + targz += 8*(2*FRACUNIT)/7; + else + targz -= 8*(2*FRACUNIT)/7; + }*/ + + if (speed > dist) + P_InstaThrust(cur, cur->angle, speed-dist); + + P_SetObjectMomZ(cur, FixedMul(targz - cur->z, 7*FRACUNIT/8) - gravity, false); + + if (R_PointToDist2(cur->x, cur->y, targx, targy) > 768*FRACUNIT) + P_TeleportMove(cur, targx, targy, cur->z); + + cur = cur->hnext; + } + } + break; + default: + break; + } } /** \brief Decreases various kart timers and powers per frame. Called in P_PlayerThink in p_user.c @@ -2301,7 +3068,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) K_UpdateOffroad(player); // setting players to use the star colormap and spawning afterimages - if (player->kartstuff[k_startimer]) + if (player->kartstuff[k_invincibilitytimer]) { mobj_t *ghost; player->mo->colorized = true; @@ -2309,36 +3076,78 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) ghost->fuse = 4; ghost->frame |= FF_FULLBRIGHT; } + else if (player->kartstuff[k_eggmanexplode]) + { + const INT32 flashtime = 4<<(player->kartstuff[k_eggmanexplode]/TICRATE); + if (player->kartstuff[k_eggmanexplode] == 1 || (player->kartstuff[k_eggmanexplode] % (flashtime/2) != 0)) + { + player->mo->colorized = false; + player->mo->color = player->skincolor; + } + else if (player->kartstuff[k_eggmanexplode] % flashtime == 0) + { + player->mo->colorized = true; + player->mo->color = SKINCOLOR_BLACK; + } + else + { + player->mo->colorized = true; + player->mo->color = SKINCOLOR_CRIMSON; + } + } + else if (player->kartstuff[k_growshrinktimer]) + { + if (player->kartstuff[k_growshrinktimer] % 5 == 0) + { + player->mo->colorized = true; + player->mo->color = (player->kartstuff[k_growshrinktimer] < 0 ? SKINCOLOR_CREAMSICLE : SKINCOLOR_PERIWINKLE); + } + else + { + player->mo->colorized = false; + player->mo->color = player->skincolor; + } + } else { player->mo->colorized = false; } - if (player->kartstuff[k_itemclose]) - player->kartstuff[k_itemclose]--; - - if (player->kartstuff[k_spinout]) - player->kartstuff[k_spinout]--; - if (player->kartstuff[k_spinouttimer]) - player->kartstuff[k_spinouttimer]--; - else if (!comeback) - player->kartstuff[k_comebacktimer] = comebacktime; - else if (player->kartstuff[k_comebacktimer]) { - player->kartstuff[k_comebacktimer]--; - if (player == &players[consoleplayer] && player->kartstuff[k_balloon] <= 0 && player->kartstuff[k_comebacktimer] <= 0) - comebackshowninfo = true; // client has already seen the message + if ((P_IsObjectOnGround(player->mo) || player->kartstuff[k_spinouttype] == 1) + && (player->kartstuff[k_sneakertimer] == 0)) + { + player->kartstuff[k_spinouttimer]--; + if (player->kartstuff[k_wipeoutslow] > 1) + player->kartstuff[k_wipeoutslow]--; + if (player->kartstuff[k_spinouttimer] == 0) + player->kartstuff[k_spinouttype] = 0; // Reset type + } + } + else + { + if (player->kartstuff[k_wipeoutslow] == 1) + player->mo->friction = ORIG_FRICTION; + player->kartstuff[k_wipeoutslow] = 0; + if (!comeback) + player->kartstuff[k_comebacktimer] = comebacktime; + else if (player->kartstuff[k_comebacktimer]) + { + player->kartstuff[k_comebacktimer]--; + if (P_IsLocalPlayer(player) && player->kartstuff[k_bumper] <= 0 && player->kartstuff[k_comebacktimer] <= 0) + comebackshowninfo = true; // client has already seen the message + } } - if (player->kartstuff[k_spinout] == 0 && player->kartstuff[k_spinouttimer] == 0 && player->powers[pw_flashing] == K_GetKartFlashing()) + if (player->kartstuff[k_spinouttimer] == 0 && player->powers[pw_flashing] == K_GetKartFlashing(player)) player->powers[pw_flashing]--; - if (player->kartstuff[k_magnettimer]) - player->kartstuff[k_magnettimer]--; + /*if (player->kartstuff[k_thunderanim]) + player->kartstuff[k_thunderanim]--;*/ - if (player->kartstuff[k_mushroomtimer]) - player->kartstuff[k_mushroomtimer]--; + if (player->kartstuff[k_sneakertimer]) + player->kartstuff[k_sneakertimer]--; if (player->kartstuff[k_floorboost]) player->kartstuff[k_floorboost]--; @@ -2346,8 +3155,8 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->kartstuff[k_driftboost]) player->kartstuff[k_driftboost]--; - if (player->kartstuff[k_startimer]) - player->kartstuff[k_startimer]--; + if (player->kartstuff[k_invincibilitytimer]) + player->kartstuff[k_invincibilitytimer]--; if (player->kartstuff[k_growshrinktimer] > 0) player->kartstuff[k_growshrinktimer]--; @@ -2357,42 +3166,43 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->kartstuff[k_growshrinktimer] == 1 || player->kartstuff[k_growshrinktimer] == -1) { + if (player->kartstuff[k_invincibilitytimer] == 0) + player->mo->color = player->skincolor; player->mo->destscale = mapheaderinfo[gamemap-1]->mobj_scale; + if (cv_kartdebugshrink.value && !player->bot) + player->mo->destscale = 6*player->mo->destscale/8; P_RestoreMusic(player); } - if (player->kartstuff[k_bootaketimer] == 0 && player->kartstuff[k_boostolentimer] == 0 - && player->kartstuff[k_goldshroomtimer]) - player->kartstuff[k_goldshroomtimer]--; + if (player->kartstuff[k_stealingtimer] == 0 && player->kartstuff[k_stolentimer] == 0 + && player->kartstuff[k_rocketsneakertimer]) + player->kartstuff[k_rocketsneakertimer]--; - if (player->kartstuff[k_bootimer]) - player->kartstuff[k_bootimer]--; + if (player->kartstuff[k_hyudorotimer]) + player->kartstuff[k_hyudorotimer]--; - if (player->kartstuff[k_bootaketimer]) - player->kartstuff[k_bootaketimer]--; + if (player->kartstuff[k_sadtimer]) + player->kartstuff[k_sadtimer]--; - if (player->kartstuff[k_boostolentimer]) - player->kartstuff[k_boostolentimer]--; + if (player->kartstuff[k_stealingtimer]) + player->kartstuff[k_stealingtimer]--; + + if (player->kartstuff[k_stolentimer]) + player->kartstuff[k_stolentimer]--; if (player->kartstuff[k_squishedtimer]) player->kartstuff[k_squishedtimer]--; - if (player->kartstuff[k_laserwisptimer]) - player->kartstuff[k_laserwisptimer]--; - if (player->kartstuff[k_justbumped]) player->kartstuff[k_justbumped]--; if (player->kartstuff[k_deathsentence]) { if (player->kartstuff[k_deathsentence] == 1) - K_DoBlueShell(player, &players[blueshellplayer]); + K_DoSPB(player, &players[spbplayer]); player->kartstuff[k_deathsentence]--; } - if (player->kartstuff[k_poweritemtimer]) - player->kartstuff[k_poweritemtimer]--; - if (player->kartstuff[k_lapanimation]) player->kartstuff[k_lapanimation]--; @@ -2402,6 +3212,10 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) { if (player->exiting < 6*TICRATE) player->kartstuff[k_cardanimation] += ((164-player->kartstuff[k_cardanimation])/8)+1; + else if (player->exiting == 6*TICRATE) + player->kartstuff[k_cardanimation] = 0; + else if (player->kartstuff[k_cardanimation] < 2*TICRATE) + player->kartstuff[k_cardanimation]++; } else { @@ -2416,6 +3230,11 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->kartstuff[k_cardanimation] < 0) player->kartstuff[k_cardanimation] = 0; } + else if (G_RaceGametype() && player->exiting) + { + if (player->kartstuff[k_cardanimation] < 2*TICRATE) + player->kartstuff[k_cardanimation]++; + } else player->kartstuff[k_cardanimation] = 0; @@ -2425,6 +3244,37 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->kartstuff[k_tauntvoices]) player->kartstuff[k_tauntvoices]--; + if (G_BattleGametype() && player->kartstuff[k_bumper] > 0) + player->kartstuff[k_wanted]++; + + if (P_IsObjectOnGround(player->mo)) + player->kartstuff[k_waterskip] = 0; + + if (player->kartstuff[k_instashield]) + player->kartstuff[k_instashield]--; + + if (player->kartstuff[k_eggmanexplode]) + { + if (player->spectator || (G_BattleGametype() && !player->kartstuff[k_bumper])) + player->kartstuff[k_eggmanexplode] = 0; + else + { + player->kartstuff[k_eggmanexplode]--; + if (player->kartstuff[k_eggmanexplode] <= 0) + { + mobj_t *eggsexplode; + player->powers[pw_flashing] = 0; + eggsexplode = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_BLUEEXPLOSION); + if (player->kartstuff[k_eggmanblame] >= 0 + && player->kartstuff[k_eggmanblame] < MAXPLAYERS + && playeringame[player->kartstuff[k_eggmanblame]] + && !players[player->kartstuff[k_eggmanblame]].spectator + && players[player->kartstuff[k_eggmanblame]].mo) + P_SetTarget(&eggsexplode->target, players[player->kartstuff[k_eggmanblame]].mo); + } + } + } + // ??? /* if (player->kartstuff[k_jmp] > 1 && onground) @@ -2439,56 +3289,55 @@ 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) - && player->kartstuff[k_feather] & 2) - player->kartstuff[k_feather] &= ~2; + if (P_IsObjectOnGround(player->mo) && player->mo->momz <= 0 && player->kartstuff[k_pogospring]) + player->kartstuff[k_pogospring] = 0; if (cmd->buttons & BT_DRIFT) player->kartstuff[k_jmp] = 1; else player->kartstuff[k_jmp] = 0; - // Lakitu Checker - if (player->kartstuff[k_lakitu]) - K_LakituChecker(player); + // Respawn Checker + if (player->kartstuff[k_respawn]) + K_RespawnChecker(player); // Roulette Code - //K_KartItemRouletteByPosition(player, cmd); // Old, position-based - K_KartItemRouletteByDistance(player, cmd); // New, distance-based + K_KartItemRoulette(player, cmd); - // Stopping of the horrible star SFX - if (player->mo->health <= 0 || player->mo->player->kartstuff[k_startimer] <= 0 - || player->mo->player->kartstuff[k_growshrinktimer] > 0) // If you don't have invincibility (or mega is active too) + // Stopping of the horrible invincibility SFX + if (player->mo->health <= 0 || player->mo->player->kartstuff[k_invincibilitytimer] <= 0 + || player->mo->player->kartstuff[k_growshrinktimer] > 0) // If you don't have invincibility (or grow is active too) { - if (S_SoundPlaying(player->mo, sfx_star)) // But the sound is playing - S_StopSoundByID(player->mo, sfx_star); // Stop it + if (S_SoundPlaying(player->mo, sfx_kinvnc)) // But the sound is playing + S_StopSoundByID(player->mo, sfx_kinvnc); // Stop it } - // And the same for the mega mushroom SFX + // And the same for the grow SFX if (!(player->mo->health > 0 && player->mo->player->kartstuff[k_growshrinktimer] > 0)) // If you aren't big { - if (S_SoundPlaying(player->mo, sfx_mega)) // But the sound is playing - S_StopSoundByID(player->mo, sfx_mega); // Stop it + if (S_SoundPlaying(player->mo, sfx_kgrow)) // But the sound is playing + S_StopSoundByID(player->mo, sfx_kgrow); // Stop it } - // AAAAAAND handle the SMK star alarm - if (player->mo->health > 0 && (player->mo->player->kartstuff[k_startimer] > 0 + // AAAAAAND handle the invincibility alarm + if (player->mo->health > 0 && (player->mo->player->kartstuff[k_invincibilitytimer] > 0 || player->mo->player->kartstuff[k_growshrinktimer] > 0)) { - if (leveltime % 13 == 0 && cv_kartstarsfx.value && !P_IsLocalPlayer(player)) + if (leveltime % 13 == 0 && cv_kartinvinsfx.value && !P_IsLocalPlayer(player)) S_StartSound(player->mo, sfx_smkinv); } else if (S_SoundPlaying(player->mo, sfx_smkinv)) S_StopSoundByID(player->mo, sfx_smkinv); // Plays the music after the starting countdown. - if (P_IsLocalPlayer(player) && leveltime == 158) - S_ChangeMusic(mapmusname, mapmusflags, true); + if (P_IsLocalPlayer(player) && leveltime == (starttime + (TICRATE/2))) + S_ChangeMusicInternal(mapmusname, true); } void K_KartPlayerAfterThink(player_t *player) { - if (player->kartstuff[k_startimer]) + if (player->kartstuff[k_invincibilitytimer] + || (player->kartstuff[k_growshrinktimer] != 0 && player->kartstuff[k_growshrinktimer] % 5 == 4)) // 4 instead of 0 because this is afterthink! { player->mo->frame |= FF_FULLBRIGHT; } @@ -2497,6 +3346,9 @@ void K_KartPlayerAfterThink(player_t *player) if (!(player->mo->state->frame & FF_FULLBRIGHT)) player->mo->frame &= ~FF_FULLBRIGHT; } + + // Move held objects (Bananas, Orbinaut, etc) + K_MoveHeldObjects(player); } // Returns false if this player being placed here causes them to collide with any other player @@ -2570,23 +3422,24 @@ INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue) turnvalue = FixedMul(turnvalue, adjustangle); // Weight has a small effect on turning - if (player->kartstuff[k_startimer] || player->kartstuff[k_mushroomtimer] || player->kartstuff[k_growshrinktimer] > 0) + if (player->kartstuff[k_invincibilitytimer] || player->kartstuff[k_sneakertimer] || player->kartstuff[k_growshrinktimer] > 0) turnvalue = FixedMul(turnvalue, FixedDiv(5*FRACUNIT, 4*FRACUNIT)); return turnvalue; } +fixed_t K_GetKartDriftSparkValue(player_t *player) +{ + UINT8 kartspeed = (G_BattleGametype() && player->kartstuff[k_bumper] <= 0) + ? 1 + : player->kartspeed; + return (26*4 + kartspeed*2 + (9 - player->kartweight))*8; +} + static void K_KartDrift(player_t *player, boolean onground) { - UINT8 kartspeed = player->kartspeed; - fixed_t dsone, dstwo; - - if (G_BattleGametype() && player->kartstuff[k_balloon] <= 0) - kartspeed = 1; - - // IF YOU CHANGE THESE: MAKE SURE YOU UPDATE THE SAME VALUES IN p_mobjc, "case MT_DRIFT:" - dsone = (26*4 + kartspeed*2 + (9 - player->kartweight))*8; - dstwo = dsone*2; + fixed_t dsone = K_GetKartDriftSparkValue(player); + fixed_t dstwo = dsone*2; // Drifting is actually straffing + automatic turning. // Holding the Jump button will enable drifting. @@ -2605,7 +3458,7 @@ static void K_KartDrift(player_t *player, boolean onground) && onground) { player->kartstuff[k_driftboost] = 20; - S_StartSound(player->mo, sfx_mush); + S_StartSound(player->mo, sfx_s23c); player->kartstuff[k_driftcharge] = 0; } else if ((player->kartstuff[k_drift] != -5 && player->kartstuff[k_drift] != 5) @@ -2614,7 +3467,7 @@ static void K_KartDrift(player_t *player, boolean onground) && onground) { player->kartstuff[k_driftboost] = 50; - S_StartSound(player->mo, sfx_mush); + S_StartSound(player->mo, sfx_s23c); player->kartstuff[k_driftcharge] = 0; } @@ -2653,8 +3506,7 @@ static void K_KartDrift(player_t *player, boolean onground) } // 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) + if (player->kartstuff[k_spinouttimer] == 0 && player->kartstuff[k_jmp] == 1 && onground && player->kartstuff[k_drift] != 0) { fixed_t driftadditive = 24; @@ -2665,9 +3517,9 @@ static void K_KartDrift(player_t *player, boolean onground) player->kartstuff[k_drift] = 5; if (player->cmd.driftturn > 0) // Inward - driftadditive += (player->cmd.driftturn/800)/8; + driftadditive += abs(player->cmd.driftturn)/100; if (player->cmd.driftturn < 0) // Outward - driftadditive -= (player->cmd.driftturn/800)/8; + driftadditive -= abs(player->cmd.driftturn)/75; } else if (player->kartstuff[k_drift] <= -1) // Drifting to the right { @@ -2676,9 +3528,9 @@ static void K_KartDrift(player_t *player, boolean onground) player->kartstuff[k_drift] = -5; if (player->cmd.driftturn < 0) // Inward - driftadditive += (player->cmd.driftturn/800)/4; + driftadditive += abs(player->cmd.driftturn)/100; if (player->cmd.driftturn > 0) // Outward - driftadditive -= (player->cmd.driftturn/800)/4; + driftadditive -= abs(player->cmd.driftturn)/75; } // This spawns the drift sparks @@ -2795,104 +3647,63 @@ static void K_KartUpdatePosition(player_t *player) } else if (G_BattleGametype()) { - if (player->exiting) - return; - if (players[i].kartstuff[k_balloon] == player->kartstuff[k_balloon] && players[i].score > player->score) - position++; - else if (players[i].kartstuff[k_balloon] > player->kartstuff[k_balloon]) - position++; + if (player->exiting) // End of match standings + { + if (players[i].marescore > player->marescore) // Only score matters + position++; + } + else + { + if (players[i].kartstuff[k_bumper] == player->kartstuff[k_bumper] && players[i].marescore > player->marescore) + position++; + else if (players[i].kartstuff[k_bumper] > player->kartstuff[k_bumper]) + position++; + } } } - if (leveltime < 4*TICRATE || oldposition == 0) + if (leveltime < starttime || oldposition == 0) oldposition = position; if (oldposition != position) // Changed places? - player->kartstuff[k_positiondelay] = 10; // and set up the timer. + player->kartstuff[k_positiondelay] = 10; // Position number growth player->kartstuff[k_position] = position; } -// -// K_CheckForHoldItem -// -static boolean K_CheckForHoldItem(player_t *player) -{ - if ( player->kartstuff[k_greenshell] == 1 - || player->kartstuff[k_redshell] == 1 - || player->kartstuff[k_banana] == 1 - || player->kartstuff[k_fakeitem] == 1 - || player->kartstuff[k_bobomb] == 1 - || player->kartstuff[k_triplegreenshell] & 1 - || player->kartstuff[k_triplegreenshell] & 2 - || player->kartstuff[k_triplegreenshell] & 4 - || player->kartstuff[k_tripleredshell] & 1 - || player->kartstuff[k_tripleredshell] & 2 - || player->kartstuff[k_tripleredshell] & 4 - || player->kartstuff[k_triplebanana] & 1 - || player->kartstuff[k_triplebanana] & 2 - || player->kartstuff[k_triplebanana] & 4 - ) return true; - return false; -} + // // K_StripItems // -static void K_StripItems(player_t *player) +void K_StripItems(player_t *player) { - if ( player->kartstuff[k_kitchensink] - || player->kartstuff[k_feather] & 1 - || player->kartstuff[k_lightning] - || player->kartstuff[k_tripleredshell] - || player->kartstuff[k_fireflower] - || player->kartstuff[k_blueshell] - || player->kartstuff[k_bobomb] - || player->kartstuff[k_triplegreenshell] - || player->kartstuff[k_redshell] - || player->kartstuff[k_greenshell] - || player->kartstuff[k_banana] - || player->kartstuff[k_fakeitem] & 2 - || player->kartstuff[k_triplebanana] - || player->kartstuff[k_star] - || player->kartstuff[k_goldshroom] - || player->kartstuff[k_megashroom] - || player->kartstuff[k_mushroom] - || player->kartstuff[k_boo] - || player->kartstuff[k_magnet] - || player->kartstuff[k_bootimer] - || player->kartstuff[k_bootaketimer] - || player->kartstuff[k_boostolentimer] - || player->kartstuff[k_goldshroomtimer] - || player->kartstuff[k_growshrinktimer] - || player->kartstuff[k_itemroulette] - ) player->kartstuff[k_itemclose] = 10; - player->kartstuff[k_kitchensink] = 0; - player->kartstuff[k_feather] = 0; - player->kartstuff[k_lightning] = 0; - player->kartstuff[k_tripleredshell] = 0; - player->kartstuff[k_fireflower] = 0; - player->kartstuff[k_blueshell] = 0; - player->kartstuff[k_bobomb] = 0; - player->kartstuff[k_triplegreenshell] = 0; - player->kartstuff[k_redshell] = 0; - player->kartstuff[k_greenshell] = 0; - player->kartstuff[k_banana] = 0; - player->kartstuff[k_fakeitem] = 0; - player->kartstuff[k_triplebanana] = 0; - player->kartstuff[k_star] = 0; - player->kartstuff[k_goldshroom] = 0; - player->kartstuff[k_megashroom] = 0; - player->kartstuff[k_mushroom] = 0; - player->kartstuff[k_boo] = 0; - player->kartstuff[k_magnet] = 0; + player->kartstuff[k_itemtype] = 0; + player->kartstuff[k_itemamount] = 0; + player->kartstuff[k_itemheld] = 0; + player->kartstuff[k_itemroulette] = 0; - player->kartstuff[k_bootimer] = 0; - player->kartstuff[k_bootaketimer] = 0; - player->kartstuff[k_boostolentimer] = 0; - player->kartstuff[k_goldshroomtimer] = 0; + player->kartstuff[k_roulettetype] = 0; + + player->kartstuff[k_rocketsneakertimer] = 0; + player->kartstuff[k_invincibilitytimer] = 0; player->kartstuff[k_growshrinktimer] = 0; - player->kartstuff[k_magnettimer] = 0; - player->kartstuff[k_startimer] = 0; + + player->kartstuff[k_eggmanheld] = 0; + player->kartstuff[k_eggmanexplode] = 0; + player->kartstuff[k_eggmanblame] = 0; + + player->kartstuff[k_hyudorotimer] = 0; + player->kartstuff[k_stealingtimer] = 0; + player->kartstuff[k_stolentimer] = 0; + + player->kartstuff[k_curshield] = 0; + //player->kartstuff[k_thunderanim] = 0; + player->kartstuff[k_bananadrag] = 0; + + player->kartstuff[k_sadtimer] = 0; + + K_CleanHnextList(player->mo); } + // // K_MoveKartPlayer // @@ -2900,15 +3711,18 @@ void K_MoveKartPlayer(player_t *player, boolean onground) { ticcmd_t *cmd = &player->cmd; boolean ATTACK_IS_DOWN = ((cmd->buttons & BT_ATTACK) && !(player->pflags & PF_ATTACKDOWN)); - boolean HOLDING_ITEM = K_CheckForHoldItem(player); - boolean NO_BOO = (player->kartstuff[k_boostolentimer] == 0 && player->kartstuff[k_bootaketimer] == 0); + boolean HOLDING_ITEM = (player->kartstuff[k_itemheld] || player->kartstuff[k_eggmanheld]); + boolean NO_HYUDORO = (player->kartstuff[k_stolentimer] == 0 && player->kartstuff[k_stealingtimer] == 0); K_KartUpdatePosition(player); if (!player->exiting) { - if (player->kartstuff[k_oldposition] <= player->kartstuff[k_position]) // But first, if you lost a place, + if (player->kartstuff[k_oldposition] < player->kartstuff[k_position]) // But first, if you lost a place, + { player->kartstuff[k_oldposition] = player->kartstuff[k_position]; // then the other player taunts. + K_RegularVoiceTimers(player); // and you can't for a bit + } else if (player->kartstuff[k_oldposition] > player->kartstuff[k_position]) // Otherwise, { K_PlayOvertakeSound(player->mo); // Say "YOU'RE TOO SLOW!" @@ -2919,504 +3733,407 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if (player->kartstuff[k_positiondelay]) player->kartstuff[k_positiondelay]--; - // Race Spectator - if (netgame && player->jointime < 1 - && G_RaceGametype() && countdown) - { - player->spectator = true; - player->powers[pw_nocontrol] = 5; - } - if ((player->pflags & PF_ATTACKDOWN) && !(cmd->buttons & BT_ATTACK)) player->pflags &= ~PF_ATTACKDOWN; else if (cmd->buttons & BT_ATTACK) player->pflags |= PF_ATTACKDOWN; - if (player && player->mo && player->mo->health > 0 && !player->spectator && !player->exiting && player->kartstuff[k_spinouttimer] == 0) + if (player && player->mo && player->mo->health > 0 && !player->spectator && !(player->exiting || mapreset) && player->kartstuff[k_spinouttimer] == 0) { + // First, the really specific, finicky items that function without the item being directly in your item slot. + // Karma item dropping + if (ATTACK_IS_DOWN && player->kartstuff[k_comebackmode] && !player->kartstuff[k_comebacktimer]) + { + mobj_t *newitem; -// Magnet -// Boo -// Mushroom -// Triple Mushroom -// Mega Mushroom -// Gold Mushroom -// Star -// Triple Banana -// Fake Item -// Banana -// Green Shell -// Red Shell -// Triple Green Shell -// Bob-omb -// Blue Shell -// Fire Flower -// Triple Red Shell -// Lightning -// Feather + player->kartstuff[k_comebackmode] = 0; + player->kartstuff[k_comebacktimer] = comebacktime; + S_StartSound(player->mo, sfx_s254); - // GoldenMushroom power - if (ATTACK_IS_DOWN && !HOLDING_ITEM && onground && player->kartstuff[k_goldshroom] == 1 - && player->kartstuff[k_goldshroomtimer] == 0 && NO_BOO) - { - K_DoMushroom(player, true); - player->kartstuff[k_goldshroomtimer] = itemtime; - player->kartstuff[k_goldshroom] = 0; + newitem = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_RANDOMITEM); + newitem->flags2 = (player->mo->flags2 & MF2_OBJECTFLIP); + newitem->fuse = 15*TICRATE; // selected randomly. + newitem->threshold = 69; // selected "randomly". } - // GoldenMushroom power - else if (ATTACK_IS_DOWN && player->kartstuff[k_goldshroomtimer] > 1 && onground && NO_BOO) + // Eggman Monitor exploding + else if (player->kartstuff[k_eggmanexplode]) { - K_DoMushroom(player, true); - player->kartstuff[k_goldshroomtimer] -= 5; - if (player->kartstuff[k_goldshroomtimer] < 1) - player->kartstuff[k_goldshroomtimer] = 1; + if (ATTACK_IS_DOWN && player->kartstuff[k_eggmanexplode] <= 3*TICRATE && player->kartstuff[k_eggmanexplode] > 1) + player->kartstuff[k_eggmanexplode] = 1; } - // TripleMushroom power - else if (ATTACK_IS_DOWN && !HOLDING_ITEM && player->kartstuff[k_mushroom] == 4 && onground && NO_BOO) - { - K_DoMushroom(player, true); - player->kartstuff[k_mushroom] = 2; - } - // DoubleMushroom power - else if (ATTACK_IS_DOWN && !HOLDING_ITEM && player->kartstuff[k_mushroom] == 2 && onground && NO_BOO) - { - K_DoMushroom(player, true); - player->kartstuff[k_mushroom] = 1; - } - // Mushroom power - else if (ATTACK_IS_DOWN && !HOLDING_ITEM && player->kartstuff[k_mushroom] == 1 && onground && NO_BOO) - { - K_DoMushroom(player, true); - player->kartstuff[k_mushroom] = 0; - } - // Star power - else if (ATTACK_IS_DOWN && !HOLDING_ITEM && player->kartstuff[k_star] == 1 && NO_BOO) - { - if (P_IsLocalPlayer(player) && !player->exiting) - S_ChangeMusicInternal("minvnc", true); - if (!cv_kartstarsfx.value && !P_IsLocalPlayer(player)) - S_StartSound(player->mo, sfx_star); - player->kartstuff[k_startimer] = itemtime; // Activate it - K_PlayTauntSound(player->mo); - player->kartstuff[k_star] = 0; - if (G_BattleGametype()) - player->kartstuff[k_poweritemtimer] = 10*TICRATE; - player->kartstuff[k_itemclose] = 10; - player->pflags |= PF_ATTACKDOWN; - } - // Green Shell - else if (ATTACK_IS_DOWN && !HOLDING_ITEM && player->kartstuff[k_greenshell] & 2 && NO_BOO) - { - angle_t newangle; - fixed_t newx; - fixed_t newy; - mobj_t *mo; - player->kartstuff[k_greenshell] &= ~2; - player->kartstuff[k_greenshell] |= 1; - player->pflags |= PF_ATTACKDOWN; - newangle = player->mo->angle; - newx = player->mo->x + P_ReturnThrustX(player->mo, newangle + ANGLE_180, 64*FRACUNIT); - newy = player->mo->y + P_ReturnThrustY(player->mo, newangle + ANGLE_180, 64*FRACUNIT); - mo = P_SpawnMobj(newx, newy, player->mo->z, MT_GREENSHIELD); - mo->threshold = 10; - if (mo) - P_SetTarget(&mo->target, player->mo); - player->kartstuff[k_itemclose] = 10; - } - else if (!(cmd->buttons & BT_ATTACK) && player->kartstuff[k_greenshell] & 1) - { - player->kartstuff[k_greenshell] &= ~1; - - K_ThrowKartItem(player, true, MT_GREENITEM, 1, false); - K_PlayTauntSound(player->mo); - - } - else if (ATTACK_IS_DOWN && !HOLDING_ITEM && player->kartstuff[k_fireflower] && NO_BOO) - { - player->kartstuff[k_fireflower] = 0; - - K_ThrowKartItem(player, true, MT_FIREBALL, 1, false); - S_StartSound(player->mo, sfx_mario7); - K_PlayTauntSound(player->mo); - - player->kartstuff[k_itemclose] = 10; - } - // Triple Green Shell - else if (ATTACK_IS_DOWN && !HOLDING_ITEM && player->kartstuff[k_triplegreenshell] & 8 && NO_BOO) - { - angle_t newangle; - fixed_t newx; - fixed_t newy; - mobj_t *mo, *mo2, *mo3; - player->kartstuff[k_triplegreenshell] &= ~8; - player->kartstuff[k_triplegreenshell] |= 7; - player->pflags |= PF_ATTACKDOWN; - newangle = player->mo->angle; - K_PlayTauntSound(player->mo); - newx = player->mo->x + P_ReturnThrustX(player->mo, newangle + ANGLE_180, 64*FRACUNIT); - newy = player->mo->y + P_ReturnThrustY(player->mo, newangle + ANGLE_180, 64*FRACUNIT); - mo = P_SpawnMobj(newx, newy, player->mo->z, MT_TRIPLEGREENSHIELD1); - mo->threshold = 10; - P_SetTarget(&mo->target, player->mo); - mo->angle = 0; - mo2 = P_SpawnMobj(newx, newy, player->mo->z, MT_TRIPLEGREENSHIELD2); - mo2->threshold = 10; - P_SetTarget(&mo2->target, player->mo); - mo2->angle = ANGLE_120; - mo3 = P_SpawnMobj(newx, newy, player->mo->z, MT_TRIPLEGREENSHIELD3); - mo3->threshold = 10; - P_SetTarget(&mo3->target, player->mo); - mo3->angle = ANGLE_240; - player->kartstuff[k_itemclose] = 10; - } - else if (ATTACK_IS_DOWN && (player->kartstuff[k_triplegreenshell] & 1 || player->kartstuff[k_triplegreenshell] & 2 || player->kartstuff[k_triplegreenshell] & 4)) - { - K_ThrowKartItem(player, true, MT_GREENITEM, 1, false); - K_PlayTauntSound(player->mo); - player->pflags |= PF_ATTACKDOWN; - - if (player->kartstuff[k_triplegreenshell] & 4) - player->kartstuff[k_triplegreenshell] &= ~4; - else if (player->kartstuff[k_triplegreenshell] & 2) - player->kartstuff[k_triplegreenshell] &= ~2; - else if (player->kartstuff[k_triplegreenshell] & 1) - player->kartstuff[k_triplegreenshell] &= ~1; - - } - // Red Shell - else if (ATTACK_IS_DOWN && !HOLDING_ITEM && player->kartstuff[k_redshell] & 2 && NO_BOO) - { - angle_t newangle; - fixed_t newx; - fixed_t newy; - mobj_t *mo; - player->kartstuff[k_redshell] &= ~2; - player->kartstuff[k_redshell] |= 1; - player->pflags |= PF_ATTACKDOWN; - newangle = player->mo->angle; - newx = player->mo->x + P_ReturnThrustX(player->mo, newangle + ANGLE_180, 64*FRACUNIT); - newy = player->mo->y + P_ReturnThrustY(player->mo, newangle + ANGLE_180, 64*FRACUNIT); - mo = P_SpawnMobj(newx, newy, player->mo->z, MT_REDSHIELD); - mo->threshold = 10; - if (mo) - P_SetTarget(&mo->target, player->mo); - player->kartstuff[k_itemclose] = 10; - } - else if (!(cmd->buttons & BT_ATTACK) && player->kartstuff[k_redshell] & 1 && (player->kartstuff[k_throwdir] == 1 || player->kartstuff[k_throwdir] == 0)) - { - player->kartstuff[k_redshell] &= ~1; - - K_ThrowKartItem(player, true, MT_REDITEM, 1, false); - K_PlayTauntSound(player->mo); - } - // Red Shell Dud - else if (!(cmd->buttons & BT_ATTACK) && player->kartstuff[k_redshell] & 1 && player->kartstuff[k_throwdir] == -1) - { - player->kartstuff[k_redshell] &= ~1; - - K_ThrowKartItem(player, true, MT_REDITEMDUD, -1, false); - K_PlayTauntSound(player->mo); - } - // Triple Red Shell - else if (ATTACK_IS_DOWN && !HOLDING_ITEM && player->kartstuff[k_tripleredshell] & 8 && NO_BOO) - { - angle_t newangle; - fixed_t newx; - fixed_t newy; - mobj_t *mo, *mo2, *mo3; - player->kartstuff[k_tripleredshell] &= ~8; - player->kartstuff[k_tripleredshell] |= 7; - player->pflags |= PF_ATTACKDOWN; - newangle = player->mo->angle; - K_PlayTauntSound(player->mo); - newx = player->mo->x + P_ReturnThrustX(player->mo, newangle + ANGLE_180, 64*FRACUNIT); - newy = player->mo->y + P_ReturnThrustY(player->mo, newangle + ANGLE_180, 64*FRACUNIT); - mo = P_SpawnMobj(newx, newy, player->mo->z, MT_TRIPLEREDSHIELD1); - mo->threshold = 10; - P_SetTarget(&mo->target, player->mo); - mo->angle = 0; - mo2 = P_SpawnMobj(newx, newy, player->mo->z, MT_TRIPLEREDSHIELD2); - mo2->threshold = 10; - P_SetTarget(&mo2->target, player->mo); - mo2->angle = ANGLE_120; - mo3 = P_SpawnMobj(newx, newy, player->mo->z, MT_TRIPLEREDSHIELD3); - mo3->threshold = 10; - P_SetTarget(&mo3->target, player->mo); - mo3->angle = ANGLE_240; - player->kartstuff[k_itemclose] = 10; - } - else if (ATTACK_IS_DOWN && (player->kartstuff[k_tripleredshell] & 1 || player->kartstuff[k_tripleredshell] & 2 || player->kartstuff[k_tripleredshell] & 4) - && (player->kartstuff[k_throwdir] == 1 || player->kartstuff[k_throwdir] == 0)) - { - K_ThrowKartItem(player, true, MT_REDITEM, 1, false); - K_PlayTauntSound(player->mo); - player->pflags |= PF_ATTACKDOWN; - if (player->kartstuff[k_tripleredshell] & 4) - player->kartstuff[k_tripleredshell] &= ~4; - else if (player->kartstuff[k_tripleredshell] & 2) - player->kartstuff[k_tripleredshell] &= ~2; - else if (player->kartstuff[k_tripleredshell] & 1) - player->kartstuff[k_tripleredshell] &= ~1; - } - else if (ATTACK_IS_DOWN && (player->kartstuff[k_tripleredshell] & 1 || player->kartstuff[k_tripleredshell] & 2 || player->kartstuff[k_tripleredshell] & 4) - && player->kartstuff[k_throwdir] == -1) - { - K_ThrowKartItem(player, true, MT_REDITEMDUD, -1, false); - K_PlayTauntSound(player->mo); - player->pflags |= PF_ATTACKDOWN; - if (player->kartstuff[k_tripleredshell] & 4) - player->kartstuff[k_tripleredshell] &= ~4; - else if (player->kartstuff[k_tripleredshell] & 2) - player->kartstuff[k_tripleredshell] &= ~2; - else if (player->kartstuff[k_tripleredshell] & 1) - player->kartstuff[k_tripleredshell] &= ~1; - } - // Banana Peel - else if (ATTACK_IS_DOWN && !HOLDING_ITEM && player->kartstuff[k_banana] & 2 && NO_BOO) - { - angle_t newangle; - fixed_t newx; - fixed_t newy; - mobj_t *mo; - player->kartstuff[k_banana] &= ~2; - player->kartstuff[k_banana] |= 1; - player->pflags |= PF_ATTACKDOWN; - newangle = player->mo->angle; - newx = player->mo->x + P_ReturnThrustX(player->mo, newangle + ANGLE_180, 64*FRACUNIT); - newy = player->mo->y + P_ReturnThrustY(player->mo, newangle + ANGLE_180, 64*FRACUNIT); - mo = P_SpawnMobj(newx, newy, player->mo->z, MT_BANANASHIELD); - mo->threshold = 10; - if (mo) - P_SetTarget(&mo->target, player->mo); - player->kartstuff[k_itemclose] = 10; - } - else if (!(cmd->buttons & BT_ATTACK) && player->kartstuff[k_banana] & 1) - { - K_ThrowKartItem(player, false, MT_BANANAITEM, -1, false); - K_PlayTauntSound(player->mo); - player->kartstuff[k_banana] &= ~1; - } - // Triple Banana Peel - else if (ATTACK_IS_DOWN && !HOLDING_ITEM && player->kartstuff[k_triplebanana] & 8 && NO_BOO) - { - angle_t newangle; - fixed_t newx; - fixed_t newy; - mobj_t *mo, *mo2, *mo3; - K_PlayTauntSound(player->mo); - player->kartstuff[k_triplebanana] &= ~8; - player->kartstuff[k_triplebanana] |= 7; - player->pflags |= PF_ATTACKDOWN; - newangle = player->mo->angle; - newx = player->mo->x + P_ReturnThrustX(player->mo, newangle + ANGLE_180, 64*FRACUNIT); - newy = player->mo->y + P_ReturnThrustY(player->mo, newangle + ANGLE_180, 64*FRACUNIT); - mo = P_SpawnMobj(newx, newy, player->mo->z, MT_TRIPLEBANANASHIELD1); - mo->threshold = 10; - if (mo) { - P_SetTarget(&mo->target, player->mo); - mo->angle = 0; } - mo2 = P_SpawnMobj(newx, newy, player->mo->z, MT_TRIPLEBANANASHIELD2); - mo2->threshold = 10; - if (mo2) { - P_SetTarget(&mo2->target, player->mo); - mo2->angle = ANGLE_135; } - mo3 = P_SpawnMobj(newx, newy, player->mo->z, MT_TRIPLEBANANASHIELD3); - mo3->threshold = 10; - if (mo3) { - P_SetTarget(&mo3->target, player->mo); - mo3->angle = ANGLE_225; } - player->kartstuff[k_itemclose] = 10; - } - else if (ATTACK_IS_DOWN && (player->kartstuff[k_triplebanana] & 1 || player->kartstuff[k_triplebanana] & 2 || player->kartstuff[k_triplebanana] & 4)) - { - K_ThrowKartItem(player, false, MT_BANANAITEM, -1,false ); - K_PlayTauntSound(player->mo); - player->pflags |= PF_ATTACKDOWN; - if (player->kartstuff[k_triplebanana] & 4) - player->kartstuff[k_triplebanana] &= ~4; - else if (player->kartstuff[k_triplebanana] & 2) - player->kartstuff[k_triplebanana] &= ~2; - else if (player->kartstuff[k_triplebanana] & 1) - player->kartstuff[k_triplebanana] &= ~1; - } - // Fake Itembox - else if (ATTACK_IS_DOWN && !HOLDING_ITEM && player->kartstuff[k_fakeitem] & 2 && NO_BOO) - { - angle_t newangle; - fixed_t newx; - fixed_t newy; - mobj_t *mo; - player->kartstuff[k_fakeitem] &= ~2; - player->kartstuff[k_fakeitem] |= 1; - player->pflags |= PF_ATTACKDOWN; - newangle = player->mo->angle; - newx = player->mo->x + P_ReturnThrustX(player->mo, newangle + ANGLE_180, 64*FRACUNIT); - newy = player->mo->y + P_ReturnThrustY(player->mo, newangle + ANGLE_180, 64*FRACUNIT); - mo = P_SpawnMobj(newx, newy, player->mo->z, MT_FAKESHIELD); - mo->scale = FRACUNIT/2; - mo->threshold = 10; - if (mo) - P_SetTarget(&mo->target, player->mo); - player->kartstuff[k_itemclose] = 10; - } - else if (!(cmd->buttons & BT_ATTACK) && player->kartstuff[k_fakeitem] & 1) + // Eggman Monitor throwing + else if (ATTACK_IS_DOWN && player->kartstuff[k_eggmanheld]) { K_ThrowKartItem(player, false, MT_FAKEITEM, -1, false); K_PlayTauntSound(player->mo); - player->kartstuff[k_fakeitem] &= ~1; + player->kartstuff[k_eggmanheld] = 0; + K_CleanHnextList(player->mo); } - // Bomb - else if (ATTACK_IS_DOWN && !HOLDING_ITEM && player->kartstuff[k_bobomb] & 2 && NO_BOO) + // Rocket Sneaker + else if (ATTACK_IS_DOWN && !HOLDING_ITEM && onground && NO_HYUDORO + && player->kartstuff[k_rocketsneakertimer] > 1) { - angle_t newangle; - fixed_t newx; - fixed_t newy; - mobj_t *mo; - player->kartstuff[k_bobomb] &= ~2; - player->kartstuff[k_bobomb] |= 1; - player->pflags |= PF_ATTACKDOWN; - newangle = player->mo->angle; - newx = player->mo->x + P_ReturnThrustX(player->mo, newangle + ANGLE_180, 64*FRACUNIT); - newy = player->mo->y + P_ReturnThrustY(player->mo, newangle + ANGLE_180, 64*FRACUNIT); - mo = P_SpawnMobj(newx, newy, player->mo->z, MT_BOMBSHIELD); - mo->threshold = 10; - if (mo) - P_SetTarget(&mo->target, player->mo); - player->kartstuff[k_itemclose] = 10; + K_DoSneaker(player, true); + player->kartstuff[k_rocketsneakertimer] -= 5; + if (player->kartstuff[k_rocketsneakertimer] < 1) + player->kartstuff[k_rocketsneakertimer] = 1; } - if (!(cmd->buttons & BT_ATTACK) && player->kartstuff[k_bobomb] & 1) + else if (player->kartstuff[k_itemamount] <= 0) { - K_ThrowKartItem(player, false, MT_BOMBITEM, 1, true); - K_PlayTauntSound(player->mo); - player->kartstuff[k_bobomb] &= ~1; + player->kartstuff[k_itemamount] = player->kartstuff[k_itemheld] = 0; } - // Thunder - else if (ATTACK_IS_DOWN && !HOLDING_ITEM && player->kartstuff[k_lightning] == 1 && NO_BOO) + else { - K_DoLightning(player); - player->kartstuff[k_lightning] = 0; - player->kartstuff[k_itemclose] = 10; - } - // Blue Shell - else if (ATTACK_IS_DOWN && !HOLDING_ITEM && player->kartstuff[k_blueshell] == 1 && NO_BOO) - { - UINT8 i; - UINT8 bestrank = 0; - fixed_t dist = 0; - - //K_DoLightning(player, true); - - for (i = 0; i < MAXPLAYERS; i++) + switch (player->kartstuff[k_itemtype]) { - fixed_t thisdist; - if (!playeringame[i] || players[i].spectator) - continue; - if (&players[i] == player) - continue; - if (!players[i].mo) - continue; - if (players[i].exiting) - continue; - thisdist = R_PointToDist2(player->mo->x, player->mo->y, players[i].mo->x, players[i].mo->y); - if (bestrank == 0 || players[i].kartstuff[k_position] < bestrank) - { - bestrank = players[i].kartstuff[k_position]; - dist = thisdist; - } + case KITEM_SNEAKER: + if (ATTACK_IS_DOWN && !HOLDING_ITEM && onground && NO_HYUDORO) + { + K_DoSneaker(player, true); + player->kartstuff[k_itemamount]--; + } + break; + case KITEM_ROCKETSNEAKER: + if (ATTACK_IS_DOWN && !HOLDING_ITEM && onground && NO_HYUDORO + && player->kartstuff[k_rocketsneakertimer] == 0) + { + K_DoSneaker(player, true); + player->kartstuff[k_rocketsneakertimer] = itemtime; + player->kartstuff[k_itemamount]--; + } + break; + case KITEM_INVINCIBILITY: + if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) // Doesn't hold your item slot hostage normally, so you're free to waste it if you have multiple + { + if (!player->kartstuff[k_invincibilitytimer]) + { + mobj_t *overlay = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_INVULNFLASH); + P_SetTarget(&overlay->target, player->mo); + overlay->destscale = player->mo->scale; + P_SetScale(overlay, player->mo->scale); + } + player->kartstuff[k_invincibilitytimer] = itemtime+(2*TICRATE); // 10 seconds + P_RestoreMusic(player); + if (!cv_kartinvinsfx.value && !P_IsLocalPlayer(player)) + S_StartSound(player->mo, sfx_kinvnc); + K_PlayTauntSound(player->mo); + player->kartstuff[k_itemamount]--; + } + break; + case KITEM_BANANA: + if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) + { + INT32 moloop; + mobj_t *mo; + mobj_t *prev = player->mo; + + //K_PlayTauntSound(player->mo); + player->kartstuff[k_itemheld] = 1; + S_StartSound(player->mo, sfx_s254); + + for (moloop = 0; moloop < player->kartstuff[k_itemamount]; moloop++) + { + mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_BANANA_SHIELD); + if (!mo) + { + player->kartstuff[k_itemamount] = moloop; + break; + } + mo->flags |= MF_NOCLIPTHING; + mo->threshold = 10; + mo->movecount = player->kartstuff[k_itemamount]; + mo->movedir = moloop+1; + P_SetTarget(&mo->target, player->mo); + P_SetTarget(&mo->hprev, prev); + P_SetTarget(&prev->hnext, mo); + prev = mo; + } + } + else if (ATTACK_IS_DOWN && player->kartstuff[k_itemheld]) // Banana x3 thrown + { + K_ThrowKartItem(player, false, MT_BANANA, -1, false); + K_PlayTauntSound(player->mo); + player->kartstuff[k_itemamount]--; + K_UpdateHnextList(player); + } + break; + case KITEM_EGGMAN: + if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) + { + mobj_t *mo; + player->kartstuff[k_itemamount]--; + player->kartstuff[k_eggmanheld] = 1; + S_StartSound(player->mo, sfx_s254); + mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_FAKESHIELD); + if (mo) + { + mo->flags |= MF_NOCLIPTHING; + mo->threshold = 10; + mo->movecount = 1; + mo->movedir = 1; + P_SetTarget(&mo->target, player->mo); + P_SetTarget(&player->mo->hnext, mo); + } + } + break; + case KITEM_ORBINAUT: + if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) + { + angle_t newangle; + fixed_t newx; + fixed_t newy; + INT32 moloop; + mobj_t *mo = NULL; + mobj_t *prev = player->mo; + + //K_PlayTauntSound(player->mo); + player->kartstuff[k_itemheld] = 1; + S_StartSound(player->mo, sfx_s3k3a); + + for (moloop = 0; moloop < player->kartstuff[k_itemamount]; moloop++) + { + newangle = FixedAngle(((360/player->kartstuff[k_itemamount])*moloop)*FRACUNIT) + ANGLE_90; + newx = player->mo->x + P_ReturnThrustX(player->mo, newangle, 64*FRACUNIT); + newy = player->mo->y + P_ReturnThrustY(player->mo, newangle, 64*FRACUNIT); + mo = P_SpawnMobj(newx, newy, player->mo->z, MT_ORBINAUT_SHIELD); + if (!mo) + { + player->kartstuff[k_itemamount] = moloop; + break; + } + mo->flags |= MF_NOCLIPTHING; + mo->angle = newangle; + mo->threshold = 10; + mo->movecount = player->kartstuff[k_itemamount]; + mo->movedir = mo->lastlook = moloop+1; + mo->color = player->skincolor; + P_SetTarget(&mo->target, player->mo); + P_SetTarget(&mo->hprev, prev); + P_SetTarget(&prev->hnext, mo); + prev = mo; + } + } + else if (ATTACK_IS_DOWN && player->kartstuff[k_itemheld]) // Orbinaut x3 thrown + { + K_ThrowKartItem(player, true, MT_ORBINAUT, 1, false); + K_PlayTauntSound(player->mo); + player->kartstuff[k_itemamount]--; + K_UpdateHnextList(player); + } + break; + case KITEM_JAWZ: + if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) + { + angle_t newangle; + fixed_t newx; + fixed_t newy; + INT32 moloop; + mobj_t *mo = NULL; + mobj_t *prev = player->mo; + + //K_PlayTauntSound(player->mo); + player->kartstuff[k_itemheld] = 1; + S_StartSound(player->mo, sfx_s3k3a); + + for (moloop = 0; moloop < player->kartstuff[k_itemamount]; moloop++) + { + newangle = FixedAngle(((360/player->kartstuff[k_itemamount])*moloop)*FRACUNIT) + ANGLE_90; + newx = player->mo->x + P_ReturnThrustX(player->mo, newangle, 64*FRACUNIT); + newy = player->mo->y + P_ReturnThrustY(player->mo, newangle, 64*FRACUNIT); + mo = P_SpawnMobj(newx, newy, player->mo->z, MT_JAWZ_SHIELD); + if (!mo) + { + player->kartstuff[k_itemamount] = moloop; + break; + } + mo->flags |= MF_NOCLIPTHING; + mo->angle = newangle; + mo->threshold = 10; + mo->movecount = player->kartstuff[k_itemamount]; + mo->movedir = mo->lastlook = moloop+1; + P_SetTarget(&mo->target, player->mo); + P_SetTarget(&mo->hprev, prev); + P_SetTarget(&prev->hnext, mo); + prev = mo; + } + } + else if (ATTACK_IS_DOWN && HOLDING_ITEM && player->kartstuff[k_itemheld]) // Jawz thrown + { + if (player->kartstuff[k_throwdir] == 1 || player->kartstuff[k_throwdir] == 0) + K_ThrowKartItem(player, true, MT_JAWZ, 1, false); + else if (player->kartstuff[k_throwdir] == -1) // Throwing backward gives you a dud that doesn't home in + K_ThrowKartItem(player, true, MT_JAWZ_DUD, -1, false); + K_PlayTauntSound(player->mo); + player->kartstuff[k_itemamount]--; + K_UpdateHnextList(player); + } + break; + case KITEM_MINE: + if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) + { + mobj_t *mo; + player->kartstuff[k_itemheld] = 1; + S_StartSound(player->mo, sfx_s254); + mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_SSMINE_SHIELD); + if (mo) + { + mo->flags |= MF_NOCLIPTHING; + mo->threshold = 10; + mo->movecount = 1; + mo->movedir = 1; + P_SetTarget(&mo->target, player->mo); + P_SetTarget(&player->mo->hnext, mo); + } + } + else if (ATTACK_IS_DOWN && player->kartstuff[k_itemheld]) + { + K_ThrowKartItem(player, false, MT_SSMINE, 1, true); + K_PlayTauntSound(player->mo); + player->kartstuff[k_itemamount]--; + player->kartstuff[k_itemheld] = 0; + K_CleanHnextList(player->mo); + } + break; + case KITEM_BALLHOG: + if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) + { + player->kartstuff[k_itemamount]--; + K_ThrowKartItem(player, true, MT_BALLHOG, 1, false); + S_StartSound(player->mo, sfx_mario7); + K_PlayTauntSound(player->mo); + } + break; + case KITEM_SPB: + if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) + { + UINT8 ploop; + UINT8 bestrank = 0; + fixed_t dist = 0; + + for (ploop = 0; ploop < MAXPLAYERS; ploop++) + { + fixed_t thisdist; + if (!playeringame[ploop] || players[ploop].spectator) + continue; + if (&players[ploop] == player) + continue; + if (!players[ploop].mo) + continue; + if (players[ploop].exiting) + continue; + thisdist = R_PointToDist2(player->mo->x, player->mo->y, players[ploop].mo->x, players[ploop].mo->y); + if (bestrank == 0 || players[ploop].kartstuff[k_position] < bestrank) + { + bestrank = players[ploop].kartstuff[k_position]; + dist = thisdist; + } + } + + if (dist == 0) + spbincoming = 6*TICRATE; // If you couldn't find anyone, just set an abritary timer + else + spbincoming = (tic_t)max(1, FixedDiv(dist, 64*FRACUNIT)/FRACUNIT); + + spbplayer = player-players; + + player->kartstuff[k_itemamount]--; + + K_PlayTauntSound(player->mo); + } + break; + case KITEM_GROW: + if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO + && player->kartstuff[k_growshrinktimer] <= 0) // Grow holds the item box hostage + { + K_PlayTauntSound(player->mo); + player->mo->scalespeed = FRACUNIT/TICRATE; + player->mo->destscale = 3*(mapheaderinfo[gamemap-1]->mobj_scale)/2; + if (cv_kartdebugshrink.value && !player->bot) + player->mo->destscale = 6*player->mo->destscale/8; + player->kartstuff[k_growshrinktimer] = itemtime+(4*TICRATE); // 12 seconds + P_RestoreMusic(player); + if (!cv_kartinvinsfx.value && !P_IsLocalPlayer(player)) + S_StartSound(player->mo, sfx_kgrow); + S_StartSound(player->mo, sfx_kc5a); + player->kartstuff[k_itemamount]--; + } + break; + case KITEM_SHRINK: + if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) + { + K_DoShrink(player); + player->kartstuff[k_itemamount]--; + } + break; + case KITEM_THUNDERSHIELD: + if (player->kartstuff[k_curshield] <= 0) + { + mobj_t *shield = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_THUNDERSHIELD); + P_SetTarget(&shield->target, player->mo); + player->kartstuff[k_curshield] = 1; + } + if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) + { + K_DoThunderShield(player); + player->kartstuff[k_itemamount]--; + } + break; + case KITEM_HYUDORO: + if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) + { + player->kartstuff[k_itemamount]--; + K_DoHyudoroSteal(player); // yes. yes they do. + } + break; + case KITEM_POGOSPRING: + if (ATTACK_IS_DOWN && !HOLDING_ITEM && onground && NO_HYUDORO + && !player->kartstuff[k_pogospring]) + { + K_PlayTauntSound(player->mo); + K_DoPogoSpring(player->mo, 32<kartstuff[k_pogospring] = 1; + player->kartstuff[k_itemamount]--; + } + break; + case KITEM_KITCHENSINK: + if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) + { + K_ThrowKartItem(player, false, MT_SINK, 1, true); + K_PlayTauntSound(player->mo); + player->kartstuff[k_itemamount]--; + player->kartstuff[k_itemheld] = 0; + } + break; + case KITEM_SAD: + if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO + && !player->kartstuff[k_sadtimer]) + { + player->kartstuff[k_sadtimer] = stealtime; + player->kartstuff[k_itemamount]--; + } + break; + default: + break; } - - if (dist == 0) - blueshellincoming = 6*TICRATE; // If you couldn't find anyone, just set an abritary timer - else - blueshellincoming = (tic_t)max(1, FixedDiv(dist, 64*FRACUNIT)/FRACUNIT); - - blueshellplayer = player-players; - player->pflags |= PF_ATTACKDOWN; - K_PlayTauntSound(player->mo); - player->kartstuff[k_blueshell] = 0; - player->kartstuff[k_itemclose] = 10; } - // Mega Mushroom - else if (ATTACK_IS_DOWN && !HOLDING_ITEM && player->kartstuff[k_megashroom] == 1 && NO_BOO) + + // No more! + if (!player->kartstuff[k_itemamount]) { - if (P_IsLocalPlayer(player) && !player->exiting) - S_ChangeMusicInternal("mega", true); - if (!cv_kartstarsfx.value && !P_IsLocalPlayer(player)) - S_StartSound(player->mo, sfx_mega); - K_PlayTauntSound(player->mo); - player->kartstuff[k_growshrinktimer] = itemtime + TICRATE*2; - S_StartSound(player->mo, sfx_mario3); - player->pflags |= PF_ATTACKDOWN; - player->kartstuff[k_megashroom] = 0; - if (G_BattleGametype()) - player->kartstuff[k_poweritemtimer] = 10*TICRATE; - player->kartstuff[k_itemclose] = 10; - } - // Boo - else if (ATTACK_IS_DOWN && !HOLDING_ITEM && player->kartstuff[k_boo] == 1 && NO_BOO) - { - K_DoBooSteal(player); - player->pflags |= PF_ATTACKDOWN; - player->kartstuff[k_boo] = 0; - } - // Magnet - else if (ATTACK_IS_DOWN && !HOLDING_ITEM && player->kartstuff[k_magnet] == 1 && NO_BOO) - { - K_DoMagnet(player); - player->pflags |= PF_ATTACKDOWN; - player->kartstuff[k_magnet] = 0; - } - // Feather - else if (ATTACK_IS_DOWN && !HOLDING_ITEM && player->kartstuff[k_feather] & 1 && onground && NO_BOO) - { - K_PlayTauntSound(player->mo); - K_DoBouncePad(player->mo, 32<pflags |= PF_ATTACKDOWN; - player->kartstuff[k_feather] |= 2; - player->kartstuff[k_feather] &= ~1; - - player->kartstuff[k_itemclose] = 10; + player->kartstuff[k_itemheld] = 0; + player->kartstuff[k_itemtype] = KITEM_NONE; } - // Mushroom Boost - if (((player->kartstuff[k_mushroomtimer] > 0 && player->kartstuff[k_boosting] == 0) - || (player->kartstuff[k_mushroomtimer] > 0 && ATTACK_IS_DOWN && NO_BOO)) && onground) - { - player->kartstuff[k_boosting] = 1; - } - else if (player->kartstuff[k_mushroomtimer] == 0 && player->kartstuff[k_boosting] == 1) - player->kartstuff[k_boosting] = 0; + if (player->kartstuff[k_itemtype] != KITEM_THUNDERSHIELD) + player->kartstuff[k_curshield] = 0; - // Megashroom - Make the player grow! - if (player->kartstuff[k_growshrinktimer] > ((itemtime + TICRATE*2) - 25)) - { - if (leveltime & 2) - player->mo->destscale = (mapheaderinfo[gamemap-1]->mobj_scale)*3/2; - else - player->mo->destscale = (mapheaderinfo[gamemap-1]->mobj_scale); - } - else if (player->kartstuff[k_growshrinktimer] > 26 - && player->kartstuff[k_growshrinktimer] <= ((itemtime + TICRATE*2) - 25)) - player->mo->destscale = (mapheaderinfo[gamemap-1]->mobj_scale)*3/2; - // Megashroom - Back to normal... - else if (player->kartstuff[k_growshrinktimer] > 1 - && player->kartstuff[k_growshrinktimer] <= 26) - { - if (leveltime & 2) - player->mo->destscale = (mapheaderinfo[gamemap-1]->mobj_scale); - else - player->mo->destscale = (mapheaderinfo[gamemap-1]->mobj_scale)*3/2; - } - if (player->kartstuff[k_growshrinktimer] == 26) - S_StartSound(player->mo, sfx_mario8); + if (player->kartstuff[k_itemtype] == KITEM_SPB + || player->kartstuff[k_itemtype] == KITEM_SHRINK + || player->kartstuff[k_growshrinktimer] < 0 + || spbincoming) + indirectitemcooldown = 20*TICRATE; - if ((G_BattleGametype()) - && (player->kartstuff[k_star] || player->kartstuff[k_megashroom] - || player->kartstuff[k_startimer] || player->kartstuff[k_growshrinktimer] > 0)) - player->kartstuff[k_poweritemtimer] = 10*TICRATE; - - if (player->kartstuff[k_bootimer] > 0) + if (player->kartstuff[k_hyudorotimer] > 0) { if (splitscreen) { @@ -3425,7 +4142,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) else player->mo->flags2 &= ~MF2_DONTDRAW; - if (player->kartstuff[k_bootimer] >= (1*TICRATE/2) && player->kartstuff[k_bootimer] <= bootime-(1*TICRATE/2)) + if (player->kartstuff[k_hyudorotimer] >= (1*TICRATE/2) && player->kartstuff[k_hyudorotimer] <= hyudorotime-(1*TICRATE/2)) { if (player == &players[secondarydisplayplayer]) player->mo->eflags |= MFE_DRAWONLYFORP2; @@ -3442,7 +4159,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) else { if (player == &players[displayplayer] - || (player != &players[displayplayer] && (player->kartstuff[k_bootimer] < (1*TICRATE/2) || player->kartstuff[k_bootimer] > bootime-(1*TICRATE/2)))) + || (player != &players[displayplayer] && (player->kartstuff[k_hyudorotimer] < (1*TICRATE/2) || player->kartstuff[k_hyudorotimer] > hyudorotime-(1*TICRATE/2)))) { if (leveltime & 1) player->mo->flags2 |= MF2_DONTDRAW; @@ -3453,62 +4170,23 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->mo->flags2 |= MF2_DONTDRAW; } - player->powers[pw_flashing] = player->kartstuff[k_bootimer]; // We'll do this for now, let's people know about the invisible people through subtle hints + player->powers[pw_flashing] = player->kartstuff[k_hyudorotimer]; // We'll do this for now, let's people know about the invisible people through subtle hints } - else if (player->kartstuff[k_bootimer] == 0) + else if (player->kartstuff[k_hyudorotimer] == 0) { player->mo->flags2 &= ~MF2_DONTDRAW; player->mo->eflags &= ~(MFE_DRAWONLYFORP1|MFE_DRAWONLYFORP2|MFE_DRAWONLYFORP3|MFE_DRAWONLYFORP4); } - if (G_BattleGametype() && player->kartstuff[k_balloon] <= 0) // dead in match? you da bomb + if (G_BattleGametype() && player->kartstuff[k_bumper] <= 0) // dead in match? you da bomb { K_StripItems(player); player->mo->flags2 |= MF2_SHADOW; - - if (!(player->mo->tracer)) - { - player->mo->tracer = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_OVERLAY); - P_SetMobjState(player->mo->tracer, S_PLAYERBOMB); - } - - P_SetTarget(&player->mo->tracer->target, player->mo); - player->mo->tracer->color = player->mo->color; - - if (player->kartstuff[k_comebacktimer] > 0) - { - if (player->mo->tracer->state != &states[S_PLAYERBOMB]) - P_SetMobjState(player->mo->tracer, S_PLAYERBOMB); - - if (player->kartstuff[k_comebacktimer] < TICRATE && (leveltime & 1)) - player->mo->tracer->flags2 &= ~MF2_DONTDRAW; - else - player->mo->tracer->flags2 |= MF2_DONTDRAW; - - player->powers[pw_flashing] = player->kartstuff[k_comebacktimer]; - } - else - { - if (player->kartstuff[k_comebackmode] == 0 - && player->mo->tracer->state != &states[S_PLAYERBOMB]) - P_SetMobjState(player->mo->tracer, S_PLAYERBOMB); - else if (player->kartstuff[k_comebackmode] == 1 - && player->mo->tracer->state != &states[S_PLAYERITEM]) - P_SetMobjState(player->mo->tracer, S_PLAYERITEM); - - if (player->powers[pw_flashing] && (leveltime & 1)) - player->mo->tracer->flags2 |= MF2_DONTDRAW; - else - player->mo->tracer->flags2 &= ~MF2_DONTDRAW; - } + player->powers[pw_flashing] = player->kartstuff[k_comebacktimer]; } - else if (G_RaceGametype() || player->kartstuff[k_balloon] > 0) + else if (G_RaceGametype() || player->kartstuff[k_bumper] > 0) { player->mo->flags2 &= ~MF2_SHADOW; - if (player->mo->tracer - && (player->mo->tracer->state == &states[S_PLAYERBOMB] - || player->mo->tracer->state == &states[S_PLAYERITEM])) - P_RemoveMobj(player->mo->tracer); } } @@ -3520,7 +4198,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->mo->friction += 4608; if (player->speed > 0 && cmd->forwardmove < 0 && player->mo->friction == 59392) player->mo->friction += 1608; - if (G_BattleGametype() && player->kartstuff[k_balloon] <= 0) + if (G_BattleGametype() && player->kartstuff[k_bumper] <= 0) { player->mo->friction += 1228; @@ -3539,20 +4217,26 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if (player->mo->movefactor < 32) player->mo->movefactor = 32; } + if (player->kartstuff[k_spinouttimer] && player->kartstuff[k_wipeoutslow]) + { + player->mo->friction -= FixedMul(1228, player->kartstuff[k_offroad]); + if (player->kartstuff[k_wipeoutslow] == 1) + player->mo->friction -= 4912; + } K_KartDrift(player, onground); // Quick Turning // You can't turn your kart when you're not moving. // So now it's time to burn some rubber! - if (player->speed < 2 && leveltime > 140 && cmd->buttons & BT_ACCELERATE && cmd->buttons & BT_BRAKE && cmd->driftturn != 0) + if (player->speed < 2 && leveltime > starttime && cmd->buttons & BT_ACCELERATE && cmd->buttons & BT_BRAKE && cmd->driftturn != 0) { if (leveltime % 20 == 0) S_StartSound(player->mo, sfx_mkslid); } // Squishing - // If a Mega Mushroom or a Thwomp crushes you, get flattened instead of being killed. + // If a Grow player or a sector crushes you, get flattened instead of being killed. if (player->kartstuff[k_squishedtimer] <= 0) { @@ -3565,51 +4249,198 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->mo->momy = 0; } - // Play the stop light's sounds - if ((leveltime == (TICRATE-4)*2) || (leveltime == (TICRATE-2)*3)) - S_StartSound(NULL, sfx_lkt1); - if (leveltime == (TICRATE)*4) - S_StartSound(NULL, sfx_lkt2); + // Play the starting countdown sounds + if (player == &players[displayplayer]) // Don't play louder in splitscreen + { + if ((leveltime == starttime-(3*TICRATE)) || (leveltime == starttime-(2*TICRATE)) || (leveltime == starttime-TICRATE)) + S_StartSound(NULL, sfx_s3ka7); + if (leveltime == starttime) + { + S_StartSound(NULL, sfx_s3kad); + S_StopMusic(); // The GO! sound stops the level start ambience + } + } + // Start charging once you're given the opportunity. - if (leveltime >= 70 && leveltime <= 140 && cmd->buttons & BT_ACCELERATE) - player->kartstuff[k_boostcharge]++; - if (leveltime >= 70 && leveltime <= 140 && !(cmd->buttons & BT_ACCELERATE)) - player->kartstuff[k_boostcharge] = 0; + if (leveltime >= starttime-(2*TICRATE) && leveltime <= starttime) + { + if (cmd->buttons & BT_ACCELERATE) + player->kartstuff[k_boostcharge]++; + else + player->kartstuff[k_boostcharge] = 0; + } + // Increase your size while charging your engine. - if (leveltime < 150) + if (leveltime < starttime+10) + { player->mo->destscale = (mapheaderinfo[gamemap-1]->mobj_scale) + (player->kartstuff[k_boostcharge]*131); + if (cv_kartdebugshrink.value && !player->bot) + player->mo->destscale = 6*player->mo->destscale/8; + } // Determine the outcome of your charge. - if (leveltime > 140 && player->kartstuff[k_boostcharge]) + if (leveltime > starttime && player->kartstuff[k_boostcharge]) { - // Get an instant boost! - if (player->kartstuff[k_boostcharge] >= 35 && player->kartstuff[k_boostcharge] <= 50) + // Not even trying? + if (player->kartstuff[k_boostcharge] < 35) { + if (player->kartstuff[k_boostcharge] > 17) + S_StartSound(player->mo, sfx_cdfm00); // chosen instead of a conventional skid because it's more engine-like + } + // Get an instant boost! + else if (player->kartstuff[k_boostcharge] <= 50) + { + player->kartstuff[k_sneakertimer] = -((21*(player->kartstuff[k_boostcharge]*player->kartstuff[k_boostcharge]))/425)+131; // max time is 70, min time is 7; yay parabooolas if (!player->kartstuff[k_floorboost] || player->kartstuff[k_floorboost] == 3) - S_StartSound(player->mo, sfx_sboost); - - player->kartstuff[k_mushroomtimer] = -((21*(player->kartstuff[k_boostcharge]*player->kartstuff[k_boostcharge]))/425)+131; // max time is 70, min time is 7; yay parabooolas + { + if (player->kartstuff[k_sneakertimer] >= 70) + S_StartSound(player->mo, sfx_s25f); // Special sound for the perfect start boost! + else if (player->kartstuff[k_sneakertimer] >= sneakertime) + S_StartSound(player->mo, sfx_cdfm01); // Sneaker boost sound for big boost + else + S_StartSound(player->mo, sfx_s23c); // Drift boost sound for small boost + } } // You overcharged your engine? Those things are expensive!!! else if (player->kartstuff[k_boostcharge] > 50) { player->powers[pw_nocontrol] = 40; - S_StartSound(player->mo, sfx_slip); + //S_StartSound(player->mo, sfx_kc34); + S_StartSound(player->mo, sfx_s3k83); + player->pflags |= PF_SKIDDOWN; // cheeky pflag reuse } player->kartstuff[k_boostcharge] = 0; } } -void K_CheckBalloons(void) +void K_CalculateBattleWanted(void) +{ + UINT8 numingame = 0, numwanted = 0; + SINT8 bestbumperplayer = -1, bestbumper = -1; + SINT8 camppos[MAXPLAYERS]; // who is the biggest camper + UINT8 ties = 0, nextcamppos = 0; + boolean setbumper = false; + UINT8 i, j; + + if (!G_BattleGametype()) + { + for (i = 0; i < 4; i++) + battlewanted[i] = -1; + return; + } + + wantedcalcdelay = wantedfrequency; + + for (i = 0; i < MAXPLAYERS; i++) + camppos[i] = -1; // initialize + + for (i = 0; i < MAXPLAYERS; i++) + { + UINT8 position = 1; + + if (!playeringame[i] || players[i].spectator) // Not playing + continue; + + if (players[i].exiting) // We're done, don't calculate. + return; + + if (players[i].kartstuff[k_bumper] <= 0) // Not alive, so don't do anything else + continue; + + numingame++; + + if (bestbumper == -1 || players[i].kartstuff[k_bumper] > bestbumper) + { + bestbumper = players[i].kartstuff[k_bumper]; + bestbumperplayer = i; + } + else if (players[i].kartstuff[k_bumper] == bestbumper) + bestbumperplayer = -1; // Tie, no one has best bumper. + + for (j = 0; j < MAXPLAYERS; j++) + { + if (!playeringame[j] || players[j].spectator) + continue; + if (players[j].kartstuff[k_bumper] <= 0) + continue; + if (j == i) + continue; + if (players[j].kartstuff[k_wanted] == players[i].kartstuff[k_wanted] && players[j].marescore > players[i].marescore) + position++; + else if (players[j].kartstuff[k_wanted] > players[i].kartstuff[k_wanted]) + position++; + } + + position--; // Make zero based + + while (camppos[position] != -1) // Port priority! + position++; + + camppos[position] = i; + } + + if (numingame <= 2) + numwanted = 0; + else + numwanted = min(4, 1 + ((numingame-2) / 4)); + + for (i = 0; i < 4; i++) + { + if (i+1 > numwanted) // Not enough players for this slot to be wanted! + battlewanted[i] = -1; + else if (bestbumperplayer != -1 && !setbumper) // If there's a player who has an untied bumper lead over everyone else, they are the first to be wanted. + { + battlewanted[i] = bestbumperplayer; + setbumper = true; // Don't set twice + } + else + { + // Don't accidentally set the same player, if the bestbumperplayer is also a huge camper. + while (bestbumperplayer != -1 && camppos[nextcamppos] != -1 + && bestbumperplayer == camppos[nextcamppos]) + nextcamppos++; + + // Do not add *any* more people if there's too many times that are tied with others. + // This could theoretically happen very easily if people don't hit each other for a while after the start of a match. + // (I will be sincerely impressed if more than 2 people tie after people start hitting each other though) + + if (camppos[nextcamppos] == -1 // Out of entries + || ties >= (numwanted-i)) // Already counted ties + { + battlewanted[i] = -1; + continue; + } + + if (ties < (numwanted-i)) + { + ties = 0; // Reset + for (j = 0; j < 2; j++) + { + if (camppos[nextcamppos+(j+1)] == -1) // Nothing beyond, cancel + break; + if (players[camppos[nextcamppos]].kartstuff[k_wanted] == players[camppos[nextcamppos+(j+1)]].kartstuff[k_wanted]) + ties++; + } + } + + if (ties < (numwanted-i)) // Is it still low enough after counting? + { + battlewanted[i] = camppos[nextcamppos]; + nextcamppos++; + } + else + battlewanted[i] = -1; + } + } +} + +void K_CheckBumpers(void) { UINT8 i; UINT8 numingame = 0; SINT8 winnernum = -1; - -#if 0 - return; // set to 1 to test comeback mechanics while alone -#endif + INT32 winnerscoreadd = 0; if (!multiplayer) return; @@ -3629,134 +4460,160 @@ void K_CheckBalloons(void) return; numingame++; + winnerscoreadd += players[i].marescore; - if (players[i].kartstuff[k_balloon] <= 0) // if you don't have any balloons, you're probably not a winner + if (players[i].kartstuff[k_bumper] <= 0) // if you don't have any bumpers, you're probably not a winner continue; else if (winnernum > -1) // TWO winners? that's dumb :V return; + winnernum = i; + winnerscoreadd -= players[i].marescore; } if (numingame <= 1) return; - if (playeringame[winnernum]) + if (winnernum > -1 && playeringame[winnernum]) { - players[winnernum].score += 1; - CONS_Printf(M_GetText("%s recieved a point for winning!\n"), player_names[winnernum]); + players[winnernum].marescore += winnerscoreadd; + CONS_Printf(M_GetText("%s recieved %d point%s for winning!\n"), player_names[winnernum], winnerscoreadd, (winnerscoreadd == 1 ? "" : "s")); } - for (i = 0; i < MAXPLAYERS; i++) + for (i = 0; i < MAXPLAYERS; i++) // This can't go in the earlier loop because winning adds points + K_KartUpdatePosition(&players[i]); + + for (i = 0; i < MAXPLAYERS; i++) // and it can't be merged with this loop because it needs to be all updated before exiting... multi-loops suck... P_DoPlayerExit(&players[i]); } +void K_CheckSpectateStatus(void) +{ + UINT8 respawnlist[MAXPLAYERS]; + UINT8 i, numingame = 0, numjoiners = 0; + + // Get the number of players in game, and the players to be de-spectated. + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; + + if (!players[i].spectator) + { + numingame++; + if (gamestate != GS_LEVEL) // Allow if you're not in a level + continue; + if (players[i].exiting) // DON'T allow if anyone's exiting + return; + if (numingame < 2 || leveltime < starttime || mapreset) // Allow if the match hasn't started yet + continue; + if (G_RaceGametype() && players[i].laps) // DON'T allow if the race is at 2 laps + return; + continue; + } + else if (!(players[i].pflags & PF_WANTSTOJOIN)) + continue; + + respawnlist[numjoiners++] = i; + } + + // literally zero point in going any further if nobody is joining + if (!numjoiners) + return; + + // Reset the match if you're in an empty server + if (!mapreset && gamestate == GS_LEVEL && leveltime >= starttime && (numingame < 2 && numingame+numjoiners >= 2)) + { + S_ChangeMusicInternal("chalng", false); // COME ON + mapreset = 3*TICRATE; // Even though only the server uses this for game logic, set for everyone for HUD in the future + } + + // Finally, we can de-spectate everyone! + for (i = 0; i < numjoiners; i++) + P_SpectatorJoinGame(&players[respawnlist[i]]); +} + //} //{ SRB2kart HUD Code -#define NUMLAKIFRAMES 13 #define NUMPOSNUMS 10 #define NUMPOSFRAMES 7 // White, three blues, three reds +#define NUMWINFRAMES 6 // Red, yellow, green, cyan, blue, purple //{ Patch Definitions static patch_t *kp_nodraw; -static patch_t *kp_itembg; + static patch_t *kp_timesticker; static patch_t *kp_timestickerwide; static patch_t *kp_lapsticker; static patch_t *kp_lapstickernarrow; static patch_t *kp_splitlapflag; -static patch_t *kp_balloonsticker; -static patch_t *kp_balloonstickerwide; +static patch_t *kp_bumpersticker; +static patch_t *kp_bumperstickerwide; static patch_t *kp_karmasticker; static patch_t *kp_splitkarmabomb; static patch_t *kp_timeoutsticker; -static patch_t *kp_lakitustart[NUMLAKIFRAMES]; -static patch_t *kp_lakitulaps[17]; + +static patch_t *kp_startcountdown[8]; +static patch_t *kp_racefinish[2]; + static patch_t *kp_positionnum[NUMPOSNUMS][NUMPOSFRAMES]; static patch_t *kp_winnernum[NUMPOSFRAMES]; + static patch_t *kp_facenull; static patch_t *kp_facefirst; static patch_t *kp_facesecond; static patch_t *kp_facethird; static patch_t *kp_facefourth; + +static patch_t *kp_rankbumper; +static patch_t *kp_ranknobumpers; + static patch_t *kp_battlewin; +static patch_t *kp_battlecool; static patch_t *kp_battlelose; static patch_t *kp_battlewait; static patch_t *kp_battleinfo; -static patch_t *kp_magnet; -static patch_t *kp_boo; -static patch_t *kp_boosteal; -static patch_t *kp_mushroom; -static patch_t *kp_doublemushroom; -static patch_t *kp_triplemushroom; -static patch_t *kp_megashroom; -static patch_t *kp_goldshroom; -static patch_t *kp_star; -static patch_t *kp_triplebanana; -static patch_t *kp_fakeitem; -static patch_t *kp_banana; -static patch_t *kp_greenshell; -static patch_t *kp_redshell; -static patch_t *kp_triplegreenshell; -static patch_t *kp_bobomb; -static patch_t *kp_blueshell; -static patch_t *kp_fireflower; -static patch_t *kp_tripleredshell; -static patch_t *kp_lightning; -static patch_t *kp_feather; -static patch_t *kp_kitchensink; -static patch_t *kp_itemused1; -static patch_t *kp_itemused2; -static patch_t *kp_itemused3; -static patch_t *kp_itemused4; -static patch_t *kp_itemused5; -static patch_t *kp_singlebananaicon; -static patch_t *kp_doublebananaicon; -static patch_t *kp_triplebananaicon; -static patch_t *kp_singlegreenshellicon; -static patch_t *kp_doublegreenshellicon; -static patch_t *kp_triplegreenshellicon; -static patch_t *kp_singleredshellicon; -static patch_t *kp_doubleredshellicon; -static patch_t *kp_tripleredshellicon; -static patch_t *kp_check; -static patch_t *kp_checkw; -static patch_t *kp_checkstar; -static patch_t *kp_checkstarw; -static patch_t *kp_checkmega; -static patch_t *kp_checkmegaw; -static patch_t *kp_rankballoon; -static patch_t *kp_ranknoballoons; -static patch_t *kp_bswarning[2]; -/* -static patch_t *kp_neonoitem; -static patch_t *kp_electroshield; -static patch_t *kp_skghost; -static patch_t *kp_skghoststeal; -static patch_t *kp_speedshoe; -static patch_t *kp_doublespeedshoe; -static patch_t *kp_triplespeedshoe; -static patch_t *kp_sizeupmonitor; -static patch_t *kp_rocketshoe; -static patch_t *kp_invincibility; -static patch_t *kp_neotriplebanana; -static patch_t *kp_eggmanmonitor; -static patch_t *kp_neobanana; -static patch_t *kp_orbinaut; -static patch_t *kp_jaws; -static patch_t *kp_tripleorbinaut; -static patch_t *kp_specialstagemine; -static patch_t *kp_deton; -static patch_t *kp_laserwisp; -static patch_t *kp_doublejaws; -static patch_t *kp_sizedownmonitor; -static patch_t *kp_neoitemused1; -static patch_t *kp_neoitemused2; -static patch_t *kp_neoitemused3; -static patch_t *kp_neoitemused4; -static patch_t *kp_neoitemused5; -*/ +static patch_t *kp_wanted; + +static patch_t *kp_itembg[4]; +static patch_t *kp_itemtimer[2]; +static patch_t *kp_itemmulsticker[2]; +static patch_t *kp_itemx; + +static patch_t *kp_sneaker[2]; +static patch_t *kp_rocketsneaker[2]; +static patch_t *kp_invincibility[13]; +static patch_t *kp_banana[2]; +static patch_t *kp_eggman[2]; +static patch_t *kp_orbinaut[5]; +static patch_t *kp_jawz[2]; +static patch_t *kp_mine[2]; +static patch_t *kp_ballhog[2]; +static patch_t *kp_selfpropelledbomb[2]; +static patch_t *kp_grow[2]; +static patch_t *kp_shrink[2]; +static patch_t *kp_thundershield[2]; +static patch_t *kp_hyudoro[2]; +static patch_t *kp_pogospring[2]; +static patch_t *kp_kitchensink[2]; +static patch_t *kp_sadface[2]; + +static patch_t *kp_check[6]; + +static patch_t *kp_spbwarning[2]; +static patch_t *kp_eggnum[4]; + +static patch_t *kp_fpview[3]; +static patch_t *kp_inputwheel[5]; + +static patch_t *kp_challenger[25]; + +static patch_t *kp_lapanim_lap[7]; +static patch_t *kp_lapanim_final[11]; +static patch_t *kp_lapanim_number[10][3]; +static patch_t *kp_lapanim_emblem; void K_LoadKartHUDGraphics(void) { @@ -3765,8 +4622,6 @@ void K_LoadKartHUDGraphics(void) // Null Stuff kp_nodraw = W_CachePatchName("K_TRNULL", PU_HUDGFX); - kp_itembg = W_CachePatchName("K_ITNULL", PU_HUDGFX); - //kp_neonoitem = W_CachePatchName("KNITNULL", PU_HUDGFX); // Stickers kp_timesticker = W_CachePatchName("K_STTIME", PU_HUDGFX); @@ -3774,45 +4629,24 @@ void K_LoadKartHUDGraphics(void) kp_lapsticker = W_CachePatchName("K_STLAPS", PU_HUDGFX); kp_lapstickernarrow = W_CachePatchName("K_STLAPN", PU_HUDGFX); kp_splitlapflag = W_CachePatchName("K_SPTLAP", PU_HUDGFX); - kp_balloonsticker = W_CachePatchName("K_STBALN", PU_HUDGFX); - kp_balloonstickerwide = W_CachePatchName("K_STBALW", PU_HUDGFX); + kp_bumpersticker = W_CachePatchName("K_STBALN", PU_HUDGFX); + kp_bumperstickerwide = W_CachePatchName("K_STBALW", PU_HUDGFX); kp_karmasticker = W_CachePatchName("K_STKARM", PU_HUDGFX); kp_splitkarmabomb = W_CachePatchName("K_SPTKRM", PU_HUDGFX); kp_timeoutsticker = W_CachePatchName("K_STTOUT", PU_HUDGFX); - // Lakitu Start-up Frames - kp_lakitustart[0] = W_CachePatchName("K_LAKISA", PU_HUDGFX); - kp_lakitustart[1] = W_CachePatchName("K_LAKISB", PU_HUDGFX); - kp_lakitustart[2] = W_CachePatchName("K_LAKISC", PU_HUDGFX); - kp_lakitustart[3] = W_CachePatchName("K_LAKISD", PU_HUDGFX); - kp_lakitustart[4] = W_CachePatchName("K_LAKISE", PU_HUDGFX); - kp_lakitustart[5] = W_CachePatchName("K_LAKISF", PU_HUDGFX); - kp_lakitustart[6] = W_CachePatchName("K_LAKISG", PU_HUDGFX); - kp_lakitustart[7] = W_CachePatchName("K_LAKISH", PU_HUDGFX); - kp_lakitustart[8] = W_CachePatchName("K_LAKISI", PU_HUDGFX); - kp_lakitustart[9] = W_CachePatchName("K_LAKISJ", PU_HUDGFX); - kp_lakitustart[10] = W_CachePatchName("K_LAKISK", PU_HUDGFX); - kp_lakitustart[11] = W_CachePatchName("K_LAKISL", PU_HUDGFX); - kp_lakitustart[12] = W_CachePatchName("K_LAKISM", PU_HUDGFX); + // Starting countdown + kp_startcountdown[0] = W_CachePatchName("K_CNT3A", PU_HUDGFX); + kp_startcountdown[1] = W_CachePatchName("K_CNT2A", PU_HUDGFX); + kp_startcountdown[2] = W_CachePatchName("K_CNT1A", PU_HUDGFX); + kp_startcountdown[3] = W_CachePatchName("K_CNTGOA", PU_HUDGFX); + kp_startcountdown[4] = W_CachePatchName("K_CNT3B", PU_HUDGFX); + kp_startcountdown[5] = W_CachePatchName("K_CNT2B", PU_HUDGFX); + kp_startcountdown[6] = W_CachePatchName("K_CNT1B", PU_HUDGFX); + kp_startcountdown[7] = W_CachePatchName("K_CNTGOB", PU_HUDGFX); - // Lakitu Lap Frames - kp_lakitulaps[0] = W_CachePatchName("K_LAKIL2", PU_HUDGFX); - kp_lakitulaps[1] = W_CachePatchName("K_LAKIL3", PU_HUDGFX); - kp_lakitulaps[2] = W_CachePatchName("K_LAKIL4", PU_HUDGFX); - kp_lakitulaps[3] = W_CachePatchName("K_LAKIL5", PU_HUDGFX); - kp_lakitulaps[4] = W_CachePatchName("K_LAKIL6", PU_HUDGFX); - kp_lakitulaps[5] = W_CachePatchName("K_LAKIL7", PU_HUDGFX); - kp_lakitulaps[6] = W_CachePatchName("K_LAKIL8", PU_HUDGFX); - kp_lakitulaps[7] = W_CachePatchName("K_LAKIL9", PU_HUDGFX); - kp_lakitulaps[8] = W_CachePatchName("K_LAKILF", PU_HUDGFX); - kp_lakitulaps[9] = W_CachePatchName("K_LAKIF1", PU_HUDGFX); - kp_lakitulaps[10] = W_CachePatchName("K_LAKIF2", PU_HUDGFX); - kp_lakitulaps[11] = W_CachePatchName("K_LAKIF3", PU_HUDGFX); - kp_lakitulaps[12] = W_CachePatchName("K_LAKIF4", PU_HUDGFX); - kp_lakitulaps[13] = W_CachePatchName("K_LAKIF5", PU_HUDGFX); - kp_lakitulaps[14] = W_CachePatchName("K_LAKIF6", PU_HUDGFX); - kp_lakitulaps[15] = W_CachePatchName("K_LAKIF7", PU_HUDGFX); - kp_lakitulaps[16] = W_CachePatchName("K_LAKIF8", PU_HUDGFX); + kp_racefinish[0] = W_CachePatchName("K_FINA", PU_HUDGFX); + kp_racefinish[1] = W_CachePatchName("K_FINB", PU_HUDGFX); // Position numbers sprintf(buffer, "K_POSNxx"); @@ -3821,16 +4655,16 @@ void K_LoadKartHUDGraphics(void) buffer[6] = '0'+i; for (j = 0; j < NUMPOSFRAMES; j++) { - //if (i > 4 && j < 4 && j != 0) continue; // We don't need blue numbers for ranks past 4th //sprintf(buffer, "K_POSN%d%d", i, j); buffer[7] = '0'+j; kp_positionnum[i][j] = (patch_t *) W_CachePatchName(buffer, PU_HUDGFX); } } - for (i = 0; i < NUMPOSFRAMES; i++) + sprintf(buffer, "K_POSNWx"); + for (i = 0; i < NUMWINFRAMES; i++) { - sprintf(buffer, "K_POSNW%d", i); + buffer[7] = '0'+i; kp_winnernum[i] = (patch_t *) W_CachePatchName(buffer, PU_HUDGFX); } @@ -3840,114 +4674,168 @@ void K_LoadKartHUDGraphics(void) kp_facethird = W_CachePatchName("K_PFACE3", PU_HUDGFX); kp_facefourth = W_CachePatchName("K_PFACE4", PU_HUDGFX); + // Extra ranking icons + kp_rankbumper = W_CachePatchName("K_BLNICO", PU_HUDGFX); + kp_ranknobumpers = W_CachePatchName("K_NOBLNS", PU_HUDGFX); + // Battle graphics kp_battlewin = W_CachePatchName("K_BWIN", PU_HUDGFX); + kp_battlecool = W_CachePatchName("K_BCOOL", PU_HUDGFX); kp_battlelose = W_CachePatchName("K_BLOSE", PU_HUDGFX); kp_battlewait = W_CachePatchName("K_BWAIT", PU_HUDGFX); kp_battleinfo = W_CachePatchName("K_BINFO", PU_HUDGFX); + kp_wanted = W_CachePatchName("K_WANTED", PU_HUDGFX); // Kart Item Windows - kp_magnet = W_CachePatchName("K_ITMAGN", PU_HUDGFX); - kp_boo = W_CachePatchName("K_ITBOO1", PU_HUDGFX); - kp_boosteal = W_CachePatchName("K_ITBOO2", PU_HUDGFX); - kp_mushroom = W_CachePatchName("K_ITMUSH", PU_HUDGFX); - kp_doublemushroom = W_CachePatchName("K_ITDOUB", PU_HUDGFX); - kp_triplemushroom = W_CachePatchName("K_ITTRIP", PU_HUDGFX); - kp_megashroom = W_CachePatchName("K_ITMEGA", PU_HUDGFX); - kp_goldshroom = W_CachePatchName("K_ITGOLD", PU_HUDGFX); - kp_star = W_CachePatchName("K_ITSTAR", PU_HUDGFX); - kp_triplebanana = W_CachePatchName("K_ITTBAN", PU_HUDGFX); - kp_fakeitem = W_CachePatchName("K_ITFAKE", PU_HUDGFX); - kp_banana = W_CachePatchName("K_ITBANA", PU_HUDGFX); - kp_greenshell = W_CachePatchName("K_ITGREE", PU_HUDGFX); - kp_redshell = W_CachePatchName("K_ITREDS", PU_HUDGFX); - kp_triplegreenshell = W_CachePatchName("K_ITTGRE", PU_HUDGFX); - kp_bobomb = W_CachePatchName("K_ITBOBO", PU_HUDGFX); - kp_blueshell = W_CachePatchName("K_ITBLUE", PU_HUDGFX); - kp_fireflower = W_CachePatchName("K_ITFIRE", PU_HUDGFX); - kp_tripleredshell = W_CachePatchName("K_ITTRED", PU_HUDGFX); - kp_lightning = W_CachePatchName("K_ITLIGH", PU_HUDGFX); - kp_feather = W_CachePatchName("K_ITFETH", PU_HUDGFX); - kp_kitchensink = W_CachePatchName("K_ITSINK", PU_HUDGFX); + kp_itembg[0] = W_CachePatchName("K_ITBG", PU_HUDGFX); + kp_itembg[1] = W_CachePatchName("K_ITBGD", PU_HUDGFX); + kp_itemtimer[0] = W_CachePatchName("K_ITIMER", PU_HUDGFX); + kp_itemmulsticker[0] = W_CachePatchName("K_ITMUL", PU_HUDGFX); + kp_itemx = W_CachePatchName("K_ITX", PU_HUDGFX); - // Item-used - Closing the item window after an item is used - kp_itemused1 = W_CachePatchName("K_ITUSE1", PU_HUDGFX); - kp_itemused2 = W_CachePatchName("K_ITUSE2", PU_HUDGFX); - kp_itemused3 = W_CachePatchName("K_ITUSE3", PU_HUDGFX); - kp_itemused4 = W_CachePatchName("K_ITUSE4", PU_HUDGFX); - kp_itemused5 = W_CachePatchName("K_ITUSE5", PU_HUDGFX); + kp_sneaker[0] = W_CachePatchName("K_ITSHOE", PU_HUDGFX); + kp_rocketsneaker[0] = W_CachePatchName("K_ITRSHE", PU_HUDGFX); - // Triple-item HUD icons - kp_singlebananaicon = W_CachePatchName("K_TRBAN1", PU_HUDGFX); - kp_doublebananaicon = W_CachePatchName("K_TRBAN2", PU_HUDGFX); - kp_triplebananaicon = W_CachePatchName("K_TRBAN3", PU_HUDGFX); - kp_singlegreenshellicon = W_CachePatchName("K_TRGRE1", PU_HUDGFX); - kp_doublegreenshellicon = W_CachePatchName("K_TRGRE2", PU_HUDGFX); - kp_triplegreenshellicon = W_CachePatchName("K_TRGRE3", PU_HUDGFX); - kp_singleredshellicon = W_CachePatchName("K_TRRED1", PU_HUDGFX); - kp_doubleredshellicon = W_CachePatchName("K_TRRED2", PU_HUDGFX); - kp_tripleredshellicon = W_CachePatchName("K_TRRED3", PU_HUDGFX); + sprintf(buffer, "K_ITINVx"); + for (i = 0; i < 7; i++) + { + buffer[7] = '1'+i; + kp_invincibility[i] = (patch_t *) W_CachePatchName(buffer, PU_HUDGFX); + } + kp_banana[0] = W_CachePatchName("K_ITBANA", PU_HUDGFX); + kp_eggman[0] = W_CachePatchName("K_ITEGGM", PU_HUDGFX); + sprintf(buffer, "K_ITORBx"); + for (i = 0; i < 4; i++) + { + buffer[7] = '1'+i; + kp_orbinaut[i] = (patch_t *) W_CachePatchName(buffer, PU_HUDGFX); + } + kp_jawz[0] = W_CachePatchName("K_ITJAWZ", PU_HUDGFX); + kp_mine[0] = W_CachePatchName("K_ITMINE", PU_HUDGFX); + kp_ballhog[0] = W_CachePatchName("K_ITBHOG", PU_HUDGFX); + kp_selfpropelledbomb[0] = W_CachePatchName("K_ITSPB", PU_HUDGFX); + kp_grow[0] = W_CachePatchName("K_ITGROW", PU_HUDGFX); + kp_shrink[0] = W_CachePatchName("K_ITSHRK", PU_HUDGFX); + kp_thundershield[0] = W_CachePatchName("K_ITTHNS", PU_HUDGFX); + kp_hyudoro[0] = W_CachePatchName("K_ITHYUD", PU_HUDGFX); + kp_pogospring[0] = W_CachePatchName("K_ITPOGO", PU_HUDGFX); + kp_kitchensink[0] = W_CachePatchName("K_ITSINK", PU_HUDGFX); + kp_sadface[0] = W_CachePatchName("K_ITSAD", PU_HUDGFX); + + // Splitscreen + kp_itembg[2] = W_CachePatchName("K_ISBG", PU_HUDGFX); + kp_itembg[3] = W_CachePatchName("K_ISBGD", PU_HUDGFX); + kp_itemtimer[1] = W_CachePatchName("K_ISIMER", PU_HUDGFX); + kp_itemmulsticker[1] = W_CachePatchName("K_ISMUL", PU_HUDGFX); + + kp_sneaker[1] = W_CachePatchName("K_ISSHOE", PU_HUDGFX); + kp_rocketsneaker[1] = W_CachePatchName("K_ISRSHE", PU_HUDGFX); + sprintf(buffer, "K_ISINVx"); + for (i = 0; i < 6; i++) + { + buffer[7] = '1'+i; + kp_invincibility[i+7] = (patch_t *) W_CachePatchName(buffer, PU_HUDGFX); + } + kp_banana[1] = W_CachePatchName("K_ISBANA", PU_HUDGFX); + kp_eggman[1] = W_CachePatchName("K_ISEGGM", PU_HUDGFX); + kp_orbinaut[4] = W_CachePatchName("K_ISORBN", PU_HUDGFX); + kp_jawz[1] = W_CachePatchName("K_ISJAWZ", PU_HUDGFX); + kp_mine[1] = W_CachePatchName("K_ISMINE", PU_HUDGFX); + kp_ballhog[1] = W_CachePatchName("K_ISBHOG", PU_HUDGFX); + kp_selfpropelledbomb[1] = W_CachePatchName("K_ISSPB", PU_HUDGFX); + kp_grow[1] = W_CachePatchName("K_ISGROW", PU_HUDGFX); + kp_shrink[1] = W_CachePatchName("K_ISSHRK", PU_HUDGFX); + kp_thundershield[1] = W_CachePatchName("K_ISTHNS", PU_HUDGFX); + kp_hyudoro[1] = W_CachePatchName("K_ISHYUD", PU_HUDGFX); + kp_pogospring[1] = W_CachePatchName("K_ISPOGO", PU_HUDGFX); + kp_kitchensink[1] = W_CachePatchName("K_ISSINK", PU_HUDGFX); + kp_sadface[1] = W_CachePatchName("K_ISSAD", PU_HUDGFX); // CHECK indicators - kp_check = W_CachePatchName("K_CHECK1", PU_HUDGFX); - kp_checkw = W_CachePatchName("K_CHECK2", PU_HUDGFX); - kp_checkstar = W_CachePatchName("K_CHECK3", PU_HUDGFX); - kp_checkstarw = W_CachePatchName("K_CHECK4", PU_HUDGFX); - kp_checkmega = W_CachePatchName("K_CHECK5", PU_HUDGFX); - kp_checkmegaw = W_CachePatchName("K_CHECK6", PU_HUDGFX); + sprintf(buffer, "K_CHECKx"); + for (i = 0; i < 6; i++) + { + buffer[7] = '1'+i; + kp_check[i] = (patch_t *) W_CachePatchName(buffer, PU_HUDGFX); + } - // Extra ranking icons - kp_rankballoon = W_CachePatchName("K_BLNICO", PU_HUDGFX); - kp_ranknoballoons = W_CachePatchName("K_NOBLNS", PU_HUDGFX); + // SPB warning + kp_spbwarning[0] = W_CachePatchName("K_SPBW1", PU_HUDGFX); + kp_spbwarning[1] = W_CachePatchName("K_SPBW2", PU_HUDGFX); - // Blue Shell warning - kp_bswarning[0] = W_CachePatchName("K_BSWRN1", PU_HUDGFX); - kp_bswarning[1] = W_CachePatchName("K_BSWRN2", PU_HUDGFX); + // Eggman warning numbers + sprintf(buffer, "K_EGGNx"); + for (i = 0; i < 4; i++) + { + buffer[6] = '0'+i; + kp_eggnum[i] = (patch_t *) W_CachePatchName(buffer, PU_HUDGFX); + } - /* - // Neo-Kart item windows - kp_electroshield = W_CachePatchName("KNITELEC", PU_HUDGFX); - kp_skghost = W_CachePatchName("KTITSKG1", PU_HUDGFX); - kp_skghoststeal = W_CachePatchName("KTITSKG2", PU_HUDGFX); - kp_speedshoe = W_CachePatchName("KTITSPEE", PU_HUDGFX); - kp_triplespeedshoe = W_CachePatchName("KTITTSPE", PU_HUDGFX); - kp_sizeupmonitor = W_CachePatchName("KTITSUPM", PU_HUDGFX); - kp_rocketshoe = W_CachePatchName("KTITROCK", PU_HUDGFX); - kp_invincibility = W_CachePatchName("KTITINVI", PU_HUDGFX); - kp_neotriplebanana = W_CachePatchName("KTITTBAN", PU_HUDGFX); - kp_eggmanmonitor = W_CachePatchName("KTITEGGM", PU_HUDGFX); - kp_neobanana = W_CachePatchName("KTITBANA", PU_HUDGFX); - kp_orbinaut = W_CachePatchName("KTITORBI", PU_HUDGFX); - kp_jaws = W_CachePatchName("KTITJAWS", PU_HUDGFX); - kp_tripleorbinaut = W_CachePatchName("KTITTORB", PU_HUDGFX); - kp_specialstagemine = W_CachePatchName("KTITSPEC", PU_HUDGFX); - kp_deton = W_CachePatchName("KTITDETO", PU_HUDGFX); - kp_laserwisp = W_CachePatchName("KTITLASE", PU_HUDGFX); - kp_doublejaws = W_CachePatchName("KTITDJAW", PU_HUDGFX); - kp_sizedownmonitor = W_CachePatchName("KTITSDOW", PU_HUDGFX); + // First person mode + kp_fpview[0] = W_CachePatchName("VIEWA0", PU_HUDGFX); + kp_fpview[1] = W_CachePatchName("VIEWB0D0", PU_HUDGFX); + kp_fpview[2] = W_CachePatchName("VIEWC0E0", PU_HUDGFX); - // Item-used - Closing the item window after an item is used (Neo-Kart) - kp_neoitemused1 = W_CachePatchName("KNITUSE1", PU_HUDGFX); - kp_neoitemused2 = W_CachePatchName("KNITUSE2", PU_HUDGFX); - kp_neoitemused3 = W_CachePatchName("KNITUSE3", PU_HUDGFX); - kp_neoitemused4 = W_CachePatchName("KNITUSE4", PU_HUDGFX); - kp_neoitemused5 = W_CachePatchName("KNITUSE5", PU_HUDGFX); - */ + // Input UI Wheel + sprintf(buffer, "K_WHEELx"); + for (i = 0; i < 5; i++) + { + buffer[7] = '0'+i; + kp_inputwheel[i] = (patch_t *) W_CachePatchName(buffer, PU_HUDGFX); + } + + // HERE COMES A NEW CHALLENGER + sprintf(buffer, "K_CHALxx"); + for (i = 0; i < 25; i++) + { + buffer[6] = '0'+((i+1)/10); + buffer[7] = '0'+((i+1)%10); + kp_challenger[i] = (patch_t *) W_CachePatchName(buffer, PU_HUDGFX); + } + + // Lap start animation + sprintf(buffer, "K_LAP0x"); + for (i = 0; i < 7; i++) + { + buffer[6] = '0'+(i+1); + kp_lapanim_lap[i] = (patch_t *) W_CachePatchName(buffer, PU_HUDGFX); + } + + sprintf(buffer, "K_LAPFxx"); + for (i = 0; i < 11; i++) + { + buffer[6] = '0'+((i+1)/10); + buffer[7] = '0'+((i+1)%10); + kp_lapanim_final[i] = (patch_t *) W_CachePatchName(buffer, PU_HUDGFX); + } + + sprintf(buffer, "K_LAPNxx"); + for (i = 0; i < 10; i++) + { + buffer[6] = '0'+i; + for (j = 0; j < 3; j++) + { + buffer[7] = '0'+(j+1); + kp_lapanim_number[i][j] = (patch_t *) W_CachePatchName(buffer, PU_HUDGFX); + } + } + + kp_lapanim_emblem = (patch_t *) W_CachePatchName("K_LAPE00", PU_HUDGFX); } //} INT32 ITEM_X, ITEM_Y; // Item Window -INT32 TRIP_X, TRIP_Y; // Triple Item Icon INT32 TIME_X, TIME_Y; // Time Sticker INT32 LAPS_X, LAPS_Y; // Lap Sticker INT32 SPDM_X, SPDM_Y; // Speedometer INT32 POSI_X, POSI_Y; // Position Number INT32 FACE_X, FACE_Y; // Top-four Faces -INT32 LAKI_X, LAKI_Y; // Lakitu +INT32 STCD_X, STCD_Y; // Starting countdown INT32 CHEK_Y; // CHECK graphic INT32 MINI_X, MINI_Y; // Minimap -INT32 BSWR_X, BSWR_Y; // Blue Shell warning +INT32 SPBW_X, SPBW_Y; // SPB warning +INT32 WANT_X, WANT_Y; // Battle WANTED poster static void K_initKartHUD(void) { @@ -3987,65 +4875,74 @@ static void K_initKartHUD(void) // Single Screen (defaults) // Item Window - ITEM_X = BASEVIDWIDTH - 52; // 268 - ITEM_Y = 9; // 9 - // Triple Item Object - TRIP_X = 143; // 143 - TRIP_Y = BASEVIDHEIGHT- 34; // 166 + ITEM_X = 5; // 5 + ITEM_Y = 5; // 5 // Level Timer - TIME_X = 9; // 172 - TIME_Y = 9; // 9 + TIME_X = BASEVIDWIDTH - 148; // 172 + TIME_Y = 9; // 9 // Level Laps - LAPS_X = 9; // 9 - LAPS_Y = BASEVIDHEIGHT- 29; // 171 + LAPS_X = 9; // 9 + LAPS_Y = BASEVIDHEIGHT - 29; // 171 // Speedometer - SPDM_X = 9; // 9 - SPDM_Y = BASEVIDHEIGHT- 45; // 155 + SPDM_X = 9; // 9 + SPDM_Y = BASEVIDHEIGHT - 45; // 155 // Position Number - POSI_X = BASEVIDWIDTH - 9; // 268 - POSI_Y = BASEVIDHEIGHT- 9; // 138 + POSI_X = BASEVIDWIDTH - 9; // 268 + POSI_Y = BASEVIDHEIGHT - 9; // 138 // Top-Four Faces - FACE_X = 9; // 9 - FACE_Y = 92; // 92 - // Lakitu - LAKI_X = 136; // 138 - LAKI_Y = 58 - 200; // 58 + FACE_X = 9; // 9 + FACE_Y = 92; // 92 + // Starting countdown + STCD_X = BASEVIDWIDTH/2; // 9 + STCD_Y = BASEVIDHEIGHT/2; // 92 // CHECK graphic - CHEK_Y = BASEVIDHEIGHT; // 200 + CHEK_Y = BASEVIDHEIGHT; // 200 // Minimap - MINI_X = BASEVIDWIDTH - 50; // 270 - MINI_Y = BASEVIDHEIGHT/2; // 100 + MINI_X = BASEVIDWIDTH - 50; // 270 + MINI_Y = (BASEVIDHEIGHT/2)-16; // 84 // Blue Shell warning - BSWR_X = BASEVIDWIDTH/2; // 270 - BSWR_Y = BASEVIDHEIGHT- 24; // 176 + SPBW_X = BASEVIDWIDTH/2; // 270 + SPBW_Y = BASEVIDHEIGHT- 24; // 176 + // Battle WANTED poster + WANT_X = BASEVIDWIDTH - 55; // 270 + WANT_Y = BASEVIDHEIGHT- 71; // 176 if (splitscreen) // Splitscreen { - ITEM_X = 9; - ITEM_Y = 4; + ITEM_X = 5; + ITEM_Y = 3; LAPS_Y = (BASEVIDHEIGHT/2)-24; POSI_Y = (BASEVIDHEIGHT/2)- 2; + STCD_Y = BASEVIDHEIGHT/4; + MINI_Y = (BASEVIDHEIGHT/2); - BSWR_Y = (BASEVIDHEIGHT/2)-8; + SPBW_Y = (BASEVIDHEIGHT/2)-8; + + WANT_X = BASEVIDWIDTH-8; + WANT_Y = (BASEVIDHEIGHT/2)-12; if (splitscreen > 1) // 3P/4P Small Splitscreen { - ITEM_X = 0; - ITEM_Y = 0; + ITEM_X = -9; + ITEM_Y = -8; LAPS_X = 3; LAPS_Y = (BASEVIDHEIGHT/2)-13; POSI_X = (BASEVIDWIDTH/2)-3; + STCD_X = BASEVIDWIDTH/4; + MINI_X = (3*BASEVIDWIDTH/4); MINI_Y = (3*BASEVIDHEIGHT/4); - BSWR_X = BASEVIDWIDTH/4; + SPBW_X = BASEVIDWIDTH/4; + + WANT_X = (BASEVIDWIDTH/2)-8; if (splitscreen > 2) // 4P-only { @@ -4054,6 +4951,13 @@ static void K_initKartHUD(void) } } } + + if (timeinmap > 113) + hudtrans = cv_translucenthud.value; + else if (timeinmap > 105) + hudtrans = ((((INT32)timeinmap) - 105)*cv_translucenthud.value)/(113-105); + else + hudtrans = 0; } INT32 K_calcSplitFlags(INT32 snapflags) @@ -4094,333 +4998,300 @@ INT32 K_calcSplitFlags(INT32 snapflags) return (splitflags|snapflags); } -static void K_drawKartItemClose(void) -{ - // ITEM_X = BASEVIDWIDTH-50; // 270 - // ITEM_Y = 24; // 24 - - // Why write V_DrawScaledPatch calls over and over when they're all the same? - // Set to 'no draw' just in case. - patch_t *localpatch = kp_nodraw; - INT32 splitflags = K_calcSplitFlags(V_SNAPTOTOP|V_SNAPTORIGHT); - - if (splitscreen) - splitflags = K_calcSplitFlags(V_SNAPTOTOP|V_SNAPTOLEFT); - - /*if () - switch (stplyr->kartstuff[k_itemclose]) - { - case 1: localpatch = kp_neoitemused5; break; - case 3: localpatch = kp_neoitemused4; break; - case 5: localpatch = kp_neoitemused3; break; - case 7: localpatch = kp_neoitemused2; break; - case 9: localpatch = kp_neoitemused1; break; - default: break; - } - else*/ - switch (stplyr->kartstuff[k_itemclose]) - { - case 1: localpatch = kp_itemused5; break; - case 3: localpatch = kp_itemused4; break; - case 5: localpatch = kp_itemused3; break; - case 7: localpatch = kp_itemused2; break; - case 9: localpatch = kp_itemused1; break; - default: break; - } - - if (localpatch != kp_nodraw) - V_DrawScaledPatch(ITEM_X, ITEM_Y, V_HUDTRANS|splitflags, localpatch); -} - -static void K_drawKartItemRoulette(void) +static void K_drawKartItem(void) { // ITEM_X = BASEVIDWIDTH-50; // 270 // ITEM_Y = 24; // 24 // Why write V_DrawScaledPatch calls over and over when they're all the same? // Set to 'no item' just in case. + const UINT8 offset = ((splitscreen > 1) ? 1 : 0); patch_t *localpatch = kp_nodraw; - patch_t *localbg = kp_itembg; - INT32 splitflags = K_calcSplitFlags(V_SNAPTOTOP|V_SNAPTORIGHT); + patch_t *localbg = ((offset) ? kp_itembg[2] : kp_itembg[0]); + patch_t *localinv = ((offset) ? kp_invincibility[((leveltime % (6*3)) / 3) + 7] : kp_invincibility[(leveltime % (7*3)) / 3]); + INT32 splitflags = K_calcSplitFlags(V_SNAPTOTOP|V_SNAPTOLEFT); + const INT32 numberdisplaymin = ((!offset && stplyr->kartstuff[k_itemtype] == KITEM_ORBINAUT) ? 5 : 2); + INT32 itembar = 0; - if (splitscreen) + if (stplyr->kartstuff[k_itemroulette]) { - splitflags = K_calcSplitFlags(V_SNAPTOTOP|V_SNAPTOLEFT); - if (splitscreen > 1) - localbg = kp_itemused1; - } - - /*if () - switch(stplyr->kartstuff[k_itemroulette] % 53) + switch((stplyr->kartstuff[k_itemroulette] % (13*3)) / 3) { // Each case is handled in threes, to give three frames of in-game time to see the item on the roulette - // I'm also skipping by threes for the power order as to what item shows on the roulette - case 0: case 1: case 2: localpatch = kp_electroshield; break; // Electro-Shield - case 3: case 4: case 5: localpatch = kp_triplespeedshoe; break; // Triple Speed Shoe - case 6: case 7: case 8: localpatch = kp_invincibility; break; // Invincibility - case 9: case 10: case 11: localpatch = kp_neobanana; break; // Banana - case 12: case 13: case 14: localpatch = kp_tripleorbinaut; break; // 3x Orbinaut - case 15: case 16: case 17: localpatch = kp_laserwisp; break; // Laser Wisp - case 18: case 19: case 20: localpatch = kp_skghost; break; // S3K Ghost - case 21: case 22: case 23: localpatch = kp_sizeupmonitor; break; // Size-Up Monitor - case 24: case 25: case 26: localpatch = kp_neotriplebanana; break; // Triple Banana - case 27: case 28: case 29: localpatch = kp_orbinaut; break; // 1x Orbinaut - case 30: case 31: case 32: localpatch = kp_specialstagemine; break; // Specialstage Mines - case 33: case 34: case 35: localpatch = kp_doublejaws; break; // 2x Jaws - case 36: case 37: case 38: localpatch = kp_speedshoe; break; // Speed Shoe - case 39: case 40: case 41: localpatch = kp_rocketshoe; break; // Rocket Shoe - case 42: case 43: case 44: localpatch = kp_eggmanmonitor; break; // Eggman Monitor - case 45: case 46: case 47: localpatch = kp_jaws; break; // 1x Jaws - case 48: case 49: case 50: localpatch = kp_deton; break; // Deton - case 51: case 52: case 53: localpatch = kp_sizedownmonitor; break; // Size-Down Monitor + case 0: localpatch = kp_sneaker[offset]; break; // Sneaker + case 1: localpatch = kp_banana[offset]; break; // Banana + case 2: localpatch = kp_orbinaut[3+offset]; break; // Orbinaut + case 3: localpatch = kp_mine[offset]; break; // Mine + case 4: localpatch = kp_grow[offset]; break; // Grow + case 5: localpatch = kp_hyudoro[offset]; break; // Hyudoro + case 6: localpatch = kp_rocketsneaker[offset]; break; // Rocket Sneaker + case 7: localpatch = kp_jawz[offset]; break; // Jawz + case 8: localpatch = kp_selfpropelledbomb[offset]; break; // Self-Propelled Bomb + case 9: localpatch = kp_shrink[offset]; break; // Shrink + case 10: localpatch = localinv; break; // Invincibility + case 11: localpatch = kp_eggman[offset]; break; // Eggman Monitor + case 12: localpatch = kp_ballhog[offset]; break; // Ballhog + case 13: localpatch = kp_thundershield[offset]; break; // Thunder Shield + //case 14: localpatch = kp_pogospring[offset]; break; // Pogo Spring + //case 15: localpatch = kp_kitchensink[offset]; break; // Kitchen Sink default: break; } - else*/ - switch(stplyr->kartstuff[k_itemroulette] % 53) - { - // Each case is handled in threes, to give three frames of in-game time to see the item on the roulette - // I'm also skipping by threes for the power order as to what item shows on the roulette - case 0: case 1: case 2: localpatch = kp_magnet; break; // Magnet - case 3: case 4: case 5: localpatch = kp_triplemushroom; break; // Triple Mushroom - case 6: case 7: case 8: localpatch = kp_star; break; // Star - case 9: case 10: case 11: localpatch = kp_banana; break; // Banana - case 12: case 13: case 14: localpatch = kp_triplegreenshell; break; // Triple Green Shell - case 15: case 16: case 17: localpatch = kp_fireflower; break; // Fire Flower - case 18: case 19: case 20: localpatch = kp_boo; break; // Boo - case 21: case 22: case 23: localpatch = kp_megashroom; break; // Mega Mushroom - case 24: case 25: case 26: localpatch = kp_triplebanana; break; // Triple Banana - case 27: case 28: case 29: localpatch = kp_greenshell; break; // Green Shell - case 30: case 31: case 32: localpatch = kp_bobomb; break; // Bob-omb - case 33: case 34: case 35: localpatch = kp_tripleredshell; break; // Triple Red Shell - case 36: case 37: case 38: localpatch = kp_mushroom; break; // Mushroom - case 39: case 40: case 41: localpatch = kp_goldshroom; break; // Gold Mushroom - case 42: case 43: case 44: localpatch = kp_fakeitem; break; // Fake Item - case 45: case 46: case 47: localpatch = kp_redshell; break; // Red Shell - case 48: case 49: case 50: localpatch = kp_blueshell; break; // Blue Shell - case 51: case 52: case 53: localpatch = kp_lightning; break; // Lightning - default: break; - } - - if (localpatch == kp_nodraw) - return; - - V_DrawScaledPatch(ITEM_X, ITEM_Y, V_HUDTRANS|splitflags, localbg); - V_DrawScaledPatch(ITEM_X, ITEM_Y, V_HUDTRANS|splitflags, localpatch); -} - -static void K_drawKartRetroItem(void) -{ - // ITEM_X = BASEVIDWIDTH-50; // 270 - // ITEM_Y = 24; // 24 - - // Why write V_DrawScaledPatch calls over and over when they're all the same? - // Set to 'no item' just in case. - patch_t *localpatch = kp_nodraw; - patch_t *localbg = kp_itembg; - INT32 X = ITEM_X; - INT32 splitflags = K_calcSplitFlags(V_SNAPTOTOP|V_SNAPTORIGHT); - - if (splitscreen) - { - splitflags = K_calcSplitFlags(V_SNAPTOTOP|V_SNAPTOLEFT); - if (splitscreen > 1) - localbg = kp_itemused1; - } - - // I'm doing this a little weird and drawing mostly in reverse order - // The only actual reason is to make triple/double/single mushrooms line up this way in the code below - // This shouldn't have any actual baring over how it functions - // Boo is first, because we're drawing it on top of the player's current item - if ((stplyr->kartstuff[k_bootaketimer] > 0 || stplyr->kartstuff[k_boostolentimer] > 0) - && (leveltime & 2)) localpatch = kp_boosteal; - else if (stplyr->kartstuff[k_boostolentimer] > 0 && !(leveltime & 2)) localpatch = kp_nodraw; - else if (stplyr->kartstuff[k_kitchensink] == 1) localpatch = kp_kitchensink; - else if (stplyr->kartstuff[k_feather] & 1) localpatch = kp_feather; - else if (stplyr->kartstuff[k_lightning] == 1) localpatch = kp_lightning; - else if (stplyr->kartstuff[k_tripleredshell]) localpatch = kp_tripleredshell; // &8 - else if (stplyr->kartstuff[k_fireflower] == 1) localpatch = kp_fireflower; - else if (stplyr->kartstuff[k_blueshell] == 1) localpatch = kp_blueshell; - else if (stplyr->kartstuff[k_bobomb]) localpatch = kp_bobomb; // &2 - else if (stplyr->kartstuff[k_triplegreenshell]) localpatch = kp_triplegreenshell; // &8 - else if (stplyr->kartstuff[k_redshell]) localpatch = kp_redshell; // &2 - else if (stplyr->kartstuff[k_greenshell]) localpatch = kp_greenshell; // &2 - else if (stplyr->kartstuff[k_banana]) localpatch = kp_banana; // &2 - else if (stplyr->kartstuff[k_fakeitem] & 2) localpatch = kp_fakeitem; - else if (stplyr->kartstuff[k_triplebanana]) localpatch = kp_triplebanana; // &8 - else if (stplyr->kartstuff[k_star] == 1) localpatch = kp_star; - else if (stplyr->kartstuff[k_goldshroom] == 1 - || (stplyr->kartstuff[k_goldshroomtimer] > 1 && (leveltime & 1))) localpatch = kp_goldshroom; - else if (stplyr->kartstuff[k_goldshroomtimer] > 1 && !(leveltime & 1)) localpatch = kp_nodraw; - else if (stplyr->kartstuff[k_megashroom] == 1 - || (stplyr->kartstuff[k_growshrinktimer] > 1 && (leveltime & 1))) localpatch = kp_megashroom; - else if (stplyr->kartstuff[k_growshrinktimer] > 1 && !(leveltime & 1)) localpatch = kp_nodraw; - else if (stplyr->kartstuff[k_mushroom] & 4) localpatch = kp_triplemushroom; - else if (stplyr->kartstuff[k_mushroom] & 2) localpatch = kp_doublemushroom; - else if (stplyr->kartstuff[k_mushroom] == 1) localpatch = kp_mushroom; - else if (stplyr->kartstuff[k_boo] == 1) localpatch = kp_boo; - else if (stplyr->kartstuff[k_magnet] == 1) localpatch = kp_magnet; - - if (localpatch == kp_nodraw) - return; - - V_DrawScaledPatch(X, ITEM_Y, V_HUDTRANS|splitflags, localbg); - V_DrawScaledPatch(X, ITEM_Y, V_HUDTRANS|splitflags, localpatch); -} - -/* -static void K_drawKartNeoItem(void) -{ - // ITEM_X = BASEVIDWIDTH-50; // 270 - // ITEM_Y = 24; // 24 - - // Why write V_DrawScaledPatch calls over and over when they're all the same? - // Set to 'no item' just in case. - patch_t *localpatch = kp_noitem; - - // I'm doing this a little weird and drawing mostly in reverse order - // The only actual reason is to make triple/double/single mushrooms line up this way in the code below - // This shouldn't have any actual baring over how it functions - // Boo is first, because we're drawing it on top of the player's current item - if ((stplyr->kartstuff[k_bootaketimer] > 0 - || stplyr->kartstuff[k_boostolentimer] > 0) && (leveltime & 2)) localpatch = kp_skghoststeal; - else if (stplyr->kartstuff[k_boostolentimer] > 0 && !(leveltime & 2)) localpatch = kp_neonoitem; - else if (stplyr->kartstuff[k_lightning] == 1) localpatch = kp_sizedownmonitor; - else if (stplyr->kartstuff[k_jaws] & 4) localpatch = kp_doublejaws; - else if (stplyr->kartstuff[k_laserwisp] == 1) localpatch = kp_laserwisp; - else if (stplyr->kartstuff[k_blueshell] == 1) localpatch = kp_deton; - else if (stplyr->kartstuff[k_bobomb] & 2) localpatch = kp_specialstagemine; - else if (stplyr->kartstuff[k_triplegreenshell] & 8) localpatch = kp_tripleorbinaut; - else if (stplyr->kartstuff[k_redshell] & 2) localpatch = kp_jaws; - else if (stplyr->kartstuff[k_greenshell] & 2) localpatch = kp_orbinaut; - else if (stplyr->kartstuff[k_banana] & 2) localpatch = kp_neobanana; - else if (stplyr->kartstuff[k_fakeitem] & 2) localpatch = kp_eggmanmonitor; - else if (stplyr->kartstuff[k_triplebanana] & 8) localpatch = kp_neotriplebanana; - else if (stplyr->kartstuff[k_star] == 1) localpatch = kp_invincibility; - else if (stplyr->kartstuff[k_goldshroom] == 1 - || (stplyr->kartstuff[k_goldshroomtimer] > 1 && (leveltime & 1))) localpatch = kp_rocketshoe; - else if (stplyr->kartstuff[k_goldshroomtimer] > 1 && !(leveltime & 1)) localpatch = kp_neonoitem; - else if (stplyr->kartstuff[k_megashroom] == 1 - || (stplyr->kartstuff[k_growshrinktimer] > 1 && (leveltime & 1))) localpatch = kp_sizeupmonitor; - else if (stplyr->kartstuff[k_growshrinktimer] > 1 && !(leveltime & 1)) localpatch = kp_neonoitem; - else if (stplyr->kartstuff[k_mushroom] & 4) localpatch = kp_triplespeedshoe; - else if (stplyr->kartstuff[k_mushroom] & 2) localpatch = kp_doublespeedshoe; - else if (stplyr->kartstuff[k_mushroom] == 1) localpatch = kp_speedshoe; - else if (stplyr->kartstuff[k_boo] & 8) localpatch = kp_skghost; - else if (stplyr->kartstuff[k_magnet] & 8) localpatch = kp_electroshield; - - V_DrawScaledPatch(ITEM_X, ITEM_Y, V_SNAPTORIGHT|V_HUDTRANSHALF, localpatch); -} -*/ - -/* -static void K_DrawKartTripleItem(void) -{ - // TRIP_X = 143; // 143 - // TRIP_Y = BASEVIDHEIGHT-34; // 166 - - // Why write V_DrawScaledPatch calls over and over when they're all the same? - // Set to 'no draw' just in case. - patch_t *localpatch = kp_nodraw; - INT32 thisitem; - - if () - { - thisitem = stplyr->kartstuff[k_triplebanana]; - if (thisitem & 1) localpatch = kp_singleneobananaicon; - else if (thisitem & 2) localpatch = kp_doubleneobananaicon; - else if (thisitem & 4) localpatch = kp_tripleneobananaicon; - - thisitem = stplyr->kartstuff[k_triplegreenshell]; - if (thisitem & 1) localpatch = kp_singleorbitauricon; - else if (thisitem & 2) localpatch = kp_doubleorbitauricon; - else if (thisitem & 4) localpatch = kp_tripleorbitauricon; - - thisitem = stplyr->kartstuff[k_jaws]; - if (thisitem & 1) localpatch = kp_singlejawsicon; - else if (thisitem & 2) localpatch = kp_doublejawsicon; } else { - thisitem = stplyr->kartstuff[k_triplebanana]; - if (thisitem & 4) localpatch = kp_triplebananaicon; - else if (thisitem & 2) localpatch = kp_doublebananaicon; - else if (thisitem & 1) localpatch = kp_singlebananaicon; + // I'm doing this a little weird and drawing mostly in reverse order + // The only actual reason is to make sneakers line up this way in the code below + // This shouldn't have any actual baring over how it functions + // Hyudoro is first, because we're drawing it on top of the player's current item + if (stplyr->kartstuff[k_stolentimer] > 0) + { + if (leveltime & 2) + localpatch = kp_hyudoro[offset]; + else + localpatch = kp_nodraw; + } + else if ((stplyr->kartstuff[k_stealingtimer] > 0) && (leveltime & 2)) + { + localpatch = kp_hyudoro[offset]; + } + else if (stplyr->kartstuff[k_eggmanexplode] > 1) + { + if (leveltime & 1) + localpatch = kp_eggman[offset]; + else + localpatch = kp_nodraw; + } + else if (stplyr->kartstuff[k_rocketsneakertimer] > 1) + { + itembar = stplyr->kartstuff[k_rocketsneakertimer]; + if (leveltime & 1) + localpatch = kp_rocketsneaker[offset]; + else + localpatch = kp_nodraw; + } + else if (stplyr->kartstuff[k_growshrinktimer] > 1) + { + if (leveltime & 1) + localpatch = kp_grow[offset]; + else + localpatch = kp_nodraw; + } + else if (stplyr->kartstuff[k_sadtimer] > 0) + { + if (leveltime & 2) + localpatch = kp_sadface[offset]; + else + localpatch = kp_nodraw; + } + else + { + if (stplyr->kartstuff[k_itemamount] <= 0) + return; - thisitem = stplyr->kartstuff[k_triplegreenshell]; - if (thisitem & 4) localpatch = kp_triplegreenshellicon; - else if (thisitem & 2) localpatch = kp_doublegreenshellicon; - else if (thisitem & 1) localpatch = kp_singlegreenshellicon; - - thisitem = stplyr->kartstuff[k_tripleredshell]; - if (thisitem & 4) localpatch = kp_tripleredshellicon; - else if (thisitem & 2) localpatch = kp_doubleredshellicon; - else if (thisitem & 1) localpatch = kp_singleredshellicon; - - if (stplyr->kartstuff[k_banana] & 1) localpatch = kp_singlebananaicon; - if (stplyr->kartstuff[k_greenshell] & 1) localpatch = kp_singlegreenshellicon; - if (stplyr->kartstuff[k_redshell] & 1) localpatch = kp_singleredshellicon; + switch(stplyr->kartstuff[k_itemtype]) + { + case KITEM_SNEAKER: localpatch = kp_sneaker[offset]; break; + case KITEM_ROCKETSNEAKER: localpatch = kp_rocketsneaker[offset]; break; + case KITEM_INVINCIBILITY: localpatch = localinv; localbg = kp_itembg[offset+1]; break; + case KITEM_BANANA: localpatch = kp_banana[offset]; break; + case KITEM_EGGMAN: localpatch = kp_eggman[offset]; break; + case KITEM_ORBINAUT: + localpatch = kp_orbinaut[(offset ? 4 + : min(stplyr->kartstuff[k_itemamount]-1, 3))]; + break; + case KITEM_JAWZ: localpatch = kp_jawz[offset]; break; + case KITEM_MINE: localpatch = kp_mine[offset]; break; + case KITEM_BALLHOG: localpatch = kp_ballhog[offset]; break; + case KITEM_SPB: localpatch = kp_selfpropelledbomb[offset]; break; + case KITEM_GROW: localpatch = kp_grow[offset]; break; + case KITEM_SHRINK: localpatch = kp_shrink[offset]; break; + case KITEM_THUNDERSHIELD: localpatch = kp_thundershield[offset]; break; + case KITEM_HYUDORO: localpatch = kp_hyudoro[offset]; break; + case KITEM_POGOSPRING: localpatch = kp_pogospring[offset]; break; + case KITEM_KITCHENSINK: localpatch = kp_kitchensink[offset]; break; + case KITEM_SAD: localpatch = kp_sadface[offset]; break; + default: return; + } + } } - if (localpatch != kp_nodraw) - V_DrawScaledPatch(TRIP_X, TRIP_Y, V_SNAPTOBOTTOM, localpatch); + V_DrawScaledPatch(ITEM_X, ITEM_Y, V_HUDTRANS|splitflags, localbg); + + // Then, the numbers: + if (stplyr->kartstuff[k_itemamount] >= numberdisplaymin && !stplyr->kartstuff[k_itemroulette]) + { + V_DrawScaledPatch(ITEM_X, ITEM_Y, V_HUDTRANS|splitflags, kp_itemmulsticker[offset]); + V_DrawScaledPatch(ITEM_X, ITEM_Y, V_HUDTRANS|splitflags, localpatch); + if (offset) + V_DrawString(ITEM_X+24, ITEM_Y+31, V_ALLOWLOWERCASE|V_HUDTRANS|splitflags, va("x%d", stplyr->kartstuff[k_itemamount])); + else + { + V_DrawScaledPatch(ITEM_X+28, ITEM_Y+41, V_HUDTRANS|splitflags, kp_itemx); + V_DrawKartString(ITEM_X+38, ITEM_Y+36, V_HUDTRANS|splitflags, va("%d", stplyr->kartstuff[k_itemamount])); + } + } + else + V_DrawScaledPatch(ITEM_X, ITEM_Y, V_HUDTRANS|splitflags, localpatch); + + // Extensible meter, currently only used for rocket sneaker... + if (itembar && hudtrans) + { + const INT32 barlength = (splitscreen > 1 ? 12 : 24); + const INT32 max = itemtime; // timer's normal highest value + const INT32 length = min(barlength, (itembar * barlength) / max); + const INT32 height = (offset ? 1 : 2); + const INT32 x = (offset ? 17 : 11), y = (offset ? 27 : 35); + + V_DrawScaledPatch(ITEM_X+x, ITEM_Y+y, V_HUDTRANS|splitflags, kp_itemtimer[offset]); + // The left dark "AA" edge + V_DrawFill(ITEM_X+x+1, ITEM_Y+y+1, (length == 2 ? 2 : 1), height, 12|splitflags); + // The bar itself + if (length > 2) + { + V_DrawFill(ITEM_X+x+length, ITEM_Y+y+1, 1, height, 12|splitflags); // the right one + if (height == 2) + V_DrawFill(ITEM_X+x+2, ITEM_Y+y+2, length-2, 1, 8|splitflags); // the dulled underside + V_DrawFill(ITEM_X+x+2, ITEM_Y+y+1, length-2, 1, 120|splitflags); // the shine + } + } + + // Quick Eggman numbers + if (stplyr->kartstuff[k_eggmanexplode] > 1 /*&& stplyr->kartstuff[k_eggmanexplode] <= 3*TICRATE*/) + V_DrawScaledPatch(ITEM_X+17, ITEM_Y+13, V_HUDTRANS|splitflags, kp_eggnum[min(3, G_TicsToSeconds(stplyr->kartstuff[k_eggmanexplode]))]); } -*/ static void K_drawKartTimestamp(void) { // TIME_X = BASEVIDWIDTH-124; // 196 // TIME_Y = 6; // 6 - INT32 TIME_XB; - INT32 splitflags = K_calcSplitFlags(V_SNAPTOTOP|V_SNAPTOLEFT); + INT32 TIME_XB, splitflags = V_HUDTRANS|K_calcSplitFlags(V_SNAPTOTOP|V_SNAPTORIGHT); + tic_t drawtime = stplyr->realtime; - V_DrawScaledPatch(TIME_X, TIME_Y, V_HUDTRANS|splitflags, kp_timestickerwide); + if (cv_timelimit.value && timelimitintics > 0) + { + if (drawtime >= timelimitintics) + drawtime = 0; + else + drawtime = timelimitintics - drawtime; + } + + V_DrawScaledPatch(TIME_X, TIME_Y, splitflags, kp_timestickerwide); TIME_XB = TIME_X+33; - if (stplyr->realtime/(60*TICRATE) < 100) // 99:99:99 only + if (drawtime/(60*TICRATE) < 100) // 99:99:99 only { // zero minute - if (stplyr->realtime/(60*TICRATE) < 10) + if (drawtime/(60*TICRATE) < 10) { - V_DrawKartString(TIME_XB, TIME_Y+3, V_HUDTRANS|splitflags, va("0")); + V_DrawKartString(TIME_XB, TIME_Y+3, splitflags, va("0")); // minutes time 0 __ __ - V_DrawKartString(TIME_XB+12, TIME_Y+3, V_HUDTRANS|splitflags, va("%d", stplyr->realtime/(60*TICRATE))); + V_DrawKartString(TIME_XB+12, TIME_Y+3, splitflags, va("%d", drawtime/(60*TICRATE))); } // minutes time 0 __ __ else - V_DrawKartString(TIME_XB, TIME_Y+3, V_HUDTRANS|splitflags, va("%d", stplyr->realtime/(60*TICRATE))); + V_DrawKartString(TIME_XB, TIME_Y+3, splitflags, va("%d", drawtime/(60*TICRATE))); // apostrophe location _'__ __ - V_DrawKartString(TIME_XB+24, TIME_Y+3, V_HUDTRANS|splitflags, va("'")); + V_DrawKartString(TIME_XB+24, TIME_Y+3, splitflags, va("'")); // zero second _ 0_ __ - if ((stplyr->realtime/TICRATE % 60) < 10) + if ((drawtime/TICRATE % 60) < 10) { - V_DrawKartString(TIME_XB+36, TIME_Y+3, V_HUDTRANS|splitflags, va("0")); + V_DrawKartString(TIME_XB+36, TIME_Y+3, splitflags, va("0")); // seconds time _ _0 __ - V_DrawKartString(TIME_XB+48, TIME_Y+3, V_HUDTRANS|splitflags, va("%d", stplyr->realtime/TICRATE % 60)); + V_DrawKartString(TIME_XB+48, TIME_Y+3, splitflags, va("%d", drawtime/TICRATE % 60)); } // zero second _ 00 __ else - V_DrawKartString(TIME_XB+36, TIME_Y+3, V_HUDTRANS|splitflags, va("%d", stplyr->realtime/TICRATE % 60)); + V_DrawKartString(TIME_XB+36, TIME_Y+3, splitflags, va("%d", drawtime/TICRATE % 60)); // quotation mark location _ __"__ - V_DrawKartString(TIME_XB+60, TIME_Y+3, V_HUDTRANS|splitflags, va("\"")); + V_DrawKartString(TIME_XB+60, TIME_Y+3, splitflags, va("\"")); // zero tick _ __ 0_ - if (G_TicsToCentiseconds(stplyr->realtime) < 10) + if (G_TicsToCentiseconds(drawtime) < 10) { - V_DrawKartString(TIME_XB+72, TIME_Y+3, V_HUDTRANS|splitflags, va("0")); + V_DrawKartString(TIME_XB+72, TIME_Y+3, splitflags, va("0")); // tics _ __ _0 - V_DrawKartString(TIME_XB+84, TIME_Y+3, V_HUDTRANS|splitflags, va("%d", G_TicsToCentiseconds(stplyr->realtime))); + V_DrawKartString(TIME_XB+84, TIME_Y+3, splitflags, va("%d", G_TicsToCentiseconds(drawtime))); } // zero tick _ __ 00 - if (G_TicsToCentiseconds(stplyr->realtime) >= 10) - V_DrawKartString(TIME_XB+72, TIME_Y+3, V_HUDTRANS|splitflags, va("%d", G_TicsToCentiseconds(stplyr->realtime))); + if (G_TicsToCentiseconds(drawtime) >= 10) + V_DrawKartString(TIME_XB+72, TIME_Y+3, splitflags, va("%d", G_TicsToCentiseconds(drawtime))); + } + else if ((drawtime/TICRATE) & 1) + V_DrawKartString(TIME_XB, TIME_Y+3, splitflags, va("99'59\"99")); + + if (modeattacking) // emblem time! + { + INT32 workx = TIME_XB + 96, worky = TIME_Y+18; + SINT8 curemb = 0; + patch_t *emblempic[3] = {NULL, NULL, NULL}; + UINT8 *emblemcol[3] = {NULL, NULL, NULL}; + + emblem_t *emblem = M_GetLevelEmblems(gamemap); + while (emblem) + { + char targettext[9]; + + switch (emblem->type) + { + case ET_TIME: + { + static boolean canplaysound = true; + tic_t timetoreach = emblem->var; + + if (emblem->collected) + { + emblempic[curemb] = W_CachePatchName(M_GetEmblemPatch(emblem), PU_CACHE); + emblemcol[curemb] = R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(emblem), GTC_CACHE); + if (++curemb == 3) + break; + goto bademblem; + } + + snprintf(targettext, 9, "%i:%02i.%02i", + G_TicsToMinutes(timetoreach, false), + G_TicsToSeconds(timetoreach), + G_TicsToCentiseconds(timetoreach)); + + if (stplyr->realtime > timetoreach) + { + splitflags = (splitflags &~ V_HUDTRANS)|V_HUDTRANSHALF; + if (canplaysound) + { + S_StartSound(NULL, sfx_s3k72); //sfx_s26d); -- you STOLE fizzy lifting drinks + canplaysound = false; + } + } + else if (!canplaysound) + canplaysound = true; + + targettext[8] = 0; + } + break; + default: + goto bademblem; + } + + V_DrawRightAlignedString(workx, worky, splitflags, targettext); + workx -= 69; // i SWEAR i wasn't aiming for this + V_DrawSmallScaledPatch(workx + 4, worky, splitflags, W_CachePatchName("NEEDIT", PU_CACHE)); + + break; + + bademblem: + emblem = M_GetLevelEmblems(-1); + } + + while (curemb--) + { + workx -= 16; + V_DrawSmallMappedPatch(workx + 4, worky, splitflags, emblempic[curemb], emblemcol[curemb]); + } } - else - V_DrawKartString(TIME_XB, TIME_Y+3, V_HUDTRANS|splitflags, va("99'59\"99")); } static void K_DrawKartPositionNum(INT32 num) @@ -4435,7 +5306,7 @@ static void K_DrawKartPositionNum(INT32 num) INT32 splitflags = K_calcSplitFlags(V_SNAPTOBOTTOM|V_SNAPTORIGHT); if (stplyr->kartstuff[k_positiondelay] || stplyr->exiting) - scale = FixedMul(scale, 3*FRACUNIT/2); + scale *= 2; if (splitscreen) scale /= 2; @@ -4454,36 +5325,7 @@ static void K_DrawKartPositionNum(INT32 num) while (num) { if (stplyr->exiting && num == 1) // 1st place winner? You get rainbows!! - { - // Alternate frame every three frames - switch (leveltime % 21) - { - case 1: case 2: case 3: - localpatch = kp_winnernum[0]; - break; - case 4: case 5: case 6: - localpatch = kp_winnernum[1]; - break; - case 7: case 8: case 9: - localpatch = kp_winnernum[2]; - break; - case 10: case 11: case 12: - localpatch = kp_winnernum[3]; - break; - case 13: case 14: case 15: - localpatch = kp_winnernum[4]; - break; - case 16: case 17: case 18: - localpatch = kp_winnernum[5]; - break; - case 19: case 20: case 21: - localpatch = kp_winnernum[6]; - break; - default: - localpatch = kp_positionnum[1][0]; - break; - } - } + localpatch = kp_winnernum[(leveltime % (NUMWINFRAMES*3)) / 3]; else if (stplyr->laps+1 >= cv_numlaps.value || stplyr->exiting) // Check for the final lap, or won { // Alternate frame every three frames @@ -4522,7 +5364,7 @@ static void K_DrawKartPositionNum(INT32 num) } } -static void K_drawKartPositionFaces(void) +static boolean K_drawKartPositionFaces(void) { // FACE_X = 15; // 15 // FACE_Y = 72; // 72 @@ -4531,41 +5373,47 @@ static void K_drawKartPositionFaces(void) INT32 i, j, ranklines; boolean completed[MAXPLAYERS]; INT32 rankplayer[MAXPLAYERS]; - INT32 rankcolor[MAXPLAYERS]; - INT32 myplayer; - INT32 balloonx; + INT32 bumperx, numplayersingame = 0; UINT8 *colormap; patch_t *localpatch = kp_facenull; ranklines = 0; memset(completed, 0, sizeof (completed)); memset(rankplayer, 0, sizeof (rankplayer)); - memset(rankcolor, 0, sizeof (rankcolor)); - myplayer = demoplayback ? displayplayer : consoleplayer; for (i = 0; i < MAXPLAYERS; i++) + { rankplayer[i] = -1; - for (j = 0; j < MAXPLAYERS; j++) - { - if (!playeringame[j] || players[j].spectator || !players[j].mo) + if (!playeringame[i] || players[i].spectator || !players[i].mo) continue; + numplayersingame++; + } + + if (numplayersingame <= 1) + return true; + + for (j = 0; j < numplayersingame; j++) + { for (i = 0; i < MAXPLAYERS; i++) { if (playeringame[i] && completed[i] == false && players[i].mo && !players[i].spectator && (rankplayer[ranklines] < 0 || players[i].kartstuff[k_position] < players[rankplayer[ranklines]].kartstuff[k_position])) { rankplayer[ranklines] = i; - rankcolor[ranklines] = players[i].skincolor; } } - completed[rankplayer[ranklines]] = true; + i = rankplayer[ranklines]; + + completed[i] = true; + + if (ranklines == 4) + break; // Only draw the top 4 players + ranklines++; } - if (ranklines > 4) ranklines = 4; // Only draw the top 4 players - Y -= (9*ranklines); for (i = 0; i < ranklines; i++) @@ -4573,70 +5421,23 @@ static void K_drawKartPositionFaces(void) if (players[rankplayer[i]].spectator) continue; // Spectators are ignored if (!players[rankplayer[i]].mo) continue; - balloonx = FACE_X+18; + bumperx = FACE_X+18; - if (rankcolor[i] == 0) - { - colormap = colormaps; - if (rankplayer[i] != myplayer) - { - V_DrawSmallTranslucentPatch(FACE_X, Y, V_HUDTRANS|V_SNAPTOLEFT, faceprefix[players[rankplayer[i]].skin]); - if (G_BattleGametype() && players[rankplayer[i]].kartstuff[k_balloon] > 0) - { - for (j = 0; j < players[rankplayer[i]].kartstuff[k_balloon]; j++) - { - V_DrawSmallTranslucentPatch(balloonx, Y+10, V_HUDTRANS|V_SNAPTOLEFT, kp_rankballoon); - balloonx += 3; - } - } - } - else - { - V_DrawSmallScaledPatch(FACE_X, Y, V_HUDTRANS|V_SNAPTOLEFT, faceprefix[players[rankplayer[i]].skin]); - if (G_BattleGametype() && players[rankplayer[i]].kartstuff[k_balloon] > 0) - { - for (j = 0; j < players[rankplayer[i]].kartstuff[k_balloon]; j++) - { - V_DrawSmallScaledPatch(balloonx, Y+10, V_HUDTRANS|V_SNAPTOLEFT, kp_rankballoon); - balloonx += 3; - } - } - } - } - else + if (players[rankplayer[i]].mo->color) { colormap = R_GetTranslationColormap(players[rankplayer[i]].skin, players[rankplayer[i]].mo->color, GTC_CACHE); if (players[rankplayer[i]].mo->colorized) - { - colormap = R_GetTranslationColormap(TC_STARMAN, players[rankplayer[i]].mo->color, GTC_CACHE); - } + colormap = R_GetTranslationColormap(TC_RAINBOW, players[rankplayer[i]].mo->color, GTC_CACHE); else - { colormap = R_GetTranslationColormap(players[rankplayer[i]].skin, players[rankplayer[i]].mo->color, GTC_CACHE); - } - if (rankplayer[i] != myplayer) + V_DrawSmallMappedPatch(FACE_X, Y, V_HUDTRANS|V_SNAPTOLEFT, faceprefix[players[rankplayer[i]].skin], colormap); + if (G_BattleGametype() && players[rankplayer[i]].kartstuff[k_bumper] > 0) { - V_DrawSmallTranslucentMappedPatch(FACE_X, Y, V_HUDTRANS|V_SNAPTOLEFT, faceprefix[players[rankplayer[i]].skin], colormap); - if (G_BattleGametype() && players[rankplayer[i]].kartstuff[k_balloon] > 0) + for (j = 0; j < players[rankplayer[i]].kartstuff[k_bumper]; j++) { - for (j = 0; j < players[rankplayer[i]].kartstuff[k_balloon]; j++) - { - V_DrawSmallTranslucentMappedPatch(balloonx, Y+10, V_HUDTRANS|V_SNAPTOLEFT, kp_rankballoon, colormap); - balloonx += 3; - } - } - } - else - { - V_DrawSmallMappedPatch(FACE_X, Y, V_HUDTRANS|V_SNAPTOLEFT, faceprefix[players[rankplayer[i]].skin], colormap); - if (G_BattleGametype() && players[rankplayer[i]].kartstuff[k_balloon] > 0) - { - for (j = 0; j < players[rankplayer[i]].kartstuff[k_balloon]; j++) - { - V_DrawSmallMappedPatch(balloonx, Y+10, V_HUDTRANS|V_SNAPTOLEFT, kp_rankballoon, colormap); - balloonx += 3; - } + V_DrawSmallMappedPatch(bumperx, Y+10, V_HUDTRANS|V_SNAPTOLEFT, kp_rankbumper, colormap); + bumperx += 3; } } } @@ -4651,23 +5452,15 @@ static void K_drawKartPositionFaces(void) default: break; } - if (rankplayer[i] != myplayer) - { - if (G_BattleGametype() && players[rankplayer[i]].kartstuff[k_balloon] <= 0) - V_DrawSmallTranslucentPatch(FACE_X-2, Y, V_HUDTRANS|V_SNAPTOLEFT, kp_ranknoballoons); - else - V_DrawSmallTranslucentPatch(FACE_X, Y, V_HUDTRANS|V_SNAPTOLEFT, localpatch); - } + if (G_BattleGametype() && players[rankplayer[i]].kartstuff[k_bumper] <= 0) + V_DrawSmallScaledPatch(FACE_X-2, Y, V_HUDTRANS|V_SNAPTOLEFT, kp_ranknobumpers); else - { - if (G_BattleGametype() && players[rankplayer[i]].kartstuff[k_balloon] <= 0) - V_DrawSmallScaledPatch(FACE_X-2, Y, V_HUDTRANS|V_SNAPTOLEFT, kp_ranknoballoons); - else - V_DrawSmallScaledPatch(FACE_X, Y, V_HUDTRANS|V_SNAPTOLEFT, localpatch); - } + V_DrawSmallScaledPatch(FACE_X, Y, V_HUDTRANS|V_SNAPTOLEFT, localpatch); Y += 18; } + + return false; } static void K_drawKartLaps(void) @@ -4699,74 +5492,74 @@ static void K_drawKartSpeedometer(void) fixed_t convSpeed; INT32 splitflags = K_calcSplitFlags(V_SNAPTOBOTTOM|V_SNAPTOLEFT); - if (cv_speedometer.value == 1) + if (cv_kartspeedometer.value == 1) // Kilometers { convSpeed = FixedDiv(FixedMul(stplyr->speed, 142371), mapheaderinfo[gamemap-1]->mobj_scale)/FRACUNIT; // 2.172409058 V_DrawKartString(SPDM_X, SPDM_Y, V_HUDTRANS|splitflags, va("%3d km/h", convSpeed)); } - else if (cv_speedometer.value == 2) + else if (cv_kartspeedometer.value == 2) // Miles { convSpeed = FixedDiv(FixedMul(stplyr->speed, 88465), mapheaderinfo[gamemap-1]->mobj_scale)/FRACUNIT; // 1.349868774 V_DrawKartString(SPDM_X, SPDM_Y, V_HUDTRANS|splitflags, va("%3d mph", convSpeed)); } - else if (cv_speedometer.value == 3) + else if (cv_kartspeedometer.value == 3) // Fracunits { convSpeed = FixedDiv(stplyr->speed, mapheaderinfo[gamemap-1]->mobj_scale)/FRACUNIT; V_DrawKartString(SPDM_X, SPDM_Y, V_HUDTRANS|splitflags, va("%3d fu/t", convSpeed)); } } -static void K_drawKartBalloonsOrKarma(void) +static void K_drawKartBumpersOrKarma(void) { UINT8 *colormap = R_GetTranslationColormap(TC_DEFAULT, stplyr->skincolor, 0); INT32 splitflags = K_calcSplitFlags(V_SNAPTOBOTTOM|V_SNAPTOLEFT); if (splitscreen > 1) { - if (stplyr->kartstuff[k_balloon] <= 0) + if (stplyr->kartstuff[k_bumper] <= 0) { V_DrawMappedPatch(LAPS_X, LAPS_Y-1, V_HUDTRANS|splitflags, kp_splitkarmabomb, colormap); V_DrawString(LAPS_X+13, LAPS_Y+1, V_HUDTRANS|splitflags, va("%d/3", stplyr->kartstuff[k_comebackpoints])); } else { - V_DrawMappedPatch(LAPS_X, LAPS_Y-1, V_HUDTRANS|splitflags, kp_rankballoon, colormap); - V_DrawString(LAPS_X+13, LAPS_Y+1, V_HUDTRANS|splitflags, va("%d/%d", stplyr->kartstuff[k_balloon], cv_kartballoons.value)); + V_DrawMappedPatch(LAPS_X, LAPS_Y-1, V_HUDTRANS|splitflags, kp_rankbumper, colormap); + V_DrawString(LAPS_X+13, LAPS_Y+1, V_HUDTRANS|splitflags, va("%d/%d", stplyr->kartstuff[k_bumper], cv_kartbumpers.value)); } } else { - if (stplyr->kartstuff[k_balloon] <= 0) + if (stplyr->kartstuff[k_bumper] <= 0) { V_DrawMappedPatch(LAPS_X, LAPS_Y, V_HUDTRANS|splitflags, kp_karmasticker, colormap); V_DrawKartString(LAPS_X+59, LAPS_Y+3, V_HUDTRANS|splitflags, va("%d/3", stplyr->kartstuff[k_comebackpoints])); } else { - if (stplyr->kartstuff[k_balloon] > 9 && cv_kartballoons.value > 9) - V_DrawMappedPatch(LAPS_X, LAPS_Y, V_HUDTRANS|splitflags, kp_balloonstickerwide, colormap); + if (stplyr->kartstuff[k_bumper] > 9 && cv_kartbumpers.value > 9) + V_DrawMappedPatch(LAPS_X, LAPS_Y, V_HUDTRANS|splitflags, kp_bumperstickerwide, colormap); else - V_DrawMappedPatch(LAPS_X, LAPS_Y, V_HUDTRANS|splitflags, kp_balloonsticker, colormap); - V_DrawKartString(LAPS_X+47, LAPS_Y+3, V_HUDTRANS|splitflags, va("%d/%d", stplyr->kartstuff[k_balloon], cv_kartballoons.value)); + V_DrawMappedPatch(LAPS_X, LAPS_Y, V_HUDTRANS|splitflags, kp_bumpersticker, colormap); + V_DrawKartString(LAPS_X+47, LAPS_Y+3, V_HUDTRANS|splitflags, va("%d/%d", stplyr->kartstuff[k_bumper], cv_kartbumpers.value)); } } } -static void K_drawBlueShellWarning(void) +static void K_drawSPBWarning(void) { patch_t *localpatch = kp_nodraw; INT32 splitflags = K_calcSplitFlags(V_SNAPTOBOTTOM); if (!(stplyr->kartstuff[k_deathsentence] > 0 - || (blueshellincoming > 0 && blueshellincoming < 2*TICRATE && stplyr->kartstuff[k_position] == 1))) + || (spbincoming > 0 && spbincoming < 2*TICRATE && stplyr->kartstuff[k_position] == 1))) return; if (leveltime % 8 > 3) - localpatch = kp_bswarning[1]; + localpatch = kp_spbwarning[1]; else - localpatch = kp_bswarning[0]; + localpatch = kp_spbwarning[0]; - V_DrawScaledPatch(BSWR_X, BSWR_Y, splitflags, localpatch); + V_DrawScaledPatch(SPBW_X, SPBW_Y, splitflags, localpatch); } fixed_t K_FindCheckX(fixed_t px, fixed_t py, angle_t ang, fixed_t mx, fixed_t my) @@ -4797,16 +5590,73 @@ fixed_t K_FindCheckX(fixed_t px, fixed_t py, angle_t ang, fixed_t mx, fixed_t my return x; } +static void K_drawKartWanted(void) +{ + UINT8 i, numwanted = 0; + UINT8 *colormap = NULL; + + if (splitscreen) // Can't fit the poster on screen, sadly + { + if (K_IsPlayerWanted(stplyr) && leveltime % 10 > 3) + V_DrawRightAlignedString(WANT_X, WANT_Y, K_calcSplitFlags(V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_HUDTRANS|V_REDMAP), "WANTED"); + return; + } + + for (i = 0; i < 4; i++) + { + if (battlewanted[i] == -1) + break; + numwanted++; + } + + if (numwanted <= 0) + return; + + if (battlewanted[0] != -1) + colormap = R_GetTranslationColormap(0, players[battlewanted[0]].skincolor, GTC_CACHE); + V_DrawFixedPatch(WANT_X< 1) + y += 17; + } + + if (players[battlewanted[i]].skincolor == 0) + V_DrawFixedPatch(x<skin], NULL); + else + { + colormap = R_GetTranslationColormap(TC_RAINBOW, p->skincolor, GTC_CACHE); + V_DrawFixedPatch(x<skin], colormap); + } + } +} + static void K_drawKartPlayerCheck(void) { INT32 i; UINT8 *colormap; INT32 x; - patch_t *localpatch; INT32 splitflags = K_calcSplitFlags(V_SNAPTOBOTTOM); - if (!(stplyr->mo)) + if (!stplyr->mo || stplyr->spectator) return; if (stplyr->awayviewtics) @@ -4817,31 +5667,22 @@ static void K_drawKartPlayerCheck(void) for (i = 0; i < MAXPLAYERS; i++) { + UINT8 pnum = 0; + + if (&players[i] == stplyr) + continue; if (!playeringame[i] || players[i].spectator) continue; if (!players[i].mo) continue; - if (&players[i] == stplyr) - continue; - if ((players[i].kartstuff[k_startimer] <= 0) && (leveltime & 2)) - { - if (players[i].kartstuff[k_megashroom] || players[i].kartstuff[k_growshrinktimer] > 0) - localpatch = kp_checkmegaw; - else if (players[i].kartstuff[k_star] || players[i].kartstuff[k_startimer]) - localpatch = kp_checkstarw; - else - localpatch = kp_checkw; - } - else - { - if (players[i].kartstuff[k_megashroom] || players[i].kartstuff[k_growshrinktimer] > 0) - localpatch = kp_checkmega; - else if (players[i].kartstuff[k_star] || players[i].kartstuff[k_startimer]) - localpatch = kp_checkstar; - else - localpatch = kp_check; - } + if ((players[i].kartstuff[k_invincibilitytimer] <= 0) && (leveltime & 2)) + pnum++; // white frames + + if (players[i].kartstuff[k_itemtype] == KITEM_GROW || players[i].kartstuff[k_growshrinktimer] > 0) + pnum += 4; + else if (players[i].kartstuff[k_itemtype] == KITEM_INVINCIBILITY || players[i].kartstuff[k_invincibilitytimer]) + pnum += 2; x = K_FindCheckX(stplyr->mo->x, stplyr->mo->y, stplyr->mo->angle, players[i].mo->x, players[i].mo->y); if (x <= 320 && x >= 0) @@ -4852,7 +5693,7 @@ static void K_drawKartPlayerCheck(void) x = 306; colormap = R_GetTranslationColormap(TC_DEFAULT, players[i].mo->color, 0); - V_DrawMappedPatch(x, CHEK_Y, V_HUDTRANS|splitflags, localpatch, colormap); + V_DrawMappedPatch(x, CHEK_Y, V_HUDTRANS|splitflags, kp_check[pnum], colormap); } } } @@ -4886,7 +5727,7 @@ void K_ReloadSkinIconGraphics(void) K_LoadIconGraphics(skins[i].iconprefix, i); } -static void K_drawKartMinimapHead(player_t *player, INT32 x, INT32 y, INT32 flags, patch_t *AutomapPic) +static void K_drawKartMinimapHead(mobj_t *mo, INT32 x, INT32 y, INT32 flags, patch_t *AutomapPic) { // amnum xpos & ypos are the icon's speed around the HUD. // The number being divided by is for how fast it moves. @@ -4895,6 +5736,8 @@ static void K_drawKartMinimapHead(player_t *player, INT32 x, INT32 y, INT32 flag // am xpos & ypos are the icon's starting position. Withouht // it, they wouldn't 'spawn' on the top-right side of the HUD. + UINT8 skin = 0; + fixed_t amnumxpos, amnumypos; INT32 amxpos, amypos; @@ -4905,6 +5748,9 @@ static void K_drawKartMinimapHead(player_t *player, INT32 x, INT32 y, INT32 flag fixed_t xoffset, yoffset; fixed_t xscale, yscale, zoom; + if (mo->skin) + skin = ((skin_t*)mo->skin)-skins; + maxx = maxy = INT32_MAX; minx = miny = INT32_MIN; minx = bsp->bbox[0][BOXLEFT]; @@ -4941,32 +5787,32 @@ static void K_drawKartMinimapHead(player_t *player, INT32 x, INT32 y, INT32 flag yscale = FixedDiv(AutomapPic->height, mapheight); zoom = FixedMul(min(xscale, yscale), FRACUNIT-FRACUNIT/20); - amnumxpos = (FixedMul(player->mo->x, zoom) - FixedMul(xoffset, zoom)); - amnumypos = -(FixedMul(player->mo->y, zoom) - FixedMul(yoffset, zoom)); - - amxpos = amnumxpos + ((x + AutomapPic->width/2 - (iconprefix[player->skin]->width/2))<height/2 - (iconprefix[player->skin]->height/2))<x, zoom) - FixedMul(xoffset, zoom)); + amnumypos = -(FixedMul(mo->y, zoom) - FixedMul(yoffset, zoom)); if (mirrormode) + amnumxpos = -amnumxpos; + + amxpos = amnumxpos + ((x + AutomapPic->width/2 - (iconprefix[skin]->width/2))<height/2 - (iconprefix[skin]->height/2))<width/2 + (iconprefix[player->skin]->width/2))<width/2 + (iconprefix[skin]->width/2))<skincolor) // 'default' color - V_DrawSciencePatch(amxpos, amypos, flags, iconprefix[player->skin], FRACUNIT); + if (!mo->color) // 'default' color + V_DrawSciencePatch(amxpos, amypos, flags, iconprefix[skin], FRACUNIT); else { UINT8 *colormap; - if (player->mo->colorized) - { - colormap = R_GetTranslationColormap(TC_STARMAN, player->mo->color, 0); - } + if (mo->colorized) + colormap = R_GetTranslationColormap(TC_RAINBOW, mo->color, 0); else - { - colormap = R_GetTranslationColormap(player->skin, player->mo->color, 0); - } - V_DrawFixedPatch(amxpos, amypos, FRACUNIT, flags, iconprefix[player->skin], colormap); + colormap = R_GetTranslationColormap(skin, mo->color, 0); + V_DrawFixedPatch(amxpos, amypos, FRACUNIT, flags, iconprefix[skin], colormap); } } @@ -4976,8 +5822,8 @@ static void K_drawKartMinimap(void) patch_t *AutomapPic; INT32 i = 0; INT32 x, y; - const INT32 minimaptrans = ((10-cv_kartminimap.value)<width/2); y = MINI_Y - (AutomapPic->height/2); - if (splitscreen) - splitflags = 0; + if (timeinmap > 105) + { + minimaptrans = (splitscreen ? 10 : cv_kartminimap.value); + if (timeinmap <= 113) + minimaptrans = ((((INT32)timeinmap) - 105)*minimaptrans)/(113-105); + if (!minimaptrans) + return; + } + else + return; + + minimaptrans = ((10-minimaptrans)<width), y, splitflags|V_FLIP, AutomapPic); @@ -5018,37 +5875,104 @@ static void K_drawKartMinimap(void) x -= SHORT(AutomapPic->leftoffset); y -= SHORT(AutomapPic->topoffset); - // Player's tiny icons on the Automap. - for (i = 0; i < MAXPLAYERS; i++) + // Player's tiny icons on the Automap. (drawn opposite direction so player 1 is drawn last in splitscreen) + if (ghosts) { - if (i == displayplayer && !splitscreen) - continue; // Do displayplayer later - if (players[i].mo && !players[i].spectator) + demoghost *g = ghosts; + while (g) { - if (G_BattleGametype() && players[i].kartstuff[k_balloon] <= 0) + K_drawKartMinimapHead(g->mo, x, y, splitflags, AutomapPic); + g = g->next; + } + if (!stplyr->mo || stplyr->spectator) // do we need the latter..? + return; + dop1later = true; + } + else + { + for (i = MAXPLAYERS-1; i >= 0; i--) + { + if (!playeringame[i]) + continue; + if (!players[i].mo || players[i].spectator) continue; - if (players[i].kartstuff[k_bootimer] > 0) + if (!splitscreen && i == displayplayer) { - if ((players[i].kartstuff[k_bootimer] < 1*TICRATE/2 - || players[i].kartstuff[k_bootimer] > bootime-(1*TICRATE/2)) - && !(leveltime & 1)) - ; - else + dop1later = true; // Do displayplayer later + continue; + } + + if (G_BattleGametype() && players[i].kartstuff[k_bumper] <= 0) + continue; + if (players[i].kartstuff[k_hyudorotimer] > 0) + { + if (!((players[i].kartstuff[k_hyudorotimer] < 1*TICRATE/2 + || players[i].kartstuff[k_hyudorotimer] > hyudorotime-(1*TICRATE/2)) + && !(leveltime & 1))) continue; } - K_drawKartMinimapHead(&players[i], x, y, splitflags, AutomapPic); + K_drawKartMinimapHead(players[i].mo, x, y, splitflags, AutomapPic); } } - if (splitscreen) - return; // Don't need this for splits + if (!dop1later) + return; // Don't need this splitflags &= ~V_HUDTRANSHALF; splitflags |= V_HUDTRANS; - if (stplyr->mo && !stplyr->spectator) - K_drawKartMinimapHead(stplyr, x, y, splitflags, AutomapPic); + K_drawKartMinimapHead(stplyr->mo, x, y, splitflags, AutomapPic); +} + +static void K_drawKartStartCountdown(void) +{ + INT32 pnum = 0, splitflags = K_calcSplitFlags(0); // 3 + + if (leveltime >= starttime-(2*TICRATE)) // 2 + pnum++; + if (leveltime >= starttime-TICRATE) // 1 + pnum++; + if (leveltime >= starttime) // GO! + pnum++; + if ((leveltime % (2*5)) / 5) // blink + pnum += 4; + + if (splitscreen) + V_DrawSmallScaledPatch(STCD_X - (SHORT(kp_startcountdown[pnum]->width)/4), STCD_Y - (SHORT(kp_startcountdown[pnum]->height)/4), splitflags, kp_startcountdown[pnum]); + else + V_DrawScaledPatch(STCD_X - (SHORT(kp_startcountdown[pnum]->width)/2), STCD_Y - (SHORT(kp_startcountdown[pnum]->height)/2), splitflags, kp_startcountdown[pnum]); +} + +static void K_drawKartFinish(void) +{ + INT32 pnum = 0, splitflags = K_calcSplitFlags(0); + + if (!stplyr->kartstuff[k_cardanimation] || stplyr->kartstuff[k_cardanimation] >= 2*TICRATE) + return; + + if ((stplyr->kartstuff[k_cardanimation] % (2*5)) / 5) // blink + pnum = 1; + + if (splitscreen > 1) + { + V_DrawTinyScaledPatch(STCD_X - (SHORT(kp_racefinish[pnum]->width)/8), STCD_Y - (SHORT(kp_racefinish[pnum]->height)/8), splitflags, kp_racefinish[pnum]); + return; + } + + { + INT32 scaleshift = (FRACBITS - splitscreen); // FRACUNIT or FRACUNIT/2 + INT32 x = ((vid.width<width)<kartstuff[k_cardanimation])*(xval > x ? xval : x))/TICRATE; + + if (splitscreen && stplyr == &players[secondarydisplayplayer]) + x = -x; + + V_DrawFixedPatch(x + (STCD_X<width)<<(scaleshift-1)), + (STCD_Y<height)<<(scaleshift-1)), + (1<exiting) { if (stplyr == &players[displayplayer]) - V_DrawFadeScreen(); - if (stplyr->kartstuff[k_balloon]) - V_DrawFixedPatch(x<exiting < 6*TICRATE) + { + if (stplyr->kartstuff[k_position] == 1) + V_DrawFixedPatch(x<kartstuff[k_balloon] <= 0 && stplyr->kartstuff[k_comebacktimer] && comeback) + else if (stplyr->kartstuff[k_bumper] <= 0 && stplyr->kartstuff[k_comebacktimer] && comeback) { - INT32 t = stplyr->kartstuff[k_comebacktimer]/TICRATE; - INT32 txoff = 0; + UINT16 t = stplyr->kartstuff[k_comebacktimer]/(10*TICRATE); + INT32 txoff, adjust = (splitscreen > 1) ? 4 : 6; // normal string is 8, kart string is 12, half of that for ease INT32 ty = (BASEVIDHEIGHT/2)+66; - if (t == 0) - txoff = 8; - else + txoff = adjust; + + while (t) { - while (t) - { - txoff += 8; - t /= 10; - } + txoff += adjust; + t /= 10; } if (splitscreen) { - if (splitscreen > 2) + if (splitscreen > 1) ty = (BASEVIDHEIGHT/4)+33; if ((splitscreen == 1 && stplyr == &players[secondarydisplayplayer]) || (stplyr == &players[thirddisplayplayer] && splitscreen > 1) @@ -5125,7 +6051,7 @@ static void K_drawBattleFullscreen(void) ty += (BASEVIDHEIGHT/2); } else - V_DrawFadeScreen(); + V_DrawFadeScreen(0xFF00, 16); if (!comebackshowninfo) V_DrawFixedPatch(x< 1) - V_DrawString(x-(txoff/2), ty, 0, va("%d", stplyr->kartstuff[k_comebacktimer]/TICRATE)); + V_DrawString(x-txoff, ty, 0, va("%d", stplyr->kartstuff[k_comebacktimer]/TICRATE)); else { V_DrawFixedPatch(x<kartstuff[k_comebacktimer]/TICRATE)); } } + + if (netgame && !stplyr->spectator && timeinmap > 113) // FREE PLAY? + { + UINT8 i; + + // check to see if there's anyone else at all + for (i = 0; i < MAXPLAYERS; i++) + { + if (i == displayplayer) + continue; + if (playeringame[i] && !stplyr->spectator) + return; + } + + K_drawKartFreePlay(leveltime); + } } -static void K_drawStartLakitu(void) +static void K_drawKartFirstPerson(void) { - patch_t *localpatch = kp_nodraw; + static INT32 pnum[4], turn[4], drift[4]; + INT32 pn = 0, tn = 0, dr = 0; + INT32 target = 0, splitflags = K_calcSplitFlags(V_SNAPTOBOTTOM); + INT32 x = BASEVIDWIDTH/2, y = BASEVIDHEIGHT; + fixed_t scale; + UINT8 *colmap = NULL; + ticcmd_t *cmd = &stplyr->cmd; - fixed_t adjustY; - tic_t numFrames = 32; // Number of frames for the animation - fixed_t finalOffset = 206; // Number of pixels to offset the patch (This is actually 200, the 6 is a buffer for the parabola) + if (stplyr->spectator || !stplyr->mo || (stplyr->mo->flags2 & MF2_DONTDRAW)) + return; - if (leveltime < 52) localpatch = kp_lakitustart[0]; - if (leveltime >= 52 && leveltime < 56) localpatch = kp_lakitustart[1]; - if (leveltime >= 56 && leveltime < 60) localpatch = kp_lakitustart[2]; - if (leveltime >= 60 && leveltime < 64) localpatch = kp_lakitustart[3]; - if (leveltime >= 64 && leveltime < 91) localpatch = kp_lakitustart[4]; - if (leveltime >= 91 && leveltime < 95) localpatch = kp_lakitustart[5]; - if (leveltime >= 95 && leveltime < 99) localpatch = kp_lakitustart[6]; - if (leveltime >= 99 && leveltime < 103) localpatch = kp_lakitustart[7]; - if (leveltime >= 103 && leveltime < 130) localpatch = kp_lakitustart[8]; - if (leveltime >= 130 && leveltime < 134) localpatch = kp_lakitustart[9]; - if (leveltime >= 134 && leveltime < 138) localpatch = kp_lakitustart[10]; - if (leveltime >= 138 && leveltime < 142) localpatch = kp_lakitustart[11]; - if (leveltime >= 142 && leveltime < 178) localpatch = kp_lakitustart[12]; - - if (leveltime <= numFrames) - adjustY = (finalOffset - 1) - FixedMul((finalOffset), FRACUNIT / (leveltime + 3)); - else if (leveltime >= 146) - { - fixed_t templeveltime = leveltime - 145; - adjustY = (finalOffset - 1) - FixedMul((finalOffset), FRACUNIT / (numFrames + 3 - templeveltime)); - } + if (stplyr == &players[secondarydisplayplayer] && splitscreen) + { pn = pnum[1]; tn = turn[1]; dr = drift[1]; } + else if (stplyr == &players[thirddisplayplayer] && splitscreen > 1) + { pn = pnum[2]; tn = turn[2]; dr = drift[2]; } + else if (stplyr == &players[fourthdisplayplayer] && splitscreen > 2) + { pn = pnum[3]; tn = turn[3]; dr = drift[3]; } else - adjustY = 200; + { pn = pnum[0]; tn = turn[0]; dr = drift[0]; } + + if (splitscreen) + { + y >>= 1; + if (splitscreen > 1) + x >>= 1; + } + + { + if (stplyr->speed < FixedMul(stplyr->runspeed, stplyr->mo->scale) && (leveltime & 1) && !splitscreen) + y++; + // the following isn't EXPLICITLY right, it just gets the result we want, but i'm too lazy to look up the right way to do it + if (stplyr->mo->flags2 & MF2_SHADOW) + splitflags |= FF_TRANS80; + else if (stplyr->mo->frame & FF_TRANSMASK) + splitflags |= (stplyr->mo->frame & FF_TRANSMASK); + } + + if (cmd->driftturn > 400) // strong left turn + target = 2; + else if (cmd->driftturn < -400) // strong right turn + target = -2; + else if (cmd->driftturn > 0) // weak left turn + target = 1; + else if (cmd->driftturn < 0) // weak right turn + target = -1; + else // forward + target = 0; if (mirrormode) - V_DrawSmallScaledPatch(320-LAKI_X, LAKI_Y + adjustY, V_SNAPTOTOP|V_FLIP, localpatch); - else - V_DrawSmallScaledPatch(LAKI_X, LAKI_Y + adjustY, V_SNAPTOTOP, localpatch); -} + target = -target; -static void K_drawLapLakitu(void) -{ - patch_t *localpatch = kp_nodraw; + if (pn < target) + pn++; + else if (pn > target) + pn--; - fixed_t swoopTimer = 80 - stplyr->kartstuff[k_lapanimation]; // Starts at 80, goes down by 1 per frame - fixed_t adjustY; - fixed_t numFrames = 32; // Number of frames for the animation - fixed_t finalOffset = 206; // Number of pixels to offset the patch (This is actually 200, the 6 is a buffer for the parabola) - boolean finishLine = false; + if (pn < 0) + splitflags |= V_FLIP; // right turn - if (stplyr->laps < (UINT8)(cv_numlaps.value - 1)) + target = abs(pn); + if (target > 2) + target = 2; + + x <<= FRACBITS; + y <<= FRACBITS; + + if (tn != cmd->driftturn/50) + tn -= (tn - (cmd->driftturn/50))/8; + + if (dr != stplyr->kartstuff[k_drift]*16) + dr -= (dr - (stplyr->kartstuff[k_drift]*16))/8; + + if (splitscreen == 1) { - switch (stplyr->laps) + scale = (2*FRACUNIT)/3; + y += FRACUNIT/(vid.dupx < vid.dupy ? vid.dupx : vid.dupy); // correct a one-pixel gap on the screen view (not the basevid view) + } + else if (splitscreen) + scale = FRACUNIT/2; + else + scale = FRACUNIT; + + if (stplyr->mo) + { + fixed_t dsone = K_GetKartDriftSparkValue(stplyr); + fixed_t dstwo = dsone*2; + +#ifndef DONTLIKETOASTERSFPTWEAKS { - case 1: localpatch = kp_lakitulaps[0]; break; - case 2: localpatch = kp_lakitulaps[1]; break; - case 3: localpatch = kp_lakitulaps[2]; break; - case 4: localpatch = kp_lakitulaps[3]; break; - case 5: localpatch = kp_lakitulaps[4]; break; - case 6: localpatch = kp_lakitulaps[5]; break; - case 7: localpatch = kp_lakitulaps[6]; break; - case 8: localpatch = kp_lakitulaps[7]; break; - } - } - else if (stplyr->laps == (UINT8)(cv_numlaps.value - 1)) - localpatch = kp_lakitulaps[8]; - else - { - // Change flag frame every 4 frames - switch (leveltime % 32) - { - case 0: case 1: case 2: case 3: - localpatch = kp_lakitulaps[9]; break; - case 4: case 5: case 6: case 7: - localpatch = kp_lakitulaps[10]; break; - case 8: case 9: case 10: case 11: - localpatch = kp_lakitulaps[11]; break; - case 12: case 13: case 14: case 15: - localpatch = kp_lakitulaps[12]; break; - case 16: case 17: case 18: case 19: - localpatch = kp_lakitulaps[13]; break; - case 20: case 21: case 22: case 23: - localpatch = kp_lakitulaps[14]; break; - case 24: case 25: case 26: case 27: - localpatch = kp_lakitulaps[15]; break; - case 28: case 29: case 30: case 31: - localpatch = kp_lakitulaps[16]; break; - } - finishLine = true; - finalOffset = 226; - } + const angle_t ang = R_PointToAngle2(0, 0, stplyr->rmomx, stplyr->rmomy) - stplyr->frameangle; + // yes, the following is correct. no, you do not need to swap the x and y. + fixed_t xoffs = -P_ReturnThrustY(stplyr->mo, ang, (BASEVIDWIDTH<<(FRACBITS-2))/2); + fixed_t yoffs = -(P_ReturnThrustX(stplyr->mo, ang, 4*FRACUNIT) - 4*FRACUNIT); - if (swoopTimer <= numFrames) - adjustY = (finalOffset - 1) - FixedMul((finalOffset), FRACUNIT / (swoopTimer + 3)); - else if (swoopTimer >= 48) - { - fixed_t templeveltime = swoopTimer - 47; - adjustY = (finalOffset - 1) - FixedMul((finalOffset), FRACUNIT / (numFrames + 3 - templeveltime)); - } - else - { - if (finishLine) - adjustY = 220; + if (splitscreen) + xoffs = FixedMul(xoffs, scale); + + xoffs -= (tn)*scale; + xoffs -= (dr)*scale; + + if (stplyr->frameangle == stplyr->mo->angle) + { + const fixed_t mag = FixedDiv(stplyr->speed, 10*stplyr->mo->scale); + + if (mag < FRACUNIT) + { + xoffs = FixedMul(xoffs, mag); + if (!splitscreen) + yoffs = FixedMul(yoffs, mag); + } + } + + if (stplyr->mo->momz > 0) // TO-DO: Draw more of the kart so we can remove this if! + yoffs += stplyr->mo->momz/3; + + if (mirrormode) + x -= xoffs; + else + x += xoffs; + if (!splitscreen) + y += yoffs; + } + + // drift sparks! + if ((leveltime & 1) && (stplyr->kartstuff[k_driftcharge] >= dstwo)) + colmap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_TANGERINE, 0); + else if ((leveltime & 1) && (stplyr->kartstuff[k_driftcharge] >= dsone)) + colmap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_SAPPHIRE, 0); else - adjustY = 200; +#endif + // invincibility/grow/shrink! + if (stplyr->mo->colorized && stplyr->mo->color) + colmap = R_GetTranslationColormap(TC_RAINBOW, stplyr->mo->color, 0); } - if (mirrormode) - V_DrawSmallScaledPatch(320-(LAKI_X+14+(swoopTimer/4)), LAKI_Y + adjustY, V_SNAPTOTOP|V_FLIP, localpatch); + V_DrawFixedPatch(x, y, scale, splitflags, kp_fpview[target], colmap); + + if (stplyr == &players[secondarydisplayplayer] && splitscreen) + { pnum[1] = pn; turn[1] = tn; drift[1] = dr; } + else if (stplyr == &players[thirddisplayplayer] && splitscreen > 1) + { pnum[2] = pn; turn[2] = tn; drift[2] = dr; } + else if (stplyr == &players[fourthdisplayplayer] && splitscreen > 2) + { pnum[3] = pn; turn[3] = tn; drift[3] = dr; } else - V_DrawSmallScaledPatch(LAKI_X+14+(swoopTimer/4), LAKI_Y + adjustY, V_SNAPTOTOP, localpatch); + { pnum[0] = pn; turn[0] = tn; drift[0] = dr; } +} + +// doesn't need to ever support 4p +static void K_drawInput(void) +{ + static INT32 pn = 0; + INT32 target = 0, splitflags = (V_SNAPTOBOTTOM|V_SNAPTORIGHT); + INT32 x = BASEVIDWIDTH - 32, y = BASEVIDHEIGHT-24, offs, col; + const INT32 accent1 = splitflags|colortranslations[stplyr->skincolor][5]; + const INT32 accent2 = splitflags|colortranslations[stplyr->skincolor][9]; + ticcmd_t *cmd = &stplyr->cmd; + + if (timeinmap <= 105) + return; + + if (timeinmap < 113) + { + INT32 count = ((INT32)(timeinmap) - 105); + offs = 64; + while (count-- > 0) + offs >>= 1; + x += offs; + } + +#define BUTTW 8 +#define BUTTH 11 + +#define drawbutt(xoffs, butt, symb)\ + if (stplyr->cmd.buttons & butt)\ + {\ + offs = 2;\ + col = accent1;\ + }\ + else\ + {\ + offs = 0;\ + col = accent2;\ + V_DrawFill(x+(xoffs), y+BUTTH, BUTTW-1, 2, splitflags|31);\ + }\ + V_DrawFill(x+(xoffs), y+offs, BUTTW-1, BUTTH, col);\ + V_DrawFixedPatch((x+1+(xoffs))<driftturn) // no turn + target = 0; + else // turning of multiple strengths! + { + target = ((abs(cmd->driftturn) - 1)/125)+1; + if (target > 4) + target = 4; + if (cmd->driftturn < 0) + target = -target; + } + + if (pn != target) + { + if (abs(pn - target) == 1) + pn = target; + else if (pn < target) + pn += 2; + else //if (pn > target) + pn -= 2; + } + + if (pn < 0) + { + splitflags |= V_FLIP; // right turn + x--; + } + + target = abs(pn); + if (target > 4) + target = 4; + + if (!stplyr->skincolor) + V_DrawFixedPatch(x<skincolor, 0); + V_DrawFixedPatch(x<kartstuff[k_lapanimation]; + + V_DrawScaledPatch(BASEVIDWIDTH/2 + (32*max(0, stplyr->kartstuff[k_lapanimation]-76)), + 64 - (32*max(0, progress-76)), + 0, kp_lapanim_emblem); + + if (stplyr->laps == (UINT8)(cv_numlaps.value - 1)) + { + V_DrawScaledPatch(27 - (32*max(0, progress-76)), + 40, + 0, kp_lapanim_final[min(progress/2, 10)]); + + if (progress/2-12 >= 0) + { + V_DrawScaledPatch(194 + (32*max(0, progress-76)), + 40, + 0, kp_lapanim_lap[min(progress/2-12, 6)]); + } + } + else + { + V_DrawScaledPatch(61 - (32*max(0, progress-76)), + 40, + 0, kp_lapanim_lap[min(progress/2, 6)]); + + if (progress/2-8 >= 0) + { + V_DrawScaledPatch(194 + (32*max(0, progress-76)), + 40, + 0, kp_lapanim_number[(((UINT32)stplyr->laps+1) / 10)][min(progress/2-8, 2)]); + + if (progress/2-10 >= 0) + { + V_DrawScaledPatch(221 + (32*max(0, progress-76)), + 40, + 0, kp_lapanim_number[(((UINT32)stplyr->laps+1) % 10)][min(progress/2-10, 2)]); + } + } + } +} + +void K_drawKartFreePlay(UINT32 flashtime) +{ + // no splitscreen support because it's not FREE PLAY if you have more than one player in-game + + if ((flashtime % TICRATE) < TICRATE/2) + return; + + V_DrawKartString((BASEVIDWIDTH - (LAPS_X+1)) - (12*9), // mirror the laps thingy + LAPS_Y+3, V_SNAPTOBOTTOM|V_SNAPTORIGHT, "FREE PLAY"); +} + +static void K_drawCheckpointDebugger(void) +{ + if ((numstarposts/2 + stplyr->starpostnum) >= numstarposts) + V_DrawString(8, 184, 0, va("Checkpoint: %d / %d (Can finish)", stplyr->starpostnum, numstarposts)); + else + V_DrawString(8, 184, 0, va("Checkpoint: %d / %d (Skip: %d)", stplyr->starpostnum, numstarposts, (numstarposts/2 + stplyr->starpostnum))); + V_DrawString(8, 192, 0, va("Waypoint dist: Prev %d, Next %d", stplyr->kartstuff[k_prevcheck], stplyr->kartstuff[k_nextcheck])); } void K_drawKartHUD(void) { + boolean isfreeplay = false; + // Define the X and Y for each drawn object // This is handled by console/menu values K_initKartHUD(); - if (splitscreen == 2) // Player 4 in 3P is basically the minimap :p + // Draw that fun first person HUD! Drawn ASAP so it looks more "real". + if ((stplyr == &players[displayplayer] && !camera.chase) + || ((splitscreen && stplyr == &players[secondarydisplayplayer]) && !camera2.chase) + || ((splitscreen > 1 && stplyr == &players[thirddisplayplayer]) && !camera3.chase) + || ((splitscreen > 2 && stplyr == &players[fourthdisplayplayer]) && !camera4.chase)) + K_drawKartFirstPerson(); + + // Draw a white fade on level opening + if (leveltime < 15 && stplyr == &players[displayplayer]) + { + if (leveltime <= 5) + V_DrawFill(0,0,BASEVIDWIDTH,BASEVIDHEIGHT,120); // Pure white on first few frames, to hide SRB2's awful level load artifacts + else + V_DrawFadeScreen(120, 15-leveltime); // Then gradually fade out from there + } + + if (splitscreen == 2) // Player 4 in 3P is the minimap :p K_drawKartMinimap(); // Draw full screen stuff that turns off the rest of the HUD + if (mapreset) + { + K_drawChallengerScreen(); + return; + } + if ((G_BattleGametype()) && (stplyr->exiting - || (stplyr->kartstuff[k_balloon] <= 0 + || (stplyr->kartstuff[k_bumper] <= 0 && stplyr->kartstuff[k_comebacktimer] && comeback && stplyr->playerstate == PST_LIVE))) @@ -5274,39 +6451,19 @@ void K_drawKartHUD(void) return; } - // Draw Lakitu - // This is done first so that regardless of HUD layers, - // he'll appear to be in the 'real world' - if (!splitscreen) - { - if (leveltime < 178) - K_drawStartLakitu(); - - if (stplyr->kartstuff[k_lapanimation]) - K_drawLapLakitu(); - - // Draw the CHECK indicator before the other items too, so it's overlapped by everything else - if (cv_kartcheck.value) - K_drawKartPlayerCheck(); - } + // Draw the CHECK indicator before the other items, so it's overlapped by everything else + if (cv_kartcheck.value && !splitscreen && !players[displayplayer].exiting) + K_drawKartPlayerCheck(); if (splitscreen == 0 && cv_kartminimap.value) K_drawKartMinimap(); // 3P splitscreen is handled above - // If the item window is closing, draw it closing! - if (stplyr->kartstuff[k_itemclose]) - K_drawKartItemClose(); + // Draw the item window + K_drawKartItem(); - // If the item-roulette is going, draw that - // Otherwise, draw the item window normally (separated for retro/neo, to prevent this block from becoming a mess - if (stplyr->kartstuff[k_itemroulette]) - K_drawKartItemRoulette(); - // else if () - // K_drawKartNeoItem(); - else - K_drawKartRetroItem(); - - //K_DrawKartTripleItem(); + // Draw WANTED status + if (G_BattleGametype()) + K_drawKartWanted(); // If not splitscreen, draw... if (!splitscreen) @@ -5316,9 +6473,8 @@ void K_drawKartHUD(void) if (!modeattacking) { - // The little triple-item icons at the bottom // The top-four faces on the left - K_drawKartPositionFaces(); + isfreeplay = K_drawKartPositionFaces(); } } @@ -5336,21 +6492,61 @@ void K_drawKartHUD(void) K_drawKartSpeedometer(); } - if (!modeattacking) + if (isfreeplay) + ; + else if (!modeattacking) { // Draw the numerical position K_DrawKartPositionNum(stplyr->kartstuff[k_position]); } + else //if (!(demoplayback && hu_showscores)) + { + // Draw the input UI + K_drawInput(); + } // You're about to DIEEEEE - K_drawBlueShellWarning(); + K_drawSPBWarning(); } else if (G_BattleGametype()) // Battle-only { // Draw the hits left! - K_drawKartBalloonsOrKarma(); + K_drawKartBumpersOrKarma(); } } + + // Draw the countdowns after everything else. + if (leveltime >= starttime-(3*TICRATE) + && leveltime < starttime+TICRATE) + K_drawKartStartCountdown(); + else if (countdown && (!splitscreen || !stplyr->exiting)) + { + char *countstr = va("%d", countdown/TICRATE); + + if (splitscreen > 1) + V_DrawCenteredString(BASEVIDWIDTH/4, LAPS_Y+1, K_calcSplitFlags(0), countstr); + else + { + INT32 karlen = strlen(countstr)*6; // half of 12 + V_DrawKartString((BASEVIDWIDTH/2)-karlen, LAPS_Y+3, K_calcSplitFlags(0), countstr); + } + } + + // Race overlays + if (G_RaceGametype()) + { + if (stplyr->exiting) + K_drawKartFinish(); + else if (stplyr->kartstuff[k_lapanimation] && !splitscreen) + K_drawLapStartAnim(); + } + + // Draw FREE PLAY. + if (isfreeplay && !stplyr->spectator && timeinmap > 113) + K_drawKartFreePlay(leveltime); + + if (cv_kartdebugcheckpoint.value) + K_drawCheckpointDebugger(); } //} diff --git a/src/k_kart.h b/src/k_kart.h index 694450d8..89f1ea7e 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -11,42 +11,56 @@ UINT8 colortranslations[MAXSKINCOLORS][16]; extern const char *KartColor_Names[MAXSKINCOLORS]; -void K_StarmanColormap(UINT8 *dest_colormap, UINT8 skincolor); +extern const UINT8 KartColor_Opposite[MAXSKINCOLORS*2]; +void K_RainbowColormap(UINT8 *dest_colormap, UINT8 skincolor); void K_GenerateKartColormap(UINT8 *dest_colormap, INT32 skinnum, UINT8 color); UINT8 K_GetKartColorByName(const char *name); 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_LakituChecker(player_t *player); +void K_RespawnChecker(player_t *player); void K_KartMoveAnimation(player_t *player); void K_KartPlayerThink(player_t *player, ticcmd_t *cmd); void K_KartPlayerAfterThink(player_t *player); -void K_SpinPlayer(player_t *player, mobj_t *source); +void K_DoInstashield(player_t *player); +void K_SpinPlayer(player_t *player, mobj_t *source, INT32 type, boolean trapitem); void K_SquishPlayer(player_t *player, mobj_t *source); void K_ExplodePlayer(player_t *player, mobj_t *source); -void K_StealBalloon(player_t *player, player_t *victim, boolean force); +void K_StealBumper(player_t *player, player_t *victim, boolean force); void K_SpawnKartExplosion(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 number, mobjtype_t type, angle_t rotangle, boolean spawncenter, boolean ghostit, mobj_t *source); -void K_SpawnBobombExplosion(mobj_t *source, UINT8 color); +void K_SpawnMineExplosion(mobj_t *source, UINT8 color); 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_DoMushroom(player_t *player, boolean doPFlag); -void K_DoBouncePad(mobj_t *mo, fixed_t vertispeed); +void K_DoSneaker(player_t *player, boolean doPFlag); +void K_DoPogoSpring(mobj_t *mo, fixed_t vertispeed, boolean mute); +void K_KillBananaChain(mobj_t *banana, mobj_t *inflictor, mobj_t *source); +void K_CleanHnextList(mobj_t *work); +void K_UpdateHnextList(player_t *player); +void K_RepairOrbitChain(mobj_t *orbit); boolean K_CheckPlayersRespawnColliding(INT32 playernum, fixed_t x, fixed_t y); INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue); +fixed_t K_GetKartDriftSparkValue(player_t *player); +void K_StripItems(player_t *player); void K_MomentumToFacing(player_t *player); fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower); fixed_t K_GetKartAccel(player_t *player); -UINT16 K_GetKartFlashing(void); +UINT16 K_GetKartFlashing(player_t *player); fixed_t K_3dKartMovement(player_t *player, boolean onground, fixed_t forwardmove); void K_MoveKartPlayer(player_t *player, boolean onground); -void K_CheckBalloons(void); +void K_CalculateBattleWanted(void); +void K_CheckBumpers(void); +void K_CheckSpectateStatus(void); INT32 K_calcSplitFlags(INT32 snapflags); void K_LoadKartHUDGraphics(void); fixed_t K_FindCheckX(fixed_t px, fixed_t py, angle_t ang, fixed_t mx, fixed_t my); void K_drawKartHUD(void); +void K_drawKartFreePlay(UINT32 flashtime); void K_LoadIconGraphics(char *facestr, INT32 skinnum); void K_ReloadSkinIconGraphics(void); diff --git a/src/lua_baselib.c b/src/lua_baselib.c index b49cdd72..7c44c796 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -20,6 +20,8 @@ #include "m_random.h" #include "s_sound.h" #include "g_game.h" +#include "hu_stuff.h" +#include "console.h" #include "k_kart.h" #include "lua_script.h" @@ -86,6 +88,57 @@ static int lib_print(lua_State *L) return 0; } +// Print stuff in the chat, or in the console if we can't. +static int lib_chatprint(lua_State *L) +{ + const char *str = luaL_checkstring(L, 1); // retrieve string + if (str == NULL) // error if we don't have a string! + return luaL_error(L, LUA_QL("tostring") " must return a string to " LUA_QL("chatprint")); + int len = strlen(str); + if (len > 255) // string is too long!!! + return luaL_error(L, "String exceeds the 255 characters limit of the chat buffer."); + + HU_AddChatText(str); + + if OLDCHAT + CONS_Printf("%s\n", str); + else + CON_LogMessage(str); // save to log.txt + + return 0; +} + +// Same as above, but do it for only one player. +static int lib_chatprintf(lua_State *L) +{ + int n = lua_gettop(L); /* number of arguments */ + player_t *plr; + if (n < 2) + return luaL_error(L, "chatprintf requires at least two arguments: player and text."); + + plr = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); // retrieve player + if (!plr) + return LUA_ErrInvalid(L, "player_t"); + if (plr != &players[consoleplayer]) + return 0; + + const char *str = luaL_checkstring(L, 2); // retrieve string + if (str == NULL) // error if we don't have a string! + return luaL_error(L, LUA_QL("tostring") " must return a string to " LUA_QL("chatprintf")); + int len = strlen(str); + if (len > 255) // string is too long!!! + return luaL_error(L, "String exceeds the 255 characters limit of the chat buffer."); + + HU_AddChatText(str); + + if OLDCHAT + CONS_Printf("%s\n", str); + else + CON_LogMessage(str); // save to log.txt + + return 0; +} + static int lib_evalMath(lua_State *L) { const char *word = luaL_checkstring(L, 1); @@ -583,6 +636,16 @@ static int lib_pCanRunOnWater(lua_State *L) return 1; } +static int lib_pSpawnShadowMobj(lua_State *L) +{ + mobj_t *caster = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + NOHUD + if (!caster) + return LUA_ErrInvalid(L, "mobj_t"); + P_SpawnShadowMobj(caster); + return 0; +} + // P_USER //////////// @@ -887,7 +950,7 @@ static int lib_pHomingAttack(lua_State *L) return 0; } -static int lib_pSuperReady(lua_State *L) +/*static int lib_pSuperReady(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); //HUDSAFE @@ -895,7 +958,7 @@ static int lib_pSuperReady(lua_State *L) return LUA_ErrInvalid(L, "player_t"); lua_pushboolean(L, P_SuperReady(player)); return 1; -} +}*/ static int lib_pDoJump(lua_State *L) { @@ -1252,7 +1315,7 @@ static int lib_pPlayLivesJingle(lua_State *L) static int lib_pCanPickupItem(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); - boolean weapon = lua_optboolean(L, 2); + UINT8 weapon = (UINT8)luaL_optinteger(L, 2, 0); //HUDSAFE if (!player) return LUA_ErrInvalid(L, "player_t"); @@ -1993,6 +2056,26 @@ static int lib_kGetKartColorByName(lua_State *L) return 1; } +static int lib_kIsPlayerLosing(lua_State *L) +{ + player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + //HUDSAFE + if (!player) + return LUA_ErrInvalid(L, "player_t"); + K_IsPlayerLosing(player); + return 0; +} + +static int lib_kIsPlayerWanted(lua_State *L) +{ + player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + //HUDSAFE + if (!player) + return LUA_ErrInvalid(L, "player_t"); + K_IsPlayerWanted(player); + return 0; +} + static int lib_kKartBouncing(lua_State *L) { mobj_t *mobj1 = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); @@ -2008,16 +2091,28 @@ static int lib_kKartBouncing(lua_State *L) return 0; } +static int lib_kDoInstashield(lua_State *L) +{ + player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + NOHUD + if (!player) + return LUA_ErrInvalid(L, "player_t"); + K_DoInstashield(player); + return 0; +} + static int lib_kSpinPlayer(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); mobj_t *source = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); + INT32 type = (INT32)luaL_checkinteger(L, 3); + boolean trapitem = luaL_checkboolean(L, 4); NOHUD if (!player) return LUA_ErrInvalid(L, "player_t"); if (!source) return LUA_ErrInvalid(L, "mobj_t"); - K_SpinPlayer(player, source); + K_SpinPlayer(player, source, type, trapitem); return 0; } @@ -2047,7 +2142,7 @@ static int lib_kExplodePlayer(lua_State *L) return 0; } -static int lib_kStealBalloon(lua_State *L) +static int lib_kStealBumper(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); player_t *victim = *((player_t **)luaL_checkudata(L, 2, META_PLAYER)); @@ -2057,7 +2152,7 @@ static int lib_kStealBalloon(lua_State *L) return LUA_ErrInvalid(L, "player_t"); if (!victim) return LUA_ErrInvalid(L, "player_t"); - K_StealBalloon(player, victim, force); + K_StealBumper(player, victim, force); return 0; } @@ -2080,7 +2175,7 @@ static int lib_kSpawnKartExplosion(lua_State *L) return 0; } -static int lib_kSpawnDriftTrail(lua_State *L) +static int lib_kSpawnBoostTrail(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); NOHUD @@ -2090,6 +2185,27 @@ static int lib_kSpawnDriftTrail(lua_State *L) return 0; } +static int lib_kSpawnSparkleTrail(lua_State *L) +{ + mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + NOHUD + if (!mo) + return LUA_ErrInvalid(L, "mobj_t"); + K_SpawnSparkleTrail(mo); + return 0; +} + +static int lib_kSpawnWipeoutTrail(lua_State *L) +{ + mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + boolean translucent = luaL_checkboolean(L, 2); + NOHUD + if (!mo) + return LUA_ErrInvalid(L, "mobj_t"); + K_SpawnWipeoutTrail(mo, translucent); + return 0; +} + static int lib_kDriftDustHandling(lua_State *L) { mobj_t *spawner = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); @@ -2100,25 +2216,52 @@ static int lib_kDriftDustHandling(lua_State *L) return 0; } -static int lib_kDoMushroom(lua_State *L) +static int lib_kDoSneaker(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); boolean doPFlag = luaL_checkboolean(L, 2); NOHUD if (!player) return LUA_ErrInvalid(L, "player_t"); - K_DoMushroom(player, doPFlag); + K_DoSneaker(player, doPFlag); return 0; } -static int lib_kDoBouncePad(lua_State *L) +static int lib_kDoPogoSpring(lua_State *L) { mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); fixed_t vertispeed = luaL_checkfixed(L, 2); + boolean mute = luaL_checkboolean(L, 3); NOHUD if (!mo) return LUA_ErrInvalid(L, "mobj_t"); - K_DoBouncePad(mo, vertispeed); + K_DoPogoSpring(mo, vertispeed, mute); + return 0; +} + +static int lib_kKillBananaChain(lua_State *L) +{ + mobj_t *banana = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + mobj_t *inflictor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + NOHUD + if (!banana) + return LUA_ErrInvalid(L, "mobj_t"); + if (!inflictor) + return LUA_ErrInvalid(L, "mobj_t"); + if (!source) + return LUA_ErrInvalid(L, "mobj_t"); + K_KillBananaChain(banana, inflictor, source); + return 0; +} + +static int lib_kRepairOrbitChain(lua_State *L) +{ + mobj_t *orbit = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + NOHUD + if (!orbit) + return LUA_ErrInvalid(L, "mobj_t"); + K_RepairOrbitChain(orbit); return 0; } @@ -2155,16 +2298,18 @@ static int lib_kGetKartAccel(lua_State *L) static int lib_kGetKartFlashing(lua_State *L) { - //player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); //HUDSAFE - //if (!player) - //return LUA_ErrInvalid(L, "player_t"); - lua_pushinteger(L, K_GetKartFlashing()); + if (!player) + return LUA_ErrInvalid(L, "player_t"); + lua_pushinteger(L, K_GetKartFlashing(player)); return 0; } static luaL_Reg lib[] = { {"print", lib_print}, + {"chatprint", lib_chatprint}, + {"chatprintf", lib_chatprintf}, {"EvalMath", lib_evalMath}, // m_random @@ -2213,6 +2358,7 @@ static luaL_Reg lib[] = { {"P_CheckDeathPitCollide",lib_pCheckDeathPitCollide}, {"P_CheckSolidLava",lib_pCheckSolidLava}, {"P_CanRunOnWater",lib_pCanRunOnWater}, + {"P_SpawnShadowMobj",lib_pSpawnShadowMobj}, // p_user {"P_GetPlayerHeight",lib_pGetPlayerHeight}, @@ -2243,7 +2389,7 @@ static luaL_Reg lib[] = { {"P_LookForEnemies",lib_pLookForEnemies}, {"P_NukeEnemies",lib_pNukeEnemies}, {"P_HomingAttack",lib_pHomingAttack}, - {"P_SuperReady",lib_pSuperReady}, + //{"P_SuperReady",lib_pSuperReady}, {"P_DoJump",lib_pDoJump}, {"P_SpawnThokMobj",lib_pSpawnThokMobj}, {"P_SpawnSpinMobj",lib_pSpawnSpinMobj}, @@ -2338,16 +2484,23 @@ static luaL_Reg lib[] = { // k_kart {"K_GetKartColorByName",lib_kGetKartColorByName}, + {"K_IsPlayerLosing",lib_kIsPlayerLosing}, + {"K_IsPlayerWanted",lib_kIsPlayerWanted}, {"K_KartBouncing",lib_kKartBouncing}, + {"K_DoInstashield",lib_kDoInstashield}, {"K_SpinPlayer",lib_kSpinPlayer}, {"K_SquishPlayer",lib_kSquishPlayer}, {"K_ExplodePlayer",lib_kExplodePlayer}, - {"K_StealBalloon",lib_kStealBalloon}, + {"K_StealBumper",lib_kStealBumper}, {"K_SpawnKartExplosion",lib_kSpawnKartExplosion}, - {"K_SpawnBoostTrail",lib_kSpawnDriftTrail}, + {"K_SpawnBoostTrail",lib_kSpawnBoostTrail}, + {"K_SpawnSparkleTrail",lib_kSpawnSparkleTrail}, + {"K_SpawnWipeoutTrail",lib_kSpawnWipeoutTrail}, {"K_DriftDustHandling",lib_kDriftDustHandling}, - {"K_DoMushroom",lib_kDoMushroom}, - {"K_DoBouncePad",lib_kDoBouncePad}, + {"K_DoSneaker",lib_kDoSneaker}, + {"K_DoPogoSpring",lib_kDoPogoSpring}, + {"K_KillBananaChain",lib_kKillBananaChain}, + {"K_RepairOrbitChain",lib_kRepairOrbitChain}, {"K_MomentumToFacing",lib_kMomentumToFacing}, {"K_GetKartSpeed",lib_kGetKartSpeed}, {"K_GetKartAccel",lib_kGetKartAccel}, diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c index d27d6fb0..366f0917 100644 --- a/src/lua_consolelib.c +++ b/src/lua_consolelib.c @@ -77,7 +77,9 @@ void Got_Luacmd(UINT8 **cp, INT32 playernum) deny: //must be hacked/buggy client - lua_settop(gL, 0); // clear stack + if (gL) // check if Lua is actually turned on first, you dummmy -- Monster Iestyn 04/07/18 + lua_settop(gL, 0); // clear stack + CONS_Alert(CONS_WARNING, M_GetText("Illegal lua command received from %s\n"), player_names[playernum]); if (server) { diff --git a/src/lua_hook.h b/src/lua_hook.h index 53e0a7d8..7acc0d0f 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -74,7 +74,7 @@ boolean LUAh_MobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source); // Ho boolean LUAh_BotTiccmd(player_t *bot, ticcmd_t *cmd); // Hook for B_BuildTiccmd boolean LUAh_BotAI(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd); // Hook for B_BuildTailsTiccmd by skin name boolean LUAh_LinedefExecute(line_t *line, mobj_t *mo, sector_t *sector); // Hook for linedef executors -boolean LUAh_PlayerMsg(int source, int target, int flags, char *msg); // Hook for chat messages +boolean LUAh_PlayerMsg(int source, int target, int flags, char *msg, int mute); // Hook for chat messages boolean LUAh_HurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source); // Hook for hurt messages #define LUAh_PlayerSpawn(player) LUAh_PlayerHook(player, hook_PlayerSpawn) // Hook for G_SpawnPlayer diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index eadd0153..5b05b77c 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -952,7 +952,9 @@ boolean LUAh_LinedefExecute(line_t *line, mobj_t *mo, sector_t *sector) } // Hook for player chat -boolean LUAh_PlayerMsg(int source, int target, int flags, char *msg) +// Added the "mute" field. It's set to true if the message was supposed to be eaten by spam protection. +// But for netgame consistency purposes, this hook is ran first reguardless, so this boolean allows for modders to adapt if they so desire. +boolean LUAh_PlayerMsg(int source, int target, int flags, char *msg, int mute) { hook_p hookp; boolean hooked = false; @@ -981,14 +983,19 @@ boolean LUAh_PlayerMsg(int source, int target, int flags, char *msg) LUA_PushUserdata(gL, &players[target-1], META_PLAYER); // target } lua_pushstring(gL, msg); // msg + if (mute) + lua_pushboolean(gL, true); // the message was supposed to be eaten by spamprotecc. + else + lua_pushboolean(gL, false); } lua_pushfstring(gL, FMT_HOOKID, hookp->id); lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - if (lua_pcall(gL, 4, 1, 0)) { + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + if (lua_pcall(gL, 5, 1, 0)) { if (!hookp->error || cv_debug & DBG_LUA) CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); lua_pop(gL, 1); diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index f9428c8c..e8e9e173 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -424,6 +424,30 @@ static int libd_drawFill(lua_State *L) return 0; } +static int libd_fadeScreen(lua_State *L) +{ + UINT16 color = luaL_checkinteger(L, 1); + UINT8 strength = luaL_checkinteger(L, 2); + const UINT8 maxstrength = ((color & 0xFF00) ? 32 : 10); + + HUDONLY + + if (!strength) + return 0; + + if (strength > maxstrength) + return luaL_error(L, "%s fade strength %d out of range (0 - %d)", ((color & 0xFF00) ? "COLORMAP" : "TRANSMAP"), strength, maxstrength); + + if (strength == maxstrength) // Allow as a shortcut for drawfill... + { + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, ((color & 0xFF00) ? 31 : color)); + return 0; + } + + V_DrawFadeScreen(color, strength); + return 0; +} + static int libd_drawString(lua_State *L) { fixed_t x = luaL_checkinteger(L, 1); @@ -568,6 +592,7 @@ static luaL_Reg lib_draw[] = { {"drawNum", libd_drawNum}, {"drawPaddedNum", libd_drawPaddedNum}, {"drawFill", libd_drawFill}, + {"fadeScreen", libd_fadeScreen}, {"drawString", libd_drawString}, {"stringWidth", libd_stringWidth}, {"getColormap", libd_getColormap}, diff --git a/src/lua_mathlib.c b/src/lua_mathlib.c index 96d50b77..50a194c8 100644 --- a/src/lua_mathlib.c +++ b/src/lua_mathlib.c @@ -16,6 +16,7 @@ #include "tables.h" #include "p_local.h" #include "doomstat.h" // for ALL7EMERALDS +#include "k_kart.h" // KartColor_Opposite #include "lua_script.h" #include "lua_libs.h" @@ -191,8 +192,8 @@ static int lib_coloropposite(lua_State *L) UINT8 colornum = (UINT8)luaL_checkinteger(L, 1); if (colornum >= MAXSKINCOLORS) return luaL_error(L, "skincolor %d out of range (0 - %d).", colornum, MAXSKINCOLORS-1); - lua_pushinteger(L, Color_Opposite[colornum*2]); // push color - lua_pushinteger(L, Color_Opposite[colornum*2+1]); // push frame + lua_pushinteger(L, KartColor_Opposite[colornum*2]); // push color + lua_pushinteger(L, KartColor_Opposite[colornum*2+1]); // push frame return 2; } diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index 2dbb58c8..814bb325 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -530,10 +530,22 @@ static int mobj_set(lua_State *L) case mobj_bprev: return UNIMPLEMENTED; case mobj_hnext: - mo->hnext = luaL_checkudata(L, 3, META_MOBJ); + if (lua_isnil(L, 3)) + P_SetTarget(&mo->hnext, NULL); + else + { + mobj_t *hnext = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); + P_SetTarget(&mo->hnext, hnext); + } break; case mobj_hprev: - mo->hprev = luaL_checkudata(L, 3, META_MOBJ); + if (lua_isnil(L, 3)) + P_SetTarget(&mo->hprev, NULL); + else + { + mobj_t *hprev = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); + P_SetTarget(&mo->hprev, hprev); + } break; case mobj_type: // yeah sure, we'll let you change the mobj's type. { diff --git a/src/lua_script.c b/src/lua_script.c index ef94cf30..d8755ff6 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -527,9 +527,23 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) break; } case LUA_TSTRING: + { + UINT16 len = (UINT16)lua_objlen(gL, myindex); // get length of string, including embedded zeros + const char *s = lua_tostring(gL, myindex); + UINT16 i = 0; WRITEUINT8(save_p, ARCH_STRING); - WRITESTRING(save_p, lua_tostring(gL, myindex)); + // if you're wondering why we're writing a string to save_p this way, + // it turns out that Lua can have embedded zeros ('\0') in the strings, + // so we can't use WRITESTRING as that cuts off when it finds a '\0'. + // Saving the size of the string also allows us to get the size of the string on the other end, + // fixing the awful crashes previously encountered for reading strings longer than 1024 + // (yes I know that's kind of a stupid thing to care about, but it'd be evil to trim or ignore them?) + // -- Monster Iestyn 05/08/18 + WRITEUINT16(save_p, len); // save size of string + while (i < len) + WRITECHAR(save_p, s[i++]); // write chars individually, including the embedded zeros break; + } case LUA_TTABLE: { boolean found = false; @@ -810,9 +824,19 @@ static UINT8 UnArchiveValue(int TABLESINDEX) break; case ARCH_STRING: { - char value[1024]; - READSTRING(save_p, value); - lua_pushstring(gL, value); + UINT16 len = READUINT16(save_p); // length of string, including embedded zeros + char *value; + UINT16 i = 0; + // See my comments in the ArchiveValue function; + // it's much the same for reading strings as writing them! + // (i.e. we can't use READSTRING either) + // -- Monster Iestyn 05/08/18 + value = malloc(len); // make temp buffer of size len + // now read the actual string + while (i < len) + value[i++] = READCHAR(save_p); // read chars individually, including the embedded zeros + lua_pushlstring(gL, value, len); // push the string (note: this function supports embedded zeros) + free(value); // free the buffer break; } case ARCH_TABLE: diff --git a/src/m_cheat.c b/src/m_cheat.c index fed76edd..99b96d99 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -1149,7 +1149,7 @@ void OP_ObjectplaceMovement(player_t *player) // make sure viewz follows player if in 1st person mode //player->deltaviewheight = 0; - player->viewheight = FixedMul(cv_viewheight.value << FRACBITS, player->mo->scale); + player->viewheight = FixedMul(32 << FRACBITS, player->mo->scale); if (player->mo->eflags & MFE_VERTICALFLIP) player->viewz = player->mo->z + player->mo->height - player->viewheight; else @@ -1368,7 +1368,7 @@ void Command_ObjectPlace_f(void) players[0].mo->color = op_oldcolor; // This is necessary for recovery of dying players. - if (players[0].powers[pw_flashing] >= K_GetKartFlashing()) - players[0].powers[pw_flashing] = K_GetKartFlashing() - 1; + if (players[0].powers[pw_flashing] >= K_GetKartFlashing(&players[0])) + players[0].powers[pw_flashing] = K_GetKartFlashing(&players[0]) - 1; } } diff --git a/src/m_menu.c b/src/m_menu.c index c3a9abf5..a9de402a 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -241,6 +241,7 @@ menu_t MISC_ScrambleTeamDef, MISC_ChangeTeamDef; // Single Player //static void M_LoadGame(INT32 choice); static void M_TimeAttack(INT32 choice); +static boolean M_QuitTimeAttackMenu(void); //static void M_NightsAttack(INT32 choice); static void M_Statistics(INT32 choice); static void M_HandleStaffReplay(INT32 choice); @@ -251,7 +252,7 @@ static void M_ModeAttackRetry(INT32 choice); static void M_ModeAttackEndGame(INT32 choice); static void M_SetGuestReplay(INT32 choice); static void M_ChoosePlayer(INT32 choice); -menu_t SP_GameStatsDef, SP_LevelStatsDef; +menu_t SP_LevelStatsDef; static menu_t SP_TimeAttackDef, SP_ReplayDef, SP_GuestReplayDef, SP_GhostDef; //static menu_t SP_NightsAttackDef, SP_NightsReplayDef, SP_NightsGuestReplayDef, SP_NightsGhostDef; @@ -259,13 +260,8 @@ static menu_t SP_TimeAttackDef, SP_ReplayDef, SP_GuestReplayDef, SP_GhostDef; #ifndef NONET static void M_StartServerMenu(INT32 choice); static void M_ConnectMenu(INT32 choice); -static void M_ConnectIPMenu(INT32 choice); #endif static void M_StartSplitServerMenu(INT32 choice); -#ifndef NOFOURPLAYER -static void M_Start3PServerMenu(INT32 choice); -static void M_Start4PServerMenu(INT32 choice); -#endif static void M_StartServer(INT32 choice); #ifndef NONET static void M_Refresh(INT32 choice); @@ -284,11 +280,9 @@ static void M_SetupMultiPlayer4(INT32 choice); // Controls menu_t OP_ControlsDef, /*OP_ControlListDef,*/ OP_MoveControlsDef; menu_t /*OP_MPControlsDef, OP_CameraControlsDef, OP_MiscControlsDef,*/ OP_CustomControlsDef, OP_SpectateControlsDef; -menu_t OP_P1ControlsDef, OP_P2ControlsDef; menu_t OP_MouseOptionsDef, OP_Mouse2OptionsDef; menu_t OP_Joystick1Def, OP_Joystick2Def; #ifndef NOFOURPLAYER -menu_t OP_P3ControlsDef, OP_P4ControlsDef; menu_t OP_Joystick3Def, OP_Joystick4Def; #endif static void M_VideoModeMenu(INT32 choice); @@ -313,14 +307,16 @@ menu_t OP_VideoOptionsDef, OP_VideoModeDef; menu_t OP_OpenGLOptionsDef, OP_OpenGLFogDef, OP_OpenGLColorDef; #endif menu_t OP_SoundOptionsDef; -static void M_ToggleSFX(void); -static void M_ToggleDigital(void); -static void M_ToggleMIDI(void); +static void M_ToggleSFX(INT32 choice); +static void M_ToggleDigital(INT32 choice); +//static void M_ToggleMIDI(INT32 choice); +static void M_RestartAudio(void); //Misc -menu_t OP_DataOptionsDef, OP_ScreenshotOptionsDef, OP_EraseDataDef; +menu_t /*OP_DataOptionsDef,*/ OP_ScreenshotOptionsDef, OP_EraseDataDef; +menu_t OP_HUDOptionsDef, OP_ChatOptionsDef; menu_t OP_GameOptionsDef, OP_ServerOptionsDef; -menu_t OP_NetgameOptionsDef, OP_GametypeOptionsDef; +//menu_t OP_NetgameOptionsDef, OP_GametypeOptionsDef; menu_t OP_MonitorToggleDef; static void M_ScreenshotOptions(INT32 choice); static void M_EraseData(INT32 choice); @@ -332,16 +328,17 @@ static void M_DrawSkyRoom(void); static void M_DrawChecklist(void); static void M_DrawEmblemHints(void); static void M_DrawPauseMenu(void); +static void M_DrawLevelSelectOnly(boolean leftfade, boolean rightfade); static void M_DrawServerMenu(void); -static void M_DrawLevelSelectMenu(void); static void M_DrawImageDef(void); static void M_DrawLoad(void); static void M_DrawLevelStats(void); -static void M_DrawGameStats(void); static void M_DrawTimeAttackMenu(void); //static void M_DrawNightsAttackMenu(void); static void M_DrawSetupChoosePlayerMenu(void); static void M_DrawControl(void); +static void M_DrawVideoMenu(void); +static void M_DrawHUDOptions(void); static void M_DrawVideoMode(void); //static void M_DrawMonitorToggles(void); #ifdef HWRENDER @@ -350,7 +347,7 @@ static void M_OGL_DrawColorMenu(void); #endif #ifndef NONET static void M_DrawConnectMenu(void); -static void M_DrawConnectIPMenu(void); +static void M_DrawMPMainMenu(void); static void M_DrawRoomMenu(void); #endif static void M_DrawJoystick(void); @@ -365,7 +362,6 @@ static boolean M_QuitMultiPlayerMenu(void); static void M_HandleSoundTest(INT32 choice); static void M_HandleImageDef(INT32 choice); static void M_HandleLoadSave(INT32 choice); -static void M_HandleGameStats(INT32 choice); static void M_HandleLevelStats(INT32 choice); #ifndef NONET static void M_HandleConnectIP(INT32 choice); @@ -434,7 +430,7 @@ consvar_t cv_serversort = {"serversort", "Ping", CV_HIDEN | CV_CALL, serversort_ // autorecord demos for time attack static consvar_t cv_autorecord = {"autorecord", "Yes", 0, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; -CV_PossibleValue_t ghost_cons_t[] = {{0, "Hide"}, {1, "Show"}, {2, "Show All"}, {0, NULL}}; +CV_PossibleValue_t ghost_cons_t[] = {{0, "Hide"}, {1, "Show Character"}, {2, "Show All"}, {0, NULL}}; CV_PossibleValue_t ghost2_cons_t[] = {{0, "Hide"}, {1, "Show"}, {0, NULL}}; consvar_t cv_ghost_besttime = {"ghost_besttime", "Show All", CV_SAVE, ghost_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -446,6 +442,12 @@ consvar_t cv_ghost_staff = {"ghost_staff", "Show", CV_SAVE, ghost2_cons_ //Console variables used solely in the menu system. //todo: add a way to use non-console variables in the menu // or make these consvars legitimate like color or skin. +#ifndef NOFOURPLAYER +static void Dummysplitplayers_OnChange(void); +static CV_PossibleValue_t dummysplitplayers_cons_t[] = {{2, "Two"}, {3, "Three"}, {4, "Four"}, {0, NULL}}; +static consvar_t cv_dummysplitplayers = {"dummysplitplayers", "Two", CV_HIDEN|CV_CALL, dummysplitplayers_cons_t, Dummysplitplayers_OnChange, 0, NULL, NULL, 0, 0, NULL}; +#endif + static CV_PossibleValue_t dummyteam_cons_t[] = {{0, "Spectator"}, {1, "Red"}, {2, "Blue"}, {0, NULL}}; static CV_PossibleValue_t dummyscramble_cons_t[] = {{0, "Random"}, {1, "Points"}, {0, NULL}}; static CV_PossibleValue_t ringlimit_cons_t[] = {{0, "MIN"}, {9999, "MAX"}, {0, NULL}}; @@ -479,7 +481,12 @@ static menuitem_t MainMenu[] = { {IT_SUBMENU|IT_STRING, NULL, "Extras", &SR_UnlockChecklistDef, 84}, {IT_CALL |IT_STRING, NULL, "1 Player", M_SinglePlayerMenu, 92}, +#ifdef NONET +M_StartSplitServerMenu + {IT_CALL |IT_STRING, NULL, "Splitscreen", M_StartSplitServerMenu,100}, +#else {IT_SUBMENU|IT_STRING, NULL, "Multiplayer", &MP_MainDef, 100}, +#endif {IT_CALL |IT_STRING, NULL, "Options", M_Options, 108}, {IT_CALL |IT_STRING, NULL, "Quit Game", M_QuitSRB2, 116}, }; @@ -515,21 +522,22 @@ typedef enum // --------------------- static menuitem_t MPauseMenu[] = { - {IT_STRING | IT_SUBMENU, NULL, "Scramble Teams...", &MISC_ScrambleTeamDef, 16}, - {IT_STRING | IT_CALL, NULL, "Switch Map..." , M_MapChange, 24}, + {IT_STRING | IT_SUBMENU, NULL, "Scramble Teams...", &MISC_ScrambleTeamDef, 16}, + {IT_STRING | IT_CALL, NULL, "Switch Map..." , M_MapChange, 24}, {IT_CALL | IT_STRING, NULL, "Continue", M_SelectableClearMenus,40}, - {IT_CALL | IT_STRING, NULL, "Player 1 Setup", M_SetupMultiPlayer, 48}, // splitscreen - {IT_CALL | IT_STRING, NULL, "Player 2 Setup", M_SetupMultiPlayer2, 56}, // splitscreen + {IT_CALL | IT_STRING, NULL, "P1 Setup...", M_SetupMultiPlayer, 48}, // splitscreen + {IT_CALL | IT_STRING, NULL, "P2 Setup...", M_SetupMultiPlayer2, 56}, // splitscreen #ifndef NOFOURPLAYER - {IT_CALL | IT_STRING, NULL, "Player 3 Setup", M_SetupMultiPlayer3, 64}, // splitscreen - {IT_CALL | IT_STRING, NULL, "Player 4 Setup", M_SetupMultiPlayer4, 72}, // splitscreen + {IT_CALL | IT_STRING, NULL, "P3 Setup...", M_SetupMultiPlayer3, 64}, // splitscreen + {IT_CALL | IT_STRING, NULL, "P4 Setup...", M_SetupMultiPlayer4, 72}, // splitscreen #endif {IT_STRING | IT_CALL, NULL, "Spectate", M_ConfirmSpectate, 48}, {IT_STRING | IT_CALL, NULL, "Enter Game", M_ConfirmEnterGame, 48}, + {IT_STRING | IT_CALL, NULL, "Cancel Join", M_ConfirmSpectate, 48}, {IT_STRING | IT_SUBMENU, NULL, "Switch Team...", &MISC_ChangeTeamDef, 48}, - {IT_CALL | IT_STRING, NULL, "Player Setup", M_SetupMultiPlayer, 56}, // alone + {IT_CALL | IT_STRING, NULL, "Player Setup...", M_SetupMultiPlayer, 56}, // alone {IT_CALL | IT_STRING, NULL, "Options", M_Options, 64}, {IT_CALL | IT_STRING, NULL, "Return to Title", M_EndGame, 80}, @@ -550,6 +558,7 @@ typedef enum #endif mpause_spectate, mpause_entergame, + mpause_canceljoin, mpause_switchteam, mpause_psetup, mpause_options, @@ -607,9 +616,9 @@ static menuitem_t MISC_ChangeTeamMenu[] = static menuitem_t MISC_ChangeLevelMenu[] = { - {IT_STRING|IT_CVAR, NULL, "Game Type", &cv_newgametype, 30}, - {IT_STRING|IT_CVAR, NULL, "Level", &cv_nextmap, 60}, - {IT_WHITESTRING|IT_CALL, NULL, "Change Level", M_ChangeLevel, 120}, + {IT_STRING|IT_CVAR, NULL, "Game Type", &cv_newgametype, 68}, + {IT_STRING|IT_CVAR, NULL, "Level", &cv_nextmap, 78}, + {IT_WHITESTRING|IT_CALL, NULL, "Change Level", M_ChangeLevel, 130}, }; static menuitem_t MISC_HelpMenu[] = @@ -683,9 +692,8 @@ static menuitem_t SR_MainMenu[] = static menuitem_t SR_LevelSelectMenu[] = { - {IT_STRING|IT_CVAR, NULL, "Level", &cv_nextmap, 60}, - - {IT_WHITESTRING|IT_CALL, NULL, "Start", M_LevelSelectWarp, 120}, + {IT_STRING|IT_CVAR, NULL, "Level", &cv_nextmap, 78}, + {IT_WHITESTRING|IT_CALL, NULL, "Start", M_LevelSelectWarp, 130}, }; static menuitem_t SR_UnlockChecklistMenu[] = @@ -730,29 +738,30 @@ static menuitem_t SP_LoadGameMenu[] = // Single Player Level Select static menuitem_t SP_LevelSelectMenu[] = { - {IT_STRING|IT_CVAR, NULL, "Level", &cv_nextmap, 60}, - - {IT_WHITESTRING|IT_CALL, NULL, "Start", M_LevelSelectWarp, 120}, + {IT_STRING|IT_CVAR, NULL, "Level", &cv_nextmap, 78}, + {IT_WHITESTRING|IT_CALL, NULL, "Start", M_LevelSelectWarp, 130}, }; // Single Player Time Attack static menuitem_t SP_TimeAttackMenu[] = { - {IT_STRING|IT_CVAR, NULL, "Level", &cv_nextmap, 48}, - {IT_STRING|IT_CVAR, NULL, "Player", &cv_chooseskin, 58}, - {IT_STRING|IT_CVAR, NULL, "Color", &cv_playercolor, 68}, + {IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Name", &cv_playername, 0}, + {IT_STRING|IT_CVAR, NULL, "Character", &cv_chooseskin, 13}, + {IT_STRING|IT_CVAR, NULL, "Color", &cv_playercolor, 26}, + {IT_STRING|IT_CVAR, NULL, "Level", &cv_nextmap, 78}, - {IT_DISABLED, NULL, "Guest Option...", &SP_GuestReplayDef, 100}, - {IT_DISABLED, NULL, "Replay...", &SP_ReplayDef, 110}, - {IT_DISABLED, NULL, "Ghosts...", &SP_GhostDef, 120}, - {IT_WHITESTRING|IT_CALL|IT_CALL_NOTMODIFIED, NULL, "Start", M_ChooseTimeAttack, 130}, + {IT_DISABLED, NULL, "Guest...", &SP_GuestReplayDef, 98}, + {IT_DISABLED, NULL, "Replay...", &SP_ReplayDef, 108}, + {IT_WHITESTRING|IT_SUBMENU, NULL, "Ghosts...", &SP_GhostDef, 118}, + {IT_WHITESTRING|IT_CALL|IT_CALL_NOTMODIFIED, NULL, "Start", M_ChooseTimeAttack, 130}, }; enum { - talevel, + taname, taplayer, tacolor, + talevel, taguest, tareplay, @@ -762,14 +771,14 @@ enum static menuitem_t SP_ReplayMenu[] = { - {IT_WHITESTRING|IT_CALL, NULL, "Replay Best Time", M_ReplayTimeAttack, 0}, - {IT_WHITESTRING|IT_CALL, NULL, "Replay Best Lap", M_ReplayTimeAttack, 8}, + {IT_WHITESTRING|IT_CALL, NULL, "Replay Best Time", M_ReplayTimeAttack, 90}, + {IT_WHITESTRING|IT_CALL, NULL, "Replay Best Lap", M_ReplayTimeAttack, 98}, - {IT_WHITESTRING|IT_CALL, NULL, "Replay Last", M_ReplayTimeAttack,21}, - {IT_WHITESTRING|IT_CALL, NULL, "Replay Guest", M_ReplayTimeAttack,29}, - {IT_WHITESTRING|IT_KEYHANDLER, NULL, "Replay Staff",M_HandleStaffReplay,37}, + {IT_WHITESTRING|IT_CALL, NULL, "Replay Last", M_ReplayTimeAttack, 106}, + {IT_WHITESTRING|IT_CALL, NULL, "Replay Guest", M_ReplayTimeAttack, 114}, + {IT_WHITESTRING|IT_KEYHANDLER, NULL, "Replay Staff",M_HandleStaffReplay,122}, - {IT_WHITESTRING|IT_SUBMENU, NULL, "Back", &SP_TimeAttackDef, 50} + {IT_WHITESTRING|IT_SUBMENU, NULL, "Back", &SP_TimeAttackDef, 130} }; /*static menuitem_t SP_NightsReplayMenu[] = @@ -786,13 +795,13 @@ static menuitem_t SP_ReplayMenu[] = static menuitem_t SP_GuestReplayMenu[] = { - {IT_WHITESTRING|IT_CALL, NULL, "Save Best Time as Guest", M_SetGuestReplay, 8}, - {IT_WHITESTRING|IT_CALL, NULL, "Save Best Lap as Guest", M_SetGuestReplay,16}, - {IT_WHITESTRING|IT_CALL, NULL, "Save Last as Guest", M_SetGuestReplay,24}, + {IT_WHITESTRING|IT_CALL, NULL, "Save Best Time as Guest", M_SetGuestReplay, 94}, + {IT_WHITESTRING|IT_CALL, NULL, "Save Best Lap as Guest", M_SetGuestReplay,102}, + {IT_WHITESTRING|IT_CALL, NULL, "Save Last as Guest", M_SetGuestReplay,110}, - {IT_WHITESTRING|IT_CALL, NULL, "Delete Guest Replay", M_SetGuestReplay,37}, + {IT_WHITESTRING|IT_CALL, NULL, "Delete Guest Replay", M_SetGuestReplay,120}, - {IT_WHITESTRING|IT_SUBMENU, NULL, "Back", &SP_TimeAttackDef, 50} + {IT_WHITESTRING|IT_SUBMENU, NULL, "Back", &SP_TimeAttackDef, 130} }; /*static menuitem_t SP_NightsGuestReplayMenu[] = @@ -808,14 +817,13 @@ static menuitem_t SP_GuestReplayMenu[] = static menuitem_t SP_GhostMenu[] = { - {IT_STRING|IT_CVAR, NULL, "Best Time", &cv_ghost_besttime, 0}, - {IT_STRING|IT_CVAR, NULL, "Best Lap", &cv_ghost_bestlap, 8}, - {IT_STRING|IT_CVAR, NULL, "Last", &cv_ghost_last, 16}, + {IT_STRING|IT_CVAR, NULL, "Best Time", &cv_ghost_besttime, 88}, + {IT_STRING|IT_CVAR, NULL, "Best Lap", &cv_ghost_bestlap, 96}, + {IT_STRING|IT_CVAR, NULL, "Last", &cv_ghost_last, 104}, + {IT_DISABLED, NULL, "Guest", &cv_ghost_guest, 112}, + {IT_DISABLED, NULL, "Staff Attack",&cv_ghost_staff, 120}, - {IT_STRING|IT_CVAR, NULL, "Guest", &cv_ghost_guest, 29}, - {IT_STRING|IT_CVAR, NULL, "Staff Attack",&cv_ghost_staff, 37}, - - {IT_WHITESTRING|IT_SUBMENU, NULL, "Back", &SP_TimeAttackDef, 50} + {IT_WHITESTRING|IT_SUBMENU, NULL, "Back", &SP_TimeAttackDef, 130} }; /*static menuitem_t SP_NightsGhostMenu[] = @@ -854,11 +862,6 @@ enum }; // Statistics -static menuitem_t SP_GameStatsMenu[] = -{ - {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleGameStats, '\0'}, // dummy menuitem for the control func -}; - static menuitem_t SP_LevelStatsMenu[] = { {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleLevelStats, '\0'}, // dummy menuitem for the control func @@ -907,52 +910,79 @@ menuitem_t PlayerMenu[32] = // Multiplayer and all of its submenus // ----------------------------------- // Prefix: MP_ + +#ifndef NONET + static menuitem_t MP_MainMenu[] = { -#ifndef NONET - {IT_CALL | IT_STRING, NULL, "HOST GAME", M_StartServerMenu, 10}, - {IT_CALL | IT_STRING, NULL, "JOIN GAME (Search)", M_ConnectMenu, 30}, - {IT_CALL | IT_STRING, NULL, "JOIN GAME (Specify IP)", M_ConnectIPMenu, 40}, -#endif - - {IT_CALL | IT_STRING, NULL, "TWO PLAYER GAME", M_StartSplitServerMenu, 60}, - -#ifdef NOFOURPLAYER - {IT_CALL | IT_STRING, NULL, "SETUP PLAYER 1", M_SetupMultiPlayer, 80}, - {IT_CALL | IT_STRING, NULL, "SETUP PLAYER 2", M_SetupMultiPlayer2, 90}, -#else - {IT_CALL | IT_STRING, NULL, "THREE PLAYER GAME", M_Start3PServerMenu, 70}, - {IT_CALL | IT_STRING, NULL, "FOUR PLAYER GAME", M_Start4PServerMenu, 80}, - - {IT_CALL | IT_STRING, NULL, "SETUP PLAYER 1", M_SetupMultiPlayer, 100}, - {IT_CALL | IT_STRING, NULL, "SETUP PLAYER 2", M_SetupMultiPlayer2, 110}, - {IT_CALL | IT_STRING, NULL, "SETUP PLAYER 3", M_SetupMultiPlayer3, 120}, - {IT_CALL | IT_STRING, NULL, "SETUP PLAYER 4", M_SetupMultiPlayer4, 130}, -#endif + {IT_HEADER, NULL, "Host a game", NULL, 0}, + {IT_STRING|IT_CALL, NULL, "Internet/LAN...", M_StartServerMenu, 10}, + {IT_STRING|IT_CALL, NULL, "Splitscreen...", M_StartSplitServerMenu, 18}, + {IT_HEADER, NULL, "Join a game", NULL, 32}, + {IT_STRING|IT_CALL, NULL, "Server browser...", M_ConnectMenu, 42}, + {IT_STRING|IT_KEYHANDLER, NULL, "Specify IPv4 address:", M_HandleConnectIP, 50}, + {IT_HEADER, NULL, "Player setup", NULL, 80}, + {IT_STRING|IT_CALL, NULL, "Name, character, color...", M_SetupMultiPlayer, 90}, }; +#endif + static menuitem_t MP_ServerMenu[] = { - {IT_STRING|IT_CVAR, NULL, "Game Type", &cv_newgametype, 10}, + {IT_STRING|IT_CVAR, NULL, "Max. Player Count", &cv_maxplayers, 10}, #ifndef NONET - {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_CALL, NULL, "Room...", M_RoomMenu, 20}, + {IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Server Name", &cv_servername, 30}, #endif - {IT_STRING|IT_CVAR, NULL, "Level", &cv_nextmap, 80}, + {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}, }; -enum +// Separated splitscreen and normal servers. +static menuitem_t MP_SplitServerMenu[] = { - mp_server_gametype = 0, -#ifndef NONET - mp_server_room, - mp_server_name, +#ifndef NOFOURPLAYER + {IT_STRING|IT_CVAR, NULL, "Number of players", &cv_dummysplitplayers, 10}, #endif - mp_server_level, - mp_server_start + + {IT_STRING|IT_CVAR, NULL, "Game Type", &cv_newgametype, 68}, + {IT_STRING|IT_CVAR, NULL, "Level", &cv_nextmap, 78}, +#ifdef NOFOURPLAYER + {IT_STRING|IT_CALL, NULL, "P1 Setup...", M_SetupMultiPlayer, 110}, + {IT_STRING|IT_CALL, NULL, "P2 Setup... ", M_SetupMultiPlayer2, 120}, +#else + {IT_STRING|IT_CALL, NULL, "P1 Setup...", M_SetupMultiPlayer, 90}, + {IT_STRING|IT_CALL, NULL, "P2 Setup... ", M_SetupMultiPlayer2, 100}, + {IT_GRAYEDOUT, NULL, "P3 Setup...", M_SetupMultiPlayer3, 110}, + {IT_GRAYEDOUT, NULL, "P4 Setup... ", M_SetupMultiPlayer4, 120}, +#endif + {IT_WHITESTRING|IT_CALL, NULL, "Start", M_StartServer, 130}, +}; + +#ifndef NOFOURPLAYER +static void Dummysplitplayers_OnChange(void) +{ + UINT8 i = 2; // player 2 is the last unchanging setup + + while (i < 4) + { + if (i < cv_dummysplitplayers.value) + MP_SplitServerMenu[3+i].status = IT_STRING|IT_CALL; + else + MP_SplitServerMenu[3+i].status = IT_GRAYEDOUT; + i++; + } +} +#endif + +static menuitem_t MP_PlayerSetupMenu[] = +{ + {IT_KEYHANDLER | IT_STRING, NULL, "Name", M_HandleSetupMultiPlayer, 0}, + {IT_KEYHANDLER | IT_STRING, NULL, "Character", M_HandleSetupMultiPlayer, 16}, // Tails 01-18-2001 + {IT_KEYHANDLER | IT_STRING, NULL, "Color", M_HandleSetupMultiPlayer, 152}, }; #ifndef NONET @@ -1006,156 +1036,87 @@ static menuitem_t MP_RoomMenu[] = {IT_DISABLED, NULL, "", M_ChooseRoom, 153}, {IT_DISABLED, NULL, "", M_ChooseRoom, 162}, }; - -static menuitem_t MP_ConnectIPMenu[] = -{ - {IT_KEYHANDLER | IT_STRING, NULL, " IP Address:", M_HandleConnectIP, 0}, -}; #endif -// Separated splitscreen and normal servers. -static menuitem_t MP_SplitServerMenu[] = -{ - {IT_STRING|IT_CVAR, NULL, "Game Type", &cv_newgametype, 10}, - {IT_STRING|IT_CVAR, NULL, "Level", &cv_nextmap, 80}, - {IT_WHITESTRING|IT_CALL, NULL, "Start", M_StartServer, 130}, -}; - -static menuitem_t MP_PlayerSetupMenu[] = -{ - {IT_KEYHANDLER | IT_STRING, NULL, "Name", M_HandleSetupMultiPlayer, 0}, - {IT_KEYHANDLER | IT_STRING, NULL, "Character", M_HandleSetupMultiPlayer, 16}, // Tails 01-18-2001 - {IT_KEYHANDLER | IT_STRING, NULL, "Color", M_HandleSetupMultiPlayer, 152}, -}; - // ------------------------------------ // Options and most (?) of its submenus // ------------------------------------ // Prefix: OP_ static menuitem_t OP_MainMenu[] = { - {IT_SUBMENU | IT_STRING, NULL, "Setup Controls...", &OP_ControlsDef, 10}, + {IT_SUBMENU|IT_STRING, NULL, "Control Setup...", &OP_ControlsDef, 10}, - {IT_SUBMENU | IT_STRING, NULL, "Video Options...", &OP_VideoOptionsDef, 30}, - {IT_SUBMENU | IT_STRING, NULL, "Sound Options...", &OP_SoundOptionsDef, 40}, - {IT_SUBMENU | IT_STRING, NULL, "Data Options...", &OP_DataOptionsDef, 50}, + {IT_SUBMENU|IT_STRING, NULL, "Video Options...", &OP_VideoOptionsDef, 30}, + {IT_SUBMENU|IT_STRING, NULL, "Sound Options...", &OP_SoundOptionsDef, 40}, - {IT_SUBMENU | IT_STRING, NULL, "Game Options...", &OP_GameOptionsDef, 70}, - {IT_SUBMENU | IT_STRING, NULL, "Server Options...", &OP_ServerOptionsDef, 80}, + {IT_SUBMENU|IT_STRING, NULL, "HUD Options...", &OP_HUDOptionsDef, 60}, + {IT_STRING|IT_CALL, NULL, "Screenshot Options...", M_ScreenshotOptions, 70}, - {IT_CALL | IT_STRING, NULL, "Play Credits", M_Credits, 100}, - {IT_KEYHANDLER | IT_STRING, NULL, "Sound Test", M_HandleSoundTest, 110}, + {IT_SUBMENU|IT_STRING, NULL, "Gameplay Options...", &OP_GameOptionsDef, 90}, + {IT_SUBMENU|IT_STRING, NULL, "Server Options...", &OP_ServerOptionsDef, 100}, + + {IT_CALL|IT_STRING, NULL, "Play Credits", M_Credits, 120}, + {IT_SUBMENU|IT_STRING, NULL, "Erase Data...", &OP_EraseDataDef, 130}, }; static menuitem_t OP_ControlsMenu[] = { - {IT_SUBMENU | IT_STRING, NULL, "Player 1 Controls...", &OP_P1ControlsDef, 10}, - {IT_SUBMENU | IT_STRING, NULL, "Player 2 Controls...", &OP_P2ControlsDef, 20}, + {IT_CALL | IT_STRING, NULL, "Player 1 Controls...", M_Setup1PControlsMenu, 10}, + {IT_CALL | IT_STRING, NULL, "Player 2 Controls...", M_Setup2PControlsMenu, 20}, #ifdef NOFOURPLAYER {IT_STRING | IT_CVAR, NULL, "Controls per key", &cv_controlperkey, 40}, #else - {IT_SUBMENU | IT_STRING, NULL, "Player 3 Controls...", &OP_P3ControlsDef, 30}, - {IT_SUBMENU | IT_STRING, NULL, "Player 4 Controls...", &OP_P4ControlsDef, 40}, + {IT_CALL | IT_STRING, NULL, "Player 3 Controls...", &M_Setup3PControlsMenu, 30}, + {IT_CALL | IT_STRING, NULL, "Player 4 Controls...", &M_Setup4PControlsMenu, 40}, {IT_STRING | IT_CVAR, NULL, "Controls per key", &cv_controlperkey, 60}, #endif }; -static menuitem_t OP_P1ControlsMenu[] = -{ - {IT_CALL | IT_STRING, NULL, "Control Configuration...", M_Setup1PControlsMenu, 10}, - //{IT_SUBMENU | IT_STRING, NULL, "Mouse Options...", &OP_MouseOptionsDef, 20}, - {IT_SUBMENU | IT_STRING, NULL, "Joystick Options...", &OP_Joystick1Def , 20}, - - {IT_STRING | IT_CVAR, NULL, "Camera" , &cv_chasecam , 40}, - {IT_STRING | IT_CVAR, NULL, "Crosshair", &cv_crosshair , 50}, - - //{IT_STRING | IT_CVAR, NULL, "Analog Control", &cv_useranalog, 80}, -}; - -static menuitem_t OP_P2ControlsMenu[] = -{ - {IT_CALL | IT_STRING, NULL, "Control Configuration...", M_Setup2PControlsMenu, 10}, - //{IT_SUBMENU | IT_STRING, NULL, "Second Mouse Options...", &OP_Mouse2OptionsDef, 20}, - {IT_SUBMENU | IT_STRING, NULL, "Second Joystick Options...", &OP_Joystick2Def , 20}, - - {IT_STRING | IT_CVAR, NULL, "Camera" , &cv_chasecam2 , 40}, - {IT_STRING | IT_CVAR, NULL, "Crosshair", &cv_crosshair2, 50}, - - //{IT_STRING | IT_CVAR, NULL, "Analog Control", &cv_useranalog2, 70}, -}; - -#ifndef NOFOURPLAYER -static menuitem_t OP_P3ControlsMenu[] = -{ - {IT_CALL | IT_STRING, NULL, "Control Configuration...", M_Setup3PControlsMenu, 10}, - {IT_SUBMENU | IT_STRING, NULL, "Third Joystick Options...", &OP_Joystick3Def , 20}, - - {IT_STRING | IT_CVAR, NULL, "Camera" , &cv_chasecam3 , 40}, - {IT_STRING | IT_CVAR, NULL, "Crosshair", &cv_crosshair3, 50}, - - //{IT_STRING | IT_CVAR, NULL, "Analog Control", &cv_useranalog3, 60}, -}; - -static menuitem_t OP_P4ControlsMenu[] = -{ - {IT_CALL | IT_STRING, NULL, "Control Configuration...", M_Setup4PControlsMenu, 10}, - {IT_SUBMENU | IT_STRING, NULL, "Fourth Joystick Options...", &OP_Joystick4Def , 20}, - - {IT_STRING | IT_CVAR, NULL, "Camera" , &cv_chasecam4 , 40}, - {IT_STRING | IT_CVAR, NULL, "Crosshair", &cv_crosshair4, 50}, - - //{IT_STRING | IT_CVAR, NULL, "Analog Control", &cv_useranalog4, 60}, -}; -#endif - -/*static menuitem_t OP_ControlListMenu[] = -{ - {IT_SUBMENU | IT_STRING, NULL, "Kart Controls...", &OP_MoveControlsDef, 10}, -// {IT_SUBMENU | IT_STRING, NULL, "Multiplayer Controls...", &OP_MPControlsDef, 20}, -// {IT_SUBMENU | IT_STRING, NULL, "Camera Controls...", &OP_CameraControlsDef, 20}, -// {IT_SUBMENU | IT_STRING, NULL, "Miscellaneous Controls...", &OP_MiscControlsDef, 20}, -};*/ - static menuitem_t OP_MoveControlsMenu[] = { - {IT_CALL | IT_STRING2, NULL, "Aim Forward", M_ChangeControl, gc_aimforward }, - {IT_CALL | IT_STRING2, NULL, "Aim Backward", M_ChangeControl, gc_aimbackward}, - {IT_CALL | IT_STRING2, NULL, "Turn Left", M_ChangeControl, gc_turnleft }, - {IT_CALL | IT_STRING2, NULL, "Turn Right", M_ChangeControl, gc_turnright }, - {IT_CALL | IT_STRING2, NULL, "Accelerate", M_ChangeControl, gc_accelerate }, - {IT_CALL | IT_STRING2, NULL, "Drift", M_ChangeControl, gc_drift }, - {IT_CALL | IT_STRING2, NULL, "Brake", M_ChangeControl, gc_brake }, - {IT_CALL | IT_STRING2, NULL, "Use/Throw Item", M_ChangeControl, gc_fire }, - {IT_CALL | IT_STRING2, NULL, "Look Backward", M_ChangeControl, gc_lookback }, + {IT_CONTROL, NULL, "Accelerate", M_ChangeControl, gc_accelerate }, + {IT_CONTROL, NULL, "Turn Left", M_ChangeControl, gc_turnleft }, + {IT_CONTROL, NULL, "Turn Right", M_ChangeControl, gc_turnright }, + {IT_CONTROL, NULL, "Drift", M_ChangeControl, gc_drift }, + {IT_CONTROL, NULL, "Brake", M_ChangeControl, gc_brake }, + {IT_CONTROL, NULL, "Use/Throw Item", M_ChangeControl, gc_fire }, + {IT_CONTROL, NULL, "Aim Forward", M_ChangeControl, gc_aimforward }, + {IT_CONTROL, NULL, "Aim Backward", M_ChangeControl, gc_aimbackward}, + {IT_CONTROL, NULL, "Look Backward", M_ChangeControl, gc_lookback }, - {IT_CALL | IT_STRING2, NULL, "Talk key", M_ChangeControl, gc_talkkey }, - {IT_CALL | IT_STRING2, NULL, "Team-Talk key", M_ChangeControl, gc_teamkey }, - {IT_CALL | IT_STRING2, NULL, "Rankings/Scores", M_ChangeControl, gc_scores }, + {IT_SPACE, NULL, "", NULL, 76}, + {IT_CONTROL, NULL, "Talk key", M_ChangeControl, gc_talkkey }, + //{IT_CONTROL, NULL, "Team-Talk key", M_ChangeControl, gc_teamkey }, + {IT_CONTROL, NULL, "Rankings/Scores", M_ChangeControl, gc_scores }, + {IT_CONTROL, NULL, "Open/Close Menu (ESC)", M_ChangeControl, gc_systemmenu}, + {IT_CONTROL, NULL, "Pause", M_ChangeControl, gc_pause }, + {IT_CONTROL, NULL, "Console", M_ChangeControl, gc_console }, - {IT_CALL | IT_STRING2, NULL, "Pause", M_ChangeControl, gc_pause }, - {IT_CALL | IT_STRING2, NULL, "Console", M_ChangeControl, gc_console }, - - {IT_SUBMENU | IT_STRING, NULL, "Spectator Controls...", &OP_SpectateControlsDef, 112}, - {IT_SUBMENU | IT_STRING, NULL, "Custom Lua Actions...", &OP_CustomControlsDef, 120}, + {IT_SUBMENU | IT_STRING, NULL, "Gamepad Options...", &OP_Joystick1Def, 120}, + {IT_SUBMENU | IT_STRING, NULL, "Spectator Controls...", &OP_SpectateControlsDef, 128}, + {IT_SUBMENU | IT_STRING, NULL, "Custom Lua Actions...", &OP_CustomControlsDef, 136}, }; static menuitem_t OP_SpectateControlsMenu[] = { - {IT_CALL | IT_STRING2, NULL, "Spectate", M_ChangeControl, gc_spectate }, - {IT_CALL | IT_STRING2, NULL, "Look Up", M_ChangeControl, gc_lookup }, - {IT_CALL | IT_STRING2, NULL, "Look Down", M_ChangeControl, gc_lookdown }, - {IT_CALL | IT_STRING2, NULL, "Center View", M_ChangeControl, gc_centerview}, - {IT_CALL | IT_STRING2, NULL, "Reset Camera", M_ChangeControl, gc_camreset }, - {IT_CALL | IT_STRING2, NULL, "Toggle Chasecam", M_ChangeControl, gc_camtoggle }, + {IT_CONTROL, NULL, "Become Spectator", M_ChangeControl, gc_spectate }, + {IT_CONTROL, NULL, "Look Up", M_ChangeControl, gc_lookup }, + {IT_CONTROL, NULL, "Look Down", M_ChangeControl, gc_lookdown }, + {IT_CONTROL, NULL, "Center View", M_ChangeControl, gc_centerview}, + {IT_CONTROL, NULL, "Reset Camera", M_ChangeControl, gc_camreset }, + {IT_CONTROL, NULL, "Toggle Chasecam", M_ChangeControl, gc_camtoggle }, + + {IT_STRING | IT_CVAR, NULL, "Chasecam" , &cv_chasecam , 52}, + {IT_STRING | IT_CVAR, NULL, "Crosshair", &cv_crosshair, 60}, }; static menuitem_t OP_CustomControlsMenu[] = { - {IT_CALL | IT_STRING2, NULL, "Custom Action 1", M_ChangeControl, gc_custom1}, - {IT_CALL | IT_STRING2, NULL, "Custom Action 2", M_ChangeControl, gc_custom2}, - {IT_CALL | IT_STRING2, NULL, "Custom Action 3", M_ChangeControl, gc_custom3}, + {IT_CONTROL, NULL, "Custom Action 1", M_ChangeControl, gc_custom1}, + {IT_CONTROL, NULL, "Custom Action 2", M_ChangeControl, gc_custom2}, + {IT_CONTROL, NULL, "Custom Action 3", M_ChangeControl, gc_custom3}, }; // Obsolete thanks to Kart @@ -1197,7 +1158,7 @@ static menuitem_t OP_MiscControlsMenu[] = static menuitem_t OP_Joystick1Menu[] = { - {IT_STRING | IT_CALL, NULL, "Select Joystick..." , M_Setup1PJoystickMenu, 10}, + {IT_STRING | IT_CALL, NULL, "Select Gamepad..." , M_Setup1PJoystickMenu, 10}, {IT_STRING | IT_CVAR, NULL, "Aim Forward/Back" , &cv_aimaxis , 30}, {IT_STRING | IT_CVAR, NULL, "Turn Left/Right" , &cv_turnaxis , 40}, {IT_STRING | IT_CVAR, NULL, "Accelerate" , &cv_moveaxis , 50}, @@ -1209,7 +1170,7 @@ static menuitem_t OP_Joystick1Menu[] = static menuitem_t OP_Joystick2Menu[] = { - {IT_STRING | IT_CALL, NULL, "Select Joystick..." , M_Setup2PJoystickMenu, 10}, + {IT_STRING | IT_CALL, NULL, "Select Gamepad..." , M_Setup2PJoystickMenu, 10}, {IT_STRING | IT_CVAR, NULL, "Aim Forward/Back" , &cv_aimaxis2 , 30}, {IT_STRING | IT_CVAR, NULL, "Turn Left/Right" , &cv_turnaxis2 , 40}, {IT_STRING | IT_CVAR, NULL, "Accelerate" , &cv_moveaxis2 , 50}, @@ -1222,7 +1183,7 @@ static menuitem_t OP_Joystick2Menu[] = #ifndef NOFOURPLAYER static menuitem_t OP_Joystick3Menu[] = { - {IT_STRING | IT_CALL, NULL, "Select Joystick..." , M_Setup3PJoystickMenu, 10}, + {IT_STRING | IT_CALL, NULL, "Select Gamepad..." , M_Setup3PJoystickMenu, 10}, {IT_STRING | IT_CVAR, NULL, "Aim Forward/Back" , &cv_aimaxis3 , 30}, {IT_STRING | IT_CVAR, NULL, "Turn Left/Right" , &cv_turnaxis3 , 40}, {IT_STRING | IT_CVAR, NULL, "Accelerate" , &cv_moveaxis3 , 50}, @@ -1234,7 +1195,7 @@ static menuitem_t OP_Joystick3Menu[] = static menuitem_t OP_Joystick4Menu[] = { - {IT_STRING | IT_CALL, NULL, "Select Joystick..." , M_Setup4PJoystickMenu, 10}, + {IT_STRING | IT_CALL, NULL, "Select Gamepad..." , M_Setup4PJoystickMenu, 10}, {IT_STRING | IT_CVAR, NULL, "Aim Forward/Back" , &cv_aimaxis4 , 30}, {IT_STRING | IT_CVAR, NULL, "Turn Left/Right" , &cv_turnaxis4 , 40}, {IT_STRING | IT_CVAR, NULL, "Accelerate" , &cv_moveaxis4 , 50}, @@ -1247,16 +1208,17 @@ static menuitem_t OP_Joystick4Menu[] = static menuitem_t OP_JoystickSetMenu[] = { - {IT_CALL | IT_NOTHING, "None", NULL, M_AssignJoystick, '0'}, - {IT_CALL | IT_NOTHING, "", NULL, M_AssignJoystick, '1'}, - {IT_CALL | IT_NOTHING, "", NULL, M_AssignJoystick, '2'}, - {IT_CALL | IT_NOTHING, "", NULL, M_AssignJoystick, '3'}, - {IT_CALL | IT_NOTHING, "", NULL, M_AssignJoystick, '4'}, - {IT_CALL | IT_NOTHING, "", NULL, M_AssignJoystick, '5'}, - {IT_CALL | IT_NOTHING, "", NULL, M_AssignJoystick, '6'}, + {IT_CALL | IT_NOTHING, "None", NULL, M_AssignJoystick, LINEHEIGHT+5}, + {IT_CALL | IT_NOTHING, "", NULL, M_AssignJoystick, (LINEHEIGHT*2)+5}, + {IT_CALL | IT_NOTHING, "", NULL, M_AssignJoystick, (LINEHEIGHT*3)+5}, + {IT_CALL | IT_NOTHING, "", NULL, M_AssignJoystick, (LINEHEIGHT*4)+5}, + {IT_CALL | IT_NOTHING, "", NULL, M_AssignJoystick, (LINEHEIGHT*5)+5}, + {IT_CALL | IT_NOTHING, "", NULL, M_AssignJoystick, (LINEHEIGHT*6)+5}, + {IT_CALL | IT_NOTHING, "", NULL, M_AssignJoystick, (LINEHEIGHT*7)+5}, + {IT_CALL | IT_NOTHING, "", NULL, M_AssignJoystick, (LINEHEIGHT*8)+5}, }; -static menuitem_t OP_MouseOptionsMenu[] = +/*static menuitem_t OP_MouseOptionsMenu[] = { {IT_STRING | IT_CVAR, NULL, "Use Mouse", &cv_usemouse, 10}, @@ -1282,30 +1244,47 @@ static menuitem_t OP_Mouse2OptionsMenu[] = NULL, "Mouse X Speed", &cv_mousesens2, 60}, {IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Mouse Y Speed", &cv_mouseysens2, 70}, -}; +};*/ static menuitem_t OP_VideoOptionsMenu[] = { - {IT_STRING | IT_CALL, NULL, "Video Modes...", M_VideoModeMenu, 10}, + {IT_STRING | IT_CALL, NULL, "Set Resolution...", M_VideoModeMenu, 10}, +#if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL) + {IT_STRING|IT_CVAR, NULL, "Fullscreen", &cv_fullscreen, 20}, +#endif + {IT_STRING | IT_CVAR | IT_CV_SLIDER, + NULL, "Gamma", &cv_usegamma, 30}, + + {IT_STRING | IT_CVAR, NULL, "Draw Distance", &cv_drawdist, 45}, + //{IT_STRING | IT_CVAR, NULL, "NiGHTS Draw Dist", &cv_drawdist_nights, 55}, + {IT_STRING | IT_CVAR, NULL, "Weather Draw Distance",&cv_drawdist_precip, 55}, + {IT_STRING | IT_CVAR, NULL, "Weather Density", &cv_precipdensity, 65}, + {IT_STRING | IT_CVAR, NULL, "Skyboxes", &cv_skybox, 75}, + + {IT_STRING | IT_CVAR, NULL, "Show FPS", &cv_ticrate, 90}, + {IT_STRING | IT_CVAR, NULL, "Vertical Sync", &cv_vidwait, 100}, #ifdef HWRENDER - {IT_SUBMENU|IT_STRING, NULL, "3D Card Options...", &OP_OpenGLOptionsDef, 20}, + {IT_SUBMENU|IT_STRING, NULL, "OpenGL Options...", &OP_OpenGLOptionsDef, 115}, #endif +}; +enum +{ + op_video_res = 0, #if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL) - {IT_STRING|IT_CVAR, NULL, "Fullscreen", &cv_fullscreen, 30}, + op_video_fullscreen, +#endif + op_video_gamma, + op_video_dd, + op_video_wdd, + op_video_wd, + op_video_skybox, + op_video_fps, + op_video_vsync, +#ifdef HWRENDER + op_video_ogl, #endif - - {IT_STRING | IT_CVAR | IT_CV_SLIDER, - NULL, "Brightness", &cv_usegamma, 50}, - {IT_STRING | IT_CVAR, NULL, "Draw Distance", &cv_drawdist, 60}, - {IT_STRING | IT_CVAR, NULL, "NiGHTS Draw Dist", &cv_drawdist_nights, 70}, - {IT_STRING | IT_CVAR, NULL, "Precip Draw Dist", &cv_drawdist_precip, 80}, - {IT_STRING | IT_CVAR, NULL, "Precip Density", &cv_precipdensity, 90}, - - {IT_STRING | IT_CVAR, NULL, "Show FPS", &cv_ticrate, 110}, - {IT_STRING | IT_CVAR, NULL, "Clear Before Redraw", &cv_homremoval, 120}, - {IT_STRING | IT_CVAR, NULL, "Vertical Sync", &cv_vidwait, 130}, }; static menuitem_t OP_VideoModeMenu[] = @@ -1316,7 +1295,7 @@ static menuitem_t OP_VideoModeMenu[] = #ifdef HWRENDER static menuitem_t OP_OpenGLOptionsMenu[] = { - {IT_STRING|IT_CVAR, NULL, "Field of view", &cv_grfov, 10}, + {IT_STRING|IT_CVAR, NULL, "Field of View", &cv_grfov, 10}, {IT_STRING|IT_CVAR, NULL, "Quality", &cv_scr_depth, 20}, {IT_STRING|IT_CVAR, NULL, "Texture Filter", &cv_grfiltermode, 30}, {IT_STRING|IT_CVAR, NULL, "Anisotropic", &cv_granisotropicmode,40}, @@ -1343,43 +1322,56 @@ static menuitem_t OP_OpenGLLightingMenu[] = static menuitem_t OP_OpenGLFogMenu[] = { {IT_STRING|IT_CVAR, NULL, "Fog", &cv_grfog, 10}, - {IT_STRING|IT_KEYHANDLER, NULL, "Fog color", M_HandleFogColor, 20}, - {IT_STRING|IT_CVAR, NULL, "Fog density", &cv_grfogdensity, 30}, + {IT_STRING|IT_KEYHANDLER, NULL, "Fog Color", M_HandleFogColor, 20}, + {IT_STRING|IT_CVAR, NULL, "Fog Density", &cv_grfogdensity, 30}, {IT_STRING|IT_CVAR, NULL, "Software Fog",&cv_grsoftwarefog,40}, }; static menuitem_t OP_OpenGLColorMenu[] = { - {IT_STRING|IT_CVAR|IT_CV_SLIDER, NULL, "red", &cv_grgammared, 10}, - {IT_STRING|IT_CVAR|IT_CV_SLIDER, NULL, "green", &cv_grgammagreen, 20}, - {IT_STRING|IT_CVAR|IT_CV_SLIDER, NULL, "blue", &cv_grgammablue, 30}, + {IT_STRING|IT_CVAR|IT_CV_SLIDER, NULL, "Red", &cv_grgammared, 10}, + {IT_STRING|IT_CVAR|IT_CV_SLIDER, NULL, "Green", &cv_grgammagreen, 20}, + {IT_STRING|IT_CVAR|IT_CV_SLIDER, NULL, "Blue", &cv_grgammablue, 30}, }; #endif static menuitem_t OP_SoundOptionsMenu[] = { - {IT_STRING | IT_CVAR | IT_CV_SLIDER, - NULL, "Sound Volume" , &cv_soundvolume, 10}, - {IT_STRING | IT_CVAR | IT_CV_SLIDER, - NULL, "Music Volume" , &cv_digmusicvolume, 20}, - {IT_STRING | IT_CVAR | IT_CV_SLIDER, - NULL, "MIDI Volume" , &cv_midimusicvolume, 30}, -#ifdef PC_DOS - {IT_STRING | IT_CVAR | IT_CV_SLIDER, - NULL, "CD Volume" , &cd_volume, 40}, -#endif + {IT_KEYHANDLER|IT_STRING, NULL, "SFX", M_ToggleSFX, 10}, + {IT_STRING|IT_CVAR|IT_CV_SLIDER, + NULL, "SFX Volume", &cv_soundvolume, 18}, - {IT_STRING | IT_CALL, NULL, "Toggle SFX" , M_ToggleSFX, 50}, - {IT_STRING | IT_CALL, NULL, "Toggle Digital Music", M_ToggleDigital, 60}, - {IT_STRING | IT_CALL, NULL, "Toggle MIDI Music", M_ToggleMIDI, 70}, + {IT_KEYHANDLER|IT_STRING, NULL, "Music", M_ToggleDigital, 30}, + {IT_STRING|IT_CVAR|IT_CV_SLIDER, + NULL, "Music Volume", &cv_digmusicvolume, 38}, + +/* -- :nonnathisshit: + {IT_KEYHANDLER|IT_STRING, NULL, "MIDI", M_ToggleMIDI, 50}, + {IT_STRING|IT_CVAR|IT_CV_SLIDER, + NULL, "MIDI Volume", &cv_midimusicvolume, 58}, +#ifdef PC_DOS + {IT_STRING|IT_CVAR|IT_CV_SLIDER, + NULL, "CD Volume", &cd_volume, 40}, +#endif*/ + + {IT_STRING|IT_CALL, NULL, "Restart Audio System", M_RestartAudio, 50}, + + {IT_STRING|IT_CVAR, NULL, "Reverse L/R Channels", &stereoreverse, 65}, + {IT_STRING|IT_CVAR, NULL, "Surround Sound", &surround, 75}, + + {IT_STRING|IT_CVAR, NULL, "Chat sounds", &cv_chatnotifications, 90}, + {IT_STRING|IT_CVAR, NULL, "Character voices", &cv_kartvoices, 100}, + {IT_STRING|IT_CVAR, NULL, "Powerup Warning", &cv_kartinvinsfx, 110}, + + {IT_KEYHANDLER|IT_STRING, NULL, "Sound Test", M_HandleSoundTest, 125}, }; -static menuitem_t OP_DataOptionsMenu[] = +/*static menuitem_t OP_DataOptionsMenu[] = { {IT_STRING | IT_CALL, NULL, "Screenshot Options...", M_ScreenshotOptions, 10}, {IT_STRING | IT_SUBMENU, NULL, "Erase Data...", &OP_EraseDataDef, 30}, -}; +};*/ static menuitem_t OP_ScreenshotOptionsMenu[] = { @@ -1417,63 +1409,84 @@ enum static menuitem_t OP_EraseDataMenu[] = { {IT_STRING | IT_CALL, NULL, "Erase Record Data", M_EraseData, 10}, - {IT_STRING | IT_CALL, NULL, "Erase Secrets Data", M_EraseData, 20}, + {IT_STRING | IT_CALL, NULL, "Erase Unlockable Data", M_EraseData, 20}, {IT_STRING | IT_CALL, NULL, "\x85" "Erase ALL Data", M_EraseData, 40}, }; +static menuitem_t OP_HUDOptionsMenu[] = +{ + {IT_STRING | IT_CVAR, NULL, "Show HUD (F3)", &cv_showhud, 10}, + {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_CVAR, NULL, "Background Glass", &cons_backcolor, 45}, + + {IT_STRING | IT_CVAR | IT_CV_SLIDER, + NULL, "Minimap Visibility", &cv_kartminimap, 60}, + {IT_STRING | IT_CVAR, NULL, "Speedometer Display", &cv_kartspeedometer, 70}, + {IT_STRING | IT_CVAR, NULL, "Show \"CHECK\"", &cv_kartcheck, 80}, + + {IT_STRING | IT_CVAR, NULL, "Menu Highlights", &cons_menuhighlight, 95}, + // highlight info - (GOOD HIGHLIGHT, WARNING HIGHLIGHT) - 105 (see M_DrawHUDOptions) + + {IT_STRING | IT_CVAR, NULL, "Console Text Size", &cv_constextsize, 120}, +}; + +static menuitem_t OP_ChatOptionsMenu[] = +{ + // will ANYONE who doesn't know how to use the console want to touch this one? + {IT_STRING | IT_CVAR, NULL, "Chat mode", &cv_consolechat, 10}, // nonetheless... + {IT_STRING | IT_CVAR | IT_CV_SLIDER, + NULL, "Window width", &cv_chatwidth, 25}, + {IT_STRING | IT_CVAR | IT_CV_SLIDER, + NULL, "Window height", &cv_chatheight, 35}, + {IT_STRING | IT_CVAR, NULL, "Message fadeout time", &cv_chattime, 50}, + {IT_STRING | IT_CVAR, NULL, "Show tint behind messages",&cv_chatbacktint, 60}, +}; + static menuitem_t OP_GameOptionsMenu[] = { -#ifndef NONET - {IT_STRING | IT_CVAR | IT_CV_STRING, - NULL, "Master server", &cv_masterserver, 10}, -#endif - {IT_STRING | IT_CVAR, NULL, "Show HUD", &cv_showhud, 40}, - {IT_STRING | IT_CVAR | IT_CV_SLIDER, - NULL, "HUD Visibility", &cv_translucenthud, 50}, + {IT_STRING | IT_SUBMENU, NULL, "Random Item Toggles...", &OP_MonitorToggleDef, 10}, - {IT_STRING | IT_CVAR | IT_CV_SLIDER, - NULL, "Minimap Visibility", &cv_kartminimap, 62}, - {IT_STRING | IT_CVAR, NULL, "Speedometer Display", &cv_speedometer, 72}, - {IT_STRING | IT_CVAR, NULL, "Show \"CHECK\"", &cv_kartcheck, 82}, - {IT_STRING | IT_CVAR, NULL, "Star SFX", &cv_kartstarsfx, 92}, + {IT_STRING | IT_CVAR, NULL, "Game Speed", &cv_kartspeed, 30}, + {IT_STRING | IT_CVAR, NULL, "Frantic Items", &cv_kartfrantic, 40}, + {IT_STRING | IT_CVAR, NULL, "Mirror Mode", &cv_kartmirror, 50}, -#ifdef SEENAMES - {IT_STRING | IT_CVAR, NULL, "HUD Player Names", &cv_seenames, 104}, -#endif - {IT_STRING | IT_CVAR, NULL, "Log Hazard Damage", &cv_hazardlog, 114}, + {IT_STRING | IT_CVAR, NULL, "Number of Laps", &cv_basenumlaps, 70}, + {IT_STRING | IT_CVAR, NULL, "Exit Countdown Timer", &cv_countdowntime, 80}, - {IT_STRING | IT_CVAR, NULL, "Console Back Color", &cons_backcolor, 126}, - {IT_STRING | IT_CVAR, NULL, "Console Text Size", &cv_constextsize,136}, - {IT_STRING | IT_CVAR, NULL, "Uppercase Console", &cv_allcaps, 146}, + //{IT_STRING | IT_CVAR, NULL, "Time Limit", &cv_timelimit, 100}, + {IT_STRING | IT_CVAR, NULL, "Starting Bumpers", &cv_kartbumpers, 100}, + {IT_STRING | IT_CVAR, NULL, "Karma Comeback", &cv_kartcomeback, 110}, - {IT_STRING | IT_CVAR, NULL, "Title Screen Demos", &cv_rollingdemos, 158}, + {IT_STRING | IT_CVAR, NULL, "Force Character #", &cv_forceskin, 130}, + {IT_STRING | IT_CVAR, NULL, "Restrict Character Changes", &cv_restrictskinchange, 140}, }; static menuitem_t OP_ServerOptionsMenu[] = { - {IT_STRING | IT_SUBMENU, NULL, "General netgame options...", &OP_NetgameOptionsDef, 10}, - {IT_STRING | IT_SUBMENU, NULL, "Gametype options...", &OP_GametypeOptionsDef, 20}, - {IT_STRING | IT_SUBMENU, NULL, "Random item toggles...", &OP_MonitorToggleDef, 30}, - #ifndef NONET {IT_STRING | IT_CVAR | IT_CV_STRING, - NULL, "Server name", &cv_servername, 50}, + NULL, "Server Name", &cv_servername, 10}, #endif - {IT_STRING | IT_CVAR, NULL, "Intermission Timer", &cv_inttime, 80}, - {IT_STRING | IT_CVAR, NULL, "Voting Timer", &cv_votetime, 90}, - {IT_STRING | IT_CVAR, NULL, "Advance to next map", &cv_advancemap, 100}, + {IT_STRING | IT_CVAR, NULL, "Intermission Timer", &cv_inttime, 40}, + {IT_STRING | IT_CVAR, NULL, "Map Progression", &cv_advancemap, 50}, + {IT_STRING | IT_CVAR, NULL, "Voting Timer", &cv_votetime, 60}, #ifndef NONET - {IT_STRING | IT_CVAR, NULL, "Max Players", &cv_maxplayers, 120}, - {IT_STRING | IT_CVAR, NULL, "Allow players to join", &cv_allownewplayer, 130}, - {IT_STRING | IT_CVAR, NULL, "Allow WAD Downloading", &cv_downloading, 140}, - {IT_STRING | IT_CVAR, NULL, "Attempts to Resynch", &cv_resynchattempts, 150}, + {IT_STRING | IT_CVAR, NULL, "Max. Player Count", &cv_maxplayers, 80}, + {IT_STRING | IT_CVAR, NULL, "Allow Players to Join", &cv_allownewplayer, 90}, + //{IT_STRING | IT_CVAR, NULL, "Join on Map Change", &cv_joinnextround, 100}, + + {IT_STRING | IT_CVAR, NULL, "Allow WAD Downloading", &cv_downloading, 100}, + {IT_STRING | IT_CVAR, NULL, "Attempts to resynchronise", &cv_resynchattempts, 110}, #endif }; -static menuitem_t OP_NetgameOptionsMenu[] = +/*static menuitem_t OP_NetgameOptionsMenu[] = { {IT_STRING | IT_CVAR, NULL, "Time Limit", &cv_timelimit, 10}, {IT_STRING | IT_CVAR, NULL, "Point Limit", &cv_pointlimit, 18}, @@ -1481,18 +1494,18 @@ static menuitem_t OP_NetgameOptionsMenu[] = {IT_STRING | IT_CVAR, NULL, "Frantic Items", &cv_kartfrantic, 34}, {IT_STRING | IT_CVAR, NULL, "Item Respawn", &cv_itemrespawn, 50}, - {IT_STRING | IT_CVAR, NULL, "Item Respawn time", &cv_itemrespawntime, 58}, + {IT_STRING | IT_CVAR, NULL, "Item Respawn Delay", &cv_itemrespawntime, 58}, - {IT_STRING | IT_CVAR, NULL, "Player respawn delay", &cv_respawntime, 74}, + {IT_STRING | IT_CVAR, NULL, "Player Respawn Delay", &cv_respawntime, 74}, {IT_STRING | IT_CVAR, NULL, "Force Skin #", &cv_forceskin, 90}, - {IT_STRING | IT_CVAR, NULL, "Restrict skin changes", &cv_restrictskinchange, 98}, + {IT_STRING | IT_CVAR, NULL, "Restrict Skin Changes", &cv_restrictskinchange, 98}, //{IT_STRING | IT_CVAR, NULL, "Autobalance Teams", &cv_autobalance, 114}, //{IT_STRING | IT_CVAR, NULL, "Scramble Teams on Map Change", &cv_scrambleonchange, 122}, -}; +};*/ -static menuitem_t OP_GametypeOptionsMenu[] = +/*static menuitem_t OP_GametypeOptionsMenu[] = { {IT_HEADER, NULL, "RACE", NULL, 2}, {IT_STRING | IT_CVAR, NULL, "Game Speed", &cv_kartspeed, 10}, @@ -1501,33 +1514,33 @@ static menuitem_t OP_GametypeOptionsMenu[] = {IT_STRING | IT_CVAR, NULL, "Use Map Lap Counts", &cv_usemapnumlaps, 34}, {IT_HEADER, NULL, "BATTLE", NULL, 50}, - {IT_STRING | IT_CVAR, NULL, "Starting Balloons", &cv_kartballoons, 58}, + {IT_STRING | IT_CVAR, NULL, "Starting Bumpers", &cv_kartbumpers, 58}, {IT_STRING | IT_CVAR, NULL, "Karma Comeback", &cv_kartcomeback, 66}, -}; +};*/ static menuitem_t OP_MonitorToggleMenu[] = { // Printing handled by drawing function // Instead of using this for dumb monitors, lets use the new item bools we have :V - {IT_STRING | IT_CVAR, NULL, "Mushrooms", &cv_mushroom, 10}, - {IT_STRING | IT_CVAR, NULL, "Triple Mushrooms", &cv_triplemushroom, 18}, - {IT_STRING | IT_CVAR, NULL, "Mega Mushrooms", &cv_megashroom, 26}, - {IT_STRING | IT_CVAR, NULL, "Golden Mushrooms", &cv_goldshroom, 34}, - {IT_STRING | IT_CVAR, NULL, "Stars", &cv_star, 42}, - {IT_STRING | IT_CVAR, NULL, "Bananas", &cv_banana, 50}, - {IT_STRING | IT_CVAR, NULL, "Triple Bananas", &cv_triplebanana, 58}, - {IT_STRING | IT_CVAR, NULL, "Fake Items", &cv_fakeitem, 66}, - {IT_STRING | IT_CVAR, NULL, "Green Shells", &cv_greenshell, 74}, - {IT_STRING | IT_CVAR, NULL, "Red Shells", &cv_redshell, 82}, - {IT_STRING | IT_CVAR, NULL, "Triple Green Shells", &cv_triplegreenshell, 90}, - {IT_STRING | IT_CVAR, NULL, "Triple Red Shells", &cv_tripleredshell, 98}, - {IT_STRING | IT_CVAR, NULL, "Bob-ombs", &cv_bobomb, 106}, - {IT_STRING | IT_CVAR, NULL, "Fire Flowers", &cv_fireflower, 114}, - {IT_STRING | IT_CVAR, NULL, "Magnets", &cv_magnet, 122}, - {IT_STRING | IT_CVAR, NULL, "Boos", &cv_boo, 130}, - {IT_STRING | IT_CVAR, NULL, "Lightning", &cv_lightning, 138}, - {IT_STRING | IT_CVAR, NULL, "Blue Lightning", &cv_blueshell, 146}, - {IT_STRING | IT_CVAR, NULL, "Feathers", &cv_feather, 154}, + {IT_STRING | IT_CVAR, NULL, "Sneakers", &cv_sneaker, 10}, + {IT_STRING | IT_CVAR, NULL, "Sneakers x3", &cv_triplesneaker, 18}, + {IT_STRING | IT_CVAR, NULL, "Rocket Sneakers", &cv_rocketsneaker, 26}, + {IT_STRING | IT_CVAR, NULL, "Invinciblity", &cv_invincibility, 34}, + {IT_STRING | IT_CVAR, NULL, "Bananas", &cv_banana, 42}, + {IT_STRING | IT_CVAR, NULL, "Bananas x3", &cv_triplebanana, 50}, + {IT_STRING | IT_CVAR, NULL, "Eggman Monitors", &cv_eggmanmonitor, 58}, + {IT_STRING | IT_CVAR, NULL, "Orbinauts", &cv_orbinaut, 66}, + {IT_STRING | IT_CVAR, NULL, "Orbinauts x3", &cv_tripleorbinaut, 74}, + {IT_STRING | IT_CVAR, NULL, "Jawz", &cv_jawz, 82}, + {IT_STRING | IT_CVAR, NULL, "Jawz x2", &cv_dualjawz, 90}, + {IT_STRING | IT_CVAR, NULL, "Mines", &cv_mine, 98}, + {IT_STRING | IT_CVAR, NULL, "Ballhogs", &cv_ballhog, 106}, + {IT_STRING | IT_CVAR, NULL, "Self-Propelled Bombs",&cv_selfpropelledbomb,114}, + {IT_STRING | IT_CVAR, NULL, "Grow", &cv_grow, 122}, + {IT_STRING | IT_CVAR, NULL, "Shrink", &cv_shrink, 130}, + {IT_STRING | IT_CVAR, NULL, "Thunder Shields", &cv_thundershield, 138}, + {IT_STRING | IT_CVAR, NULL, "Hyudoros", &cv_hyudoro, 146}, + {IT_STRING | IT_CVAR, NULL, "Pogo Springs", &cv_pogospring, 154}, }; // ========================================================================== @@ -1547,6 +1560,73 @@ menu_t MISC_ChangeTeamDef = DEFAULTMENUSTYLE(NULL, MISC_ChangeTeamMenu, &MPauseD menu_t MISC_ChangeLevelDef = MAPICONMENUSTYLE(NULL, MISC_ChangeLevelMenu, &MPauseDef); menu_t MISC_HelpDef = IMAGEDEF(MISC_HelpMenu); +// +// M_GetGametypeColor +// +// Pretty and consistent ^u^ +// See also G_GetGametypeColor. +// + +static INT32 highlightflags, recommendedflags, warningflags; + +inline static void M_GetGametypeColor(void) +{ + INT16 gt; + + warningflags = V_REDMAP; + recommendedflags = V_GREENMAP; + + if (cons_menuhighlight.value) + { + highlightflags = cons_menuhighlight.value; + if (highlightflags == V_REDMAP) + { + warningflags = V_ORANGEMAP; + return; + } + if (highlightflags == V_GREENMAP) + { + recommendedflags = V_SKYMAP; + return; + } + return; + } + + warningflags = V_REDMAP; + recommendedflags = V_GREENMAP; + + if (modeattacking // == ATTACKING_RECORD + || gamestate == GS_TIMEATTACK) + { + highlightflags = V_ORANGEMAP; + return; + } + + if (currentMenu->drawroutine == M_DrawServerMenu) + gt = cv_newgametype.value; + else if (!Playing()) + { + highlightflags = V_YELLOWMAP; + return; + } + else + gt = gametype; + + if (gt == GT_MATCH) + { + highlightflags = V_REDMAP; + warningflags = V_ORANGEMAP; + return; + } + if (gt == GT_RACE) + { + highlightflags = V_SKYMAP; + return; + } + + highlightflags = V_YELLOWMAP; // FALLBACK +} + // Sky Room menu_t SR_PandoraDef = { @@ -1570,17 +1650,9 @@ menu_t SR_MainDef = 0, NULL }; -menu_t SR_LevelSelectDef = -{ - 0, - sizeof (SR_LevelSelectMenu)/sizeof (menuitem_t), - &SR_MainDef, - SR_LevelSelectMenu, - M_DrawLevelSelectMenu, - 40, 40, - 0, - NULL -}; + +menu_t SR_LevelSelectDef = MAPICONMENUSTYLE(NULL, SR_LevelSelectMenu, &SR_MainDef); + menu_t SR_UnlockChecklistDef = { NULL, @@ -1619,17 +1691,6 @@ menu_t SP_LoadDef = }; menu_t SP_LevelSelectDef = MAPICONMENUSTYLE(NULL, SP_LevelSelectMenu, &SP_LoadDef); -menu_t SP_GameStatsDef = -{ - "M_STATS", - 1, - &SP_MainDef, - SP_GameStatsMenu, - M_DrawGameStats, - 280, 185, - 0, - NULL -}; menu_t SP_LevelStatsDef = { "M_STATS", @@ -1649,9 +1710,9 @@ static menu_t SP_TimeAttackDef = &MainDef, // Doesn't matter. SP_TimeAttackMenu, M_DrawTimeAttackMenu, - 32, 40, + 34, 40, 0, - NULL + M_QuitTimeAttackMenu }; static menu_t SP_ReplayDef = { @@ -1660,7 +1721,7 @@ static menu_t SP_ReplayDef = &SP_TimeAttackDef, SP_ReplayMenu, M_DrawTimeAttackMenu, - 32, 120, + 34, 40, 0, NULL }; @@ -1671,7 +1732,7 @@ static menu_t SP_GuestReplayDef = &SP_TimeAttackDef, SP_GuestReplayMenu, M_DrawTimeAttackMenu, - 32, 120, + 34, 40, 0, NULL }; @@ -1682,7 +1743,7 @@ static menu_t SP_GhostDef = &SP_TimeAttackDef, SP_GhostMenu, M_DrawTimeAttackMenu, - 32, 120, + 34, 40, 0, NULL }; @@ -1745,9 +1806,22 @@ menu_t SP_PlayerDef = NULL }; +#ifndef NONET // Multiplayer -menu_t MP_MainDef = DEFAULTMENUSTYLE("M_MULTI", MP_MainMenu, &MainDef, 60, 40); +menu_t MP_MainDef = +{ + "M_MULTI", + sizeof (MP_MainMenu)/sizeof (menuitem_t), + &MainDef, + MP_MainMenu, + M_DrawMPMainMenu, + 42, 50, + 0, + M_CancelConnect +}; menu_t MP_ServerDef = MAPICONMENUSTYLE("M_MULTI", MP_ServerMenu, &MP_MainDef); +#endif +menu_t MP_SplitServerDef = MAPICONMENUSTYLE("M_MULTI", MP_SplitServerMenu, &MP_MainDef); #ifndef NONET menu_t MP_ConnectDef = { @@ -1760,17 +1834,6 @@ menu_t MP_ConnectDef = 0, M_CancelConnect }; -menu_t MP_ConnectIPDef = -{ - "M_MULTI", - sizeof (MP_ConnectIPMenu)/sizeof (menuitem_t), - &MP_MainDef, - MP_ConnectIPMenu, - M_DrawConnectIPMenu, - 27,40, - 0, - M_CancelConnect -}; menu_t MP_RoomDef = { "M_MULTI", @@ -1783,9 +1846,6 @@ menu_t MP_RoomDef = NULL }; #endif -menu_t MP_SplitServerDef = MAPICONMENUSTYLE("M_MULTI", MP_SplitServerMenu, &MP_MainDef); -menu_t MP_3PServerDef = MAPICONMENUSTYLE("M_MULTI", MP_SplitServerMenu, &MP_MainDef); -menu_t MP_4PServerDef = MAPICONMENUSTYLE("M_MULTI", MP_SplitServerMenu, &MP_MainDef); menu_t MP_PlayerSetupDef = { NULL, //"M_SPLAYR" @@ -1793,7 +1853,7 @@ menu_t MP_PlayerSetupDef = &MP_MainDef, MP_PlayerSetupMenu, M_DrawSetupMultiPlayerMenu, - 32, 16, + 36, 14, 0, M_QuitMultiPlayerMenu }; @@ -1805,7 +1865,7 @@ menu_t OP_MainDef = sizeof (OP_MainMenu)/sizeof (menuitem_t), &MainDef, OP_MainMenu, - M_DrawSkyRoom, + M_DrawGenericMenu, 60, 30, 0, NULL @@ -1819,6 +1879,7 @@ menu_t OP_MoveControlsDef = CONTROLMENUSTYLE(OP_MoveControlsMenu, &OP_ControlsDe //menu_t OP_MiscControlsDef = CONTROLMENUSTYLE(OP_MiscControlsMenu, &OP_ControlListDef); menu_t OP_CustomControlsDef = CONTROLMENUSTYLE(OP_CustomControlsMenu, &OP_MoveControlsDef); menu_t OP_SpectateControlsDef = CONTROLMENUSTYLE(OP_SpectateControlsMenu, &OP_MoveControlsDef); +/* menu_t OP_P1ControlsDef = DEFAULTMENUSTYLE("M_CONTRO", OP_P1ControlsMenu, &OP_ControlsDef, 60, 30); menu_t OP_P2ControlsDef = DEFAULTMENUSTYLE("M_CONTRO", OP_P2ControlsMenu, &OP_ControlsDef, 60, 30); #ifndef NOFOURPLAYER @@ -1827,11 +1888,12 @@ menu_t OP_P4ControlsDef = DEFAULTMENUSTYLE("M_CONTRO", OP_P4ControlsMenu, &OP_Co #endif menu_t OP_MouseOptionsDef = DEFAULTMENUSTYLE("M_CONTRO", OP_MouseOptionsMenu, &OP_P1ControlsDef, 60, 30); menu_t OP_Mouse2OptionsDef = DEFAULTMENUSTYLE("M_CONTRO", OP_Mouse2OptionsMenu, &OP_P2ControlsDef, 60, 30); -menu_t OP_Joystick1Def = DEFAULTMENUSTYLE("M_CONTRO", OP_Joystick1Menu, &OP_P1ControlsDef, 60, 30); -menu_t OP_Joystick2Def = DEFAULTMENUSTYLE("M_CONTRO", OP_Joystick2Menu, &OP_P2ControlsDef, 60, 30); +*/ +menu_t OP_Joystick1Def = DEFAULTMENUSTYLE("M_CONTRO", OP_Joystick1Menu, &OP_MoveControlsDef, 60, 30); +menu_t OP_Joystick2Def = DEFAULTMENUSTYLE("M_CONTRO", OP_Joystick2Menu, &OP_MoveControlsDef, 60, 30); #ifndef NOFOURPLAYER -menu_t OP_Joystick3Def = DEFAULTMENUSTYLE("M_CONTRO", OP_Joystick3Menu, &OP_P3ControlsDef, 60, 30); -menu_t OP_Joystick4Def = DEFAULTMENUSTYLE("M_CONTRO", OP_Joystick4Menu, &OP_P4ControlsDef, 60, 30); +menu_t OP_Joystick3Def = DEFAULTMENUSTYLE("M_CONTRO", OP_Joystick3Menu, &OP_MoveControlsDef, 60, 30); +menu_t OP_Joystick4Def = DEFAULTMENUSTYLE("M_CONTRO", OP_Joystick4Menu, &OP_MoveControlsDef, 60, 30); #endif menu_t OP_JoystickSetDef = { @@ -1845,7 +1907,18 @@ menu_t OP_JoystickSetDef = NULL }; -menu_t OP_VideoOptionsDef = DEFAULTMENUSTYLE("M_VIDEO", OP_VideoOptionsMenu, &OP_MainDef, 60, 30); +menu_t OP_VideoOptionsDef = +{ + "M_VIDEO", + sizeof(OP_VideoOptionsMenu)/sizeof(menuitem_t), + &OP_MainDef, + OP_VideoOptionsMenu, + M_DrawVideoMenu, + 30, 30, + 0, + NULL +}; + menu_t OP_VideoModeDef = { "M_VIDEO", @@ -1857,13 +1930,39 @@ menu_t OP_VideoModeDef = 0, NULL }; -menu_t OP_SoundOptionsDef = DEFAULTMENUSTYLE("M_SOUND", OP_SoundOptionsMenu, &OP_MainDef, 60, 30); -menu_t OP_GameOptionsDef = DEFAULTMENUSTYLE("M_GAME", OP_GameOptionsMenu, &OP_MainDef, 30, 30); -menu_t OP_ServerOptionsDef = DEFAULTMENUSTYLE("M_SERVER", OP_ServerOptionsMenu, &OP_MainDef, 30, 30); -menu_t OP_NetgameOptionsDef = DEFAULTMENUSTYLE("M_SERVER", OP_NetgameOptionsMenu, &OP_ServerOptionsDef, 30, 30); -menu_t OP_GametypeOptionsDef = DEFAULTMENUSTYLE("M_SERVER", OP_GametypeOptionsMenu, &OP_ServerOptionsDef, 30, 30); -menu_t OP_MonitorToggleDef = DEFAULTMENUSTYLE("M_SERVER", OP_MonitorToggleMenu, &OP_ServerOptionsDef, 30, 30); +menu_t OP_SoundOptionsDef = +{ + "M_SOUND", + sizeof (OP_SoundOptionsMenu)/sizeof (menuitem_t), + &OP_MainDef, + OP_SoundOptionsMenu, + M_DrawSkyRoom, + 30, 30, + 0, + NULL +}; + +menu_t OP_HUDOptionsDef = +{ + "M_HUD", + sizeof (OP_HUDOptionsMenu)/sizeof (menuitem_t), + &OP_MainDef, + OP_HUDOptionsMenu, + M_DrawHUDOptions, + 30, 30, + 0, + NULL +}; + +menu_t OP_ChatOptionsDef = DEFAULTMENUSTYLE("M_HUD", OP_ChatOptionsMenu, &OP_HUDOptionsDef, 30, 30); + +menu_t OP_GameOptionsDef = DEFAULTMENUSTYLE("M_GAME", OP_GameOptionsMenu, &OP_MainDef, 30, 30); +menu_t OP_ServerOptionsDef = DEFAULTMENUSTYLE("M_SERVER", OP_ServerOptionsMenu, &OP_MainDef, 24, 30); + +//menu_t OP_NetgameOptionsDef = DEFAULTMENUSTYLE("M_SERVER", OP_NetgameOptionsMenu, &OP_ServerOptionsDef, 30, 30); +//menu_t OP_GametypeOptionsDef = DEFAULTMENUSTYLE("M_SERVER", OP_GametypeOptionsMenu, &OP_ServerOptionsDef, 30, 30); +menu_t OP_MonitorToggleDef = DEFAULTMENUSTYLE("M_GAME", OP_MonitorToggleMenu, &OP_GameOptionsDef, 30, 30); /*menu_t OP_MonitorToggleDef = { "M_SERVER", @@ -1904,9 +2003,9 @@ menu_t OP_OpenGLColorDef = NULL }; #endif -menu_t OP_DataOptionsDef = DEFAULTMENUSTYLE("M_DATA", OP_DataOptionsMenu, &OP_MainDef, 60, 30); -menu_t OP_ScreenshotOptionsDef = DEFAULTMENUSTYLE("M_DATA", OP_ScreenshotOptionsMenu, &OP_DataOptionsDef, 30, 30); -menu_t OP_EraseDataDef = DEFAULTMENUSTYLE("M_DATA", OP_EraseDataMenu, &OP_DataOptionsDef, 60, 30); +//menu_t OP_DataOptionsDef = DEFAULTMENUSTYLE("M_DATA", OP_DataOptionsMenu, &OP_MainDef, 60, 30); +menu_t OP_ScreenshotOptionsDef = DEFAULTMENUSTYLE("M_SCSHOT", OP_ScreenshotOptionsMenu, &OP_MainDef, 30, 30); +menu_t OP_EraseDataDef = DEFAULTMENUSTYLE("M_DATA", OP_EraseDataMenu, &OP_MainDef, 60, 30); // ========================================================================== // CVAR ONCHANGE EVENTS GO HERE @@ -1921,8 +2020,6 @@ static INT32 M_GetFirstLevelInList(void); static void Nextmap_OnChange(void) { char *leveltitle; - char tabase[329]; - short i; UINT8 active; lumpnum_t l; @@ -1931,115 +2028,74 @@ static void Nextmap_OnChange(void) leveltitle = G_BuildMapTitle(cv_nextmap.value); cv_nextmap.string = cv_nextmap.zstring = leveltitle ? leveltitle : Z_StrDup(G_BuildMapName(cv_nextmap.value)); - /*if (currentMenu == &SP_NightsAttackDef) + if (currentMenu == &SP_TimeAttackDef) { - CV_StealthSetValue(&cv_dummymares, 0); - // Hide the record changing CVAR if only one mare is available. - if (!nightsrecords[cv_nextmap.value-1] || nightsrecords[cv_nextmap.value-1]->nummares < 2) - SP_NightsAttackMenu[narecords].status = IT_DISABLED; - else - SP_NightsAttackMenu[narecords].status = IT_STRING|IT_CVAR; + // see also p_setup.c's P_LoadRecordGhosts + const size_t glen = strlen(srb2home)+1+strlen("replay")+1+strlen(timeattackfolder)+1+strlen("MAPXX")+1; + char *gpath = malloc(glen); + INT32 i; - CV_StealthSetValue(&cv_dummystaff, 0); + if (!gpath) + return; - // Do the replay things. - active = false; - SP_NightsAttackMenu[naguest].status = IT_DISABLED; - SP_NightsAttackMenu[nareplay].status = IT_DISABLED; - SP_NightsAttackMenu[naghost].status = IT_DISABLED; + sprintf(gpath,"%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value)); - // Check if file exists, if not, disable REPLAY option - sprintf(tabase,"%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s",srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value)); - for (i = 0; i < 5; i++) { - SP_NightsReplayMenu[i].status = IT_DISABLED; - SP_NightsGuestReplayMenu[i].status = IT_DISABLED; - } - if (FIL_FileExists(va("%s-score-best.lmp", tabase))) { - SP_NightsReplayMenu[0].status = IT_WHITESTRING|IT_CALL; - SP_NightsGuestReplayMenu[0].status = IT_WHITESTRING|IT_CALL; - active |= 3; - } - if (FIL_FileExists(va("%s-time-best.lmp", tabase))) { - SP_NightsReplayMenu[1].status = IT_WHITESTRING|IT_CALL; - SP_NightsGuestReplayMenu[1].status = IT_WHITESTRING|IT_CALL; - active |= 3; - } - if (FIL_FileExists(va("%s-last.lmp", tabase))) { - SP_NightsReplayMenu[2].status = IT_WHITESTRING|IT_CALL; - SP_NightsGuestReplayMenu[2].status = IT_WHITESTRING|IT_CALL; - active |= 3; - } - if (FIL_FileExists(va("%s-guest.lmp", tabase))) { - SP_NightsReplayMenu[3].status = IT_WHITESTRING|IT_CALL; - SP_NightsGuestReplayMenu[3].status = IT_WHITESTRING|IT_CALL; - active |= 3; - } - if ((l = W_CheckNumForName(va("%sS01",G_BuildMapName(cv_nextmap.value)))) != LUMPERROR) { - SP_NightsReplayMenu[4].status = IT_WHITESTRING|IT_KEYHANDLER; - CV_StealthSetValue(&cv_dummystaff, 1); - active |= 1; - } - if (active) { - if (active & 1) - SP_NightsAttackMenu[nareplay].status = IT_WHITESTRING|IT_SUBMENU; - if (active & 2) - SP_NightsAttackMenu[naguest].status = IT_WHITESTRING|IT_SUBMENU; - SP_NightsAttackMenu[naghost].status = IT_WHITESTRING|IT_SUBMENU; - } - else if(itemOn == nareplay) // Reset lastOn so replay isn't still selected when not available. - { - currentMenu->lastOn = itemOn; - itemOn = nastart; - } - } - else*/ if (currentMenu == &SP_TimeAttackDef) - { CV_StealthSetValue(&cv_dummystaff, 0); active = false; SP_TimeAttackMenu[taguest].status = IT_DISABLED; SP_TimeAttackMenu[tareplay].status = IT_DISABLED; - SP_TimeAttackMenu[taghost].status = IT_DISABLED; + //SP_TimeAttackMenu[taghost].status = IT_DISABLED; // Check if file exists, if not, disable REPLAY option - sprintf(tabase,"%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s",srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), cv_chooseskin.string); - for (i = 0; i < 5; i++) { + for (i = 0; i < 4; i++) + { SP_ReplayMenu[i].status = IT_DISABLED; SP_GuestReplayMenu[i].status = IT_DISABLED; } - if (FIL_FileExists(va("%s-time-best.lmp", tabase))) { + SP_ReplayMenu[4].status = IT_DISABLED; + + SP_GhostMenu[3].status = IT_DISABLED; + SP_GhostMenu[4].status = IT_DISABLED; + + if (FIL_FileExists(va("%s-%s-time-best.lmp", gpath, cv_chooseskin.string))) { SP_ReplayMenu[0].status = IT_WHITESTRING|IT_CALL; SP_GuestReplayMenu[0].status = IT_WHITESTRING|IT_CALL; active |= 3; } - if (FIL_FileExists(va("%s-lap-best.lmp", tabase))) { + if (FIL_FileExists(va("%s-%s-lap-best.lmp", gpath, cv_chooseskin.string))) { SP_ReplayMenu[1].status = IT_WHITESTRING|IT_CALL; SP_GuestReplayMenu[1].status = IT_WHITESTRING|IT_CALL; active |= 3; } - if (FIL_FileExists(va("%s-last.lmp", tabase))) { + if (FIL_FileExists(va("%s-%s-last.lmp", gpath, cv_chooseskin.string))) { SP_ReplayMenu[2].status = IT_WHITESTRING|IT_CALL; SP_GuestReplayMenu[2].status = IT_WHITESTRING|IT_CALL; active |= 3; } - if (FIL_FileExists(va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-guest.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value)))) { + + if (FIL_FileExists(va("%s-guest.lmp", gpath))) + { SP_ReplayMenu[3].status = IT_WHITESTRING|IT_CALL; SP_GuestReplayMenu[3].status = IT_WHITESTRING|IT_CALL; + SP_GhostMenu[3].status = IT_STRING|IT_CVAR; active |= 3; } - if ((l = W_CheckNumForName(va("%sS01",G_BuildMapName(cv_nextmap.value)))) != LUMPERROR) { + if ((l = W_CheckNumForName(va("%sS01",G_BuildMapName(cv_nextmap.value)))) != LUMPERROR) + { SP_ReplayMenu[4].status = IT_WHITESTRING|IT_KEYHANDLER; + SP_GhostMenu[4].status = IT_STRING|IT_CVAR; CV_StealthSetValue(&cv_dummystaff, 1); active |= 1; } + if (active) { if (active & 1) SP_TimeAttackMenu[tareplay].status = IT_WHITESTRING|IT_SUBMENU; if (active & 2) SP_TimeAttackMenu[taguest].status = IT_WHITESTRING|IT_SUBMENU; - SP_TimeAttackMenu[taghost].status = IT_WHITESTRING|IT_SUBMENU; } - else if(itemOn == tareplay) // Reset lastOn so replay isn't still selected when not available. + else if (itemOn == tareplay) // Reset lastOn so replay isn't still selected when not available. { currentMenu->lastOn = itemOn; itemOn = tastart; @@ -2047,6 +2103,8 @@ static void Nextmap_OnChange(void) if (mapheaderinfo[cv_nextmap.value-1] && mapheaderinfo[cv_nextmap.value-1]->forcecharacter[0] != '\0') CV_Set(&cv_chooseskin, mapheaderinfo[cv_nextmap.value-1]->forcecharacter); + + free(gpath); } } @@ -2131,8 +2189,8 @@ static void Newgametype_OnChange(void) } CV_SetValue(&cv_nextmap, M_FindFirstMap(value)); - CV_AddValue(&cv_nextmap, -1); - CV_AddValue(&cv_nextmap, 1); + //CV_AddValue(&cv_nextmap, -1); + //CV_AddValue(&cv_nextmap, 1); } } } @@ -2181,45 +2239,72 @@ static void M_ChangeCvar(INT32 choice) { consvar_t *cv = (consvar_t *)currentMenu->menuitems[itemOn].itemaction; + if (choice == -1) + { + if (cv == &cv_playercolor) + { + SINT8 skinno = R_SkinAvailable(cv_chooseskin.string); + if (skinno != -1) + CV_SetValue(cv,skins[skinno].prefcolor); + return; + } + CV_Set(cv,cv->defaultvalue); + return; + } + + choice = (choice<<1) - 1; + if (((currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_SLIDER) ||((currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_INVISSLIDER) ||((currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_NOMOD)) { - CV_SetValue(cv,cv->value+(choice*2-1)); + CV_SetValue(cv,cv->value+choice); } else if (cv->flags & CV_FLOAT) { char s[20]; - sprintf(s,"%f",FIXED_TO_FLOAT(cv->value)+(choice*2-1)*(1.0f/16.0f)); + sprintf(s,"%f",FIXED_TO_FLOAT(cv->value)+(choice)*(1.0f/16.0f)); CV_Set(cv,s); } else - CV_AddValue(cv,choice*2-1); + CV_AddValue(cv,choice); } static boolean M_ChangeStringCvar(INT32 choice) { consvar_t *cv = (consvar_t *)currentMenu->menuitems[itemOn].itemaction; - char buf[255]; + char buf[MAXSTRINGLENGTH]; size_t len; + if (shiftdown && choice >= 32 && choice <= 127) + choice = shiftxform[choice]; + switch (choice) { case KEY_BACKSPACE: len = strlen(cv->string); if (len > 0) { + S_StartSound(NULL,sfx_menu1); // Tails M_Memcpy(buf, cv->string, len); buf[len-1] = 0; CV_Set(cv, buf); } return true; + case KEY_DEL: + if (cv->string[0]) + { + S_StartSound(NULL,sfx_menu1); // Tails + CV_Set(cv, ""); + } + return true; default: if (choice >= 32 && choice <= 127) { len = strlen(cv->string); if (len < MAXSTRINGLENGTH - 1) { + S_StartSound(NULL,sfx_menu1); // Tails M_Memcpy(buf, cv->string, len); buf[len++] = (char)choice; buf[len] = 0; @@ -2378,11 +2463,14 @@ boolean M_Responder(event_t *ev) if (ch == -1) return false; + else if (ch == gamecontrol[gc_systemmenu][0]) // allow remappable ESC key + ch = KEY_ESCAPE; // F-Keys if (!menuactive) { noFurtherInput = true; + switch (ch) { case KEY_F1: // Help key @@ -2540,7 +2628,7 @@ boolean M_Responder(event_t *ev) if (routine && ((currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_ARROWS || (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_CVAR)) { - if (currentMenu != &OP_SoundOptionsDef) + if (currentMenu != &OP_SoundOptionsDef || itemOn > 3) S_StartSound(NULL, sfx_menu1); routine(0); } @@ -2550,7 +2638,7 @@ boolean M_Responder(event_t *ev) if (routine && ((currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_ARROWS || (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_CVAR)) { - if (currentMenu != &OP_SoundOptionsDef) + if (currentMenu != &OP_SoundOptionsDef || itemOn > 3) S_StartSound(NULL, sfx_menu1); routine(1); } @@ -2625,10 +2713,29 @@ boolean M_Responder(event_t *ev) G_ClearControlKeys(setupcontrols, currentMenu->menuitems[itemOn].alphaKey); return true; } + + if (routine && ((currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_ARROWS + || (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_CVAR)) + { + consvar_t *cv = (consvar_t *)currentMenu->menuitems[itemOn].itemaction; + + if (cv == &cv_chooseskin + || cv == &cv_dummystaff + || cv == &cv_nextmap + || cv == &cv_newgametype) + return true; + + if (currentMenu != &OP_SoundOptionsDef || itemOn > 3) + S_StartSound(NULL, sfx_menu1); + routine(-1); + return true; + } + // Why _does_ backspace go back anyway? - //currentMenu->lastOn = itemOn; - //if (currentMenu->prevMenu) - // M_SetupNextMenu(currentMenu->prevMenu); + // Sal: Because it supports gamepads better. And still makes sense for keyboard. + currentMenu->lastOn = itemOn; + if (currentMenu->prevMenu) + M_SetupNextMenu(currentMenu->prevMenu); return false; default: @@ -2652,10 +2759,13 @@ void M_Drawer(void) { // now that's more readable with a faded background (yeah like Quake...) if (!WipeInAction) - V_DrawFadeScreen(); + V_DrawFadeScreen(0xFF00, 16); if (currentMenu->drawroutine) + { + M_GetGametypeColor(); currentMenu->drawroutine(); // call current menu Draw routine + } // Draw version down in corner // ... but only in the MAIN MENU. I'm a picky bastard. @@ -2683,9 +2793,9 @@ void M_Drawer(void) { M_DrawTextBox((BASEVIDWIDTH/2) - (60), (BASEVIDHEIGHT/2) - (16), 13, 2); if (gamestate == GS_LEVEL && (P_AutoPause() || paused)) - V_DrawCenteredString(BASEVIDWIDTH/2, (BASEVIDHEIGHT/2) - (4), V_YELLOWMAP, "Game Paused"); + V_DrawCenteredString(BASEVIDWIDTH/2, (BASEVIDHEIGHT/2) - (4), highlightflags, "Game Paused"); else - V_DrawCenteredString(BASEVIDWIDTH/2, (BASEVIDHEIGHT/2) - (4), V_YELLOWMAP, "Focus Lost"); + V_DrawCenteredString(BASEVIDWIDTH/2, (BASEVIDHEIGHT/2) - (4), highlightflags, "Focus Lost"); } } @@ -2698,6 +2808,7 @@ void M_StartControlPanel(void) if (modeattacking && demoplayback) { G_CheckDemoStatus(); + S_ChangeMusicInternal("racent", true); return; } @@ -2779,6 +2890,7 @@ void M_StartControlPanel(void) #endif MPauseMenu[mpause_spectate].status = IT_DISABLED; MPauseMenu[mpause_entergame].status = IT_DISABLED; + MPauseMenu[mpause_canceljoin].status = IT_DISABLED; MPauseMenu[mpause_switchteam].status = IT_DISABLED; MPauseMenu[mpause_psetup].status = IT_DISABLED; // Reset these in case splitscreen messes things up @@ -2826,7 +2938,14 @@ void M_StartControlPanel(void) if (G_GametypeHasTeams()) MPauseMenu[mpause_switchteam].status = IT_STRING | IT_SUBMENU; else if (G_GametypeHasSpectators()) - MPauseMenu[((&players[consoleplayer] && players[consoleplayer].spectator) ? mpause_entergame : mpause_spectate)].status = IT_STRING | IT_CALL; + { + if (!players[consoleplayer].spectator) + MPauseMenu[mpause_spectate].status = IT_STRING | IT_CALL; + else if (players[consoleplayer].pflags & PF_WANTSTOJOIN) + MPauseMenu[mpause_canceljoin].status = IT_STRING | IT_CALL; + else + MPauseMenu[mpause_entergame].status = IT_STRING | IT_CALL; + } else // in this odd case, we still want something to be on the menu even if it's useless MPauseMenu[mpause_spectate].status = IT_GRAYEDOUT; } @@ -2935,6 +3054,9 @@ void M_Init(void) return; // Menu hacks +#ifndef NOFOURPLAYER + CV_RegisterVar(&cv_dummysplitplayers); +#endif CV_RegisterVar(&cv_dummyteam); CV_RegisterVar(&cv_dummyscramble); CV_RegisterVar(&cv_dummyrings); @@ -2947,31 +3069,31 @@ void M_Init(void) quitmsg[QUITMSG1] = M_GetText("What would Tails say if\nhe saw you quitting the game?\n\n(Press 'Y' to quit)"); quitmsg[QUITMSG2] = M_GetText("Hey!\nWhere do ya think you're goin'?\n\n(Press 'Y' to quit)"); quitmsg[QUITMSG3] = M_GetText("Forget your studies!\nPlay some more!\n\n(Press 'Y' to quit)"); - quitmsg[QUITMSG4] = M_GetText("You're trying to say you\nlike Sonic 2K6 better than\nthis, right?\n\n(Press 'Y' to quit)"); + quitmsg[QUITMSG4] = M_GetText("You're trying to say you\nlike Sonic R better than\nthis, aren't you?\n\n(Press 'Y' to quit)"); quitmsg[QUITMSG5] = M_GetText("Don't leave yet -- there's a\nsuper emerald around that corner!\n\n(Press 'Y' to quit)"); quitmsg[QUITMSG6] = M_GetText("You'd rather work than play?\n\n(Press 'Y' to quit)"); quitmsg[QUITMSG7] = M_GetText("Go ahead and leave. See if I care...\n*sniffle*\n\n(Press 'Y' to quit)"); quitmsg[QUIT2MSG] = M_GetText("If you leave now,\nEggman will take over the world!\n\n(Press 'Y' to quit)"); - quitmsg[QUIT2MSG1] = M_GetText("Don't quit!\nThere are animals\nto save!\n\n(Press 'Y' to quit)"); - quitmsg[QUIT2MSG2] = M_GetText("Aw c'mon, just bop\na few more robots!\n\n(Press 'Y' to quit)"); + quitmsg[QUIT2MSG1] = M_GetText("On your mark,\nget set,\nhit the 'N' key!\n\n(Press 'Y' to quit)"); + quitmsg[QUIT2MSG2] = M_GetText("Aw c'mon, just\na few more laps!\n\n(Press 'Y' to quit)"); quitmsg[QUIT2MSG3] = M_GetText("Did you get all those Chaos Emeralds?\n\n(Press 'Y' to quit)"); - quitmsg[QUIT2MSG4] = M_GetText("If you leave, I'll use\nmy spin attack on you!\n\n(Press 'Y' to quit)"); + quitmsg[QUIT2MSG4] = M_GetText("If you leave, I'll use\nmy Jawz on you!\n\n(Press 'Y' to quit)"); quitmsg[QUIT2MSG5] = M_GetText("Don't go!\nYou might find the hidden\nlevels!\n\n(Press 'Y' to quit)"); quitmsg[QUIT2MSG6] = M_GetText("Hit the 'N' key, Sonic!\nThe 'N' key!\n\n(Press 'Y' to quit)"); quitmsg[QUIT3MSG] = M_GetText("Are you really going to give up?\nWe certainly would never give you up.\n\n(Press 'Y' to quit)"); quitmsg[QUIT3MSG1] = M_GetText("Come on, just ONE more netgame!\n\n(Press 'Y' to quit)"); - quitmsg[QUIT3MSG2] = M_GetText("Press 'N' to unlock\nthe Ultimate Cheat!\n\n(Press 'Y' to quit)"); - quitmsg[QUIT3MSG3] = M_GetText("Why don't you go back and try\njumping on that house to\nsee what happens?\n\n(Press 'Y' to quit)"); + quitmsg[QUIT3MSG2] = M_GetText("Press 'N' to unlock\nthe Golden Kart!\n\n(Press 'Y' to quit)"); + quitmsg[QUIT3MSG3] = M_GetText("Couldn't handle\nthe banana meta?\n\n(Press 'Y' to quit)"); quitmsg[QUIT3MSG4] = M_GetText("Every time you press 'Y', an\nSRB2Kart Developer cries...\n\n(Press 'Y' to quit)"); - quitmsg[QUIT3MSG5] = M_GetText("You'll be back to play soon, though...\n......right?\n\n(Press 'Y' to quit)"); - quitmsg[QUIT3MSG6] = M_GetText("Aww, is Egg Rock Zone too\ndifficult for you?\n\n(Press 'Y' to quit)"); + quitmsg[QUIT3MSG5] = M_GetText("You'll be back to play soon, though...\n...right?\n\n(Press 'Y' to quit)"); + quitmsg[QUIT3MSG6] = M_GetText("Aww, is Eggman's Nightclub too\ndifficult for you?\n\n(Press 'Y' to quit)"); #ifdef HWRENDER // Permanently hide some options based on render mode if (rendermode == render_soft) - OP_VideoOptionsMenu[1].status = IT_DISABLED; + OP_VideoOptionsMenu[op_video_ogl].status = IT_DISABLED; #endif #ifndef NONET @@ -3038,7 +3160,7 @@ static void M_DrawThermo(INT32 x, INT32 y, consvar_t *cv) } // A smaller 'Thermo', with range given as percents (0-100) -static void M_DrawSlider(INT32 x, INT32 y, const consvar_t *cv) +static void M_DrawSlider(INT32 x, INT32 y, const consvar_t *cv, boolean ontop) { INT32 i; INT32 range; @@ -3046,16 +3168,31 @@ static void M_DrawSlider(INT32 x, INT32 y, const consvar_t *cv) for (i = 0; cv->PossibleValue[i+1].strvalue; i++); - range = ((cv->value - cv->PossibleValue[0].value) * 100 / - (cv->PossibleValue[i].value - cv->PossibleValue[0].value)); - - if (range < 0) - range = 0; - if (range > 100) - range = 100; - x = BASEVIDWIDTH - x - SLIDER_WIDTH; + if (ontop) + { + V_DrawCharacter(x - 16 - (skullAnimCounter/5), y, + '\x1C' | highlightflags, false); // left arrow + V_DrawCharacter(x+(SLIDER_RANGE*8) + 8 + (skullAnimCounter/5), y, + '\x1D' | highlightflags, false); // right arrow + } + + if ((range = atoi(cv->defaultvalue)) != cv->value) + { + range = ((range - cv->PossibleValue[0].value) * 100 / + (cv->PossibleValue[1].value - cv->PossibleValue[0].value)); + + if (range < 0) + range = 0; + if (range > 100) + range = 100; + + // draw the default + p = W_CachePatchName("M_SLIDEC", PU_CACHE); + V_DrawScaledPatch(x - 4 + (((SLIDER_RANGE)*8 + 4)*range)/100, y, 0, p); + } + V_DrawScaledPatch(x - 8, y, 0, W_CachePatchName("M_SLIDEL", PU_CACHE)); p = W_CachePatchName("M_SLIDEM", PU_CACHE); @@ -3065,9 +3202,17 @@ static void M_DrawSlider(INT32 x, INT32 y, const consvar_t *cv) p = W_CachePatchName("M_SLIDER", PU_CACHE); V_DrawScaledPatch(x+SLIDER_RANGE*8, y, 0, p); + range = ((cv->value - cv->PossibleValue[0].value) * 100 / + (cv->PossibleValue[1].value - cv->PossibleValue[0].value)); + + if (range < 0) + range = 0; + if (range > 100) + range = 100; + // draw the slider cursor p = W_CachePatchName("M_SLIDEC", PU_CACHE); - V_DrawMappedPatch(x + ((SLIDER_RANGE-1)*8*range)/100, y, 0, p, yellowmap); + V_DrawScaledPatch(x - 4 + (((SLIDER_RANGE)*8 + 4)*range)/100, y, 0, p); } // @@ -3227,7 +3372,7 @@ static void M_DrawMenuTitle(void) static void M_DrawGenericMenu(void) { - INT32 x, y, i, cursory = 0; + INT32 x, y, w, i, cursory = 0; // DRAW MENU x = currentMenu->x; @@ -3260,7 +3405,7 @@ static void M_DrawGenericMenu(void) /* FALLTHRU */ case IT_NOTHING: case IT_DYBIGSPACE: - y += LINEHEIGHT; + y = currentMenu->y+currentMenu->menuitems[i].alphaKey;//+= LINEHEIGHT; break; case IT_BIGSLIDER: M_DrawThermo(x, y, (consvar_t *)currentMenu->menuitems[i].itemaction); @@ -3276,7 +3421,7 @@ static void M_DrawGenericMenu(void) if ((currentMenu->menuitems[i].status & IT_DISPLAY)==IT_STRING) V_DrawString(x, y, 0, currentMenu->menuitems[i].text); else - V_DrawString(x, y, V_YELLOWMAP, currentMenu->menuitems[i].text); + V_DrawString(x, y, highlightflags, currentMenu->menuitems[i].text); // Cvar specific handling switch (currentMenu->menuitems[i].status & IT_TYPE) @@ -3286,7 +3431,7 @@ static void M_DrawGenericMenu(void) switch (currentMenu->menuitems[i].status & IT_CVARTYPE) { case IT_CV_SLIDER: - M_DrawSlider(x, y, cv); + M_DrawSlider(x, y, cv, (i == itemOn)); case IT_CV_NOPRINT: // color use this case IT_CV_INVISSLIDER: // monitor toggles use this break; @@ -3299,8 +3444,16 @@ static void M_DrawGenericMenu(void) y += 16; break; default: - V_DrawString(BASEVIDWIDTH - x - V_StringWidth(cv->string, 0), y, - ((cv->flags & CV_CHEAT) && !CV_IsSetToDefault(cv) ? V_REDMAP : V_YELLOWMAP), cv->string); + w = V_StringWidth(cv->string, 0); + V_DrawString(BASEVIDWIDTH - x - w, y, + ((cv->flags & CV_CHEAT) && !CV_IsSetToDefault(cv) ? warningflags : highlightflags), cv->string); + if (i == itemOn) + { + V_DrawCharacter(BASEVIDWIDTH - x - 10 - w - (skullAnimCounter/5), y, + '\x1C' | highlightflags, false); // left arrow + V_DrawCharacter(BASEVIDWIDTH - x + 2 + (skullAnimCounter/5), y, + '\x1D' | highlightflags, false); // right arrow + } break; } break; @@ -3338,7 +3491,7 @@ static void M_DrawGenericMenu(void) if (currentMenu->menuitems[i].alphaKey) y = currentMenu->y+currentMenu->menuitems[i].alphaKey; - V_DrawString(x-16, y, V_YELLOWMAP, currentMenu->menuitems[i].text); + V_DrawString(x-16, y, highlightflags, currentMenu->menuitems[i].text); y += SMALLLINEHEIGHT; break; } @@ -3355,12 +3508,13 @@ static void M_DrawGenericMenu(void) { V_DrawScaledPatch(currentMenu->x - 24, cursory, 0, W_CachePatchName("M_CURSOR", PU_CACHE)); - V_DrawString(currentMenu->x, cursory, V_YELLOWMAP, currentMenu->menuitems[itemOn].text); + V_DrawString(currentMenu->x, cursory, highlightflags, currentMenu->menuitems[itemOn].text); } } static void M_DrawPauseMenu(void) { +#if 0 if (!netgame && !multiplayer && (gamestate == GS_LEVEL || gamestate == GS_INTERMISSION || gamestate == GS_VOTING)) { emblem_t *emblem_detail[3] = {NULL, NULL, NULL}; @@ -3375,16 +3529,16 @@ static void M_DrawPauseMenu(void) if (strlen(mapheaderinfo[gamemap-1]->zonttl) > 0) { if (strlen(mapheaderinfo[gamemap-1]->actnum) > 0) - V_DrawString(40, 28, V_YELLOWMAP, va("%s %s %s", mapheaderinfo[gamemap-1]->lvlttl, mapheaderinfo[gamemap-1]->zonttl, mapheaderinfo[gamemap-1]->actnum)); + V_DrawString(40, 28, highlightflags, va("%s %s %s", mapheaderinfo[gamemap-1]->lvlttl, mapheaderinfo[gamemap-1]->zonttl, mapheaderinfo[gamemap-1]->actnum)); else - V_DrawString(40, 28, V_YELLOWMAP, va("%s %s", mapheaderinfo[gamemap-1]->lvlttl, mapheaderinfo[gamemap-1]->zonttl)); + V_DrawString(40, 28, highlightflags, va("%s %s", mapheaderinfo[gamemap-1]->lvlttl, mapheaderinfo[gamemap-1]->zonttl)); } else { if (strlen(mapheaderinfo[gamemap-1]->actnum) > 0) - V_DrawString(40, 28, V_YELLOWMAP, va("%s %s", mapheaderinfo[gamemap-1]->lvlttl, mapheaderinfo[gamemap-1]->actnum)); + V_DrawString(40, 28, highlightflags, va("%s %s", mapheaderinfo[gamemap-1]->lvlttl, mapheaderinfo[gamemap-1]->actnum)); else - V_DrawString(40, 28, V_YELLOWMAP, mapheaderinfo[gamemap-1]->lvlttl); + V_DrawString(40, 28, highlightflags, mapheaderinfo[gamemap-1]->lvlttl); } // Set up the detail boxes. @@ -3496,19 +3650,20 @@ static void M_DrawPauseMenu(void) { /*case ET_SCORE: case ET_NGRADE: - V_DrawString(56, 44 + (i*8), V_YELLOWMAP, "SCORE:"); + V_DrawString(56, 44 + (i*8), highlightflags, "SCORE:"); break;*/ case ET_TIME: //case ET_NTIME: - V_DrawString(56, 44 + (i*8), V_YELLOWMAP, "TIME:"); + V_DrawString(56, 44 + (i*8), highlightflags, "TIME:"); break; /*case ET_RINGS: - V_DrawString(56, 44 + (i*8), V_YELLOWMAP, "RINGS:"); + V_DrawString(56, 44 + (i*8), highlightflags, "RINGS:"); break;*/ } V_DrawRightAlignedString(284, 44 + (i*8), V_MONOSPACE, emblem_text[i]); } } +#endif M_DrawGenericMenu(); } @@ -3564,7 +3719,7 @@ static void M_DrawCenteredMenu(void) if ((currentMenu->menuitems[i].status & IT_DISPLAY)==IT_STRING) V_DrawCenteredString(x, y, 0, currentMenu->menuitems[i].text); else - V_DrawCenteredString(x, y, V_YELLOWMAP, currentMenu->menuitems[i].text); + V_DrawCenteredString(x, y, highlightflags, currentMenu->menuitems[i].text); // Cvar specific handling switch(currentMenu->menuitems[i].status & IT_TYPE) @@ -3574,7 +3729,7 @@ static void M_DrawCenteredMenu(void) switch(currentMenu->menuitems[i].status & IT_CVARTYPE) { case IT_CV_SLIDER: - M_DrawSlider(x, y, cv); + M_DrawSlider(x, y, cv, (i == itemOn)); case IT_CV_NOPRINT: // color use this break; case IT_CV_STRING: @@ -3587,7 +3742,7 @@ static void M_DrawCenteredMenu(void) break; default: V_DrawString(BASEVIDWIDTH - x - V_StringWidth(cv->string, 0), y, - ((cv->flags & CV_CHEAT) && !CV_IsSetToDefault(cv) ? V_REDMAP : V_YELLOWMAP), cv->string); + ((cv->flags & CV_CHEAT) && !CV_IsSetToDefault(cv) ? warningflags : highlightflags), cv->string); break; } break; @@ -3627,7 +3782,7 @@ static void M_DrawCenteredMenu(void) { V_DrawScaledPatch(x - V_StringWidth(currentMenu->menuitems[itemOn].text, 0)/2 - 24, cursory, 0, W_CachePatchName("M_CURSOR", PU_CACHE)); - V_DrawCenteredString(x, cursory, V_YELLOWMAP, currentMenu->menuitems[itemOn].text); + V_DrawCenteredString(x, cursory, highlightflags, currentMenu->menuitems[itemOn].text); } } @@ -3673,14 +3828,15 @@ static void M_PatchSkinNameTable(void) { skins_cons_t[j].strvalue = NULL; skins_cons_t[j].value = 0; + break; } } - CV_SetValue(&cv_chooseskin, cv_chooseskin.value); // This causes crash sometimes?! + j = R_SkinAvailable(cv_skin.string); + if (j == -1) + j = 0; - CV_SetValue(&cv_chooseskin, 1); - CV_AddValue(&cv_chooseskin, -1); - CV_AddValue(&cv_chooseskin, 1); + CV_SetValue(&cv_chooseskin, j+1); // This causes crash sometimes?! return; } @@ -3714,7 +3870,7 @@ boolean M_CanShowLevelInList(INT32 mapnum, INT32 gt) { case LLM_CREATESERVER: // Should the map be hidden? - if (mapheaderinfo[mapnum]->menuflags & LF2_HIDEINMENU) + if (mapheaderinfo[mapnum]->menuflags & LF2_HIDEINMENU && mapnum+1 != gamemap) return false; if (M_MapLocked(mapnum+1)) @@ -4107,11 +4263,11 @@ static void M_ConfirmSpectate(INT32 choice) static void M_ConfirmEnterGame(INT32 choice) { (void)choice; - if (!cv_allowteamchange.value) + /*if (!cv_allowteamchange.value) { M_StartMessage(M_GetText("The server is not allowing\nteam changes at this time.\nPress a key.\n"), NULL, MM_NOTHING); return; - } + }*/ M_ClearMenus(true); COM_ImmedExecute("changeteam playing"); } @@ -4161,13 +4317,12 @@ static void M_Options(INT32 choice) { (void)choice; - // if the player is not admin or server, disable server options - OP_MainMenu[5].status = (Playing() && !(server || IsPlayerAdmin(consoleplayer))) ? (IT_GRAYEDOUT) : (IT_STRING|IT_SUBMENU); + // if the player is not admin or server, disable gameplay & server options + OP_MainMenu[5].status = OP_MainMenu[6].status = (Playing() && !(server || IsPlayerAdmin(consoleplayer))) ? (IT_GRAYEDOUT) : (IT_STRING|IT_SUBMENU); - // if the player is playing _at all_, disable the erase data options - OP_DataOptionsMenu[1].status = (Playing()) ? (IT_GRAYEDOUT) : (IT_STRING|IT_SUBMENU); - // SRB2Kart: Same with the "Play Credits" option - OP_MainMenu[6].status = (Playing()) ? (IT_GRAYEDOUT) : (IT_STRING|IT_CALL); + // if the player is playing _at all_, disable the erase data & credits options + OP_MainMenu[7].status = (Playing()) ? (IT_GRAYEDOUT) : (IT_STRING|IT_CALL); + OP_MainMenu[8].status = (Playing()) ? (IT_GRAYEDOUT) : (IT_STRING|IT_SUBMENU); OP_MainDef.prevMenu = currentMenu; M_SetupNextMenu(&OP_MainDef); @@ -4325,7 +4480,7 @@ static void M_DrawChecklist(void) continue; ++line; - V_DrawString(8, (line*8), V_RETURN8|(unlockables[i].unlocked ? V_GREENMAP : V_REDMAP), unlockables[i].name); + V_DrawString(8, (line*8), V_RETURN8|(unlockables[i].unlocked ? recommendedflags : warningflags), unlockables[i].name); if (conditionSets[unlockables[i].conditionset - 1].numconditions) { @@ -4345,13 +4500,13 @@ static void M_DrawChecklist(void) if (lastid == -1 || cond.id != (UINT32)lastid) { - V_DrawString(16, (line*8), V_MONOSPACE|V_ALLOWLOWERCASE|(achieved ? V_YELLOWMAP : 0), "*"); - V_DrawString(32, (line*8), V_MONOSPACE|V_ALLOWLOWERCASE|(achieved ? V_YELLOWMAP : 0), str); + V_DrawString(16, (line*8), V_MONOSPACE|V_ALLOWLOWERCASE|(achieved ? highlightflags : 0), "*"); + V_DrawString(32, (line*8), V_MONOSPACE|V_ALLOWLOWERCASE|(achieved ? highlightflags : 0), str); } else { - V_DrawString(32, (line*8), V_MONOSPACE|V_ALLOWLOWERCASE|(achieved ? V_YELLOWMAP : 0), "&"); - V_DrawString(48, (line*8), V_MONOSPACE|V_ALLOWLOWERCASE|(achieved ? V_YELLOWMAP : 0), str); + V_DrawString(32, (line*8), V_MONOSPACE|V_ALLOWLOWERCASE|(achieved ? highlightflags : 0), "&"); + V_DrawString(48, (line*8), V_MONOSPACE|V_ALLOWLOWERCASE|(achieved ? highlightflags : 0), str); } lastid = cond.id; @@ -4390,7 +4545,7 @@ static void M_DrawEmblemHints(void) if (emblem->collected) { - collected = V_GREENMAP; + 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)); } @@ -4411,52 +4566,71 @@ static void M_DrawEmblemHints(void) break; } if (!j) - V_DrawCenteredString(160, 48, V_YELLOWMAP, "No hidden emblems on this map."); + V_DrawCenteredString(160, 48, highlightflags, "No hidden emblems on this map."); M_DrawGenericMenu(); } -static void M_DrawLevelSelectMenu(void) -{ - M_DrawGenericMenu(); - - if (cv_nextmap.value) - { - lumpnum_t lumpnum; - patch_t *PictureOfLevel; - - // A 160x100 image of the level as entry MAPxxP - lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(cv_nextmap.value))); - - if (lumpnum != LUMPERROR) - PictureOfLevel = W_CachePatchName(va("%sP", G_BuildMapName(cv_nextmap.value)), PU_CACHE); - else - PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); - - V_DrawSmallScaledPatch(200, 110, 0, PictureOfLevel); - } -} - static void M_DrawSkyRoom(void) { INT32 i, y = 0; + INT32 lengthstring = 0; M_DrawGenericMenu(); + if (currentMenu == &OP_SoundOptionsDef) + { + V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, + currentMenu->y+currentMenu->menuitems[0].alphaKey, + (nosound ? warningflags : highlightflags), + ((nosound || sound_disabled) ? "OFF" : "ON")); + + V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, + currentMenu->y+currentMenu->menuitems[2].alphaKey, + (nodigimusic ? warningflags : highlightflags), + ((nodigimusic || digital_disabled) ? "OFF" : "ON")); + + /*V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, + currentMenu->y+currentMenu->menuitems[5].alphaKey, + (nomidimusic ? warningflags : highlightflags), + ((nomidimusic || music_disabled) ? "OFF" : "ON"));*/ + + if (itemOn == 0) + lengthstring = 8*((nosound || sound_disabled) ? 3 : 2); + else if (itemOn == 2) + lengthstring = 8*((nodigimusic || digital_disabled) ? 3 : 2); + /*else if (itemOn == 5) + lengthstring = 8*((nomidimusic || music_disabled) ? 3 : 2);*/ + } + for (i = 0; i < currentMenu->numitems; ++i) { - if (currentMenu->menuitems[i].status == (IT_STRING|IT_KEYHANDLER)) + if (currentMenu->menuitems[i].itemaction == M_HandleSoundTest) { y = currentMenu->menuitems[i].alphaKey; break; } } - if (!y) - return; - V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, currentMenu->y + y, V_YELLOWMAP, cv_soundtest.string); - if (cv_soundtest.value) - V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, currentMenu->y + y + 8, V_YELLOWMAP, S_sfx[cv_soundtest.value].name); + if (y) + { + y += currentMenu->y; + + V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, y, highlightflags, cv_soundtest.string); + if (cv_soundtest.value) + V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, y + 8, highlightflags, S_sfx[cv_soundtest.value].name); + + if (i == itemOn) + lengthstring = V_StringWidth(cv_soundtest.string, 0); + } + + if (lengthstring) + { + V_DrawCharacter(BASEVIDWIDTH - currentMenu->x - 10 - lengthstring - (skullAnimCounter/5), currentMenu->y+currentMenu->menuitems[itemOn].alphaKey, + '\x1C' | highlightflags, false); // left arrow + V_DrawCharacter(BASEVIDWIDTH - currentMenu->x + 2 + (skullAnimCounter/5), currentMenu->y+currentMenu->menuitems[itemOn].alphaKey, + '\x1D' | highlightflags, false); // right arrow + } } static void M_HandleSoundTest(INT32 choice) @@ -4703,7 +4877,7 @@ static void M_DrawLoadGameData(void) if (savegameinfo[saveSlotSelected].lives == -666) // savegame is bad { - V_DrawCenteredString(ecks + 68, 144, V_REDMAP, "CORRUPT SAVE FILE"); + V_DrawCenteredString(ecks + 68, 144, warningflags, "CORRUPT SAVE FILE"); V_DrawCenteredString(ecks + 68, 156, 0, "THIS SAVE FILE"); V_DrawCenteredString(ecks + 68, 164, 0, "CAN NOT BE LOADED."); V_DrawCenteredString(ecks + 68, 172, 0, "DELETE USING BACKSPACE."); @@ -4724,11 +4898,11 @@ static void M_DrawLoadGameData(void) #ifdef SAVEGAMES_OTHERVERSIONS if (savegameinfo[saveSlotSelected].gamemap & 16384) - V_DrawCenteredString(ecks + 68, 144, V_REDMAP, "OUTDATED SAVE FILE!"); + V_DrawCenteredString(ecks + 68, 144, warningflags, "OUTDATED SAVE FILE!"); #endif if (savegameinfo[saveSlotSelected].gamemap & 8192) - V_DrawString(ecks + 12, 160, V_GREENMAP, "CLEAR!"); + V_DrawString(ecks + 12, 160, recommendedflags, "CLEAR!"); else V_DrawString(ecks + 12, 160, 0, va("%s", savegameinfo[saveSlotSelected].levelname)); @@ -4784,9 +4958,9 @@ static void M_DrawLoad(void) if (savegameinfo[i%MAXSAVEGAMES].lives == -42) V_DrawString(SP_LoadDef.x-6, LOADBARHEIGHT - 1, V_TRANSLUCENT, "NO DATA"); else if (savegameinfo[i%MAXSAVEGAMES].lives == -666) - V_DrawString(SP_LoadDef.x-6, LOADBARHEIGHT - 1, V_REDMAP, "CORRUPT SAVE FILE"); + V_DrawString(SP_LoadDef.x-6, LOADBARHEIGHT - 1, warningflags, "CORRUPT SAVE FILE"); else if (savegameinfo[i%MAXSAVEGAMES].gamemap & 8192) - V_DrawString(SP_LoadDef.x-6, LOADBARHEIGHT - 1, V_GREENMAP, "CLEAR!"); + V_DrawString(SP_LoadDef.x-6, LOADBARHEIGHT - 1, recommendedflags, "CLEAR!"); else V_DrawString(SP_LoadDef.x-6, LOADBARHEIGHT - 1, 0, va("%s", savegameinfo[i%MAXSAVEGAMES].levelname)); @@ -5293,6 +5467,10 @@ static void M_ChoosePlayer(INT32 choice) // STATISTICS MENU // =============== +// =============== +// STATISTICS MENU +// =============== + static INT32 statsLocation; static INT32 statsMax; static INT16 statsMapList[NUMMAPS+1]; @@ -5311,7 +5489,7 @@ static void M_Statistics(INT32 choice) continue; if (!(mapheaderinfo[i]->typeoflevel & TOL_RACE) // TOL_SP - || (mapheaderinfo[i]->menuflags & LF2_HIDEINSTATS)) + || (mapheaderinfo[i]->menuflags & (LF2_HIDEINSTATS|LF2_HIDEINMENU))) continue; if (M_MapLocked(i+1)) // !mapvisited[i] @@ -5320,23 +5498,24 @@ static void M_Statistics(INT32 choice) statsMapList[j++] = i; } statsMapList[j] = -1; - statsMax = j - 13 + numextraemblems; + statsMax = j - 11 + numextraemblems; statsLocation = 0; if (statsMax < 0) statsMax = 0; - M_SetupNextMenu(&SP_GameStatsDef); + M_SetupNextMenu(&SP_LevelStatsDef); } static void M_DrawStatsMaps(int location) { - INT32 y = 76, i = -1; + INT32 y = 80, i = -1; INT16 mnum; extraemblem_t *exemblem; + boolean dotopname = true, dobottomarrow = (location < statsMax); - V_DrawString(20, y-12, 0, "LEVEL NAME"); - V_DrawString(248, y-12, 0, "EMBLEMS"); + if (location) + V_DrawString(10, y-(skullAnimCounter/5), highlightflags, "\x1A"); while (statsMapList[++i] != -1) { @@ -5345,43 +5524,60 @@ static void M_DrawStatsMaps(int location) --location; continue; } + else if (dotopname) + { + V_DrawString(20, y, highlightflags, "LEVEL NAME"); + V_DrawString(248, y, highlightflags, "EMBLEMS"); + y += 8; + dotopname = false; + } mnum = statsMapList[i]; M_DrawMapEmblems(mnum+1, 292, y); - if (strlen(mapheaderinfo[gamemap-1]->zonttl) > 0) - { - if (strlen(mapheaderinfo[gamemap-1]->actnum) > 0) - V_DrawString(20, y, V_YELLOWMAP, va("%s %s %s", mapheaderinfo[mnum]->lvlttl, mapheaderinfo[mnum]->zonttl, mapheaderinfo[mnum]->actnum)); - else - V_DrawString(20, y, V_YELLOWMAP, va("%s %s", mapheaderinfo[mnum]->lvlttl, mapheaderinfo[mnum]->zonttl)); - } + if (mapheaderinfo[mnum]->levelflags & LF_NOZONE) + V_DrawString(20, y, 0, va("%s %s", + mapheaderinfo[mnum]->lvlttl, + mapheaderinfo[mnum]->actnum)); else - { - if (strlen(mapheaderinfo[gamemap-1]->actnum) > 0) - V_DrawString(20, y, V_YELLOWMAP, va("%s %s", mapheaderinfo[mnum]->lvlttl, mapheaderinfo[mnum]->actnum)); - else - V_DrawString(20, y, V_YELLOWMAP, mapheaderinfo[mnum]->lvlttl); - } + V_DrawString(20, y, 0, va("%s %s %s", + mapheaderinfo[mnum]->lvlttl, + (mapheaderinfo[mnum]->zonttl[0] ? mapheaderinfo[mnum]->zonttl : "ZONE"), + mapheaderinfo[mnum]->actnum)); y += 8; if (y >= BASEVIDHEIGHT-8) - return; + goto bottomarrow; } + if (dotopname && !location) + { + V_DrawString(20, y, highlightflags, "LEVEL NAME"); + V_DrawString(248, y, highlightflags, "EMBLEMS"); + y += 8; + } + else if (location) + --location; // Extra Emblems for (i = -2; i < numextraemblems; ++i) { + if (i == -1) + { + V_DrawString(20, y, highlightflags, "EXTRA EMBLEMS"); + if (location) + { + y += 8; + location++; + } + } if (location) { --location; continue; } - if (i == -1) - V_DrawString(20, y, V_GREENMAP, "EXTRA EMBLEMS"); - else if (i >= 0) + if (i >= 0) { exemblem = &extraemblems[i]; @@ -5391,23 +5587,64 @@ static void M_DrawStatsMaps(int location) else V_DrawSmallScaledPatch(292, y, 0, W_CachePatchName("NEEDIT", PU_CACHE)); - V_DrawString(20, y, V_YELLOWMAP, va("%s", exemblem->description)); + V_DrawString(20, y, 0, va("%s", exemblem->description)); } y += 8; if (y >= BASEVIDHEIGHT-8) - return; + goto bottomarrow; } +bottomarrow: + if (dobottomarrow) + V_DrawString(10, y-8 + (skullAnimCounter/5), highlightflags, "\x1B"); } static void M_DrawLevelStats(void) { - M_DrawMenuTitle(); - V_DrawCenteredString(BASEVIDWIDTH/2, 24, V_YELLOWMAP, "PAGE 2 OF 2"); + char beststr[40]; - V_DrawString(72, 48, 0, va("x %d/%d", M_CountEmblems(), numemblems+numextraemblems)); - V_DrawScaledPatch(40, 48-4, 0, W_CachePatchName("EMBLICON", PU_STATIC)); + tic_t besttime = 0; + + INT32 i; + INT32 mapsunfinished = 0; + + M_DrawMenuTitle(); + + V_DrawString(20, 24, highlightflags, "Total Play Time:"); + V_DrawCenteredString(BASEVIDWIDTH/2, 32, 0, va("%i hours, %i minutes, %i seconds", + G_TicsToHours(totalplaytime), + G_TicsToMinutes(totalplaytime, false), + G_TicsToSeconds(totalplaytime))); + V_DrawString(20, 42, highlightflags, "Total Matches:"); + V_DrawRightAlignedString(BASEVIDWIDTH-16, 42, 0, va("%i played", matchesplayed)); + + for (i = 0; i < NUMMAPS; i++) + { + if (!mapheaderinfo[i] || !(mapheaderinfo[i]->menuflags & LF2_RECORDATTACK)) + continue; + + if (!mainrecords[i] || mainrecords[i]->time <= 0) + { + mapsunfinished++; + continue; + } + + besttime += mainrecords[i]->time; + } + + V_DrawString(20, 62, highlightflags, "Combined time records:"); + + sprintf(beststr, "%i:%02i:%02i.%02i", G_TicsToHours(besttime), G_TicsToMinutes(besttime, false), G_TicsToSeconds(besttime), G_TicsToCentiseconds(besttime)); + V_DrawRightAlignedString(BASEVIDWIDTH-16, 62, (mapsunfinished ? warningflags : 0), beststr); + + if (mapsunfinished) + V_DrawRightAlignedString(BASEVIDWIDTH-16, 70, warningflags, va("(%d unfinished)", mapsunfinished)); + else + V_DrawRightAlignedString(BASEVIDWIDTH-16, 70, recommendedflags, "(complete)"); + + V_DrawString(36, 70, 0, va("x %d/%d", M_CountEmblems(), numemblems+numextraemblems)); + V_DrawSmallScaledPatch(20, 70, 0, W_CachePatchName("EMBLICON", PU_STATIC)); M_DrawStatsMaps(statsLocation); } @@ -5431,124 +5668,19 @@ static void M_HandleLevelStats(INT32 choice) --statsLocation; break; - case KEY_RIGHTARROW: + case KEY_PGDN: S_StartSound(NULL, sfx_menu1); - statsLocation += (statsLocation+15 >= statsMax) ? statsMax-statsLocation : 15; + statsLocation += (statsLocation+13 >= statsMax) ? statsMax-statsLocation : 13; break; - case KEY_LEFTARROW: + case KEY_PGUP: S_StartSound(NULL, sfx_menu1); - statsLocation -= (statsLocation < 15) ? statsLocation : 15; + statsLocation -= (statsLocation < 13) ? statsLocation : 13; break; case KEY_ESCAPE: exitmenu = true; break; - - case KEY_ENTER: - S_StartSound(NULL, sfx_menu1); - M_SetupNextMenu(&SP_GameStatsDef); - break; - } - if (exitmenu) - { - if (currentMenu->prevMenu) - M_SetupNextMenu(currentMenu->prevMenu); - else - M_ClearMenus(true); - } -} - -// Handle GAME statistics. -static void M_DrawGameStats(void) -{ - char beststr[40]; - - tic_t besttime = 0; - //UINT32 bestscore = 0; - //UINT32 bestrings = 0; - - INT32 i; - INT32 mapsunfinished = 0; //INT32 mapsunfinished[3] = {0, 0, 0}; - - M_DrawMenuTitle(); - V_DrawCenteredString(BASEVIDWIDTH/2, 24, V_YELLOWMAP, "PAGE 1 OF 2"); - - V_DrawString(32, 60, V_YELLOWMAP, "Total Play Time:"); - V_DrawRightAlignedString(BASEVIDWIDTH-32, 70, 0, va("%i hours, %i minutes, %i seconds", - G_TicsToHours(totalplaytime), - G_TicsToMinutes(totalplaytime, false), - G_TicsToSeconds(totalplaytime))); - - V_DrawString(32, 90, V_YELLOWMAP, "Total Matches Played:"); - V_DrawRightAlignedString(BASEVIDWIDTH-32, 100, 0, va("%i", matchesplayed)); - - for (i = 0; i < NUMMAPS; i++) - { - if (!mapheaderinfo[i] || !(mapheaderinfo[i]->menuflags & LF2_RECORDATTACK)) - continue; - - if (!mainrecords[i]) - { - /*mapsunfinished[0]++; - mapsunfinished[1]++; - mapsunfinished[2]++;*/ - mapsunfinished++; - continue; - } - - /*if (mainrecords[i]->score > 0) - bestscore += mainrecords[i]->score; - else - mapsunfinished[0]++;*/ - - if (mainrecords[i]->time > 0) - besttime += mainrecords[i]->time; - else - mapsunfinished++; //mapsunfinished[1]++; - - /*if (mainrecords[i]->rings > 0) - bestrings += mainrecords[i]->rings; - else - mapsunfinished[2]++;*/ - - } - - V_DrawCenteredString(BASEVIDWIDTH/2, 120, 0, "* COMBINED RECORDS *"); - - /*sprintf(beststr, "%u", bestscore); - V_DrawString(32, 100, V_YELLOWMAP, "SCORE:"); - V_DrawRightAlignedString(BASEVIDWIDTH-32, 100, 0, beststr); - if (mapsunfinished[0]) - V_DrawRightAlignedString(BASEVIDWIDTH-32, 108, V_REDMAP, va("(%d unfinished)", mapsunfinished[0]));*/ - - sprintf(beststr, "%i:%02i:%02i.%02i", G_TicsToHours(besttime), G_TicsToMinutes(besttime, false), G_TicsToSeconds(besttime), G_TicsToCentiseconds(besttime)); - V_DrawString(32, 140, V_YELLOWMAP, "TIME:"); - V_DrawRightAlignedString(BASEVIDWIDTH-32, 140, 0, beststr); - if (mapsunfinished) - V_DrawRightAlignedString(BASEVIDWIDTH-32, 148, V_REDMAP, va("(%d unfinished)", mapsunfinished)); - - /*sprintf(beststr, "%u", bestrings); - V_DrawString(32, 140, V_YELLOWMAP, "RINGS:"); - V_DrawRightAlignedString(BASEVIDWIDTH-32, 140, 0, beststr); - if (mapsunfinished[2]) - V_DrawRightAlignedString(BASEVIDWIDTH-32, 148, V_REDMAP, va("(%d unfinished)", mapsunfinished[2]));*/ -} - -static void M_HandleGameStats(INT32 choice) -{ - boolean exitmenu = false; // exit to previous menu - - switch (choice) - { - case KEY_ESCAPE: - exitmenu = true; - break; - - case KEY_ENTER: - S_StartSound(NULL, sfx_menu1); - M_SetupNextMenu(&SP_LevelStatsDef); - break; } if (exitmenu) { @@ -5568,21 +5700,30 @@ void M_DrawTimeAttackMenu(void) { INT32 i, x, y, cursory = 0; UINT16 dispstatus; - patch_t *PictureOfLevel, *PictureOfUrFace; - lumpnum_t lumpnum; + patch_t *PictureOfUrFace; char beststr[40]; - S_ChangeMusicInternal("racent", true); // Eww, but needed for when user hits escape during demo playback + //S_ChangeMusicInternal("racent", true); // Eww, but needed for when user hits escape during demo playback V_DrawPatchFill(W_CachePatchName("SRB2BACK", PU_CACHE)); M_DrawMenuTitle(); + if (currentMenu == &SP_TimeAttackDef) + M_DrawLevelSelectOnly(true, false); // draw menu (everything else goes on top of it) // Sadly we can't just use generic mode menus because we need some extra hacks x = currentMenu->x; y = currentMenu->y; + // Character face! + if (W_CheckNumForName(skins[cv_chooseskin.value-1].face) != LUMPERROR) + { + UINT8 *colormap = R_GetTranslationColormap(cv_chooseskin.value-1, cv_playercolor.value, 0); + PictureOfUrFace = W_CachePatchName(skins[cv_chooseskin.value-1].face, PU_CACHE); + V_DrawMappedPatch(BASEVIDWIDTH-x - SHORT(PictureOfUrFace->width), y, 0, PictureOfUrFace, colormap); + } + for (i = 0; i < currentMenu->numitems; ++i) { dispstatus = (currentMenu->menuitems[i].status & IT_DISPLAY); @@ -5593,67 +5734,55 @@ void M_DrawTimeAttackMenu(void) if (i == itemOn) cursory = y; - V_DrawString(x, y, (dispstatus == IT_WHITESTRING) ? V_YELLOWMAP : 0 , currentMenu->menuitems[i].text); + V_DrawString(x, y, (dispstatus == IT_WHITESTRING) ? highlightflags : 0 , currentMenu->menuitems[i].text); // Cvar specific handling if ((currentMenu->menuitems[i].status & IT_TYPE) == IT_CVAR) { consvar_t *cv = (consvar_t *)currentMenu->menuitems[i].itemaction; - INT32 soffset = 40; - - // hack to keep the menu from overlapping the player icon - if (currentMenu != &SP_TimeAttackDef) - soffset = 80; - - // Should see nothing but strings - if (cv == &cv_chooseskin) - V_DrawString(BASEVIDWIDTH - x - soffset - V_StringWidth(skins[cv_chooseskin.value-1].realname, 0), y, V_YELLOWMAP, skins[cv_chooseskin.value-1].realname); + if (currentMenu->menuitems[i].status & IT_CV_STRING) + { + M_DrawTextBox(x + 32, y - 8, MAXPLAYERNAME, 1); + V_DrawString(x + 40, y, V_ALLOWLOWERCASE, cv->string); + if (itemOn == i && skullAnimCounter < 4) // blink cursor + V_DrawCharacter(x + 40 + V_StringWidth(cv->string, V_ALLOWLOWERCASE), y, '_',false); + } else - V_DrawString(BASEVIDWIDTH - x - soffset - V_StringWidth(cv->string, 0), y, V_YELLOWMAP, cv->string); + { + const char *str = ((cv == &cv_chooseskin) ? skins[cv_chooseskin.value-1].realname : cv->string); + INT32 soffset = 40, strw = V_StringWidth(str, 0); + + // hack to keep the menu from overlapping the level icon + if (currentMenu != &SP_TimeAttackDef || cv == &cv_nextmap) + soffset = 0; + + // Should see nothing but strings + V_DrawString(BASEVIDWIDTH - x - soffset - strw, y, highlightflags, str); + + if (i == itemOn) + { + V_DrawCharacter(BASEVIDWIDTH - x - soffset - 10 - strw - (skullAnimCounter/5), y, + '\x1C' | highlightflags, false); // left arrow + V_DrawCharacter(BASEVIDWIDTH - x - soffset + 2 + (skullAnimCounter/5), y, + '\x1D' | highlightflags, false); // right arrow + } + } } else if ((currentMenu->menuitems[i].status & IT_TYPE) == IT_KEYHANDLER && cv_dummystaff.value) // bad hacky assumption: IT_KEYHANDLER is assumed to be staff ghost selector - { - V_DrawString(BASEVIDWIDTH - x - 80 - V_StringWidth(cv_dummystaff.string, 0), y, V_YELLOWMAP, cv_dummystaff.string); - } + V_DrawString(BASEVIDWIDTH - x - 80 - V_StringWidth(cv_dummystaff.string, 0), y, highlightflags, cv_dummystaff.string); } + x = currentMenu->x; + y = currentMenu->y; + // DRAW THE SKULL CURSOR - V_DrawScaledPatch(currentMenu->x - 24, cursory, 0, W_CachePatchName("M_CURSOR", PU_CACHE)); - V_DrawString(currentMenu->x, cursory, V_YELLOWMAP, currentMenu->menuitems[itemOn].text); - - // A 160x100 image of the level as entry MAPxxP - lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(cv_nextmap.value))); - - if (lumpnum != LUMPERROR) - PictureOfLevel = W_CachePatchName(va("%sP", G_BuildMapName(cv_nextmap.value)), PU_CACHE); - else - PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); - - V_DrawSmallScaledPatch(208, 32, 0, PictureOfLevel); - - // Character face! - if (W_CheckNumForName(skins[cv_chooseskin.value-1].face) != LUMPERROR) - { - UINT8 *colormap = R_GetTranslationColormap(cv_chooseskin.value-1, cv_playercolor.value, 0); - PictureOfUrFace = W_CachePatchName(skins[cv_chooseskin.value-1].face, PU_CACHE); - V_DrawMappedPatch(256,88,0,PictureOfUrFace, colormap); - } + V_DrawScaledPatch(x - 24, cursory, 0, W_CachePatchName("M_CURSOR", PU_CACHE)); + V_DrawString(x, cursory, highlightflags, currentMenu->menuitems[itemOn].text); // Level record list if (cv_nextmap.value) { emblem_t *em; - INT32 yHeight; - - V_DrawCenteredString(104, 32, 0, "* LEVEL RECORDS *"); - - /*if (!mainrecords[cv_nextmap.value-1] || !mainrecords[cv_nextmap.value-1]->score) - sprintf(beststr, "(none)"); - else - sprintf(beststr, "%u", mainrecords[cv_nextmap.value-1]->score); - - V_DrawString(104-72, 48, V_YELLOWMAP, "SCORE:"); - V_DrawRightAlignedString(104+72, 48, V_ALLOWLOWERCASE, beststr);*/ if (!mainrecords[cv_nextmap.value-1] || !mainrecords[cv_nextmap.value-1]->time) sprintf(beststr, "(none)"); @@ -5662,8 +5791,8 @@ void M_DrawTimeAttackMenu(void) G_TicsToSeconds(mainrecords[cv_nextmap.value-1]->time), G_TicsToCentiseconds(mainrecords[cv_nextmap.value-1]->time)); - V_DrawString(104-72, 53, V_YELLOWMAP, "BEST TIME:"); - V_DrawRightAlignedString(104+72, 53, V_ALLOWLOWERCASE, beststr); + V_DrawString(64, y+48, highlightflags, "BEST TIME:"); + V_DrawRightAlignedString(BASEVIDWIDTH - 64 - 24 - 8, y+48, V_ALLOWLOWERCASE, beststr); if (!mainrecords[cv_nextmap.value-1] || !mainrecords[cv_nextmap.value-1]->lap) sprintf(beststr, "(none)"); @@ -5672,8 +5801,8 @@ void M_DrawTimeAttackMenu(void) G_TicsToSeconds(mainrecords[cv_nextmap.value-1]->lap), G_TicsToCentiseconds(mainrecords[cv_nextmap.value-1]->lap)); - V_DrawString(104-72, 63, V_YELLOWMAP, "BEST LAP:"); - V_DrawRightAlignedString(104+72, 63, V_ALLOWLOWERCASE, beststr); + V_DrawString(64, y+56, highlightflags, "BEST LAP:"); + V_DrawRightAlignedString(BASEVIDWIDTH - 64 - 24 - 8, y+56, V_ALLOWLOWERCASE, beststr); // Draw record emblems. em = M_GetLevelEmblems(cv_nextmap.value); @@ -5681,41 +5810,49 @@ void M_DrawTimeAttackMenu(void) { switch (em->type) { - case ET_TIME: yHeight = 53; break; + case ET_TIME: break; default: goto skipThisOne; } if (em->collected) - V_DrawSmallMappedPatch(104+76, yHeight, 0, W_CachePatchName(M_GetEmblemPatch(em), PU_CACHE), + V_DrawMappedPatch(BASEVIDWIDTH - 64 - 24, y+48, 0, W_CachePatchName(M_GetEmblemPatch(em), PU_CACHE), R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(em), GTC_CACHE)); else - V_DrawSmallScaledPatch(104+76, yHeight, 0, W_CachePatchName("NEEDIT", PU_CACHE)); + V_DrawScaledPatch(BASEVIDWIDTH - 64 - 24, y+48, 0, W_CachePatchName("NEEDIT", PU_CACHE)); skipThisOne: em = M_GetLevelEmblems(-1); } } - // ALWAYS DRAW level name, skin and color even when not on this menu! + // ALWAYS DRAW player name, level name, skin and color even when not on this menu! if (currentMenu != &SP_TimeAttackDef) { consvar_t *ncv; - x = SP_TimeAttackDef.x; - y = SP_TimeAttackDef.y; - - for (i = 0; i < 3; ++i) + for (i = 0; i < 4; ++i) { + y = currentMenu->y+SP_TimeAttackMenu[i].alphaKey; + V_DrawString(x, y, V_TRANSLUCENT, SP_TimeAttackMenu[i].text); ncv = (consvar_t *)SP_TimeAttackMenu[i].itemaction; - - V_DrawString(x, y + SP_TimeAttackMenu[i].alphaKey, V_TRANSLUCENT, SP_TimeAttackMenu[i].text); - if (ncv == &cv_chooseskin) - V_DrawString(BASEVIDWIDTH - x - 40 - V_StringWidth(skins[cv_chooseskin.value-1].realname, 0), - y + SP_TimeAttackMenu[i].alphaKey, V_YELLOWMAP|V_TRANSLUCENT, skins[cv_chooseskin.value-1].realname); + if (SP_TimeAttackMenu[i].status & IT_CV_STRING) + { + M_DrawTextBox(x + 32, y - 8, MAXPLAYERNAME, 1); + V_DrawString(x + 40, y, V_TRANSLUCENT|V_ALLOWLOWERCASE, ncv->string); + } else - V_DrawString(BASEVIDWIDTH - x - 40 - V_StringWidth(ncv->string, 0), - y + SP_TimeAttackMenu[i].alphaKey, V_YELLOWMAP|V_TRANSLUCENT, ncv->string); + { + const char *str = ((ncv == &cv_chooseskin) ? skins[cv_chooseskin.value-1].realname : ncv->string); + INT32 soffset = 40, strw = V_StringWidth(str, 0); + + // hack to keep the menu from overlapping the level icon + if (ncv == &cv_nextmap) + soffset = 0; + + // Should see nothing but strings + V_DrawString(BASEVIDWIDTH - x - soffset - strw, y, highlightflags|V_TRANSLUCENT, str); + } } } } @@ -5747,6 +5884,13 @@ static void M_TimeAttack(INT32 choice) S_ChangeMusicInternal("racent", true); } +static boolean M_QuitTimeAttackMenu(void) +{ + // you know what? always putting these in the buffer won't hurt anything. + COM_BufAddText(va("skin \"%s\"\n", cv_chooseskin.string)); + return true; +} + // Drawing function for Nights Attack /*void M_DrawNightsAttackMenu(void) { @@ -5765,7 +5909,7 @@ static void M_TimeAttack(INT32 choice) lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(cv_nextmap.value))); if (lumpnum != LUMPERROR) - PictureOfLevel = W_CachePatchName(va("%sP", G_BuildMapName(cv_nextmap.value)), PU_CACHE); + PictureOfLevel = W_CachePatchNum(lumpnum, PU_CACHE); else PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); @@ -5789,7 +5933,7 @@ static void M_TimeAttack(INT32 choice) { if (P_HasGrades(cv_nextmap.value, cv_dummymares.value)) { - V_DrawString(160-88, 112, V_YELLOWMAP, "BEST GRADE:"); + V_DrawString(160-88, 112, highlightflags, "BEST GRADE:"); V_DrawSmallScaledPatch(160 + 86 - (ngradeletters[bestgrade]->width/2), 112 + 8 - (ngradeletters[bestgrade]->height/2), 0, ngradeletters[bestgrade]); @@ -5800,7 +5944,7 @@ static void M_TimeAttack(INT32 choice) else sprintf(beststr, "%u", bestscore); - V_DrawString(160 - 88, 122, V_YELLOWMAP, "BEST SCORE:"); + V_DrawString(160 - 88, 122, highlightflags, "BEST SCORE:"); V_DrawRightAlignedString(160 + 88, 122, V_ALLOWLOWERCASE, beststr); if (besttime == UINT32_MAX) @@ -5810,7 +5954,7 @@ static void M_TimeAttack(INT32 choice) G_TicsToSeconds(besttime), G_TicsToCentiseconds(besttime)); - V_DrawString(160-88, 132, V_YELLOWMAP, "BEST TIME:"); + V_DrawString(160-88, 132, highlightflags, "BEST TIME:"); V_DrawRightAlignedString(160+88, 132, V_ALLOWLOWERCASE, beststr); if (cv_dummymares.value == 0) { @@ -5847,7 +5991,7 @@ static void M_TimeAttack(INT32 choice) ncv = (consvar_t *)SP_NightsAttackMenu[0].itemaction; V_DrawString(x, y + SP_NightsAttackMenu[0].alphaKey, V_TRANSLUCENT, SP_NightsAttackMenu[0].text); V_DrawString(BASEVIDWIDTH - x - V_StringWidth(ncv->string, 0), - y + SP_NightsAttackMenu[0].alphaKey, V_YELLOWMAP|V_TRANSLUCENT, ncv->string); + y + SP_NightsAttackMenu[0].alphaKey, highlightflags|V_TRANSLUCENT, ncv->string); } } }*/ @@ -6282,7 +6426,7 @@ static void M_DrawRoomMenu(void) // use generic drawer for cursor, items and title M_DrawGenericMenu(); - V_DrawString(currentMenu->x - 16, currentMenu->y, V_YELLOWMAP, M_GetText("Select a room")); + V_DrawString(currentMenu->x - 16, currentMenu->y, highlightflags, M_GetText("Select a room")); M_DrawTextBox(144, 24, 20, 20); @@ -6310,14 +6454,14 @@ static void M_DrawConnectMenu(void) // Room name if (ms_RoomId < 0) V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, currentMenu->y + MP_ConnectMenu[mp_connect_room].alphaKey, - V_YELLOWMAP, (itemOn == mp_connect_room) ? "" : ""); else V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, currentMenu->y + MP_ConnectMenu[mp_connect_room].alphaKey, - V_YELLOWMAP, room_list[menuRoomIndex].name); + highlightflags, room_list[menuRoomIndex].name); // Page num V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, currentMenu->y + MP_ConnectMenu[mp_connect_page].alphaKey, - V_YELLOWMAP, va("%u of %d", serverlistpage+1, numPages)); + highlightflags, va("%u of %d", serverlistpage+1, numPages)); // Horizontal line! V_DrawFill(1, currentMenu->y+40, 318, 1, 0); @@ -6329,7 +6473,7 @@ static void M_DrawConnectMenu(void) { INT32 slindex = i + serverlistpage * SERVERS_PER_PAGE; UINT32 globalflags = ((serverlist[slindex].info.numberofplayer >= serverlist[slindex].info.maxplayer) ? V_TRANSLUCENT : 0) - |((itemOn == FIRSTSERVERLINE+i) ? V_YELLOWMAP : 0)|V_ALLOWLOWERCASE; + |((itemOn == FIRSTSERVERLINE+i) ? highlightflags : 0)|V_ALLOWLOWERCASE; V_DrawString(currentMenu->x, S_LINEY(i), globalflags, serverlist[slindex].info.servername); @@ -6535,13 +6679,16 @@ static void M_ChooseRoom(INT32 choice) // // FindFirstMap // -// Finds the first map of a particular gametype +// Finds the first map of a particular gametype (or returns the current map) // Defaults to 1 if nothing found. // static INT32 M_FindFirstMap(INT32 gtype) { INT32 i; + if (mapheaderinfo[gamemap] && (mapheaderinfo[gamemap]->typeoflevel & gtype)) + return gamemap; + for (i = 0; i < NUMMAPS; i++) { if (mapheaderinfo[i] && (mapheaderinfo[i]->typeoflevel & gtype)) @@ -6555,15 +6702,16 @@ static void M_StartServer(INT32 choice) { UINT8 ssplayers = 0; - if (currentMenu == &MP_SplitServerDef) - ssplayers = 1; - else if (currentMenu == &MP_3PServerDef) - ssplayers = 2; - else if (currentMenu == &MP_4PServerDef) - ssplayers = 3; - (void)choice; - if (ssplayers < 2) + + if (currentMenu == &MP_SplitServerDef) + ssplayers = +#ifdef NOFOURPLAYER + 1; +#else + cv_dummysplitplayers.value-1; +#endif + else netgame = true; multiplayer = true; @@ -6598,44 +6746,185 @@ static void M_StartServer(INT32 choice) M_ClearMenus(true); } -static void M_DrawServerMenu(void) +static void M_DrawLevelSelectOnly(boolean leftfade, boolean rightfade) { lumpnum_t lumpnum; patch_t *PictureOfLevel; + INT32 x, y, w, i, oldval, trans, dupadjust = ((vid.width/vid.dupx) - BASEVIDWIDTH)>>1; + // A 160x100 image of the level as entry MAPxxP + lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(cv_nextmap.value))); + + if (lumpnum != LUMPERROR) + PictureOfLevel = W_CachePatchNum(lumpnum, PU_CACHE); + else + PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); + + w = SHORT(PictureOfLevel->width)/2; + i = SHORT(PictureOfLevel->height)/2; + x = BASEVIDWIDTH/2 - w/2; + y = currentMenu->y + 130 + 8 - i; + + if (currentMenu->menuitems[itemOn].itemaction == &cv_nextmap && skullAnimCounter < 4) + trans = 120; + else + trans = G_GetGametypeColor(cv_newgametype.value); + + V_DrawFill(x-1, y-1, w+2, i+2, trans); // variable reuse... + + V_DrawSmallScaledPatch(x, y, 0, PictureOfLevel); + /*V_DrawDiag(x, y, 12, 31); + V_DrawDiag(x, y, 10, G_GetGametypeColor(cv_newgametype.value));*/ + + y += i/4; + i = cv_nextmap.value - 1; + trans = (leftfade ? V_TRANSLUCENT : 0); + +#define horizspac 2 + do + { + oldval = i; + do + { + i--; + if (i == -1) + i = NUMMAPS-1; + + if (i == oldval) + return; + + if(!mapheaderinfo[i]) + continue; // Don't allocate the header. That just makes memory usage skyrocket. + + } while (!M_CanShowLevelInList(i, cv_newgametype.value)); + + // A 160x100 image of the level as entry MAPxxP + lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(i+1))); + + if (lumpnum != LUMPERROR) + PictureOfLevel = W_CachePatchNum(lumpnum, PU_CACHE); + else + PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); + + x -= horizspac + SHORT(PictureOfLevel->width)/4; + V_DrawTinyScaledPatch(x, y, trans, PictureOfLevel); + } while (x > horizspac-dupadjust); + + x = (BASEVIDWIDTH + w)/2 + horizspac; + i = cv_nextmap.value - 1; + trans = (rightfade ? V_TRANSLUCENT : 0); + + while (x < BASEVIDWIDTH+dupadjust-horizspac) + { + oldval = i; + do + { + i++; + if (i == NUMMAPS) + i = 0; + + if (i == oldval) + return; + + if(!mapheaderinfo[i]) + continue; // Don't allocate the header. That just makes memory usage skyrocket. + + } while (!M_CanShowLevelInList(i, cv_newgametype.value)); + + // A 160x100 image of the level as entry MAPxxP + lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(i+1))); + + if (lumpnum != LUMPERROR) + PictureOfLevel = W_CachePatchNum(lumpnum, PU_CACHE); + else + PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); + + V_DrawTinyScaledPatch(x, y, trans, PictureOfLevel); + x += horizspac + SHORT(PictureOfLevel->width)/4; + } +#undef horizspac +} + +static void M_DrawServerMenu(void) +{ + M_DrawLevelSelectOnly((currentMenu == &MP_SplitServerDef), false); M_DrawGenericMenu(); #ifndef NONET // Room name if (currentMenu == &MP_ServerDef) { +#define mp_server_room 1 if (ms_RoomId < 0) V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, currentMenu->y + MP_ServerMenu[mp_server_room].alphaKey, - V_YELLOWMAP, (itemOn == mp_server_room) ? "" : ""); else V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, currentMenu->y + MP_ServerMenu[mp_server_room].alphaKey, - V_YELLOWMAP, room_list[menuRoomIndex].name); + highlightflags, room_list[menuRoomIndex].name); +#undef mp_server_room } + else +#endif + if (currentMenu == &MP_SplitServerDef) + // character bar, ripped off the color bar :V + { +#define iconwidth 32 +#define spacingwidth 32 +#define incrwidth (iconwidth + spacingwidth) + UINT8 i = 0, pskin, pcol; + // player arrangement width, but there's also a chance i'm a furry, shhhhhh + const INT32 paw = iconwidth + +#ifndef NOFOURPLAYER + 3* +#endif + incrwidth; + INT32 x = BASEVIDWIDTH/2 - paw/2, y = currentMenu->y + 27, trans = 0; + patch_t *face; + + while (++i <= +#ifdef NOFOURPLAYER + 2 +#else + 4 +#endif + ) + { + switch (i) + { + default: + pskin = R_SkinAvailable(cv_skin.string); + pcol = cv_playercolor.value; + break; + case 2: + pskin = R_SkinAvailable(cv_skin2.string); + pcol = cv_playercolor2.value; + break; + case 3: + pskin = R_SkinAvailable(cv_skin3.string); + pcol = cv_playercolor3.value; + break; + case 4: + pskin = R_SkinAvailable(cv_skin4.string); + pcol = cv_playercolor4.value; + break; + } + + if (pskin >= MAXSKINS) + pskin = 0; + +#ifndef NOFOURPLAYER + if (!trans && i > cv_dummysplitplayers.value) + trans = V_TRANSLUCENT; #endif - // SRB2kart - // A 70x70 image of the level's gametype - /* - if (mapheaderinfo[cv_nextmap.value-1].typeoflevel & TOL_KART) - V_DrawSmallScaledPatch(BASEVIDWIDTH/2,130,0,W_CachePatchName("KART", PU_STATIC)); - else - V_DrawSmallScaledPatch(BASEVIDWIDTH/2,130,0,W_CachePatchName("SONR", PU_STATIC)); - */ - - // A 160x100 image of the level as entry MAPxxP - lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(cv_nextmap.value))); - - if (lumpnum != LUMPERROR) - PictureOfLevel = W_CachePatchName(va("%sP", G_BuildMapName(cv_nextmap.value)), PU_CACHE); - else - PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); - - V_DrawSmallScaledPatch((BASEVIDWIDTH*3/4)-(SHORT(PictureOfLevel->width)/4), ((BASEVIDHEIGHT*3/4)-(SHORT(PictureOfLevel->height)/4)+10), 0, PictureOfLevel); + face = W_CachePatchName(skins[pskin].face, PU_CACHE); + V_DrawFixedPatch(x<x; + INT32 y = currentMenu->y; + // use generic drawer for cursor, items and title M_DrawGenericMenu(); +#if MAXPLAYERS == 16 + V_DrawRightAlignedString(BASEVIDWIDTH-x, y+MP_MainMenu[1].alphaKey, + ((itemOn == 1) ? highlightflags : 0), "(2-16 players)"); +#else +Update the maxplayers label... +#endif + + V_DrawRightAlignedString(BASEVIDWIDTH-x, y+MP_MainMenu[2].alphaKey, + ((itemOn == 2) ? highlightflags : 0), +#ifdef NOFOURPLAYER + "(2 players)" +#else + "(2-4 players)" +#endif + ); + + y += MP_MainMenu[5].alphaKey; + + V_DrawFill(x+5, y+4+5, /*16*8 + 6,*/ BASEVIDWIDTH - 2*(x+5), 8+6, 239); + // draw name string - V_DrawString(128,40, V_MONOSPACE, setupm_ip); + V_DrawString(x+8,y+12, V_MONOSPACE, setupm_ip); // draw text cursor for name - if (itemOn == 0 && - skullAnimCounter < 4) //blink cursor - V_DrawCharacter(128+V_StringWidth(setupm_ip, V_MONOSPACE),40,'_',false); + if (itemOn == 5 + && skullAnimCounter < 4) //blink cursor + V_DrawCharacter(x+8+V_StringWidth(setupm_ip, V_MONOSPACE),y+12,'_',false); } // Tails 11-19-2002 @@ -6745,11 +7029,21 @@ static void M_ConnectIP(INT32 choice) // Tails 11-19-2002 static void M_HandleConnectIP(INT32 choice) { - size_t l; - boolean exitmenu = false; // exit to previous menu and send name change + size_t l; + boolean exitmenu = false; // exit to previous menu and send name change switch (choice) { + case KEY_DOWNARROW: + M_NextOpt(); + S_StartSound(NULL,sfx_menu1); // Tails + break; + + case KEY_UPARROW: + M_PrevOpt(); + S_StartSound(NULL,sfx_menu1); // Tails + break; + case KEY_ENTER: S_StartSound(NULL,sfx_menu1); // Tails M_ClearMenus(true); @@ -6761,29 +7055,41 @@ static void M_HandleConnectIP(INT32 choice) break; case KEY_BACKSPACE: - if ((l = strlen(setupm_ip))!=0 && itemOn == 0) + if ((l = strlen(setupm_ip)) != 0) { S_StartSound(NULL,sfx_menu1); // Tails - setupm_ip[l-1] =0; + setupm_ip[l-1] = 0; + } + break; + + case KEY_DEL: + if (setupm_ip[0]) + { + S_StartSound(NULL,sfx_menu1); // Tails + setupm_ip[0] = 0; } break; default: l = strlen(setupm_ip); - if (l < 16-1 && (choice == 46 || (choice >= 48 && choice <= 57))) // Rudimentary number and period enforcing + if (l >= 16-1) + break; + + if (choice == 46 || (choice >= 48 && choice <= 57)) // Rudimentary number and period enforcing { S_StartSound(NULL,sfx_menu1); // Tails - setupm_ip[l] =(char)choice; - setupm_ip[l+1] =0; + setupm_ip[l] = (char)choice; + setupm_ip[l+1] = 0; } - else if (l < 16-1 && choice >= 199 && choice <= 211 && choice != 202 && choice != 206) //numpad too! + else if (choice >= 199 && choice <= 211 && choice != 202 && choice != 206) //numpad too! { - XBOXSTATIC char keypad_translation[] = {'7','8','9','-','4','5','6','+','1','2','3','0','.'}; + char keypad_translation[] = {'7','8','9','-','4','5','6','+','1','2','3','0','.'}; choice = keypad_translation[choice - 199]; S_StartSound(NULL,sfx_menu1); // Tails - setupm_ip[l] =(char)choice; - setupm_ip[l+1] =0; + setupm_ip[l] = (char)choice; + setupm_ip[l+1] = 0; } + break; } @@ -6827,6 +7133,7 @@ static void M_DrawSetupMultiPlayerMenu(void) UINT8 speed; UINT8 weight; UINT8 i; + const UINT8 *flashcol = V_GetStringColormap(highlightflags); mx = MP_PlayerSetupDef.x; my = MP_PlayerSetupDef.y; @@ -6838,21 +7145,37 @@ static void M_DrawSetupMultiPlayerMenu(void) M_DrawTextBox(mx + 32, my - 8, MAXPLAYERNAME, 1); V_DrawString(mx + 40, my, V_ALLOWLOWERCASE, setupm_name); + // draw text cursor for name + if (!itemOn && skullAnimCounter < 4) // blink cursor + V_DrawCharacter(mx + 40 + V_StringWidth(setupm_name, V_ALLOWLOWERCASE), my, '_',false); + // draw skin string - V_DrawString(mx + 80, my + 16, - ((MP_PlayerSetupMenu[2].status & IT_TYPE) == IT_SPACE ? V_TRANSLUCENT : 0)|V_YELLOWMAP|V_ALLOWLOWERCASE, + st = V_StringWidth(skins[setupm_fakeskin].realname, 0); + V_DrawString(BASEVIDWIDTH - mx - st, my + 16, + ((MP_PlayerSetupMenu[2].status & IT_TYPE) == IT_SPACE ? V_TRANSLUCENT : 0)|highlightflags|V_ALLOWLOWERCASE, skins[setupm_fakeskin].realname); + if (itemOn == 1) + { + V_DrawCharacter(BASEVIDWIDTH - mx - 10 - st - (skullAnimCounter/5), my + 16, + '\x1C' | highlightflags, false); // left arrow + V_DrawCharacter(BASEVIDWIDTH - mx + 2 + (skullAnimCounter/5), my + 16, + '\x1D' | highlightflags, false); // right arrow + } // draw the name of the color you have chosen // Just so people don't go thinking that "Default" is Green. - V_DrawString(mx + 48, my + 152, V_YELLOWMAP|V_ALLOWLOWERCASE, KartColor_Names[setupm_fakecolor]); // SRB2kart - - // draw text cursor for name - if (!itemOn && skullAnimCounter < 4) // blink cursor - V_DrawCharacter(mx + 40 + V_StringWidth(setupm_name, 0), my, '_',false); + st = V_StringWidth(KartColor_Names[setupm_fakecolor], 0); + V_DrawString(BASEVIDWIDTH - mx - st, my + 152, highlightflags|V_ALLOWLOWERCASE, KartColor_Names[setupm_fakecolor]); // SRB2kart + if (itemOn == 2) + { + V_DrawCharacter(BASEVIDWIDTH - mx - 10 - st - (skullAnimCounter/5), my + 152, + '\x1C' | highlightflags, false); // left arrow + V_DrawCharacter(BASEVIDWIDTH - mx + 2 + (skullAnimCounter/5), my + 152, + '\x1D' | highlightflags, false); // right arrow + } // SRB2Kart: draw the stat backer - V_DrawFixedPatch((mx+141)<= MAXSKINCOLORS) col -= MAXSKINCOLORS-1; x += w; @@ -6893,6 +7229,7 @@ static void M_DrawSetupMultiPlayerMenu(void) #undef indexwidth // character bar, ripped off the color bar :V + if (setupm_fakecolor) // inverse should never happen #define iconwidth 32 { const INT32 icons = 4; @@ -6961,45 +7298,23 @@ static void M_DrawSetupMultiPlayerMenu(void) flags |= V_FLIP; // This sprite is left/right flipped! // draw box around guy - V_DrawFill((mx+42)-(charw/2), my+66, charw, 84, 239); - - if (skullAnimCounter < 4) // SRB2Kart: we draw this dot later so that it's not covered if there's multiple skins with the same stats - statdot = W_CachePatchName("K_SDOT2", PU_CACHE); - else - statdot = W_CachePatchName("K_SDOT1", PU_CACHE); - - speed = skins[setupm_fakeskin].kartspeed; - weight = skins[setupm_fakeskin].kartweight; + V_DrawFill(mx + 43 - (charw/2), my+65, charw, 84, 239); // draw player sprite - if (!setupm_fakecolor) // should never happen but hey, who knows - { - if (skins[setupm_fakeskin].flags & SF_HIRES) - { - V_DrawSciencePatch((mx+42)< 127 || itemOn != 0) break; l = strlen(setupm_name); - if (l < MAXPLAYERNAME-1) + if (l < MAXPLAYERNAME) { S_StartSound(NULL,sfx_menu1); // Tails setupm_name[l] =(char)choice; @@ -7301,7 +7636,7 @@ static void M_DrawJoystick(void) M_DrawGenericMenu(); - for (i = 0;i < 8; i++) + for (i = 0; i < 8; i++) { M_DrawSaveLoadBorder(OP_JoystickSetDef.x, OP_JoystickSetDef.y+LINEHEIGHT*i); @@ -7309,7 +7644,7 @@ static void M_DrawJoystick(void) || (setupcontrols_thirdplayer && (i == cv_usejoystick3.value)) || (setupcontrols_secondaryplayer && (i == cv_usejoystick2.value)) || (!(setupcontrols_secondaryplayer || setupcontrols_thirdplayer || setupcontrols_fourthplayer) && (i == cv_usejoystick.value))) - V_DrawString(OP_JoystickSetDef.x, OP_JoystickSetDef.y+LINEHEIGHT*i,V_GREENMAP,joystickInfo[i]); + V_DrawString(OP_JoystickSetDef.x, OP_JoystickSetDef.y+LINEHEIGHT*i,recommendedflags,joystickInfo[i]); else V_DrawString(OP_JoystickSetDef.x, OP_JoystickSetDef.y+LINEHEIGHT*i,0,joystickInfo[i]); } @@ -7396,13 +7731,17 @@ static void M_Setup1PControlsMenu(INT32 choice) currentMenu->lastOn = itemOn; // Unhide P1-only controls - OP_MoveControlsMenu[9].status = IT_CALL|IT_STRING2; // Talk - OP_MoveControlsMenu[10].status = IT_CALL|IT_STRING2; // Team talk - OP_MoveControlsMenu[11].status = IT_CALL|IT_STRING2; // Rankings - OP_MoveControlsMenu[12].status = IT_CALL|IT_STRING2; // Pause - OP_MoveControlsMenu[13].status = IT_CALL|IT_STRING2; // Console + OP_MoveControlsMenu[10].status = IT_CONTROL; // Talk + //OP_MoveControlsMenu[11].status = IT_CONTROL; // Team-talk + OP_MoveControlsMenu[11].status = IT_CONTROL; // Rankings + OP_MoveControlsMenu[12].status = IT_CONTROL; // Pause + OP_MoveControlsMenu[13].status = IT_CONTROL; // Console + OP_MoveControlsMenu[14].itemaction = &OP_Joystick1Def; // Gamepad + + // Set cvars + OP_SpectateControlsMenu[6].itemaction = &cv_chasecam; // Chasecam + OP_SpectateControlsMenu[7].itemaction = &cv_crosshair; // Crosshair - OP_MoveControlsDef.prevMenu = &OP_P1ControlsDef; M_SetupNextMenu(&OP_MoveControlsDef); } @@ -7410,19 +7749,22 @@ static void M_Setup2PControlsMenu(INT32 choice) { (void)choice; setupcontrols_secondaryplayer = true; - setupcontrols_thirdplayer = false; - setupcontrols_fourthplayer = false; + setupcontrols_thirdplayer = setupcontrols_fourthplayer = false; setupcontrols = gamecontrolbis; currentMenu->lastOn = itemOn; // Hide P1-only controls - OP_MoveControlsMenu[9].status = IT_GRAYEDOUT2; // Talk - OP_MoveControlsMenu[10].status = IT_GRAYEDOUT2; // Team talk + OP_MoveControlsMenu[10].status = IT_GRAYEDOUT2; // Talk + //OP_MoveControlsMenu[11].status = IT_GRAYEDOUT2; // Team-talk OP_MoveControlsMenu[11].status = IT_GRAYEDOUT2; // Rankings OP_MoveControlsMenu[12].status = IT_GRAYEDOUT2; // Pause OP_MoveControlsMenu[13].status = IT_GRAYEDOUT2; // Console + OP_MoveControlsMenu[14].itemaction = &OP_Joystick2Def; // Gamepad + + // Set cvars + OP_SpectateControlsMenu[6].itemaction = &cv_chasecam2; // Chasecam + OP_SpectateControlsMenu[7].itemaction = &cv_crosshair2; // Crosshair - OP_MoveControlsDef.prevMenu = &OP_P2ControlsDef; M_SetupNextMenu(&OP_MoveControlsDef); } @@ -7431,19 +7773,22 @@ static void M_Setup3PControlsMenu(INT32 choice) { (void)choice; setupcontrols_thirdplayer = true; - setupcontrols_secondaryplayer = false; - setupcontrols_fourthplayer = false; + setupcontrols_secondaryplayer = setupcontrols_fourthplayer = false; setupcontrols = gamecontrol3; currentMenu->lastOn = itemOn; // Hide P1-only controls - OP_MoveControlsMenu[9].status = IT_GRAYEDOUT2; // Talk - OP_MoveControlsMenu[10].status = IT_GRAYEDOUT2; // Team talk + OP_MoveControlsMenu[10].status = IT_GRAYEDOUT2; // Talk + //OP_MoveControlsMenu[11].status = IT_GRAYEDOUT2; // Team-talk OP_MoveControlsMenu[11].status = IT_GRAYEDOUT2; // Rankings OP_MoveControlsMenu[12].status = IT_GRAYEDOUT2; // Pause OP_MoveControlsMenu[13].status = IT_GRAYEDOUT2; // Console + OP_MoveControlsMenu[14].itemaction = &OP_Joystick3Def; // Gamepad + + // Set cvars + OP_SpectateControlsMenu[6].itemaction = &cv_chasecam3; // Chasecam + OP_SpectateControlsMenu[7].itemaction = &cv_crosshair3; // Crosshair - OP_MoveControlsDef.prevMenu = &OP_P3ControlsDef; M_SetupNextMenu(&OP_MoveControlsDef); } @@ -7451,19 +7796,22 @@ static void M_Setup4PControlsMenu(INT32 choice) { (void)choice; setupcontrols_fourthplayer = true; - setupcontrols_secondaryplayer = false; - setupcontrols_thirdplayer = false; + setupcontrols_secondaryplayer = setupcontrols_thirdplayer = false; setupcontrols = gamecontrol4; currentMenu->lastOn = itemOn; // Hide P1-only controls - OP_MoveControlsMenu[9].status = IT_GRAYEDOUT2; // Talk - OP_MoveControlsMenu[10].status = IT_GRAYEDOUT2; // Team talk + OP_MoveControlsMenu[10].status = IT_GRAYEDOUT2; // Talk + //OP_MoveControlsMenu[11].status = IT_GRAYEDOUT2; // Team-talk OP_MoveControlsMenu[11].status = IT_GRAYEDOUT2; // Rankings OP_MoveControlsMenu[12].status = IT_GRAYEDOUT2; // Pause OP_MoveControlsMenu[13].status = IT_GRAYEDOUT2; // Console + OP_MoveControlsMenu[14].itemaction = &OP_Joystick4Def; // Gamepad + + // Set cvars + OP_SpectateControlsMenu[6].itemaction = &cv_chasecam4; // Chasecam + OP_SpectateControlsMenu[7].itemaction = &cv_crosshair4; // Crosshair - OP_MoveControlsDef.prevMenu = &OP_P4ControlsDef; M_SetupNextMenu(&OP_MoveControlsDef); } #endif @@ -7472,7 +7820,7 @@ static void M_Setup4PControlsMenu(INT32 choice) static void M_DrawControl(void) { char tmp[50]; - INT32 i; + INT32 i, y; INT32 keys[2]; const char *ctrl; @@ -7480,18 +7828,25 @@ static void M_DrawControl(void) M_DrawGenericMenu(); if (setupcontrols_secondaryplayer) - ctrl = "SET CONTROLS FOR SECONDARY PLAYER"; + ctrl = "\x86""SET ""\x82""CONTROLS""\x86"" FOR ""\x82""SECONDARY PLAYER"; else if (setupcontrols_thirdplayer) - ctrl = "SET CONTROLS FOR THIRD PLAYER"; + ctrl = "\x86""SET ""\x82""CONTROLS""\x86"" FOR ""\x82""THIRD PLAYER"; else if (setupcontrols_fourthplayer) - ctrl = "SET CONTROLS FOR FOURTH PLAYER"; + ctrl = "\x86""SET ""\x82""CONTROLS""\x86"" FOR ""\x82""FOURTH PLAYER"; else - ctrl = "PRESS ENTER TO CHANGE, BACKSPACE TO CLEAR"; + ctrl = "\x86""PRESS ""\x82""ENTER""\x86"" TO CHANGE, ""\x82""BACKSPACE""\x86"" TO CLEAR"; - M_CentreText(30, ctrl); + M_CentreText(28, ctrl); - for (i = 0;i < currentMenu->numitems;i++) + y = currentMenu->y; + + for (i = 0; i < currentMenu->numitems;i++) { + if (currentMenu->menuitems[i].status != IT_CONTROL) + { + y = currentMenu->y+currentMenu->menuitems[i].alphaKey; + continue; + } if (currentMenu->menuitems[i].status != IT_CONTROL) continue; @@ -7516,7 +7871,8 @@ static void M_DrawControl(void) } - V_DrawRightAlignedString(BASEVIDWIDTH-currentMenu->x, currentMenu->y + i*8, V_YELLOWMAP, tmp); + V_DrawRightAlignedString(BASEVIDWIDTH-currentMenu->x, y, highlightflags, tmp); + y += SMALLLINEHEIGHT; } } @@ -7616,85 +7972,189 @@ static void M_ChangeControl(INT32 choice) // ===== // Toggles sound systems in-game. -static void M_ToggleSFX(void) +static void M_ToggleSFX(INT32 choice) { + switch (choice) + { + case KEY_DOWNARROW: + S_StartSound(NULL, sfx_menu1); + itemOn++; + return; + + case KEY_UPARROW: + S_StartSound(NULL, sfx_menu1); + itemOn = currentMenu->numitems-1; + return; + + case KEY_ESCAPE: + currentMenu->lastOn = itemOn; + if (currentMenu->prevMenu) + M_SetupNextMenu(currentMenu->prevMenu); + else + M_ClearMenus(true); + return; + default: + break; + } + if (nosound) { nosound = false; I_StartupSound(); if (nosound) return; - S_Init(cv_soundvolume.value, cv_digmusicvolume.value, cv_midimusicvolume.value); - M_StartMessage(M_GetText("SFX Enabled\n"), NULL, MM_NOTHING); + S_Init(cv_soundvolume.value, cv_digmusicvolume.value);//, cv_midimusicvolume.value); + S_StartSound(NULL, sfx_strpst); + //M_StartMessage(M_GetText("SFX Enabled\n"), NULL, MM_NOTHING); } else { if (sound_disabled) { sound_disabled = false; - M_StartMessage(M_GetText("SFX Enabled\n"), NULL, MM_NOTHING); + S_StartSound(NULL, sfx_strpst); + //M_StartMessage(M_GetText("SFX Enabled\n"), NULL, MM_NOTHING); } else { sound_disabled = true; S_StopSounds(); - M_StartMessage(M_GetText("SFX Disabled\n"), NULL, MM_NOTHING); + //M_StartMessage(M_GetText("SFX Disabled\n"), NULL, MM_NOTHING); } } } -static void M_ToggleDigital(void) +static void M_ToggleDigital(INT32 choice) { + switch (choice) + { + case KEY_DOWNARROW: + S_StartSound(NULL, sfx_menu1); + itemOn++; + return; + + case KEY_UPARROW: + S_StartSound(NULL, sfx_menu1); + itemOn--; + return; + + case KEY_ESCAPE: + currentMenu->lastOn = itemOn; + if (currentMenu->prevMenu) + M_SetupNextMenu(currentMenu->prevMenu); + else + M_ClearMenus(true); + return; + default: + break; + } + if (nodigimusic) { nodigimusic = false; I_InitDigMusic(); if (nodigimusic) return; - S_Init(cv_soundvolume.value, cv_digmusicvolume.value, cv_midimusicvolume.value); + S_Init(cv_soundvolume.value, cv_digmusicvolume.value);//, cv_midimusicvolume.value); S_StopMusic(); - S_ChangeMusicInternal("lclear", false); - M_StartMessage(M_GetText("Digital Music Enabled\n"), NULL, MM_NOTHING); + if (Playing()) + P_RestoreMusic(&players[consoleplayer]); + else + S_ChangeMusicInternal("titles", looptitle); + //M_StartMessage(M_GetText("Digital Music Enabled\n"), NULL, MM_NOTHING); } else { if (digital_disabled) { digital_disabled = false; - M_StartMessage(M_GetText("Digital Music Enabled\n"), NULL, MM_NOTHING); + if (Playing()) + P_RestoreMusic(&players[consoleplayer]); + else + S_ChangeMusicInternal("titles", looptitle); + //M_StartMessage(M_GetText("Digital Music Enabled\n"), NULL, MM_NOTHING); } else { digital_disabled = true; S_StopMusic(); - M_StartMessage(M_GetText("Digital Music Disabled\n"), NULL, MM_NOTHING); + //M_StartMessage(M_GetText("Digital Music Disabled\n"), NULL, MM_NOTHING); } } } -static void M_ToggleMIDI(void) +/*static void M_ToggleMIDI(INT32 choice) { + switch (choice) + { + case KEY_DOWNARROW: + S_StartSound(NULL, sfx_menu1); + itemOn++; + return; + + case KEY_UPARROW: + S_StartSound(NULL, sfx_menu1); + itemOn--; + return; + + case KEY_ESCAPE: + if (currentMenu->prevMenu) + M_SetupNextMenu(currentMenu->prevMenu); + else + M_ClearMenus(true); + return; + default: + break; + } + if (nomidimusic) { nomidimusic = false; I_InitMIDIMusic(); if (nomidimusic) return; S_Init(cv_soundvolume.value, cv_digmusicvolume.value, cv_midimusicvolume.value); - S_ChangeMusicInternal("lclear", false); - M_StartMessage(M_GetText("MIDI Music Enabled\n"), NULL, MM_NOTHING); + if (Playing()) + P_RestoreMusic(&players[consoleplayer]); + else + S_ChangeMusicInternal("_clear", false); + //M_StartMessage(M_GetText("MIDI Music Enabled\n"), NULL, MM_NOTHING); } else { if (music_disabled) { music_disabled = false; - M_StartMessage(M_GetText("MIDI Music Enabled\n"), NULL, MM_NOTHING); + if (Playing()) + P_RestoreMusic(&players[consoleplayer]); + else + S_ChangeMusicInternal("_clear", false); + //M_StartMessage(M_GetText("MIDI Music Enabled\n"), NULL, MM_NOTHING); } else { music_disabled = true; S_StopMusic(); - M_StartMessage(M_GetText("MIDI Music Disabled\n"), NULL, MM_NOTHING); + //M_StartMessage(M_GetText("MIDI Music Disabled\n"), NULL, MM_NOTHING); } } +}*/ + +static void M_RestartAudio(void) +{ + S_StopMusic(); + I_ShutdownMusic(); + I_ShutdownSound(); + I_StartupSound(); + I_InitMusic(); + + I_SetSfxVolume(cv_soundvolume.value); + I_SetDigMusicVolume(cv_digmusicvolume.value); + //I_SetMIDIMusicVolume(cv_midimusicvolume.value); + + S_StartSound(NULL, sfx_strpst); + + if (Playing()) // Gotta make sure the player is in a level + P_RestoreMusic(&players[consoleplayer]); + else + S_ChangeMusicInternal("titles", looptitle); } // =============== @@ -7787,6 +8247,37 @@ static void M_VideoModeMenu(INT32 choice) M_SetupNextMenu(&OP_VideoModeDef); } +static void M_DrawVideoMenu(void) +{ + M_DrawGenericMenu(); + + V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, currentMenu->y + OP_VideoOptionsMenu[0].alphaKey, + (SCR_IsAspectCorrect(vid.width, vid.height) ? recommendedflags : highlightflags), + va("%dx%d", vid.width, vid.height)); +} + +static void M_DrawHUDOptions(void) +{ + const char *str0 = ")"; + const char *str1 = " Warning highlight"; + const char *str2 = ","; + const char *str3 = "Good highlight"; + INT32 x = BASEVIDWIDTH - currentMenu->x + 2, y = currentMenu->y + 105; + INT32 w0 = V_StringWidth(str0, 0), w1 = V_StringWidth(str1, 0), w2 = V_StringWidth(str2, 0), w3 = V_StringWidth(str3, 0); + + M_DrawGenericMenu(); + + x -= w0; + V_DrawString(x, y, highlightflags, str0); + x -= w1; + V_DrawString(x, y, warningflags, str1); + x -= w2; + V_DrawString(x, y, highlightflags, str2); + x -= w3; + V_DrawString(x, y, recommendedflags, str3); + V_DrawRightAlignedString(x, y, highlightflags, "("); +} + // Draw the video modes list, a-la-Quake static void M_DrawVideoMode(void) { @@ -7796,17 +8287,17 @@ static void M_DrawVideoMode(void) M_DrawMenuTitle(); V_DrawCenteredString(BASEVIDWIDTH/2, OP_VideoModeDef.y, - V_YELLOWMAP, "Choose mode, reselect to change default"); + highlightflags, "Choose mode, reselect to change default"); row = 41; col = OP_VideoModeDef.y + 14; for (i = 0; i < vidm_nummodes; i++) { if (i == vidm_selected) - V_DrawString(row, col, V_YELLOWMAP, modedescs[i].desc); + V_DrawString(row, col, highlightflags, modedescs[i].desc); // Show multiples of 320x200 as green. else - V_DrawString(row, col, (modedescs[i].goodratio) ? V_GREENMAP : 0, modedescs[i].desc); + V_DrawString(row, col, (modedescs[i].goodratio) ? recommendedflags : 0, modedescs[i].desc); col += 8; if ((i % vidm_column_size) == (vidm_column_size-1)) @@ -7844,11 +8335,11 @@ static void M_DrawVideoMode(void) cv_scr_width.value, cv_scr_height.value)); V_DrawCenteredString(BASEVIDWIDTH/2, OP_VideoModeDef.y + 138, - V_GREENMAP, "Green modes are recommended."); - V_DrawCenteredString(BASEVIDWIDTH/2, OP_VideoModeDef.y + 150, - V_YELLOWMAP, "Other modes may have visual errors."); + recommendedflags, "Marked modes are recommended."); + V_DrawCenteredString(BASEVIDWIDTH/2, OP_VideoModeDef.y + 146, + highlightflags, "Other modes may have visual errors."); V_DrawCenteredString(BASEVIDWIDTH/2, OP_VideoModeDef.y + 158, - V_YELLOWMAP, "Use at own risk."); + highlightflags, "Larger modes may have performance issues."); } // Draw the cursor for the VidMode menu @@ -7959,16 +8450,16 @@ static void M_HandleVideoMode(INT32 ch) cv = (consvar_t *)currentMenu->menuitems[i].itemaction; y = currentMenu->y + currentMenu->menuitems[i].alphaKey; - M_DrawSlider(currentMenu->x + 20, y, cv); + M_DrawSlider(currentMenu->x + 20, y, cv, (i == itemOn)); if (!cv->value) - V_DrawRightAlignedString(312, y, V_OLDSPACING|((i == itemOn) ? V_YELLOWMAP : 0), "None"); + V_DrawRightAlignedString(312, y, V_OLDSPACING|((i == itemOn) ? highlightflags : 0), "None"); else - V_DrawRightAlignedString(312, y, V_OLDSPACING|((i == itemOn) ? V_YELLOWMAP : 0), va("%3d%%", (cv->value*100)/sum)); + V_DrawRightAlignedString(312, y, V_OLDSPACING|((i == itemOn) ? highlightflags : 0), va("%3d%%", (cv->value*100)/sum)); } if (cheating) - V_DrawCenteredString(BASEVIDWIDTH/2, currentMenu->y, V_REDMAP, "* MODIFIED, CHEATS ENABLED *"); + V_DrawCenteredString(BASEVIDWIDTH/2, currentMenu->y, warningflags, "* MODIFIED, CHEATS ENABLED *"); }*/ // ========= @@ -8043,7 +8534,7 @@ static void M_OGL_DrawFogMenu(void) my = currentMenu->y; M_DrawGenericMenu(); // use generic drawer for cursor, items and title V_DrawString(BASEVIDWIDTH - mx - V_StringWidth(cv_grfogcolor.string, 0), - my + currentMenu->menuitems[FOG_COLOR_ITEM].alphaKey, V_YELLOWMAP, cv_grfogcolor.string); + my + currentMenu->menuitems[FOG_COLOR_ITEM].alphaKey, highlightflags, cv_grfogcolor.string); // blink cursor on FOG_COLOR_ITEM if selected if (itemOn == FOG_COLOR_ITEM && skullAnimCounter < 4) V_DrawCharacter(BASEVIDWIDTH - mx, @@ -8061,7 +8552,7 @@ static void M_OGL_DrawColorMenu(void) my = currentMenu->y; M_DrawGenericMenu(); // use generic drawer for cursor, items and title V_DrawString(mx, my + currentMenu->menuitems[0].alphaKey - 10, - V_YELLOWMAP, "Gamma correction"); + highlightflags, "Gamma correction"); } //=================== diff --git a/src/m_menu.h b/src/m_menu.h index 4d6e2fac..51559489 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -267,7 +267,7 @@ void Screenshot_option_Onchange(void); prev,\ source,\ M_DrawServerMenu,\ - 27,40,\ + 24,40,\ 0,\ NULL\ } @@ -279,7 +279,7 @@ void Screenshot_option_Onchange(void); prev,\ source,\ M_DrawControl,\ - 24, 40,\ + 26, 40,\ 0,\ NULL\ } diff --git a/src/p_enemy.c b/src/p_enemy.c index b8486683..6bbf00b2 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -187,9 +187,11 @@ void A_RandomStateRange(mobj_t *actor); void A_DualAction(mobj_t *actor); void A_RemoteAction(mobj_t *actor); void A_ToggleFlameJet(mobj_t *actor); -void A_ItemPop(mobj_t *actor); // SRB2kart -void A_RedShellChase(mobj_t *actor); // SRB2kart -void A_BobombExplode(mobj_t *actor); // SRB2kart +void A_ItemPop(mobj_t *actor); // SRB2kart +void A_JawzChase(mobj_t *actor); // SRB2kart +void A_JawzExplode(mobj_t *actor); // SRB2kart +void A_MineExplode(mobj_t *actor); // SRB2kart +void A_BallhogExplode(mobj_t *actor); // SRB2kart void A_OrbitNights(mobj_t *actor); void A_GhostMe(mobj_t *actor); void A_SetObjectState(mobj_t *actor); @@ -849,7 +851,7 @@ void A_Look(mobj_t *actor) if (!P_LookForPlayers(actor, locvar1 & 65535, false , FixedMul((locvar1 >> 16)*FRACUNIT, actor->scale))) return; - if (leveltime < 4*TICRATE) // SRB2kart - no looking before race starts + if (leveltime < starttime) // SRB2kart - no looking before race starts return; // go into chase state @@ -2549,7 +2551,7 @@ void A_MonitorPop(mobj_t *actor) mobj_t *remains; mobjtype_t explode; mobjtype_t item = 0; - mobjtype_t newbox; + //mobjtype_t newbox; #ifdef HAVE_BLUA if (LUA_CallAction("A_MonitorPop", actor)) @@ -2601,7 +2603,7 @@ void A_MonitorPop(mobj_t *actor) switch (actor->type) { - case MT_QUESTIONBOX: // Random! + /*case MT_QUESTIONBOX: // Random! { mobjtype_t spawnchance[256]; INT32 numchoices = 0, i = 0; @@ -2635,7 +2637,7 @@ for (i = cvar.value; i; --i) spawnchance[numchoices++] = type remains->flags2 &= ~MF2_AMBUSH; break; - } + }*/ default: item = actor->info->damage; break; @@ -3238,8 +3240,10 @@ void A_WaterShield(mobj_t *actor) P_SpawnShieldOrb(player); } + /* // SRB2kart - Can't drown. if (player->powers[pw_underwater] && player->powers[pw_underwater] <= 12*TICRATE + 1) P_RestoreMusic(player); + */ player->powers[pw_underwater] = 0; @@ -3825,7 +3829,7 @@ void A_ThrownRing(mobj_t *actor) P_SetTarget(&actor->tracer, NULL); } - if (actor->tracer && (actor->tracer->health)) // SRB2kart - red shells always follow + if (actor->tracer && (actor->tracer->health)) // SRB2kart - jawz always follow //&& (actor->tracer->player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT)// Already found someone to follow. { const INT32 temp = actor->threshold; @@ -3877,7 +3881,7 @@ void A_ThrownRing(mobj_t *actor) && actor->target->player->ctfteam == player->ctfteam) continue; - if (actor->target->player->kartstuff[k_position] < player->kartstuff[k_position]) // SRB2kart - Red Shells only go after people ahead of you + if (actor->target->player->kartstuff[k_position] < player->kartstuff[k_position]) // SRB2kart - Jawz only go after people ahead of you continue; } @@ -3920,8 +3924,8 @@ static inline boolean PIT_GrenadeRing(mobj_t *thing) if (thing == grenade->target && grenade->threshold != 0) // Don't blow up at your owner. return true; - if (thing->player && (thing->player->kartstuff[k_bootimer] - || (G_BattleGametype() && thing->player && thing->player->kartstuff[k_balloon] <= 0 && thing->player->kartstuff[k_comebacktimer]))) + if (thing->player && (thing->player->kartstuff[k_hyudorotimer] + || (G_BattleGametype() && thing->player && thing->player->kartstuff[k_bumper] <= 0 && thing->player->kartstuff[k_comebacktimer]))) return true; if ((gametype == GT_CTF || gametype == GT_TEAMMATCH) @@ -3990,15 +3994,19 @@ void A_SetSolidSteam(mobj_t *actor) #endif actor->flags &= ~MF_NOCLIP; actor->flags |= MF_SOLID; - if (P_RandomChance(FRACUNIT/8)) + + if (!(actor->flags2 & MF2_AMBUSH)) // Don't be so obnoxious. { - if (actor->info->deathsound) - S_StartSound(actor, actor->info->deathsound); // Hiss! - } - else - { - if (actor->info->painsound) - S_StartSound(actor, actor->info->painsound); + if (P_RandomChance(FRACUNIT/8)) + { + if (actor->info->deathsound) + S_StartSound(actor, actor->info->deathsound); // Hiss! + } + else + { + if (actor->info->painsound) + S_StartSound(actor, actor->info->painsound); + } } P_SetObjectMomZ (actor, 1, true); @@ -4042,8 +4050,8 @@ void A_SignPlayer(mobj_t *actor) return; // Set the sign to be an appropriate background color for this player's skincolor. - actor->color = Color_Opposite[actor->target->player->skincolor*2]; - actor->frame += Color_Opposite[actor->target->player->skincolor*2+1]; + actor->color = KartColor_Opposite[actor->target->player->skincolor*2]; + actor->frame += KartColor_Opposite[actor->target->player->skincolor*2+1]; // spawn an overlay of the player's face. ov = P_SpawnMobj(actor->x, actor->y, actor->z, MT_OVERLAY); @@ -8085,7 +8093,7 @@ void A_ToggleFlameJet(mobj_t* actor) } } -//{ SRB2kart - A_ItemPop, A_RedShellChase and A_BobombExplode +//{ SRB2kart - A_ItemPop, A_JawzChase, A_JawzExplode, A_MineExplode, and A_BallhogExplode void A_ItemPop(mobj_t *actor) { mobj_t *remains; @@ -8134,7 +8142,7 @@ void A_ItemPop(mobj_t *actor) remains->flags = actor->flags; // Transfer flags remains->flags2 = actor->flags2; // Transfer flags2 remains->fuse = actor->fuse; // Transfer respawn timer - remains->threshold = 68; + remains->threshold = (actor->threshold == 69 ? 69 : 68); remains->skin = NULL; remains->spawnpoint = actor->spawnpoint; @@ -8143,25 +8151,25 @@ void A_ItemPop(mobj_t *actor) if (actor->info->deathsound) S_StartSound(remains, actor->info->deathsound); - if (!(G_BattleGametype() && actor->target->player->kartstuff[k_balloon] <= 0)) + if (!(G_BattleGametype() && actor->target->player->kartstuff[k_bumper] <= 0)) actor->target->player->kartstuff[k_itemroulette] = 1; remains->flags2 &= ~MF2_AMBUSH; - if (G_BattleGametype()) + if (G_BattleGametype() && actor->threshold != 69) numgotboxes++; P_RemoveMobj(actor); } -void A_RedShellChase(mobj_t *actor) +void A_JawzChase(mobj_t *actor) { INT32 c = 0; INT32 stop; player_t *player; #ifdef HAVE_BLUA - if (LUA_CallAction("A_RedShellChase", actor)) + if (LUA_CallAction("A_JawzChase", actor)) return; #endif @@ -8221,13 +8229,13 @@ void A_RedShellChase(mobj_t *actor) if (G_RaceGametype()) // Only in races, in match and CTF you should go after any nearby players { // USER TARGET - if (actor->target->player->kartstuff[k_position] != (player->kartstuff[k_position] + 1)) // Red Shells only go after the person directly ahead of you -Sryder + if (actor->target->player->kartstuff[k_position] != (player->kartstuff[k_position] + 1)) // Jawz only go after the person directly ahead of you -Sryder continue; } if (G_BattleGametype()) { - if (player->kartstuff[k_balloon] <= 0) + if (player->kartstuff[k_bumper] <= 0) continue; if (P_AproxDistance(P_AproxDistance(player->mo->x-actor->x, @@ -8239,7 +8247,7 @@ void A_RedShellChase(mobj_t *actor) if ((G_RaceGametype()) || (G_BattleGametype() // If in match etc. only home in when you get close enough, in race etc. home in all the time && P_AproxDistance(P_AproxDistance(player->mo->x-actor->x, player->mo->y-actor->y), player->mo->z-actor->z) < RING_DIST - && player->kartstuff[k_balloon] > 0)) + && player->kartstuff[k_bumper] > 0)) P_SetTarget(&actor->tracer, player->mo); return; @@ -8258,7 +8266,45 @@ void A_RedShellChase(mobj_t *actor) } -void A_BobombExplode(mobj_t *actor) +void A_JawzExplode(mobj_t *actor) +{ + INT32 shrapnel = 2; + mobj_t *truc; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_JawzExplode", actor)) + return; +#endif + + truc = P_SpawnMobj(actor->x, actor->y, actor->z, MT_BOOMEXPLODE); + truc->scale = actor->scale*2; + truc->color = SKINCOLOR_RED; + + while (shrapnel) + { + INT32 speed, speed2; + + truc = P_SpawnMobj(actor->x + P_RandomRange(-8, 8)*FRACUNIT, actor->y + P_RandomRange(-8, 8)*FRACUNIT, + actor->z + P_RandomRange(0, 8)*FRACUNIT, MT_BOOMPARTICLE); + truc->scale = actor->scale*2; + + speed = FixedMul(7*FRACUNIT, actor->scale)>>FRACBITS; + truc->momx = P_RandomRange(-speed, speed)*FRACUNIT; + truc->momy = P_RandomRange(-speed, speed)*FRACUNIT; + + speed = FixedMul(5*FRACUNIT, actor->scale)>>FRACBITS; + speed2 = FixedMul(15*FRACUNIT, actor->scale)>>FRACBITS; + truc->momz = P_RandomRange(speed, speed2)*FRACUNIT; + truc->tics = TICRATE*2; + truc->color = SKINCOLOR_RED; + + shrapnel--; + } + + return; +} + +void A_MineExplode(mobj_t *actor) { mobj_t *mo2; thinker_t *th; @@ -8266,7 +8312,7 @@ void A_BobombExplode(mobj_t *actor) INT32 locvar1 = var1; mobjtype_t type; #ifdef HAVE_BLUA - if (LUA_CallAction("A_BobombExplode", actor)) + if (LUA_CallAction("A_MineExplode", actor)) return; #endif @@ -8282,10 +8328,10 @@ void A_BobombExplode(mobj_t *actor) mo2 = (mobj_t *)th; - if (mo2 == actor || mo2->type == MT_BOMBEXPLOSIONSOUND) // Don't explode yourself! Endless loop! + if (mo2 == actor || mo2->type == MT_MINEEXPLOSIONSOUND) // Don't explode yourself! Endless loop! continue; - if (G_BattleGametype() && actor->target && actor->target->player && actor->target->player->kartstuff[k_balloon] <= 0 && mo2 == actor->target) + if (G_BattleGametype() && actor->target && actor->target->player && actor->target->player->kartstuff[k_bumper] <= 0 && mo2 == actor->target) continue; if (P_AproxDistance(P_AproxDistance(mo2->x - actor->x, mo2->y - actor->y), mo2->z - actor->z) > actor->info->painchance) @@ -8308,14 +8354,29 @@ void A_BobombExplode(mobj_t *actor) K_SpawnKartExplosion(actor->x, actor->y, actor->z, actor->info->painchance + 32*FRACUNIT, 32, type, d*(ANGLE_45/4), true, false, actor->target); // 32 <-> 64 if (actor->target && actor->target->player) - K_SpawnBobombExplosion(actor, actor->target->player->skincolor); + K_SpawnMineExplosion(actor, actor->target->player->skincolor); else - K_SpawnBobombExplosion(actor, SKINCOLOR_RED); + K_SpawnMineExplosion(actor, SKINCOLOR_RED); - P_SpawnMobj(actor->x, actor->y, actor->z, MT_BOMBEXPLOSIONSOUND); + P_SpawnMobj(actor->x, actor->y, actor->z, MT_MINEEXPLOSIONSOUND); return; } + +void A_BallhogExplode(mobj_t *actor) +{ + mobj_t *mo2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_BallhogExplode", actor)) + return; +#endif + + mo2 = P_SpawnMobj(actor->x, actor->y, actor->z, MT_BALLHOGBOOM); + P_SetScale(mo2, actor->scale*2); + mo2->destscale = mo2->scale; + S_StartSound(mo2, actor->info->deathsound); + return; +} //} // Function: A_OrbitNights diff --git a/src/p_floor.c b/src/p_floor.c index d143f6e9..ac8e60dc 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -237,7 +237,7 @@ result_e T_MovePlane(sector_t *sector, fixed_t speed, fixed_t dest, boolean crus { case MT_GOOP: // Egg Slimer's goop objects case MT_SPINFIRE: // Elemental Shield flame balls - case MT_MUSHROOMTRAIL: + case MT_SNEAKERTRAIL: case MT_SPIKE: // Floor Spike // Is the object hang from the ceiling? // In that case, swap the planes used. diff --git a/src/p_inter.c b/src/p_inter.c index 6099e585..f980e70d 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -150,28 +150,47 @@ void P_ResetStarposts(void) // // Returns true if the player is in a state where they can pick up items. // -boolean P_CanPickupItem(player_t *player, boolean weapon) +boolean P_CanPickupItem(player_t *player, UINT8 weapon) { - /*if (G_BattleGametype() && player->kartstuff[k_balloon] <= 0) // No balloons in Match - return false;*/ + if (player->exiting || mapreset) + return false; + + /*if (G_BattleGametype() && player->kartstuff[k_bumper] <= 0) // No bumpers in Match + return false;*/ if (weapon) { - if (player->kartstuff[k_bootaketimer] || player->kartstuff[k_boostolentimer] - || player->kartstuff[k_growshrinktimer] > 1 || player->kartstuff[k_goldshroomtimer]) // Item-specific timer going off - return false; + // Item slot already taken up + if (weapon == 2) + { + // Invulnerable + if (player->powers[pw_flashing] > 0 + || player->kartstuff[k_spinouttimer] > 0 + || player->kartstuff[k_squishedtimer] > 0 + || player->kartstuff[k_invincibilitytimer] > 0 + || player->kartstuff[k_growshrinktimer] > 0 + || player->kartstuff[k_hyudorotimer] > 0) + return false; - if (player->kartstuff[k_itemroulette] - || player->kartstuff[k_greenshell] || player->kartstuff[k_triplegreenshell] - || player->kartstuff[k_redshell] || player->kartstuff[k_tripleredshell] - || player->kartstuff[k_banana] || player->kartstuff[k_triplebanana] - || player->kartstuff[k_fakeitem] & 2 || player->kartstuff[k_magnet] - || player->kartstuff[k_bobomb] || player->kartstuff[k_blueshell] - || player->kartstuff[k_mushroom] || player->kartstuff[k_fireflower] - || player->kartstuff[k_star] || player->kartstuff[k_goldshroom] - || player->kartstuff[k_lightning] || player->kartstuff[k_megashroom] - || player->kartstuff[k_boo] || player->kartstuff[k_feather] & 1) // Item slot already taken up - return false; + // Already have fake + if (player->kartstuff[k_roulettetype] == 2 + || player->kartstuff[k_eggmanexplode]) + return false; + } + else + { + // Item-specific timer going off + if (player->kartstuff[k_stealingtimer] || player->kartstuff[k_stolentimer] + || player->kartstuff[k_growshrinktimer] != 0 || player->kartstuff[k_rocketsneakertimer] + || player->kartstuff[k_eggmanexplode]) + return false; + + // Item slot already taken up + if (player->kartstuff[k_itemroulette] + || player->kartstuff[k_itemamount] + || player->kartstuff[k_itemheld]) + return false; + } } return true; @@ -411,12 +430,12 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) switch (special->type) { case MT_RANDOMITEM: // SRB2kart - if (!P_CanPickupItem(player, true)) + if (!P_CanPickupItem(player, 1)) return; - if (G_BattleGametype() && player->kartstuff[k_balloon] <= 0) + if (G_BattleGametype() && player->kartstuff[k_bumper] <= 0) { - if (player->kartstuff[k_comebackmode] == 1 || player->kartstuff[k_comebacktimer]) + if (player->kartstuff[k_comebackmode] != 0 || player->kartstuff[k_comebacktimer]) return; if (player->kartstuff[k_comebackmode] == 0) player->kartstuff[k_comebackmode] = 1; @@ -426,6 +445,106 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) P_SetTarget(&special->target, toucher); P_KillMobj(special, toucher, toucher); break; + case MT_FAKESHIELD: // SRB2kart + case MT_FAKEITEM: + if ((special->target == toucher || special->target == toucher->target) && (special->threshold > 0)) + return; + + if (special->health <= 0 || toucher->health <= 0) + return; + + if (!P_CanPickupItem(player, 2)) + return; + + if (G_BattleGametype() && player->kartstuff[k_bumper] <= 0) + { + /*if (player->kartstuff[k_comebackmode] != 0 || player->kartstuff[k_comebacktimer]) + return; + if (player->kartstuff[k_comebackmode] == 0) + player->kartstuff[k_comebackmode] = 2;*/ + return; + } + + { + mobj_t *poof = P_SpawnMobj(special->x, special->y, special->z, MT_EXPLODE); + S_StartSound(poof, special->info->deathsound); + + K_StripItems(player); + if (player->kartstuff[k_itemroulette] <= 0) + player->kartstuff[k_itemroulette] = 1; + player->kartstuff[k_roulettetype] = 2; + if (special->target && special->target->player + && (G_RaceGametype() || special->target->player->kartstuff[k_bumper] > 0)) + player->kartstuff[k_eggmanblame] = special->target->player-players; + else + player->kartstuff[k_eggmanblame] = player-players; + + P_RemoveMobj(special); + return; + } + break; + case MT_KARMAHITBOX: + if (!special->target->player) + return; + if (player == special->target->player) + return; + if (player->kartstuff[k_bumper] <= 0) + return; + if (special->target->player->exiting || player->exiting) + return; + + if (special->target->player->kartstuff[k_comebacktimer] + || special->target->player->kartstuff[k_spinouttimer] + || special->target->player->kartstuff[k_squishedtimer]) + return; + + if (special->target->player->kartstuff[k_comebackmode] == 0) + { + if (player->kartstuff[k_growshrinktimer] || player->kartstuff[k_squishedtimer] + || player->kartstuff[k_hyudorotimer] || player->kartstuff[k_spinouttimer] + || player->kartstuff[k_invincibilitytimer] || player->powers[pw_flashing]) + return; + else + { + mobj_t *boom = P_SpawnMobj(special->target->x, special->target->y, special->target->z, MT_BOOMEXPLODE); + boom->scale = special->target->scale; + boom->destscale = special->target->scale; + boom->momz = 5*FRACUNIT; + if (special->target->color) + boom->color = special->target->color; + else + boom->color = SKINCOLOR_RED; + S_StartSound(boom, special->info->attacksound); + + special->target->player->kartstuff[k_comebackpoints] += 2 * (K_IsPlayerWanted(player) ? 2 : 1); + if (netgame && cv_hazardlog.value) + CONS_Printf(M_GetText("%s bombed %s!\n"), player_names[special->target->player-players], player_names[player-players]); + if (special->target->player->kartstuff[k_comebackpoints] >= 3) + K_StealBumper(special->target->player, player, true); + special->target->player->kartstuff[k_comebacktimer] = comebacktime; + + K_ExplodePlayer(player, special->target); + } + } + else if (special->target->player->kartstuff[k_comebackmode] == 1 && P_CanPickupItem(player, 1)) + { + mobj_t *poof = P_SpawnMobj(tmthing->x, tmthing->y, tmthing->z, MT_EXPLODE); + S_StartSound(poof, special->info->seesound); + + special->target->player->kartstuff[k_comebackmode] = 0; + special->target->player->kartstuff[k_comebackpoints]++; + + if (netgame && cv_hazardlog.value) + CONS_Printf(M_GetText("%s gave an item to %s.\n"), player_names[special->target->player-players], player_names[player-players]); + if (special->target->player->kartstuff[k_comebackpoints] >= 3) + K_StealBumper(special->target->player, player, true); + special->target->player->kartstuff[k_comebacktimer] = comebacktime; + + player->kartstuff[k_itemroulette] = 1; + player->kartstuff[k_roulettetype] = 1; + } + return; + // ***************************************** // // Rings, coins, spheres, weapon panels, etc // // ***************************************** // @@ -439,7 +558,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) /* FALLTHRU */ case MT_RING: case MT_FLINGRING: - if (!(P_CanPickupItem(player, false))) + if (!(P_CanPickupItem(player, 0))) return; special->momx = special->momy = special->momz = 0; @@ -451,7 +570,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) case MT_COIN: case MT_FLINGCOIN: - if (!(P_CanPickupItem(player, false))) + if (!(P_CanPickupItem(player, 0))) return; special->momx = special->momy = 0; @@ -461,7 +580,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) P_DoNightsScore(player); break; case MT_BLUEBALL: - if (!(P_CanPickupItem(player, false))) + if (!(P_CanPickupItem(player, 0))) return; P_GivePlayerRings(player, 1); @@ -482,7 +601,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) case MT_GRENADEPICKUP: case MT_EXPLODEPICKUP: case MT_RAILPICKUP: - if (!(P_CanPickupItem(player, true))) + if (!(P_CanPickupItem(player, 1))) return; // Give the power and ringweapon @@ -506,7 +625,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) case MT_GRENADERING: case MT_EXPLOSIONRING: case MT_RAILRING: - if (!(P_CanPickupItem(player, true))) + if (!(P_CanPickupItem(player, 1))) return; if (special->info->mass >= pw_infinityring && special->info->mass <= pw_railring) @@ -594,7 +713,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) // Power stones / Match emeralds case MT_FLINGEMERALD: - if (!(P_CanPickupItem(player, true)) || player->tossdelay) + if (!(P_CanPickupItem(player, 1)) || player->tossdelay) return; player->powers[pw_emeralds] |= special->threshold; @@ -1490,12 +1609,14 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) || special->z > toucher->z + (toucher->height*2/3)) return; // Only go in the mouth + /* // SRB2kart - Can't drown. // Eaten by player! if (player->powers[pw_underwater] && player->powers[pw_underwater] <= 12*TICRATE + 1) P_RestoreMusic(player); if (player->powers[pw_underwater] < underwatertics + 1) player->powers[pw_underwater] = underwatertics + 1; + */ /* if (!player->climbing) @@ -1612,7 +1733,7 @@ static void P_HitDeathMessages(player_t *player, mobj_t *inflictor, mobj_t *sour str = M_GetText("%s%s's tagging hand %s %s.\n"); break; case MT_SPINFIRE: - case MT_MUSHROOMTRAIL: + case MT_SNEAKERTRAIL: str = M_GetText("%s%s's elemental fire trail %s %s.\n"); break; case MT_THROWNBOUNCE: @@ -1749,7 +1870,7 @@ void P_CheckTimeLimit(void) if (G_RaceGametype()) return; - if (leveltime < timelimitintics) + if (leveltime < (timelimitintics + starttime)) return; if (gameaction == ga_completed) @@ -1771,9 +1892,6 @@ void P_CheckTimeLimit(void) P_AddPlayerScore(&players[i], players[i].score); } } - - if (server) - SendNetXCmd(XD_EXITLEVEL, NULL, 0); } //Optional tie-breaker for Match/CTF @@ -1787,6 +1905,8 @@ void P_CheckTimeLimit(void) //Figure out if we have enough participating players to care. for (i = 0; i < MAXPLAYERS; i++) { + if (players[i].exiting) + return; if (playeringame[i] && players[i].spectator) spectators++; } @@ -1815,7 +1935,7 @@ void P_CheckTimeLimit(void) { for (k = i; k < playercount; k++) { - if (players[playerarray[i-1]].score < players[playerarray[k]].score) + if (players[playerarray[i-1]].marescore < players[playerarray[k]].marescore) { tempplayer = playerarray[i-1]; playerarray[i-1] = playerarray[k]; @@ -1825,7 +1945,7 @@ void P_CheckTimeLimit(void) } //End the round if the top players aren't tied. - if (players[playerarray[0]].score == players[playerarray[1]].score) + if (players[playerarray[0]].marescore == players[playerarray[1]].marescore) return; } else @@ -1835,12 +1955,19 @@ void P_CheckTimeLimit(void) return; } } - if (server) - SendNetXCmd(XD_EXITLEVEL, NULL, 0); } - if (server) - SendNetXCmd(XD_EXITLEVEL, NULL, 0); + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i] || players[i].spectator) + continue; + if (players[i].exiting) + return; + P_DoPlayerExit(&players[i]); + } + + /*if (server) + SendNetXCmd(XD_EXITLEVEL, NULL, 0);*/ } /** Checks if a player's score is over the pointlimit and the round should end. @@ -1863,7 +1990,7 @@ void P_CheckPointLimit(void) return; // pointlimit is nonzero, check if it's been reached by this player - if (G_GametypeHasTeams()) + /*if (G_GametypeHasTeams()) { // Just check both teams if ((UINT32)cv_pointlimit.value <= redscore || (UINT32)cv_pointlimit.value <= bluescore) @@ -1872,18 +1999,27 @@ void P_CheckPointLimit(void) SendNetXCmd(XD_EXITLEVEL, NULL, 0); } } - else + else*/ { for (i = 0; i < MAXPLAYERS; i++) { if (!playeringame[i] || players[i].spectator) continue; - if ((UINT32)cv_pointlimit.value <= players[i].score) + if ((UINT32)cv_pointlimit.value <= players[i].marescore) { - if (server) - SendNetXCmd(XD_EXITLEVEL, NULL, 0); - return; + for (i = 0; i < MAXPLAYERS; i++) // AAAAA nested loop using the same iteration variable ;; + { + if (!playeringame[i] || players[i].spectator) + continue; + if (players[i].exiting) + return; + P_DoPlayerExit(&players[i]); + } + + /*if (server) + SendNetXCmd(XD_EXITLEVEL, NULL, 0);*/ + return; // good thing we're leaving the function immediately instead of letting the loop get mangled! } } } @@ -1977,13 +2113,15 @@ void P_CheckSurvivors(void) // Checks whether or not to end a race netgame. boolean P_CheckRacers(void) { - INT32 i; + INT32 i, j, numplayersingame = 0; // Check if all the players in the race have finished. If so, end the level. for (i = 0; i < MAXPLAYERS; i++) { - if (playeringame[i] && !players[i].spectator && !players[i].exiting && players[i].lives > 0) - break; + if (!playeringame[i] || players[i].spectator || players[i].exiting || !players[i].lives) + continue; + + break; } if (i == MAXPLAYERS) // finished @@ -1992,6 +2130,35 @@ boolean P_CheckRacers(void) return true; } + if (cv_karteliminatelast.value) + { + for (j = 0; j < MAXPLAYERS; j++) + { + if (!playeringame[j] || players[j].spectator) + continue; + numplayersingame++; + } + + if (numplayersingame > 1) // if there's more than one player in-game, this is safe to do + { + // check if we just got unlucky and there was only one guy who was a problem + for (j = i+1; j < MAXPLAYERS; j++) + { + if (!playeringame[j] || players[j].spectator || players[j].exiting || !players[j].lives) + continue; + + break; + } + + if (j == MAXPLAYERS) // finish anyways, force a time over + { + P_DoTimeOver(&players[i]); + countdown = countdown2 = 0; + return true; + } + } + } + return false; } @@ -2011,43 +2178,6 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source) //if (inflictor && (inflictor->type == MT_SHELL || inflictor->type == MT_FIREBALL)) // P_SetTarget(&target->tracer, inflictor); - // SRB2kart - // I wish I knew a better way to do this - if (target->target && target->target->player && target->target->player->mo) - { - if (target->type == MT_GREENSHIELD && target->target->player->kartstuff[k_greenshell] & 1) - target->target->player->kartstuff[k_greenshell] &= ~1; - else if (target->type == MT_REDSHIELD && target->target->player->kartstuff[k_redshell] & 1) - target->target->player->kartstuff[k_redshell] &= ~1; - else if (target->type == MT_BANANASHIELD && target->target->player->kartstuff[k_banana] & 1) - target->target->player->kartstuff[k_banana] &= ~1; - else if (target->type == MT_FAKESHIELD && target->target->player->kartstuff[k_fakeitem] & 1) - target->target->player->kartstuff[k_fakeitem] &= ~1; - else if (target->type == MT_BOMBSHIELD && target->target->player->kartstuff[k_bobomb] & 1) - target->target->player->kartstuff[k_bobomb] &= ~1; - else if (target->type == MT_TRIPLEGREENSHIELD1 && target->target->player->kartstuff[k_triplegreenshell] & 1) - target->target->player->kartstuff[k_triplegreenshell] &= ~1; - else if (target->type == MT_TRIPLEGREENSHIELD2 && target->target->player->kartstuff[k_triplegreenshell] & 2) - target->target->player->kartstuff[k_triplegreenshell] &= ~2; - else if (target->type == MT_TRIPLEGREENSHIELD3 && target->target->player->kartstuff[k_triplegreenshell] & 4) - target->target->player->kartstuff[k_triplegreenshell] &= ~4; - else if (target->type == MT_TRIPLEREDSHIELD1 && target->target->player->kartstuff[k_tripleredshell] & 1) - target->target->player->kartstuff[k_tripleredshell] &= ~1; - else if (target->type == MT_TRIPLEREDSHIELD2 && target->target->player->kartstuff[k_tripleredshell] & 2) - target->target->player->kartstuff[k_tripleredshell] &= ~2; - else if (target->type == MT_TRIPLEREDSHIELD3 && target->target->player->kartstuff[k_tripleredshell] & 4) - target->target->player->kartstuff[k_tripleredshell] &= ~4; - else if (target->type == MT_TRIPLEBANANASHIELD1 && target->target->player->kartstuff[k_triplebanana] & 1) - target->target->player->kartstuff[k_triplebanana] &= ~1; - else if (target->type == MT_TRIPLEBANANASHIELD2 && target->target->player->kartstuff[k_triplebanana] & 2) - target->target->player->kartstuff[k_triplebanana] &= ~2; - else if (target->type == MT_TRIPLEBANANASHIELD3 && target->target->player->kartstuff[k_triplebanana] & 4) - target->target->player->kartstuff[k_triplebanana] &= ~4; - /*else if (target->type == MT_BATTLEBALLOON && target->target->player->kartstuff[k_balloon] > target->threshold-1) - target->target->player->kartstuff[k_balloon] = target->threshold-1;*/ - } - // - if (!useNightsSS && G_IsSpecialStage(gamemap) && target->player && sstimer > 6) sstimer = 6; // Just let P_Ticker take care of the rest. @@ -2056,14 +2186,11 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source) // SRB2kart if (target->type != MT_PLAYER && !(target->flags & MF_MONITOR) - && !(target->type == MT_GREENITEM || target->type == MT_GREENSHIELD - || target->type == MT_TRIPLEGREENSHIELD1 || target->type == MT_TRIPLEGREENSHIELD2 || target->type == MT_TRIPLEGREENSHIELD3 - || target->type == MT_REDITEM || target->type == MT_REDITEMDUD || target->type == MT_REDSHIELD - || target->type == MT_TRIPLEREDSHIELD1 || target->type == MT_TRIPLEREDSHIELD2 || target->type == MT_TRIPLEREDSHIELD3 - || target->type == MT_BANANAITEM || target->type == MT_BANANASHIELD - || target->type == MT_TRIPLEBANANASHIELD1 || target->type == MT_TRIPLEBANANASHIELD2 || target->type == MT_TRIPLEBANANASHIELD3 + && !(target->type == MT_ORBINAUT || target->type == MT_ORBINAUT_SHIELD + || target->type == MT_JAWZ || target->type == MT_JAWZ_DUD || target->type == MT_JAWZ_SHIELD + || target->type == MT_BANANA || target->type == MT_BANANA_SHIELD || target->type == MT_FAKEITEM || target->type == MT_FAKESHIELD - || target->type == MT_FIREBALL)) // kart dead items + || target->type == MT_BALLHOG)) // kart dead items target->flags |= MF_NOGRAVITY; // Don't drop Tails 03-08-2000 else target->flags &= ~MF_NOGRAVITY; // lose it if you for whatever reason have it, I'm looking at you shields @@ -2082,6 +2209,49 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source) return; #endif + // SRB2kart + // I wish I knew a better way to do this + if (target->target && target->target->player && target->target->player->mo) + { + if (target->target->player->kartstuff[k_eggmanheld] && target->type == MT_FAKESHIELD) + target->target->player->kartstuff[k_eggmanheld] = 0; + + if (target->target->player->kartstuff[k_itemheld]) + { + if ((target->type == MT_BANANA_SHIELD && target->target->player->kartstuff[k_itemtype] == KITEM_BANANA) // trail items + || (target->type == MT_SSMINE_SHIELD && target->target->player->kartstuff[k_itemtype] == KITEM_MINE)) + { + if (target->movedir != 0 && target->movedir < (UINT16)target->target->player->kartstuff[k_itemamount]) + { + if (target->target->hnext) + K_KillBananaChain(target->target->hnext, inflictor, source); + target->target->player->kartstuff[k_itemamount] = 0; + } + else + target->target->player->kartstuff[k_itemamount]--; + } + else if ((target->type == MT_ORBINAUT_SHIELD && target->target->player->kartstuff[k_itemtype] == KITEM_ORBINAUT) // orbit items + || (target->type == MT_JAWZ_SHIELD && target->target->player->kartstuff[k_itemtype] == KITEM_JAWZ)) + { + target->target->player->kartstuff[k_itemamount]--; + if (target->lastlook != 0) + { + K_RepairOrbitChain(target); + } + } + + if (target->target->player->kartstuff[k_itemamount] < 0) + target->target->player->kartstuff[k_itemamount] = 0; + + if (!target->target->player->kartstuff[k_itemamount]) + target->target->player->kartstuff[k_itemheld] = 0; + + if (target->target->hnext == target) + P_SetTarget(&target->target->hnext, NULL); + } + } + // + // Let EVERYONE know what happened to a player! 01-29-2002 Tails if (target->player && !target->player->spectator) { @@ -2197,7 +2367,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source) { target->flags &= ~(MF_SOLID|MF_SHOOTABLE); // does not block P_UnsetThingPosition(target); - target->flags |= MF_NOBLOCKMAP; + target->flags |= MF_NOBLOCKMAP|MF_NOCLIPHEIGHT; P_SetThingPosition(target); if (!target->player->bot && !G_IsSpecialStage(gamemap) @@ -2272,9 +2442,9 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source) } } else if (G_BattleGametype()) - { - K_CheckBalloons(); - } + K_CheckBumpers(); + + target->player->kartstuff[k_pogospring] = 0; } if (source && target && target->player && source->player) @@ -2586,7 +2756,7 @@ static inline void P_NiGHTSDamage(mobj_t *target, mobj_t *source) target->momy = FixedMul(FINESINE(fa),target->target->radius); } - player->powers[pw_flashing] = K_GetKartFlashing(); + player->powers[pw_flashing] = K_GetKartFlashing(player); P_SetMobjState(target->tracer, S_NIGHTSHURT1); S_StartSound(target, sfx_nghurt); @@ -2773,14 +2943,22 @@ static void P_KillPlayer(player_t *player, mobj_t *source, INT32 damage) if (G_BattleGametype()) { - if (player->kartstuff[k_balloon] > 0) + if (player->kartstuff[k_bumper] > 0) { - if (player->kartstuff[k_balloon] == 1) - CONS_Printf(M_GetText("%s lost all of their balloons!\n"), player_names[player-players]); - player->kartstuff[k_balloon]--; + if (player->kartstuff[k_bumper] == 1) + { + mobj_t *karmahitbox = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_KARMAHITBOX); // Player hitbox is too small!! + P_SetTarget(&karmahitbox->target, player->mo); + karmahitbox->destscale = player->mo->scale; + P_SetScale(karmahitbox, player->mo->scale); + CONS_Printf(M_GetText("%s lost all of their bumpers!\n"), player_names[player-players]); + } + player->kartstuff[k_bumper]--; + if (K_IsPlayerWanted(player)) + K_CalculateBattleWanted(); } - K_CheckBalloons(); + K_CheckBumpers(); } } @@ -2907,6 +3085,8 @@ static void P_ShieldDamage(player_t *player, mobj_t *inflictor, mobj_t *source, static void P_RingDamage(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 damage) { + //const UINT8 scoremultiply = ((K_IsWantedPlayer(player) && !trapitem) : 2 ? 1); + if (!(inflictor && ((inflictor->flags & MF_MISSILE) || inflictor->player) && player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds]))) { P_DoPlayerPain(player, source, inflictor); @@ -2917,11 +3097,11 @@ static void P_RingDamage(player_t *player, mobj_t *inflictor, mobj_t *source, IN S_StartSound(player->mo, sfx_spkdth); } - if (source && source->player && !player->powers[pw_super]) //don't score points against super players + /*if (source && source->player && !player->powers[pw_super]) //don't score points against super players { // Award no points when players shoot each other when cv_friendlyfire is on. if (!G_GametypeHasTeams() || !(source->player->ctfteam == player->ctfteam && source != player->mo)) - P_AddPlayerScore(source->player, 1); + P_AddPlayerScore(source->player, scoremultiply); } if (gametype == GT_CTF && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG))) @@ -2931,9 +3111,9 @@ static void P_RingDamage(player_t *player, mobj_t *inflictor, mobj_t *source, IN { // Award no points when players shoot each other when cv_friendlyfire is on. if (!G_GametypeHasTeams() || !(source->player->ctfteam == player->ctfteam && source != player->mo)) - P_AddPlayerScore(source->player, 1); + P_AddPlayerScore(source->player, scoremultiply); } - } + }*/ // Ring loss sound plays despite hitting spikes P_PlayRinglossSound(player->mo); // Ringledingle! @@ -2964,7 +3144,6 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da #else static const boolean force = false; #endif - mobj_t *blueexplode; if (objectplacing) return false; @@ -3124,42 +3303,57 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da //{ SRB2kart - special damage sources - player->kartstuff[k_mushroomtimer] = 0; - - // Thunder + // Shrink if (damage == 64) { if (player == source->player) return false; // Don't flip out while super! - if (!player->kartstuff[k_startimer] && player->kartstuff[k_growshrinktimer] <= 0) + if (!player->kartstuff[k_invincibilitytimer] && player->kartstuff[k_growshrinktimer] <= 0) { - // Start slipping! - K_SpinPlayer(player, source); - // Start shrinking! + player->mo->scalespeed = FRACUNIT/TICRATE; player->mo->destscale = 6*(mapheaderinfo[gamemap-1]->mobj_scale)/8; - player->kartstuff[k_growshrinktimer] -= (100+20*(16-(player->kartstuff[k_position]))); + if (cv_kartdebugshrink.value && !player->bot) + player->mo->destscale = 6*player->mo->destscale/8; + + // Wipeout + K_SpinPlayer(player, source, 1, false); + damage = player->mo->health - 1; + P_RingDamage(player, inflictor, source, damage); + P_PlayerRingBurst(player, 5); + player->mo->momx = player->mo->momy = 0; + if (P_IsLocalPlayer(player)) + { + quake.intensity = 32*FRACUNIT; + quake.time = 5; + } + + K_StripItems(player); + player->kartstuff[k_growshrinktimer] -= (200+(40*(16-player->kartstuff[k_position]))); } - // Mega Mushroom? Let's take that away. + // Grow? Let's take that away. if (player->kartstuff[k_growshrinktimer] > 0) { player->kartstuff[k_growshrinktimer] = 2; } + player->kartstuff[k_sneakertimer] = 0; // Invincible or not, we still need this. - P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_LIGHTNING); + //P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_LIGHTNING); + S_StartSound(player->mo, sfx_kc59); return true; } - // Blue Thunder + // Self-Propelled Bomb if (damage == 65) { + mobj_t *spbexplode; if (player == source->player) return false; // Just need to do this now! Being thrown upwards is done by the explosion. - P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_BLUELIGHTNING); - blueexplode = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_BLUEEXPLOSION); - P_SetTarget(&blueexplode->target, source); + //P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_BLUELIGHTNING); + spbexplode = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_BLUEEXPLOSION); + P_SetTarget(&spbexplode->target, source); return true; } //} @@ -3185,23 +3379,22 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da // Instant-Death if (damage == 10000) P_KillPlayer(player, source, damage); - else if (player->kartstuff[k_startimer] > 0 || player->kartstuff[k_growshrinktimer] > 0 || player->powers[pw_flashing]) + else if (player->kartstuff[k_invincibilitytimer] > 0 || player->kartstuff[k_growshrinktimer] > 0 || player->powers[pw_flashing]) + { + K_DoInstashield(player); return false; + } else { - if (inflictor && (inflictor->type == MT_GREENITEM || inflictor->type == MT_GREENSHIELD - || inflictor->type == MT_REDITEM || inflictor->type == MT_REDSHIELD || inflictor->type == MT_REDITEMDUD - || inflictor->type == MT_FAKEITEM || inflictor->type == MT_FAKESHIELD - || inflictor->type == MT_TRIPLEGREENSHIELD1 || inflictor->type == MT_TRIPLEGREENSHIELD2 || inflictor->type == MT_TRIPLEGREENSHIELD3 - || inflictor->type == MT_TRIPLEREDSHIELD1 || inflictor->type == MT_TRIPLEREDSHIELD2 || inflictor->type == MT_TRIPLEREDSHIELD3 + if (inflictor && (inflictor->type == MT_ORBINAUT || inflictor->type == MT_ORBINAUT_SHIELD + || inflictor->type == MT_JAWZ || inflictor->type == MT_JAWZ_SHIELD || inflictor->type == MT_JAWZ_DUD || inflictor->player)) { - player->kartstuff[k_spinouttype] = 1; - K_SpinPlayer(player, source); + player->kartstuff[k_sneakertimer] = 0; + K_SpinPlayer(player, source, 1, false); damage = player->mo->health - 1; P_RingDamage(player, inflictor, source, damage); P_PlayerRingBurst(player, 5); - player->mo->momx = player->mo->momy = 0; if (P_IsLocalPlayer(player)) { quake.intensity = 32*FRACUNIT; @@ -3210,8 +3403,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da } else { - player->kartstuff[k_spinouttype] = -1; - K_SpinPlayer(player, source); + K_SpinPlayer(player, source, 0, false); } return true; } @@ -3304,7 +3496,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da player->health -= damage; // mirror mobj health here if (damage < 10000) { - target->player->powers[pw_flashing] = K_GetKartFlashing(); + target->player->powers[pw_flashing] = K_GetKartFlashing(target->player); if (damage > 0) // don't spill emeralds/ammo/panels for shield damage P_PlayerRingBurst(player, damage); } @@ -3362,22 +3554,25 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da break; } - target->reactiontime = 0; // we're awake now... - - if (source && source != target) + if (!P_MobjWasRemoved(target)) { - // if not intent on another player, - // chase after this one - P_SetTarget(&target->target, source); - if (target->state == &states[target->info->spawnstate] && target->info->seestate != S_NULL) + target->reactiontime = 0; // we're awake now... + + if (source && source != target) { - if (player) + // if not intent on another player, + // chase after this one + P_SetTarget(&target->target, source); + if (target->state == &states[target->info->spawnstate] && target->info->seestate != S_NULL) { - if (!(player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds]))) - P_SetPlayerMobjState(target, target->info->seestate); + if (player) + { + if (!(player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds]))) + P_SetPlayerMobjState(target, target->info->seestate); + } + else + P_SetMobjState(target, target->info->seestate); } - else - P_SetMobjState(target, target->info->seestate); } } diff --git a/src/p_local.h b/src/p_local.h index 8a4bfa7b..7d7342bc 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -25,7 +25,7 @@ #define FLOATSPEED (FRACUNIT*4) -#define VIEWHEIGHTS "41" +//#define VIEWHEIGHTS "41" // Maximum player score. #define MAXSCORE 999999990 @@ -150,6 +150,7 @@ boolean P_InQuicksand(mobj_t *mo); void P_SetObjectMomZ(mobj_t *mo, fixed_t value, boolean relative); void P_RestoreMusic(player_t *player); +boolean P_EndingMusic(player_t *player); void P_SpawnShieldOrb(player_t *player); mobj_t *P_SpawnGhostMobj(mobj_t *mobj); void P_GivePlayerRings(player_t *player, INT32 num_rings); @@ -167,6 +168,7 @@ void P_ElementalFireTrail(player_t *player); void P_PlayerThink(player_t *player); void P_PlayerAfterThink(player_t *player); void P_DoPlayerExit(player_t *player); +void P_DoTimeOver(player_t *player); void P_NightserizePlayer(player_t *player, INT32 ptime); void P_InstaThrust(mobj_t *mo, angle_t angle, fixed_t move); @@ -177,12 +179,13 @@ void P_InstaThrustEvenIn2D(mobj_t *mo, angle_t angle, fixed_t move); boolean P_LookForEnemies(player_t *player); void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius); void P_HomingAttack(mobj_t *source, mobj_t *enemy); /// \todo doesn't belong in p_user -boolean P_SuperReady(player_t *player); +//boolean P_SuperReady(player_t *player); void P_DoJump(player_t *player, boolean soundandstate); boolean P_AnalogMove(player_t *player); boolean P_TransferToNextMare(player_t *player); UINT8 P_FindLowestMare(void); UINT8 P_FindLowestLap(void); +UINT8 P_FindHighestLap(void); void P_FindEmerald(void); void P_TransferToAxis(player_t *player, INT32 axisnum); boolean P_PlayerMoving(INT32 pnum); @@ -191,9 +194,9 @@ void P_SpawnSpinMobj(player_t *player, mobjtype_t type); void P_Telekinesis(player_t *player, fixed_t thrust, fixed_t range); void P_PlayLivesJingle(player_t *player); -#define P_PlayRinglossSound(s) S_StartSound(s, (mariomode) ? sfx_mario8 : sfx_altow1 + P_RandomKey(4)); -#define P_PlayDeathSound(s) S_StartSound(s, sfx_altdi1 + P_RandomKey(4)); -#define P_PlayVictorySound(s) S_StartSound(s, sfx_victr1 + P_RandomKey(4)); +void P_PlayRinglossSound(mobj_t *source); +void P_PlayDeathSound(mobj_t *source); +void P_PlayVictorySound(mobj_t *source); // @@ -209,7 +212,7 @@ void P_PlayLivesJingle(player_t *player); extern mapthing_t *itemrespawnque[ITEMQUESIZE]; extern tic_t itemrespawntime[ITEMQUESIZE]; extern size_t iquehead, iquetail; -extern consvar_t cv_gravity, cv_viewheight; +extern consvar_t cv_gravity/*, cv_viewheight*/; void P_RespawnSpecials(void); @@ -338,6 +341,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff); boolean P_Move(mobj_t *actor, fixed_t speed); boolean P_TeleportMove(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z); void P_SlideMove(mobj_t *mo, boolean forceslide); +void P_BouncePlayerMove(mobj_t *mo); void P_BounceMove(mobj_t *mo); boolean P_CheckSight(mobj_t *t1, mobj_t *t2); void P_CheckHoopPosition(mobj_t *hoopthing, fixed_t x, fixed_t y, fixed_t z, fixed_t radius); @@ -405,7 +409,7 @@ boolean P_CheckRacers(void); void P_ClearStarPost(INT32 postnum); void P_ResetStarposts(void); -boolean P_CanPickupItem(player_t *player, boolean weapon); +boolean P_CanPickupItem(player_t *player, UINT8 weapon); void P_DoNightsScore(player_t *player); // diff --git a/src/p_map.c b/src/p_map.c index ece49f26..5c3e7177 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -116,6 +116,8 @@ boolean P_TeleportMove(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z) boolean P_DoSpring(mobj_t *spring, mobj_t *object) { //INT32 pflags; + const fixed_t hscale = mapheaderinfo[gamemap-1]->mobj_scale + (mapheaderinfo[gamemap-1]->mobj_scale - object->scale); + const fixed_t vscale = mapheaderinfo[gamemap-1]->mobj_scale + (object->scale - mapheaderinfo[gamemap-1]->mobj_scale); fixed_t offx, offy; fixed_t vertispeed = spring->info->mass; fixed_t horizspeed = spring->info->damage; @@ -178,12 +180,12 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) } if (vertispeed) - object->momz = FixedMul(vertispeed,FixedSqrt(FixedMul(object->scale, spring->scale))); + object->momz = FixedMul(vertispeed,FixedSqrt(FixedMul(vscale, spring->scale))); if (horizspeed) { if (!object->player) - P_InstaThrustEvenIn2D(object, spring->angle, FixedMul(horizspeed,FixedSqrt(FixedMul(object->scale, spring->scale)))); + P_InstaThrustEvenIn2D(object, spring->angle, FixedMul(horizspeed,FixedSqrt(FixedMul(hscale, spring->scale)))); else { fixed_t finalSpeed = horizspeed; @@ -192,7 +194,7 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) if (pSpeed > finalSpeed) finalSpeed = pSpeed; - P_InstaThrustEvenIn2D(object, spring->angle, FixedMul(finalSpeed,FixedSqrt(FixedMul(object->scale, spring->scale)))); + P_InstaThrustEvenIn2D(object, spring->angle, FixedMul(finalSpeed,FixedSqrt(FixedMul(hscale, spring->scale)))); } } @@ -308,7 +310,17 @@ static void P_DoFanAndGasJet(mobj_t *spring, mobj_t *object) if (spring->state != &states[S_STEAM1]) // Only when it bursts break; - object->momz = flipval*FixedMul(speed, FixedSqrt(FixedMul(spring->scale, object->scale))); // scale the speed with both objects' scales, just like with springs! + if (spring->spawnpoint && spring->spawnpoint->options & MTF_OBJECTSPECIAL) + { + if (object->eflags & MFE_SPRUNG) + break; + if (object->player) + object->player->kartstuff[k_pogospring] = 1; + K_DoPogoSpring(object, 0, true); + return; + } + else + object->momz = flipval*FixedMul(speed, FixedSqrt(FixedMul(spring->scale, object->scale))); // scale the speed with both objects' scales, just like with springs! /* // SRB2kart - don't need state change if (p) @@ -655,10 +667,8 @@ static boolean PIT_CheckThing(mobj_t *thing) if (tmthing->type == MT_RANDOMITEM) return true; - if (tmthing->type == MT_GREENITEM || tmthing->type == MT_REDITEM || tmthing->type == MT_REDITEMDUD || - tmthing->type == MT_GREENSHIELD || tmthing->type == MT_REDSHIELD || - tmthing->type == MT_TRIPLEGREENSHIELD1 || tmthing->type == MT_TRIPLEGREENSHIELD2 || tmthing->type == MT_TRIPLEGREENSHIELD3 || - tmthing->type == MT_TRIPLEREDSHIELD1 || tmthing->type == MT_TRIPLEREDSHIELD2 || tmthing->type == MT_TRIPLEREDSHIELD3) + if (tmthing->type == MT_ORBINAUT || tmthing->type == MT_JAWZ || tmthing->type == MT_JAWZ_DUD + || tmthing->type == MT_ORBINAUT_SHIELD || tmthing->type == MT_JAWZ_SHIELD) { // see if it went over / under if (tmthing->z > thing->z + thing->height) @@ -672,23 +682,22 @@ static boolean PIT_CheckThing(mobj_t *thing) if (tmthing->health <= 0 || thing->health <= 0) return true; - if (((tmthing->type == MT_TRIPLEGREENSHIELD1 || tmthing->type == MT_TRIPLEGREENSHIELD2 || tmthing->type == MT_TRIPLEGREENSHIELD3 - || tmthing->type == MT_TRIPLEREDSHIELD1 || tmthing->type == MT_TRIPLEREDSHIELD2 || tmthing->type == MT_TRIPLEREDSHIELD3) - && (thing->type == MT_TRIPLEGREENSHIELD1 || thing->type == MT_TRIPLEGREENSHIELD2 || thing->type == MT_TRIPLEGREENSHIELD3 - || thing->type == MT_TRIPLEREDSHIELD1 || thing->type == MT_TRIPLEREDSHIELD2 || thing->type == MT_TRIPLEREDSHIELD3)) + if ((tmthing->type == MT_ORBINAUT_SHIELD || tmthing->type == MT_JAWZ_SHIELD) && tmthing->lastlook + && (thing->type == MT_ORBINAUT_SHIELD || thing->type == MT_JAWZ_SHIELD) && thing->lastlook && (tmthing->target == thing->target)) // Don't hit each other if you have the same target return true; if (thing->player && thing->player->powers[pw_flashing] - && !(tmthing->type == MT_GREENITEM || tmthing->type == MT_REDITEM || tmthing->type == MT_REDITEMDUD)) + && !(tmthing->type == MT_ORBINAUT || tmthing->type == MT_JAWZ || tmthing->type == MT_JAWZ_DUD)) return true; if (thing->type == MT_PLAYER) { // Player Damage P_DamageMobj(thing, tmthing, tmthing->target, 1); + K_KartBouncing(thing, tmthing, false, false); - if (tmthing->type == MT_GREENITEM || tmthing->type == MT_REDITEM || tmthing->type == MT_REDITEMDUD) + if (tmthing->type == MT_ORBINAUT || tmthing->type == MT_JAWZ || tmthing->type == MT_JAWZ_DUD) S_StartSound(thing, sfx_shelit); // This Item Damage @@ -703,13 +712,10 @@ static boolean PIT_CheckThing(mobj_t *thing) P_SetObjectMomZ(tmthing, 8*FRACUNIT, false); P_InstaThrust(tmthing, R_PointToAngle2(thing->x, thing->y, tmthing->x, tmthing->y)+ANGLE_90, 16*FRACUNIT); } - else if (thing->type == MT_GREENITEM || thing->type == MT_REDITEM || thing->type == MT_REDITEMDUD - || thing->type == MT_GREENSHIELD || thing->type == MT_REDSHIELD - || thing->type == MT_TRIPLEGREENSHIELD1 || thing->type == MT_TRIPLEGREENSHIELD2 || thing->type == MT_TRIPLEGREENSHIELD3 - || thing->type == MT_TRIPLEREDSHIELD1 || thing->type == MT_TRIPLEREDSHIELD2 || thing->type == MT_TRIPLEREDSHIELD3 - || thing->type == MT_BANANAITEM || thing->type == MT_BANANASHIELD - || thing->type == MT_TRIPLEBANANASHIELD1 || thing->type == MT_TRIPLEBANANASHIELD2 || thing->type == MT_TRIPLEBANANASHIELD3 - || thing->type == MT_FIREBALL) + 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 + || thing->type == MT_BANANA || thing->type == MT_BANANA_SHIELD + || thing->type == MT_BALLHOG) { // Other Item Damage if (thing->eflags & MFE_VERTICALFLIP) @@ -737,40 +743,7 @@ static boolean PIT_CheckThing(mobj_t *thing) P_SetObjectMomZ(tmthing, 8*FRACUNIT, false); P_InstaThrust(tmthing, R_PointToAngle2(thing->x, thing->y, tmthing->x, tmthing->y)+ANGLE_90, 16*FRACUNIT); } - else if (thing->type == MT_FAKEITEM || thing->type == MT_FAKESHIELD) - { - if (tmthing->type == MT_GREENSHIELD || tmthing->type == MT_REDSHIELD - || tmthing->type == MT_TRIPLEGREENSHIELD1 || tmthing->type == MT_TRIPLEGREENSHIELD2 || tmthing->type == MT_TRIPLEGREENSHIELD3 - || tmthing->type == MT_TRIPLEREDSHIELD1 || tmthing->type == MT_TRIPLEREDSHIELD2 || tmthing->type == MT_TRIPLEREDSHIELD3) - { - // This Item Damage - if (tmthing->eflags & MFE_VERTICALFLIP) - tmthing->z -= tmthing->height; - else - tmthing->z += tmthing->height; - - S_StartSound(tmthing, tmthing->info->deathsound); - P_KillMobj(tmthing, thing, thing); - - P_SetObjectMomZ(tmthing, 8*FRACUNIT, false); - P_InstaThrust(tmthing, R_PointToAngle2(thing->x, thing->y, tmthing->x, tmthing->y)+ANGLE_90, 16*FRACUNIT); - - P_SpawnMobj(thing->x/2 + tmthing->x/2, thing->y/2 + tmthing->y/2, thing->z/2 + tmthing->z/2, MT_ITEMCLASH); - } - - // Other Item Damage - if (thing->eflags & MFE_VERTICALFLIP) - thing->z -= thing->height; - else - thing->z += thing->height; - - S_StartSound(thing, thing->info->deathsound); - P_KillMobj(thing, tmthing, tmthing); - - P_SetObjectMomZ(thing, 8*FRACUNIT, false); - P_InstaThrust(thing, R_PointToAngle2(tmthing->x, tmthing->y, thing->x, thing->y)+ANGLE_90, 16*FRACUNIT); - } - else if (thing->type == MT_BOMBSHIELD || thing->type == MT_BOMBITEM) + else if (thing->type == MT_SSMINE_SHIELD || thing->type == MT_SSMINE) { // This Item Damage if (tmthing->eflags & MFE_VERTICALFLIP) @@ -787,12 +760,12 @@ static boolean PIT_CheckThing(mobj_t *thing) // Bomb death P_KillMobj(thing, tmthing, tmthing); } - else if (thing->flags & MF_SPRING && (tmthing->type == MT_REDITEM || tmthing->type == MT_REDITEMDUD || tmthing->type == MT_GREENITEM)) + else if (thing->flags & MF_SPRING && (tmthing->type == MT_JAWZ || tmthing->type == MT_JAWZ_DUD || tmthing->type == MT_ORBINAUT)) P_DoSpring(thing, tmthing); return true; } - else if (tmthing->flags & MF_SPRING && (thing->type == MT_REDITEM || thing->type == MT_REDITEMDUD || thing->type == MT_GREENITEM)) + else if (tmthing->flags & MF_SPRING && (thing->type == MT_JAWZ || thing->type == MT_JAWZ_DUD || thing->type == MT_ORBINAUT)) { // see if it went over / under if (tmthing->z > thing->z + thing->height) @@ -834,7 +807,7 @@ static boolean PIT_CheckThing(mobj_t *thing) return true; } - else if (tmthing->type == MT_BOMBEXPLOSION) + else if (tmthing->type == MT_MINEEXPLOSION) { // see if it went over / under if (tmthing->z > thing->z + thing->height) @@ -850,17 +823,16 @@ static boolean PIT_CheckThing(mobj_t *thing) if (thing->type == MT_PLAYER && thing->player) { - if (tmthing->state == &states[S_BOMBEXPLOSION1]) + if (tmthing->state == &states[S_MINEEXPLOSION1]) K_ExplodePlayer(thing->player, tmthing->target); else - K_SpinPlayer(thing->player, tmthing->target); + K_SpinPlayer(thing->player, tmthing->target, 0, false); } return true; // This doesn't collide with anything, but we want it to effect the player anyway. } - else if (tmthing->type == MT_BANANASHIELD || tmthing->type == MT_BANANAITEM - || tmthing->type == MT_TRIPLEBANANASHIELD1 || tmthing->type == MT_TRIPLEBANANASHIELD2 || tmthing->type == MT_TRIPLEBANANASHIELD3 - || tmthing->type == MT_FIREBALL) + else if (tmthing->type == MT_BANANA_SHIELD || tmthing->type == MT_BANANA + || tmthing->type == MT_BALLHOG) { // see if it went over / under if (tmthing->z > thing->z + thing->height) @@ -874,13 +846,12 @@ static boolean PIT_CheckThing(mobj_t *thing) if (tmthing->health <= 0 || thing->health <= 0) return true; - if (((tmthing->type == MT_BANANASHIELD || tmthing->type == MT_TRIPLEBANANASHIELD1 || tmthing->type == MT_TRIPLEBANANASHIELD2 || tmthing->type == MT_TRIPLEBANANASHIELD3) - && (thing->type == MT_BANANASHIELD || thing->type == MT_TRIPLEBANANASHIELD1 || thing->type == MT_TRIPLEBANANASHIELD2 || thing->type == MT_TRIPLEBANANASHIELD3)) + if (((tmthing->type == MT_BANANA_SHIELD) && (thing->type == MT_BANANA_SHIELD)) && (tmthing->target == thing->target)) // Don't hit each other if you have the same target return true; - if (tmthing->type == MT_FIREBALL && thing->type == MT_FIREBALL) - return true; // Fireballs don't collide with eachother + if (tmthing->type == MT_BALLHOG && thing->type == MT_BALLHOG) + return true; // Ballhogs don't collide with eachother if (thing->player && thing->player->powers[pw_flashing]) return true; @@ -888,7 +859,7 @@ static boolean PIT_CheckThing(mobj_t *thing) if (thing->type == MT_PLAYER) { // Player Damage - K_SpinPlayer(thing->player, tmthing->target); + K_SpinPlayer(thing->player, tmthing->target, 0, (tmthing->type == MT_BANANA || tmthing->type == MT_BANANA_SHIELD)); // This Item Damage if (tmthing->eflags & MFE_VERTICALFLIP) @@ -902,12 +873,10 @@ static boolean PIT_CheckThing(mobj_t *thing) P_SetObjectMomZ(tmthing, 8*FRACUNIT, false); P_InstaThrust(tmthing, R_PointToAngle2(thing->x, thing->y, tmthing->x, tmthing->y)+ANGLE_90, 16*FRACUNIT); } - else if (thing->type == MT_BANANASHIELD || thing->type == MT_BANANAITEM - || thing->type == MT_TRIPLEBANANASHIELD1 || thing->type == MT_TRIPLEBANANASHIELD2 || thing->type == MT_TRIPLEBANANASHIELD3 - || thing->type == MT_GREENITEM || thing->type == MT_REDITEM || thing->type == MT_REDITEMDUD - || thing->type == MT_GREENSHIELD || thing->type == MT_TRIPLEGREENSHIELD1 || thing->type == MT_TRIPLEGREENSHIELD2 || thing->type == MT_TRIPLEGREENSHIELD3 - || thing->type == MT_REDSHIELD || thing->type == MT_TRIPLEREDSHIELD1 || thing->type == MT_TRIPLEREDSHIELD2 || thing->type == MT_TRIPLEREDSHIELD3 - || thing->type == MT_FIREBALL) + else if (thing->type == MT_BANANA || thing->type == MT_BANANA_SHIELD + || thing->type == MT_ORBINAUT || thing->type == MT_ORBINAUT_SHIELD + || thing->type == MT_JAWZ || thing->type == MT_JAWZ_DUD || thing->type == MT_JAWZ_SHIELD + || thing->type == MT_BALLHOG) { // Other Item Damage if (thing->eflags & MFE_VERTICALFLIP) @@ -935,126 +904,10 @@ static boolean PIT_CheckThing(mobj_t *thing) P_SetObjectMomZ(tmthing, 8*FRACUNIT, false); P_InstaThrust(tmthing, R_PointToAngle2(thing->x, thing->y, tmthing->x, tmthing->y)+ANGLE_90, 16*FRACUNIT); } - else if (thing->type == MT_FAKEITEM || thing->type == MT_FAKESHIELD) - { - if (tmthing->type == MT_BANANASHIELD || tmthing->type == MT_TRIPLEBANANASHIELD1 || tmthing->type == MT_TRIPLEBANANASHIELD2 || tmthing->type == MT_TRIPLEBANANASHIELD3) - { - // This Item Damage - if (tmthing->eflags & MFE_VERTICALFLIP) - tmthing->z -= tmthing->height; - else - tmthing->z += tmthing->height; - - S_StartSound(tmthing, tmthing->info->deathsound); - P_KillMobj(tmthing, thing, thing); - - P_SetObjectMomZ(tmthing, 8*FRACUNIT, false); - P_InstaThrust(tmthing, R_PointToAngle2(thing->x, thing->y, tmthing->x, tmthing->y)+ANGLE_90, 16*FRACUNIT); - - P_SpawnMobj(thing->x/2 + tmthing->x/2, thing->y/2 + tmthing->y/2, thing->z/2 + tmthing->z/2, MT_ITEMCLASH); - } - // Other Item Damage - if (thing->eflags & MFE_VERTICALFLIP) - thing->z -= thing->height; - else - thing->z += thing->height; - - S_StartSound(thing, thing->info->deathsound); - P_KillMobj(thing, tmthing, tmthing); - - P_SetObjectMomZ(thing, 8*FRACUNIT, false); - P_InstaThrust(thing, R_PointToAngle2(tmthing->x, tmthing->y, thing->x, thing->y)+ANGLE_90, 16*FRACUNIT); - } return true; } - else if (tmthing->type == MT_FAKESHIELD || tmthing->type == MT_FAKEITEM) - { - // see if it went over / under - if (tmthing->z > thing->z + thing->height) - return true; // overhead - if (tmthing->z + tmthing->height < thing->z) - return true; // underneath - - if (((tmthing->target == thing) || (tmthing->target == thing->target)) && (tmthing->threshold > 0 || (thing->type != MT_PLAYER && thing->threshold > 0))) - return true; - - if (tmthing->health <= 0 || thing->health <= 0) - return true; - - if (thing->player && thing->player->powers[pw_flashing]) - return true; - - if (thing->type == MT_GREENITEM // When these items collide with the fake item, just the fake item is destroyed - || thing->type == MT_REDITEM || thing->type == MT_REDITEMDUD - || thing->type == MT_BOMBITEM - || thing->type == MT_BANANAITEM || thing->type == MT_FIREBALL) - { - // This Item Damage - if (tmthing->eflags & MFE_VERTICALFLIP) - tmthing->z -= tmthing->height; - else - tmthing->z += tmthing->height; - - S_StartSound(tmthing, tmthing->info->deathsound); - P_KillMobj(tmthing, thing, thing); - - P_SetObjectMomZ(tmthing, 8*FRACUNIT, false); - P_InstaThrust(tmthing, R_PointToAngle2(thing->x, thing->y, tmthing->x, tmthing->y)+ANGLE_90, 16*FRACUNIT); - } - else if (thing->type == MT_GREENSHIELD || thing->type == MT_TRIPLEGREENSHIELD1 || thing->type == MT_TRIPLEGREENSHIELD2 || thing->type == MT_TRIPLEGREENSHIELD3 // When these items collide with the fake item, both of them are destroyed - || thing->type == MT_REDSHIELD || thing->type == MT_TRIPLEREDSHIELD1 || thing->type == MT_TRIPLEREDSHIELD2 || thing->type == MT_TRIPLEREDSHIELD3 - || thing->type == MT_BOMBSHIELD - || thing->type == MT_BANANASHIELD || thing->type == MT_TRIPLEBANANASHIELD1 || thing->type == MT_TRIPLEBANANASHIELD2 || thing->type == MT_TRIPLEBANANASHIELD3 - || thing->type == MT_FAKEITEM || thing->type == MT_FAKESHIELD) - { - // Other Item Damage - if (thing->eflags & MFE_VERTICALFLIP) - thing->z -= thing->height; - else - thing->z += thing->height; - - S_StartSound(thing, thing->info->deathsound); - P_KillMobj(thing, tmthing, tmthing); - - P_SetObjectMomZ(thing, 8*FRACUNIT, false); - P_InstaThrust(thing, R_PointToAngle2(tmthing->x, tmthing->y, thing->x, thing->y)+ANGLE_90, 16*FRACUNIT); - - P_SpawnMobj(thing->x/2 + tmthing->x/2, thing->y/2 + tmthing->y/2, thing->z/2 + tmthing->z/2, MT_ITEMCLASH); - - // This Item Damage - if (tmthing->eflags & MFE_VERTICALFLIP) - tmthing->z -= tmthing->height; - else - tmthing->z += tmthing->height; - - S_StartSound(tmthing, tmthing->info->deathsound); - P_KillMobj(tmthing, thing, thing); - - P_SetObjectMomZ(tmthing, 8*FRACUNIT, false); - P_InstaThrust(tmthing, R_PointToAngle2(thing->x, thing->y, tmthing->x, tmthing->y)+ANGLE_90, 16*FRACUNIT); - } - else if (thing->type == MT_PLAYER) - { - // Player Damage - P_DamageMobj(thing, tmthing, tmthing->target, 1); - - // This Item Damage - if (tmthing->eflags & MFE_VERTICALFLIP) - tmthing->z -= tmthing->height; - else - tmthing->z += tmthing->height; - - S_StartSound(tmthing, tmthing->info->deathsound); - P_KillMobj(tmthing, thing, thing); - - P_SetObjectMomZ(tmthing, 8*FRACUNIT, false); - P_InstaThrust(tmthing, R_PointToAngle2(thing->x, thing->y, tmthing->x, tmthing->y)+ANGLE_90, 16*FRACUNIT); - } - - return true; - } - else if (tmthing->type == MT_BOMBSHIELD || tmthing->type == MT_BOMBITEM) + else if (tmthing->type == MT_SSMINE_SHIELD || tmthing->type == MT_SSMINE) { // see if it went over / under if (tmthing->z > thing->z + thing->height) @@ -1075,9 +928,8 @@ static boolean PIT_CheckThing(mobj_t *thing) { P_KillMobj(tmthing, thing, thing); } - else if (thing->type == MT_GREENITEM || thing->type == MT_REDITEM || thing->type == MT_REDITEMDUD - || thing->type == MT_GREENSHIELD || thing->type == MT_TRIPLEGREENSHIELD1 || thing->type == MT_TRIPLEGREENSHIELD2 || thing->type == MT_TRIPLEGREENSHIELD3 - || thing->type == MT_REDSHIELD || thing->type == MT_TRIPLEREDSHIELD1 || thing->type == MT_TRIPLEREDSHIELD2 || thing->type == MT_TRIPLEREDSHIELD3) + 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) { P_KillMobj(tmthing, thing, thing); @@ -1097,16 +949,12 @@ static boolean PIT_CheckThing(mobj_t *thing) return true; } else if (tmthing->type == MT_PLAYER && - (thing->type == MT_GREENSHIELD || thing->type == MT_GREENITEM - || thing->type == MT_REDSHIELD || thing->type == MT_REDITEM || thing->type == MT_REDITEMDUD - || thing->type == MT_TRIPLEGREENSHIELD1 || thing->type == MT_TRIPLEGREENSHIELD2 || thing->type == MT_TRIPLEGREENSHIELD3 - || thing->type == MT_TRIPLEREDSHIELD1 || thing->type == MT_TRIPLEREDSHIELD2 || thing->type == MT_TRIPLEREDSHIELD3 - || thing->type == MT_FAKESHIELD || thing->type == MT_FAKEITEM - || thing->type == MT_BANANASHIELD || thing->type == MT_BANANAITEM - || thing->type == MT_TRIPLEBANANASHIELD1 || thing->type == MT_TRIPLEBANANASHIELD2 || thing->type == MT_TRIPLEBANANASHIELD3 - || thing->type == MT_BOMBSHIELD || thing->type == MT_BOMBITEM - || thing->type == MT_BOMBEXPLOSION - || thing->type == MT_SINK || thing->type == MT_FIREBALL + (thing->type == MT_ORBINAUT_SHIELD || thing->type == MT_ORBINAUT + || thing->type == MT_JAWZ_SHIELD || thing->type == MT_JAWZ || thing->type == MT_JAWZ_DUD + || thing->type == MT_BANANA_SHIELD || thing->type == MT_BANANA + || thing->type == MT_SSMINE_SHIELD || thing->type == MT_SSMINE + || thing->type == MT_MINEEXPLOSION + || thing->type == MT_SINK || thing->type == MT_BALLHOG )) { // see if it went over / under @@ -1116,13 +964,11 @@ static boolean PIT_CheckThing(mobj_t *thing) return true; // underneath if (tmthing->player && tmthing->player->powers[pw_flashing] - && !(thing->type == MT_GREENITEM || thing->type == MT_REDITEM || thing->type == MT_REDITEMDUD)) + && !(thing->type == MT_ORBINAUT || thing->type == MT_JAWZ || thing->type == MT_JAWZ_DUD)) return true; - if (thing->type == MT_GREENSHIELD || thing->type == MT_TRIPLEGREENSHIELD1 || thing->type == MT_TRIPLEGREENSHIELD2 || thing->type == MT_TRIPLEGREENSHIELD3 - || thing->type == MT_REDSHIELD || thing->type == MT_TRIPLEREDSHIELD1 || thing->type == MT_TRIPLEREDSHIELD2 || thing->type == MT_TRIPLEREDSHIELD3 - || thing->type == MT_GREENITEM || thing->type == MT_REDITEM || thing->type == MT_REDITEMDUD - || thing->type == MT_FAKESHIELD || thing->type == MT_FAKEITEM) + if (thing->type == MT_ORBINAUT_SHIELD || thing->type == MT_JAWZ_SHIELD + || thing->type == MT_ORBINAUT || thing->type == MT_JAWZ || thing->type == MT_JAWZ_DUD) { if ((thing->target == tmthing) && (thing->threshold > 0)) return true; @@ -1132,8 +978,9 @@ static boolean PIT_CheckThing(mobj_t *thing) // Player Damage P_DamageMobj(tmthing, thing, thing->target, 1); + K_KartBouncing(tmthing, thing, false, false); - if (thing->type == MT_GREENITEM || thing->type == MT_REDITEM || thing->type == MT_REDITEMDUD) + if (thing->type == MT_ORBINAUT || thing->type == MT_JAWZ || thing->type == MT_JAWZ_DUD) S_StartSound(tmthing, sfx_shelit); // Other Item Damage @@ -1148,9 +995,8 @@ static boolean PIT_CheckThing(mobj_t *thing) P_SetObjectMomZ(thing, 8*FRACUNIT, false); P_InstaThrust(thing, R_PointToAngle2(tmthing->x, tmthing->y, thing->x, thing->y)+ANGLE_90, 16*FRACUNIT); } - else if (thing->type == MT_BANANASHIELD || thing->type == MT_BANANAITEM - || thing->type == MT_TRIPLEBANANASHIELD1 || thing->type == MT_TRIPLEBANANASHIELD2 || thing->type == MT_TRIPLEBANANASHIELD3 - || thing->type == MT_FIREBALL) + else if (thing->type == MT_BANANA_SHIELD || thing->type == MT_BANANA + || thing->type == MT_BALLHOG) { if ((thing->target == tmthing) && (thing->threshold > 0)) return true; @@ -1159,7 +1005,7 @@ static boolean PIT_CheckThing(mobj_t *thing) return true; // Player Damage - K_SpinPlayer(tmthing->player, thing->target); + K_SpinPlayer(tmthing->player, thing->target, 0, (thing->type == MT_BANANA || thing->type == MT_BANANA_SHIELD)); // Other Item Damage if (thing->eflags & MFE_VERTICALFLIP) @@ -1173,7 +1019,7 @@ static boolean PIT_CheckThing(mobj_t *thing) P_SetObjectMomZ(thing, 8*FRACUNIT, false); P_InstaThrust(thing, R_PointToAngle2(tmthing->x, tmthing->y, thing->x, thing->y)+ANGLE_90, 16*FRACUNIT); } - else if (thing->type == MT_BOMBSHIELD || thing->type == MT_BOMBITEM) + else if (thing->type == MT_SSMINE_SHIELD || thing->type == MT_SSMINE) { if ((thing->target == tmthing) && (thing->threshold > 0)) return true; @@ -1183,13 +1029,13 @@ static boolean PIT_CheckThing(mobj_t *thing) P_KillMobj(thing, tmthing, tmthing); } - else if (thing->type == MT_BOMBEXPLOSION && tmthing->player) + else if (thing->type == MT_MINEEXPLOSION && tmthing->player) { // Player Damage - if (thing->state == &states[S_BOMBEXPLOSION1]) + if (thing->state == &states[S_MINEEXPLOSION1]) K_ExplodePlayer(tmthing->player, thing->target); else - K_SpinPlayer(tmthing->player, thing->target); + K_SpinPlayer(tmthing->player, thing->target, 0, false); return true; } @@ -1543,21 +1389,15 @@ static boolean PIT_CheckThing(mobj_t *thing) && !(thing->z + thing->height < tmthing->z || thing->z > tmthing->z + tmthing->height)) { // SRB2kart - Squish! - if ((tmthing->player->kartstuff[k_growshrinktimer] > 0 && thing->player->kartstuff[k_growshrinktimer] <= 0) - || (tmthing->player->kartstuff[k_growshrinktimer] == 0 && thing->player->kartstuff[k_growshrinktimer] < 0)) - { + if (tmthing->scale > thing->scale + (FRACUNIT/8)) K_SquishPlayer(thing->player, tmthing); - } - else if ((thing->player->kartstuff[k_growshrinktimer] > 0 && tmthing->player->kartstuff[k_growshrinktimer] <= 0) - || (thing->player->kartstuff[k_growshrinktimer] == 0 && tmthing->player->kartstuff[k_growshrinktimer] < 0)) - { + else if (thing->scale > tmthing->scale + (FRACUNIT/8)) K_SquishPlayer(tmthing->player, thing); - } // SRB2kart - Starpower! - if (tmthing->player->kartstuff[k_startimer] && !thing->player->kartstuff[k_startimer]) + if (tmthing->player->kartstuff[k_invincibilitytimer] && !thing->player->kartstuff[k_invincibilitytimer]) P_DamageMobj(thing, tmthing, tmthing, 1); - else if (thing->player->kartstuff[k_startimer] && !tmthing->player->kartstuff[k_startimer]) + else if (thing->player->kartstuff[k_invincibilitytimer] && !tmthing->player->kartstuff[k_invincibilitytimer]) P_DamageMobj(tmthing, thing, thing, 1); if (G_BattleGametype() && (!G_GametypeHasTeams() || tmthing->player->ctfteam != thing->player->ctfteam)) @@ -1649,107 +1489,32 @@ static boolean PIT_CheckThing(mobj_t *thing) if (tmthing->z + tmthing->height < thing->z) return true; // underneath - if (thing->player->kartstuff[k_growshrinktimer] || thing->player->kartstuff[k_squishedtimer] - || thing->player->kartstuff[k_bootimer] || thing->player->kartstuff[k_spinouttimer] - || thing->player->kartstuff[k_startimer] || thing->player->kartstuff[k_justbumped] - || (G_BattleGametype() && (thing->player->kartstuff[k_balloon] <= 0 - && (thing->player->kartstuff[k_comebacktimer]))) - || tmthing->player->kartstuff[k_growshrinktimer] || tmthing->player->kartstuff[k_squishedtimer] - || tmthing->player->kartstuff[k_bootimer] || tmthing->player->kartstuff[k_spinouttimer] - || tmthing->player->kartstuff[k_startimer] || tmthing->player->kartstuff[k_justbumped] - || (G_BattleGametype() && (tmthing->player->kartstuff[k_balloon] <= 0 - && (tmthing->player->kartstuff[k_comebacktimer])))) + if (thing->player->kartstuff[k_squishedtimer] || thing->player->kartstuff[k_hyudorotimer] + || thing->player->kartstuff[k_justbumped] || thing->scale > tmthing->scale + (FRACUNIT/8) + || (G_BattleGametype() && thing->player->kartstuff[k_bumper] <= 0) + || tmthing->player->kartstuff[k_squishedtimer] || tmthing->player->kartstuff[k_hyudorotimer] + || tmthing->player->kartstuff[k_justbumped] || tmthing->scale > thing->scale + (FRACUNIT/8) + || (G_BattleGametype() && tmthing->player->kartstuff[k_bumper] <= 0)) { return true; } - if (G_BattleGametype()) - { - if (thing->player->kartstuff[k_balloon] <= 0 || tmthing->player->kartstuff[k_balloon] <= 0) - { - if (thing->player->kartstuff[k_comebackmode] == 0 - && (tmthing->player->kartstuff[k_balloon] > 0 - && !tmthing->player->powers[pw_flashing])) - { - mobj_t *boom = P_SpawnMobj(thing->x, thing->y, thing->z, MT_BOOMPARTICLE); - boom->scale = thing->scale; - boom->destscale = thing->scale; - boom->momz = 5*FRACUNIT; - if (thing->player->skincolor) - boom->color = thing->player->skincolor; - else - boom->color = SKINCOLOR_RED; - S_StartSound(boom, sfx_s3k4e); - K_ExplodePlayer(tmthing->player, thing); - thing->player->kartstuff[k_comebacktimer] = comebacktime; - return true; - } - else if (tmthing->player->kartstuff[k_comebackmode] == 0 - && (thing->player->kartstuff[k_balloon] > 0 - && !thing->player->powers[pw_flashing])) - { - mobj_t *boom = P_SpawnMobj(tmthing->x, tmthing->y, tmthing->z, MT_BOOMPARTICLE); - boom->scale = tmthing->scale; - boom->destscale = tmthing->scale; - boom->momz = 5*FRACUNIT; - if (tmthing->player->skincolor) - boom->color = tmthing->player->skincolor; - else - boom->color = SKINCOLOR_RED; - S_StartSound(boom, sfx_s3k4e); - K_ExplodePlayer(thing->player, tmthing); - tmthing->player->kartstuff[k_comebacktimer] = comebacktime; - return true; - } - else if (thing->player->kartstuff[k_comebackmode] == 1 - && (tmthing->player->kartstuff[k_balloon] > 0 - && P_CanPickupItem(tmthing->player, true))) - { - thing->player->kartstuff[k_comebackmode] = 0; - thing->player->kartstuff[k_comebackpoints]++; - if (netgame && cv_hazardlog.value) - CONS_Printf(M_GetText("%s gave an item to %s.\n"), player_names[thing->player-players], player_names[tmthing->player-players]); - tmthing->player->kartstuff[k_itemroulette] = 1; - tmthing->player->kartstuff[k_roulettetype] = 1; - if (thing->player->kartstuff[k_comebackpoints] >= 3) - K_StealBalloon(thing->player, tmthing->player, true); - thing->player->kartstuff[k_comebacktimer] = comebacktime; - return true; - } - else if (tmthing->player->kartstuff[k_comebackmode] == 1 - && (thing->player->kartstuff[k_balloon] > 0 - && P_CanPickupItem(thing->player, true))) - { - tmthing->player->kartstuff[k_comebackmode] = 0; - tmthing->player->kartstuff[k_comebackpoints]++; - if (netgame && cv_hazardlog.value) - CONS_Printf(M_GetText("%s gave an item to %s.\n"), player_names[tmthing->player-players], player_names[thing->player-players]); - thing->player->kartstuff[k_itemroulette] = 1; - thing->player->kartstuff[k_roulettetype] = 1; - if (tmthing->player->kartstuff[k_comebackpoints] >= 3) - K_StealBalloon(tmthing->player, thing->player, true); - tmthing->player->kartstuff[k_comebacktimer] = comebacktime; - return true; - } - } - } - if (P_IsObjectOnGround(thing) && tmthing->momz < 0) { K_KartBouncing(tmthing, thing, true, false); - if (G_BattleGametype() && tmthing->player->kartstuff[k_feather] & 2) + if (G_BattleGametype() && tmthing->player->kartstuff[k_pogospring]) { - K_StealBalloon(tmthing->player, thing->player, false); - K_SpinPlayer(thing->player, tmthing); + K_StealBumper(tmthing->player, thing->player, false); + K_SpinPlayer(thing->player, tmthing, 0, false); } } else if (P_IsObjectOnGround(tmthing) && thing->momz < 0) { K_KartBouncing(thing, tmthing, true, false); - if (G_BattleGametype() && thing->player->kartstuff[k_feather] & 2) + if (G_BattleGametype() && thing->player->kartstuff[k_pogospring]) { - K_StealBalloon(thing->player, tmthing->player, false); - K_SpinPlayer(tmthing->player, thing); + K_StealBumper(thing->player, tmthing->player, false); + K_SpinPlayer(tmthing->player, thing, 0, false); } } else @@ -1757,15 +1522,15 @@ static boolean PIT_CheckThing(mobj_t *thing) if (G_BattleGametype()) { - if (thing->player->kartstuff[k_mushroomtimer] && !(tmthing->player->kartstuff[k_mushroomtimer])) + if (thing->player->kartstuff[k_sneakertimer] && !(tmthing->player->kartstuff[k_sneakertimer])) { - K_StealBalloon(thing->player, tmthing->player, false); - K_SpinPlayer(tmthing->player, thing); + K_StealBumper(thing->player, tmthing->player, false); + K_SpinPlayer(tmthing->player, thing, 0, false); } - else if (tmthing->player->kartstuff[k_mushroomtimer] && !(thing->player->kartstuff[k_mushroomtimer])) + else if (tmthing->player->kartstuff[k_sneakertimer] && !(thing->player->kartstuff[k_sneakertimer])) { - K_StealBalloon(tmthing->player, thing->player, false); - K_SpinPlayer(thing->player, tmthing); + K_StealBumper(tmthing->player, thing->player, false); + K_SpinPlayer(thing->player, tmthing, 0, false); } } @@ -2608,10 +2373,13 @@ boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam) fixed_t tryx = thiscam->x; fixed_t tryy = thiscam->y; +#ifndef NOCLIPCAM if ((thiscam == &camera && (players[displayplayer].pflags & PF_NOCLIP)) || (thiscam == &camera2 && (players[secondarydisplayplayer].pflags & PF_NOCLIP)) || (thiscam == &camera3 && (players[thirddisplayplayer].pflags & PF_NOCLIP)) - || (thiscam == &camera4 && (players[fourthdisplayplayer].pflags & PF_NOCLIP))) + || (thiscam == &camera4 && (players[fourthdisplayplayer].pflags & PF_NOCLIP)) + || (leveltime < introtime)) +#endif { // Noclipping player camera noclips too!! floatok = true; thiscam->floorz = thiscam->z; @@ -3229,11 +2997,11 @@ static void P_HitSlideLine(line_t *ld) } // -// P_HitBounceLine +// P_PlayerHitBounceLine // -// Adjusts the xmove / ymove so that the next move will bounce off the wall. +// HitBounceLine, for players // -static void P_HitBounceLine(line_t *ld) +static void P_PlayerHitBounceLine(line_t *ld) { INT32 side; angle_t lineangle; @@ -3256,6 +3024,47 @@ static void P_HitBounceLine(line_t *ld) tmymove += FixedMul(movelen, FINESINE(lineangle)); } +// +// P_HitBounceLine +// +// Adjusts the xmove / ymove so that the next move will bounce off the wall. +// +static void P_HitBounceLine(line_t *ld) +{ + angle_t lineangle, moveangle, deltaangle; + fixed_t movelen; + + if (ld->slopetype == ST_HORIZONTAL) + { + tmymove = -tmymove; + return; + } + + if (ld->slopetype == ST_VERTICAL) + { + tmxmove = -tmxmove; + return; + } + + lineangle = R_PointToAngle2(0, 0, ld->dx, ld->dy); + + if (lineangle >= ANGLE_180) + lineangle -= ANGLE_180; + + moveangle = R_PointToAngle2(0, 0, tmxmove, tmymove); + deltaangle = moveangle + 2*(lineangle - moveangle); + + lineangle >>= ANGLETOFINESHIFT; + deltaangle >>= ANGLETOFINESHIFT; + + movelen = P_AproxDistance(tmxmove, tmymove); + + tmxmove = FixedMul(movelen, FINECOSINE(deltaangle)); + tmymove = FixedMul(movelen, FINESINE(deltaangle)); + + deltaangle = R_PointToAngle2(0, 0, tmxmove, tmymove); +} + // // PTR_SlideCameraTraverse // @@ -3874,41 +3683,35 @@ stairstep: } // -// P_BounceMove +// P_BouncePlayerMove // -// The momx / momy move is bad, so try to bounce off a wall. +// Bounce move, for players. // -void P_BounceMove(mobj_t *mo) + +void P_BouncePlayerMove(mobj_t *mo) { fixed_t leadx, leady; fixed_t trailx, traily; - //fixed_t newx, newy; - //INT32 hitcount; fixed_t mmomx = 0, mmomy = 0; - if (mo->eflags & MFE_JUSTBOUNCEDWALL) + if (!mo->player) + return; + + if ((mo->eflags & MFE_JUSTBOUNCEDWALL) || (mo->player->spectator)) { P_SlideMove(mo, true); return; } slidemo = mo; - //hitcount = 0; -/*retry: - if (++hitcount == 3) - goto bounceback; // don't loop forever*/ + mmomx = mo->player->rmomx; + mmomy = mo->player->rmomy; - if (mo->player) + if (mo->player->kartstuff[k_drift] != 0) // SRB2kart { - mmomx = mo->player->rmomx; - mmomy = mo->player->rmomy; - - if (mo->player->kartstuff[k_drift] != 0) // SRB2kart - { - mo->player->kartstuff[k_drift] = 0; - mo->player->kartstuff[k_driftcharge] = 0; - } + mo->player->kartstuff[k_drift] = 0; + mo->player->kartstuff[k_driftcharge] = 0; } else { @@ -3945,8 +3748,107 @@ void P_BounceMove(mobj_t *mo) P_PathTraverse(trailx, leady, trailx + mmomx, leady + mmomy, PT_ADDLINES, PTR_SlideTraverse); P_PathTraverse(leadx, traily, leadx + mmomx, traily + mmomy, PT_ADDLINES, PTR_SlideTraverse); + // Now continue along the wall. + // First calculate remainder. + bestslidefrac = FRACUNIT - bestslidefrac; + + if (bestslidefrac > FRACUNIT) + bestslidefrac = FRACUNIT; + + if (bestslidefrac <= 0) + return; + + tmxmove = FixedMul(mmomx, (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3))); + tmymove = FixedMul(mmomy, (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3))); + + { + mobj_t *fx = P_SpawnMobj(mo->x, mo->y, mo->z, MT_BUMP); + if (mo->eflags & MFE_VERTICALFLIP) + fx->eflags |= MFE_VERTICALFLIP; + else + fx->eflags &= ~MFE_VERTICALFLIP; + fx->scale = mo->scale; + + S_StartSound(mo, sfx_s3k49); + } + + P_PlayerHitBounceLine(bestslideline); + mo->eflags |= MFE_JUSTBOUNCEDWALL; + + mo->momx = tmxmove; + mo->momy = tmymove; + mo->player->cmomx = tmxmove; + mo->player->cmomy = tmymove; + + P_TryMove(mo, mo->x + tmxmove, mo->y + tmymove, true); +} + +// +// P_BounceMove +// +// The momx / momy move is bad, so try to bounce off a wall. +// +void P_BounceMove(mobj_t *mo) +{ + fixed_t leadx, leady; + fixed_t trailx, traily; + fixed_t newx, newy; + INT32 hitcount; + fixed_t mmomx = 0, mmomy = 0; + + if (mo->eflags & MFE_JUSTBOUNCEDWALL) + { + P_SlideMove(mo, true); + return; + } + + if (mo->player) + { + P_BouncePlayerMove(mo); + return; + } + + slidemo = mo; + hitcount = 0; + +retry: + if (++hitcount == 3) + goto bounceback; // don't loop forever + + mmomx = mo->momx; + mmomy = mo->momy; + + // trace along the three leading corners + if (mo->momx > 0) + { + leadx = mo->x + mo->radius; + trailx = mo->x - mo->radius; + } + else + { + leadx = mo->x - mo->radius; + trailx = mo->x + mo->radius; + } + + if (mo->momy > 0) + { + leady = mo->y + mo->radius; + traily = mo->y - mo->radius; + } + else + { + leady = mo->y - mo->radius; + traily = mo->y + mo->radius; + } + + bestslidefrac = FRACUNIT + 1; + + P_PathTraverse(leadx, leady, leadx + mmomx, leady + mmomy, PT_ADDLINES, PTR_SlideTraverse); + P_PathTraverse(trailx, leady, trailx + mmomx, leady + mmomy, PT_ADDLINES, PTR_SlideTraverse); + P_PathTraverse(leadx, traily, leadx + mmomx, traily + mmomy, PT_ADDLINES, PTR_SlideTraverse); + // move up to the wall - /*if (bestslidefrac == FRACUNIT + 1) + if (bestslidefrac == FRACUNIT + 1) { // the move must have hit the middle, so bounce straight back bounceback: @@ -3956,22 +3858,12 @@ bounceback: mo->momy *= -1; mo->momx = FixedMul(mo->momx, (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3))); mo->momy = FixedMul(mo->momy, (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3))); - - if (mo->player) - { - mo->player->cmomx *= -1; - mo->player->cmomy *= -1; - mo->player->cmomx = FixedMul(mo->player->cmomx, - (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3))); - mo->player->cmomy = FixedMul(mo->player->cmomy, - (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3))); - } } return; - }*/ + } // fudge a bit to make sure it doesn't hit - /*bestslidefrac -= 0x800; + bestslidefrac -= 0x800; if (bestslidefrac > 0) { newx = FixedMul(mmomx, bestslidefrac); @@ -3979,7 +3871,7 @@ bounceback: if (!P_TryMove(mo, mo->x + newx, mo->y + newy, true)) goto bounceback; - }*/ + } // Now continue along the wall. // First calculate remainder. @@ -4011,34 +3903,15 @@ bounceback: { tmxmove = FixedMul(mmomx, (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3))); tmymove = FixedMul(mmomy, (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3))); - if (mo->player) - { - mobj_t *fx = P_SpawnMobj(mo->x, mo->y, mo->z, MT_BUMP); - if (mo->eflags & MFE_VERTICALFLIP) - fx->eflags |= MFE_VERTICALFLIP; - else - fx->eflags &= ~MFE_VERTICALFLIP; - fx->scale = mo->scale; - - S_StartSound(mo, sfx_s3k49); - } } - P_HitBounceLine(bestslideline); - mo->eflags |= MFE_JUSTBOUNCEDWALL; + P_HitBounceLine(bestslideline); // clip the moves mo->momx = tmxmove; mo->momy = tmymove; - if (mo->player) - { - mo->player->cmomx = tmxmove; - mo->player->cmomy = tmymove; - } - - /*if (!P_TryMove(mo, mo->x + tmxmove, mo->y + tmymove, true)) - goto retry;*/ - P_TryMove(mo, mo->x + tmxmove, mo->y + tmymove, true); + if (!P_TryMove(mo, mo->x + tmxmove, mo->y + tmymove, true)) + goto retry; } // diff --git a/src/p_mobj.c b/src/p_mobj.c index 9619ccb6..d7ef576d 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -38,8 +38,8 @@ #include "k_kart.h" // protos. -static CV_PossibleValue_t viewheight_cons_t[] = {{16, "MIN"}, {56, "MAX"}, {0, NULL}}; -consvar_t cv_viewheight = {"viewheight", VIEWHEIGHTS, 0, viewheight_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +//static CV_PossibleValue_t viewheight_cons_t[] = {{16, "MIN"}, {56, "MAX"}, {0, NULL}}; +//consvar_t cv_viewheight = {"viewheight", VIEWHEIGHTS, 0, viewheight_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; #ifdef WALLSPLATS consvar_t cv_splats = {"splats", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; #endif @@ -217,10 +217,10 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state) } } // 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() && state != mobj->info->painstate) + else */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()-1; + player->powers[pw_flashing] = K_GetKartFlashing(player)-1; //P_DoPityCheck(player); } @@ -1343,7 +1343,7 @@ fixed_t P_GetMobjGravity(mobj_t *mo) // || (mo->state >= &states[S_PLAY_SPC1] && mo->state <= &states[S_PLAY_SPC4])))) // gravityadd = gravityadd/3; // less gravity while flying/gliding if (mo->player->climbing || (mo->player->pflags & PF_NIGHTSMODE)) - gravityadd = 0; + return 0; if (!(mo->flags2 & MF2_OBJECTFLIP) != !(mo->player->powers[pw_gravityboots])) // negated to turn numeric into bool - would be double negated, but not needed if both would be { @@ -1352,7 +1352,7 @@ fixed_t P_GetMobjGravity(mobj_t *mo) } if (wasflip == !(mo->eflags & MFE_VERTICALFLIP)) // note!! == ! is not equivalent to != here - turns numeric into bool this way P_PlayerFlip(mo); - if (mo->player->kartstuff[k_feather] & 2) + if (mo->player->kartstuff[k_pogospring]) gravityadd = FixedMul(gravityadd, 5*FRACUNIT/2); } else @@ -1401,9 +1401,10 @@ fixed_t P_GetMobjGravity(mobj_t *mo) case MT_WATERDROP: gravityadd >>= 1; break; - case MT_BANANAITEM: + case MT_BANANA: case MT_FAKEITEM: - case MT_BOMBITEM: + case MT_SSMINE: + case MT_SINK: gravityadd = FixedMul(gravityadd, 5*FRACUNIT/2); default: break; @@ -1722,14 +1723,22 @@ void P_XYMovement(mobj_t *mo) if (CheckForBustableBlocks && mo->flags & MF_PUSHABLE) P_PushableCheckBustables(mo); - //{ SRB2kart - Fireball - if (mo->type == MT_FIREBALL) + //{ SRB2kart - Ballhogs + if (mo->type == MT_BALLHOG) { - mo->health--; - if (mo->health == 0) + if (mo->health) { - S_StartSound(mo, mo->info->deathsound); - P_SetMobjState(mo, mo->info->deathstate); + mo->health--; + if (mo->health == 0) + mo->destscale = 1; + } + else + { + if (mo->scale < mapheaderinfo[gamemap-1]->mobj_scale/16) + { + P_RemoveMobj(mo); + return; + } } } //} @@ -1742,8 +1751,8 @@ void P_XYMovement(mobj_t *mo) if (player->bot) B_MoveBlocked(player); } - //{ SRB2kart - Red Shell - if (mo->type == MT_REDITEM || mo->type == MT_REDITEMDUD) + //{ SRB2kart - Jawz + if (mo->type == MT_JAWZ || mo->type == MT_JAWZ_DUD) { if (mo->health == 1) { @@ -1760,9 +1769,11 @@ void P_XYMovement(mobj_t *mo) { P_BounceMove(mo); xmove = ymove = 0; - //S_StartSound(mo, mo->info->activesound); - //{ SRB2kart - Green Shell, Fireball - if (mo->type == MT_GREENITEM) + S_StartSound(mo, mo->info->activesound); + + //{ SRB2kart - Orbinaut, Ballhog + // Bump sparks + if (mo->type == MT_ORBINAUT || mo->type == MT_BALLHOG) { mobj_t *fx; fx = P_SpawnMobj(mo->x, mo->y, mo->z, MT_BUMP); @@ -1771,6 +1782,10 @@ void P_XYMovement(mobj_t *mo) else fx->eflags &= ~MFE_VERTICALFLIP; fx->scale = mo->scale; + } + + if (mo->type == MT_ORBINAUT) // Orbinaut speed decreasing + { if (mo->health > 1) { S_StartSound(mo, mo->info->attacksound); @@ -1787,10 +1802,6 @@ void P_XYMovement(mobj_t *mo) P_InstaThrust(mo, R_PointToAngle2(mo->x, mo->y, mo->x + xmove, mo->y + ymove)+ANGLE_90, 16*FRACUNIT); } } - if (mo->type == MT_FIREBALL) - S_StartSound(mo, mo->info->attacksound); - else - S_StartSound(mo, mo->info->activesound); //} // Bounce ring algorithm @@ -1861,7 +1872,7 @@ void P_XYMovement(mobj_t *mo) // draw damage on wall //SPLAT TEST ---------------------------------------------------------- #ifdef WALLSPLATS - if (blockingline && mo->type != MT_REDRING //&& mo->type != MT_FIREBALL + if (blockingline && mo->type != MT_REDRING && mo->type != MT_FIREBALL && !(mo->flags2 & (MF2_AUTOMATIC|MF2_RAILRING|MF2_BOUNCERING|MF2_EXPLOSION|MF2_SCATTER))) // set by last P_TryMove() that failed { @@ -1997,10 +2008,10 @@ void P_XYMovement(mobj_t *mo) #endif //{ SRB2kart stuff - if (mo->type == MT_GREENITEM || mo->type == MT_REDITEMDUD || mo->type == MT_REDITEM || mo->type == MT_FIREBALL) //(mo->type == MT_REDITEM && !mo->tracer)) + if (mo->type == MT_ORBINAUT || mo->type == MT_JAWZ_DUD || mo->type == MT_JAWZ || mo->type == MT_BALLHOG) //(mo->type == MT_JAWZ && !mo->tracer)) return; - if (mo->player && mo->player->kartstuff[k_spinouttimer] && mo->player->speed <= mo->player->normalspeed/2) + if (mo->player && (mo->player->kartstuff[k_spinouttimer] && !mo->player->kartstuff[k_wipeoutslow]) && mo->player->speed <= mo->player->normalspeed/2) return; //} @@ -2328,11 +2339,12 @@ static boolean P_ZMovement(mobj_t *mo) // SRB2kart stuff that should die in pits // Shouldn't stop moving along the Z if there's no speed though! case MT_FAKEITEM: - case MT_BANANAITEM: - case MT_GREENITEM: - case MT_REDITEM: - case MT_REDITEMDUD: - case MT_FIREBALL: + case MT_BANANA: + case MT_ORBINAUT: + case MT_JAWZ: + case MT_JAWZ_DUD: + case MT_BALLHOG: + case MT_SSMINE: // Remove stuff from death pits. if (P_CheckDeathPitCollide(mo)) { @@ -2886,16 +2898,16 @@ static void P_PlayerZMovement(mobj_t *mo) // Cut momentum in half when you hit the ground and // aren't pressing any controls. if (!(mo->player->cmd.forwardmove || mo->player->cmd.sidemove) && !mo->player->cmomx && !mo->player->cmomy - && !(mo->player->pflags & PF_SPINNING) && !(mo->player->kartstuff[k_spinouttimer])) + && !(mo->player->kartstuff[k_spinouttimer])) { mo->momx = mo->momx/2; mo->momy = mo->momy/2; - } - if (mo->player->cmd.buttons & BT_BRAKE && !(mo->player->cmd.forwardmove)) // FURTHER slowdown if you're braking. - { - mo->momx = mo->momx/2; - mo->momy = mo->momy/2; + if (mo->player->cmd.buttons & BT_BRAKE && !(mo->player->cmd.forwardmove)) // FURTHER slowdown if you're braking. + { + mo->momx = mo->momx/2; + mo->momy = mo->momy/2; + } } } @@ -2907,7 +2919,7 @@ static void P_PlayerZMovement(mobj_t *mo) mo->tics = -1; } else if ((mo->player->pflags & PF_JUMPED || (mo->player->pflags & (PF_SPINNING|PF_USEDOWN)) != (PF_SPINNING|PF_USEDOWN) - || mo->player->powers[pw_tailsfly]) && (mo->player->kartstuff[k_spinouttimer] == 0)) // SRB2kart + || mo->player->powers[pw_tailsfly]) && (mo->player->kartstuff[k_spinouttimer] == 0)) // SRB2kart { K_KartMoveAnimation(mo->player); } @@ -3372,17 +3384,30 @@ void P_MobjCheckWater(mobj_t *mobj) } // skipping stone! - if (p && (p->charability2 == CA2_SPINDASH) && p->speed/2 > abs(mobj->momz) - && ((p->pflags & (PF_SPINNING|PF_JUMPED)) == PF_SPINNING) + 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! && ((!(mobj->eflags & MFE_VERTICALFLIP) && thingtop - mobj->momz > mobj->watertop) || ((mobj->eflags & MFE_VERTICALFLIP) && mobj->z - mobj->momz < mobj->waterbottom))) { + const fixed_t min = 6<momx = mobj->momx/2; + mobj->momy = mobj->momy/2; mobj->momz = -mobj->momz/2; - if (!(mobj->eflags & MFE_VERTICALFLIP) && mobj->momz > FixedMul(6*FRACUNIT, mobj->scale)) - mobj->momz = FixedMul(6*FRACUNIT, mobj->scale); - else if (mobj->eflags & MFE_VERTICALFLIP && mobj->momz < FixedMul(-6*FRACUNIT, mobj->scale)) - mobj->momz = FixedMul(-6*FRACUNIT, mobj->scale); + if (!(mobj->eflags & MFE_VERTICALFLIP) && mobj->momz < FixedMul(min, mobj->scale)) + mobj->momz = FixedMul(min, mobj->scale); + else if (mobj->eflags & MFE_VERTICALFLIP && mobj->momz > FixedMul(-min, mobj->scale)) + mobj->momz = FixedMul(-min, mobj->scale); + + /*if (!(mobj->eflags & MFE_VERTICALFLIP) && mobj->momz > FixedMul(max, mobj->scale)) + mobj->momz = FixedMul(max, mobj->scale); + else if (mobj->eflags & MFE_VERTICALFLIP && mobj->momz < FixedMul(-max, mobj->scale)) + mobj->momz = FixedMul(-max, mobj->scale);*/ + + p->kartstuff[k_waterskip]++; } } @@ -3677,7 +3702,7 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled dummy.y = thiscam->y; dummy.z = thiscam->z; dummy.height = thiscam->height; - if (!resetcalled && !(player->pflags & PF_NOCLIP) && !P_CheckSight(&dummy, player->mo)) // TODO: "P_CheckCameraSight" instead. + if (!resetcalled && !(player->pflags & PF_NOCLIP || leveltime < introtime) && !P_CheckSight(&dummy, player->mo)) // TODO: "P_CheckCameraSight" instead. P_ResetCamera(player, thiscam); else P_SlideCameraMove(thiscam); @@ -3698,7 +3723,8 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled // adjust height thiscam->z += thiscam->momz + player->mo->pmomz; - if (!itsatwodlevel && !(player->pflags & PF_NOCLIP)) +#ifndef NOCLIPCAM + if (!itsatwodlevel && !(player->pflags & PF_NOCLIP || leveltime < introtime)) { // clip movement if (thiscam->z <= thiscam->floorz) // hit the floor @@ -3738,6 +3764,7 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled } } } +#endif } if (itsatwodlevel @@ -6264,6 +6291,11 @@ void P_RunShadows(void) else mobj->flags2 &= ~MF2_DONTDRAW; + if (mobj->target->eflags & MFE_VERTICALFLIP) + mobj->eflags |= MFE_VERTICALFLIP; + else + mobj->eflags &= ~MFE_VERTICALFLIP; + if (mobj->target->eflags & MFE_DRAWONLYFORP1) // groooooaann... mobj->eflags |= MFE_DRAWONLYFORP1; else @@ -6289,12 +6321,13 @@ void P_RunShadows(void) P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z); - if (mobj->floorz < mobj->z) + if (((mobj->eflags & MFE_VERTICALFLIP) && (mobj->ceilingz > mobj->z+mobj->height)) + || (!(mobj->eflags & MFE_VERTICALFLIP) && (mobj->floorz < mobj->z))) { INT32 i; fixed_t prevz; - mobj->z = mobj->floorz; + mobj->z = (mobj->eflags & MFE_VERTICALFLIP ? mobj->ceilingz : mobj->floorz); for (i = 0; i < MAXFFLOORS; i++) { @@ -6306,7 +6339,7 @@ void P_RunShadows(void) // Check new position to see if you should still be on that ledge P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->z); - mobj->z = mobj->floorz; + mobj->z = (mobj->eflags & MFE_VERTICALFLIP ? mobj->ceilingz : mobj->floorz); if (mobj->z == prevz) break; @@ -6431,6 +6464,11 @@ void P_MobjThinker(mobj_t *mobj) P_SetTarget(&mobj->target, NULL); if (mobj->tracer && P_MobjWasRemoved(mobj->tracer)) P_SetTarget(&mobj->tracer, NULL); + // hnext/hprev changes suggested by toaster + if (mobj->hnext && P_MobjWasRemoved(mobj->hnext)) + P_SetTarget(&mobj->hnext, NULL); + if (mobj->hprev && P_MobjWasRemoved(mobj->hprev)) + P_SetTarget(&mobj->hprev, NULL); mobj->flags2 &= ~MF2_PUSHED; mobj->eflags &= ~(MFE_SPRUNG|MFE_JUSTBOUNCEDWALL); @@ -6577,16 +6615,11 @@ void P_MobjThinker(mobj_t *mobj) { if (mobj->target && mobj->target->player && mobj->target->player->mo && mobj->target->player->health > 0 && !mobj->target->player->spectator) { - UINT8 kartspeed = mobj->target->player->kartspeed; - fixed_t dsone, dstwo; - INT32 HEIGHT; + fixed_t HEIGHT; fixed_t radius; - if (G_BattleGametype() && mobj->target->player->kartstuff[k_balloon] <= 0) - kartspeed = 1; - - dsone = (26*4 + kartspeed*2 + (9 - mobj->target->player->kartweight))*8; - dstwo = dsone*2; + fixed_t dsone = K_GetKartDriftSparkValue(mobj->target->player); + fixed_t dstwo = dsone*2; if (mobj->target->player->kartstuff[k_driftcharge] < dsone) { @@ -6594,7 +6627,7 @@ void P_MobjThinker(mobj_t *mobj) return; } - if (mobj->target->player->kartstuff[k_bootimer] > 0) + if (mobj->target->player->kartstuff[k_hyudorotimer] > 0) { if (splitscreen) { @@ -6603,7 +6636,7 @@ void P_MobjThinker(mobj_t *mobj) else mobj->flags2 &= ~MF2_DONTDRAW; - if (mobj->target->player->kartstuff[k_bootimer] >= (1*TICRATE/2) && mobj->target->player->kartstuff[k_bootimer] <= bootime-(1*TICRATE/2)) + if (mobj->target->player->kartstuff[k_hyudorotimer] >= (1*TICRATE/2) && mobj->target->player->kartstuff[k_hyudorotimer] <= hyudorotime-(1*TICRATE/2)) { if (mobj->target->player == &players[secondarydisplayplayer]) mobj->eflags |= MFE_DRAWONLYFORP2; @@ -6621,7 +6654,7 @@ void P_MobjThinker(mobj_t *mobj) { if (mobj->target->player == &players[displayplayer] || (mobj->target->player != &players[displayplayer] - && (mobj->target->player->kartstuff[k_bootimer] < (1*TICRATE/2) || mobj->target->player->kartstuff[k_bootimer] > bootime-(1*TICRATE/2)))) + && (mobj->target->player->kartstuff[k_hyudorotimer] < (1*TICRATE/2) || mobj->target->player->kartstuff[k_hyudorotimer] > hyudorotime-(1*TICRATE/2)))) { if (leveltime & 1) mobj->flags2 |= MF2_DONTDRAW; @@ -6632,7 +6665,7 @@ void P_MobjThinker(mobj_t *mobj) mobj->flags2 |= MF2_DONTDRAW; } } - else if (mobj->target->player->kartstuff[k_bootimer] == 0) + else if (mobj->target->player->kartstuff[k_hyudorotimer] == 0) { mobj->flags2 &= ~MF2_DONTDRAW; mobj->eflags &= ~(MFE_DRAWONLYFORP1|MFE_DRAWONLYFORP2|MFE_DRAWONLYFORP3|MFE_DRAWONLYFORP4); @@ -6652,15 +6685,15 @@ void P_MobjThinker(mobj_t *mobj) mobj->angle = ANGLE_180 + mobj->target->player->frameangle; // If the player is on the ceiling, then flip - if (mobj->target->player && mobj->target->eflags & MFE_VERTICALFLIP) + if (mobj->target->eflags & MFE_VERTICALFLIP) { mobj->eflags |= MFE_VERTICALFLIP; - HEIGHT = mobj->target->height; + HEIGHT = (16<eflags &= ~MFE_VERTICALFLIP; - HEIGHT = mobj->target->height-mobj->target->height; + HEIGHT = 0; } // Shrink if the player shrunk too. @@ -6671,7 +6704,7 @@ void P_MobjThinker(mobj_t *mobj) const angle_t fa = mobj->angle>>ANGLETOFINESHIFT; mobj->x = mobj->target->x + FixedMul(finecosine[fa],radius); mobj->y = mobj->target->y + FixedMul(finesine[fa],radius); - mobj->z = mobj->target->z + HEIGHT; + mobj->z = mobj->target->z - HEIGHT; P_SetThingPosition(mobj); } } @@ -6682,109 +6715,26 @@ void P_MobjThinker(mobj_t *mobj) } break; } - case MT_GREENSHIELD: - case MT_REDSHIELD: - case MT_BANANASHIELD: + case MT_ORBINAUT_SHIELD: // Kart orbit/trail items + case MT_JAWZ_SHIELD: + case MT_BANANA_SHIELD: + case MT_SSMINE_SHIELD: case MT_FAKESHIELD: - case MT_BOMBSHIELD: - case MT_TRIPLEGREENSHIELD1: - case MT_TRIPLEGREENSHIELD2: - case MT_TRIPLEGREENSHIELD3: - case MT_TRIPLEREDSHIELD1: - case MT_TRIPLEREDSHIELD2: - case MT_TRIPLEREDSHIELD3: - case MT_TRIPLEBANANASHIELD1: - case MT_TRIPLEBANANASHIELD2: - case MT_TRIPLEBANANASHIELD3: - if (mobj->health > 0 && mobj->target && mobj->target->player && mobj->target->player->mo + /*if (mobj->health > 0 && mobj->target && mobj->target->player && mobj->target->player->health > 0 && !mobj->target->player->spectator) { - fixed_t z; - const fixed_t radius = FixedHypot(mobj->target->radius, mobj->target->radius) + FixedHypot(mobj->radius, mobj->radius); // mobj's distance from its Target, or Radius. - - //mobj->angle += FixedAngle(12*FRACUNIT); // mobj's actual speed. - if (mobj->type == MT_TRIPLEGREENSHIELD1 || mobj->type == MT_TRIPLEGREENSHIELD2 || mobj->type == MT_TRIPLEGREENSHIELD3 - || mobj->type == MT_TRIPLEREDSHIELD1 || mobj->type == MT_TRIPLEREDSHIELD2 || mobj->type == MT_TRIPLEREDSHIELD3) - mobj->angle += FixedAngle(mobj->info->speed); - else if (mobj->type == MT_TRIPLEBANANASHIELD2) - mobj->angle = (mobj->target->angle + ANGLE_135); - else if (mobj->type == MT_TRIPLEBANANASHIELD3) - mobj->angle = (mobj->target->angle + ANGLE_225); - else - mobj->angle = (mobj->target->angle + ANGLE_180); - - // If the player is on the ceiling, then flip your items as well. - if (mobj->target->player && mobj->target->eflags & MFE_VERTICALFLIP) - { - mobj->eflags |= MFE_VERTICALFLIP; - } - else - { - mobj->eflags &= ~MFE_VERTICALFLIP; - } - - // Shrink your items if the player shrunk too. - if (mobj->target->player) - mobj->scale = mobj->target->scale; - - if (P_MobjFlip(mobj) > 0) - { - z = mobj->target->z; - } - else - { - z = mobj->target->z + mobj->target->height - mobj->height; - } - - mobj->flags |= MF_NOCLIPTHING; // temporarily make them noclip other objects so they can't hit anyone while in the player - P_TeleportMove(mobj, mobj->target->x, mobj->target->y, z); - mobj->momx = FixedMul(FINECOSINE(mobj->angle>>ANGLETOFINESHIFT),radius); - mobj->momy = FixedMul(FINESINE(mobj->angle>>ANGLETOFINESHIFT), radius); - mobj->flags &= ~MF_NOCLIPTHING; - if (!P_TryMove(mobj, mobj->target->x + mobj->momx, mobj->target->y + mobj->momy, true)) - P_SlideMove(mobj, true); - if (P_IsObjectOnGround(mobj->target)) - { - if (P_MobjFlip(mobj) > 0) - { - if (mobj->floorz > mobj->target->z - mobj->height) - { - z = mobj->floorz; - } - } - else - { - if (mobj->ceilingz < mobj->target->z + mobj->target->height + mobj->height) - { - z = mobj->ceilingz - mobj->height; - } - } - } - mobj->z = z; - mobj->momx = mobj->momy = 0; - - // Was this so hard? - if ((mobj->type == MT_GREENSHIELD && !(mobj->target->player->kartstuff[k_greenshell] & 1)) - || (mobj->type == MT_REDSHIELD && !(mobj->target->player->kartstuff[k_redshell] & 1)) - || (mobj->type == MT_BANANASHIELD && !(mobj->target->player->kartstuff[k_banana] & 1)) - || (mobj->type == MT_TRIPLEGREENSHIELD1 && !(mobj->target->player->kartstuff[k_triplegreenshell] & 1)) - || (mobj->type == MT_TRIPLEGREENSHIELD2 && !(mobj->target->player->kartstuff[k_triplegreenshell] & 2)) - || (mobj->type == MT_TRIPLEGREENSHIELD3 && !(mobj->target->player->kartstuff[k_triplegreenshell] & 4)) - || (mobj->type == MT_TRIPLEREDSHIELD1 && !(mobj->target->player->kartstuff[k_tripleredshell] & 1)) - || (mobj->type == MT_TRIPLEREDSHIELD2 && !(mobj->target->player->kartstuff[k_tripleredshell] & 2)) - || (mobj->type == MT_TRIPLEREDSHIELD3 && !(mobj->target->player->kartstuff[k_tripleredshell] & 4)) - || (mobj->type == MT_TRIPLEBANANASHIELD1 && !(mobj->target->player->kartstuff[k_triplebanana] & 1)) - || (mobj->type == MT_TRIPLEBANANASHIELD2 && !(mobj->target->player->kartstuff[k_triplebanana] & 2)) - || (mobj->type == MT_TRIPLEBANANASHIELD3 && !(mobj->target->player->kartstuff[k_triplebanana] & 4)) - || (mobj->type == MT_BOMBSHIELD && !(mobj->target->player->kartstuff[k_bobomb] & 1)) - || (mobj->type == MT_FAKESHIELD && !(mobj->target->player->kartstuff[k_fakeitem] & 1))) + // Was this so hard? -- Handled this with K_UpdateHnextList and K_ClearHnextList instead of thinking it away... + if ((mobj->type == MT_ORBINAUT_SHIELD && mobj->target->player->kartstuff[k_itemtype] != KITEM_ORBINAUT) + || (mobj->type == MT_JAWZ_SHIELD && mobj->target->player->kartstuff[k_itemtype] != KITEM_JAWZ) + || (mobj->movedir > 0 && ((UINT16)mobj->target->player->kartstuff[k_itemamount] < mobj->movedir)) + || (!mobj->target->player->kartstuff[k_itemheld])) { P_RemoveMobj(mobj); return; } } - else if ((mobj->health > 0 - && (!mobj->target || !mobj->target->player || !mobj->target->player->mo || mobj->target->player->health <= 0 || mobj->target->player->spectator)) + else*/ 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) || P_CheckDeathPitCollide(mobj)) // When in death state { @@ -6829,7 +6779,7 @@ void P_MobjThinker(mobj_t *mobj) } } break; - case MT_BATTLEBALLOON: + case MT_BATTLEBUMPER: if (mobj->health > 0 && mobj->target && mobj->target->player && mobj->target->player->health > 0 && !mobj->target->player->spectator) { @@ -6842,10 +6792,10 @@ void P_MobjThinker(mobj_t *mobj) else ang = FixedAngle(mobj->info->speed); - if (mobj->target->player->kartstuff[k_balloon] <= 1) + if (mobj->target->player->kartstuff[k_bumper] <= 1) diff = 0; else - diff = FixedAngle(360*FRACUNIT/mobj->target->player->kartstuff[k_balloon]); + diff = FixedAngle(360*FRACUNIT/mobj->target->player->kartstuff[k_bumper]); ang = (ang*leveltime) + (diff * (mobj->threshold-1)); @@ -6893,16 +6843,16 @@ void P_MobjThinker(mobj_t *mobj) if (mobj->tracer && mobj->tracer->player && mobj->tracer->player->mo && mobj->tracer->player->health > 0 && !mobj->tracer->player->spectator) // STOLEN - mobj->color = mobj->tracer->player->skincolor; // don't do star flashing for stolen balloons + mobj->color = mobj->tracer->player->skincolor; // don't do star flashing for stolen bumpers else mobj->color = mobj->target->color; // but do so if it belongs to you :B - if (mobj->target->player->kartstuff[k_balloon] < 2) - P_SetMobjState(mobj, S_BATTLEBALLOON3); - else if (mobj->target->player->kartstuff[k_balloon] < 3) - P_SetMobjState(mobj, S_BATTLEBALLOON2); + if (mobj->target->player->kartstuff[k_bumper] < 2) + P_SetMobjState(mobj, S_BATTLEBUMPER3); + else if (mobj->target->player->kartstuff[k_bumper] < 3) + P_SetMobjState(mobj, S_BATTLEBUMPER2); else - P_SetMobjState(mobj, S_BATTLEBALLOON1); + P_SetMobjState(mobj, S_BATTLEBUMPER1); // Shrink your items if the player shrunk too. mobj->scale = mobj->target->scale; @@ -6917,7 +6867,7 @@ void P_MobjThinker(mobj_t *mobj) } // Was this so hard? - if (mobj->target->player->kartstuff[k_balloon] <= mobj->threshold) + if (mobj->target->player->kartstuff[k_bumper] <= mobj->threshold) { P_RemoveMobj(mobj); return; @@ -6941,10 +6891,14 @@ void P_MobjThinker(mobj_t *mobj) fixed_t scale = mobj->target->scale; mobj->color = mobj->target->color; - if (!netgame || G_RaceGametype() + if (G_RaceGametype() || mobj->target->player == &players[displayplayer] - || mobj->target->player->kartstuff[k_balloon] <= 0 - || (mobj->target->player->mo->flags2 & MF2_DONTDRAW)) + || mobj->target->player->kartstuff[k_bumper] <= 0 + || (mobj->target->player->mo->flags2 & MF2_DONTDRAW) +#if 1 // Set to 0 to test without needing to host + || !netgame +#endif + ) mobj->flags2 |= MF2_DONTDRAW; else mobj->flags2 &= ~MF2_DONTDRAW; @@ -6965,42 +6919,194 @@ void P_MobjThinker(mobj_t *mobj) } P_SetThingPosition(mobj); - // Set it to use the correct states for its condition - if (mobj->target->player->kartstuff[k_itemroulette]) + scale += FixedMul(FixedDiv(abs(P_AproxDistance(players[displayplayer].mo->x-mobj->target->x, + players[displayplayer].mo->y-mobj->target->y)), RING_DIST), mobj->target->scale); + if (scale > 16*FRACUNIT) + scale = 16*FRACUNIT; + mobj->destscale = scale; + + if (!mobj->tracer) { - if (mobj->state != &states[S_PLAYERARROW_ROULETTE]) // don't reset FF_ANIMATE - P_SetMobjState(mobj, S_PLAYERARROW_ROULETTE); + mobj->tracer = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_OVERLAY); + P_SetTarget(&mobj->tracer->target, mobj); + P_SetMobjState(mobj->tracer, S_PLAYERARROW_ITEM); + P_SetScale(mobj->tracer, mobj->scale); } - else if (mobj->target->player->kartstuff[k_kitchensink]) P_SetMobjState(mobj, S_PLAYERARROW_KITCHENSINK); - else if (mobj->target->player->kartstuff[k_megashroom] == 1 - || (mobj->target->player->kartstuff[k_growshrinktimer] > 1 - && (leveltime & 1))) P_SetMobjState(mobj, S_PLAYERARROW_MEGASHROOM); - else if (mobj->target->player->kartstuff[k_growshrinktimer] > 1 - && !(leveltime & 1)) P_SetMobjState(mobj, S_PLAYERARROW_EMPTY); // S_INVISIBLE - else if (mobj->target->player->kartstuff[k_star] == 1) P_SetMobjState(mobj, S_PLAYERARROW_STAR); - else if (mobj->target->player->kartstuff[k_tripleredshell]) P_SetMobjState(mobj, S_PLAYERARROW_TRIPLEREDSHELL); - else if (mobj->target->player->kartstuff[k_triplebanana]) P_SetMobjState(mobj, S_PLAYERARROW_TRIPLEBANANA); - else if (mobj->target->player->kartstuff[k_triplegreenshell]) P_SetMobjState(mobj, S_PLAYERARROW_TRIPLEGREENSHELL); - else if (mobj->target->player->kartstuff[k_fireflower]) P_SetMobjState(mobj, S_PLAYERARROW_FIREFLOWER); - else if (mobj->target->player->kartstuff[k_bobomb]) P_SetMobjState(mobj, S_PLAYERARROW_BOBOMB); - else if (mobj->target->player->kartstuff[k_redshell]) P_SetMobjState(mobj, S_PLAYERARROW_REDSHELL); - else if (mobj->target->player->kartstuff[k_feather] & 1) P_SetMobjState(mobj, S_PLAYERARROW_FEATHER); - else if (mobj->target->player->kartstuff[k_boo] == 1) P_SetMobjState(mobj, S_PLAYERARROW_BOO); - else if (mobj->target->player->kartstuff[k_fakeitem] & 2) P_SetMobjState(mobj, S_PLAYERARROW_FAKEITEM); - else if (mobj->target->player->kartstuff[k_banana]) P_SetMobjState(mobj, S_PLAYERARROW_BANANA); - else if (mobj->target->player->kartstuff[k_greenshell]) P_SetMobjState(mobj, S_PLAYERARROW_GREENSHELL); - else if (mobj->target->player->kartstuff[k_mushroom]) P_SetMobjState(mobj, S_PLAYERARROW_MUSHROOM); - else if (mobj->target->player->kartstuff[k_mushroom] - && mobj->target->player->kartstuff[k_mushroomtimer] > 1 - && !(leveltime & 1)) P_SetMobjState(mobj, S_PLAYERARROW_EMPTY); // S_INVISIBLE - else P_SetMobjState(mobj, S_PLAYERARROW); // S_INVISIBLE + + if (!(mobj->flags2 & MF2_DONTDRAW)) + { + const INT32 numberdisplaymin = ((mobj->target->player->kartstuff[k_itemtype] == KITEM_ORBINAUT) ? 5 : 2); + + // Set it to use the correct states for its condition + if (mobj->target->player->kartstuff[k_itemroulette]) + { + P_SetMobjState(mobj, S_PLAYERARROW_BOX); + mobj->tracer->sprite = SPR_ITEM; + mobj->tracer->frame = FF_FULLBRIGHT|(((mobj->target->player->kartstuff[k_itemroulette] % (13*3)) / 3) + 1); + mobj->tracer->flags2 &= ~MF2_DONTDRAW; + } + else if (mobj->target->player->kartstuff[k_stolentimer] > 0) + { + P_SetMobjState(mobj, S_PLAYERARROW_BOX); + mobj->tracer->sprite = SPR_ITEM; + mobj->tracer->frame = FF_FULLBRIGHT|KITEM_HYUDORO; + if (leveltime & 2) + mobj->tracer->flags2 &= ~MF2_DONTDRAW; + else + mobj->tracer->flags2 |= MF2_DONTDRAW; + } + else if ((mobj->target->player->kartstuff[k_stealingtimer] > 0) && (leveltime & 2)) + { + P_SetMobjState(mobj, S_PLAYERARROW_BOX); + mobj->tracer->sprite = SPR_ITEM; + mobj->tracer->frame = FF_FULLBRIGHT|KITEM_HYUDORO; + mobj->tracer->flags2 &= ~MF2_DONTDRAW; + } + else if (mobj->target->player->kartstuff[k_eggmanexplode] > 1) + { + P_SetMobjState(mobj, S_PLAYERARROW_BOX); + mobj->tracer->sprite = SPR_ITEM; + mobj->tracer->frame = FF_FULLBRIGHT|KITEM_EGGMAN; + if (leveltime & 1) + mobj->tracer->flags2 &= ~MF2_DONTDRAW; + else + mobj->tracer->flags2 |= MF2_DONTDRAW; + } + else if (mobj->target->player->kartstuff[k_rocketsneakertimer] > 1) + { + //itembar = mobj->target->player->kartstuff[k_rocketsneakertimer]; -- not today satan + P_SetMobjState(mobj, S_PLAYERARROW_BOX); + mobj->tracer->sprite = SPR_ITEM; + mobj->tracer->frame = FF_FULLBRIGHT|KITEM_ROCKETSNEAKER; + if (leveltime & 1) + mobj->tracer->flags2 &= ~MF2_DONTDRAW; + else + mobj->tracer->flags2 |= MF2_DONTDRAW; + } + else if (mobj->target->player->kartstuff[k_growshrinktimer] > 0) + { + P_SetMobjState(mobj, S_PLAYERARROW_BOX); + mobj->tracer->sprite = SPR_ITEM; + mobj->tracer->frame = FF_FULLBRIGHT|KITEM_GROW; + + if (leveltime & 1) + mobj->tracer->flags2 &= ~MF2_DONTDRAW; + else + mobj->tracer->flags2 |= MF2_DONTDRAW; + } + else if (mobj->target->player->kartstuff[k_itemtype] && mobj->target->player->kartstuff[k_itemamount] > 0) + { + P_SetMobjState(mobj, S_PLAYERARROW_BOX); + + switch (mobj->target->player->kartstuff[k_itemtype]) + { + case KITEM_ORBINAUT: + mobj->tracer->sprite = SPR_ITMO; + mobj->tracer->frame = FF_FULLBRIGHT|(min(mobj->target->player->kartstuff[k_itemamount]-1, 3)); + break; + case KITEM_INVINCIBILITY: + mobj->tracer->sprite = SPR_ITMI; + mobj->tracer->frame = FF_FULLBRIGHT|((leveltime % (7*3)) / 3); + break; + case KITEM_SAD: + mobj->tracer->sprite = SPR_ITEM; + mobj->tracer->frame = FF_FULLBRIGHT; + break; + default: + mobj->tracer->sprite = SPR_ITEM; + mobj->tracer->frame = FF_FULLBRIGHT|(mobj->target->player->kartstuff[k_itemtype]); + break; + } + + mobj->tracer->flags2 &= ~MF2_DONTDRAW; + } + else + { + P_SetMobjState(mobj, S_PLAYERARROW); + P_SetMobjState(mobj->tracer, S_INVISIBLE); + } + + mobj->tracer->destscale = scale; + + if (mobj->target->player->kartstuff[k_itemamount] >= numberdisplaymin + && mobj->target->player->kartstuff[k_itemamount] < 10) // Meh, too difficult to support greater than this; convert this to a decent HUD object and then maybe :V + { + mobj_t *number = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_OVERLAY); + mobj_t *numx = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_OVERLAY); + + P_SetTarget(&number->target, mobj); + P_SetMobjState(number, S_PLAYERARROW_NUMBER); + P_SetScale(number, mobj->scale); + number->destscale = scale; + number->frame = FF_FULLBRIGHT|(mobj->target->player->kartstuff[k_itemamount]); + + P_SetTarget(&numx->target, mobj); + P_SetMobjState(numx, S_PLAYERARROW_X); + P_SetScale(numx, mobj->scale); + numx->destscale = scale; + } + + if (K_IsPlayerWanted(mobj->target->player) && mobj->movecount != 1) + { + mobj_t *wanted = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_PLAYERWANTED); + P_SetTarget(&wanted->target, mobj->target); + P_SetTarget(&wanted->tracer, mobj); + P_SetScale(wanted, mobj->scale); + wanted->destscale = scale; + mobj->movecount = 1; + } + else if (!K_IsPlayerWanted(mobj->target->player)) + mobj->movecount = 0; + } + else + mobj->tracer->flags2 |= MF2_DONTDRAW; + } + else if (mobj->health > 0) + { + P_KillMobj(mobj, NULL, NULL); + return; + } + break; + case MT_PLAYERWANTED: + if (mobj->target && mobj->target->health && mobj->tracer + && mobj->target->player && !mobj->target->player->spectator + && mobj->target->player->health && mobj->target->player->playerstate != PST_DEAD + && players[displayplayer].mo && !players[displayplayer].spectator) + { + fixed_t scale = mobj->target->scale; + + if (!K_IsPlayerWanted(mobj->target->player)) + { + mobj->tracer->movecount = 0; + P_RemoveMobj(mobj); + return; + } + + if (mobj->tracer->flags2 & MF2_DONTDRAW) + mobj->flags2 |= MF2_DONTDRAW; + else + mobj->flags2 &= ~MF2_DONTDRAW; + + P_UnsetThingPosition(mobj); + mobj->x = mobj->target->x; + mobj->y = mobj->target->y; + + if (!(mobj->target->eflags & MFE_VERTICALFLIP)) + { + mobj->z = mobj->target->z + (P_GetPlayerHeight(mobj->target->player)+16*FRACUNIT+(64*mobj->scale)); + mobj->eflags &= ~MFE_VERTICALFLIP; + } + else + { + mobj->z = mobj->target->z - (P_GetPlayerHeight(mobj->target->player)+16*FRACUNIT+(64*mobj->scale)); + mobj->eflags |= MFE_VERTICALFLIP; + } + P_SetThingPosition(mobj); scale += FixedMul(FixedDiv(abs(P_AproxDistance(players[displayplayer].mo->x-mobj->target->x, players[displayplayer].mo->y-mobj->target->y)), RING_DIST), mobj->target->scale); if (scale > 16*FRACUNIT) - { scale = 16*FRACUNIT; - } mobj->destscale = scale; } else if (mobj->health > 0) @@ -7229,7 +7335,7 @@ void P_MobjThinker(mobj_t *mobj) P_PushableThinker(mobj); // Extinguish fire objects in water. (Yes, it's extraordinarily rare to have a pushable flame object, but Brak uses such a case.) - if (mobj->flags & MF_FIRE && mobj->type != MT_PUMA //&& mobj->type != MT_FIREBALL + if (mobj->flags & MF_FIRE && mobj->type != MT_PUMA && mobj->type != MT_FIREBALL && (mobj->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER))) { P_KillMobj(mobj, NULL, NULL); @@ -7366,19 +7472,37 @@ void P_MobjThinker(mobj_t *mobj) } } else // Apply gravity to fall downwards. + { P_SetObjectMomZ(mobj, -2*FRACUNIT/3, true); + if (mobj->player) + mobj->player->frameangle -= ANGLE_22h; + } } break; //{ SRB2kart Items - Death States - case MT_GREENITEM: - case MT_REDITEM: - case MT_REDITEMDUD: - case MT_BANANAITEM: + case MT_ORBINAUT: + case MT_BANANA: case MT_FAKEITEM: if (mobj->z <= mobj->floorz) + { P_RemoveMobj(mobj); + return; + } + // fallthru + case MT_ORBINAUT_SHIELD: + case MT_BANANA_SHIELD: + case MT_FAKESHIELD: + mobj->flags2 ^= MF2_DONTDRAW; break; - case MT_BOMBITEM: + case MT_JAWZ: + case MT_JAWZ_DUD: + if (mobj->z <= mobj->floorz) + P_SetMobjState(mobj, mobj->info->xdeathstate); + // fallthru + case MT_JAWZ_SHIELD: + mobj->flags2 ^= MF2_DONTDRAW; + break; + case MT_SSMINE: case MT_BLUEEXPLOSION: if (mobj->health > -100) { @@ -7386,11 +7510,14 @@ void P_MobjThinker(mobj_t *mobj) mobj->health = -100; } else + { P_RemoveMobj(mobj); + return; + } break; - case MT_BOMBEXPLOSIONSOUND: + case MT_MINEEXPLOSIONSOUND: P_RemoveMobj(mobj); - break; + return; //} default: break; @@ -7876,7 +8003,7 @@ void P_MobjThinker(mobj_t *mobj) mobj->threshold = 0; } break; - case MT_GREENITEM: + case MT_ORBINAUT: { sector_t *sec2; fixed_t finalspeed = mobj->info->speed; @@ -7888,7 +8015,7 @@ void P_MobjThinker(mobj_t *mobj) else if (gamespeed == 2) finalspeed = FixedMul(finalspeed, FRACUNIT+FRACUNIT/4); - mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->x+mobj->momx, mobj->y+mobj->momy); + mobj->angle = R_PointToAngle2(0, 0, mobj->momx, mobj->momy); if (mobj->health <= 5) { INT32 i; @@ -7909,7 +8036,7 @@ void P_MobjThinker(mobj_t *mobj) if ((sec2 && GETSECSPECIAL(sec2->special, 3) == 1) || (P_IsObjectOnRealGround(mobj, mobj->subsector->sector) && GETSECSPECIAL(mobj->subsector->sector->special, 3) == 1)) - K_DoBouncePad(mobj, 0); + K_DoPogoSpring(mobj, 0, false); if (mobj->threshold > 0) mobj->threshold--; @@ -7918,7 +8045,7 @@ void P_MobjThinker(mobj_t *mobj) S_StartSound(mobj, mobj->info->activesound); break; } - case MT_REDITEM: + case MT_JAWZ: { sector_t *sec2; fixed_t topspeed = 64*FRACUNIT; @@ -7929,7 +8056,7 @@ void P_MobjThinker(mobj_t *mobj) if (mobj->threshold > 0) mobj->threshold--; - if (leveltime % 7 == 0) + if (leveltime % TICRATE == 0) S_StartSound(mobj, mobj->info->activesound); if (gamespeed == 0) @@ -7968,7 +8095,8 @@ void P_MobjThinker(mobj_t *mobj) mobj->friction = 0; } - P_InstaThrust(mobj, R_PointToAngle2(0, 0, mobj->momx, mobj->momy), topspeed); + mobj->angle = R_PointToAngle2(0, 0, mobj->momx, mobj->momy); + P_InstaThrust(mobj, mobj->angle, topspeed); if (mobj->tracer) mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->tracer->x, mobj->tracer->y); @@ -7981,33 +8109,33 @@ void P_MobjThinker(mobj_t *mobj) if ((sec2 && GETSECSPECIAL(sec2->special, 3) == 1) || (P_IsObjectOnRealGround(mobj, mobj->subsector->sector) && GETSECSPECIAL(mobj->subsector->sector->special, 3) == 1)) - K_DoBouncePad(mobj, 0); + K_DoPogoSpring(mobj, 0, false); break; } - case MT_REDITEMDUD: + case MT_JAWZ_DUD: { sector_t *sec2; P_SpawnGhostMobj(mobj); - mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->x+mobj->momx, mobj->y+mobj->momy); + mobj->angle = R_PointToAngle2(0, 0, mobj->momx, mobj->momy); P_InstaThrust(mobj, mobj->angle, mobj->info->speed); sec2 = P_ThingOnSpecial3DFloor(mobj); if ((sec2 && GETSECSPECIAL(sec2->special, 3) == 1) || (P_IsObjectOnRealGround(mobj, mobj->subsector->sector) && GETSECSPECIAL(mobj->subsector->sector->special, 3) == 1)) - K_DoBouncePad(mobj, 0); + K_DoPogoSpring(mobj, 0, false); if (mobj->threshold > 0) mobj->threshold--; - if (leveltime % 7 == 0) + if (leveltime % TICRATE == 0) S_StartSound(mobj, mobj->info->activesound); break; } - case MT_BANANAITEM: + case MT_BANANA: case MT_FAKEITEM: if (mobj->momx || mobj->momy) P_SpawnGhostMobj(mobj); @@ -8020,13 +8148,14 @@ void P_MobjThinker(mobj_t *mobj) if (mobj->threshold > 0) mobj->threshold--; break; - case MT_FIREBALL: - var1 = MT_FIRETRAIL; - A_SmokeTrailer(mobj); + case MT_BALLHOG: + P_SpawnGhostMobj(mobj)->fuse = 3; if (mobj->threshold > 0) mobj->threshold--; break; case MT_SINK: + if (mobj->momx || mobj->momy) + P_SpawnGhostMobj(mobj); if (mobj->z <= mobj->floorz) { S_StartSound(mobj, mobj->info->deathsound); @@ -8035,16 +8164,19 @@ void P_MobjThinker(mobj_t *mobj) if (mobj->threshold > 0) mobj->threshold--; break; - case MT_BOMBITEM: + case MT_SSMINE: + if (mobj->target && mobj->target->player) + mobj->color = mobj->target->player->skincolor; + else + mobj->color = SKINCOLOR_RED; if (mobj->momx || mobj->momy) P_SpawnGhostMobj(mobj); if (P_IsObjectOnGround(mobj)) { + 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->state == &states[S_BOMBAIR]) - P_SetMobjState(mobj, S_BOMBITEM); - mobj->momx = mobj->momy = 0; S_StartSound(mobj, mobj->info->activesound); mobj->reactiontime--; @@ -8056,13 +8188,16 @@ void P_MobjThinker(mobj_t *mobj) 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; case MT_BLUEEXPLOSION: mobj->health--; break; - case MT_BOMBEXPLOSION: + case MT_MINEEXPLOSION: if ((mobj->z < mobj->floorz - mobj->height) || (mobj->z > mobj->ceilingz + mobj->height)) { P_KillMobj(mobj, NULL, NULL); @@ -8085,11 +8220,119 @@ void P_MobjThinker(mobj_t *mobj) mobj->z += mobj->momz; P_SetThingPosition(mobj); return; - case MT_BOMBEXPLOSIONSOUND: + case MT_MINEEXPLOSIONSOUND: if (mobj->health == 100) S_StartSound(mobj, sfx_prloop); mobj->health--; break; + case MT_SPARKLETRAIL: + if (!mobj->target) + { + P_RemoveMobj(mobj); + return; + } + mobj->color = mobj->target->color; + mobj->colorized = mobj->target->colorized; + break; + case MT_INVULNFLASH: + if (!mobj->target || !mobj->target->health || (mobj->target->player && !mobj->target->player->kartstuff[k_invincibilitytimer])) + { + P_RemoveMobj(mobj); + return; + } + P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z); + break; + case MT_INSTASHIELDB: + if (leveltime & 1) + mobj->flags2 |= MF2_DONTDRAW; + else + mobj->flags2 &= ~MF2_DONTDRAW; + /* FALLTHRU */ + case MT_INSTASHIELDA: + if (!mobj->target || !mobj->target->health || (mobj->target->player && !mobj->target->player->kartstuff[k_instashield])) + { + P_RemoveMobj(mobj); + return; + } + P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z); + break; + case MT_THUNDERSHIELD: + if (!mobj->target || !mobj->target->health || (mobj->target->player && mobj->target->player->kartstuff[k_curshield] != 1)) + { + P_RemoveMobj(mobj); + return; + } + P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z); + break; + case MT_KARMAHITBOX: + if (!mobj->target || !mobj->target->health || !mobj->target->player || mobj->target->player->spectator + || (G_RaceGametype() || mobj->target->player->kartstuff[k_bumper])) + { + P_RemoveMobj(mobj); + return; + } + + P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z); + mobj->scalespeed = mobj->target->scalespeed; + mobj->destscale = mobj->target->destscale; + P_SetScale(mobj, mobj->target->scale); + mobj->color = mobj->target->color; + mobj->colorized = (mobj->target->player->kartstuff[k_comebackmode] == 1); + + if (mobj->target->player->kartstuff[k_comebacktimer] > 0) + { + if (mobj->state != &states[mobj->info->spawnstate]) + P_SetMobjState(mobj, mobj->info->spawnstate); + + if (mobj->target->player->kartstuff[k_comebacktimer] < TICRATE && (leveltime & 1)) + mobj->flags2 &= ~MF2_DONTDRAW; + else + mobj->flags2 |= MF2_DONTDRAW; + } + else + { + if (mobj->target->player->kartstuff[k_comebackmode] == 0 + && mobj->state != &states[mobj->info->spawnstate]) + P_SetMobjState(mobj, mobj->info->spawnstate); + else if (mobj->target->player->kartstuff[k_comebackmode] == 1 + && mobj->state != &states[mobj->info->seestate]) + P_SetMobjState(mobj, mobj->info->seestate); + + if (mobj->target->player->powers[pw_flashing] && (leveltime & 1)) + mobj->flags2 |= MF2_DONTDRAW; + else + mobj->flags2 &= ~MF2_DONTDRAW; + } + + // Now for the wheels + { + const fixed_t rad = FixedMul(mobjinfo[MT_PLAYER].radius, mobj->target->scale); + mobj_t *cur = mobj->hnext; + + while (cur && !P_MobjWasRemoved(cur)) + { + fixed_t offx = rad; + fixed_t offy = rad; + + if (cur->lastlook == 1 || cur->lastlook == 3) + offx *= -1; + if (cur->lastlook == 2 || cur->lastlook == 3) + offy *= -1; + + P_TeleportMove(cur, mobj->x + offx, mobj->y + offy, mobj->z); + cur->scalespeed = mobj->target->scalespeed; + cur->destscale = mobj->target->destscale; + P_SetScale(cur, mobj->target->scale); + + if (mobj->flags2 & MF2_DONTDRAW) + cur->flags2 |= MF2_DONTDRAW; + else + cur->flags2 &= ~MF2_DONTDRAW; + + cur = cur->hnext; + } + } + break; //} case MT_TURRET: P_MobjCheckWater(mobj); @@ -8150,7 +8393,7 @@ void P_MobjThinker(mobj_t *mobj) #endif break; case MT_SPINFIRE: - case MT_MUSHROOMTRAIL: + case MT_SNEAKERTRAIL: if (mobj->eflags & MFE_VERTICALFLIP) mobj->z = mobj->ceilingz - mobj->height; else @@ -8161,7 +8404,7 @@ void P_MobjThinker(mobj_t *mobj) P_MobjCheckWater(mobj); // Extinguish fire objects in water - if (mobj->flags & MF_FIRE && mobj->type != MT_PUMA //&& mobj->type != MT_FIREBALL + if (mobj->flags & MF_FIRE && mobj->type != MT_PUMA && mobj->type != MT_FIREBALL && (mobj->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER))) { P_KillMobj(mobj, NULL, NULL); @@ -8351,19 +8594,24 @@ for (i = ((mobj->flags2 & MF2_STRONGBOX) ? strongboxamt : weakboxamt); i; --i) s return; case MT_RANDOMITEM: if (G_BattleGametype()) - break; - - // Respawn from mapthing if you have one! - if (mobj->spawnpoint) { - P_SpawnMapThing(mobj->spawnpoint); - newmobj = mobj->spawnpoint->mobj; // this is set to the new mobj in P_SpawnMapThing + if (mobj->threshold != 69) + break; } else - newmobj = P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobj->type); + { + // Respawn from mapthing if you have one! + if (mobj->spawnpoint) + { + P_SpawnMapThing(mobj->spawnpoint); + newmobj = mobj->spawnpoint->mobj; // this is set to the new mobj in P_SpawnMapThing + } + else + newmobj = P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobj->type); - // Transfer flags2 (strongbox, objectflip) - newmobj->flags2 = mobj->flags2; + // Transfer flags2 (strongbox, objectflip) + newmobj->flags2 = mobj->flags2 & ~MF2_DONTDRAW; + } P_RemoveMobj(mobj); // make sure they disappear return; case MT_METALSONIC_BATTLE: @@ -8386,6 +8634,8 @@ for (i = ((mobj->flags2 & MF2_STRONGBOX) ? strongboxamt : weakboxamt); i; --i) s if (P_MobjWasRemoved(mobj)) return; } + else if (mobj->type == MT_RANDOMITEM && mobj->threshold == 69 && mobj->fuse <= TICRATE) + mobj->flags2 ^= MF2_DONTDRAW; } I_Assert(mobj != NULL); @@ -8850,6 +9100,39 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) case MT_BLUEBALL: nummaprings++; break; + case MT_KARMAHITBOX: // SRB2Kart + { + const fixed_t rad = FixedMul(mobjinfo[MT_PLAYER].radius, mobj->scale); + mobj_t *cur, *prev = mobj; + INT32 i; + + for (i = 0; i < 4; i++) + { + fixed_t offx = rad; + fixed_t offy = rad; + + if (i == 1 || i == 3) + offx *= -1; + if (i == 2 || i == 3) + offy *= -1; + + cur = P_SpawnMobj(mobj->x + offx, mobj->y + offy, mobj->z, MT_KARMAWHEEL); + cur->destscale = mobj->scale; + P_SetScale(cur, mobj->scale); + + cur->lastlook = i; + + P_SetTarget(&cur->hprev, prev); + P_SetTarget(&prev->hnext, cur); + + prev = cur; + } + } + break; + case MT_BIGRING: + mobj->destscale = 3*FRACUNIT; + P_SetScale(mobj, 3*FRACUNIT); + break; default: break; } @@ -8857,18 +9140,16 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) switch (mobj->type) { case MT_PLAYER: - case MT_BIGMACE: case MT_SMALLMACE: + case MT_BIGMACE: case MT_SMALLMACE: case MT_FALLINGROCK: //case MT_RANDOMITEM: - case MT_BANANAITEM: case MT_BANANASHIELD: - case MT_TRIPLEBANANASHIELD1: case MT_TRIPLEBANANASHIELD2: case MT_TRIPLEBANANASHIELD3: - case MT_GREENITEM: case MT_GREENSHIELD: - case MT_TRIPLEGREENSHIELD1: case MT_TRIPLEGREENSHIELD2: case MT_TRIPLEGREENSHIELD3: - case MT_REDITEM: case MT_REDSHIELD: case MT_REDITEMDUD: - case MT_TRIPLEREDSHIELD1: case MT_TRIPLEREDSHIELD2: case MT_TRIPLEREDSHIELD3: - case MT_BATTLEBALLOON: case MT_FIREBALL: - case MT_FAKEITEM: case MT_FAKESHIELD: - case MT_BOMBITEM: case MT_BOMBSHIELD: + case MT_BATTLEBUMPER: + case MT_BANANA: case MT_BANANA_SHIELD: + //case MT_FAKEITEM: case MT_FAKESHIELD: + case MT_ORBINAUT: case MT_ORBINAUT_SHIELD: + case MT_JAWZ: case MT_JAWZ_DUD: case MT_JAWZ_SHIELD: + case MT_SSMINE: case MT_SSMINE_SHIELD: + case MT_BALLHOG: case MT_SINK: P_SpawnShadowMobj(mobj); default: break; @@ -9125,6 +9406,18 @@ void P_RemoveMobj(mobj_t *mobj) iquetail = (iquetail+1)&(ITEMQUESIZE-1); } + if (mobj->type == MT_KARMAHITBOX) // Remove linked list objects for certain types + { + mobj_t *cur = mobj->hnext; + + while (cur && !P_MobjWasRemoved(cur)) + { + mobj_t *prev = cur; // Kind of a dumb var, but we need to set cur before we remove the mobj + cur = cur->hnext; + P_RemoveMobj(prev); + } + } + if (mobj->type == MT_OVERLAY) P_RemoveOverlay(mobj); @@ -9153,6 +9446,23 @@ void P_RemoveMobj(mobj_t *mobj) // Remove any references to other mobjs. P_SetTarget(&mobj->target, P_SetTarget(&mobj->tracer, NULL)); + // repair hnext chain + { + mobj_t *cachenext = mobj->hnext; + + if (mobj->hnext && !P_MobjWasRemoved(mobj->hnext)) + { + P_SetTarget(&mobj->hnext->hprev, mobj->hprev); + P_SetTarget(&mobj->hnext, NULL); + } + + if (mobj->hprev && !P_MobjWasRemoved(mobj->hprev)) + { + P_SetTarget(&mobj->hprev->hnext, cachenext); + P_SetTarget(&mobj->hprev, NULL); + } + } + // free block // DBG: set everything in mobj_t to 0xFF instead of leaving it. debug memory error. if (mobj->flags & MF_NOTHINK && !mobj->thinker.next) @@ -9231,7 +9541,7 @@ void P_RemoveSavegameMobj(mobj_t *mobj) } static CV_PossibleValue_t respawnitemtime_cons_t[] = {{1, "MIN"}, {300, "MAX"}, {0, NULL}}; -consvar_t cv_itemrespawntime = {"respawnitemtime", "1", CV_NETVAR|CV_CHEAT, respawnitemtime_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_itemrespawntime = {"respawnitemtime", "2", CV_NETVAR|CV_CHEAT, respawnitemtime_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_itemrespawn = {"respawnitem", "On", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; static CV_PossibleValue_t flagtime_cons_t[] = {{0, "MIN"}, {300, "MAX"}, {0, NULL}}; consvar_t cv_flagtime = {"flagtime", "30", CV_NETVAR|CV_CHEAT, flagtime_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -9466,17 +9776,23 @@ void P_RespawnSpecials(void) { P_SpawnMapThing(box->spawnpoint); newmobj = box->spawnpoint->mobj; // this is set to the new mobj in P_SpawnMapThing + P_SpawnMobj(box->spawnpoint->mobj->x, box->spawnpoint->mobj->y, box->spawnpoint->mobj->z, MT_EXPLODE); // poof into existance } else + { newmobj = P_SpawnMobj(box->x, box->y, box->z, box->type); + P_SpawnMobj(newmobj->x, newmobj->y, newmobj->z, MT_EXPLODE); // poof into existance + } // Transfer flags2 (strongbox, objectflip) newmobj->flags2 = box->flags2; P_RemoveMobj(box); // make sure they disappear - continue; + numgotboxes--; // you've restored a box, remove it from the count + //continue; -- irrelevant? } - numgotboxes = 0; + if (numgotboxes < 0) + numgotboxes = 0; } // only respawn items when cv_itemrespawn is on @@ -9577,25 +9893,33 @@ void P_RespawnSpecials(void) // void P_SpawnPlayer(INT32 playernum) { + UINT8 i, pcount = 0; player_t *p = &players[playernum]; mobj_t *mobj; - mobj_t *overheadarrow; if (p->playerstate == PST_REBORN) G_PlayerReborn(playernum); + for (i = 0; i < MAXPLAYERS; i++) + { + if (i == playernum) + continue; + if (!playeringame[i] || players[i].spectator) + continue; + pcount++; + } + // spawn as spectator determination if (!G_GametypeHasSpectators()) + p->spectator = false; + else if (netgame && p->jointime <= 1 && pcount) { - // Special case for (NiGHTS) special stages! - // if stage has already started, force players to become spectators until the next stage - /*if (multiplayer && netgame && G_IsSpecialStage(gamemap) && useNightsSS && leveltime > 0) - p->spectator = true; - else*/ - p->spectator = false; + p->spectator = true; + // Oni doesn't want this + /*if (pcount == 1 || leveltime < starttime) + p->pflags |= PF_WANTSTOJOIN; + p->jointime = 2;*/ } - else if (netgame && p->jointime < 1) - /*p->spectator = true*/; else if (multiplayer && !netgame) { // If you're in a team game and you don't have a team assigned yet... @@ -9661,65 +9985,59 @@ void P_SpawnPlayer(INT32 playernum) p->awayviewtics = 0; // set the scale to the mobj's destscale so settings get correctly set. if we don't, they sometimes don't. + if (cv_kartdebugshrink.value && !p->bot) + mobj->destscale = 6*mobj->destscale/8; P_SetScale(mobj, mobj->destscale); P_FlashPal(p, 0, 0); // Resets // Spawn with a pity shield if necessary. //P_DoPityCheck(p); - overheadarrow = P_SpawnMobj(mobj->x, mobj->y, mobj->z + P_GetPlayerHeight(p)+16*FRACUNIT, MT_PLAYERARROW); - P_SetTarget(&overheadarrow->target, mobj); - overheadarrow->flags2 |= MF2_DONTDRAW; - P_SetScale(overheadarrow, mobj->destscale); - - if (G_BattleGametype()) + if (G_BattleGametype()) // SRB2kart { - /*INT32 i; - INT32 pcount = 0; + mobj_t *overheadarrow = P_SpawnMobj(mobj->x, mobj->y, mobj->z + P_GetPlayerHeight(p)+16*FRACUNIT, MT_PLAYERARROW); + P_SetTarget(&overheadarrow->target, mobj); + overheadarrow->flags2 |= MF2_DONTDRAW; + P_SetScale(overheadarrow, mobj->destscale); - for (i = 0; i < MAXPLAYERS; i++) + if (p->spectator && pcount > 1) // HEY! No being cheap... + p->kartstuff[k_bumper] = 0; + else if (p->kartstuff[k_bumper] > 0 || leveltime < 1 + || (p->jointime <= 1 && pcount <= 1)) { - if (!playeringame[i] || players[i].spectator || &players[i] == p) - continue; - if (players[i].jointime > 0) - continue; - pcount++; - }*/ + if (leveltime < 1 || (p->jointime <= 1 && pcount <= 1)) // Start of the map? + p->kartstuff[k_bumper] = cv_kartbumpers.value; // Reset those bumpers! - if (p->kartstuff[k_balloon] > 0 || leveltime < 1/* || pcount <= 1*/) // srb2kart - { - INT32 i; - angle_t newangle; - angle_t diff; - fixed_t newx; - fixed_t newy; - mobj_t *mo; - - if (leveltime < 1 /*|| pcount <= 1*/) // Start of the map? - p->kartstuff[k_balloon] = cv_kartballoons.value; // Reset those balloons! - - if (p->kartstuff[k_balloon] <= 1) - diff = 0; - else - diff = FixedAngle(360*FRACUNIT/p->kartstuff[k_balloon]); - - newangle = mobj->angle; - newx = mobj->x + P_ReturnThrustX(mobj, newangle + ANGLE_180, 64*FRACUNIT); - newy = mobj->y + P_ReturnThrustY(mobj, newangle + ANGLE_180, 64*FRACUNIT); - - for (i = 0; i < p->kartstuff[k_balloon]; i++) + if (p->kartstuff[k_bumper]) { - mo = P_SpawnMobj(newx, newy, mobj->z, MT_BATTLEBALLOON); - mo->threshold = i; - P_SetTarget(&mo->target, mobj); - mo->angle = (diff * (i-1)); - mo->color = mobj->color; - if (mobj->flags2 & MF2_DONTDRAW) - mo->flags2 |= MF2_DONTDRAW; - else - mo->flags2 &= ~MF2_DONTDRAW; + INT32 i; + angle_t diff = FixedAngle(360*FRACUNIT/p->kartstuff[k_bumper]); + angle_t newangle = mobj->angle; + fixed_t newx = mobj->x + P_ReturnThrustX(mobj, newangle + ANGLE_180, 64*FRACUNIT); + fixed_t newy = mobj->y + P_ReturnThrustY(mobj, newangle + ANGLE_180, 64*FRACUNIT); + mobj_t *mo; + + for (i = 0; i < p->kartstuff[k_bumper]; i++) + { + mo = P_SpawnMobj(newx, newy, mobj->z, MT_BATTLEBUMPER); + mo->threshold = i; + P_SetTarget(&mo->target, mobj); + mo->angle = (diff * (i-1)); + mo->color = mobj->color; + if (mobj->flags2 & MF2_DONTDRAW) + mo->flags2 |= MF2_DONTDRAW; + else + mo->flags2 &= ~MF2_DONTDRAW; + } } } + else if (p->kartstuff[k_bumper] <= 0) + { + mobj_t *karmahitbox = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_KARMAHITBOX); // Player hitbox is too small!! + P_SetTarget(&karmahitbox->target, mobj); + karmahitbox->destscale = mobj->scale; + P_SetScale(karmahitbox, mobj->scale); + } } } @@ -9737,7 +10055,7 @@ void P_AfterPlayerSpawn(INT32 playernum) else if (playernum == fourthdisplayplayer) localangle4 = mobj->angle; - p->viewheight = cv_viewheight.value<viewheight = 32<mo->eflags & MFE_VERTICALFLIP) p->viewz = p->mo->z + p->mo->height - p->viewheight; @@ -9827,7 +10145,7 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing) z = ceiling - mobjinfo[MT_PLAYER].height; if (mthing->options >> ZSHIFT) z -= ((mthing->options >> ZSHIFT) << FRACBITS); - if (p->kartstuff[k_lakitu]) + if (p->kartstuff[k_respawn]) z -= 128*FRACUNIT; } else @@ -9835,7 +10153,7 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing) z = floor; if (mthing->options >> ZSHIFT) z += ((mthing->options >> ZSHIFT) << FRACBITS); - if (p->kartstuff[k_lakitu]) + if (p->kartstuff[k_respawn]) z += 128*FRACUNIT; } @@ -9897,7 +10215,7 @@ void P_MovePlayerToStarpost(INT32 playernum) #endif sector->ceilingheight; - z = (p->starpostz + 128) << FRACBITS; // Lakitu spawns you off the ground + z = (p->starpostz + 128) << FRACBITS; // Respawn off the ground if (z < floor) z = floor; else if (z > ceiling - mobjinfo[MT_PLAYER].height) diff --git a/src/p_mobj.h b/src/p_mobj.h index 0efda5cc..50645e4b 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -366,7 +366,7 @@ typedef struct mobj_s struct pslope_s *standingslope; // The slope that the object is standing on (shouldn't need synced in savegames, right?) #endif - boolean colorized; // Whether the mobj uses the starman colormap + boolean colorized; // Whether the mobj uses the rainbow colormap // WARNING: New fields must be added separately to savegame and Lua. } mobj_t; diff --git a/src/p_saveg.c b/src/p_saveg.c index 68191a58..fdbe4033 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -436,7 +436,7 @@ static void P_NetUnArchivePlayers(void) if (flags & AWAYVIEW) players[i].awayviewmobj = (mobj_t *)(size_t)READUINT32(save_p); - players[i].viewheight = cv_viewheight.value<numlaps); + else if (G_RaceGametype() && server) + CV_StealthSetValue(&cv_numlaps, + ((netgame || multiplayer) && cv_basenumlaps.value) + ? cv_basenumlaps.value + : mapheaderinfo[gamemap - 1]->numlaps); // =========== // landing point for netgames. @@ -2990,22 +2997,27 @@ boolean P_SetupLevel(boolean skipprecip) else { if (G_BattleGametype()) + { gamespeed = 0; - else - gamespeed = (UINT8)cv_kartspeed.value; - - if (G_BattleGametype()) mirrormode = false; + } else + { + gamespeed = (UINT8)cv_kartspeed.value; mirrormode = (boolean)cv_kartmirror.value; - + } franticitems = (boolean)cv_kartfrantic.value; comeback = (boolean)cv_kartcomeback.value; } - lightningcooldown = 0; - blueshellincoming = 0; - blueshellplayer = 0; + for (i = 0; i < 4; i++) + battlewanted[i] = -1; + + wantedcalcdelay = wantedfrequency*2; + indirectitemcooldown = 0; + spbincoming = 0; + spbplayer = 0; + mapreset = 0; // clear special respawning que iquehead = iquetail = 0; @@ -3025,7 +3037,7 @@ boolean P_SetupLevel(boolean skipprecip) // Remove the loading shit from the screen if (rendermode != render_none) - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (ranspecialwipe) ? 0 : 31); + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 120); if (precache || dedicated) R_PrecacheLevel(); @@ -3143,7 +3155,7 @@ boolean P_AddWadFile(const char *wadfilename, char **firstmapname) } else if (name[1] == '_') { - CONS_Debug(DBG_SETUP, "Music %.8s replaced\n", name); + CONS_Debug(DBG_SETUP, "Music %.8s ignored\n", name); mreplaces++; } } @@ -3164,7 +3176,7 @@ boolean P_AddWadFile(const char *wadfilename, char **firstmapname) if (!devparm && sreplaces) CONS_Printf(M_GetText("%s sounds replaced\n"), sizeu1(sreplaces)); if (!devparm && mreplaces) - CONS_Printf(M_GetText("%s midi musics replaced\n"), sizeu1(mreplaces)); + CONS_Printf(M_GetText("%s midi musics ignored\n"), sizeu1(mreplaces)); if (!devparm && digmreplaces) CONS_Printf(M_GetText("%s digital musics replaced\n"), sizeu1(digmreplaces)); diff --git a/src/p_spec.c b/src/p_spec.c index 7883a2ca..87894d05 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3753,22 +3753,46 @@ DoneSection2: // Process Section 3 switch (special) { - case 1: // SRB2kart: bounce pad + case 1: // SRB2kart: Spring Panel if (roversector || P_MobjReadyToTrigger(player->mo, sector)) { + const fixed_t scale = mapheaderinfo[gamemap-1]->mobj_scale + abs(player->mo->scale - mapheaderinfo[gamemap-1]->mobj_scale); + const fixed_t minspeed = 24*scale; + if (player->mo->eflags & MFE_SPRUNG) break; - if (player->speed < K_GetKartSpeed(player, true)/4) // Push forward to prevent getting stuck - P_InstaThrust(player->mo, player->mo->angle, FixedMul(K_GetKartSpeed(player, true)/4, player->mo->scale)); + if (player->speed < minspeed) // Push forward to prevent getting stuck + P_InstaThrust(player->mo, player->mo->angle, minspeed); - player->kartstuff[k_feather] |= 2; - K_DoBouncePad(player->mo, 0); + player->kartstuff[k_pogospring] = 1; + K_DoPogoSpring(player->mo, 0, false); } break; case 2: // Wind/Current - case 3: // Unused (was "Ice/Sludge and Wind/Current") + break; + + case 3: // SRB2kart: Spring Panel (capped speed) + if (roversector || P_MobjReadyToTrigger(player->mo, sector)) + { + const fixed_t scale = mapheaderinfo[gamemap-1]->mobj_scale + abs(player->mo->scale - mapheaderinfo[gamemap-1]->mobj_scale); + const fixed_t minspeed = 24*scale; + const fixed_t maxspeed = 36*scale; + + if (player->mo->eflags & MFE_SPRUNG) + break; + + if (player->speed > maxspeed) // Prevent overshooting jumps + P_InstaThrust(player->mo, R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy), maxspeed); + else if (player->speed < minspeed) // Push forward to prevent getting stuck + P_InstaThrust(player->mo, player->mo->angle, minspeed); + + player->kartstuff[k_pogospring] = 2; + K_DoPogoSpring(player->mo, 0, false); + } + break; + case 4: // Conveyor Belt break; @@ -3969,22 +3993,21 @@ DoneSection2: // P_SetPlayerMobjState(player->mo, S_PLAY_FALL1); break; - case 6: // SRB2kart 190117 - Mushroom Boost Panel + case 6: // SRB2kart 190117 - Sneaker Panel if (roversector || P_MobjReadyToTrigger(player->mo, sector)) { if (!player->kartstuff[k_floorboost]) player->kartstuff[k_floorboost] = 3; else player->kartstuff[k_floorboost] = 2; - K_DoMushroom(player, false); + K_DoSneaker(player, false); } break; case 7: // SRB2kart 190117 - Oil Slick if (roversector || P_MobjReadyToTrigger(player->mo, sector)) { - player->kartstuff[k_spinouttype] = -1; - K_SpinPlayer(player, NULL); + K_SpinPlayer(player, NULL, 0, false); } break; @@ -4184,11 +4207,12 @@ DoneSection2: if (P_IsLocalPlayer(player)) { - if (player->laps < (UINT8)(cv_numlaps.value - 1)) - S_StartSound(NULL, sfx_mlap); - else if (player->laps == (UINT8)(cv_numlaps.value - 1)) - S_StartSound(NULL, sfx_mlap); + if (player->laps == (UINT8)(cv_numlaps.value - 1)) + S_StartSound(NULL, sfx_s3k68); + else if (player->laps < (UINT8)(cv_numlaps.value - 1)) + S_StartSound(NULL, sfx_s221); } + // //player->starpostangle = player->starposttime = player->starpostnum = 0; //player->starpostx = player->starposty = player->starpostz = 0; @@ -4207,26 +4231,10 @@ DoneSection2: if (player->laps >= (unsigned)cv_numlaps.value) { - if (P_IsLocalPlayer(player)) - { - // SRB2kart 200117 - if (splitscreen) - S_ChangeMusicInternal("karwin", true); - else - { - if (player->kartstuff[k_position] == 1) - S_ChangeMusicInternal("karwin", true); - else if (K_IsPlayerLosing(player)) - S_ChangeMusicInternal("karlos", true); - else - S_ChangeMusicInternal("karok", true); - } - } - - if (player->kartstuff[k_position] == 1) + if (!splitscreen && P_IsLocalPlayer(player)) + S_StartSound(NULL, sfx_s3k6a); + else if (player->kartstuff[k_position] == 1) S_StartSound(NULL, sfx_s253); - else if (P_IsLocalPlayer(player)) - S_StartSound(NULL, sfx_s24f); P_DoPlayerExit(player); } @@ -7222,8 +7230,8 @@ void T_Friction(friction_t *f) // friction works for all mobj's // (or at least MF_PUSHABLEs, which is all I care about anyway) if ((!(thing->flags & (MF_NOGRAVITY | MF_NOCLIP)) && thing->z == thing->floorz) && (thing->player - && (thing->player->kartstuff[k_startimer] == 0 && thing->player->kartstuff[k_bootimer] == 0 - && thing->player->kartstuff[k_mushroomtimer] == 0 && thing->player->kartstuff[k_growshrinktimer] <= 0))) + && (thing->player->kartstuff[k_invincibilitytimer] == 0 && thing->player->kartstuff[k_hyudorotimer] == 0 + && thing->player->kartstuff[k_sneakertimer] == 0 && thing->player->kartstuff[k_growshrinktimer] <= 0))) { if (f->roverfriction) { @@ -7619,7 +7627,9 @@ void T_Pusher(pusher_t *p) if (thing->player && thing->player->pflags & PF_ROPEHANG) continue; - if (thing->player && (thing->state == &states[thing->info->painstate]) && (thing->player->powers[pw_flashing] > (K_GetKartFlashing()/4)*3 && thing->player->powers[pw_flashing] <= K_GetKartFlashing())) + if (thing->player && (thing->state == &states[thing->info->painstate]) + && (thing->player->powers[pw_flashing] > (K_GetKartFlashing(thing->player)/4)*3 + && thing->player->powers[pw_flashing] <= K_GetKartFlashing(thing->player))) continue; inFOF = touching = moved = false; @@ -7756,7 +7766,6 @@ void T_Pusher(pusher_t *p) thing->player->pflags |= PF_JUMPED; thing->player->pflags |= PF_SLIDING; - P_SetPlayerMobjState (thing, thing->info->painstate); // Whee! thing->angle = R_PointToAngle2 (0, 0, xspeed<<(FRACBITS-PUSH_FACTOR), yspeed<<(FRACBITS-PUSH_FACTOR)); if (!demoplayback || P_AnalogMove(thing->player)) diff --git a/src/p_tick.c b/src/p_tick.c index 8235e8d5..b9aaccf7 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -677,12 +677,12 @@ void P_Ticker(boolean run) if (countdown2) countdown2--; - if (blueshellincoming && --blueshellincoming <= 0) + if (spbincoming && --spbincoming <= 0) { UINT8 best = 0; SINT8 hurtthisguy = -1; - blueshellincoming = 0; + spbincoming = 0; for (i = 0; i < MAXPLAYERS; i++) { @@ -703,11 +703,20 @@ void P_Ticker(boolean run) } if (hurtthisguy != -1) - players[hurtthisguy].kartstuff[k_deathsentence] = TICRATE+1; + { + players[hurtthisguy].kartstuff[k_deathsentence] = (2*TICRATE)+1; + S_StartSound(players[hurtthisguy].mo, sfx_kc57); + } } - if (lightningcooldown) - lightningcooldown--; + if (indirectitemcooldown) + indirectitemcooldown--; + + if (G_BattleGametype()) + { + if (wantedcalcdelay && --wantedcalcdelay <= 0) + K_CalculateBattleWanted(); + } if (quake.time) { @@ -731,6 +740,11 @@ void P_Ticker(boolean run) G_ConsGhostTic(); if (modeattacking) G_GhostTicker(); + + if (mapreset > 1 + && --mapreset <= 1 + && server) // Remember: server uses it for mapchange, but EVERYONE ticks down for the animation + D_MapChange(gamemap, gametype, ultimatemode, true, 0, false, false); } P_MapEnd(); diff --git a/src/p_user.c b/src/p_user.c index f5ab500f..53faf8f3 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -218,7 +218,7 @@ void P_CalcHeight(player_t *player) //bob = FixedMul(player->bob/2, FINESINE(angle)); // move viewheight - player->viewheight = FixedMul(cv_viewheight.value << FRACBITS, mo->scale); // default eye view height + player->viewheight = FixedMul(32 << FRACBITS, mo->scale); // default eye view height /*if (player->playerstate == PST_LIVE) { @@ -406,6 +406,31 @@ UINT8 P_FindLowestLap(void) return lowest; } +// +// P_FindHighestLap +// +UINT8 P_FindHighestLap(void) +{ + INT32 i; + UINT8 highest = 0; + + if (!G_RaceGametype()) + return 0; + + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i] || players[i].spectator) + continue; + + if (players[i].laps > highest) + highest = players[i].laps; + } + + CONS_Debug(DBG_GAMELOGIC, "Highest laps found: %d\n", highest); + + return highest; +} + // // P_TransferToNextMare // @@ -636,9 +661,6 @@ static void P_DeNightserizePlayer(player_t *player) else if (player == &players[fourthdisplayplayer]) localaiming4 = 0; - // If you screwed up, kiss your score goodbye. - player->marescore = 0; - if (player->mo->tracer) P_RemoveMobj(player->mo->tracer); //P_SetPlayerMobjState(player->mo, S_PLAY_FALL1); // SRB2kart @@ -765,8 +787,6 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime) G_AddTempNightsRecords(players[i].marescore, leveltime - player->marebegunat, players[i].mare + 1);*/ // transfer scores anyway - players[i].lastmarescore = players[i].marescore; - players[i].marescore = 0; players[i].mo->health = players[i].health = 1; P_DoPlayerExit(&players[i]); @@ -788,8 +808,6 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime) G_AddTempNightsRecords(player->marescore, leveltime - player->marebegunat, (UINT8)(oldmare + 1));*/ // Starting a new mare, transfer scores - player->lastmarescore = player->marescore; - player->marescore = 0; player->marebegunat = leveltime; player->mo->health = player->health = 1; @@ -834,15 +852,19 @@ void P_DoPlayerPain(player_t *player, mobj_t *source, mobj_t *inflictor) angle_t ang; fixed_t fallbackspeed; - if (player->mo->eflags & MFE_VERTICALFLIP) - player->mo->z--; - else - player->mo->z++; + if (inflictor && (inflictor->type != MT_PLAYER && inflictor->type != MT_ORBINAUT && inflictor->type != MT_ORBINAUT_SHIELD + && inflictor->type != MT_JAWZ && inflictor->type != MT_JAWZ_DUD && inflictor->type != MT_JAWZ_SHIELD)) + { + 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); + 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); + } if (inflictor) { @@ -897,7 +919,7 @@ void P_DoPlayerPain(player_t *player, mobj_t *source, mobj_t *inflictor) P_ResetPlayer(player); P_SetPlayerMobjState(player->mo, player->mo->info->painstate); - player->powers[pw_flashing] = K_GetKartFlashing(); + player->powers[pw_flashing] = K_GetKartFlashing(player); if (player->timeshit != UINT8_MAX) ++player->timeshit; @@ -1039,11 +1061,10 @@ void P_DoSuperTransformation(player_t *player, boolean giverings) // Adds to the player's score void P_AddPlayerScore(player_t *player, UINT32 amount) { - UINT32 oldscore; + //UINT32 oldscore; -#if 1 - return; // Nope, still don't need this for Battle even -#endif + if (!(G_BattleGametype())) + return; if (player->bot) player = &players[consoleplayer]; @@ -1051,73 +1072,20 @@ void P_AddPlayerScore(player_t *player, UINT32 amount) if (player->exiting) // srb2kart return; - // NiGHTS does it different! - if (gamestate == GS_LEVEL && mapheaderinfo[gamemap-1]->typeoflevel & TOL_NIGHTS) - { - if ((netgame || multiplayer) && G_IsSpecialStage(gamemap)) - { // Pseudo-shared score for multiplayer special stages. - INT32 i; - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && players[i].pflags & PF_NIGHTSMODE) - { - oldscore = players[i].marescore; - - // Don't go above MAXSCORE. - if (players[i].marescore + amount < MAXSCORE) - players[i].marescore += amount; - else - players[i].marescore = MAXSCORE; - - // Continues are worthless in netgames. - // If that stops being the case uncomment this. -/* if (!ultimatemode && players[i].marescore > 50000 - && oldscore < 50000) - { - players[i].continues += 1; - players[i].gotcontinue = true; - if (P_IsLocalPlayer(player)) - S_StartSound(NULL, sfx_flgcap); - } */ - } - } - else - { - oldscore = player->marescore; - - // Don't go above MAXSCORE. - if (player->marescore + amount < MAXSCORE) - player->marescore += amount; - else - player->marescore = MAXSCORE; - - if (!ultimatemode && !(netgame || multiplayer) && G_IsSpecialStage(gamemap) - && player->marescore >= 50000 && oldscore < 50000) - { - player->continues += 1; - player->gotcontinue = true; - if (P_IsLocalPlayer(player)) - S_StartSound(NULL, sfx_flgcap); - } - } - - if (gametype == GT_COOP) - return; - } - - oldscore = player->score; + //oldscore = player->score; // Don't go above MAXSCORE. - if (player->score + amount < MAXSCORE) - player->score += amount; + if (player->marescore + amount < MAXSCORE) + player->marescore += amount; else - player->score = MAXSCORE; + player->marescore = MAXSCORE; // check for extra lives every 50000 pts - if (!ultimatemode && !modeattacking && player->score > oldscore && player->score % 50000 < amount && (gametype == GT_COMPETITION || gametype == GT_COOP)) + /*if (!ultimatemode && !modeattacking && player->score > oldscore && player->score % 50000 < amount && (gametype == GT_COMPETITION || gametype == GT_COOP)) { P_GivePlayerLives(player, (player->score/50000) - (oldscore/50000)); P_PlayLivesJingle(player); - } + }*/ // In team match, all awarded points are incremented to the team's running score. if (gametype == GT_TEAMMATCH) @@ -1150,6 +1118,84 @@ void P_PlayLivesJingle(player_t *player) } } +void P_PlayRinglossSound(mobj_t *source) +{ + sfxenum_t key = P_RandomKey(4); + if (cv_kartvoices.value) + S_StartSound(source, (mariomode) ? sfx_mario8 : sfx_altow1 + key); + else + S_StartSound(source, sfx_slip); +} + +void P_PlayDeathSound(mobj_t *source) +{ + sfxenum_t key = P_RandomKey(4); + if (cv_kartvoices.value) + S_StartSound(source, sfx_altdi1 + key); + else + S_StartSound(source, sfx_s3k35); +} + +void P_PlayVictorySound(mobj_t *source) +{ + sfxenum_t key = P_RandomKey(4); + if (cv_kartvoices.value) + S_StartSound(source, sfx_victr1 + key); +} + +// +// P_EndingMusic +// +// Consistently sets ending music! +// +boolean P_EndingMusic(player_t *player) +{ + char buffer[9]; + boolean looping = true; + + if (!P_IsLocalPlayer(player)) // Only applies to a local player + return false; + + // Event - Level Finish + if (splitscreen + && (players[displayplayer].exiting + || players[secondarydisplayplayer].exiting + || ((splitscreen < 2) && players[thirddisplayplayer].exiting) + || ((splitscreen < 3) && players[fourthdisplayplayer].exiting))) + { + sprintf(buffer, "k*ok"); + } + else if (player->pflags & PF_TIMEOVER) // || !player->lives) -- outta lives, outta time + { + sprintf(buffer, "k*lose"); + } + else if (player->exiting) + { + if (player->kartstuff[k_position] == 1) + sprintf(buffer, "k*win"); + else if (K_IsPlayerLosing(player)) + sprintf(buffer, "k*lose"); + else + sprintf(buffer, "k*ok"); + } + else + return false; + + S_SpeedMusic(1.0f); + + if (G_RaceGametype()) + buffer[1] = 'r'; + else if (G_BattleGametype()) + { + buffer[1] = 'b'; + looping = false; + } + + S_ChangeMusicInternal(buffer, looping); + + return true; +} + // // P_RestoreMusic // @@ -1160,43 +1206,37 @@ void P_RestoreMusic(player_t *player) if (!P_IsLocalPlayer(player)) // Only applies to a local player return; - if (player->powers[pw_extralife] > 1) + // Event - HERE COMES A NEW CHALLENGER + if (mapreset) + { + S_ChangeMusicInternal("chalng", false); //S_StopMusic(); return; + } + + // Event - Level Ending + if (P_EndingMusic(player)) + return; + S_SpeedMusic(1.0f); - // SRB2kart - We have some different powers than vanilla, some of which tweak the music. - if (splitscreen != 0 && G_RaceGametype() - && (players[consoleplayer].exiting - || players[secondarydisplayplayer].exiting - || players[thirddisplayplayer].exiting - || players[fourthdisplayplayer].exiting)) - S_ChangeMusicInternal("karwin", true); - else if (splitscreen == 0 && G_RaceGametype() && player->exiting) + // Event - Level Start + if (leveltime < (starttime + (TICRATE/2))) + S_ChangeMusicInternal("kstart", false); //S_StopMusic(); + else // see also where time overs are handled - search for "lives = 2" in this file { - if (player->kartstuff[k_position] == 1) - S_ChangeMusicInternal("karwin", true); - else if (K_IsPlayerLosing(player)) - S_ChangeMusicInternal("karlos", true); - else - S_ChangeMusicInternal("karok", true); - } - else - { - // Item - Mega Mushroom + // Item - Grow if (player->kartstuff[k_growshrinktimer] > 1 && player->playerstate == PST_LIVE) - S_ChangeMusicInternal("mega", true); - // Item - Star - else if (player->kartstuff[k_startimer] > 1 && player->playerstate == PST_LIVE) - S_ChangeMusicInternal("minvnc", false); - else if (leveltime > 157) + S_ChangeMusicInternal("kgrow", true); + // Item - Invincibility + else if (player->kartstuff[k_invincibilitytimer] > 1 && player->playerstate == PST_LIVE) + S_ChangeMusicInternal("kinvnc", true); + else { // Event - Final Lap if (G_RaceGametype() && player->laps >= (UINT8)(cv_numlaps.value - 1)) S_SpeedMusic(1.2f); S_ChangeMusic(mapmusname, mapmusflags, true); } - else - S_StopMusic(); } } @@ -1543,7 +1583,11 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj) ghost->color = mobj->color; ghost->colorized = mobj->colorized; // Kart: they should also be colorized if their origin is - ghost->angle = mobj->angle; + if (mobj->player) + ghost->angle = mobj->player->frameangle; + else + ghost->angle = mobj->angle; + ghost->sprite = mobj->sprite; ghost->frame = mobj->frame; ghost->tics = -1; @@ -1671,7 +1715,7 @@ void P_SpawnSpinMobj(player_t *player, mobjtype_t type) // Player exits the map via sector trigger void P_DoPlayerExit(player_t *player) { - if (player->exiting) + if (player->exiting || mapreset) return; if ((player == &players[consoleplayer] @@ -1689,8 +1733,7 @@ void P_DoPlayerExit(player_t *player) else if (!countdown) countdown = cv_countdowntime.value*TICRATE + 1; // Use cv_countdowntime - - if (circuitmap) + if (cv_kartvoices.value) { if (K_IsPlayerLosing(player)) S_StartSound(player->mo, sfx_klose); @@ -1698,34 +1741,23 @@ void P_DoPlayerExit(player_t *player) S_StartSound(player->mo, sfx_kwin); } - if (P_IsLocalPlayer(player) && cv_inttime.value > 0) - { - if (!splitscreen) - { - if (player->kartstuff[k_position] == 1) - S_ChangeMusicInternal("karwin", true); - else if (K_IsPlayerLosing(player)) - S_ChangeMusicInternal("karlos", true); - else - S_ChangeMusicInternal("karok", true); - } - else - S_ChangeMusicInternal("karok", true); - } - player->exiting = 3*TICRATE; + if (cv_inttime.value > 0) + P_EndingMusic(player); + // SRB2kart 120217 - if (!countdown2 && !(netgame || multiplayer)) - countdown2 = (66)*TICRATE + 1; // 6 seconds past the time over - else if (!countdown2) - countdown2 = (8 + cv_countdowntime.value)*TICRATE + 1; // 8 sec more than countdowntime -- 11 is too much + //if (!countdown2) + //countdown2 = countdown + 8*TICRATE; if (P_CheckRacers()) player->exiting = (14*TICRATE)/5 + 1; } - else if (G_BattleGametype()) - player->exiting = 8*TICRATE + 1; // Battle Mode exiting + else if (G_BattleGametype()) // Battle Mode exiting + { + player->exiting = 8*TICRATE + 1; + P_EndingMusic(player); + } else player->exiting = (14*TICRATE)/5 + 2; // Accidental death safeguard??? @@ -1741,7 +1773,6 @@ void P_DoPlayerExit(player_t *player) player->powers[pw_underwater] = 0; player->powers[pw_spacetime] = 0; player->kartstuff[k_cardanimation] = 0; // srb2kart: reset battle animation - P_RestoreMusic(player); /*if (playeringame[player-players] && netgame && !circuitmap) CONS_Printf(M_GetText("%s has completed the level.\n"), player_names[player-players]);*/ @@ -2164,6 +2195,7 @@ static void P_CheckQuicksand(player_t *player) // // Restores music from sneaker and life fanfares // +/* // SRB2kart - Can't drown. static void P_CheckSneakerAndLivesTimer(player_t *player) { if ((player->powers[pw_underwater] <= 11*TICRATE + 1) @@ -2176,12 +2208,14 @@ static void P_CheckSneakerAndLivesTimer(player_t *player) //if (player->powers[pw_sneakers] == 1) // SRB2kart // P_RestoreMusic(player); } +*/ // // P_CheckUnderwaterAndSpaceTimer // // Restores music from underwater and space warnings, and handles number generation // +/* // SRB2kart - Can't drown. static void P_CheckUnderwaterAndSpaceTimer(player_t *player) { fixed_t height; @@ -2290,7 +2324,7 @@ static void P_CheckUnderwaterAndSpaceTimer(player_t *player) player->powers[pw_spacetime] = 0; } -} +}*/ // // P_CheckInvincibilityTimer @@ -2299,20 +2333,20 @@ static void P_CheckUnderwaterAndSpaceTimer(player_t *player) // static void P_CheckInvincibilityTimer(player_t *player) { - if (!player->powers[pw_invulnerability] && !player->kartstuff[k_startimer]) + if (!player->powers[pw_invulnerability] && !player->kartstuff[k_invincibilitytimer]) return; //if (mariomode && !player->powers[pw_super]) // SRB2kart player->mo->color = (UINT8)(1 + (leveltime % (MAXSKINCOLORS-1))); - if (leveltime % (TICRATE/7) == 0) + /*if (leveltime % (TICRATE/7) == 0) { mobj_t *sparkle = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_IVSP); sparkle->destscale = player->mo->scale; P_SetScale(sparkle, player->mo->scale); - } + }*/ // Resume normal music stuff. - if (player->powers[pw_invulnerability] == 1 || player->kartstuff[k_startimer] == 1) + if (player->powers[pw_invulnerability] == 1 || player->kartstuff[k_invincibilitytimer] == 1) { if (!player->powers[pw_super]) { @@ -2334,11 +2368,11 @@ static void P_CheckInvincibilityTimer(player_t *player) P_SpawnShieldOrb(player); } - if ((player->powers[pw_underwater] <= 11*TICRATE + 1) + /*if ((player->powers[pw_underwater] <= 11*TICRATE + 1) && (player->powers[pw_underwater] > 1)) return; // don't restore music if drowning music is playing - if (!player->powers[pw_super] || (mapheaderinfo[gamemap-1]->levelflags & LF_NOSSMUSIC)) + if (!player->powers[pw_super] || (mapheaderinfo[gamemap-1]->levelflags & LF_NOSSMUSIC))*/ P_RestoreMusic(player); } } @@ -3562,10 +3596,10 @@ static void P_DoSuperStuff(player_t *player) 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) + /*if ((ALL7EMERALDS(emeralds) || ALL7EMERALDS(player->powers[pw_emeralds])) && player->health > 50) player->pflags |= PF_SUPERREADY; else - player->pflags &= ~PF_SUPERREADY; + player->pflags &= ~PF_SUPERREADY;*/ if (player->powers[pw_super]) { @@ -3691,7 +3725,7 @@ static void P_DoSuperStuff(player_t *player) // // Returns true if player is ready to turn super, duh // -boolean P_SuperReady(player_t *player) +/*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) @@ -3702,7 +3736,7 @@ boolean P_SuperReady(player_t *player) return true; return false; -} +}*/ // // P_DoJump @@ -4015,7 +4049,6 @@ static void P_DoSpinDash(player_t *player, ticcmd_t *cmd) // SRB2kart - unused. // void P_DoJumpShield(player_t *player) { - return; // SRB2kart - Would be useful for feathers, but those are impossible to balance, so nuts to it. if (player->pflags & PF_THOKKED) return; @@ -4704,21 +4737,23 @@ static void P_3dMovement(player_t *player) cmd = &player->cmd; - if (player->exiting || player->pflags & PF_STASIS || player->kartstuff[k_spinouttimer]) // pw_introcam? + if ((player->exiting || mapreset) || player->pflags & PF_STASIS || player->kartstuff[k_spinouttimer]) // pw_introcam? { cmd->forwardmove = cmd->sidemove = 0; + if (player->kartstuff[k_sneakertimer]) + cmd->forwardmove = 50; if (player->pflags & PF_GLIDING) { if (!player->skidtime) player->pflags &= ~PF_GLIDING; - else if (player->exiting) + else if (player->exiting || mapreset) { player->pflags &= ~PF_GLIDING; P_SetPlayerMobjState(player->mo, S_KART_WALK1); // SRB2kart - was S_PLAY_RUN1 player->skidtime = 0; } } - if (player->pflags & PF_SPINNING && !player->exiting) + if (player->pflags & PF_SPINNING && !(player->exiting || mapreset)) { player->pflags &= ~PF_SPINNING; P_SetPlayerMobjState(player->mo, S_KART_STND1); // SRB2kart - was S_PLAY_STND @@ -4797,13 +4832,13 @@ static void P_3dMovement(player_t *player) cmd->forwardmove = 0; // Do not let the player control movement if not onground. - // SRB2Kart: feather and speed bumps are supposed to control like you're on the ground - onground = (P_IsObjectOnGround(player->mo) || (player->kartstuff[k_feather] & 2)); + // SRB2Kart: pogo spring and speed bumps are supposed to control like you're on the ground + onground = (P_IsObjectOnGround(player->mo) || (player->kartstuff[k_pogospring])); player->aiming = cmd->aiming<exiting || (P_PlayerInPain(player) && !onground))) + if (!((player->exiting || mapreset) || (P_PlayerInPain(player) && !onground))) { //movepushforward = cmd->forwardmove * (thrustfactor * acceleration); movepushforward = K_3dKartMovement(player, onground, cmd->forwardmove); @@ -4821,6 +4856,15 @@ static void P_3dMovement(player_t *player) if (cmd->buttons & BT_BRAKE && !cmd->forwardmove) // SRB2kart - braking isn't instant movepushforward /= 64; + if (cmd->forwardmove > 0) + player->kartstuff[k_brakestop] = 0; + else if (player->kartstuff[k_brakestop] < 6) // Don't start reversing with brakes until you've made a stop first + { + if (player->speed < 8*FRACUNIT) + player->kartstuff[k_brakestop]++; + movepushforward = 0; + } + #ifdef ESLOPE totalthrust.x += P_ReturnThrustX(player->mo, movepushangle, movepushforward); totalthrust.y += P_ReturnThrustY(player->mo, movepushangle, movepushforward); @@ -4834,7 +4878,7 @@ static void P_3dMovement(player_t *player) } // Sideways movement - if (cmd->sidemove != 0 && !(player->exiting || (P_PlayerInPain(player)))) + if (cmd->sidemove != 0 && !((player->exiting || mapreset) || player->kartstuff[k_spinouttimer])) { if (cmd->sidemove > 0) movepushside = (cmd->sidemove * FRACUNIT/128) + FixedDiv(player->speed, K_GetKartSpeed(player, true)); @@ -4885,7 +4929,7 @@ static void P_3dMovement(player_t *player) if (newMagnitude > K_GetKartSpeed(player, true)) //topspeed) { fixed_t tempmomx, tempmomy; - if (oldMagnitude > K_GetKartSpeed(player, true)) //topspeed) + if (oldMagnitude > K_GetKartSpeed(player, true) && onground) // SRB2Kart: onground check for air speed cap { if (newMagnitude > oldMagnitude) { @@ -5760,7 +5804,7 @@ static void P_NiGHTSMovement(player_t *player) } // Currently reeling from being hit. - if (player->powers[pw_flashing] > (2*K_GetKartFlashing())/3) + if (player->powers[pw_flashing] > (2*K_GetKartFlashing(player))/3) { { const angle_t fa = (FixedAngle(player->flyangle*FRACUNIT)>>ANGLETOFINESHIFT) & FINEMASK; @@ -6471,8 +6515,8 @@ static void P_MovePlayer(player_t *player) { player->pflags |= PF_FULLSTASIS; // If you're in stasis in tag, you don't drown. - if (player->powers[pw_underwater] <= 12*TICRATE + 1) - P_RestoreMusic(player); + /*if (player->powers[pw_underwater] <= 12*TICRATE + 1) + P_RestoreMusic(player);*/ player->powers[pw_underwater] = player->powers[pw_spacetime] = 0; } } @@ -6543,23 +6587,6 @@ static void P_MovePlayer(player_t *player) // MOVEMENT CODE // ////////////////////// - //{ SRB2kart slip net - - if (player->kartstuff[k_spinouttimer] > 0 && player->kartstuff[k_spinout] == 0) - { - K_SpinPlayer(player, NULL); // Here just for in-level oil spills now - } - // If you have one but not the other, we should get rid of the one we have - else if (player->kartstuff[k_spinouttimer] == 0 && player->kartstuff[k_spinout] > 0) - player->kartstuff[k_spinout] = 0; - - // If somehow the power has gotten larger than the timer, it should be lowered back to it - if (player->kartstuff[k_spinouttimer] > player->kartstuff[k_spinout]) - player->kartstuff[k_spinouttimer] = player->kartstuff[k_spinout]; - - //} - - if (twodlevel || player->mo->flags2 & MF2_TWOD) // 2d-level, so special control applies. P_2dMovement(player); else @@ -6615,18 +6642,28 @@ static void P_MovePlayer(player_t *player) if (player->mo->state != &states[S_KART_SQUISH]) P_SetPlayerMobjState(player->mo, S_KART_SQUISH); } - else if (player->kartstuff[k_spinouttimer] > 0) + else if (player->kartstuff[k_spinouttimer] > 0 || player->pflags & PF_SLIDING) { if (player->mo->state != &states[S_KART_SPIN]) P_SetPlayerMobjState(player->mo, S_KART_SPIN); player->frameangle -= ANGLE_22h; } - else if (player->kartstuff[k_spinouttimer] == 0 && player->kartstuff[k_squishedtimer] == 0) + else if (player->powers[pw_nocontrol] && player->pflags & PF_SKIDDOWN) + { + if (player->mo->state != &states[S_KART_SPIN]) + P_SetPlayerMobjState(player->mo, S_KART_SPIN); + + if (((player->powers[pw_nocontrol] + 5) % 20) < 10) + player->frameangle += ANGLE_11hh; + else + player->frameangle -= ANGLE_11hh; + } + else { K_KartMoveAnimation(player); - if (player->kartstuff[k_feather] & 2) + if (player->kartstuff[k_pogospring]) player->frameangle += ANGLE_22h; else player->frameangle = player->mo->angle; @@ -6922,9 +6959,15 @@ static void P_MovePlayer(player_t *player) //////////////////////////// // SRB2kart - Drifting smoke and fire - if (player->kartstuff[k_mushroomtimer] > 0 && onground && (leveltime & 1)) + if (player->kartstuff[k_sneakertimer] > 0 && onground && (leveltime & 1)) K_SpawnBoostTrail(player); + if (player->kartstuff[k_invincibilitytimer] > 0) + K_SpawnSparkleTrail(player->mo); + + if (player->kartstuff[k_wipeoutslow] > 1 && (leveltime & 1)) + K_SpawnWipeoutTrail(player->mo, false); + K_DriftDustHandling(player->mo); /* // SRB2kart - nadah @@ -7657,14 +7700,11 @@ void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius) P_DamageMobj(mo, inflictor, source, 1); //{ SRB2kart - if (mo->type == MT_GREENITEM || mo->type == MT_REDITEM || mo->type == MT_REDITEMDUD - || mo->type == MT_GREENSHIELD || mo->type == MT_REDSHIELD - || mo->type == MT_TRIPLEGREENSHIELD1 || mo->type == MT_TRIPLEGREENSHIELD2 || mo->type == MT_TRIPLEGREENSHIELD3 - || mo->type == MT_TRIPLEREDSHIELD1 || mo->type == MT_TRIPLEREDSHIELD2 || mo->type == MT_TRIPLEREDSHIELD3 - || mo->type == MT_BANANAITEM || mo->type == MT_BANANASHIELD - || mo->type == MT_TRIPLEBANANASHIELD1 || mo->type == MT_TRIPLEBANANASHIELD2 || mo->type == MT_TRIPLEBANANASHIELD3 + if (mo->type == MT_ORBINAUT || mo->type == MT_JAWZ || mo->type == MT_JAWZ_DUD + || mo->type == MT_ORBINAUT_SHIELD || mo->type == MT_JAWZ_SHIELD + || mo->type == MT_BANANA || mo->type == MT_BANANA_SHIELD || mo->type == MT_FAKEITEM || mo->type == MT_FAKESHIELD - || mo->type == MT_FIREBALL) + || mo->type == MT_BALLHOG) { if (mo->eflags & MFE_VERTICALFLIP) mo->z -= mo->height; @@ -7682,7 +7722,7 @@ void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius) continue; if (mo->type == MT_PLAYER) // Players wipe out in Kart - K_SpinPlayer(mo->player, source); + K_SpinPlayer(mo->player, source, 0, false); //} else P_DamageMobj(mo, inflictor, source, 1000); @@ -7852,44 +7892,34 @@ void P_FindEmerald(void) // static void P_DeathThink(player_t *player) { - ticcmd_t *cmd = &player->cmd; + //ticcmd_t *cmd = &player->cmd; //player->deltaviewheight = 0; if (player->deadtimer < INT32_MAX) player->deadtimer++; // continue logic - if (!(netgame || multiplayer) && player->lives <= 0) + /*if (!(netgame || multiplayer) && player->lives <= 0) { if (player->deadtimer > TICRATE && (cmd->buttons & BT_BRAKE || cmd->buttons & BT_ACCELERATE || cmd->buttons & BT_DRIFT) && player->continues > 0) G_UseContinue(); else if (player->deadtimer >= gameovertics) G_UseContinue(); // Even if we don't have one this handles ending the game - } + }*/ // Force respawn if idle for more than 30 seconds in shooter modes. - if (player->deadtimer > 30*TICRATE && !G_RaceGametype()) + /*if (player->deadtimer > 30*TICRATE && !G_RaceGametype()) player->playerstate = PST_REBORN; - else if (player->lives > 0 && !G_IsSpecialStage(gamemap) && leveltime >= 140) // Don't allow "click to respawn" in special stages! + else if (player->lives > 0 && !G_IsSpecialStage(gamemap)*/ + if (player->lives > 0 && leveltime >= starttime) // *could* you respawn? { - // SRB2kart-- But wait, why'd we add this? :eggthinking: - /*if (player->spectator) - { - CONS_Printf("%s entered the game.\n", player_names[player-players]); - player->spectator = false; - }*/ - - //player->kartstuff[k_lakitu] = 48; // See G_PlayerReborn in g_game.c - // SRB2kart - spawn automatically after 1 second - if (player->deadtimer > cv_respawntime.value*TICRATE) - player->playerstate = PST_REBORN; - - // Single player auto respawn - if (!(netgame || multiplayer) && player->deadtimer > 5*TICRATE) - player->playerstate = PST_REBORN; + if (player->deadtimer > ((netgame || multiplayer) + ? cv_respawntime.value*TICRATE + : TICRATE)) // don't let them change it in record attack + player->playerstate = PST_REBORN; } - else if ((netgame || multiplayer) && player->deadtimer == 8*TICRATE) + /*else if ((netgame || multiplayer) && player->deadtimer == 8*TICRATE) { // In a net/multiplayer game, and out of lives if (gametype == GT_COMPETITION) @@ -7925,13 +7955,11 @@ static void P_DeathThink(player_t *player) countdown2 = 1*TICRATE; skipstats = true; - /* // SRB2kart 010217 - Score doesn't need to be reset in Kart. for (i = 0; i < MAXPLAYERS; i++) { if (playeringame[i]) players[i].score = 0; } - */ //emeralds = 0; tokenbits = 0; @@ -7939,14 +7967,14 @@ static void P_DeathThink(player_t *player) token = 0; } } - } + }*/ // Keep time rolling - if (!(countdown2 && !countdown) && !player->exiting && !(player->pflags & PF_TIMEOVER)) + if (!(countdown2 && !countdown) && !(player->exiting || mapreset) && !(player->pflags & PF_TIMEOVER)) { - if (leveltime >= 4*TICRATE) + if (leveltime >= starttime) { - player->realtime = leveltime - 4*TICRATE; + player->realtime = leveltime - starttime; if (player == &players[consoleplayer]) { if (player->spectator || !circuitmap) @@ -7963,8 +7991,12 @@ static void P_DeathThink(player_t *player) } } - if ((G_RaceGametype() || (gametype == GT_COOP && (multiplayer || netgame))) && (player->lives <= 0)) + /*if (G_RaceGametype() && (player->lives <= 0)) { + // to the lose music! + if (player->deadtimer == 4*TICRATE) + P_EndingMusic(player); + // stuff below isn't for kart // Return to level music if (netgame) { @@ -8001,7 +8033,7 @@ static void P_DeathThink(player_t *player) } } } - } + }*/ if (!player->mo) return; @@ -8106,9 +8138,9 @@ void P_ResetCamera(player_t *player, camera_t *thiscam) x = player->mo->x - P_ReturnThrustX(player->mo, thiscam->angle, player->mo->radius); y = player->mo->y - P_ReturnThrustY(player->mo, thiscam->angle, player->mo->radius); if (player->mo->eflags & MFE_VERTICALFLIP) - z = player->mo->z + player->mo->height - (cv_viewheight.value<mo->z + player->mo->height - (32<mo->z + (cv_viewheight.value<mo->z + (32<x = x; @@ -8143,10 +8175,13 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall subsector_t *newsubsec; fixed_t f1, f2; - if (player->exiting) // SRB2Kart: Leave the camera behind while exiting, for dramatic effect! - return true; - - cameranoclip = (player->pflags & (PF_NOCLIP|PF_NIGHTSMODE)) || (player->mo->flags & (MF_NOCLIP|MF_NOCLIPHEIGHT)); // Noclipping player camera noclips too!! +#ifdef NOCLIPCAM + cameranoclip = true; // We like camera noclip! +#else + cameranoclip = ((player->pflags & (PF_NOCLIP|PF_NIGHTSMODE)) + || (player->mo->flags & (MF_NOCLIP|MF_NOCLIPHEIGHT)) // Noclipping player camera noclips too!! + || (leveltime < introtime)); // Kart intro cam +#endif if (!(player->climbing || (player->pflags & PF_NIGHTSMODE) || player->playerstate == PST_DEAD)) { @@ -8188,6 +8223,11 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall camrotate = cv_cam4_rotate.value; else camrotate = 0; + if (leveltime < introtime) // Whoooshy camera! + { + const INT32 introcam = (introtime - leveltime); + camrotate += introcam*5; + } thiscam->angle = focusangle + FixedAngle(camrotate*FRACUNIT); P_ResetCamera(player, thiscam); return true; @@ -8280,8 +8320,16 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall lookback = camspin4; } - // SRB2kart - Camera flipper - if (lookback) + if (leveltime < introtime) // Whoooshy camera! + { + const INT32 introcam = (introtime - leveltime); + camrotate += introcam*5; + camdist += (introcam * mapheaderinfo[gamemap-1]->mobj_scale)*3; + camheight += (introcam * mapheaderinfo[gamemap-1]->mobj_scale)*2; + } + else if (player->exiting) // SRB2Kart: Leave the camera behind while exiting, for dramatic effect! + camstill = true; + else if (lookback) // SRB2kart - Camera flipper { camrotate += 180; camspeed *= 2; @@ -8321,7 +8369,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall } else if (P_AnalogMove(player)) // Analog angle = R_PointToAngle2(thiscam->x, thiscam->y, mo->x, mo->y); - else if (demoplayback) + else if (demoplayback && leveltime > starttime) { angle = focusangle; focusangle = R_PointToAngle2(thiscam->x, thiscam->y, mo->x, mo->y); @@ -8336,7 +8384,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall else angle = focusangle + FixedAngle(camrotate*FRACUNIT); - if (!resetcalled && (cv_analog.value || demoplayback) + if (!resetcalled && (leveltime > starttime) && (cv_analog.value || demoplayback) && ((thiscam == &camera && t_cam_rotate != -42) || (thiscam == &camera2 && t_cam2_rotate != -42) || (thiscam == &camera3 && t_cam3_rotate != -42) @@ -8453,7 +8501,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall } #endif // bad 2D camera code - pviewheight = FixedMul(cv_viewheight.value<scale); + pviewheight = FixedMul(32<scale); if (mo->eflags & MFE_VERTICALFLIP) z = mo->z + mo->height - pviewheight - camheight; @@ -8689,27 +8737,36 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall } }*/ - if (twodlevel || (mo->flags2 & MF2_TWOD)) + if (player->exiting) { - thiscam->momx = x-thiscam->x; - thiscam->momy = y-thiscam->y; - thiscam->momz = z-thiscam->z; + thiscam->momx = 0; + thiscam->momy = 0; + thiscam->momz = 0; } else { - thiscam->momx = FixedMul(x - thiscam->x, camspeed); - thiscam->momy = FixedMul(y - thiscam->y, camspeed); - - if ((GETSECSPECIAL(thiscam->subsector->sector->special, 1) == 6 - && thiscam->z < thiscam->subsector->sector->floorheight + 256*FRACUNIT - && FixedMul(z - thiscam->z, camspeed) < 0) -#if 0 - || player->kartstuff[k_feather] & 2 // SRB2Kart: don't follow while bouncing, experimental -#endif - ) - thiscam->momz = 0; // Don't go down a death pit + if (twodlevel || (mo->flags2 & MF2_TWOD)) + { + thiscam->momx = x-thiscam->x; + thiscam->momy = y-thiscam->y; + thiscam->momz = z-thiscam->z; + } else - thiscam->momz = FixedMul(z - thiscam->z, camspeed); + { + thiscam->momx = FixedMul(x - thiscam->x, camspeed); + thiscam->momy = FixedMul(y - thiscam->y, camspeed); + + if ((GETSECSPECIAL(thiscam->subsector->sector->special, 1) == 6 + && thiscam->z < thiscam->subsector->sector->floorheight + 256*FRACUNIT + && FixedMul(z - thiscam->z, camspeed) < 0) +#if 0 + || player->kartstuff[k_pogospring] // SRB2Kart: don't follow while bouncing, experimental +#endif + ) + thiscam->momz = 0; // Don't go down a death pit + else + thiscam->momz = FixedMul(z - thiscam->z, camspeed); + } } // compute aming to look the viewed point @@ -8792,20 +8849,13 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall boolean P_SpectatorJoinGame(player_t *player) { - if (!G_GametypeHasSpectators() && G_IsSpecialStage(gamemap) && useNightsSS) // Special Stage spectators should NEVER be allowed to rejoin the game - { - if (P_IsLocalPlayer(player)) - CONS_Printf(M_GetText("You cannot enter the game while a special stage is in progress.\n")); - player->powers[pw_flashing] += 2*TICRATE; //to prevent message spam. - } - - else if (!cv_allowteamchange.value) + // Team changing isn't allowed. + if (!cv_allowteamchange.value) { if (P_IsLocalPlayer(player)) CONS_Printf(M_GetText("Server does not allow team change.\n")); - player->powers[pw_flashing] += 2*TICRATE; //to prevent message spam. + //player->powers[pw_flashing] = TICRATE + 1; //to prevent message spam. } - // Team changing in Team Match and CTF // Pressing fire assigns you to a team that needs players if allowed. // Partial code reproduction from p_tick.c autobalance code. @@ -8842,6 +8892,7 @@ boolean P_SpectatorJoinGame(player_t *player) player->mo = NULL; } player->spectator = false; + player->pflags &= ~PF_WANTSTOJOIN; player->ctfteam = changeto; player->playerstate = PST_REBORN; @@ -8859,43 +8910,21 @@ boolean P_SpectatorJoinGame(player_t *player) // Joining in game from firing. else { - // Exception for hide and seek. Don't join a game when you simply - // respawn in place and sit there for the rest of the round. - if (!(gametype == GT_HIDEANDSEEK && leveltime > (hidetime * TICRATE))) + if (player->mo) { - if (player->mo) - { - P_RemoveMobj(player->mo); - player->mo = NULL; - } - player->spectator = false; - player->playerstate = PST_REBORN; - - if (gametype == GT_TAG) - { - //Make joining players "it" after hidetime. - if (leveltime > (hidetime * TICRATE)) - { - CONS_Printf(M_GetText("%s is now IT!\n"), player_names[player-players]); // Tell everyone who is it! - player->pflags |= PF_TAGIT; - } - - P_CheckSurvivors(); - } - - //Reset away view - if (P_IsLocalPlayer(player) && displayplayer != consoleplayer) - displayplayer = consoleplayer; - - CONS_Printf(M_GetText("%s entered the game.\n"), player_names[player-players]); - return true; // no more player->mo, cannot continue. - } - else - { - if (P_IsLocalPlayer(player)) - CONS_Printf(M_GetText("You must wait until next round to enter the game.\n")); - player->powers[pw_flashing] += 2*TICRATE; //to prevent message spam. + P_RemoveMobj(player->mo); + player->mo = NULL; } + player->spectator = false; + player->pflags &= ~PF_WANTSTOJOIN; + player->playerstate = PST_REBORN; + + //Reset away view + if (P_IsLocalPlayer(player) && displayplayer != consoleplayer) + displayplayer = consoleplayer; + + CONS_Printf(M_GetText("%s entered the game.\n"), player_names[player-players]); + return true; // no more player->mo, cannot continue. } return false; } @@ -9037,6 +9066,36 @@ static void P_CalcPostImg(player_t *player) } }*/ +void P_DoTimeOver(player_t *player) +{ + if (netgame && player->health > 0) + CONS_Printf(M_GetText("%s ran out of time.\n"), player_names[player-players]); + + player->pflags |= PF_TIMEOVER; + + if ((player == &players[consoleplayer] + || (splitscreen && player == &players[secondarydisplayplayer]) + || (splitscreen > 1 && player == &players[thirddisplayplayer]) + || (splitscreen > 2 && player == &players[fourthdisplayplayer])) + && !demoplayback) + legitimateexit = true; // SRB2kart: losing a race is still seeing it through to the end :p + + if (player->mo) + { + S_StopSound(player->mo); + P_DamageMobj(player->mo, NULL, NULL, 10000); + } + player->lives = 0; + + P_EndingMusic(player); + +#if 0 + // sal, when you do the f-zero explosion, this is how you make sure the map doesn't end before it's done ^u^ ~toast + if (!countdown2) + countdown2 = 5*TICRATE; +#endif +} + // // P_PlayerThink // @@ -9127,101 +9186,84 @@ void P_PlayerThink(player_t *player) I_Error("player %s is in PST_REBORN\n", sizeu1(playeri)); #endif - if (G_RaceGametype()) + if (!mapreset) { - INT32 i; - - // Check if all the players in the race have finished. If so, end the level. - for (i = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i] && !players[i].spectator) - { - if (!players[i].exiting && players[i].lives > 0) - break; - } - } - - if (i == MAXPLAYERS && player->exiting == 3*TICRATE) // finished - player->exiting = (14*TICRATE)/5 + 1; - - // If 10 seconds are left on the timer, - // begin the drown music for countdown! - /* - if (countdown == 11*TICRATE - 1) - { - if (P_IsLocalPlayer(player)) - S_ChangeMusicInternal("drown", false); - } - - // If you've hit the countdown and you haven't made - // it to the exit, you're a goner! - else */ - if (countdown == 1 && !player->exiting && !player->spectator && player->lives > 0) - { - if (netgame && player->health > 0) - CONS_Printf(M_GetText("%s ran out of time.\n"), player_names[player-players]); - - player->pflags |= PF_TIMEOVER; - - if ((player == &players[consoleplayer] - || (splitscreen && player == &players[secondarydisplayplayer]) - || (splitscreen > 1 && player == &players[thirddisplayplayer]) - || (splitscreen > 2 && player == &players[fourthdisplayplayer])) - && !demoplayback) - legitimateexit = true; // SRB2kart: losing a race is still seeing it through to the end :p - - if (player->pflags & PF_NIGHTSMODE) - { - P_DeNightserizePlayer(player); - S_StartScreamSound(player->mo, sfx_s3k66); - } - - player->lives = 2; // Don't start the game over music! - P_DamageMobj(player->mo, NULL, NULL, 10000); - player->lives = 0; - - if (player->playerstate == PST_DEAD) - return; - } - } - - // If it is set, start subtracting - // Don't allow it to go back to 0 - if (player->exiting > 1 && (player->exiting < 3*TICRATE || !G_RaceGametype())) // SRB2kart - "&& player->exiting > 1" - player->exiting--; - - if (player->exiting && countdown2) - player->exiting = 99; // SRB2kart - - if (player->exiting == 2 || countdown2 == 2) - { - if (cv_playersforexit.value) // Count to be sure everyone's exited + if (G_RaceGametype()) { INT32 i; + // Check if all the players in the race have finished. If so, end the level. for (i = 0; i < MAXPLAYERS; i++) { - if (!playeringame[i] || players[i].spectator || players[i].bot) - continue; - if (players[i].lives <= 0) - continue; - - if (!players[i].exiting || players[i].exiting > 3) - break; + if (playeringame[i] && !players[i].spectator) + { + if (!players[i].exiting && players[i].lives > 0) + break; + } } - if (i == MAXPLAYERS) + if (i == MAXPLAYERS && player->exiting == 3*TICRATE) // finished + player->exiting = (14*TICRATE)/5 + 1; + + // If 10 seconds are left on the timer, + // begin the drown music for countdown! + + // SRB2Kart: despite how perfect this is, it's disabled FOR A REASON + /*if (countdown == 11*TICRATE - 1) + { + if (P_IsLocalPlayer(player)) + S_ChangeMusicInternal("drown", false); + }*/ + + // If you've hit the countdown and you haven't made + // it to the exit, you're a goner! + else if (countdown == 1 && !player->exiting && !player->spectator && player->lives > 0) + { + P_DoTimeOver(player); + + if (player->playerstate == PST_DEAD) + return; + } + } + + // If it is set, start subtracting + // Don't allow it to go back to 0 + if (player->exiting > 1 && (player->exiting < 3*TICRATE || !G_RaceGametype())) // SRB2kart - "&& player->exiting > 1" + player->exiting--; + + if (player->exiting && countdown2) + player->exiting = 99; // SRB2kart + + if (player->exiting == 2 || countdown2 == 2) + { + if (cv_playersforexit.value) // Count to be sure everyone's exited + { + INT32 i; + + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i] || players[i].spectator || players[i].bot) + continue; + if (players[i].lives <= 0) + continue; + + if (!players[i].exiting || players[i].exiting > 3) + break; + } + + if (i == MAXPLAYERS) + { + if (server) + SendNetXCmd(XD_EXITLEVEL, NULL, 0); + } + else + player->exiting = 3; + } + else { if (server) SendNetXCmd(XD_EXITLEVEL, NULL, 0); } - else - player->exiting = 3; - } - else - { - if (server) - SendNetXCmd(XD_EXITLEVEL, NULL, 0); } } @@ -9259,18 +9301,22 @@ void P_PlayerThink(player_t *player) player->health = 1; } +#if 0 if ((netgame || multiplayer) && player->lives <= 0) { // In Co-Op, replenish a user's lives if they are depleted. // of course, this is just a cheap hack, meh... player->lives = cv_startinglives.value; } +#else + player->lives = 1; // SRB2Kart +#endif if (player == &players[displayplayer]) playerdeadview = false; // SRB2kart 010217 - if (leveltime < 4*TICRATE) + if (leveltime < starttime) player->powers[pw_nocontrol] = 2; /* if ((gametype == GT_RACE || gametype == GT_COMPETITION) && leveltime < 4*TICRATE) @@ -9284,9 +9330,9 @@ void P_PlayerThink(player_t *player) // Synchronizes the "real" amount of time spent in the level. if (!player->exiting) { - if (leveltime >= 4*TICRATE) + if (leveltime >= starttime) { - player->realtime = leveltime - 4*TICRATE; + player->realtime = leveltime - starttime; if (player == &players[consoleplayer]) { if (player->spectator || !circuitmap) @@ -9305,8 +9351,10 @@ void P_PlayerThink(player_t *player) if ((netgame || splitscreen) && player->spectator && cmd->buttons & BT_ATTACK && !player->powers[pw_flashing]) { - if (P_SpectatorJoinGame(player)) - return; // player->mo was removed. + player->pflags ^= PF_WANTSTOJOIN; + //player->powers[pw_flashing] = TICRATE + 1; + /*if (P_SpectatorJoinGame(player)) + return; // player->mo was removed.*/ } // Even if not NiGHTS, pull in nearby objects when walking around as John Q. Elliot. @@ -9393,16 +9441,16 @@ void P_PlayerThink(player_t *player) #endif //P_DoSuperStuff(player); - P_CheckSneakerAndLivesTimer(player); + //P_CheckSneakerAndLivesTimer(player); P_DoBubbleBreath(player); // Spawn Sonic's bubbles - P_CheckUnderwaterAndSpaceTimer(player); // Display the countdown drown numbers! + //P_CheckUnderwaterAndSpaceTimer(player); // Display the countdown drown numbers! P_CheckInvincibilityTimer(player); // Spawn Invincibility Sparkles P_DoPlayerHeadSigns(player); // Spawn Tag/CTF signs over player's head #if 1 // "Blur" a bit when you have speed shoes and are going fast enough if ((player->powers[pw_super] || player->powers[pw_sneakers] - || player->kartstuff[k_driftboost] || player->kartstuff[k_mushroomtimer]) && !player->kartstuff[k_startimer] // SRB2kart + || player->kartstuff[k_driftboost] || player->kartstuff[k_sneakertimer]) && !player->kartstuff[k_invincibilitytimer] // SRB2kart && (player->speed + abs(player->mo->momz)) > FixedMul(20*FRACUNIT,player->mo->scale)) { mobj_t *gmobj = P_SpawnGhostMobj(player->mo); @@ -9457,12 +9505,14 @@ void P_PlayerThink(player_t *player) if (player->powers[pw_invulnerability] && player->powers[pw_invulnerability] < UINT16_MAX) player->powers[pw_invulnerability]--; - if (player->powers[pw_flashing] && player->powers[pw_flashing] < UINT16_MAX && ((player->pflags & PF_NIGHTSMODE) || player->powers[pw_flashing] < K_GetKartFlashing())) + if (player->powers[pw_flashing] && player->powers[pw_flashing] < UINT16_MAX && ((player->pflags & PF_NIGHTSMODE) + || (player->spectator || player->powers[pw_flashing] < K_GetKartFlashing(player)))) player->powers[pw_flashing]--; if (player->powers[pw_tailsfly] && player->powers[pw_tailsfly] < UINT16_MAX && player->charability != CA_SWIM && !(player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds]))) // tails fly counter player->powers[pw_tailsfly]--; + /* // SRB2kart - Can't drown. if (player->powers[pw_underwater] && (player->pflags & PF_GODMODE || (player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL)) { if (player->powers[pw_underwater] <= 12*TICRATE+1) @@ -9477,6 +9527,7 @@ void P_PlayerThink(player_t *player) player->powers[pw_spacetime] = 0; else if (player->powers[pw_spacetime] && !(maptol & TOL_NIGHTS) && !((netgame || multiplayer) && player->spectator)) // underwater timer player->powers[pw_spacetime]--; + */ if (player->powers[pw_gravityboots] && player->powers[pw_gravityboots] < UINT16_MAX) player->powers[pw_gravityboots]--; @@ -9494,7 +9545,10 @@ void P_PlayerThink(player_t *player) player->powers[pw_nights_helper]--; if (player->powers[pw_nocontrol] & ((1<<15)-1) && player->powers[pw_nocontrol] < UINT16_MAX) - player->powers[pw_nocontrol]--; + { + if (!(--player->powers[pw_nocontrol])) + player->pflags &= ~PF_SKIDDOWN; + } else player->powers[pw_nocontrol] = 0; @@ -9542,21 +9596,17 @@ void P_PlayerThink(player_t *player) player->losstime--; // Flash player after being hit. - if (!(player->pflags & PF_NIGHTSMODE)) + if (!(player->pflags & PF_NIGHTSMODE + || player->kartstuff[k_hyudorotimer] // SRB2kart - fixes Hyudoro not flashing when it should. + || player->kartstuff[k_growshrinktimer] > 0 // Grow doesn't flash either. + || (G_BattleGametype() && player->kartstuff[k_bumper] <= 0 && player->kartstuff[k_comebacktimer]) + || leveltime < starttime)) // Level intro { - // SRB2kart - fixes boo not flashing when it should. Mega doesn't flash either. Flashing is local. - if ((player == &players[displayplayer] - || (splitscreen && player == &players[secondarydisplayplayer]) - || (splitscreen > 1 && player == &players[thirddisplayplayer]) - || (splitscreen > 2 && player == &players[fourthdisplayplayer])) - && player->kartstuff[k_bootimer] == 0 && player->kartstuff[k_growshrinktimer] <= 0 - && (player->kartstuff[k_comebacktimer] == 0 || (G_RaceGametype() || player->kartstuff[k_balloon] > 0))) - { - if (player->powers[pw_flashing] > 0 && player->powers[pw_flashing] < K_GetKartFlashing() && (leveltime & 1)) - player->mo->flags2 |= MF2_DONTDRAW; - else - player->mo->flags2 &= ~MF2_DONTDRAW; - } + if (player->powers[pw_flashing] > 0 && player->powers[pw_flashing] < K_GetKartFlashing(player) + && (leveltime & 1)) + player->mo->flags2 |= MF2_DONTDRAW; + else + player->mo->flags2 &= ~MF2_DONTDRAW; } else if (player->mo->tracer) { @@ -9938,7 +9988,7 @@ void P_PlayerAfterThink(player_t *player) { // defaults to make sure 1st person cam doesn't do anything weird on startup //player->deltaviewheight = 0; - player->viewheight = FixedMul(cv_viewheight.value << FRACBITS, player->mo->scale); + player->viewheight = FixedMul(32 << FRACBITS, player->mo->scale); if (player->mo->eflags & MFE_VERTICALFLIP) player->viewz = player->mo->z + player->mo->height - player->viewheight; else diff --git a/src/r_bsp.c b/src/r_bsp.c index 234d6ee0..56f159c2 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -855,7 +855,7 @@ static void R_AddPolyObjects(subsector_t *sub) drawseg_t *firstseg; -static void R_Subsector(size_t num, UINT8 ssplayer) +static void R_Subsector(size_t num, UINT8 viewnumber) { INT32 count, floorlightlevel, ceilinglightlevel, light; seg_t *line; @@ -1213,7 +1213,7 @@ static void R_Subsector(size_t num, UINT8 ssplayer) // Either you must pass the fake sector and handle validcount here, on the // real sector, or you must account for the lighting in some other way, // like passing it as an argument. - R_AddSprites(sub->sector, (floorlightlevel+ceilinglightlevel)/2, ssplayer); + R_AddSprites(sub->sector, (floorlightlevel+ceilinglightlevel)/2, viewnumber); firstseg = NULL; @@ -1419,7 +1419,7 @@ INT32 R_GetPlaneLight(sector_t *sector, fixed_t planeheight, boolean underside) // // killough 5/2/98: reformatted, removed tail recursion -void R_RenderBSPNode(INT32 bspnum, UINT8 ssplayer) +void R_RenderBSPNode(INT32 bspnum, UINT8 viewnumber) { node_t *bsp; INT32 side; @@ -1430,7 +1430,7 @@ void R_RenderBSPNode(INT32 bspnum, UINT8 ssplayer) // Decide which side the view point is on. side = R_PointOnSide(viewx, viewy, bsp); // Recursively divide front space. - R_RenderBSPNode(bsp->children[side], ssplayer); + R_RenderBSPNode(bsp->children[side], viewnumber); // Possibly divide back space. @@ -1448,5 +1448,5 @@ void R_RenderBSPNode(INT32 bspnum, UINT8 ssplayer) portalcullsector = NULL; } - R_Subsector(bspnum == -1 ? 0 : bspnum & ~NF_SUBSECTOR, ssplayer); + R_Subsector(bspnum == -1 ? 0 : bspnum & ~NF_SUBSECTOR, viewnumber); } diff --git a/src/r_bsp.h b/src/r_bsp.h index db340221..f493a8a6 100644 --- a/src/r_bsp.h +++ b/src/r_bsp.h @@ -37,7 +37,7 @@ extern INT32 doorclosed; void R_ClearClipSegs(void); void R_PortalClearClipSegs(INT32 start, INT32 end); void R_ClearDrawSegs(void); -void R_RenderBSPNode(INT32 bspnum, UINT8 ssplayer); +void R_RenderBSPNode(INT32 bspnum, UINT8 viewnumber); void R_AddPortal(INT32 line1, INT32 line2, INT32 x1, INT32 x2); #ifdef POLYOBJECTS diff --git a/src/r_data.c b/src/r_data.c index d19882dd..e1d4b893 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1087,7 +1087,7 @@ INT32 R_ColormapNumForName(char *name) extra_colormaps[num_extra_colormaps].fadecolor = 0x0; extra_colormaps[num_extra_colormaps].maskamt = 0x0; extra_colormaps[num_extra_colormaps].fadestart = 0; - extra_colormaps[num_extra_colormaps].fadeend = 33; + extra_colormaps[num_extra_colormaps].fadeend = 31; extra_colormaps[num_extra_colormaps].fog = 0; num_extra_colormaps++; @@ -1115,7 +1115,7 @@ INT32 R_CreateColormap(char *p1, char *p2, char *p3) size_t mapnum = num_extra_colormaps; size_t i; UINT32 cr, cg, cb, maskcolor, fadecolor; - UINT32 fadestart = 0, fadeend = 33, fadedist = 33; + UINT32 fadestart = 0, fadeend = 31, fadedist = 31; #define HEX2INT(x) (UINT32)(x >= '0' && x <= '9' ? x - '0' : x >= 'a' && x <= 'f' ? x - 'a' + 10 : x >= 'A' && x <= 'F' ? x - 'A' + 10 : 0) if (p1[0] == '#') @@ -1156,12 +1156,12 @@ INT32 R_CreateColormap(char *p1, char *p2, char *p3) // Get parameters like fadestart, fadeend, and the fogflag fadestart = NUMFROMCHAR(p2[3]) + (NUMFROMCHAR(p2[2]) * 10); fadeend = NUMFROMCHAR(p2[5]) + (NUMFROMCHAR(p2[4]) * 10); - if (fadestart > 32) + if (fadestart > 30) fadestart = 0; - if (fadeend > 33 || fadeend < 1) - fadeend = 33; + if (fadeend > 31 || fadeend < 1) + fadeend = 31; fadedist = fadeend - fadestart; - fog = NUMFROMCHAR(p2[1]) ? 1 : 0; + fog = NUMFROMCHAR(p2[1]); } #undef getnum @@ -1262,7 +1262,7 @@ void R_CreateColormap2(char *p1, char *p2, char *p3) size_t i; char *colormap_p; UINT32 cr, cg, cb, maskcolor, fadecolor; - UINT32 fadestart = 0, fadeend = 33, fadedist = 33; + UINT32 fadestart = 0, fadeend = 31, fadedist = 31; #define HEX2INT(x) (UINT32)(x >= '0' && x <= '9' ? x - '0' : x >= 'a' && x <= 'f' ? x - 'a' + 10 : x >= 'A' && x <= 'F' ? x - 'A' + 10 : 0) if (p1[0] == '#') @@ -1303,12 +1303,12 @@ void R_CreateColormap2(char *p1, char *p2, char *p3) // Get parameters like fadestart, fadeend, and the fogflag fadestart = NUMFROMCHAR(p2[3]) + (NUMFROMCHAR(p2[2]) * 10); fadeend = NUMFROMCHAR(p2[5]) + (NUMFROMCHAR(p2[4]) * 10); - if (fadestart > 32) + if (fadestart > 30) fadestart = 0; - if (fadeend > 33 || fadeend < 1) - fadeend = 33; + if (fadeend > 31 || fadeend < 1) + fadeend = 31; fadedist = fadeend - fadestart; - fog = NUMFROMCHAR(p2[1]) ? 1 : 0; + fog = NUMFROMCHAR(p2[1]); } #undef getnum diff --git a/src/r_draw.c b/src/r_draw.c index 5560ffa0..60927434 100644 --- a/src/r_draw.c +++ b/src/r_draw.c @@ -135,7 +135,7 @@ UINT32 nflatxshift, nflatyshift, nflatshiftup, nflatmask; #define BOSS_TT_CACHE_INDEX (MAXSKINS + 1) #define METALSONIC_TT_CACHE_INDEX (MAXSKINS + 2) #define ALLWHITE_TT_CACHE_INDEX (MAXSKINS + 3) -#define STARMAN_TT_CACHE_INDEX (MAXSKINS + 4) +#define RAINBOW_TT_CACHE_INDEX (MAXSKINS + 4) #define SKIN_RAMP_LENGTH 16 #define DEFAULT_STARTTRANSCOLOR 160 #define NUM_PALETTE_ENTRIES 256 @@ -155,7 +155,7 @@ const char *Color_Names[MAXSKINCOLORS] = "Black", // SKINCOLOR_BLACK "Cyan", // SKINCOLOR_CYAN "Teal", // SKINCOLOR_TEAL - "Steel_Blue",// SKINCOLOR_STEELBLUE + "Steel_Blue",// SKINCOLOR_STEEL "Blue", // SKINCOLOR_BLUE "Peach", // SKINCOLOR_PEACH "Tan", // SKINCOLOR_TAN @@ -175,7 +175,6 @@ const char *Color_Names[MAXSKINCOLORS] = "Yellow", // SKINCOLOR_YELLOW "Gold" // SKINCOLOR_GOLD }; -*/ const UINT8 Color_Opposite[MAXSKINCOLORS*2] = { @@ -186,7 +185,7 @@ const UINT8 Color_Opposite[MAXSKINCOLORS*2] = SKINCOLOR_WHITE,8, // SKINCOLOR_BLACK SKINCOLOR_NONE,8, // SKINCOLOR_CYAN SKINCOLOR_NONE,8, // SKINCOLOR_TEAL - SKINCOLOR_NONE,8, // SKINCOLOR_STEELBLUE + SKINCOLOR_NONE,8, // SKINCOLOR_STEEL SKINCOLOR_ORANGE,9, // SKINCOLOR_BLUE SKINCOLOR_NONE,8, // SKINCOLOR_PEACH SKINCOLOR_NONE,8, // SKINCOLOR_TAN @@ -206,6 +205,7 @@ const UINT8 Color_Opposite[MAXSKINCOLORS*2] = SKINCOLOR_NONE,8, // SKINCOLOR_YELLOW SKINCOLOR_NONE,8 // SKINCOLOR_GOLD }; +*/ CV_PossibleValue_t Color_cons_t[MAXSKINCOLORS+1]; @@ -257,7 +257,7 @@ static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, U 0x18, // SKINCOLOR_BLACK 0xd0, // SKINCOLOR_CYAN 0xdc, // SKINCOLOR_TEAL - 0xc8, // SKINCOLOR_STEELBLUE + 0xc8, // SKINCOLOR_STEEL 0xe2, // SKINCOLOR_BLUE 0x40, // SKINCOLOR_PEACH 0x48, // SKINCOLOR_TAN @@ -339,7 +339,7 @@ static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, U case SKINCOLOR_WHITE: case SKINCOLOR_BLACK: - case SKINCOLOR_STEELBLUE: + case SKINCOLOR_STEEL: case SKINCOLOR_PINK: case SKINCOLOR_LAVENDER: case SKINCOLOR_PURPLE: @@ -529,7 +529,7 @@ UINT8* R_GetTranslationColormap(INT32 skinnum, skincolors_t color, UINT8 flags) else if (skinnum == TC_BOSS) skintableindex = BOSS_TT_CACHE_INDEX; else if (skinnum == TC_METALSONIC) skintableindex = METALSONIC_TT_CACHE_INDEX; else if (skinnum == TC_ALLWHITE) skintableindex = ALLWHITE_TT_CACHE_INDEX; - else if (skinnum == TC_STARMAN) skintableindex = STARMAN_TT_CACHE_INDEX; + else if (skinnum == TC_RAINBOW) skintableindex = RAINBOW_TT_CACHE_INDEX; else skintableindex = skinnum; if (flags & GTC_CACHE) diff --git a/src/r_draw.h b/src/r_draw.h index ae70cd8a..3199f0f6 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -107,7 +107,7 @@ extern lumpnum_t viewborderlump[8]; #define TC_BOSS -2 #define TC_METALSONIC -3 // For Metal Sonic battle #define TC_ALLWHITE -4 // For Cy-Brak-demon -#define TC_STARMAN -5 // For star power +#define TC_RAINBOW -5 // For invincibility power // Initialize color translation tables, for player rendering etc. void R_InitTranslationTables(void); diff --git a/src/r_draw8.c b/src/r_draw8.c index 39585f58..800f28b6 100644 --- a/src/r_draw8.c +++ b/src/r_draw8.c @@ -297,7 +297,7 @@ void R_DrawTranslucentColumn_8(void) // Re-map color indices from wall texture column // using a lighting/special effects LUT. // heightmask is the Tutti-Frutti fix - *dest = colormap[*(transmap + (source[frac>>FRACBITS]<<8) + (*dest))]; + *dest = *(transmap + (colormap[source[frac>>FRACBITS]]<<8) + (*dest)); dest += vid.width; if ((frac += fracstep) >= heightmask) frac -= heightmask; @@ -308,15 +308,15 @@ void R_DrawTranslucentColumn_8(void) { while ((count -= 2) >= 0) // texture height is a power of 2 { - *dest = colormap[*(transmap + ((source[(frac>>FRACBITS)&heightmask]<<8)) + (*dest))]; + *dest = *(transmap + (colormap[source[(frac>>FRACBITS)&heightmask]]<<8) + (*dest)); dest += vid.width; frac += fracstep; - *dest = colormap[*(transmap + ((source[(frac>>FRACBITS)&heightmask]<<8)) + (*dest))]; + *dest = *(transmap + (colormap[source[(frac>>FRACBITS)&heightmask]]<<8) + (*dest)); dest += vid.width; frac += fracstep; } if (count & 1) - *dest = colormap[*(transmap + ((source[(frac>>FRACBITS)&heightmask]<<8)) + (*dest))]; + *dest = *(transmap + (colormap[source[(frac>>FRACBITS)&heightmask]]<<8) + (*dest)); } } } @@ -367,8 +367,7 @@ void R_DrawTranslatedTranslucentColumn_8(void) // using a lighting/special effects LUT. // heightmask is the Tutti-Frutti fix - *dest = dc_colormap[*(dc_transmap - + (dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]]<<8) + (*dest))]; + *dest = *(dc_transmap + (dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]]<<8) + (*dest)); dest += vid.width; if ((frac += fracstep) >= heightmask) @@ -380,17 +379,15 @@ void R_DrawTranslatedTranslucentColumn_8(void) { while ((count -= 2) >= 0) // texture height is a power of 2 { - *dest = dc_colormap[*(dc_transmap - + (dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]]<<8) + (*dest))]; + *dest = *(dc_transmap + (dc_colormap[dc_translation[dc_source[(frac>>FRACBITS)&heightmask]]]<<8) + (*dest)); dest += vid.width; frac += fracstep; - *dest = dc_colormap[*(dc_transmap - + (dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]]<<8) + (*dest))]; + *dest = *(dc_transmap + (dc_colormap[dc_translation[dc_source[(frac>>FRACBITS)&heightmask]]]<<8) + (*dest)); dest += vid.width; frac += fracstep; } if (count & 1) - *dest = dc_colormap[*(dc_transmap + (dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]] <<8) + (*dest))]; + *dest = *(dc_transmap + (dc_colormap[dc_translation[dc_source[(frac>>FRACBITS)&heightmask]]]<<8) + (*dest)); } } } @@ -738,8 +735,7 @@ void R_DrawTiltedTranslucentSpan_8(void) v = (INT64)(vz*z) + viewy; colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - - *dest = colormap[*(ds_transmap + (source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)] << 8) + dest[0])]; + *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest); dest++; iz += ds_sz.x; uz += ds_su.x; @@ -776,7 +772,7 @@ void R_DrawTiltedTranslucentSpan_8(void) for (i = SPANSIZE-1; i >= 0; i--) { colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = colormap[*(ds_transmap + (source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)] << 8) + dest[0])]; + *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest); dest++; u += stepu; v += stepv; @@ -792,7 +788,7 @@ void R_DrawTiltedTranslucentSpan_8(void) u = (INT64)(startu); v = (INT64)(startv); colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = colormap[*(ds_transmap + (source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)] << 8) + dest[0])]; + *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest); } else { @@ -813,7 +809,7 @@ void R_DrawTiltedTranslucentSpan_8(void) for (; width != 0; width--) { colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = colormap[*(ds_transmap + (source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)] << 8) + dest[0])]; + *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest); dest++; u += stepu; v += stepv; @@ -1124,49 +1120,49 @@ void R_DrawTranslucentSplat_8 (void) // need! val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; if (val != TRANSPARENTPIXEL) - dest[0] = colormap[*(ds_transmap + (val << 8) + dest[0])]; + dest[0] = *(ds_transmap + (colormap[val] << 8) + dest[0]); xposition += xstep; yposition += ystep; val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; if (val != TRANSPARENTPIXEL) - dest[1] = colormap[*(ds_transmap + (val << 8) + dest[1])]; + dest[1] = *(ds_transmap + (colormap[val] << 8) + dest[1]); xposition += xstep; yposition += ystep; val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; if (val != TRANSPARENTPIXEL) - dest[2] = colormap[*(ds_transmap + (val << 8) + dest[2])]; + dest[2] = *(ds_transmap + (colormap[val] << 8) + dest[2]); xposition += xstep; yposition += ystep; val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; if (val != TRANSPARENTPIXEL) - dest[3] = colormap[*(ds_transmap + (val << 8) + dest[3])]; + dest[3] = *(ds_transmap + (colormap[val] << 8) + dest[3]); xposition += xstep; yposition += ystep; val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; if (val != TRANSPARENTPIXEL) - dest[4] = colormap[*(ds_transmap + (val << 8) + dest[4])]; + dest[4] = *(ds_transmap + (colormap[val] << 8) + dest[4]); xposition += xstep; yposition += ystep; val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; if (val != TRANSPARENTPIXEL) - dest[5] = colormap[*(ds_transmap + (val << 8) + dest[5])]; + dest[5] = *(ds_transmap + (colormap[val] << 8) + dest[5]); xposition += xstep; yposition += ystep; val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; if (val != TRANSPARENTPIXEL) - dest[6] = colormap[*(ds_transmap + (val << 8) + dest[6])]; + dest[6] = *(ds_transmap + (colormap[val] << 8) + dest[6]); xposition += xstep; yposition += ystep; val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; if (val != TRANSPARENTPIXEL) - dest[7] = colormap[*(ds_transmap + (val << 8) + dest[7])]; + dest[7] = *(ds_transmap + (colormap[val] << 8) + dest[7]); xposition += xstep; yposition += ystep; @@ -1177,7 +1173,7 @@ void R_DrawTranslucentSplat_8 (void) { val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; if (val != TRANSPARENTPIXEL) - *dest = colormap[*(ds_transmap + (val << 8) + *dest)]; + *dest = *(ds_transmap + (colormap[val] << 8) + *dest); dest++; xposition += xstep; @@ -1220,35 +1216,35 @@ void R_DrawTranslucentSpan_8 (void) // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't // have the uber complicated math to calculate it now, so that was a memory write we didn't // need! - dest[0] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + dest[0])]; + dest[0] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[0]); xposition += xstep; yposition += ystep; - dest[1] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + dest[1])]; + dest[1] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[1]); xposition += xstep; yposition += ystep; - dest[2] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + dest[2])]; + dest[2] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[2]); xposition += xstep; yposition += ystep; - dest[3] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + dest[3])]; + dest[3] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[3]); xposition += xstep; yposition += ystep; - dest[4] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + dest[4])]; + dest[4] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[4]); xposition += xstep; yposition += ystep; - dest[5] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + dest[5])]; + dest[5] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[5]); xposition += xstep; yposition += ystep; - dest[6] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + dest[6])]; + dest[6] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[6]); xposition += xstep; yposition += ystep; - dest[7] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + dest[7])]; + dest[7] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[7]); xposition += xstep; yposition += ystep; @@ -1257,7 +1253,7 @@ void R_DrawTranslucentSpan_8 (void) } while (count--) { - *dest = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dest)]; + *dest = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + *dest); dest++; xposition += xstep; yposition += ystep; diff --git a/src/r_main.c b/src/r_main.c index 49f69af0..5990224c 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -170,7 +170,7 @@ consvar_t cv_drawdist_precip = {"drawdist_precip", "1024", CV_SAVE, drawdist_con consvar_t cv_precipdensity = {"precipdensity", "Moderate", CV_SAVE, precipdensity_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; // Okay, whoever said homremoval causes a performance hit should be shot. -consvar_t cv_homremoval = {"homremoval", "No", CV_SAVE, homremoval_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_homremoval = {"homremoval", "Yes", CV_SAVE, homremoval_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_maxportals = {"maxportals", "2", CV_SAVE, maxportals_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -1334,28 +1334,43 @@ void R_RenderPlayerView(player_t *player) { portal_pair *portal; const boolean skybox = (skyboxmo[0] && cv_skybox.value); - UINT8 ssplayer; + UINT8 viewnumber; if (player == &players[secondarydisplayplayer] && splitscreen) - ssplayer = 2; + viewnumber = 1; else if (player == &players[thirddisplayplayer] && splitscreen > 1) - ssplayer = 3; + viewnumber = 2; else if (player == &players[fourthdisplayplayer] && splitscreen > 2) - ssplayer = 4; - else if (splitscreen) - ssplayer = 1; + viewnumber = 3; else - ssplayer = 0; + viewnumber = 0; - if (cv_homremoval.value && player == &players[displayplayer]) // if this is display player 1 + // if this is display player 1 + if (cv_homremoval.value && player == &players[displayplayer]) { if (cv_homremoval.value == 1) V_DrawFill(0, 0, vid.width, vid.height, 31); // No HOM effect! else //'development' HOM removal -- makes it blindingly obvious if HOM is spotted. V_DrawFill(0, 0, vid.width, vid.height, 128+(timeinmap&15)); } + // Draw over the fourth screen so you don't have to stare at a HOM :V else if (splitscreen == 2 && player == &players[thirddisplayplayer]) - V_DrawFill(viewwidth, viewheight, viewwidth, viewheight, 31|V_NOSCALESTART); // Draw over the fourth screen so you don't have to stare at a HOM :V +#if 1 + { + // V_DrawPatchFill, but for the fourth screen only + patch_t *pat = W_CachePatchName("SRB2BACK", PU_CACHE); + INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); + INT32 x, y, pw = SHORT(pat->width) * dupz, ph = SHORT(pat->height) * dupz; + + for (x = vid.width>>1; x < vid.width; x += pw) + { + for (y = vid.height>>1; y < vid.height; y += ph) + V_DrawScaledPatch(x, y, V_NOSCALESTART, pat); + } + } +#else + V_DrawFill(viewwidth, viewheight, viewwidth, viewheight, 31|V_NOSCALESTART); +#endif // load previous saved value of skyVisible for the player if (splitscreen > 2 && player == &players[fourthdisplayplayer]) @@ -1382,7 +1397,7 @@ void R_RenderPlayerView(player_t *player) R_ClearVisibleFloorSplats(); #endif - R_RenderBSPNode((INT32)numnodes - 1, ssplayer); + R_RenderBSPNode((INT32)numnodes - 1, viewnumber); R_ClipSprites(); R_DrawPlanes(); #ifdef FLOORSPLATS @@ -1415,7 +1430,7 @@ void R_RenderPlayerView(player_t *player) mytotal = 0; ProfZeroTimer(); #endif - R_RenderBSPNode((INT32)numnodes - 1, ssplayer); + R_RenderBSPNode((INT32)numnodes - 1, viewnumber); R_ClipSprites(); #ifdef TIMING RDMSR(0x10, &mycount); @@ -1440,7 +1455,7 @@ void R_RenderPlayerView(player_t *player) validcount++; - R_RenderBSPNode((INT32)numnodes - 1, ssplayer); + R_RenderBSPNode((INT32)numnodes - 1, viewnumber); R_ClipSprites(); //R_DrawPlanes(); //R_DrawMasked(); @@ -1547,7 +1562,7 @@ void R_RegisterEngineStuff(void) // Default viewheight is changeable, // initialized to standard viewheight - CV_RegisterVar(&cv_viewheight); + //CV_RegisterVar(&cv_viewheight); #ifdef HWRENDER // GL-specific Commands diff --git a/src/r_plane.c b/src/r_plane.c index 92e0cacb..68be24b2 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -37,6 +37,9 @@ // Quincunx antialiasing of flats! //#define QUINCUNX +// good night sweet prince +//#define SHITPLANESPARENCY + //SoM: 3/23/2000: Use Boom visplane hashing. #define MAXVISPLANES 512 @@ -769,7 +772,11 @@ void R_DrawSinglePlane(visplane_t *pl) else // Opaque, but allow transparent flat pixels spanfunc = splatfunc; - if (pl->extra_colormap && pl->extra_colormap->fog) +#ifdef SHITPLANESPARENCY + if (spanfunc == splatfunc || (pl->extra_colormap && pl->extra_colormap->fog)) +#else + if (!pl->extra_colormap || !(pl->extra_colormap->fog & 2)) +#endif light = (pl->lightlevel >> LIGHTSEGSHIFT); else light = LIGHTLEVELS-1; @@ -823,7 +830,11 @@ void R_DrawSinglePlane(visplane_t *pl) else // Opaque, but allow transparent flat pixels spanfunc = splatfunc; - if (pl->extra_colormap && pl->extra_colormap->fog) +#ifdef SHITPLANESPARENCY + if (spanfunc == splatfunc || (pl->extra_colormap && pl->extra_colormap->fog)) +#else + if (!pl->extra_colormap || !(pl->extra_colormap->fog & 2)) +#endif light = (pl->lightlevel >> LIGHTSEGSHIFT); else light = LIGHTLEVELS-1; diff --git a/src/r_things.c b/src/r_things.c index 1efe6495..5adcecd4 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -826,15 +826,12 @@ static void R_DrawVisSprite(vissprite_t *vis) { colfunc = transtransfunc; dc_transmap = vis->transmap; - if (vis->mobj->skin && vis->mobj->sprite == SPR_PLAY) // MT_GHOST LOOKS LIKE A PLAYER SO USE THE PLAYER TRANSLATION TABLES. >_> + if (vis->mobj->colorized) + dc_translation = R_GetTranslationColormap(TC_RAINBOW, vis->mobj->color, GTC_CACHE); + else if (vis->mobj->skin && vis->mobj->sprite == SPR_PLAY) // MT_GHOST LOOKS LIKE A PLAYER SO USE THE PLAYER TRANSLATION TABLES. >_> { - if (vis->mobj->colorized) - dc_translation = R_GetTranslationColormap(TC_STARMAN, vis->mobj->color, GTC_CACHE); - else - { - size_t skinnum = (skin_t*)vis->mobj->skin-skins; - dc_translation = R_GetTranslationColormap((INT32)skinnum, vis->mobj->color, GTC_CACHE); - } + size_t skinnum = (skin_t*)vis->mobj->skin-skins; + dc_translation = R_GetTranslationColormap((INT32)skinnum, vis->mobj->color, GTC_CACHE); } else // Use the defaults dc_translation = R_GetTranslationColormap(TC_DEFAULT, vis->mobj->color, GTC_CACHE); @@ -850,15 +847,12 @@ static void R_DrawVisSprite(vissprite_t *vis) colfunc = transcolfunc; // New colormap stuff for skins Tails 06-07-2002 - if (vis->mobj->skin && vis->mobj->sprite == SPR_PLAY) // This thing is a player! + if (vis->mobj->colorized) + dc_translation = R_GetTranslationColormap(TC_RAINBOW, vis->mobj->color, GTC_CACHE); + else if (vis->mobj->skin && vis->mobj->sprite == SPR_PLAY) // This thing is a player! { - if (vis->mobj->colorized) - dc_translation = R_GetTranslationColormap(TC_STARMAN, vis->mobj->color, GTC_CACHE); - else - { - size_t skinnum = (skin_t*)vis->mobj->skin-skins; - dc_translation = R_GetTranslationColormap((INT32)skinnum, vis->mobj->color, GTC_CACHE); - } + size_t skinnum = (skin_t*)vis->mobj->skin-skins; + dc_translation = R_GetTranslationColormap((INT32)skinnum, vis->mobj->color, GTC_CACHE); } else // Use the defaults dc_translation = R_GetTranslationColormap(TC_DEFAULT, vis->mobj->color, GTC_CACHE); @@ -1092,7 +1086,7 @@ static void R_SplitSprite(vissprite_t *sprite, mobj_t *thing) else */ if (!((thing->frame & (FF_FULLBRIGHT|FF_TRANSMASK) || thing->flags2 & MF2_SHADOW) - && (!newsprite->extra_colormap || !newsprite->extra_colormap->fog))) + && (!newsprite->extra_colormap || !(newsprite->extra_colormap->fog & 1)))) { lindex = FixedMul(sprite->xscale, FixedDiv(640, vid.width))>>(LIGHTSCALESHIFT); @@ -1475,7 +1469,7 @@ static void R_ProjectSprite(mobj_t *thing) vis->transmap = transtables + (thing->frame & FF_TRANSMASK) - 0x10000; if (((thing->frame & FF_FULLBRIGHT) || (thing->flags2 & MF2_SHADOW)) - && (!vis->extra_colormap || !vis->extra_colormap->fog)) + && (!vis->extra_colormap || !(vis->extra_colormap->fog & 1))) { // full bright: goggles vis->colormap = colormaps; @@ -1676,7 +1670,7 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing) // R_AddSprites // During BSP traversal, this adds sprites by sector. // -void R_AddSprites(sector_t *sec, INT32 lightlevel, UINT8 ssplayer) +void R_AddSprites(sector_t *sec, INT32 lightlevel, UINT8 viewnumber) { mobj_t *thing; precipmobj_t *precipthing; // Tails 08-25-2002 @@ -1722,19 +1716,19 @@ void R_AddSprites(sector_t *sec, INT32 lightlevel, UINT8 ssplayer) if (splitscreen) { if (thing->eflags & MFE_DRAWONLYFORP1) - if (ssplayer != 1) + if (viewnumber != 0) continue; if (thing->eflags & MFE_DRAWONLYFORP2) - if (ssplayer != 2) + if (viewnumber != 1) continue; if (thing->eflags & MFE_DRAWONLYFORP3 && splitscreen > 1) - if (ssplayer != 3) + if (viewnumber != 2) continue; if (thing->eflags & MFE_DRAWONLYFORP4 && splitscreen > 2) - if (ssplayer != 4) + if (viewnumber != 3) continue; } @@ -1755,19 +1749,19 @@ void R_AddSprites(sector_t *sec, INT32 lightlevel, UINT8 ssplayer) if (splitscreen) { if (thing->eflags & MFE_DRAWONLYFORP1) - if (ssplayer != 1) + if (viewnumber != 0) continue; if (thing->eflags & MFE_DRAWONLYFORP2) - if (ssplayer != 2) + if (viewnumber != 1) continue; if (thing->eflags & MFE_DRAWONLYFORP3 && splitscreen > 1) - if (ssplayer != 3) + if (viewnumber != 2) continue; if (thing->eflags & MFE_DRAWONLYFORP4 && splitscreen > 2) - if (ssplayer != 4) + if (viewnumber != 3) continue; } diff --git a/src/r_things.h b/src/r_things.h index b39c5374..a037b873 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -55,7 +55,7 @@ void R_DelSpriteDefs(UINT16 wadnum); #endif //SoM: 6/5/2000: Light sprites correctly! -void R_AddSprites(sector_t *sec, INT32 lightlevel, UINT8 ssplayer); +void R_AddSprites(sector_t *sec, INT32 lightlevel, UINT8 viewnumber); void R_InitSprites(void); void R_ClearSprites(void); void R_ClipSprites(void); diff --git a/src/s_sound.c b/src/s_sound.c index 157c06ee..b9034503 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -78,9 +78,9 @@ consvar_t stereoreverse = {"stereoreverse", "Off", CV_SAVE, CV_OnOff, NULL, 0, N static consvar_t precachesound = {"precachesound", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; // actual general (maximum) sound & music volume, saved into the config -consvar_t cv_soundvolume = {"soundvolume", "31", CV_SAVE, soundvolume_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_soundvolume = {"soundvolume", "18", CV_SAVE, soundvolume_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_digmusicvolume = {"digmusicvolume", "18", CV_SAVE, soundvolume_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_midimusicvolume = {"midimusicvolume", "18", CV_SAVE, soundvolume_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +//consvar_t cv_midimusicvolume = {"midimusicvolume", "18", CV_SAVE, soundvolume_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; // number of channels available #if defined (_WIN32_WCE) || defined (DC) || defined (PSP) || defined(GP2X) consvar_t cv_numChannels = {"snd_channels", "8", CV_SAVE|CV_CALL, CV_Unsigned, SetChannelsNum, 0, NULL, NULL, 0, 0, NULL}; @@ -88,7 +88,7 @@ consvar_t cv_numChannels = {"snd_channels", "8", CV_SAVE|CV_CALL, CV_Unsigned, S consvar_t cv_numChannels = {"snd_channels", "32", CV_SAVE|CV_CALL, CV_Unsigned, SetChannelsNum, 0, NULL, NULL, 0, 0, NULL}; #endif -static consvar_t surround = {"surround", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t surround = {"surround", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; #define S_MAX_VOLUME 127 @@ -846,7 +846,7 @@ void S_StopSound(void *origin) // static INT32 actualsfxvolume; // check for change through console static INT32 actualdigmusicvolume; -static INT32 actualmidimusicvolume; +//static INT32 actualmidimusicvolume; void S_UpdateSounds(void) { @@ -873,8 +873,8 @@ void S_UpdateSounds(void) S_SetSfxVolume (cv_soundvolume.value); if (actualdigmusicvolume != cv_digmusicvolume.value) S_SetDigMusicVolume (cv_digmusicvolume.value); - if (actualmidimusicvolume != cv_midimusicvolume.value) - S_SetMIDIMusicVolume (cv_midimusicvolume.value); + //if (actualmidimusicvolume != cv_midimusicvolume.value) + //S_SetMIDIMusicVolume (cv_midimusicvolume.value); // We're done now, if we're not in a level. if (gamestate != GS_LEVEL) @@ -1438,7 +1438,7 @@ void S_StartSoundName(void *mo, const char *soundname) /// ------------------------ #ifdef MUSICSLOT_COMPATIBILITY -const char *compat_special_music_slots[21] = +const char *compat_special_music_slots[16] = { "titles", // 1036 title screen "read_m", // 1037 intro @@ -1455,12 +1455,6 @@ const char *compat_special_music_slots[21] = "credit", // 1048 credits "racent", // 1049 Race Results "stjr", // 1050 Sonic Team Jr. Presents - // SRB2kart 040217 - "finlap", // 1051 Sonic Team Jr. Presents - "karwin", // 1052 Sonic Team Jr. Presents - "karok", // 1053 Sonic Team Jr. Presents - "karlos", // 1054 Sonic Team Jr. Presents - "mega", // 1055 Sonic Team Jr. Presents "" }; #endif @@ -1476,16 +1470,22 @@ static boolean mus_paused = 0; // whether songs are mus_paused static boolean S_MIDIMusic(const char *mname, boolean looping) { - lumpnum_t mlumpnum; + /*lumpnum_t mlumpnum; void *mdata; - INT32 mhandle; + INT32 mhandle;*/ - if (nomidimusic || music_disabled) - return false; // didn't search. + (void)looping; + + /*if (nomidimusic || music_disabled) + return false; // didn't search.*/ if (W_CheckNumForName(va("d_%s", mname)) == LUMPERROR) return false; - mlumpnum = W_GetNumForName(va("d_%s", mname)); + + CONS_Alert(CONS_ERROR, "A MIDI Music lump %.6s was found,\nbut SRB2Kart does not support MIDI output.\nWe apologise for the inconvenience.\n", mname); + return false; + + /*mlumpnum = W_GetNumForName(va("d_%s", mname)); // load & register it mdata = W_CacheLumpNum(mlumpnum, PU_MUSIC); @@ -1512,7 +1512,7 @@ static boolean S_MIDIMusic(const char *mname, boolean looping) music_lumpnum = mlumpnum; music_data = mdata; music_handle = mhandle; - return true; + return true;*/ } static boolean S_DigMusic(const char *mname, boolean looping) @@ -1537,7 +1537,7 @@ void S_ChangeMusic(const char *mmusic, UINT16 mflags, boolean looping) S_ClearSfx(); #endif - if ((nomidimusic || music_disabled) && (nodigimusic || digital_disabled)) + if (/*(nomidimusic || music_disabled) && */(nodigimusic || digital_disabled)) return; // No Music (empty string) @@ -1601,7 +1601,7 @@ void S_SetDigMusicVolume(INT32 volume) I_SetDigMusicVolume(volume&31); } -void S_SetMIDIMusicVolume(INT32 volume) +/*void S_SetMIDIMusicVolume(INT32 volume) { if (volume < 0 || volume > 31) CONS_Alert(CONS_WARNING, "musicvolume should be between 0-31\n"); @@ -1613,7 +1613,7 @@ void S_SetMIDIMusicVolume(INT32 volume) I_SetMIDIMusicVolume(31); // Trick for buggy dos drivers. Win32 doesn't need this. #endif I_SetMIDIMusicVolume(volume&0x1f); -} +}*/ /// ------------------------ /// Init & Others @@ -1624,7 +1624,7 @@ void S_SetMIDIMusicVolume(INT32 volume) // Sets channels, SFX and music volume, // allocates channel buffer, sets S_sfx lookup. // -void S_Init(INT32 sfxVolume, INT32 digMusicVolume, INT32 midiMusicVolume) +void S_Init(INT32 sfxVolume, INT32 digMusicVolume) { INT32 i; @@ -1633,7 +1633,7 @@ void S_Init(INT32 sfxVolume, INT32 digMusicVolume, INT32 midiMusicVolume) S_SetSfxVolume(sfxVolume); S_SetDigMusicVolume(digMusicVolume); - S_SetMIDIMusicVolume(midiMusicVolume); + //S_SetMIDIMusicVolume(midiMusicVolume); SetChannelsNum(); diff --git a/src/s_sound.h b/src/s_sound.h index 708251a5..3561de80 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -23,8 +23,9 @@ #define PICKUP_SOUND 0x8000 extern consvar_t stereoreverse; -extern consvar_t cv_soundvolume, cv_digmusicvolume, cv_midimusicvolume; +extern consvar_t cv_soundvolume, cv_digmusicvolume;//, cv_midimusicvolume; extern consvar_t cv_numChannels; +extern consvar_t surround; #ifdef SNDSERV extern consvar_t sndserver_cmd, sndserver_arg; @@ -71,7 +72,7 @@ void S_RegisterSoundStuff(void); // Initializes sound stuff, including volume // Sets channels, SFX and music volume, allocates channel buffer, sets S_sfx lookup. // -void S_Init(INT32 sfxVolume, INT32 digMusicVolume, INT32 midiMusicVolume); +void S_Init(INT32 sfxVolume, INT32 digMusicVolume); // // Per level startup code. @@ -122,7 +123,7 @@ void S_UpdateSounds(void); FUNCMATH fixed_t S_CalculateSoundDistance(fixed_t px1, fixed_t py1, fixed_t pz1, fixed_t px2, fixed_t py2, fixed_t pz2); void S_SetDigMusicVolume(INT32 volume); -void S_SetMIDIMusicVolume(INT32 volume); +//void S_SetMIDIMusicVolume(INT32 volume); void S_SetSfxVolume(INT32 volume); INT32 S_OriginPlaying(void *origin); @@ -142,7 +143,7 @@ void S_StopSoundByNum(sfxenum_t sfxnum); #ifdef MUSICSLOT_COMPATIBILITY // For compatibility with code/scripts relying on older versions // This is a list of all the "special" slot names and their associated numbers -const char *compat_special_music_slots[21]; +const char *compat_special_music_slots[16]; #endif #endif diff --git a/src/sdl/IMG_xpm.c b/src/sdl/IMG_xpm.c index e08736d6..8adfd343 100644 --- a/src/sdl/IMG_xpm.c +++ b/src/sdl/IMG_xpm.c @@ -1,27 +1,24 @@ /* - SDL_image: An example image loading library for use with SDL - Copyright (C) 1999-2004 Sam Lantinga + SDL_image: An example image loading library for use with SDL + Copyright (C) 1997-2018 Sam Lantinga - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Sam Lantinga - slouken@libsdl.org + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. */ -/* $Id: IMG_xpm.c,v 1.10 2004/01/04 22:04:38 slouken Exp $ */ - /* * XPM (X PixMap) image loader: * @@ -45,98 +42,110 @@ * requires about 13K in binary form. */ -#include -#include -#include -#include - -//#include "SDL_image.h" - +#if 0 +#include "SDL_image.h" +#else +extern SDLCALL int SDLCALL IMG_isXPM(SDL_RWops *src); +extern SDLCALL SDL_Surface *IMG_LoadXPM_RW(SDL_RWops *src); +extern SDLCALL SDL_Surface * SDLCALL IMG_ReadXPMFromArray(const char **xpm); +#define IMG_SetError SDL_SetError +#define IMG_GetError SDL_GetError +#endif #ifdef LOAD_XPM /* See if an image is contained in a data source */ -#if 0 int IMG_isXPM(SDL_RWops *src) { - char magic[9]; + Sint64 start; + int is_XPM; + char magic[9]; - return (SDL_RWread(src, magic, sizeof (magic), 1) - && memcmp(magic, "/* XPM */", 9) == 0); + if ( !src ) + return 0; + start = SDL_RWtell(src); + is_XPM = 0; + if ( SDL_RWread(src, magic, sizeof(magic), 1) ) { + if ( SDL_memcmp(magic, "/* XPM */", sizeof(magic)) == 0 ) { + is_XPM = 1; + } + } + SDL_RWseek(src, start, RW_SEEK_SET); + return(is_XPM); } -#endif /* Hash table to look up colors from pixel strings */ #define STARTING_HASH_SIZE 256 struct hash_entry { - char *key; - Uint32 color; - struct hash_entry *next; + const char *key; + Uint32 color; + struct hash_entry *next; }; struct color_hash { - struct hash_entry **table; - struct hash_entry *entries; /* array of all entries */ - struct hash_entry *next_free; - size_t size; - int maxnum; + struct hash_entry **table; + struct hash_entry *entries; /* array of all entries */ + struct hash_entry *next_free; + int size; + int maxnum; }; -static int hash_key(const char *key, int cpp, size_t size) +static int hash_key(const char *key, int cpp, int size) { - int hash; + int hash; - hash = 0; - while ( cpp-- > 0 ) { - hash = hash * 33 + *key++; - } - return (int)(hash & (size - 1)); + hash = 0; + while ( cpp-- > 0 ) { + hash = hash * 33 + *key++; + } + return hash & (size - 1); } static struct color_hash *create_colorhash(int maxnum) { - size_t bytes; - int s; - struct color_hash *hash; + int bytes, s; + struct color_hash *hash; - /* we know how many entries we need, so we can allocate - everything here */ - hash = malloc(sizeof *hash); - if (!hash) - return NULL; + /* we know how many entries we need, so we can allocate + everything here */ + hash = (struct color_hash *)SDL_malloc(sizeof *hash); + if (!hash) + return NULL; - /* use power-of-2 sized hash table for decoding speed */ - for (s = STARTING_HASH_SIZE; s < maxnum; s <<= 1) - ; - hash->size = s; - hash->maxnum = maxnum; - bytes = hash->size * sizeof (struct hash_entry **); - hash->entries = NULL; /* in case malloc fails */ - hash->table = malloc(bytes); - if (!hash->table) - return NULL; - memset(hash->table, 0, bytes); - hash->entries = malloc(maxnum * sizeof (struct hash_entry)); - if (!hash->entries) - { - free(hash->table); - return NULL; - } - hash->next_free = hash->entries; - return hash; + /* use power-of-2 sized hash table for decoding speed */ + for (s = STARTING_HASH_SIZE; s < maxnum; s <<= 1) + ; + hash->size = s; + hash->maxnum = maxnum; + bytes = hash->size * sizeof(struct hash_entry **); + hash->entries = NULL; /* in case malloc fails */ + hash->table = (struct hash_entry **)SDL_malloc(bytes); + if (!hash->table) { + SDL_free(hash); + return NULL; + } + SDL_memset(hash->table, 0, bytes); + hash->entries = (struct hash_entry *)SDL_malloc(maxnum * sizeof(struct hash_entry)); + if (!hash->entries) { + SDL_free(hash->table); + SDL_free(hash); + return NULL; + } + hash->next_free = hash->entries; + return hash; } static int add_colorhash(struct color_hash *hash, char *key, int cpp, Uint32 color) { - const int indexkey = hash_key(key, cpp, hash->size); - struct hash_entry *e = hash->next_free++; - e->color = color; - e->key = key; - e->next = hash->table[indexkey]; - hash->table[indexkey] = e; - return 1; + int index = hash_key(key, cpp, hash->size); + struct hash_entry *e = hash->next_free++; + e->color = color; + e->key = key; + e->next = hash->table[index]; + hash->table[index] = e; + return 1; } /* fast lookup that works if cpp == 1 */ @@ -144,88 +153,756 @@ static int add_colorhash(struct color_hash *hash, static Uint32 get_colorhash(struct color_hash *hash, const char *key, int cpp) { - struct hash_entry *entry = hash->table[hash_key(key, cpp, hash->size)]; - while (entry) { - if (memcmp(key, entry->key, cpp) == 0) - return entry->color; - entry = entry->next; - } - return 0; /* garbage in - garbage out */ + struct hash_entry *entry = hash->table[hash_key(key, cpp, hash->size)]; + while (entry) { + if (SDL_memcmp(key, entry->key, cpp) == 0) + return entry->color; + entry = entry->next; + } + return 0; /* garbage in - garbage out */ } static void free_colorhash(struct color_hash *hash) { - if (hash && hash->table) { - free(hash->table); - free(hash->entries); - free(hash); - } + if (hash) { + if (hash->table) + SDL_free(hash->table); + if (hash->entries) + SDL_free(hash->entries); + SDL_free(hash); + } } -/* portable case-insensitive string comparison */ -static int string_equal(const char *a, const char *b, size_t n) -{ - while (*a && *b && n) { - if (toupper((unsigned char)*a) != toupper((unsigned char)*b)) - return 0; - a++; - b++; - n--; - } - return *a == *b; -} - -#undef ARRAYSIZE -#define ARRAYSIZE(a) (int)(sizeof (a) / sizeof ((a)[0])) - /* * convert colour spec to RGB (in 0xrrggbb format). * return 1 if successful. */ -static int color_to_rgb(const char *spec, size_t speclen, Uint32 *rgb) +static int color_to_rgb(const char *spec, int speclen, Uint32 *rgb) { - /* poor man's rgb.txt */ - static struct { const char *name; Uint32 rgb; } known[] = { - {"none", 0xffffffff}, - {"black", 0x00000000}, - {"white", 0x00ffffff}, - {"red", 0x00ff0000}, - {"green", 0x0000ff00}, - {"blue", 0x000000ff} - }; + /* poor man's rgb.txt */ + static struct { const char *name; Uint32 rgb; } known[] = { + { "none", 0xFFFFFFFF }, + { "black", 0x000000 }, + { "white", 0xFFFFFF }, + { "red", 0xFF0000 }, + { "green", 0x00FF00 }, + { "blue", 0x0000FF }, +/* This table increases the size of the library by 40K, so it's disabled by default */ +#ifdef EXTENDED_XPM_COLORS + { "aliceblue", 0xf0f8ff }, + { "antiquewhite", 0xfaebd7 }, + { "antiquewhite1", 0xffefdb }, + { "antiquewhite2", 0xeedfcc }, + { "antiquewhite3", 0xcdc0b0 }, + { "antiquewhite4", 0x8b8378 }, + { "aqua", 0x00ffff }, + { "aquamarine", 0x7fffd4 }, + { "aquamarine1", 0x7fffd4 }, + { "aquamarine2", 0x76eec6 }, + { "aquamarine3", 0x66cdaa }, + { "aquamarine4", 0x458b74 }, + { "azure", 0xf0ffff }, + { "azure1", 0xf0ffff }, + { "azure2", 0xe0eeee }, + { "azure3", 0xc1cdcd }, + { "azure4", 0x838b8b }, + { "beige", 0xf5f5dc }, + { "bisque", 0xffe4c4 }, + { "bisque1", 0xffe4c4 }, + { "bisque2", 0xeed5b7 }, + { "bisque3", 0xcdb79e }, + { "bisque4", 0x8b7d6b }, + { "black", 0x000000 }, + { "blanchedalmond", 0xffebcd }, + { "blue", 0x0000ff }, + { "blue1", 0x0000ff }, + { "blue2", 0x0000ee }, + { "blue3", 0x0000cd }, + { "blue4", 0x00008B }, + { "blueviolet", 0x8a2be2 }, + { "brown", 0xA52A2A }, + { "brown1", 0xFF4040 }, + { "brown2", 0xEE3B3B }, + { "brown3", 0xCD3333 }, + { "brown4", 0x8B2323 }, + { "burlywood", 0xDEB887 }, + { "burlywood1", 0xFFD39B }, + { "burlywood2", 0xEEC591 }, + { "burlywood3", 0xCDAA7D }, + { "burlywood4", 0x8B7355 }, + { "cadetblue", 0x5F9EA0 }, + { "cadetblue", 0x5f9ea0 }, + { "cadetblue1", 0x98f5ff }, + { "cadetblue2", 0x8ee5ee }, + { "cadetblue3", 0x7ac5cd }, + { "cadetblue4", 0x53868b }, + { "chartreuse", 0x7FFF00 }, + { "chartreuse1", 0x7FFF00 }, + { "chartreuse2", 0x76EE00 }, + { "chartreuse3", 0x66CD00 }, + { "chartreuse4", 0x458B00 }, + { "chocolate", 0xD2691E }, + { "chocolate1", 0xFF7F24 }, + { "chocolate2", 0xEE7621 }, + { "chocolate3", 0xCD661D }, + { "chocolate4", 0x8B4513 }, + { "coral", 0xFF7F50 }, + { "coral1", 0xFF7256 }, + { "coral2", 0xEE6A50 }, + { "coral3", 0xCD5B45 }, + { "coral4", 0x8B3E2F }, + { "cornflowerblue", 0x6495ed }, + { "cornsilk", 0xFFF8DC }, + { "cornsilk1", 0xFFF8DC }, + { "cornsilk2", 0xEEE8CD }, + { "cornsilk3", 0xCDC8B1 }, + { "cornsilk4", 0x8B8878 }, + { "crimson", 0xDC143C }, + { "cyan", 0x00FFFF }, + { "cyan1", 0x00FFFF }, + { "cyan2", 0x00EEEE }, + { "cyan3", 0x00CDCD }, + { "cyan4", 0x008B8B }, + { "darkblue", 0x00008b }, + { "darkcyan", 0x008b8b }, + { "darkgoldenrod", 0xb8860b }, + { "darkgoldenrod1", 0xffb90f }, + { "darkgoldenrod2", 0xeead0e }, + { "darkgoldenrod3", 0xcd950c }, + { "darkgoldenrod4", 0x8b6508 }, + { "darkgray", 0xa9a9a9 }, + { "darkgreen", 0x006400 }, + { "darkgrey", 0xa9a9a9 }, + { "darkkhaki", 0xbdb76b }, + { "darkmagenta", 0x8b008b }, + { "darkolivegreen", 0x556b2f }, + { "darkolivegreen1", 0xcaff70 }, + { "darkolivegreen2", 0xbcee68 }, + { "darkolivegreen3", 0xa2cd5a }, + { "darkolivegreen4", 0x6e8b3d }, + { "darkorange", 0xff8c00 }, + { "darkorange1", 0xff7f00 }, + { "darkorange2", 0xee7600 }, + { "darkorange3", 0xcd6600 }, + { "darkorange4", 0x8b4500 }, + { "darkorchid", 0x9932cc }, + { "darkorchid1", 0xbf3eff }, + { "darkorchid2", 0xb23aee }, + { "darkorchid3", 0x9a32cd }, + { "darkorchid4", 0x68228b }, + { "darkred", 0x8b0000 }, + { "darksalmon", 0xe9967a }, + { "darkseagreen", 0x8fbc8f }, + { "darkseagreen1", 0xc1ffc1 }, + { "darkseagreen2", 0xb4eeb4 }, + { "darkseagreen3", 0x9bcd9b }, + { "darkseagreen4", 0x698b69 }, + { "darkslateblue", 0x483d8b }, + { "darkslategray", 0x2f4f4f }, + { "darkslategray1", 0x97ffff }, + { "darkslategray2", 0x8deeee }, + { "darkslategray3", 0x79cdcd }, + { "darkslategray4", 0x528b8b }, + { "darkslategrey", 0x2f4f4f }, + { "darkturquoise", 0x00ced1 }, + { "darkviolet", 0x9400D3 }, + { "darkviolet", 0x9400d3 }, + { "deeppink", 0xff1493 }, + { "deeppink1", 0xff1493 }, + { "deeppink2", 0xee1289 }, + { "deeppink3", 0xcd1076 }, + { "deeppink4", 0x8b0a50 }, + { "deepskyblue", 0x00bfff }, + { "deepskyblue1", 0x00bfff }, + { "deepskyblue2", 0x00b2ee }, + { "deepskyblue3", 0x009acd }, + { "deepskyblue4", 0x00688b }, + { "dimgray", 0x696969 }, + { "dimgrey", 0x696969 }, + { "dodgerblue", 0x1e90ff }, + { "dodgerblue1", 0x1e90ff }, + { "dodgerblue2", 0x1c86ee }, + { "dodgerblue3", 0x1874cd }, + { "dodgerblue4", 0x104e8b }, + { "firebrick", 0xB22222 }, + { "firebrick1", 0xFF3030 }, + { "firebrick2", 0xEE2C2C }, + { "firebrick3", 0xCD2626 }, + { "firebrick4", 0x8B1A1A }, + { "floralwhite", 0xfffaf0 }, + { "forestgreen", 0x228b22 }, + { "fractal", 0x808080 }, + { "fuchsia", 0xFF00FF }, + { "gainsboro", 0xDCDCDC }, + { "ghostwhite", 0xf8f8ff }, + { "gold", 0xFFD700 }, + { "gold1", 0xFFD700 }, + { "gold2", 0xEEC900 }, + { "gold3", 0xCDAD00 }, + { "gold4", 0x8B7500 }, + { "goldenrod", 0xDAA520 }, + { "goldenrod1", 0xFFC125 }, + { "goldenrod2", 0xEEB422 }, + { "goldenrod3", 0xCD9B1D }, + { "goldenrod4", 0x8B6914 }, + { "gray", 0x7E7E7E }, + { "gray", 0xBEBEBE }, + { "gray0", 0x000000 }, + { "gray1", 0x030303 }, + { "gray10", 0x1A1A1A }, + { "gray100", 0xFFFFFF }, + { "gray11", 0x1C1C1C }, + { "gray12", 0x1F1F1F }, + { "gray13", 0x212121 }, + { "gray14", 0x242424 }, + { "gray15", 0x262626 }, + { "gray16", 0x292929 }, + { "gray17", 0x2B2B2B }, + { "gray18", 0x2E2E2E }, + { "gray19", 0x303030 }, + { "gray2", 0x050505 }, + { "gray20", 0x333333 }, + { "gray21", 0x363636 }, + { "gray22", 0x383838 }, + { "gray23", 0x3B3B3B }, + { "gray24", 0x3D3D3D }, + { "gray25", 0x404040 }, + { "gray26", 0x424242 }, + { "gray27", 0x454545 }, + { "gray28", 0x474747 }, + { "gray29", 0x4A4A4A }, + { "gray3", 0x080808 }, + { "gray30", 0x4D4D4D }, + { "gray31", 0x4F4F4F }, + { "gray32", 0x525252 }, + { "gray33", 0x545454 }, + { "gray34", 0x575757 }, + { "gray35", 0x595959 }, + { "gray36", 0x5C5C5C }, + { "gray37", 0x5E5E5E }, + { "gray38", 0x616161 }, + { "gray39", 0x636363 }, + { "gray4", 0x0A0A0A }, + { "gray40", 0x666666 }, + { "gray41", 0x696969 }, + { "gray42", 0x6B6B6B }, + { "gray43", 0x6E6E6E }, + { "gray44", 0x707070 }, + { "gray45", 0x737373 }, + { "gray46", 0x757575 }, + { "gray47", 0x787878 }, + { "gray48", 0x7A7A7A }, + { "gray49", 0x7D7D7D }, + { "gray5", 0x0D0D0D }, + { "gray50", 0x7F7F7F }, + { "gray51", 0x828282 }, + { "gray52", 0x858585 }, + { "gray53", 0x878787 }, + { "gray54", 0x8A8A8A }, + { "gray55", 0x8C8C8C }, + { "gray56", 0x8F8F8F }, + { "gray57", 0x919191 }, + { "gray58", 0x949494 }, + { "gray59", 0x969696 }, + { "gray6", 0x0F0F0F }, + { "gray60", 0x999999 }, + { "gray61", 0x9C9C9C }, + { "gray62", 0x9E9E9E }, + { "gray63", 0xA1A1A1 }, + { "gray64", 0xA3A3A3 }, + { "gray65", 0xA6A6A6 }, + { "gray66", 0xA8A8A8 }, + { "gray67", 0xABABAB }, + { "gray68", 0xADADAD }, + { "gray69", 0xB0B0B0 }, + { "gray7", 0x121212 }, + { "gray70", 0xB3B3B3 }, + { "gray71", 0xB5B5B5 }, + { "gray72", 0xB8B8B8 }, + { "gray73", 0xBABABA }, + { "gray74", 0xBDBDBD }, + { "gray75", 0xBFBFBF }, + { "gray76", 0xC2C2C2 }, + { "gray77", 0xC4C4C4 }, + { "gray78", 0xC7C7C7 }, + { "gray79", 0xC9C9C9 }, + { "gray8", 0x141414 }, + { "gray80", 0xCCCCCC }, + { "gray81", 0xCFCFCF }, + { "gray82", 0xD1D1D1 }, + { "gray83", 0xD4D4D4 }, + { "gray84", 0xD6D6D6 }, + { "gray85", 0xD9D9D9 }, + { "gray86", 0xDBDBDB }, + { "gray87", 0xDEDEDE }, + { "gray88", 0xE0E0E0 }, + { "gray89", 0xE3E3E3 }, + { "gray9", 0x171717 }, + { "gray90", 0xE5E5E5 }, + { "gray91", 0xE8E8E8 }, + { "gray92", 0xEBEBEB }, + { "gray93", 0xEDEDED }, + { "gray94", 0xF0F0F0 }, + { "gray95", 0xF2F2F2 }, + { "gray96", 0xF5F5F5 }, + { "gray97", 0xF7F7F7 }, + { "gray98", 0xFAFAFA }, + { "gray99", 0xFCFCFC }, + { "green", 0x008000 }, + { "green", 0x00FF00 }, + { "green1", 0x00FF00 }, + { "green2", 0x00EE00 }, + { "green3", 0x00CD00 }, + { "green4", 0x008B00 }, + { "greenyellow", 0xadff2f }, + { "grey", 0xBEBEBE }, + { "grey0", 0x000000 }, + { "grey1", 0x030303 }, + { "grey10", 0x1A1A1A }, + { "grey100", 0xFFFFFF }, + { "grey11", 0x1C1C1C }, + { "grey12", 0x1F1F1F }, + { "grey13", 0x212121 }, + { "grey14", 0x242424 }, + { "grey15", 0x262626 }, + { "grey16", 0x292929 }, + { "grey17", 0x2B2B2B }, + { "grey18", 0x2E2E2E }, + { "grey19", 0x303030 }, + { "grey2", 0x050505 }, + { "grey20", 0x333333 }, + { "grey21", 0x363636 }, + { "grey22", 0x383838 }, + { "grey23", 0x3B3B3B }, + { "grey24", 0x3D3D3D }, + { "grey25", 0x404040 }, + { "grey26", 0x424242 }, + { "grey27", 0x454545 }, + { "grey28", 0x474747 }, + { "grey29", 0x4A4A4A }, + { "grey3", 0x080808 }, + { "grey30", 0x4D4D4D }, + { "grey31", 0x4F4F4F }, + { "grey32", 0x525252 }, + { "grey33", 0x545454 }, + { "grey34", 0x575757 }, + { "grey35", 0x595959 }, + { "grey36", 0x5C5C5C }, + { "grey37", 0x5E5E5E }, + { "grey38", 0x616161 }, + { "grey39", 0x636363 }, + { "grey4", 0x0A0A0A }, + { "grey40", 0x666666 }, + { "grey41", 0x696969 }, + { "grey42", 0x6B6B6B }, + { "grey43", 0x6E6E6E }, + { "grey44", 0x707070 }, + { "grey45", 0x737373 }, + { "grey46", 0x757575 }, + { "grey47", 0x787878 }, + { "grey48", 0x7A7A7A }, + { "grey49", 0x7D7D7D }, + { "grey5", 0x0D0D0D }, + { "grey50", 0x7F7F7F }, + { "grey51", 0x828282 }, + { "grey52", 0x858585 }, + { "grey53", 0x878787 }, + { "grey54", 0x8A8A8A }, + { "grey55", 0x8C8C8C }, + { "grey56", 0x8F8F8F }, + { "grey57", 0x919191 }, + { "grey58", 0x949494 }, + { "grey59", 0x969696 }, + { "grey6", 0x0F0F0F }, + { "grey60", 0x999999 }, + { "grey61", 0x9C9C9C }, + { "grey62", 0x9E9E9E }, + { "grey63", 0xA1A1A1 }, + { "grey64", 0xA3A3A3 }, + { "grey65", 0xA6A6A6 }, + { "grey66", 0xA8A8A8 }, + { "grey67", 0xABABAB }, + { "grey68", 0xADADAD }, + { "grey69", 0xB0B0B0 }, + { "grey7", 0x121212 }, + { "grey70", 0xB3B3B3 }, + { "grey71", 0xB5B5B5 }, + { "grey72", 0xB8B8B8 }, + { "grey73", 0xBABABA }, + { "grey74", 0xBDBDBD }, + { "grey75", 0xBFBFBF }, + { "grey76", 0xC2C2C2 }, + { "grey77", 0xC4C4C4 }, + { "grey78", 0xC7C7C7 }, + { "grey79", 0xC9C9C9 }, + { "grey8", 0x141414 }, + { "grey80", 0xCCCCCC }, + { "grey81", 0xCFCFCF }, + { "grey82", 0xD1D1D1 }, + { "grey83", 0xD4D4D4 }, + { "grey84", 0xD6D6D6 }, + { "grey85", 0xD9D9D9 }, + { "grey86", 0xDBDBDB }, + { "grey87", 0xDEDEDE }, + { "grey88", 0xE0E0E0 }, + { "grey89", 0xE3E3E3 }, + { "grey9", 0x171717 }, + { "grey90", 0xE5E5E5 }, + { "grey91", 0xE8E8E8 }, + { "grey92", 0xEBEBEB }, + { "grey93", 0xEDEDED }, + { "grey94", 0xF0F0F0 }, + { "grey95", 0xF2F2F2 }, + { "grey96", 0xF5F5F5 }, + { "grey97", 0xF7F7F7 }, + { "grey98", 0xFAFAFA }, + { "grey99", 0xFCFCFC }, + { "honeydew", 0xF0FFF0 }, + { "honeydew1", 0xF0FFF0 }, + { "honeydew2", 0xE0EEE0 }, + { "honeydew3", 0xC1CDC1 }, + { "honeydew4", 0x838B83 }, + { "hotpink", 0xff69b4 }, + { "hotpink1", 0xff6eb4 }, + { "hotpink2", 0xee6aa7 }, + { "hotpink3", 0xcd6090 }, + { "hotpink4", 0x8b3a62 }, + { "indianred", 0xcd5c5c }, + { "indianred1", 0xff6a6a }, + { "indianred2", 0xee6363 }, + { "indianred3", 0xcd5555 }, + { "indianred4", 0x8b3a3a }, + { "indigo", 0x4B0082 }, + { "ivory", 0xFFFFF0 }, + { "ivory1", 0xFFFFF0 }, + { "ivory2", 0xEEEEE0 }, + { "ivory3", 0xCDCDC1 }, + { "ivory4", 0x8B8B83 }, + { "khaki", 0xF0E68C }, + { "khaki1", 0xFFF68F }, + { "khaki2", 0xEEE685 }, + { "khaki3", 0xCDC673 }, + { "khaki4", 0x8B864E }, + { "lavender", 0xE6E6FA }, + { "lavenderblush", 0xfff0f5 }, + { "lavenderblush1", 0xfff0f5 }, + { "lavenderblush2", 0xeee0e5 }, + { "lavenderblush3", 0xcdc1c5 }, + { "lavenderblush4", 0x8b8386 }, + { "lawngreen", 0x7cfc00 }, + { "lemonchiffon", 0xfffacd }, + { "lemonchiffon1", 0xfffacd }, + { "lemonchiffon2", 0xeee9bf }, + { "lemonchiffon3", 0xcdc9a5 }, + { "lemonchiffon4", 0x8b8970 }, + { "lightblue", 0xadd8e6 }, + { "lightblue1", 0xbfefff }, + { "lightblue2", 0xb2dfee }, + { "lightblue3", 0x9ac0cd }, + { "lightblue4", 0x68838b }, + { "lightcoral", 0xf08080 }, + { "lightcyan", 0xe0ffff }, + { "lightcyan1", 0xe0ffff }, + { "lightcyan2", 0xd1eeee }, + { "lightcyan3", 0xb4cdcd }, + { "lightcyan4", 0x7a8b8b }, + { "lightgoldenrod", 0xeedd82 }, + { "lightgoldenrod1", 0xffec8b }, + { "lightgoldenrod2", 0xeedc82 }, + { "lightgoldenrod3", 0xcdbe70 }, + { "lightgoldenrod4", 0x8b814c }, + { "lightgoldenrodyellow", 0xfafad2 }, + { "lightgray", 0xd3d3d3 }, + { "lightgreen", 0x90ee90 }, + { "lightgrey", 0xd3d3d3 }, + { "lightpink", 0xffb6c1 }, + { "lightpink1", 0xffaeb9 }, + { "lightpink2", 0xeea2ad }, + { "lightpink3", 0xcd8c95 }, + { "lightpink4", 0x8b5f65 }, + { "lightsalmon", 0xffa07a }, + { "lightsalmon1", 0xffa07a }, + { "lightsalmon2", 0xee9572 }, + { "lightsalmon3", 0xcd8162 }, + { "lightsalmon4", 0x8b5742 }, + { "lightseagreen", 0x20b2aa }, + { "lightskyblue", 0x87cefa }, + { "lightskyblue1", 0xb0e2ff }, + { "lightskyblue2", 0xa4d3ee }, + { "lightskyblue3", 0x8db6cd }, + { "lightskyblue4", 0x607b8b }, + { "lightslateblue", 0x8470ff }, + { "lightslategray", 0x778899 }, + { "lightslategrey", 0x778899 }, + { "lightsteelblue", 0xb0c4de }, + { "lightsteelblue1", 0xcae1ff }, + { "lightsteelblue2", 0xbcd2ee }, + { "lightsteelblue3", 0xa2b5cd }, + { "lightsteelblue4", 0x6e7b8b }, + { "lightyellow", 0xffffe0 }, + { "lightyellow1", 0xffffe0 }, + { "lightyellow2", 0xeeeed1 }, + { "lightyellow3", 0xcdcdb4 }, + { "lightyellow4", 0x8b8b7a }, + { "lime", 0x00FF00 }, + { "limegreen", 0x32cd32 }, + { "linen", 0xFAF0E6 }, + { "magenta", 0xFF00FF }, + { "magenta1", 0xFF00FF }, + { "magenta2", 0xEE00EE }, + { "magenta3", 0xCD00CD }, + { "magenta4", 0x8B008B }, + { "maroon", 0x800000 }, + { "maroon", 0xB03060 }, + { "maroon1", 0xFF34B3 }, + { "maroon2", 0xEE30A7 }, + { "maroon3", 0xCD2990 }, + { "maroon4", 0x8B1C62 }, + { "mediumaquamarine", 0x66cdaa }, + { "mediumblue", 0x0000cd }, + { "mediumforestgreen", 0x32814b }, + { "mediumgoldenrod", 0xd1c166 }, + { "mediumorchid", 0xba55d3 }, + { "mediumorchid1", 0xe066ff }, + { "mediumorchid2", 0xd15fee }, + { "mediumorchid3", 0xb452cd }, + { "mediumorchid4", 0x7a378b }, + { "mediumpurple", 0x9370db }, + { "mediumpurple1", 0xab82ff }, + { "mediumpurple2", 0x9f79ee }, + { "mediumpurple3", 0x8968cd }, + { "mediumpurple4", 0x5d478b }, + { "mediumseagreen", 0x3cb371 }, + { "mediumslateblue", 0x7b68ee }, + { "mediumspringgreen", 0x00fa9a }, + { "mediumturquoise", 0x48d1cc }, + { "mediumvioletred", 0xc71585 }, + { "midnightblue", 0x191970 }, + { "mintcream", 0xf5fffa }, + { "mistyrose", 0xffe4e1 }, + { "mistyrose1", 0xffe4e1 }, + { "mistyrose2", 0xeed5d2 }, + { "mistyrose3", 0xcdb7b5 }, + { "mistyrose4", 0x8b7d7b }, + { "moccasin", 0xFFE4B5 }, + { "navajowhite", 0xffdead }, + { "navajowhite1", 0xffdead }, + { "navajowhite2", 0xeecfa1 }, + { "navajowhite3", 0xcdb38b }, + { "navajowhite4", 0x8b795e }, + { "navy", 0x000080 }, + { "navyblue", 0x000080 }, + { "none", 0x0000FF }, + { "oldlace", 0xfdf5e6 }, + { "olive", 0x808000 }, + { "olivedrab", 0x6b8e23 }, + { "olivedrab1", 0xc0ff3e }, + { "olivedrab2", 0xb3ee3a }, + { "olivedrab3", 0x9acd32 }, + { "olivedrab4", 0x698b22 }, + { "opaque", 0x000000 }, + { "orange", 0xFFA500 }, + { "orange1", 0xFFA500 }, + { "orange2", 0xEE9A00 }, + { "orange3", 0xCD8500 }, + { "orange4", 0x8B5A00 }, + { "orangered", 0xff4500 }, + { "orangered1", 0xff4500 }, + { "orangered2", 0xee4000 }, + { "orangered3", 0xcd3700 }, + { "orangered4", 0x8b2500 }, + { "orchid", 0xDA70D6 }, + { "orchid1", 0xFF83FA }, + { "orchid2", 0xEE7AE9 }, + { "orchid3", 0xCD69C9 }, + { "orchid4", 0x8B4789 }, + { "palegoldenrod", 0xeee8aa }, + { "palegreen", 0x98fb98 }, + { "palegreen1", 0x9aff9a }, + { "palegreen2", 0x90ee90 }, + { "palegreen3", 0x7ccd7c }, + { "palegreen4", 0x548b54 }, + { "paleturquoise", 0xafeeee }, + { "paleturquoise1", 0xbbffff }, + { "paleturquoise2", 0xaeeeee }, + { "paleturquoise3", 0x96cdcd }, + { "paleturquoise4", 0x668b8b }, + { "palevioletred", 0xdb7093 }, + { "palevioletred1", 0xff82ab }, + { "palevioletred2", 0xee799f }, + { "palevioletred3", 0xcd6889 }, + { "palevioletred4", 0x8b475d }, + { "papayawhip", 0xffefd5 }, + { "peachpuff", 0xffdab9 }, + { "peachpuff1", 0xffdab9 }, + { "peachpuff2", 0xeecbad }, + { "peachpuff3", 0xcdaf95 }, + { "peachpuff4", 0x8b7765 }, + { "peru", 0xCD853F }, + { "pink", 0xFFC0CB }, + { "pink1", 0xFFB5C5 }, + { "pink2", 0xEEA9B8 }, + { "pink3", 0xCD919E }, + { "pink4", 0x8B636C }, + { "plum", 0xDDA0DD }, + { "plum1", 0xFFBBFF }, + { "plum2", 0xEEAEEE }, + { "plum3", 0xCD96CD }, + { "plum4", 0x8B668B }, + { "powderblue", 0xb0e0e6 }, + { "purple", 0x800080 }, + { "purple", 0xA020F0 }, + { "purple1", 0x9B30FF }, + { "purple2", 0x912CEE }, + { "purple3", 0x7D26CD }, + { "purple4", 0x551A8B }, + { "red", 0xFF0000 }, + { "red1", 0xFF0000 }, + { "red2", 0xEE0000 }, + { "red3", 0xCD0000 }, + { "red4", 0x8B0000 }, + { "rosybrown", 0xbc8f8f }, + { "rosybrown1", 0xffc1c1 }, + { "rosybrown2", 0xeeb4b4 }, + { "rosybrown3", 0xcd9b9b }, + { "rosybrown4", 0x8b6969 }, + { "royalblue", 0x4169e1 }, + { "royalblue1", 0x4876ff }, + { "royalblue2", 0x436eee }, + { "royalblue3", 0x3a5fcd }, + { "royalblue4", 0x27408b }, + { "saddlebrown", 0x8b4513 }, + { "salmon", 0xFA8072 }, + { "salmon1", 0xFF8C69 }, + { "salmon2", 0xEE8262 }, + { "salmon3", 0xCD7054 }, + { "salmon4", 0x8B4C39 }, + { "sandybrown", 0xf4a460 }, + { "seagreen", 0x2e8b57 }, + { "seagreen1", 0x54ff9f }, + { "seagreen2", 0x4eee94 }, + { "seagreen3", 0x43cd80 }, + { "seagreen4", 0x2e8b57 }, + { "seashell", 0xFFF5EE }, + { "seashell1", 0xFFF5EE }, + { "seashell2", 0xEEE5DE }, + { "seashell3", 0xCDC5BF }, + { "seashell4", 0x8B8682 }, + { "sienna", 0xA0522D }, + { "sienna1", 0xFF8247 }, + { "sienna2", 0xEE7942 }, + { "sienna3", 0xCD6839 }, + { "sienna4", 0x8B4726 }, + { "silver", 0xC0C0C0 }, + { "skyblue", 0x87ceeb }, + { "skyblue1", 0x87ceff }, + { "skyblue2", 0x7ec0ee }, + { "skyblue3", 0x6ca6cd }, + { "skyblue4", 0x4a708b }, + { "slateblue", 0x6a5acd }, + { "slateblue1", 0x836fff }, + { "slateblue2", 0x7a67ee }, + { "slateblue3", 0x6959cd }, + { "slateblue4", 0x473c8b }, + { "slategray", 0x708090 }, + { "slategray1", 0xc6e2ff }, + { "slategray2", 0xb9d3ee }, + { "slategray3", 0x9fb6cd }, + { "slategray4", 0x6c7b8b }, + { "slategrey", 0x708090 }, + { "snow", 0xFFFAFA }, + { "snow1", 0xFFFAFA }, + { "snow2", 0xEEE9E9 }, + { "snow3", 0xCDC9C9 }, + { "snow4", 0x8B8989 }, + { "springgreen", 0x00ff7f }, + { "springgreen1", 0x00ff7f }, + { "springgreen2", 0x00ee76 }, + { "springgreen3", 0x00cd66 }, + { "springgreen4", 0x008b45 }, + { "steelblue", 0x4682b4 }, + { "steelblue1", 0x63b8ff }, + { "steelblue2", 0x5cacee }, + { "steelblue3", 0x4f94cd }, + { "steelblue4", 0x36648b }, + { "tan", 0xD2B48C }, + { "tan1", 0xFFA54F }, + { "tan2", 0xEE9A49 }, + { "tan3", 0xCD853F }, + { "tan4", 0x8B5A2B }, + { "teal", 0x008080 }, + { "thistle", 0xD8BFD8 }, + { "thistle1", 0xFFE1FF }, + { "thistle2", 0xEED2EE }, + { "thistle3", 0xCDB5CD }, + { "thistle4", 0x8B7B8B }, + { "tomato", 0xFF6347 }, + { "tomato1", 0xFF6347 }, + { "tomato2", 0xEE5C42 }, + { "tomato3", 0xCD4F39 }, + { "tomato4", 0x8B3626 }, + { "transparent", 0x0000FF }, + { "turquoise", 0x40E0D0 }, + { "turquoise1", 0x00F5FF }, + { "turquoise2", 0x00E5EE }, + { "turquoise3", 0x00C5CD }, + { "turquoise4", 0x00868B }, + { "violet", 0xEE82EE }, + { "violetred", 0xd02090 }, + { "violetred1", 0xff3e96 }, + { "violetred2", 0xee3a8c }, + { "violetred3", 0xcd3278 }, + { "violetred4", 0x8b2252 }, + { "wheat", 0xF5DEB3 }, + { "wheat1", 0xFFE7BA }, + { "wheat2", 0xEED8AE }, + { "wheat3", 0xCDBA96 }, + { "wheat4", 0x8B7E66 }, + { "white", 0xFFFFFF }, + { "whitesmoke", 0xf5f5f5 }, + { "yellow", 0xFFFF00 }, + { "yellow1", 0xFFFF00 }, + { "yellow2", 0xEEEE00 }, + { "yellow3", 0xCDCD00 }, + { "yellow4", 0x8B8B00 }, + { "yellowgreen", 0x9acd32 }, +#endif /* EXTENDED_XPM_COLORS */ + {"none", 0xFFFFFF} + }; - if (spec[0] == '#') { - char buf[7]; - switch (speclen) { - case 4: - buf[0] = buf[1] = spec[1]; - buf[2] = buf[3] = spec[2]; - buf[4] = buf[5] = spec[3]; - break; - case 7: - memcpy(buf, spec + 1, 6); - break; - case 13: - buf[0] = spec[1]; - buf[1] = spec[2]; - buf[2] = spec[5]; - buf[3] = spec[6]; - buf[4] = spec[9]; - buf[5] = spec[10]; - break; - } - buf[6] = '\0'; - *rgb = (Uint32)strtol(buf, NULL, 16); - return 1; - } else { - int i; - for (i = 0; i < ARRAYSIZE(known); i++) - if (string_equal(known[i].name, spec, speclen)) { - *rgb = known[i].rgb; - return 1; - } - return 0; + if (spec[0] == '#') { + char buf[7]; + switch(speclen) { + case 4: + buf[0] = buf[1] = spec[1]; + buf[2] = buf[3] = spec[2]; + buf[4] = buf[5] = spec[3]; + break; + case 7: + SDL_memcpy(buf, spec + 1, 6); + break; + case 13: + buf[0] = spec[1]; + buf[1] = spec[2]; + buf[2] = spec[5]; + buf[3] = spec[6]; + buf[4] = spec[9]; + buf[5] = spec[10]; + break; } + buf[6] = '\0'; + *rgb = (Uint32)SDL_strtol(buf, NULL, 16); + return 1; + } else { + size_t i; + for (i = 0; i < SDL_arraysize(known); i++) { + if (SDL_strncasecmp(known[i].name, spec, speclen) == 0) { + *rgb = known[i].rgb; + return 1; + } + } + return 0; + } } #ifndef MAX @@ -243,263 +920,278 @@ static const char *error; */ static const char *get_next_line(const char ***lines, SDL_RWops *src, int len) { - char *linebufnew; - if (lines) { - return *(*lines)++; - } else { - char c; - int n; - do { - if (SDL_RWread(src, &c, 1, 1) <= 0) { - error = "Premature end of data"; - return NULL; - } - } while (c != '"'); - if (len) { - len += 4; /* "\",\n\0" */ - if (len > buflen){ - buflen = len; - linebufnew = realloc(linebuf, buflen); - if(!linebufnew) { - free(linebuf); - error = "Out of memory"; - return NULL; - } - linebuf = linebufnew; - } - if (SDL_RWread(src, linebuf, len - 1, 1) <= 0) { - error = "Premature end of data"; - return NULL; - } - n = len - 2; - } else { - n = 0; - do { - if (n >= buflen - 1) { - if (buflen == 0) - buflen = 16; - buflen *= 2; - linebufnew = realloc(linebuf, buflen); - if(!linebufnew) { - free(linebuf); - error = "Out of memory"; - return NULL; - } - linebuf = linebufnew; - } - if (SDL_RWread(src, linebuf + n, 1, 1) <= 0) { - error = "Premature end of data"; - return NULL; - } - } while (linebuf[n++] != '"'); - n--; + char *linebufnew; + + if (lines) { + return *(*lines)++; + } else { + char c; + int n; + do { + if (SDL_RWread(src, &c, 1, 1) <= 0) { + error = "Premature end of data"; + return NULL; + } + } while (c != '"'); + if (len) { + len += 4; /* "\",\n\0" */ + if (len > buflen){ + buflen = len; + linebufnew = (char *)SDL_realloc(linebuf, buflen); + if (!linebufnew) { + SDL_free(linebuf); + error = "Out of memory"; + return NULL; } - linebuf[n] = '\0'; - return linebuf; + linebuf = linebufnew; + } + if (SDL_RWread(src, linebuf, len - 1, 1) <= 0) { + error = "Premature end of data"; + return NULL; + } + n = len - 2; + } else { + n = 0; + do { + if (n >= buflen - 1) { + if (buflen == 0) + buflen = 16; + buflen *= 2; + linebufnew = (char *)SDL_realloc(linebuf, buflen); + if (!linebufnew) { + SDL_free(linebuf); + error = "Out of memory"; + return NULL; + } + linebuf = linebufnew; + } + if (SDL_RWread(src, linebuf + n, 1, 1) <= 0) { + error = "Premature end of data"; + return NULL; + } + } while (linebuf[n++] != '"'); + n--; } + linebuf[n] = '\0'; + return linebuf; + } } -#define SKIPSPACE(p) \ -do { \ - while (isspace((unsigned char)*(p))) \ - ++(p); \ +#define SKIPSPACE(p) \ +do { \ + while (SDL_isspace((unsigned char)*(p))) \ + ++(p); \ } while (0) -#define SKIPNONSPACE(p) \ -do { \ - while (!isspace((unsigned char)*(p)) && *p) \ - ++(p); \ +#define SKIPNONSPACE(p) \ +do { \ + while (!SDL_isspace((unsigned char)*(p)) && *p) \ + ++(p); \ } while (0) /* read XPM from either array or RWops */ static SDL_Surface *load_xpm(const char **xpm, SDL_RWops *src) { - SDL_Surface *image = NULL; - int indexc; - int x, y; - int w, h, ncolors, cpp; - int indexed; - Uint8 *dst; - struct color_hash *colors = NULL; - SDL_Color *im_colors = NULL; - char *keystrings = NULL, *nextkey; - const char *line; - const char ***xpmlines = NULL; - int pixels_len; + Sint64 start = 0; + SDL_Surface *image = NULL; + int index; + int x, y; + int w, h, ncolors, cpp; + int indexed; + Uint8 *dst; + struct color_hash *colors = NULL; + SDL_Color *im_colors = NULL; + char *keystrings = NULL, *nextkey; + const char *line; + const char ***xpmlines = NULL; + int pixels_len; - error = NULL; - linebuf = NULL; - buflen = 0; + error = NULL; + linebuf = NULL; + buflen = 0; - if (xpm) - xpmlines = &xpm; + if (src) + start = SDL_RWtell(src); + if (xpm) + xpmlines = &xpm; + + line = get_next_line(xpmlines, src, 0); + if (!line) + goto done; + /* + * The header string of an XPMv3 image has the format + * + * [ ] + * + * where the hotspot coords are intended for mouse cursors. + * Right now we don't use the hotspots but it should be handled + * one day. + */ + if (SDL_sscanf(line, "%d %d %d %d", &w, &h, &ncolors, &cpp) != 4 + || w <= 0 || h <= 0 || ncolors <= 0 || cpp <= 0) { + error = "Invalid format description"; + goto done; + } + + keystrings = (char *)SDL_malloc(ncolors * cpp); + if (!keystrings) { + error = "Out of memory"; + goto done; + } + nextkey = keystrings; + + /* Create the new surface */ + if (ncolors <= 256) { + indexed = 1; + image = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 8, + 0, 0, 0, 0); + im_colors = image->format->palette->colors; + image->format->palette->ncolors = ncolors; + } else { + indexed = 0; + image = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32, + 0xff0000, 0x00ff00, 0x0000ff, 0); + } + if (!image) { + /* Hmm, some SDL error (out of memory?) */ + goto done; + } + + /* Read the colors */ + colors = create_colorhash(ncolors); + if (!colors) { + error = "Out of memory"; + goto done; + } + for (index = 0; index < ncolors; ++index ) { + const char *p; line = get_next_line(xpmlines, src, 0); if (!line) - goto done; - /* - * The header string of an XPMv3 image has the format - * - * [ ] - * - * where the hotspot coords are intended for mouse cursors. - * Right now we don't use the hotspots but it should be handled - * one day. - */ - if (sscanf(line, "%d %d %d %d", &w, &h, &ncolors, &cpp) != 4 - || w <= 0 || h <= 0 || ncolors <= 0 || cpp <= 0) { - error = "Invalid format description"; - goto done; - } + goto done; - keystrings = malloc(ncolors * cpp); - if (!keystrings) { - error = "Out of memory"; - goto done; - } - nextkey = keystrings; + p = line + cpp + 1; - /* Create the new surface */ - if (ncolors <= 256) { - indexed = 1; - image = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 8, - 0, 0, 0, 0); - im_colors = image->format->palette->colors; - image->format->palette->ncolors = ncolors; + /* parse a colour definition */ + for (;;) { + char nametype; + const char *colname; + Uint32 rgb, pixel; + + SKIPSPACE(p); + if (!*p) { + error = "colour parse error"; + goto done; + } + nametype = *p; + SKIPNONSPACE(p); + SKIPSPACE(p); + colname = p; + SKIPNONSPACE(p); + if (nametype == 's') + continue; /* skip symbolic colour names */ + + if (!color_to_rgb(colname, (int)(p - colname), &rgb)) + continue; + + SDL_memcpy(nextkey, line, cpp); + if (indexed) { + SDL_Color *c = im_colors + index; + c->r = (Uint8)(rgb >> 16); + c->g = (Uint8)(rgb >> 8); + c->b = (Uint8)(rgb); + pixel = index; + } else + pixel = rgb; + add_colorhash(colors, nextkey, cpp, pixel); + nextkey += cpp; + if (rgb == 0xffffffff) + SDL_SetColorKey(image, SDL_TRUE, pixel); + break; + } + } + + /* Read the pixels */ + pixels_len = w * cpp; + dst = (Uint8 *)image->pixels; + for (y = 0; y < h; y++) { + line = get_next_line(xpmlines, src, pixels_len); + if (!line) + goto done; + + if (indexed) { + /* optimization for some common cases */ + if (cpp == 1) + for (x = 0; x < w; x++) + dst[x] = (Uint8)QUICK_COLORHASH(colors, + line + x); + else + for (x = 0; x < w; x++) + dst[x] = (Uint8)get_colorhash(colors, + line + x * cpp, + cpp); } else { - indexed = 0; - image = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32, - 0xff0000, 0x00ff00, 0x0000ff, 0); - } - if (!image) { - /* Hmm, some SDL error (out of memory?) */ - goto done; - } - - /* Read the colors */ - colors = create_colorhash(ncolors); - if (!colors) { - error = "Out of memory"; - goto done; - } - for (indexc = 0; indexc < ncolors; ++indexc ) { - const char *p; - line = get_next_line(xpmlines, src, 0); - if (!line) - goto done; - - p = line + cpp + 1; - - /* parse a colour definition */ - for (;;) { - char nametype; - const char *colname; - Uint32 rgb, pixel; - - SKIPSPACE(p); - if (!*p) { - error = "colour parse error"; - goto done; - } - nametype = *p; - SKIPNONSPACE(p); - SKIPSPACE(p); - colname = p; - SKIPNONSPACE(p); - if (nametype == 's') - continue; /* skip symbolic colour names */ - - if (!color_to_rgb(colname, p - colname, &rgb)) - continue; - - memcpy(nextkey, line, cpp); - if (indexed) { - SDL_Color *c = im_colors + indexc; - c->r = (Uint8)(rgb >> 16); - c->g = (Uint8)(rgb >> 8); - c->b = (Uint8)(rgb); - pixel = indexc; - } else - pixel = rgb; - add_colorhash(colors, nextkey, cpp, pixel); - nextkey += cpp; - if (rgb == 0xffffffff) - SDL_SetColorKey(image, SDL_SRCCOLORKEY, pixel); - break; - } - } - - /* Read the pixels */ - pixels_len = w * cpp; - dst = image->pixels; - for (y = 0; y < h; y++) { - line = get_next_line(xpmlines, src, pixels_len); - if (indexed) { - /* optimization for some common cases */ - if (cpp == 1) - for (x = 0; x < w; x++) - dst[x] = (Uint8)QUICK_COLORHASH(colors, - line + x); - else - for (x = 0; x < w; x++) - dst[x] = (Uint8)get_colorhash(colors, - line + x * cpp, - cpp); - } else { - for (x = 0; x < w; x++) - ((Uint32*)dst)[x] = get_colorhash(colors, - line + x * cpp, - cpp); - } - dst += image->pitch; + for (x = 0; x < w; x++) + ((Uint32*)dst)[x] = get_colorhash(colors, + line + x * cpp, + cpp); } + dst += image->pitch; + } done: - if (error) { - SDL_FreeSurface(image); - image = NULL; - SDL_SetError(error); + if (error) { + if ( src ) + SDL_RWseek(src, start, RW_SEEK_SET); + if ( image ) { + SDL_FreeSurface(image); + image = NULL; } - free(keystrings); - free_colorhash(colors); - free(linebuf); - return(image); + IMG_SetError("%s", error); + } + if (keystrings) + SDL_free(keystrings); + free_colorhash(colors); + if (linebuf) + SDL_free(linebuf); + return(image); } /* Load a XPM type image from an RWops datasource */ -#if 0 SDL_Surface *IMG_LoadXPM_RW(SDL_RWops *src) { - if ( !src ) { - /* The error message has been set in SDL_RWFromFile */ - return NULL; - } - return load_xpm(NULL, src); + if ( !src ) { + /* The error message has been set in SDL_RWFromFile */ + return NULL; + } + return load_xpm(NULL, src); } -#endif -static inline SDL_Surface *IMG_ReadXPMFromArray(const char **xpm) +SDL_Surface *IMG_ReadXPMFromArray(const char **xpm) { - return load_xpm(xpm, NULL); + if (!xpm) { + IMG_SetError("array is NULL"); + return NULL; + } + return load_xpm(xpm, NULL); } #else /* not LOAD_XPM */ /* See if an image is contained in a data source */ -#if 0 int IMG_isXPM(SDL_RWops *src) { - return(0); + return(0); } + /* Load a XPM type image from an SDL datasource */ SDL_Surface *IMG_LoadXPM_RW(SDL_RWops *src) { - return(NULL); + return(NULL); } -#endif -static inline SDL_Surface *IMG_ReadXPMFromArray(const char **xpm) +SDL_Surface *IMG_ReadXPMFromArray(char **xpm) { return NULL; } diff --git a/src/sdl/SDL_icon.xpm b/src/sdl/SDL_icon.xpm index cf72960d..30259d55 100644 --- a/src/sdl/SDL_icon.xpm +++ b/src/sdl/SDL_icon.xpm @@ -1,425 +1,213 @@ /* XPM */ -static char * C:\Repo\srb2\src\sdl\SDL_icon_xpm[] = { -"32 32 390 2", -" c None", -". c #4F4F70", -"+ c #4D4D87", -"@ c #4D4D84", -"# c #4E4E6C", -"$ c #6C6C95", -"% c #5E5EB2", -"& c #6B6BE7", -"* c #7373F9", -"= c #7C7CFF", -"- c #6F70E7", -"; c #494BB2", -"> c #4F4FA3", -", c #6464D4", -"' c #7979F5", -") c #5F5FCA", -"! c #5D5D93", -"~ c #3A3A9F", -"{ c #6060AC", -"] c #777793", -"^ c #5C5CB3", -"/ c #7373EA", -"( c #7A7AFF", -"_ c #7575FF", -": c #7979FF", -"< c #6264DD", -"[ c #47478C", -"} c #564567", -"| c #4647D0", -"1 c #5C5CAE", -"2 c #5E5EFF", -"3 c #2929FF", -"4 c #1D1DFF", -"5 c #1919D1", -"6 c #4F4F90", -"7 c #1E1ECE", -"8 c #5858FF", -"9 c #6767A8", -"0 c #4949A0", -"a c #7070FB", -"b c #7D7DFF", -"c c #7777FF", -"d c #7373FF", -"e c #7272FF", -"f c #7878FF", -"g c #6465D8", -"h c #363886", -"i c #9F7655", -"j c #C89B5C", -"k c #1D1CB7", -"l c #3031B1", -"m c #1919F4", -"n c #1111FF", -"o c #1818FF", -"p c #1B1BFF", -"q c #1C1CFF", -"r c #2626B3", -"s c #1E1EC8", -"t c #1A1AE8", -"u c #24249F", -"v c #2F2FD2", -"w c #7676FF", -"x c #6869E2", -"y c #414290", -"z c #8C6751", -"A c #FCBA68", -"B c #E9BD7D", -"C c #201EB8", -"D c #090AB8", -"E c #1616EB", -"F c #1818FD", -"G c #1414EE", -"H c #1010E1", -"I c #0E0EE2", -"J c #0E0EF4", -"K c #0606B2", -"L c #7A7A89", -"M c #0C0C9A", -"N c #0A0AA7", -"O c #2424E4", -"P c #6669E6", -"Q c #4F4A8F", -"R c #BF853B", -"S c #FFD98D", -"T c #CDAB76", -"U c #1717C4", -"V c #0F10BA", -"W c #0909B6", -"X c #0505C3", -"Y c #0000B6", -"Z c #0000BE", -"` c #0000AD", -" . c #1D1D83", -".. c #63638E", -"+. c #090975", -"@. c #1414F3", -"#. c #5B5BFF", -"$. c #7B7BFF", -"%. c #7070FF", -"&. c #6E6EFF", -"*. c #7172F6", -"=. c #625DAF", -"-. c #BA9E6C", -";. c #887167", -">. c #090DF2", -",. c #1313BE", -"'. c #000085", -"). c #0000AC", -"!. c #0202AA", -"~. c #242488", -"{. c #1414C7", -"]. c #1717FF", -"^. c #5959FF", -"/. c #7F7FFF", -"(. c #7474FF", -"_. c #7171FF", -":. c #8686FF", -"<. c #7574FF", -"[. c #797CFF", -"}. c #5756B8", -"|. c #1C19A4", -"1. c #1617FF", -"2. c #1212BD", -"3. c #040485", -"4. c #0707A4", -"5. c #1B1B71", -"6. c #373797", -"7. c #1616FF", -"8. c #5050FF", -"9. c #8080FF", -"0. c #AAAAFF", -"a. c #AEAEF6", -"b. c #8A8AEF", -"c. c #6969FB", -"d. c #2728FF", -"e. c #1314FF", -"f. c #1919FF", -"g. c #1313E8", -"h. c #1F1FF4", -"i. c #5454FF", -"j. c #6D6DF0", -"k. c #6868B5", -"l. c #0B0BB8", -"m. c #1212C5", -"n. c #1616FC", -"o. c #1515FF", -"p. c #1212FF", -"q. c #2323FF", -"r. c #3636FF", -"s. c #4040FF", -"t. c #4343F9", -"u. c #5D5DB8", -"v. c #7F7F92", -"w. c #878793", -"x. c #4B4B94", -"y. c #0B0CE2", -"z. c #1313FF", -"A. c #4C4CFF", -"B. c #8282FF", -"C. c #7171ED", -"D. c #636394", -"E. c #575785", -"F. c #A9A99C", -"G. c #1414BC", -"H. c #1414FF", -"I. c #0707FD", -"J. c #2525AA", -"K. c #A8A8A4", -"L. c #EBEBE2", -"M. c #F9F9F2", -"N. c #E1E1CC", -"O. c #4D4D9F", -"P. c #0B0BF7", -"Q. c #2121FF", -"R. c #3232FF", -"S. c #5555FF", -"T. c #6161B4", -"U. c #B5B5B2", -"V. c #FFFFF8", -"W. c #4F4F9A", -"X. c #0B0BF5", -"Y. c #1616C5", -"Z. c #A8A8A1", -"`. c #FFFFFC", -" + c #FFFFFF", -".+ c #C0C0C4", -"++ c #1212D4", -"@+ c #4444FF", -"#+ c #6464FF", -"$+ c #8383FF", -"%+ c #6767C3", -"&+ c #E4E4E4", -"*+ c #9494AE", -"=+ c #0808DF", -"-+ c #0D0DF2", -";+ c #61619A", -">+ c #F1F1E0", -",+ c #E8E8DD", -"'+ c #2424BB", -")+ c #1010FF", -"!+ c #3434FF", -"~+ c #6161FF", -"{+ c #6969D2", -"]+ c #EFEFF0", -"^+ c #C2C2BA", -"/+ c #1010B6", -"(+ c #0909AC", -"_+ c #A4A49A", -":+ c #EAEADE", -"<+ c #2525B8", -"[+ c #2F2FFF", -"}+ c #3C3CB5", -"|+ c #EEEEEE", -"1+ c #BBBBAD", -"2+ c #0B0B56", -"3+ c #0B0BFC", -"4+ c #1212EF", -"5+ c #0C0C3E", -"6+ c #919187", -"7+ c #DEDED6", -"8+ c #1F1FC0", -"9+ c #1A1AFF", -"0+ c #1717FA", -"a+ c #1515F8", -"b+ c #1111FC", -"c+ c #494992", -"d+ c #999998", -"e+ c #3E3E3B", -"f+ c #3C3C99", -"g+ c #535397", -"h+ c #5A5A4D", -"i+ c #6F6F70", -"j+ c #BFBFC9", -"k+ c #1111D6", -"l+ c #1515F1", -"m+ c #0F0FE2", -"n+ c #0D0DD9", -"o+ c #0909CD", -"p+ c #0808C7", -"q+ c #0505C7", -"r+ c #0303CB", -"s+ c #0101C0", -"t+ c #0202AF", -"u+ c #0606AC", -"v+ c #121283", -"w+ c #BBBBBB", -"x+ c #BEBEBE", -"y+ c #2F2F2E", -"z+ c #C7C8BB", -"A+ c #D8DAD1", -"B+ c #272828", -"C+ c #929292", -"D+ c #8688C7", -"E+ c #0506F6", -"F+ c #1616F5", -"G+ c #0B0BD3", -"H+ c #0202B6", -"I+ c #0000AF", -"J+ c #0000B4", -"K+ c #0000BD", -"L+ c #0000BB", -"M+ c #00009E", -"N+ c #2C2C7E", -"O+ c #6A6A8B", -"P+ c #959595", -"Q+ c #F0F0F1", -"R+ c #E1E1E1", -"S+ c #8C8E90", -"T+ c #BEBEBF", -"U+ c #C9C7C5", -"V+ c #939699", -"W+ c #E7EAED", -"X+ c #CBCBC7", -"Y+ c #413B9B", -"Z+ c #0607DD", -"`+ c #0C0CE2", -" @ c #0303B9", -".@ c #0000A8", -"+@ c #181888", -"@@ c #6A6A6A", -"#@ c #626263", -"$@ c #4B4B4C", -"%@ c #3E3B36", -"&@ c #9B805C", -"*@ c #D9B07D", -"=@ c #C9AE89", -"-@ c #B9AF9E", -";@ c #C7C5C4", -">@ c #CBCCCF", -",@ c #C7C6C6", -"'@ c #AEA59A", -")@ c #B69974", -"!@ c #D8B87F", -"~@ c #9B8272", -"{@ c #0E0B9B", -"]@ c #0000B7", -"^@ c #0000B8", -"/@ c #000082", -"(@ c #00007A", -"_@ c #636379", -":@ c #62533E", -"<@ c #B59B6C", -"[@ c #DEB07B", -"}@ c #FECC90", -"|@ c #FFCE92", -"1@ c #FEC98C", -"2@ c #F1BD82", -"3@ c #D1A979", -"4@ c #BC9E73", -"5@ c #CCA777", -"6@ c #EAB980", -"7@ c #FFCD90", -"8@ c #FFD595", -"9@ c #FDD782", -"0@ c #413678", -"a@ c #0000AE", -"b@ c #000077", -"c@ c #010193", -"d@ c #0C0CE4", -"e@ c #38389E", -"f@ c #EEC585", -"g@ c #FFDA9D", -"h@ c #FFC992", -"i@ c #FFC88F", -"j@ c #FFC990", -"k@ c #FFCE93", -"l@ c #FFD094", -"m@ c #FFCC92", -"n@ c #C9A174", -"o@ c #EDBD88", -"p@ c #FAD287", -"q@ c #3A2F7F", -"r@ c #0000BA", -"s@ c #0000B0", -"t@ c #0101B2", -"u@ c #1111ED", -"v@ c #1919C1", -"w@ c #95887C", -"x@ c #DCAC6E", -"y@ c #FFD393", -"z@ c #FFCD94", -"A@ c #FFCA93", -"B@ c #FFC991", -"C@ c #FFC78E", -"D@ c #FFCB91", -"E@ c #E0B581", -"F@ c #BB9A6F", -"G@ c #FFDC97", -"H@ c #C1A173", -"I@ c #0E0B9A", -"J@ c #0000B5", -"K@ c #0101B6", -"L@ c #1010E0", -"M@ c #1616EC", -"N@ c #A68156", -"O@ c #E7AC6B", -"P@ c #FFC582", -"Q@ c #FFCF8F", -"R@ c #FFD195", -"S@ c #FFD296", -"T@ c #FFD396", -"U@ c #FFD193", -"V@ c #FFD28F", -"W@ c #D2A96B", -"X@ c #2F2482", -"Y@ c #0000C1", -"Z@ c #0000C0", -"`@ c #0000BF", -" # c #0101BF", -".# c #1212F0", -"+# c #767698", -"@# c #9C866E", -"## c #A9865D", -"$# c #C0915D", -"%# c #C89760", -"&# c #C29360", -"*# c #AD8A61", -"=# c #9D8971", -"-# c #7F7A7A", -";# c #70708F", -"># c #6F6F91", -",# c #575788", -"'# c #464687", -")# c #2F2F87", -"!# c #15158F", -"~# c #0101A8", -"{# c #1313FB", -"]# c #57579F", -"^# c #343487", -"/# c #434388", +static const char *SDL_icon_xpm[] = { +/* columns rows colors chars-per-pixel */ +"32 32 175 2 ", +" c None", +". c #2E2E2E", +"X c #3C3C3C", +"o c #493939", +"O c #4E473F", +"+ c #161658", +"@ c #131369", +"# c #06067B", +"$ c #111173", +"% c #16167F", +"& c #252567", +"* c #372B7C", +"= c #3D3679", +"- c #41414A", +"; c #575655", +": c #6A5841", +"> c #5B4B72", +", c #616160", +"< c #7B7B7B", +"1 c #906E49", +"2 c #89685D", +"3 c #A67B4A", +"4 c #AA7F50", +"5 c #9B7560", +"6 c #856C78", +"7 c #997B7D", +"8 c #B48552", +"9 c #BA8A55", +"0 c #A48665", +"q c #B98F67", +"w c #B9946A", +"e c #B7937A", +"r c #C8955C", +"t c #CA9966", +"y c #DAA469", +"u c #C9A37B", +"i c #D7AB7B", +"p c #DFB07D", +"a c #EBAE6A", +"s c #E5B27A", +"d c #F1B779", +"f c #0A0A83", +"g c #05058B", +"h c #060687", +"j c #101089", +"k c #131382", +"l c #040494", +"z c #02029D", +"x c #0C0B9C", +"c c #120F9E", +"v c #19199B", +"b c #382D84", +"n c #39398D", +"m c #222296", +"M c #0101A6", +"N c #0A0AA2", +"B c #0202AC", +"V c #1919A2", +"C c #1616AD", +"Z c #0000B5", +"A c #0202BC", +"S c #0C0CB6", +"D c #1313B3", +"F c #1011BD", +"G c #1B1BBE", +"H c #2B2BAC", +"J c #3737A1", +"K c #2A26BE", +"L c #2A29B4", +"P c #3B3BB8", +"I c #48478B", +"U c #57578A", +"Y c #4A499A", +"T c #524F95", +"R c #565399", +"E c #4C4CA8", +"W c #524DA7", +"Q c #5353A4", +"! c #5555A9", +"~ c #5555B4", +"^ c #5656B7", +"/ c #6464A6", +"( c #6F67B5", +") c #0404C3", +"_ c #0707CA", +"` c #1414CB", +"' c #1A1AC6", +"] c #0A0AD3", +"[ c #0D0DDC", +"{ c #1A1AD4", +"} c #1010DF", +"| c #1E1EDE", +" . c #1817DE", +".. c #221FCA", +"X. c #2B2BCC", +"o. c #2727C9", +"O. c #3434C3", +"+. c #3434D4", +"@. c #0F0FE2", +"#. c #1313E5", +"$. c #1515ED", +"%. c #1B1BEA", +"&. c #1C1CE4", +"*. c #1515F4", +"=. c #1818F3", +"-. c #1717FD", +";. c #1818FF", +":. c #2B2BE9", +">. c #2424FF", +",. c #2A2AFF", +"<. c #2222F1", +"1. c #3737FF", +"2. c #5D5DC3", +"3. c #5F5FC9", +"4. c #5655C2", +"5. c #4747D1", +"6. c #5B5BD4", +"7. c #6565C8", +"8. c #6363DA", +"9. c #4545FF", +"0. c #4D4DFC", +"q. c #5454FF", +"w. c #5959FF", +"e. c #6969E5", +"r. c #6B6CEA", +"t. c #6666E7", +"y. c #6B6BFE", +"u. c #6767F8", +"i. c #7070F6", +"p. c #7373FF", +"a. c #7C7CFF", +"s. c #91918F", +"d. c #8F9090", +"f. c #979797", +"g. c #9C9C9C", +"h. c #8585A1", +"j. c #9C9CA7", +"k. c #9292B6", +"l. c #A4A4A4", +"z. c #BDB2A4", +"x. c #A4A4B1", +"c. c #BFBFBD", +"v. c #BABAB7", +"b. c #C8AA87", +"n. c #DAAE82", +"m. c #DBB081", +"M. c #EBBA85", +"N. c #F3BF84", +"B. c #F2BE88", +"V. c #C2B3A3", +"C. c #FBC386", +"Z. c #FCC68C", +"A. c #FFC88F", +"S. c #F4C387", +"D. c #FFC990", +"F. c #C3C1BF", +"G. c #8F8FCB", +"H. c #BDBDC2", +"J. c #BDBDD1", +"K. c #8888F9", +"L. c #A4A4FB", +"P. c #CDCDCC", +"I. c #CECAC6", +"U. c #D3CFCA", +"Y. c #D3D0CC", +"T. c #C0C0D5", +"R. c #D6D5D4", +"E. c #D7D7DD", +"W. c #E1E1DF", +"Q. c #DEDEE1", +"!. c #E4E4E4", +"~. c #E8E8E8", +"^. c #F0F0EE", +"/. c #F5F5F2", +"(. c #FFFFFF", +/* pixels */ " ", " ", " ", -" . + @ # ", -" $ % & * = - ; > , ' ) ! ", -" ~ { ] ^ / = ( _ : < [ } | 1 2 3 4 5 6 ", -" 7 8 9 0 a b c d e f g h i j k l m n o p q r ", -" s t u v _ f d d d w x y z A B C D E F G H I J K L ", -" M N O _ c e d d d _ P Q R S T U V W X Y Z ` ... ", -" +.@.#.$.d d d d %.&._ *.=.-.;.>.,.'.).!.~. ", -" {.].^./.(.d d _.$.:._ <.[.}.|.1.2.3.4.5. ", -" 6.7.7.4 8.e : w 9.0.a.b.c.2 d.e.f.g.h.i.j.k. ", -" l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.o o z.A.B./.b C.D. ", -" E.F.G.].o H.z.I.J.K.L.M.N.O.P.o o o Q.R.S._.b B.T. ", -" U.V.W.X.f.f.7.Y.Z.`. + + +.+++].o o o.n z.q.@+#+$+%+ ", -" &+ +*+=+].o -+;+>+ + + + +,+'+H.o o o o o H.)+o !+~+{+ ", -" ]+ +^+/+H.o.(+_+ + + + + +:+<+z.o o o o o o o 7.n H.[+}+ ", -" |+ +1+2+3+4+5+6+ + + + + +7+8+H.o o f.9+f.9+f.F 0+a+b+o.c+ ", -" &+ +d+e+f+g+h+i+ + + + + +j+k+].f.9+l+m+n+o+p+q+r+s+t+u+v+ ", -" w+ +x+y+z+A+B+C+ + + + + +D+E+9+F+G+H+I+J+K+L+M+N+O+ ", -" P+Q+R+S+T+U+V+W+ + + + +X+Y+Z+`+ @I+J+Z .@+@E. ", -" @@#@$@%@&@*@=@-@;@>@,@'@)@!@~@{@]@^@I+/@(@_@ ", -" :@<@[@}@|@1@2@3@4@5@6@7@8@9@0@L+a@b@c@d@e@ ", -" f@g@h@i@i@j@k@l@|@m@n@o@p@q@r@s@t@u@p v@ ", -" w@x@y@z@A@B@i@C@D@E@F@G@H@I@L+J@K@L@p M@ ", -" N@O@P@Q@R@S@T@U@V@W@X@Y@Z@Y@`@ #.#p +# ", -" @###$#%#&#*#=#-#;#>#,#'#)#!#~#{#]# ", -" ^#/# ", +" I Q T = ", +" Q 7.e.r.i.8.E E 3.r.6.J ", +" H ~ n 4.r.p.p.p.p.8.R > 5.^ w.,.-.{ v ", +" { 9.^ & P t.p.p.p.p.p.8.I 5 q K L <.;.;.;.-.' ", +" { %.H +.y.p.p.p.p.p.e.Y 2 a n.K F $.*.$.@.} ] N ", +" x D :.y.p.p.p.p.p.p.r.R 8 C.u ..F A ) A Z M h $ ", +" f =.q.p.p.p.p.p.p.p.p.i.( e 6 $.` l B M g ", +" ` ;.q.p.p.p.p.p.a.K.a.p.p.4.L -.` l N % ", +" V =.-.>.q.y.p.p.p.L.L.K.i.w.,.-.;.$.<.q.u.2. ", +" D { =.-.;.>.1.1.9.( h.h.Q &.-.-.-.;.9.p.p.p.r.! ", +" U j.o.-.;.-.;.-.P x.Q.^.R.~ *.-.;.;.>.1.q.y.p.i.2. ", +" H./.! *.;.;.;.o.x./.(.(.(.J.| -.-.;.-.-.;.,.9.u.p.7. ", +" !.(.k.#.;.-.=./ !.(.(.(.(.Q.X.-.;.;.;.;.-.-.;.;.1.w.6. ", +" ~.(.H.G ;.-.D j.(.(.(.(.(.!.O.-.-.;.;.;.-.;.-.;.-.;.,.O. ", +" ~.(.v.@ *.$.+ d.(.(.(.(.(.E.o.-.-.;.;.-.;.;.;.*.=.=.*.$.v ", +" ~.(.l.- Y T ; < (.(.(.(.(.J.&.-.;.;.$.@.[ ] _ ) ) Z B B f ", +" P.(.F.X c.I.X f.(.(.(.(.(.G.=.-.=.] A Z Z Z Z z f $ ", +" l.!.R.s.F.I.g.W.(.(.(.(.R.E .[ A Z Z Z B g $ ", +" . , ; - 0 M.b.V.U.R.Y.z.u n.7 c Z Z B g # + ", +" : w p Z.D.A.S.p u i M.A.A.S.* Z B h z ] C ", +" s D.D.A.A.A.A.A.A.A.i B.B.b A Z Z @.-.` ", +" 1 y C.D.A.A.A.A.A.M.u Z.e c A Z Z [ ;.&. ", +" 8 y d C.A.A.A.C.B.t * B Z Z Z A #.=.m ", +" 3 9 r t r 9 8 o @ $ # f j l B #.V ", +" j k ", " ", " ", " ", -" "}; +" " +}; diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 0dd022a8..5cb319f6 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -39,6 +39,10 @@ #ifdef HAVE_IMAGE #include "SDL_image.h" +#elif 1 +#define LOAD_XPM //I want XPM! +#include "IMG_xpm.c" //Alam: I don't want to add SDL_Image.dll/so +#define HAVE_IMAGE //I have SDL_Image, sortof #endif #ifdef HAVE_IMAGE @@ -1014,7 +1018,6 @@ static inline boolean I_SkipFrame(void) if (!paused) return false; /* FALLTHRU */ - case GS_TIMEATTACK: case GS_WAITINGPLAYERS: return skip; // Skip odd frames default: diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 3126643c..e124dcf1 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -66,6 +66,7 @@ static boolean midimode; static Mix_Music *music; static UINT8 music_volume, midi_volume, sfx_volume; static float loop_point; +static boolean songpaused; #ifdef HAVE_LIBGME static Music_Emu *gme; @@ -102,6 +103,7 @@ void I_StartupSound(void) } sound_started = true; + songpaused = false; Mix_AllocateChannels(256); } @@ -176,7 +178,7 @@ static Mix_Chunk *ds2chunk(void *stream) return NULL; // would and/or did wrap, can't store. break; } - sound = Z_Malloc(newsamples<<2, PU_SOUND, NULL); // samples * frequency shift * bytes per sample * channels + sound = malloc(newsamples<<2); // samples * frequency shift * bytes per sample * channels s = (SINT8 *)stream; d = (INT16 *)sound; @@ -304,7 +306,7 @@ void *I_GetSfx(sfxinfo_t *sfx) gme_track_info(emu, &info, 0); len = (info->play_length * 441 / 10) << 2; - mem = Z_Malloc(len, PU_SOUND, NULL); + mem = malloc(len); gme_play(emu, len >> 1, mem); gme_delete(emu); @@ -376,7 +378,7 @@ void *I_GetSfx(sfxinfo_t *sfx) gme_track_info(emu, &info, 0); len = (info->play_length * 441 / 10) << 2; - mem = Z_Malloc(len, PU_SOUND, NULL); + mem = malloc(len); gme_play(emu, len >> 1, mem); gme_delete(emu); @@ -450,7 +452,7 @@ static void mix_gme(void *udata, Uint8 *stream, int len) (void)udata; // no gme? no music. - if (!gme || gme_track_ended(gme)) + if (!gme || gme_track_ended(gme) || songpaused) return; // play gme into stream @@ -458,7 +460,7 @@ static void mix_gme(void *udata, Uint8 *stream, int len) // apply volume to stream for (i = 0, p = (short *)stream; i < len/2; i++, p++) - *p = ((INT32)*p) * music_volume / 31; + *p = ((INT32)*p) * music_volume*2 / 42; } #endif @@ -476,12 +478,14 @@ void I_PauseSong(INT32 handle) { (void)handle; Mix_PauseMusic(); + songpaused = true; } void I_ResumeSong(INT32 handle) { (void)handle; Mix_ResumeMusic(); + songpaused = false; } // diff --git a/src/sdl12/i_cdmus.c b/src/sdl12/i_cdmus.c index 1eeac370..b3490592 100644 --- a/src/sdl12/i_cdmus.c +++ b/src/sdl12/i_cdmus.c @@ -60,7 +60,7 @@ void SDL_SYS_CDQuit(void) UINT8 cdaudio_started = 0; // for system startup/shutdown -consvar_t cd_volume = {"cd_volume","31",CV_SAVE,soundvolume_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cd_volume = {"cd_volume","18",CV_SAVE,soundvolume_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cdUpdate = {"cd_update","1",CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; #ifndef NOSDLCD diff --git a/src/sdl12/i_video.c b/src/sdl12/i_video.c index f44b60c8..ac9d4ffc 100644 --- a/src/sdl12/i_video.c +++ b/src/sdl12/i_video.c @@ -1311,7 +1311,6 @@ static inline boolean I_SkipFrame(void) case GS_LEVEL: if (!paused) return false; - case GS_TIMEATTACK: case GS_WAITINGPLAYERS: return skip; // Skip odd frames default: diff --git a/src/sounds.c b/src/sounds.c index f5a7ee9b..991941e0 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -147,7 +147,6 @@ sfxinfo_t S_sfx[NUMSFX] = {"drown", false, 192, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"fizzle", false, 127, 8, -1, NULL, 0, -1, -1, LUMPERROR}, {"gbeep", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Grenade beep - {"gclose", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"ghit" , false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"gloop", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"gspray", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, @@ -294,7 +293,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"s1ba", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s1bb", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s1bc", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s1bd", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"s1bd", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Ballhog bounce {"s1be", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s1bf", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s1c0", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, @@ -316,7 +315,7 @@ sfxinfo_t S_sfx[NUMSFX] = // Sonic 2 sounds {"s220", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s221", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"s221", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Lap sound {"s222", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s223", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s224", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, @@ -343,7 +342,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"s239", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s23a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s23b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s23c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"s23c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Drift boost {"s23d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s23e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s23f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, @@ -362,7 +361,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"s24c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s24d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s24e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s24f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Normal finish + {"s24f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s250", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s251", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s252", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, @@ -378,7 +377,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"s25c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s25d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s25e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s25f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"s25f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Perfect start boost {"s260", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s261", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s262", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, @@ -405,7 +404,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"s3k37", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3k38", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3k39", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k3a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"s3k3a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Kart item shield {"s3k3b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3k3c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3k3d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, @@ -416,7 +415,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"s3k42", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3k43", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3k44", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k45", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"s3k45", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Kart Thunder Shield use {"s3k46", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3k47", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3k48", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, @@ -451,9 +450,9 @@ sfxinfo_t S_sfx[NUMSFX] = {"s3k65", false, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Blue Spheres {"s3k66", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3k67", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k68", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"s3k68", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Kart final lap {"s3k69", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k6a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"s3k6a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Kart finish {"s3k6b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3k6c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3k6d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, @@ -493,11 +492,11 @@ sfxinfo_t S_sfx[NUMSFX] = {"s3k8f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3k90", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3k91", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k92", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"s3k92", false, 64, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // Kart Hyudoro use {"s3k93", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3k94", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3k95", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k96", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"s3k96", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Kart Orbinaut {"s3k97", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3k98", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3k99", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, @@ -514,13 +513,13 @@ sfxinfo_t S_sfx[NUMSFX] = {"s3ka4", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3ka5", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3ka6", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3ka7", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"s3ka7", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Kart 3,2,1 {"s3ka8", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3ka9", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3kaa", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3kab", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3kac", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kad", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"s3kad", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Kart GO! {"s3kae", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3kaf", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3kb0", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, @@ -543,7 +542,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"s3kbel", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3kbfs", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3kbfl", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kc0s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"s3kc0s", false, 64, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // Kart Jawz {"s3kc0l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3kc1s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3kc1l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, @@ -557,12 +556,13 @@ sfxinfo_t S_sfx[NUMSFX] = {"s3kc5l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3kc6s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3kc6l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kc7", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"s3kc7s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"s3kc7l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3kc8s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3kc8l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3kc9s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3kc9l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kcas", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"s3kcas", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Kart respawn {"s3kcal", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3kcbs", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3kcbl", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, @@ -600,14 +600,14 @@ sfxinfo_t S_sfx[NUMSFX] = {"s3kdbl", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // 3D Blast sounds (the "missing" ones are direct copies of S3K's, no minor differences what-so-ever) - {"3db06", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"3db06", false, 64, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // Bumper stolen {"3db09", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"3db14", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"3db16", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Sonic CD sounds {"cdfm00", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm01", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"cdfm01", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Sneaker boost {"cdfm02", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"cdfm03", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"cdfm04", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, @@ -645,7 +645,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"cdfm36", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"cdfm37", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"cdfm38", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm39", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"cdfm39", false, 64, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // SS Mine deployed {"cdfm40", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"cdfm41", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"cdfm42", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, @@ -676,7 +676,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"cdfm67", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"cdfm68", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"cdfm69", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm70", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"cdfm70", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Trail item dragging {"cdfm71", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"cdfm72", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"cdfm73", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, @@ -695,7 +695,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"cdpcm6", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"cdpcm7", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"cdpcm8", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdpcm9", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"cdpcm9", false, 64, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // No damage taken // Knuckles Chaotix sounds {"kc2a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, @@ -703,7 +703,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"kc2c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"kc2d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"kc2e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc2f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Pogo Spring + {"kc2f", false, 64, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // Pogo Spring use {"kc30", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"kc31", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"kc32", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, @@ -726,7 +726,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"kc43", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"kc44", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"kc45", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc46", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"kc46", false, 64, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // Shrink use {"kc47", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"kc48", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Vote picked {"kc49", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, @@ -743,10 +743,10 @@ sfxinfo_t S_sfx[NUMSFX] = {"kc54", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"kc55", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"kc56", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc57", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"kc57", false, 64, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // SPB locked in {"kc58", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc59", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Shrink - {"kc5a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Grow + {"kc59", false, 64, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // Shrink + {"kc5a", false, 64, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // Grow {"kc5b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"kc5c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"kc5d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, @@ -777,8 +777,8 @@ sfxinfo_t S_sfx[NUMSFX] = {"mlap", true, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"sboost", true, 90, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"mush", false, 90, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"star", false, 140, 16, -1, NULL, 0, -1, -1, LUMPERROR}, - {"mega", false, 140, 16, -1, NULL, 0, -1, -1, LUMPERROR}, + {"kinvnc", false, 140, 8, -1, NULL, 0, -1, -1, LUMPERROR}, + {"kgrow", false, 140, 8, -1, NULL, 0, -1, -1, LUMPERROR}, {"bomb", false, 110, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"bomb2", false, 110, 8, -1, NULL, 0, -1, -1, LUMPERROR}, {"peel", false, 100, 0, -1, NULL, 0, -1, -1, LUMPERROR}, @@ -799,13 +799,19 @@ sfxinfo_t S_sfx[NUMSFX] = {"mkitm7", true, 72, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"mkitm8", true, 72, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"mkitmF", true, 72, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"mkitmE", true, 72, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"clash", false, 64, 8, -1, NULL, 0, -1, -1, LUMPERROR}, {"tossed", false, 150, 8, -1, NULL, 0, -1, -1, LUMPERROR}, {"shelit", false, 64, 16, -1, NULL, 0, -1, -1, LUMPERROR}, {"vroom", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"boing", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"smkinv", false, 140, 16, -1, NULL, 0, -1, -1, LUMPERROR}, + {"smkinv", false, 140, 8, -1, NULL, 0, -1, -1, LUMPERROR}, {"screec", false, 52, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"yeeeah", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"noooo1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"noooo2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"hogbom", false, 110, 8, -1, NULL, 0, -1, -1, LUMPERROR}, + {"dbgsal", false, 110, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // SRB2kart - Skin sounds {"kwin", false, 64, 0, -1, NULL, 0, SKSWIN, -1, LUMPERROR}, diff --git a/src/sounds.h b/src/sounds.h index 7954a5ef..2f073273 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -219,7 +219,6 @@ typedef enum sfx_drown, sfx_fizzle, sfx_gbeep, - sfx_gclose, sfx_ghit, sfx_gloop, sfx_gspray, @@ -629,7 +628,8 @@ typedef enum sfx_s3kc5l, sfx_s3kc6s, sfx_s3kc6l, - sfx_s3kc7, + sfx_s3kc7s, + sfx_s3kc7l, sfx_s3kc8s, sfx_s3kc8l, sfx_s3kc9s, @@ -849,8 +849,8 @@ typedef enum sfx_mlap, sfx_sboost, sfx_mush, - sfx_star, - sfx_mega, + sfx_kinvnc, + sfx_kgrow, sfx_bomb, sfx_bomb2, sfx_peel, @@ -871,6 +871,7 @@ typedef enum sfx_mkitm7, sfx_mkitm8, sfx_mkitmF, + sfx_mkitmE, sfx_clash, sfx_tossed, sfx_shelit, @@ -878,6 +879,11 @@ typedef enum sfx_boing, sfx_smkinv, sfx_screec, + sfx_yeeeah, + sfx_noooo1, + sfx_noooo2, + sfx_hogbom, + sfx_dbgsal, sfx_kwin, sfx_klose, diff --git a/src/st_stuff.c b/src/st_stuff.c index 33f7a275..02e5b657 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -229,7 +229,7 @@ void ST_doPaletteStuff(void) if (rendermode != render_none) { - V_SetPaletteLump(GetPalette()); // Reset the palette + //V_SetPaletteLump(GetPalette()); // Reset the palette -- is this needed? if (!splitscreen) V_SetPalette(palette); } @@ -755,63 +755,75 @@ static void ST_drawLevelTitle(void) char *zonttl = mapheaderinfo[gamemap-1]->zonttl; // SRB2kart char *actnum = mapheaderinfo[gamemap-1]->actnum; INT32 lvlttlxpos; - INT32 subttlxpos = BASEVIDWIDTH/2; INT32 ttlnumxpos; INT32 zonexpos; + INT32 dupcalc = (vid.width/vid.dupx); + UINT8 gtc = G_GetGametypeColor(gametype); + INT32 sub = 0; + INT32 bary = (splitscreen) + ? BASEVIDHEIGHT/2 + : 163; + INT32 lvlw; - INT32 lvlttly; - INT32 zoney; - - if (!(timeinmap > 2 && timeinmap-3 < 110)) + if (timeinmap > 113) return; - if (strlen(actnum) > 0) - lvlttlxpos = ((BASEVIDWIDTH/2) - (V_LevelNameWidth(lvlttl)/2)) - V_LevelNameWidth(actnum); - else - lvlttlxpos = ((BASEVIDWIDTH/2) - (V_LevelNameWidth(lvlttl)/2)); + lvlw = V_LevelNameWidth(lvlttl); - ttlnumxpos = lvlttlxpos + V_LevelNameWidth(lvlttl); - if (strlen(zonttl) > 0) - zonexpos = ttlnumxpos - V_LevelNameWidth(zonttl); // SRB2kart + if (strlen(actnum) > 0) + lvlttlxpos = ((BASEVIDWIDTH/2) - (lvlw/2)) - V_LevelNameWidth(actnum); else - zonexpos = ttlnumxpos - V_LevelNameWidth(M_GetText("ZONE")); + lvlttlxpos = ((BASEVIDWIDTH/2) - (lvlw/2)); + + zonexpos = ttlnumxpos = lvlttlxpos + lvlw; + if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE)) + { + if (zonttl[0]) + zonexpos -= V_LevelNameWidth(zonttl); // SRB2kart + else + zonexpos -= V_LevelNameWidth(M_GetText("ZONE")); + } if (lvlttlxpos < 0) lvlttlxpos = 0; - // There's no consistent algorithm that can accurately define the old positions - // so I just ended up resorting to a single switct statement to define them - switch (timeinmap-3) + if (timeinmap > 105) { - case 0: zoney = 200; lvlttly = 0; break; - case 1: zoney = 188; lvlttly = 12; break; - case 2: zoney = 176; lvlttly = 24; break; - case 3: zoney = 164; lvlttly = 36; break; - case 4: zoney = 152; lvlttly = 48; break; - case 5: zoney = 140; lvlttly = 60; break; - case 6: zoney = 128; lvlttly = 72; break; - case 105: zoney = 80; lvlttly = 104; break; - case 106: zoney = 56; lvlttly = 128; break; - case 107: zoney = 32; lvlttly = 152; break; - case 108: zoney = 8; lvlttly = 176; break; - case 109: zoney = 0; lvlttly = 200; break; - default: zoney = 104; lvlttly = 80; break; + INT32 count = (113 - (INT32)(timeinmap)); + sub = dupcalc; + while (count-- > 0) + sub >>= 1; + sub = -sub; } - if (strlen(actnum) > 0) - V_DrawLevelTitle(ttlnumxpos+12, zoney, 0, actnum); + { + dupcalc = (dupcalc - BASEVIDWIDTH)>>1; + V_DrawFill(sub - dupcalc, bary+9, ttlnumxpos+dupcalc + 1, 2, 31); + V_DrawDiag(sub + ttlnumxpos + 1, bary, 11, 31); + V_DrawFill(sub - dupcalc, bary, ttlnumxpos+dupcalc, 10, gtc); + V_DrawDiag(sub + ttlnumxpos, bary, 10, gtc); + if (subttl[0]) + V_DrawRightAlignedString(sub + zonexpos - 8, bary+1, V_ALLOWLOWERCASE, subttl); + //else + //V_DrawRightAlignedString(sub + zonexpos - 8, bary+1, V_ALLOWLOWERCASE, va("%s Mode", gametype_cons_t[gametype].strvalue)); + } - V_DrawLevelTitle(lvlttlxpos, lvlttly, 0, lvlttl); + ttlnumxpos += sub; + lvlttlxpos += sub; + zonexpos += sub; + + V_DrawLevelTitle(lvlttlxpos, bary-18, 0, lvlttl); if (strlen(zonttl) > 0) - V_DrawLevelTitle(zonexpos, zoney, 0, zonttl); + V_DrawLevelTitle(zonexpos, bary+6, 0, zonttl); else if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE)) - V_DrawLevelTitle(zonexpos, zoney, 0, M_GetText("ZONE")); + V_DrawLevelTitle(zonexpos, bary+6, 0, M_GetText("ZONE")); - if (lvlttly+48 < 200) - V_DrawCenteredString(subttlxpos, lvlttly+48, V_ALLOWLOWERCASE, subttl); + if (actnum[0]) + V_DrawLevelTitle(ttlnumxpos+12, bary+6, 0, actnum); } +/* static void ST_drawFirstPersonHUD(void) { player_t *player = stplyr; @@ -913,11 +925,12 @@ static void ST_drawFirstPersonHUD(void) V_DrawScaledPatch(SCX((BASEVIDWIDTH/2) - (SHORT(p->width)/2) + SHORT(p->leftoffset)), SCY(60 - SHORT(p->topoffset)), V_NOSCALESTART|V_OFFSET|V_TRANSLUCENT, p); } +*/ /* // [21:42] <+Rob> Beige - Lavender - Steel Blue - Peach - Orange - Purple - Silver - Yellow - Pink - Red - Blue - Green - Cyan - Gold static skincolors_t linkColor[14] = -{SKINCOLOR_BEIGE, SKINCOLOR_LAVENDER, SKINCOLOR_STEELBLUE, SKINCOLOR_PEACH, SKINCOLOR_ORANGE, +{SKINCOLOR_BEIGE, SKINCOLOR_LAVENDER, SKINCOLOR_STEEL, SKINCOLOR_PEACH, SKINCOLOR_ORANGE, SKINCOLOR_PURPLE, SKINCOLOR_SILVER, SKINCOLOR_SUPER4, SKINCOLOR_PINK, SKINCOLOR_RED, SKINCOLOR_BLUE, SKINCOLOR_GREEN, SKINCOLOR_CYAN, SKINCOLOR_GOLD}; @@ -967,7 +980,7 @@ static void ST_drawNightsRecords(void) V_DrawString(BASEVIDWIDTH/2 - 48, STRINGY(148), aflag, "BONUS:"); V_DrawRightAlignedString(BASEVIDWIDTH/2 + 48, STRINGY(140), V_ORANGEMAP|aflag, va("%d", stplyr->finishedrings)); V_DrawRightAlignedString(BASEVIDWIDTH/2 + 48, STRINGY(148), V_ORANGEMAP|aflag, va("%d", stplyr->finishedrings * 50)); - ST_DrawNightsOverlayNum(BASEVIDWIDTH/2 + 48, STRINGY(160), aflag, stplyr->lastmarescore, nightsnum, SKINCOLOR_STEELBLUE); + ST_DrawNightsOverlayNum(BASEVIDWIDTH/2 + 48, STRINGY(160), aflag, stplyr->lastmarescore, nightsnum, SKINCOLOR_STEEL); // If new record, say so! if (!(netgame || multiplayer) && G_GetBestNightsScore(gamemap, stplyr->lastmare + 1) <= stplyr->lastmarescore) @@ -1251,7 +1264,7 @@ static void ST_drawNiGHTSHUD(void) // SRB2kart - unused. #endif ) { - ST_DrawNightsOverlayNum(304, STRINGY(16), SPLITFLAGS(V_SNAPTOTOP)|V_SNAPTORIGHT, stplyr->marescore, nightsnum, SKINCOLOR_STEELBLUE); + ST_DrawNightsOverlayNum(304, STRINGY(16), SPLITFLAGS(V_SNAPTOTOP)|V_SNAPTORIGHT, stplyr->marescore, nightsnum, SKINCOLOR_STEEL); } if (!stplyr->exiting @@ -1488,13 +1501,13 @@ static void ST_drawMatchHUD(void) // SRB2kart - unused. static inline void ST_drawRaceHUD(void) { - if (leveltime > TICRATE && leveltime <= 2*TICRATE) + if (leveltime > starttime-(3*TICRATE) && leveltime <= starttime-(2*TICRATE)) V_DrawScaledPatch(SCX((BASEVIDWIDTH - SHORT(race3->width))/2), (INT32)(SCY(BASEVIDHEIGHT/2)), V_NOSCALESTART, race3); - else if (leveltime > 2*TICRATE && leveltime <= 3*TICRATE) + else if (leveltime > starttime-(2*TICRATE) && leveltime <= starttime-TICRATE) V_DrawScaledPatch(SCX((BASEVIDWIDTH - SHORT(race2->width))/2), (INT32)(SCY(BASEVIDHEIGHT/2)), V_NOSCALESTART, race2); - else if (leveltime > 3*TICRATE && leveltime <= 4*TICRATE) + else if (leveltime > starttime-TICRATE && leveltime <= starttime) V_DrawScaledPatch(SCX((BASEVIDWIDTH - SHORT(race1->width))/2), (INT32)(SCY(BASEVIDHEIGHT/2)), V_NOSCALESTART, race1); - else if (leveltime > 4*TICRATE && leveltime <= 5*TICRATE) + else if (leveltime > starttime && leveltime <= starttime+TICRATE) V_DrawScaledPatch(SCX((BASEVIDWIDTH - SHORT(racego->width))/2), (INT32)(SCY(BASEVIDHEIGHT/2)), V_NOSCALESTART, racego); if (circuitmap) @@ -1815,7 +1828,7 @@ static void ST_overlayDrawer(void) */ // GAME OVER pic - if (G_GametypeUsesLives() && stplyr->lives <= 0 && !(hu_showscores && (netgame || multiplayer))) + /*if (G_GametypeUsesLives() && stplyr->lives <= 0 && !(hu_showscores && (netgame || multiplayer))) { patch_t *p; @@ -1825,23 +1838,12 @@ static void ST_overlayDrawer(void) p = sboover; V_DrawScaledPatch((BASEVIDWIDTH - SHORT(p->width))/2, STRINGY(BASEVIDHEIGHT/2 - (SHORT(p->height)/2)), 0, p); - } + }*/ if (!hu_showscores) // hide the following if TAB is held { // Countdown timer for Race Mode - if (countdown) - { - INT32 x = BASEVIDWIDTH/2; - INT32 y = BASEVIDHEIGHT-24; - if (splitscreen) - { - y = (BASEVIDHEIGHT/2)-12; - if (splitscreen > 1) - x = BASEVIDWIDTH/4; - } - V_DrawCenteredString(x, y, K_calcSplitFlags(0), va("%d", countdown/TICRATE)); - } + // ...moved to k_kart.c so we can take advantage of the LAPS_Y value K_drawKartHUD(); @@ -1897,18 +1899,18 @@ static void ST_overlayDrawer(void) strlcpy(name, player_names[stplyr-players], 13); // Show name of player being displayed - V_DrawCenteredString((BASEVIDWIDTH/6), BASEVIDHEIGHT-80, 0, M_GetText("Viewpoint:")); - V_DrawCenteredString((BASEVIDWIDTH/6), BASEVIDHEIGHT-64, V_ALLOWLOWERCASE, name); + V_DrawCenteredString((BASEVIDWIDTH/2), BASEVIDHEIGHT-40, 0, M_GetText("Viewpoint:")); + V_DrawCenteredString((BASEVIDWIDTH/2), BASEVIDHEIGHT-32, V_ALLOWLOWERCASE, name); } // This is where we draw all the fun cheese if you have the chasecam off! - if ((stplyr == &players[displayplayer] && !camera.chase) + /*if ((stplyr == &players[displayplayer] && !camera.chase) || ((splitscreen && stplyr == &players[secondarydisplayplayer]) && !camera2.chase) || ((splitscreen > 1 && stplyr == &players[thirddisplayplayer]) && !camera3.chase) || ((splitscreen > 2 && stplyr == &players[fourthdisplayplayer]) && !camera4.chase)) { ST_drawFirstPersonHUD(); - } + }*/ } #ifdef HAVE_BLUA @@ -1917,16 +1919,16 @@ static void ST_overlayDrawer(void) #endif // draw level title Tails - if (*mapheaderinfo[gamemap-1]->lvlttl != '\0' && !(hu_showscores && (netgame || multiplayer)) + if (*mapheaderinfo[gamemap-1]->lvlttl != '\0' && !(hu_showscores && (netgame || multiplayer) && !mapreset) #ifdef HAVE_BLUA && LUA_HudEnabled(hud_stagetitle) #endif ) ST_drawLevelTitle(); - if (!hu_showscores && !splitscreen && netgame && displayplayer == consoleplayer) + if (!hu_showscores && !splitscreen && netgame && displayplayer == consoleplayer && !mapreset) { - if (G_GametypeUsesLives() && stplyr->lives <= 0 && countdown != 1) + /*if (G_GametypeUsesLives() && stplyr->lives <= 0 && countdown != 1) V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132), 0, M_GetText("Press F12 to watch another player.")); else if (gametype == GT_HIDEANDSEEK && (!stplyr->spectator && !(stplyr->pflags & PF_TAGIT)) && (leveltime > hidetime * TICRATE)) @@ -1934,15 +1936,15 @@ static void ST_overlayDrawer(void) V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(116), 0, M_GetText("You cannot move while hiding.")); V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132), 0, M_GetText("Press F12 to watch another player.")); } - /*else if (!G_RaceGametype() && stplyr->playerstate == PST_DEAD && stplyr->lives) //Death overrides spectator text. + else if (!G_RaceGametype() && stplyr->playerstate == PST_DEAD && stplyr->lives) //Death overrides spectator text. { INT32 respawntime = cv_respawntime.value - stplyr->deadtimer/TICRATE; if (respawntime > 0 && !stplyr->spectator) V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132), V_HUDTRANSHALF, va(M_GetText("Respawn in: %d second%s."), respawntime, respawntime == 1 ? "" : "s")); else V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132), V_HUDTRANSHALF, M_GetText("Press Jump to respawn.")); - }*/ - else if (stplyr->spectator + } + else*/ if (stplyr->spectator #ifdef HAVE_BLUA && LUA_HudEnabled(hud_textspectator) #endif @@ -1950,12 +1952,12 @@ static void ST_overlayDrawer(void) { // SRB2kart: changed positions & text V_DrawString(2, BASEVIDHEIGHT-50, V_HUDTRANSHALF|V_YELLOWMAP, M_GetText("- SPECTATING -")); - /*if (G_GametypeHasTeams()) - V_DrawString(2, BASEVIDHEIGHT-40, V_HUDTRANSHALF, M_GetText("Item - Join Team")); - else if (G_IsSpecialStage(gamemap) && useNightsSS) - V_DrawString(2, BASEVIDHEIGHT-40, V_HUDTRANSHALF|V_REDMAP, M_GetText("- CANNOT JOIN -")); - else*/ - V_DrawString(2, BASEVIDHEIGHT-40, V_HUDTRANSHALF, M_GetText("Item - Enter Game")); + if (stplyr->pflags & PF_WANTSTOJOIN) + V_DrawString(2, BASEVIDHEIGHT-40, V_HUDTRANSHALF, M_GetText("Item - Cancel Join")); + /*else if (G_GametypeHasTeams()) + V_DrawString(2, BASEVIDHEIGHT-40, V_HUDTRANSHALF, M_GetText("Item - Join Team"));*/ + else + V_DrawString(2, BASEVIDHEIGHT-40, V_HUDTRANSHALF, M_GetText("Item - Join Game")); V_DrawString(2, BASEVIDHEIGHT-30, V_HUDTRANSHALF, M_GetText("F12 - Change View")); V_DrawString(2, BASEVIDHEIGHT-20, V_HUDTRANSHALF, M_GetText("Accelerate - Float")); V_DrawString(2, BASEVIDHEIGHT-10, V_HUDTRANSHALF, M_GetText("Brake - Sink")); @@ -1968,7 +1970,7 @@ static void ST_overlayDrawer(void) void ST_Drawer(void) { #ifdef SEENAMES - if (cv_seenames.value && cv_allowseenames.value && displayplayer == consoleplayer && seenplayer && seenplayer->mo) + if (cv_seenames.value && cv_allowseenames.value && displayplayer == consoleplayer && seenplayer && seenplayer->mo && !mapreset) { if (cv_seenames.value == 1) V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2 + 15, V_HUDTRANSHALF, player_names[seenplayer-players]); diff --git a/src/v_video.c b/src/v_video.c index ac0eed17..e39663a7 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -41,7 +41,7 @@ UINT8 *screens[5]; static CV_PossibleValue_t gamma_cons_t[] = {{0, "MIN"}, {4, "MAX"}, {0, NULL}}; static void CV_usegamma_OnChange(void); -consvar_t cv_ticrate = {"showfps", "No", 0, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_ticrate = {"showfps", "No", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_usegamma = {"gamma", "0", CV_SAVE|CV_CALL, gamma_cons_t, CV_usegamma_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_allcaps = {"allcaps", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -303,8 +303,9 @@ void VID_BlitLinearScreen(const UINT8 *srcptr, UINT8 *destptr, INT32 width, INT3 #endif } -//static UINT8 hudplusalpha[11] = { 10, 8, 6, 4, 2, 0, 0, 0, 0, 0, 0}; +static UINT8 hudplusalpha[11] = { 10, 8, 6, 4, 2, 0, 0, 0, 0, 0, 0}; static UINT8 hudminusalpha[11] = { 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5}; +UINT8 hudtrans = 0; static const UINT8 *v_colormap = NULL; static const UINT8 *v_translevel = NULL; @@ -359,11 +360,11 @@ void V_DrawFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_t if ((alphalevel = ((scrn & V_ALPHAMASK) >> V_ALPHASHIFT))) { if (alphalevel == 13) - alphalevel = hudminusalpha[cv_translucenthud.value]; + alphalevel = hudminusalpha[hudtrans]; else if (alphalevel == 14) - alphalevel = 10 - cv_translucenthud.value; + alphalevel = 10 - hudtrans; /*else if (alphalevel == 15) - alphalevel = hudplusalpha[cv_translucenthud.value];*/ + alphalevel = hudplusalpha[hudtrans];*/ if (alphalevel >= 10) return; // invis @@ -418,7 +419,7 @@ void V_DrawFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_t if (scrn & V_FLIP) { flip = true; - x -= FixedMul((SHORT(patch->width) - SHORT(patch->leftoffset))<width) - SHORT(patch->leftoffset))<leftoffset)<>= FRACBITS; y >>= FRACBITS; - desttop += (y*vid.width) + x; // Center it if necessary if (!(scrn & V_SCALEPATCHMASK)) { - if (vid.width != BASEVIDWIDTH * dupx) - { - // dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx, - // so center this imaginary screen - if ((scrn & (V_HORZSCREEN|V_SNAPTOLEFT)) == (V_HORZSCREEN|V_SNAPTOLEFT)) - desttop += (vid.width/2 - (BASEVIDWIDTH/2 * dupx)); - else if (scrn & V_SNAPTORIGHT) - desttop += (vid.width - (BASEVIDWIDTH * dupx)); - else if (!(scrn & V_SNAPTOLEFT)) - desttop += (vid.width - (BASEVIDWIDTH * dupx)) / 2; - } - if (vid.height != BASEVIDHEIGHT * dupy) - { - // same thing here - if ((scrn & (V_SPLITSCREEN|V_SNAPTOTOP)) == (V_SPLITSCREEN|V_SNAPTOTOP)) - desttop += (vid.height/2 - (BASEVIDHEIGHT/2 * dupy)) * vid.width; - else if (scrn & V_SNAPTOBOTTOM) - desttop += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width; - else if (!(scrn & V_SNAPTOTOP)) - desttop += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width / 2; - } // if it's meant to cover the whole screen, black out the rest - if (x == 0 && FixedMul(SHORT(patch->width)<>FRACBITS == BASEVIDWIDTH + // BAD, BAD, BAD, FUCK OFF, STOP, EW, AAAAAAA + // This does NOT account for transparent pixels + /*if (x == 0 && FixedMul(SHORT(patch->width)<>FRACBITS == BASEVIDWIDTH && y == 0 && FixedMul(SHORT(patch->height)<>FRACBITS == BASEVIDHEIGHT) { column = (const column_t *)((const UINT8 *)(patch) + LONG(patch->columnofs[0])); source = (const UINT8 *)(column) + 3; V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0])); + }*/ + + if (vid.width != BASEVIDWIDTH * dupx) + { + // dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx, + // so center this imaginary screen + if ((scrn & (V_HORZSCREEN|V_SNAPTOLEFT)) == (V_HORZSCREEN|V_SNAPTOLEFT)) + x += (vid.width/2 - (BASEVIDWIDTH/2 * dupx)); + else if (scrn & V_SNAPTORIGHT) + x += (vid.width - (BASEVIDWIDTH * dupx)); + else if (!(scrn & V_SNAPTOLEFT)) + x += (vid.width - (BASEVIDWIDTH * dupx)) / 2; + } + if (vid.height != BASEVIDHEIGHT * dupy) + { + // same thing here + if ((scrn & (V_SPLITSCREEN|V_SNAPTOTOP)) == (V_SPLITSCREEN|V_SNAPTOTOP)) + y += (vid.height/2 - (BASEVIDHEIGHT/2 * dupy)); + else if (scrn & V_SNAPTOBOTTOM) + y += (vid.height - (BASEVIDHEIGHT * dupy)); + else if (!(scrn & V_SNAPTOTOP)) + y += (vid.height - (BASEVIDHEIGHT * dupy)) / 2; } } + + desttop += (y*vid.width) + x; } if (pscale != FRACUNIT) // scale width properly @@ -589,36 +594,39 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_ y = FixedMul(y,dupy<>= FRACBITS; y >>= FRACBITS; - desttop += (y*vid.width) + x; // Center it if necessary if (!(scrn & V_SCALEPATCHMASK)) { + // if it's meant to cover the whole screen, black out the rest + // BAD, BAD, BAD, FUCK OFF, STOP, EW, AAAAAAA + // This does NOT account for transparent pixels + /*if (x == 0 && SHORT(patch->width) == BASEVIDWIDTH && y == 0 && SHORT(patch->height) == BASEVIDHEIGHT) + { + column = (const column_t *)((const UINT8 *)(patch) + LONG(patch->columnofs[0])); + source = (const UINT8 *)(column) + 3; + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0])); + }*/ if (vid.width != BASEVIDWIDTH * dupx) { // dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx, // so center this imaginary screen if (scrn & V_SNAPTORIGHT) - desttop += (vid.width - (BASEVIDWIDTH * dupx)); + x += (vid.width - (BASEVIDWIDTH * dupx)); else if (!(scrn & V_SNAPTOLEFT)) - desttop += (vid.width - (BASEVIDWIDTH * dupx)) / 2; + x += (vid.width - (BASEVIDWIDTH * dupx)) / 2; } if (vid.height != BASEVIDHEIGHT * dupy) { // same thing here if (scrn & V_SNAPTOBOTTOM) - desttop += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width; + y += (vid.height - (BASEVIDHEIGHT * dupy)); else if (!(scrn & V_SNAPTOTOP)) - desttop += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width / 2; - } - // if it's meant to cover the whole screen, black out the rest - if (x == 0 && SHORT(patch->width) == BASEVIDWIDTH && y == 0 && SHORT(patch->height) == BASEVIDHEIGHT) - { - column = (const column_t *)((const UINT8 *)(patch) + LONG(patch->columnofs[0])); - source = (const UINT8 *)(column) + 3; - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0])); + y += (vid.height - (BASEVIDHEIGHT * dupy)) / 2; } } + + desttop += (y*vid.width) + x; } for (col = sx<>FRACBITS) < SHORT(patch->width) && (col>>FRACBITS) < w; col += colfrac, ++x, desttop++) @@ -782,7 +790,7 @@ void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c) if (x == 0 && y == 0 && w == BASEVIDWIDTH && h == BASEVIDHEIGHT) { // Clear the entire screen, from dest to deststop. Yes, this really works. - memset(screens[0], (UINT8)(c&255), vid.width * vid.height * vid.bpp); + memset(screens[0], (c&255), vid.width * vid.height * vid.bpp); return; } @@ -837,7 +845,227 @@ void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c) c &= 255; for (;(--h >= 0) && dest < deststop; dest += vid.width) - memset(dest, (UINT8)(c&255), w * vid.bpp); + memset(dest, c, w * vid.bpp); +} + +// +// Fills a triangle of pixels with a single color, NOTE: scaled to screen size +// +// ... +// .. <-- this shape only for now, i'm afraid +// . +// +void V_DrawDiag(INT32 x, INT32 y, INT32 wh, INT32 c) +{ + UINT8 *dest; + const UINT8 *deststop; + INT32 w, h, wait = 0; + + if (rendermode == render_none) + return; + +#ifdef HWRENDER + if (rendermode != render_soft && !con_startup) + { + HWR_DrawDiag(x, y, wh, c); + return; + } +#endif + + if (!(c & V_NOSCALESTART)) + { + INT32 dupx = vid.dupx, dupy = vid.dupy; + + x *= dupx; + y *= dupy; + wh *= dupx; + + // Center it if necessary + if (vid.width != BASEVIDWIDTH * dupx) + { + // dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx, + // so center this imaginary screen + if (c & V_SNAPTORIGHT) + x += (vid.width - (BASEVIDWIDTH * dupx)); + else if (!(c & V_SNAPTOLEFT)) + x += (vid.width - (BASEVIDWIDTH * dupx)) / 2; + } + if (vid.height != BASEVIDHEIGHT * dupy) + { + // same thing here + if (c & V_SNAPTOBOTTOM) + y += (vid.height - (BASEVIDHEIGHT * dupy)); + else if (!(c & V_SNAPTOTOP)) + y += (vid.height - (BASEVIDHEIGHT * dupy)) / 2; + } + } + + if (x >= vid.width || y >= vid.height) + return; // off the screen + + if (y < 0) + { + wh += y; + y = 0; + } + + w = h = wh; + + if (x < 0) + { + w += x; + x = 0; + } + + if (w <= 0 || h <= 0) + return; // zero width/height wouldn't draw anything + if (x + w > vid.width) + { + wait = w - (vid.width - x); + w = vid.width - x; + } + if (y + w > vid.height) + h = vid.height - y; + + if (h > w) + h = w; + + dest = screens[0] + y*vid.width + x; + deststop = screens[0] + vid.rowbytes * vid.height; + + c &= 255; + + for (;(--h >= 0) && dest < deststop; dest += vid.width) + { + memset(dest, c, w * vid.bpp); + if (wait) + wait--; + else + w--; + } +} + +// THANK YOU MPC!!! + +void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c) +{ + UINT8 *dest; + INT32 u, v; + UINT32 alphalevel = 0; + + if (rendermode == render_none) + return; + +#ifdef HWRENDER + if (rendermode != render_soft && rendermode != render_none) + { + UINT32 hwcolor; + switch (cons_backcolor.value) + { + case 0: hwcolor = 0xffffff00; break; // White + case 1: hwcolor = 0x80808000; break; // Gray + case 2: hwcolor = 0x40201000; break; // Brown + case 3: hwcolor = 0xff000000; break; // Red + case 4: hwcolor = 0xff800000; break; // Orange + case 5: hwcolor = 0x80800000; break; // Yellow + case 6: hwcolor = 0x00800000; break; // Green + case 7: hwcolor = 0x0000ff00; break; // Blue + case 8: hwcolor = 0x4080ff00; break; // Cyan + // Default green + default: hwcolor = 0x00800000; break; + } + HWR_DrawConsoleFill(x, y, w, h, hwcolor, c); // we still use the regular color stuff but only for flags. actual draw color is "hwcolor" for this. + return; + } +#endif + + if (!(c & V_NOSCALESTART)) + { + INT32 dupx = vid.dupx, dupy = vid.dupy; + + if (x == 0 && y == 0 && w == BASEVIDWIDTH && h == BASEVIDHEIGHT) + { // Clear the entire screen, from dest to deststop. Yes, this really works. + memset(screens[0], (UINT8)(c&255), vid.width * vid.height * vid.bpp); + return; + } + + x *= dupx; + y *= dupy; + w *= dupx; + h *= dupy; + + // Center it if necessary + if (vid.width != BASEVIDWIDTH * dupx) + { + // dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx, + // so center this imaginary screen + if (c & V_SNAPTORIGHT) + x += (vid.width - (BASEVIDWIDTH * dupx)); + else if (!(c & V_SNAPTOLEFT)) + x += (vid.width - (BASEVIDWIDTH * dupx)) / 2; + } + if (vid.height != BASEVIDHEIGHT * dupy) + { + // same thing here + if (c & V_SNAPTOBOTTOM) + y += (vid.height - (BASEVIDHEIGHT * dupy)); + else if (!(c & V_SNAPTOTOP)) + y += (vid.height - (BASEVIDHEIGHT * dupy)) / 2; + } + } + + if (x >= vid.width || y >= vid.height) + return; // off the screen + if (x < 0) { + w += x; + x = 0; + } + if (y < 0) { + h += y; + y = 0; + } + + if (w <= 0 || h <= 0) + return; // zero width/height wouldn't draw anything + if (x + w > vid.width) + w = vid.width-x; + if (y + h > vid.height) + h = vid.height-y; + + dest = screens[0] + y*vid.width + x; + + if ((alphalevel = ((c & V_ALPHAMASK) >> V_ALPHASHIFT))) + { + if (alphalevel == 13) + alphalevel = hudminusalpha[cv_translucenthud.value]; + else if (alphalevel == 14) + alphalevel = 10 - cv_translucenthud.value; + else if (alphalevel == 15) + alphalevel = hudplusalpha[cv_translucenthud.value]; + + if (alphalevel >= 10) + return; // invis + } + + c &= 255; + + if (!alphalevel) { + for (v = 0; v < h; v++, dest += vid.width) { + for (u = 0; u < w; u++) { + dest[u] = consolebgmap[dest[u]]; + } + } + } else { // mpc 12-04-2018 + const UINT8 *fadetable = ((UINT8 *)transtables + ((alphalevel-1)<y) ? y : x + w = clip(w,vid.width); + h = clip(h,vid.height); + for (v = 0; v < h; v++, dest += vid.width) { + for (u = 0; u < w; u++) { + dest[u] = fadetable[consolebgmap[dest[u]]]; + } + } + } } // @@ -953,25 +1181,34 @@ void V_DrawPatchFill(patch_t *pat) // // Fade all the screen buffer, so that the menu is more readable, // especially now that we use the small hufont in the menus... +// If color is 0x00 to 0xFF, draw transtable (strength range 0-9). +// Else, use COLORMAP lump (strength range 0-31). +// IF YOU ARE NOT CAREFUL, THIS CAN AND WILL CRASH! +// I have kept the safety checks out of this function; +// the v.fadeScreen Lua interface handles those. // -void V_DrawFadeScreen(void) +void V_DrawFadeScreen(UINT16 color, UINT8 strength) { - const UINT8 *fadetable = (UINT8 *)colormaps + 16*256; - const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; - UINT8 *buf = screens[0]; - #ifdef HWRENDER - if (rendermode != render_soft && rendermode != render_none) - { - HWR_FadeScreenMenuBack(0x01010160, 0); // hack, 0 means full height - return; - } + if (rendermode != render_soft && rendermode != render_none) + { + HWR_FadeScreenMenuBack(color, strength); + return; + } #endif - // heavily simplified -- we don't need to know x or y - // position when we're doing a full screen fade - for (; buf < deststop; ++buf) - *buf = fadetable[*buf]; + { + const UINT8 *fadetable = ((color & 0xFF00) // Color is not palette index? + ? ((UINT8 *)colormaps + strength*256) // Do COLORMAP fade. + : ((UINT8 *)transtables + ((9-strength)<> V_CHARCOLORSHIFT) { @@ -1020,7 +1257,7 @@ static const UINT8 *V_GetStringColormap(INT32 colorflags) case 2: // 0x82, yellow return yellowmap; case 3: // 0x83, lgreen - return lgreenmap; + return greenmap; case 4: // 0x84, blue return bluemap; case 5: // 0x85, red @@ -1029,6 +1266,8 @@ static const UINT8 *V_GetStringColormap(INT32 colorflags) return graymap; case 7: // 0x87, orange return orangemap; + case 8: // 0x88, sky + return skymap; default: // reset return NULL; } @@ -1060,6 +1299,32 @@ 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.. +// +void V_DrawChatCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed, UINT8 *colormap) +{ + INT32 w, flags; + //const UINT8 *colormap = V_GetStringColormap(c); + + flags = c & ~(V_CHARCOLORMASK | V_PARAMMASK); + c &= 0x7f; + if (lowercaseallowed) + c -= HU_FONTSTART; + else + c = toupper(c) - HU_FONTSTART; + 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. + if (x + w > vid.width) + return; + + V_DrawFixedPatch(x*FRACUNIT, y*FRACUNIT, (vid.width < 640) ? (FRACUNIT) : (FRACUNIT/2), flags, hu_font[c], colormap); + + +} + // Precompile a wordwrapped string to any given width. // This is a muuuch better method than V_WORDWRAP. char *V_WordWrap(INT32 x, INT32 w, INT32 option, const char *string) @@ -1135,7 +1400,7 @@ char *V_WordWrap(INT32 x, INT32 w, INT32 option, const char *string) // void V_DrawString(INT32 x, INT32 y, INT32 option, const char *string) { - INT32 w, c, cx = x, cy = y, dupx, dupy, scrwidth = BASEVIDWIDTH, center = 0; + INT32 w, c, cx = x, cy = y, dupx, dupy, scrwidth, center = 0, left = 0; const char *ch = string; INT32 charflags = 0; const UINT8 *colormap = NULL; @@ -1151,7 +1416,12 @@ void V_DrawString(INT32 x, INT32 y, INT32 option, const char *string) scrwidth = vid.width; } else + { dupx = dupy = 1; + scrwidth = vid.width/vid.dupx; + left = (scrwidth - BASEVIDWIDTH)/2; + scrwidth -= left; + } charflags = (option & V_CHARCOLORMASK); @@ -1212,9 +1482,9 @@ void V_DrawString(INT32 x, INT32 y, INT32 option, const char *string) else w = SHORT(hu_font[c]->width) * dupx; - if (cx + w > scrwidth) + if (cx > scrwidth) break; - if (cx < 0) //left boundary check + if (cx+left + w < 0) //left boundary check { cx += w; continue; @@ -1230,7 +1500,7 @@ void V_DrawString(INT32 x, INT32 y, INT32 option, const char *string) // SRB2kart void V_DrawKartString(INT32 x, INT32 y, INT32 option, const char *string) { - INT32 w, c, cx = x, cy = y, dupx, dupy, scrwidth = BASEVIDWIDTH, center = 0; + INT32 w, c, cx = x, cy = y, dupx, dupy, scrwidth, center = 0, left = 0; const char *ch = string; INT32 charflags = 0; const UINT8 *colormap = NULL; @@ -1246,7 +1516,11 @@ void V_DrawKartString(INT32 x, INT32 y, INT32 option, const char *string) scrwidth = vid.width; } else + { dupx = dupy = 1; + scrwidth = vid.width/vid.dupx; + left = (scrwidth - BASEVIDWIDTH)/2; + } charflags = (option & V_CHARCOLORMASK); @@ -1307,9 +1581,9 @@ void V_DrawKartString(INT32 x, INT32 y, INT32 option, const char *string) else w = SHORT(kart_font[c]->width) * dupx; - if (cx + w > scrwidth) + if (cx > scrwidth) break; - if (cx < 0) //left boundary check + if (cx+left + w < 0) //left boundary check { cx += w; continue; @@ -1341,7 +1615,7 @@ void V_DrawRightAlignedString(INT32 x, INT32 y, INT32 option, const char *string // void V_DrawSmallString(INT32 x, INT32 y, INT32 option, const char *string) { - INT32 w, c, cx = x, cy = y, dupx, dupy, scrwidth = BASEVIDWIDTH, center = 0; + INT32 w, c, cx = x, cy = y, dupx, dupy, scrwidth, center = 0, left = 0; const char *ch = string; INT32 charflags = 0; const UINT8 *colormap = NULL; @@ -1357,7 +1631,12 @@ void V_DrawSmallString(INT32 x, INT32 y, INT32 option, const char *string) scrwidth = vid.width; } else + { dupx = dupy = 1; + scrwidth = vid.width/vid.dupx; + left = (scrwidth - BASEVIDWIDTH)/2; + scrwidth -= left; + } charflags = (option & V_CHARCOLORMASK); @@ -1416,9 +1695,9 @@ void V_DrawSmallString(INT32 x, INT32 y, INT32 option, const char *string) } else w = SHORT(hu_font[c]->width) * dupx / 2; - if (cx + w > scrwidth) + if (cx > scrwidth) break; - if (cx < 0) //left boundary check + if (cx+left + w < 0) //left boundary check { cx += w; continue; @@ -1443,7 +1722,7 @@ void V_DrawRightAlignedSmallString(INT32 x, INT32 y, INT32 option, const char *s // void V_DrawThinString(INT32 x, INT32 y, INT32 option, const char *string) { - INT32 w, c, cx = x, cy = y, dupx, dupy, scrwidth = BASEVIDWIDTH; + INT32 w, c, cx = x, cy = y, dupx, dupy, scrwidth, left = 0; const char *ch = string; INT32 charflags = 0; const UINT8 *colormap = NULL; @@ -1459,7 +1738,12 @@ void V_DrawThinString(INT32 x, INT32 y, INT32 option, const char *string) scrwidth = vid.width; } else + { dupx = dupy = 1; + scrwidth = vid.width/vid.dupx; + left = (scrwidth - BASEVIDWIDTH)/2; + scrwidth -= left; + } charflags = (option & V_CHARCOLORMASK); @@ -1516,9 +1800,9 @@ void V_DrawThinString(INT32 x, INT32 y, INT32 option, const char *string) else w = (SHORT(tny_font[c]->width) * dupx); - if (cx + w > scrwidth) + if (cx > scrwidth) break; - if (cx < 0) //left boundary check + if (cx+left + w < 0) //left boundary check { cx += w; continue; @@ -1541,7 +1825,7 @@ void V_DrawRightAlignedThinString(INT32 x, INT32 y, INT32 option, const char *st void V_DrawStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string) { fixed_t cx = x, cy = y; - INT32 w, c, dupx, dupy, scrwidth = BASEVIDWIDTH, center = 0; + INT32 w, c, dupx, dupy, scrwidth, center = 0, left = 0; const char *ch = string; INT32 spacewidth = 4, charwidth = 0; @@ -1555,7 +1839,12 @@ void V_DrawStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string) scrwidth = vid.width; } else + { dupx = dupy = 1; + scrwidth = vid.width/vid.dupx; + left = (scrwidth - BASEVIDWIDTH)/2; + scrwidth -= left; + } switch (option & V_SPACINGMASK) { @@ -1609,9 +1898,9 @@ void V_DrawStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string) else w = SHORT(hu_font[c]->width) * dupx; - if ((cx>>FRACBITS) + w > scrwidth) + if ((cx>>FRACBITS) > scrwidth) break; - if (cx < 0) //left boundary check + if ((cx>>FRACBITS)+left + w < 0) //left boundary check { cx += w<width) * dupx; - if ((cx>>FRACBITS) + w > scrwidth) + if ((cx>>FRACBITS) > scrwidth) break; V_DrawSciencePatch(cx, cy, option, cred_font[c], FRACUNIT); @@ -1747,7 +2036,7 @@ INT32 V_CreditStringWidth(const char *string) // void V_DrawLevelTitle(INT32 x, INT32 y, INT32 option, const char *string) { - INT32 w, c, cx = x, cy = y, dupx, dupy, scrwidth = BASEVIDWIDTH; + INT32 w, c, cx = x, cy = y, dupx, dupy, scrwidth, left = 0; const char *ch = string; if (option & V_NOSCALESTART) @@ -1757,7 +2046,12 @@ void V_DrawLevelTitle(INT32 x, INT32 y, INT32 option, const char *string) scrwidth = vid.width; } else + { dupx = dupy = 1; + scrwidth = vid.width/vid.dupx; + left = (scrwidth - BASEVIDWIDTH)/2; + scrwidth -= left; + } for (;;) { @@ -1779,11 +2073,9 @@ void V_DrawLevelTitle(INT32 x, INT32 y, INT32 option, const char *string) } w = SHORT(lt_font[c]->width) * dupx; - if (cx + w > scrwidth) + if (cx > scrwidth) break; - - //left boundary check - if (cx < 0) + if (cx+left + w < 0) //left boundary check { cx += w; continue; diff --git a/src/v_video.h b/src/v_video.h index 990f9b13..e118d5cf 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -43,6 +43,8 @@ const char *GetPalette(void); extern RGBA_t *pLocalPalette; +extern UINT8 hudtrans; + // Retrieve the ARGB value from a palette color index #define V_GetColor(color) (pLocalPalette[color&0xFF]) @@ -76,6 +78,7 @@ extern RGBA_t *pLocalPalette; #define V_REDMAP 0x00005000 #define V_GRAYMAP 0x00006000 #define V_ORANGEMAP 0x00007000 +#define V_SKYMAP 0x00008000 // use bits 17-20 for alpha transparency #define V_ALPHASHIFT 16 @@ -139,16 +142,22 @@ void V_DrawScaledPic (INT32 px1, INT32 py1, INT32 scrn, INT32 lumpnum); // fill a box with a single color void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c); +void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c); +// fill a triangle with a single color +void V_DrawDiag(INT32 x, INT32 y, INT32 wh, INT32 c); // fill a box with a flat as a pattern void V_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatnum); // fade down the screen buffer before drawing the menu over -void V_DrawFadeScreen(void); +void V_DrawFadeScreen(UINT16 color, UINT8 strength); void V_DrawFadeConsBack(INT32 plines); // draw a single character void V_DrawCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed); +// draw a single character, but for the chat +void V_DrawChatCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed, UINT8 *colormap); +const UINT8 *V_GetStringColormap(INT32 colorflags); void V_DrawLevelTitle(INT32 x, INT32 y, INT32 option, const char *string); diff --git a/src/win32/win_cd.c b/src/win32/win_cd.c index 4ac1506e..f6c43074 100644 --- a/src/win32/win_cd.c +++ b/src/win32/win_cd.c @@ -161,7 +161,7 @@ static BOOL wasPlaying; //static INT cdVolume = 0; // current cd volume (0-31) // 0-31 like Music & Sfx, though CD hardware volume is 0-255. -consvar_t cd_volume = {"cd_volume","31",CV_SAVE,soundvolume_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cd_volume = {"cd_volume","18",CV_SAVE,soundvolume_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; // allow Update for next/loop track // some crap cd drivers take up to diff --git a/src/win32/win_vid.c b/src/win32/win_vid.c index a9dd097b..30fada8e 100644 --- a/src/win32/win_vid.c +++ b/src/win32/win_vid.c @@ -323,7 +323,6 @@ static inline boolean I_SkipFrame(void) if (!paused) return false; /* FALLTHRU */ - case GS_TIMEATTACK: #ifndef CLIENT_LOADINGSCREEN case GS_WAITINGPLAYERS: #endif diff --git a/src/win32ce/win_cd.c b/src/win32ce/win_cd.c index 2b1a8be9..940f59ff 100644 --- a/src/win32ce/win_cd.c +++ b/src/win32ce/win_cd.c @@ -159,7 +159,7 @@ static boolean wasPlaying; //static int cdVolume = 0; // current cd volume (0-31) // 0-31 like Music & Sfx, though CD hardware volume is 0-255. -consvar_t cd_volume = {"cd_volume","31",CV_SAVE,soundvolume_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cd_volume = {"cd_volume","18",CV_SAVE,soundvolume_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; // allow Update for next/loop track // some crap cd drivers take up to diff --git a/src/y_inter.c b/src/y_inter.c index 3efce983..9416211a 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -36,9 +36,10 @@ #include "m_cond.h" // condition sets -#include "m_random.h" // P_RandomKey +#include "m_random.h" // M_RandomKey #include "g_input.h" // PLAYER1INPUTDOWN #include "k_kart.h" // colortranslations +#include "console.h" // cons_menuhighlight #ifdef HWRENDER #include "hardware/hw_main.h" @@ -59,7 +60,7 @@ typedef struct typedef union { - struct + /*struct { char passed1[21]; // KNUCKLES GOT / CRAWLA HONCHO char passed2[16]; // THROUGH THE ACT / PASSED THE ACT @@ -77,68 +78,22 @@ typedef union patch_t *ttlnum; // act number being displayed patch_t *ptotal; // TOTAL UINT8 gotlife; // Number of extra lives obtained - } coop; + } coop;*/ struct { - char passed1[29]; // KNUCKLES GOT / CRAWLA HONCHO - char passed2[17]; // A CHAOS EMERALD / GOT THEM ALL! - char passed3[15]; // CAN NOW BECOME - char passed4[SKINNAMESIZE+7]; // SUPER CRAWLA HONCHO - INT32 passedx1; - INT32 passedx2; - INT32 passedx3; - INT32 passedx4; - - y_bonus_t bonus; - patch_t *bonuspatch; - - patch_t *pscore; // SCORE - UINT32 score; // fake score - - // Continues - UINT8 continues; - patch_t *pcontinues; - INT32 *playerchar; // Continue HUD - UINT8 *playercolor; - - UINT8 gotlife; // Number of extra lives obtained - } spec; - - struct - { - UINT32 scores[MAXPLAYERS]; // Winner's score UINT8 *color[MAXPLAYERS]; // Winner's color # - boolean spectator[MAXPLAYERS]; // Spectator list INT32 *character[MAXPLAYERS]; // Winner's character # INT32 num[MAXPLAYERS]; // Winner's player # char *name[MAXPLAYERS]; // Winner's name - patch_t *result; // RESULT - patch_t *blueflag; - patch_t *redflag; // int_ctf uses this struct too. INT32 numplayers; // Number of players being displayed - char levelstring[62]; // holds levelnames up to 32 characters + char levelstring[64]; // holds levelnames up to 64 characters // SRB2kart - int increase[MAXPLAYERS]; //how much did the score increase by? - int time[MAXPLAYERS]; //Tournament Time + UINT8 increase[MAXPLAYERS]; //how much did the score increase by? + UINT32 val[MAXPLAYERS]; //Gametype-specific value + UINT8 pos[MAXPLAYERS]; // player positions. used for ties + boolean rankingsmode; // rankings mode } match; - - struct - { - UINT8 *color[MAXPLAYERS]; // Winner's color # - INT32 *character[MAXPLAYERS]; // Winner's character # - INT32 num[MAXPLAYERS]; // Winner's player # - char name[MAXPLAYERS][9]; // Winner's name - UINT32 times[MAXPLAYERS]; - UINT32 rings[MAXPLAYERS]; - UINT32 maxrings[MAXPLAYERS]; - UINT32 monitors[MAXPLAYERS]; - UINT32 scores[MAXPLAYERS]; - UINT32 points[MAXPLAYERS]; - INT32 numplayers; // Number of players being displayed - char levelstring[40]; // holds levelnames up to 32 characters - } competition; - } y_data; static y_data data; @@ -155,16 +110,10 @@ static INT32 timer; static INT32 intertic; static INT32 endtic = -1; +static INT32 sorttic = -1; intertype_t intertype = int_none; -//static void Y_AwardCoopBonuses(void); -//static void Y_AwardSpecialStageBonus(void); -static void Y_CalculateTournamentPoints(void); // SRB2kart - -static void Y_CalculateCompetitionWinners(void); -//static void Y_CalculateTimeRaceWinners(void); -static void Y_CalculateMatchWinners(void); static void Y_FollowIntermission(void); static void Y_UnloadData(void); @@ -173,6 +122,8 @@ static void Y_UnloadData(void); typedef struct { char str[62]; + UINT8 gtc; + const char *gts; patch_t *pic; } y_votelvlinfo; @@ -191,9 +142,10 @@ typedef struct UINT8 roffset; UINT8 rsynctime; UINT8 rendoff; + boolean loaded; } y_voteclient; -static y_votelvlinfo levelinfo[4]; +static y_votelvlinfo levelinfo[5]; static y_voteclient voteclient; static INT32 votetic; static INT32 voteendtic = -1; @@ -206,30 +158,145 @@ static patch_t *randomlvl = NULL; static void Y_UnloadVoteData(void); -// Stuff copy+pasted from st_stuff.c -static INT32 SCX(INT32 x) +// +// SRB2Kart - Y_CalculateMatchData and ancillary functions +// +static void Y_CompareRace(INT32 i) { - return FixedInt(FixedMul(x< data.match.val[data.match.numplayers]))) + return; + + data.match.val[data.match.numplayers] = val; + data.match.num[data.match.numplayers] = i; +} + +static void Y_CompareRank(INT32 i) +{ + if (!(data.match.val[data.match.numplayers] == UINT32_MAX || players[i].score > data.match.val[data.match.numplayers])) + return; + + data.match.val[data.match.numplayers] = players[i].score; + data.match.num[data.match.numplayers] = i; +} + +static void Y_CalculateMatchData(boolean rankingsmode, void (*comparison)(INT32)) +{ + INT32 i, j; + boolean completed[MAXPLAYERS]; + INT32 numplayersingame = 0; + + // Initialize variables + if ((data.match.rankingsmode = rankingsmode)) + sprintf(data.match.levelstring, "* Total Rankings *"); + else + { + // set up the levelstring + if (mapheaderinfo[prevmap]->levelflags & LF_NOZONE) + { + if (mapheaderinfo[prevmap]->actnum[0]) + snprintf(data.match.levelstring, + sizeof data.match.levelstring, + "* %s %s *", + mapheaderinfo[prevmap]->lvlttl, mapheaderinfo[prevmap]->actnum); + else + snprintf(data.match.levelstring, + sizeof data.match.levelstring, + "* %s *", + mapheaderinfo[prevmap]->lvlttl); + } + else + { + const char *zonttl = (mapheaderinfo[prevmap]->zonttl[0] ? mapheaderinfo[prevmap]->zonttl : "ZONE"); + if (mapheaderinfo[prevmap]->actnum[0]) + snprintf(data.match.levelstring, + sizeof data.match.levelstring, + "* %s %s %s *", + mapheaderinfo[prevmap]->lvlttl, zonttl, mapheaderinfo[prevmap]->actnum); + else + snprintf(data.match.levelstring, + sizeof data.match.levelstring, + "* %s %s *", + mapheaderinfo[prevmap]->lvlttl, zonttl); + } + + data.match.levelstring[sizeof data.match.levelstring - 1] = '\0'; + } + + for (i = 0; i < MAXPLAYERS; i++) + { + data.match.val[i] = UINT32_MAX; + if (!rankingsmode) + data.match.increase[i] = UINT8_MAX; + + if (!playeringame[i] || players[i].spectator) + continue; + + numplayersingame++; + } + + memset(data.match.color, 0, sizeof (data.match.color)); + memset(data.match.character, 0, sizeof (data.match.character)); + memset(completed, 0, sizeof (completed)); + data.match.numplayers = 0; + + for (j = 0; j < numplayersingame; j++) + { + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i] || players[i].spectator || completed[i]) + continue; + + comparison(i); + } + + i = data.match.num[data.match.numplayers]; + + completed[i] = true; + + data.match.color[data.match.numplayers] = &players[i].skincolor; + data.match.character[data.match.numplayers] = &players[i].skin; + data.match.name[data.match.numplayers] = player_names[i]; + + if (data.match.numplayers && (data.match.val[data.match.numplayers] == data.match.val[data.match.numplayers-1])) + data.match.pos[data.match.numplayers] = data.match.pos[data.match.numplayers-1]; + else + data.match.pos[data.match.numplayers] = data.match.numplayers+1; + + if (!rankingsmode && !(players[i].pflags & PF_TIMEOVER) && (data.match.pos[data.match.numplayers] != numplayersingame)) + { + data.match.increase[i] = numplayersingame - data.match.pos[data.match.numplayers]; + players[i].score += data.match.increase[i]; + } + + data.match.numplayers++; + } +} // // Y_IntermissionDrawer // -// Called by D_Display. Nothing is modified here; all it does is draw. +// Called by D_Display. Nothing is modified here; all it does is draw. (SRB2Kart: er, about that...) // Neat concept, huh? // void Y_IntermissionDrawer(void) { - // Bonus loops - INT32 i; + INT32 i, whiteplayer = MAXPLAYERS, x = 4, hilicol = V_YELLOWMAP; // fallback if (intertype == int_none || rendermode == render_none) return; @@ -260,8 +327,33 @@ void Y_IntermissionDrawer(void) else V_DrawPatchFill(bgtile); + if (usebuffer) // Fade everything out + V_DrawFadeScreen(0xFF00, 20); + + if (!splitscreen) + whiteplayer = demoplayback ? displayplayer : consoleplayer; + + if (cons_menuhighlight.value) + hilicol = cons_menuhighlight.value; + else if (modeattacking) + hilicol = V_ORANGEMAP; + else + hilicol = ((intertype == int_race) ? V_SKYMAP : V_REDMAP); + + if (sorttic != -1 && intertic > sorttic) + { + INT32 count = (intertic - sorttic); + + if (count < 8) + x -= ((count * vid.width) / (8 * vid.dupx)); + else if (count == 8) + goto dotimer; + else if (count < 16) + x += (((16 - count) * vid.width) / (8 * vid.dupx)); + } + // SRB2kart 290117 - compeltely replaced this block. - if (intertype == int_timeattack) + /*if (intertype == int_timeattack) { // draw time ST_DrawPatchFromHud(HUD_TIME, sbotime); @@ -279,13 +371,13 @@ void Y_IntermissionDrawer(void) ST_DrawPatchFromHud(HUD_TIMECOLON, sbocolon); // Colon ST_DrawPadNumFromHud(HUD_SECONDS, seconds, 2); // Seconds - /* // SRB2kart - pulled from old coop block, just in case we need it + // SRB2kart - pulled from old coop block, just in case we need it // we should show centiseconds on the intermission screen too, if the conditions are right. if (modeattacking || cv_timetic.value == 2) { ST_DrawPatchFromHud(HUD_TIMETICCOLON, sboperiod); // Period ST_DrawPadNumFromHud(HUD_TICS, tictrn, 2); // Tics - }*/ + } ST_DrawPatchFromHud(HUD_TIMETICCOLON, sboperiod); // Period ST_DrawPadNumFromHud(HUD_TICS, tictrn, 2); // Tics @@ -301,58 +393,43 @@ void Y_IntermissionDrawer(void) //if (gottimebonus && endtic != -1) // V_DrawCenteredString(BASEVIDWIDTH/2, 172, V_YELLOWMAP, "TIME BONUS UNLOCKED!"); } - else if (intertype == int_race) + else*/ if (intertype == int_race || intertype == int_match) { - INT32 j = 0; - INT32 x = 4; INT32 y = 48; - char name[MAXPLAYERNAME+1]; + const char *timeheader; - boolean completed[MAXPLAYERS]; - memset(completed, 0, sizeof (completed)); + if (data.match.rankingsmode) + timeheader = "RANK"; + else + timeheader = (intertype == int_race ? "TIME" : "SCORE"); // draw the level name - V_DrawCenteredString(BASEVIDWIDTH/2, 20, 0, data.match.levelstring); - V_DrawFill(4, 42, 312, 1, 0); + V_DrawCenteredString(-4 + x + BASEVIDWIDTH/2, 20, 0, data.match.levelstring); + V_DrawFill(x, 42, 312, 1, 0); if (data.match.numplayers > 8) { - V_DrawFill(160, 32, 1, 152, 0); + V_DrawFill(x+156, 32, 1, 152, 0); - V_DrawCenteredString(x+6+(BASEVIDWIDTH/2), 32, V_YELLOWMAP, "#"); - V_DrawString(x+36+(BASEVIDWIDTH/2), 32, V_YELLOWMAP, "NAME"); + V_DrawCenteredString(x+6+(BASEVIDWIDTH/2), 32, hilicol, "#"); + V_DrawString(x+36+(BASEVIDWIDTH/2), 32, hilicol, "NAME"); - V_DrawRightAlignedString(x+110, 32, V_YELLOWMAP, "TIME"); - - V_DrawRightAlignedString(x+152, 32, V_YELLOWMAP, "SCORE"); + V_DrawRightAlignedString(x+152, 32, hilicol, timeheader); } - V_DrawCenteredString(x+6, 32, V_YELLOWMAP, "#"); - V_DrawString(x+36, 32, V_YELLOWMAP, "NAME"); + V_DrawCenteredString(x+6, 32, hilicol, "#"); + V_DrawString(x+36, 32, hilicol, "NAME"); - if (data.match.numplayers > 8) - { - V_DrawRightAlignedString(x+(BASEVIDWIDTH/2)+110, 32, V_YELLOWMAP, "TIME"); - } - else - { - V_DrawRightAlignedString(x+(BASEVIDWIDTH/2)+62, 32, V_YELLOWMAP, "TIME"); - } - - V_DrawRightAlignedString(x+(BASEVIDWIDTH/2)+152, 32, V_YELLOWMAP, "SCORE"); + V_DrawRightAlignedString(x+(BASEVIDWIDTH/2)+152, 32, hilicol, timeheader); for (i = 0; i < data.match.numplayers; i++) { - char strtime[10]; - - if (data.match.spectator[i]) - continue; - - V_DrawCenteredString(x+6, y, 0, va("%d", j+1)); - j++; //We skip spectators, but not their number. - - if (playeringame[data.match.num[i]]) + if (data.match.num[i] != MAXPLAYERS && playeringame[data.match.num[i]] && !players[data.match.num[i]].spectator) { + char strtime[MAXPLAYERNAME+1]; + + V_DrawCenteredString(x+6, y, 0, va("%d", data.match.pos[i])); + if (data.match.color[i] == 0) V_DrawSmallScaledPatch(x+16, y-4, 0,faceprefix[*data.match.character[i]]); else @@ -362,342 +439,99 @@ void Y_IntermissionDrawer(void) } if (data.match.numplayers > 8) - { - strlcpy(name, data.match.name[i], 6); - } + strlcpy(strtime, data.match.name[i], 6); else - STRBUFCPY(name, data.match.name[i]); + STRBUFCPY(strtime, data.match.name[i]); - V_DrawString(x+36, y, V_ALLOWLOWERCASE, name); + V_DrawString(x+36, y, + ((data.match.num[i] == whiteplayer) + ? hilicol|V_ALLOWLOWERCASE + : V_ALLOWLOWERCASE), + strtime); - snprintf(strtime, sizeof strtime, "%d", data.match.scores[i]-data.match.increase[i]); - - if (data.match.numplayers > 8) + if (data.match.rankingsmode) { - V_DrawRightAlignedString(x+152, y, V_YELLOWMAP, strtime); - } - else - { - V_DrawRightAlignedString(x+152+BASEVIDWIDTH/2, y, V_YELLOWMAP, strtime); - } + if (data.match.increase[data.match.num[i]] != UINT8_MAX) + { + if (data.match.increase[data.match.num[i]] > 9) + snprintf(strtime, sizeof strtime, "(+%02d)", data.match.increase[data.match.num[i]]); + else + snprintf(strtime, sizeof strtime, "(+ %d)", data.match.increase[data.match.num[i]]); - if (data.match.increase[i] > 9) - snprintf(strtime, sizeof strtime, "(+%02d)", data.match.increase[i]); - else - snprintf(strtime, sizeof strtime, "(+ %d)", data.match.increase[i]); + if (data.match.numplayers > 8) + V_DrawRightAlignedString(x+120, y, 0, strtime); + else + V_DrawRightAlignedString(x+120+BASEVIDWIDTH/2, y, 0, strtime); - if (data.match.numplayers <= 8) // Only draw this with less than 8 players, otherwise we won't be able to fit the times in - { - V_DrawString(x+84+BASEVIDWIDTH/2, y, 0, strtime); - } - - snprintf(strtime, sizeof strtime, "%i:%02i.%02i", G_TicsToMinutes(data.match.time[i], true), - G_TicsToSeconds(data.match.time[i]), G_TicsToCentiseconds(data.match.time[i])); - - strtime[sizeof strtime - 1] = '\0'; - - if (data.match.numplayers > 8) - { - V_DrawRightAlignedString(x+134, y, 0, strtime); - } - else - { - V_DrawRightAlignedString(x+80+BASEVIDWIDTH/2, y, 0, strtime); - } - - - completed[i] = true; - } - - y += 16; - - if (y > 160) - { - y = 48; - x += BASEVIDWIDTH/2; - } - } - } - else if (intertype == int_match) - { - INT32 j = 0; - INT32 x = 4; - INT32 y = 48; - char name[MAXPLAYERNAME+1]; - char strtime[10]; - - // draw the header - V_DrawScaledPatch(112, 2, 0, data.match.result); - - // draw the level name - V_DrawCenteredString(BASEVIDWIDTH/2, 20, 0, data.match.levelstring); - V_DrawFill(4, 42, 312, 1, 0); - - if (data.match.numplayers > 9) - { - V_DrawFill(160, 32, 1, 152, 0); - - if (intertype == int_race) - V_DrawRightAlignedString(x+152, 32, V_YELLOWMAP, "TIME"); - else - V_DrawRightAlignedString(x+152, 32, V_YELLOWMAP, "SCORE"); - - V_DrawCenteredString(x+(BASEVIDWIDTH/2)+6, 32, V_YELLOWMAP, "#"); - V_DrawString(x+(BASEVIDWIDTH/2)+36, 32, V_YELLOWMAP, "NAME"); - } - - V_DrawCenteredString(x+6, 32, V_YELLOWMAP, "#"); - V_DrawString(x+36, 32, V_YELLOWMAP, "NAME"); - - if (intertype == int_race) - V_DrawRightAlignedString(x+(BASEVIDWIDTH/2)+152, 32, V_YELLOWMAP, "TIME"); - else - V_DrawRightAlignedString(x+(BASEVIDWIDTH/2)+152, 32, V_YELLOWMAP, "SCORE"); - - for (i = 0; i < data.match.numplayers; i++) - { - if (data.match.spectator[i]) - continue; //Ignore spectators. - - V_DrawCenteredString(x+6, y, 0, va("%d", j+1)); - j++; //We skip spectators, but not their number. - - if (playeringame[data.match.num[i]]) - { - // Draw the back sprite, it looks ugly if we don't - V_DrawSmallScaledPatch(x+16, y-4, 0, livesback); - - if (data.match.color[i] == 0) - V_DrawSmallScaledPatch(x+16, y-4, 0,faceprefix[*data.match.character[i]]); - else - { - UINT8 *colormap = R_GetTranslationColormap(*data.match.character[i], *data.match.color[i], GTC_CACHE); - V_DrawSmallMappedPatch(x+16, y-4, 0,faceprefix[*data.match.character[i]], colormap); - } - - if (data.match.numplayers > 9) - { - if (intertype == int_race) - strlcpy(name, data.match.name[i], 8); + snprintf(strtime, sizeof strtime, "%d", data.match.val[i]-data.match.increase[data.match.num[i]]); + } else - strlcpy(name, data.match.name[i], 9); - } - else - STRBUFCPY(name, data.match.name[i]); + snprintf(strtime, sizeof strtime, "%d", data.match.val[i]); - V_DrawString(x+36, y, V_ALLOWLOWERCASE, name); - - if (data.match.numplayers > 9) - { - if (intertype == int_match) - V_DrawRightAlignedString(x+152, y, 0, va("%i", data.match.scores[i])); - else if (intertype == int_race) - { - if (players[data.match.num[i]].pflags & PF_TIMEOVER) - snprintf(strtime, sizeof strtime, "DNF"); - else - snprintf(strtime, sizeof strtime, - "%i:%02i.%02i", - G_TicsToMinutes(data.match.scores[i], true), - G_TicsToSeconds(data.match.scores[i]), G_TicsToCentiseconds(data.match.scores[i])); - - strtime[sizeof strtime - 1] = '\0'; + if (data.match.numplayers > 8) V_DrawRightAlignedString(x+152, y, 0, strtime); - } + else + V_DrawRightAlignedString(x+152+BASEVIDWIDTH/2, y, 0, strtime); } else { - if (intertype == int_match) - V_DrawRightAlignedString(x+152+BASEVIDWIDTH/2, y, 0, va("%u", data.match.scores[i])); - else if (intertype == int_race) + if (data.match.val[i] == (UINT32_MAX-1)) { - if (players[data.match.num[i]].pflags & PF_TIMEOVER) - snprintf(strtime, sizeof strtime, "DNF"); + if (data.match.numplayers > 8) + V_DrawRightAlignedThinString(x+152, y-1, 0, "NO CONTEST"); else - snprintf(strtime, sizeof strtime, "%i:%02i.%02i", G_TicsToMinutes(data.match.scores[i], true), - G_TicsToSeconds(data.match.scores[i]), G_TicsToCentiseconds(data.match.scores[i])); + V_DrawRightAlignedThinString(x+152+BASEVIDWIDTH/2, y-1, 0, "NO CONTEST"); + } + else + { + if (intertype == int_race) + { + snprintf(strtime, sizeof strtime, "%i:%02i.%02i", G_TicsToMinutes(data.match.val[i], true), + G_TicsToSeconds(data.match.val[i]), G_TicsToCentiseconds(data.match.val[i])); + strtime[sizeof strtime - 1] = '\0'; - strtime[sizeof strtime - 1] = '\0'; - - V_DrawRightAlignedString(x+152+BASEVIDWIDTH/2, y, 0, strtime); + if (data.match.numplayers > 8) + V_DrawRightAlignedString(x+152, y, 0, strtime); + else + V_DrawRightAlignedString(x+152+BASEVIDWIDTH/2, y, 0, strtime); + } + else + { + if (data.match.numplayers > 8) + V_DrawRightAlignedString(x+152, y, 0, va("%i", data.match.val[i])); + else + V_DrawRightAlignedString(x+152+BASEVIDWIDTH/2, y, 0, va("%i", data.match.val[i])); + } } } } + else + { + data.match.increase[data.match.num[i]] = 0; + data.match.num[i] = MAXPLAYERS; // this should be the only field setting in this function + } y += 16; - if (y > 176) + if (i == 7) { y = 48; x += BASEVIDWIDTH/2; } } } - else if (intertype == int_ctf || intertype == int_teammatch) - { - INT32 x = 4, y = 0; - INT32 redplayers = 0, blueplayers = 0; - char name[MAXPLAYERNAME+1]; - - // Show the team flags and the team score at the top instead of "RESULTS" - V_DrawSmallScaledPatch(128 - SHORT(data.match.blueflag->width)/4, 2, 0, data.match.blueflag); - V_DrawCenteredString(128, 16, 0, va("%u", bluescore)); - - V_DrawSmallScaledPatch(192 - SHORT(data.match.redflag->width)/4, 2, 0, data.match.redflag); - V_DrawCenteredString(192, 16, 0, va("%u", redscore)); - - // draw the level name - V_DrawCenteredString(BASEVIDWIDTH/2, 24, 0, data.match.levelstring); - V_DrawFill(4, 42, 312, 1, 0); - - //vert. line - V_DrawFill(160, 32, 1, 152, 0); - - //strings at the top of the list - V_DrawCenteredString(x+6, 32, V_YELLOWMAP, "#"); - V_DrawCenteredString(x+(BASEVIDWIDTH/2)+6, 32, V_YELLOWMAP, "#"); - - V_DrawString(x+36, 32, V_YELLOWMAP, "NAME"); - V_DrawString(x+(BASEVIDWIDTH/2)+36, 32, V_YELLOWMAP, "NAME"); - - V_DrawRightAlignedString(x+152, 32, V_YELLOWMAP, "SCORE"); - V_DrawRightAlignedString(x+(BASEVIDWIDTH/2)+152, 32, V_YELLOWMAP, "SCORE"); - - for (i = 0; i < data.match.numplayers; i++) - { - if (playeringame[data.match.num[i]] && !(data.match.spectator[i])) - { - UINT8 *colormap = R_GetTranslationColormap(*data.match.character[i], *data.match.color[i], GTC_CACHE); - - if (*data.match.color[i] == SKINCOLOR_RED) //red - { - if (redplayers++ > 9) - continue; - x = 4 + (BASEVIDWIDTH/2); - y = (redplayers * 16) + 32; - V_DrawCenteredString(x+6, y, 0, va("%d", redplayers)); - } - else if (*data.match.color[i] == SKINCOLOR_BLUE) //blue - { - if (blueplayers++ > 9) - continue; - x = 4; - y = (blueplayers * 16) + 32; - V_DrawCenteredString(x+6, y, 0, va("%d", blueplayers)); - } - else - continue; - - // Draw the back sprite, it looks ugly if we don't - V_DrawSmallScaledPatch(x+16, y-4, 0, livesback); - - //color is ALWAYS going to be 6/7 here, no need to check if it's nonzero. - V_DrawSmallMappedPatch(x+16, y-4, 0,faceprefix[*data.match.character[i]], colormap); - - strlcpy(name, data.match.name[i], 9); - - V_DrawString(x+36, y, V_ALLOWLOWERCASE, name); - - V_DrawRightAlignedString(x+152, y, 0, va("%u", data.match.scores[i])); - } - } - } - else if (intertype == int_classicrace) - { - INT32 x = 4; - INT32 y = 48; - UINT32 ptime, pring, pmaxring, pmonitor, pscore; - char sstrtime[10]; - - // draw the level name - V_DrawCenteredString(BASEVIDWIDTH/2, 8, 0, data.competition.levelstring); - V_DrawFill(4, 42, 312, 1, 0); - - V_DrawCenteredString(x+6, 32, V_YELLOWMAP, "#"); - V_DrawString(x+36, 32, V_YELLOWMAP, "NAME"); - // Time - V_DrawRightAlignedString(x+160, 32, V_YELLOWMAP, "TIME"); - - // Rings - V_DrawThinString(x+168, 31, V_YELLOWMAP, "RING"); - - // Total rings - V_DrawThinString(x+191, 22, V_YELLOWMAP, "TOTAL"); - V_DrawThinString(x+196, 31, V_YELLOWMAP, "RING"); - - // Monitors - V_DrawThinString(x+223, 22, V_YELLOWMAP, "ITEM"); - V_DrawThinString(x+229, 31, V_YELLOWMAP, "BOX"); - - // Score - V_DrawRightAlignedString(x+288, 32, V_YELLOWMAP, "SCORE"); - - // Points - V_DrawRightAlignedString(x+312, 32, V_YELLOWMAP, "PT"); - - for (i = 0; i < data.competition.numplayers; i++) - { - ptime = (data.competition.times[i] & ~0x80000000); - pring = (data.competition.rings[i] & ~0x80000000); - pmaxring = (data.competition.maxrings[i] & ~0x80000000); - pmonitor = (data.competition.monitors[i] & ~0x80000000); - pscore = (data.competition.scores[i] & ~0x80000000); - - V_DrawCenteredString(x+6, y, 0, va("%d", i+1)); - - if (playeringame[data.competition.num[i]]) - { - // Draw the back sprite, it looks ugly if we don't - V_DrawSmallScaledPatch(x+16, y-4, 0, livesback); - - if (data.competition.color[i] == 0) - V_DrawSmallScaledPatch(x+16, y-4, 0,faceprefix[*data.competition.character[i]]); - else - { - UINT8 *colormap = R_GetTranslationColormap(*data.competition.character[i], *data.competition.color[i], GTC_CACHE); - V_DrawSmallMappedPatch(x+16, y-4, 0,faceprefix[*data.competition.character[i]], colormap); - } - - // already constrained to 8 characters - V_DrawString(x+36, y, V_ALLOWLOWERCASE, data.competition.name[i]); - - if (players[data.competition.num[i]].pflags & PF_TIMEOVER) - snprintf(sstrtime, sizeof sstrtime, "Time Over"); - else if (players[data.competition.num[i]].lives <= 0) - snprintf(sstrtime, sizeof sstrtime, "Game Over"); - else - snprintf(sstrtime, sizeof sstrtime, "%i:%02i.%02i", G_TicsToMinutes(ptime, true), - G_TicsToSeconds(ptime), G_TicsToCentiseconds(ptime)); - - sstrtime[sizeof sstrtime - 1] = '\0'; - // Time - V_DrawRightAlignedThinString(x+160, y-1, ((data.competition.times[i] & 0x80000000) ? V_YELLOWMAP : 0), sstrtime); - // Rings - V_DrawRightAlignedThinString(x+188, y-1, V_MONOSPACE|((data.competition.rings[i] & 0x80000000) ? V_YELLOWMAP : 0), va("%u", pring)); - // Total rings - V_DrawRightAlignedThinString(x+216, y-1, V_MONOSPACE|((data.competition.maxrings[i] & 0x80000000) ? V_YELLOWMAP : 0), va("%u", pmaxring)); - // Monitors - V_DrawRightAlignedThinString(x+244, y-1, V_MONOSPACE|((data.competition.monitors[i] & 0x80000000) ? V_YELLOWMAP : 0), va("%u", pmonitor)); - // Score - V_DrawRightAlignedThinString(x+288, y-1, V_MONOSPACE|((data.competition.scores[i] & 0x80000000) ? V_YELLOWMAP : 0), va("%u", pscore)); - // Final Points - V_DrawRightAlignedString(x+312, y, V_YELLOWMAP, va("%d", data.competition.points[i])); - } - - y += 16; - - if (y > 176) - break; - } - } +dotimer: if (timer) - V_DrawCenteredString(BASEVIDWIDTH/2, 188, V_YELLOWMAP, - va("start in %d seconds", timer/TICRATE)); + { + INT32 tickdown = (timer+1)/TICRATE; + V_DrawCenteredString(BASEVIDWIDTH/2, 188, hilicol, + va("%s starts in %d", cv_advancemap.string, tickdown)); + } // Make it obvious that scrambling is happening next round. if (cv_scrambleonchange.value && cv_teamscramble.value && (intertic/TICRATE % 2 == 0)) - V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2, V_YELLOWMAP, M_GetText("Teams will be scrambled next round!")); + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2, hilicol, M_GetText("Teams will be scrambled next round!")); } // @@ -744,188 +578,47 @@ void Y_Ticker(void) return; } - if (endtic != -1) - return; // tally is done + if (intertic < TICRATE || intertic & 1 || endtic != -1) + return; - /* // SRB2kart - if (intertype == int_coop) // coop or single player, normal level + if (intertype == int_race || intertype == int_match) { - INT32 i; - UINT32 oldscore = data.coop.score; - boolean skip = false; - boolean anybonuses = false; - - if (!intertic) // first time only - S_ChangeMusicInternal("lclear", false); // don't loop it - - if (intertic < TICRATE) // one second pause before tally begins - return; - - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && (players[i].cmd.buttons & BT_BRAKE || players[i].cmd.buttons & BT_ACCELERATE)) - skip = true; - - // bonuses count down by 222 each tic - for (i = 0; i < 4; ++i) + if (netgame || multiplayer) { - if (!data.coop.bonuses[i].points) - continue; - - data.coop.bonuses[i].points -= 222; - data.coop.total += 222; - data.coop.score += 222; - if (data.coop.bonuses[i].points < 0 || skip == true) // too far? - { - data.coop.score += data.coop.bonuses[i].points; - data.coop.total += data.coop.bonuses[i].points; - data.coop.bonuses[i].points = 0; - } - if (data.coop.bonuses[i].points > 0) - anybonuses = true; - } - - if (!anybonuses) - { - endtic = intertic + 3*TICRATE; // 3 second pause after end of tally - S_StartSound(NULL, sfx_chchng); // cha-ching! - - // Update when done with tally - if ((!modifiedgame || savemoddata) && !(netgame || multiplayer) && !demoplayback) - { - if (M_UpdateUnlockablesAndExtraEmblems(false)) - S_StartSound(NULL, sfx_ncitem); - - G_SaveGameData(false); - } - } - else if (!(intertic & 1)) - S_StartSound(NULL, sfx_ptally); // tally sound effect - - if (data.coop.gotlife > 0 && (skip == true || data.coop.score % 50000 < oldscore % 50000)) // just passed a 50000 point mark - { - // lives are already added since tally is fake, but play the music - P_PlayLivesJingle(NULL); - --data.coop.gotlife; - } - } - else if (intertype == int_spec) // coop or single player, special stage - { - INT32 i; - UINT32 oldscore = data.spec.score; - boolean skip = false; - static INT32 tallydonetic = 0; - - if (!intertic) // first time only - { - S_ChangeMusicInternal("lclear", false); // don't loop it - tallydonetic = 0; - } - - if (intertic < TICRATE) // one second pause before tally begins - return; - - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && (players[i].cmd.buttons & BT_BRAKE || players[i].cmd.buttons & BT_ACCELERATE)) - skip = true; - - if (tallydonetic != 0) - { - if (intertic > tallydonetic) - { - endtic = intertic + 4*TICRATE; // 4 second pause after end of tally - S_StartSound(NULL, sfx_flgcap); // cha-ching! - } - return; - } - - // ring bonus counts down by 222 each tic - data.spec.bonus.points -= 222; - data.spec.score += 222; - if (data.spec.bonus.points < 0 || skip == true) // went too far - { - data.spec.score += data.spec.bonus.points; - data.spec.bonus.points = 0; - } - - if (!data.spec.bonus.points) - { - if (data.spec.continues & 0x80) // don't set endtic yet! - tallydonetic = intertic + (3*TICRATE)/2; - else // okay we're good. - endtic = intertic + 4*TICRATE; // 4 second pause after end of tally - - S_StartSound(NULL, sfx_chchng); // cha-ching! - - // Update when done with tally - if ((!modifiedgame || savemoddata) && !(netgame || multiplayer) && !demoplayback) - { - if (M_UpdateUnlockablesAndExtraEmblems(false)) - S_StartSound(NULL, sfx_ncitem); - - G_SaveGameData(false); - } - } - else if (!(intertic & 1)) - S_StartSound(NULL, sfx_ptally); // tally sound effect - - if (data.spec.gotlife > 0 && (skip == true || data.spec.score % 50000 < oldscore % 50000)) // just passed a 50000 point mark - { - // lives are already added since tally is fake, but play the music - P_PlayLivesJingle(NULL); - --data.spec.gotlife; - } - } - */ - if (intertype == int_timeattack) - { - if (!intertic) - endtic = intertic + 10*TICRATE; // 10 second pause after end of tally - } - else if (intertype == int_race) - { - INT32 q=0,r=0; - - /* // SRB2kart - removed temporarily. - if (!intertic) { - if (!((music_playing == "karwin") // Mario Kart Win - || (music_playing == "karok") // Mario Kart Ok - || (music_playing == "karlos"))) // Mario Kart Lose - S_ChangeMusicInternal("racent", true); // Backup Plan - }*/ - - if (intertic < TICRATE || intertic % 8) - return; - - for (q = 0; q < data.match.numplayers; q++) - { - if (data.match.increase[q]) { - data.match.increase[q]--; - r++; - } - } - if (r) - S_StartSound(NULL, sfx_menu1); - else - if (modeattacking) - endtic = intertic + 10*TICRATE; // 10 second pause after end of tally + if (sorttic == -1) + sorttic = intertic + max((cv_inttime.value/2)-2, 2)*TICRATE; // 8 second pause after match results else - endtic = intertic + 3*TICRATE; // 3 second pause after end of tally - } - else if (intertype == int_match || intertype == int_ctf || intertype == int_teammatch) // match - { - if (!intertic) // first time only - S_ChangeMusicInternal("racent", true); // loop it + { + if (!data.match.rankingsmode && (intertic >= sorttic + 8)) + Y_CalculateMatchData(true, Y_CompareRank); - // If a player has left or joined, recalculate scores. - if (data.match.numplayers != D_NumPlayers()) - Y_CalculateMatchWinners(); - } - else if (intertype == int_race || intertype == int_classicrace) // race - { - if (!intertic) // first time only - S_ChangeMusicInternal("racent", true); // loop it + if (data.match.rankingsmode && intertic > sorttic+(2*TICRATE)) + { + INT32 q=0,r=0; + boolean kaching = true; - // Don't bother recalcing for race. It doesn't make as much sense. + for (q = 0; q < data.match.numplayers; q++) + { + if (data.match.num[q] == MAXPLAYERS + || !data.match.increase[data.match.num[q]] + || data.match.increase[data.match.num[q]] == UINT8_MAX) + continue; + + data.match.increase[data.match.num[q]]--; + r++; + if (data.match.increase[data.match.num[q]]) + kaching = false; + } + + if (r) + S_StartSound(NULL, (kaching ? sfx_chchng : sfx_ptally)); + else + endtic = intertic + 3*TICRATE; // 3 second pause after end of tally + } + } + } + else + endtic = intertic + 8*TICRATE; // 8 second pause after end of tally } } @@ -1012,8 +705,6 @@ static void Y_UpdateRecordReplays(void) // void Y_StartIntermission(void) { - INT32 i; - intertic = -1; #ifdef PARANOIA @@ -1025,12 +716,6 @@ void Y_StartIntermission(void) { timer = 0; - /* - if (G_IsSpecialStage(gamemap)) - intertype = (maptol & TOL_NIGHTS) ? int_nightsspec : int_spec; - else - intertype = (maptol & TOL_NIGHTS) ? int_nights : int_coop; - */ /* // srb2kart: time attack tally is UGLY rn if (modeattacking) intertype = int_timeattack; @@ -1050,29 +735,10 @@ void Y_StartIntermission(void) timer = 1; } - /* // SRB2kart - if (gametype == GT_COOP) - { - // Nights intermission is single player only - // Don't add it here - if (G_IsSpecialStage(gamemap)) - intertype = int_spec; - else - intertype = int_coop; - } - else */ - if (gametype == GT_TEAMMATCH) - intertype = int_teammatch; - else if (gametype == GT_MATCH - || gametype == GT_TAG - || gametype == GT_HIDEANDSEEK) + if (gametype == GT_MATCH) intertype = int_match; - else if (gametype == GT_RACE) + else //if (gametype == GT_RACE) intertype = int_race; - else if (gametype == GT_COMPETITION) - intertype = int_classicrace; - else if (gametype == GT_CTF) - intertype = int_ctf; } // We couldn't display the intermission even if we wanted to. @@ -1085,284 +751,18 @@ void Y_StartIntermission(void) switch (intertype) { - case int_nights: - // Can't fail - //G_SetNightsRecords(); - - // Check records - { - UINT8 earnedEmblems = M_CheckLevelEmblems(); - if (earnedEmblems) - CONS_Printf(M_GetText("\x82" "Earned %hu emblem%s for NiGHTS records.\n"), (UINT16)earnedEmblems, earnedEmblems > 1 ? "s" : ""); - } - - // fall back into the coop intermission for now - intertype = int_timeattack; - /* FALLTHRU */ - case int_timeattack: // coop or single player, normal level // SRB2kart 230117 - replaced int_coop - { - // award time and ring bonuses - // Y_AwardCoopBonuses(); - - // setup time data - data.coop.tics = players[consoleplayer].realtime; - - if ((!modifiedgame || savemoddata) && !multiplayer && !demoplayback) - { - // Update visitation flags - mapvisited[gamemap-1] |= MV_BEATEN; - if (ALL7EMERALDS(emeralds)) - mapvisited[gamemap-1] |= MV_ALLEMERALDS; - /*if (ultimatemode) - mapvisited[gamemap-1] |= MV_ULTIMATE; - if (data.coop.gotperfbonus) - mapvisited[gamemap-1] |= MV_PERFECT;*/ - - if (modeattacking == ATTACKING_RECORD) - Y_UpdateRecordReplays(); - } - - for (i = 0; i < 4; ++i) - data.coop.bonuspatches[i] = W_CachePatchName(data.coop.bonuses[i].patch, PU_STATIC); - data.coop.ptotal = W_CachePatchName("YB_TOTAL", PU_STATIC); - - // get act number - /*if (mapheaderinfo[prevmap]->actnum) - data.coop.ttlnum = W_CachePatchName(va("TTL%.2d", mapheaderinfo[prevmap]->actnum), - PU_STATIC); - else*/ - data.coop.ttlnum = W_CachePatchName("TTL01", PU_STATIC); - - // get background patches - widebgpatch = W_CachePatchName("INTERSCW", PU_STATIC); - bgpatch = W_CachePatchName("INTERSCR", PU_STATIC); - - // grab an interscreen if appropriate - if (mapheaderinfo[gamemap-1]->interscreen[0] != '#') - { - interpic = W_CachePatchName(mapheaderinfo[gamemap-1]->interscreen, PU_STATIC); - useinterpic = true; - usebuffer = false; - } - else - { - useinterpic = false; -#ifdef HWRENDER - if (rendermode == render_opengl) - usebuffer = true; // This needs to be here for OpenGL, otherwise usebuffer is never set to true for it, and thus there's no screenshot in the intermission -#endif - } - usetile = false; - - // set up the "got through act" message according to skin name - // too long so just show "YOU GOT THROUGH THE ACT" - if (strlen(skins[players[consoleplayer].skin].realname) > 13) - { - strcpy(data.coop.passed1, "YOU GOT"); - strcpy(data.coop.passed2, (strlen(mapheaderinfo[prevmap]->actnum) > 0) ? "THROUGH ACT" : "THROUGH THE ACT"); - } - // long enough that "X GOT" won't fit so use "X PASSED THE ACT" - else if (strlen(skins[players[consoleplayer].skin].realname) > 8) - { - strcpy(data.coop.passed1, skins[players[consoleplayer].skin].realname); - strcpy(data.coop.passed2, (strlen(mapheaderinfo[prevmap]->actnum) > 0) ? "PASSED ACT" : "PASSED THE ACT"); - } - // length is okay for normal use - else - { - snprintf(data.coop.passed1, sizeof data.coop.passed1, "%s GOT", - skins[players[consoleplayer].skin].realname); - strcpy(data.coop.passed2, (strlen(mapheaderinfo[prevmap]->actnum) > 0) ? "THROUGH ACT" : "THROUGH THE ACT"); - } - - // set X positions - if (strlen(mapheaderinfo[prevmap]->actnum) > 0) - { - data.coop.passedx1 = 62 + (176 - V_LevelNameWidth(data.coop.passed1))/2; - data.coop.passedx2 = 62 + (176 - V_LevelNameWidth(data.coop.passed2))/2; - } - else - { - data.coop.passedx1 = (BASEVIDWIDTH - V_LevelNameWidth(data.coop.passed1))/2; - data.coop.passedx2 = (BASEVIDWIDTH - V_LevelNameWidth(data.coop.passed2))/2; - } - // The above value is not precalculated because it needs only be computed once - // at the start of intermission, and precalculating it would preclude mods - // changing the font to one of a slightly different width. - break; - } - - /* // SRB2kart 230117 - removed - case int_nightsspec: - if (modeattacking && stagefailed) - { - // Nuh-uh. Get out of here. - Y_EndIntermission(); - Y_FollowIntermission(); - break; - } - if (!stagefailed) - G_SetNightsRecords(); - - // Check records - { - UINT8 earnedEmblems = M_CheckLevelEmblems(); - if (earnedEmblems) - CONS_Printf(M_GetText("\x82" "Earned %hu emblem%s for NiGHTS records.\n"), (UINT16)earnedEmblems, earnedEmblems > 1 ? "s" : ""); - } - - // fall back into the special stage intermission for now - intertype = int_spec; - // FALLTHRU - case int_spec: // coop or single player, special stage - { - // Update visitation flags? - if ((!modifiedgame || savemoddata) && !multiplayer && !demoplayback) - { - if (!stagefailed) - mapvisited[gamemap-1] |= MV_BEATEN; - } - - // give out ring bonuses - Y_AwardSpecialStageBonus(); - - data.spec.bonuspatch = W_CachePatchName(data.spec.bonus.patch, PU_STATIC); - data.spec.pscore = W_CachePatchName("YB_SCORE", PU_STATIC); - data.spec.pcontinues = W_CachePatchName("YB_CONTI", PU_STATIC); - - // get background tile - bgtile = W_CachePatchName("SPECTILE", PU_STATIC); - - // grab an interscreen if appropriate - if (mapheaderinfo[gamemap-1]->interscreen[0] != '#') - { - interpic = W_CachePatchName(mapheaderinfo[gamemap-1]->interscreen, PU_STATIC); - useinterpic = true; - } - else - useinterpic = false; - - // tile if using the default background - usetile = !useinterpic; - - // get special stage specific patches - if (!stagefailed && ALL7EMERALDS(emeralds)) - { - data.spec.cemerald = W_CachePatchName("GOTEMALL", PU_STATIC); - data.spec.headx = 70; - data.spec.nowsuper = players[consoleplayer].skin - ? NULL : W_CachePatchName("NOWSUPER", PU_STATIC); - } - else - { - data.spec.cemerald = W_CachePatchName("CEMERALD", PU_STATIC); - data.spec.headx = 48; - data.spec.nowsuper = NULL; - } - - // Super form stuff (normally blank) - data.spec.passed3[0] = '\0'; - data.spec.passed4[0] = '\0'; - - // Super form stuff (normally blank) - data.spec.passed3[0] = '\0'; - data.spec.passed4[0] = '\0'; - - // set up the "got through act" message according to skin name - if (stagefailed) - { - strcpy(data.spec.passed2, "SPECIAL STAGE"); - data.spec.passed1[0] = '\0'; - } - else if (ALL7EMERALDS(emeralds)) - { - snprintf(data.spec.passed1, - sizeof data.spec.passed1, "%s", - skins[players[consoleplayer].skin].realname); - data.spec.passed1[sizeof data.spec.passed1 - 1] = '\0'; - strcpy(data.spec.passed2, "GOT THEM ALL!"); - - if (skins[players[consoleplayer].skin].flags & SF_SUPER) - { - strcpy(data.spec.passed3, "CAN NOW BECOME"); - snprintf(data.spec.passed4, - sizeof data.spec.passed4, "SUPER %s", - skins[players[consoleplayer].skin].realname); - data.spec.passed4[sizeof data.spec.passed4 - 1] = '\0'; - } - } - else - { - if (strlen(skins[players[consoleplayer].skin].realname) <= SKINNAMESIZE-5) - { - snprintf(data.spec.passed1, - sizeof data.spec.passed1, "%s GOT", - skins[players[consoleplayer].skin].realname); - data.spec.passed1[sizeof data.spec.passed1 - 1] = '\0'; - } - else - strcpy(data.spec.passed1, "YOU GOT"); - strcpy(data.spec.passed2, "A CHAOS EMERALD"); - } - data.spec.passedx1 = (BASEVIDWIDTH - V_LevelNameWidth(data.spec.passed1))/2; - data.spec.passedx2 = (BASEVIDWIDTH - V_LevelNameWidth(data.spec.passed2))/2; - data.spec.passedx3 = (BASEVIDWIDTH - V_LevelNameWidth(data.spec.passed3))/2; - data.spec.passedx4 = (BASEVIDWIDTH - V_LevelNameWidth(data.spec.passed4))/2; - break; - }*/ - case int_match: { // Calculate who won - Y_CalculateMatchWinners(); - - // set up the levelstring - if (strlen(mapheaderinfo[prevmap]->zonttl) > 0) - { - if (strlen(mapheaderinfo[prevmap]->actnum) > 0) - snprintf(data.match.levelstring, - sizeof data.match.levelstring, - "%.32s %.32s * %s *", - mapheaderinfo[prevmap]->lvlttl, mapheaderinfo[prevmap]->zonttl, mapheaderinfo[prevmap]->actnum); - else - snprintf(data.match.levelstring, - sizeof data.match.levelstring, - "* %.32s %.32s *", - mapheaderinfo[prevmap]->lvlttl, mapheaderinfo[prevmap]->zonttl); - } - else - { - if (strlen(mapheaderinfo[prevmap]->actnum) > 0) - snprintf(data.match.levelstring, - sizeof data.match.levelstring, - "%.32s * %s *", - mapheaderinfo[prevmap]->lvlttl, mapheaderinfo[prevmap]->actnum); - else - snprintf(data.match.levelstring, - sizeof data.match.levelstring, - "* %.32s *", - mapheaderinfo[prevmap]->lvlttl); - } - - data.match.levelstring[sizeof data.match.levelstring - 1] = '\0'; - - // get RESULT header - data.match.result = - W_CachePatchName("RESULT", PU_STATIC); - - bgtile = W_CachePatchName("SRB2BACK", PU_STATIC); - usetile = true; - useinterpic = false; + Y_CalculateMatchData(false, Y_CompareBattle); + if (cv_inttime.value > 0) + S_ChangeMusicInternal("racent", true); // loop it break; } - case int_race: // (time-only race) { if ((!modifiedgame || savemoddata) && !multiplayer && !demoplayback) // remove this once we have a proper time attack screen { - // setup time data - data.coop.tics = players[consoleplayer].realtime; - // Update visitation flags mapvisited[gamemap-1] |= MV_BEATEN; if (ALL7EMERALDS(emeralds)) @@ -1377,107 +777,7 @@ void Y_StartIntermission(void) } // Calculate who won - Y_CalculateTournamentPoints(); - - // set up the levelstring - if (strlen(mapheaderinfo[prevmap]->zonttl) > 0) - { - if (strlen(mapheaderinfo[prevmap]->actnum) > 0) - snprintf(data.match.levelstring, - sizeof data.match.levelstring, - "%.32s %.32s * %s *", - mapheaderinfo[prevmap]->lvlttl, mapheaderinfo[prevmap]->zonttl, mapheaderinfo[prevmap]->actnum); - else - snprintf(data.match.levelstring, - sizeof data.match.levelstring, - "* %.32s %.32s *", - mapheaderinfo[prevmap]->lvlttl, mapheaderinfo[prevmap]->zonttl); - } - else - { - if (strlen(mapheaderinfo[prevmap]->actnum) > 0) - snprintf(data.match.levelstring, - sizeof data.match.levelstring, - "%.32s * %s *", - mapheaderinfo[prevmap]->lvlttl, mapheaderinfo[prevmap]->actnum); - else - snprintf(data.match.levelstring, - sizeof data.match.levelstring, - "* %.32s *", - mapheaderinfo[prevmap]->lvlttl); - } - - data.match.levelstring[sizeof data.match.levelstring - 1] = '\0'; - - // get RESULT header - //data.match.result = W_CachePatchName("RESULT", PU_STATIC); - - bgtile = W_CachePatchName("SRB2BACK", PU_STATIC); - usetile = true; - useinterpic = false; - break; - } - - case int_teammatch: - case int_ctf: - { - // Calculate who won - Y_CalculateMatchWinners(); - - // set up the levelstring - if (strlen(mapheaderinfo[prevmap]->actnum) > 0) - snprintf(data.match.levelstring, - sizeof data.match.levelstring, - "%.32s * %s *", - mapheaderinfo[prevmap]->lvlttl, mapheaderinfo[prevmap]->actnum); - else - snprintf(data.match.levelstring, - sizeof data.match.levelstring, - "* %.32s *", - mapheaderinfo[prevmap]->lvlttl); - - data.match.levelstring[sizeof data.match.levelstring - 1] = '\0'; - - if (intertype == int_ctf) - { - data.match.redflag = rflagico; - data.match.blueflag = bflagico; - } - else // team match - { - data.match.redflag = rmatcico; - data.match.blueflag = bmatcico; - } - - bgtile = W_CachePatchName("SRB2BACK", PU_STATIC); - usetile = true; - useinterpic = false; - break; - } - - case int_classicrace: // classic (full race) - { - // find out who won - Y_CalculateCompetitionWinners(); - - // set up the levelstring - if (strlen(mapheaderinfo[prevmap]->actnum) > 0) - snprintf(data.competition.levelstring, - sizeof data.competition.levelstring, - "%.32s * %s *", - mapheaderinfo[prevmap]->lvlttl, mapheaderinfo[prevmap]->actnum); - else - snprintf(data.competition.levelstring, - sizeof data.competition.levelstring, - "* %.32s *", - mapheaderinfo[prevmap]->lvlttl); - - data.competition.levelstring[sizeof data.competition.levelstring - 1] = '\0'; - - // get background tile - bgtile = W_CachePatchName("SRB2BACK", PU_STATIC); - usetile = true; - useinterpic = false; + Y_CalculateMatchData(false, Y_CompareRace); break; } @@ -1485,521 +785,12 @@ void Y_StartIntermission(void) default: break; } -} -// -// Y_CalculateMatchWinners -// -static void Y_CalculateMatchWinners(void) -{ - INT32 i, j; - boolean completed[MAXPLAYERS]; - - // Initialize variables - memset(data.match.scores, 0, sizeof (data.match.scores)); - memset(data.match.color, 0, sizeof (data.match.color)); - memset(data.match.character, 0, sizeof (data.match.character)); - memset(data.match.spectator, 0, sizeof (data.match.spectator)); - memset(completed, 0, sizeof (completed)); - data.match.numplayers = 0; - i = j = 0; - - for (j = 0; j < MAXPLAYERS; j++) + //if (intertype == int_race || intertype == int_match) { - if (!playeringame[j]) - continue; - - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i]) - continue; - - if (players[i].score >= data.match.scores[data.match.numplayers] && completed[i] == false) - { - data.match.scores[data.match.numplayers] = players[i].score; - data.match.color[data.match.numplayers] = &players[i].skincolor; - data.match.character[data.match.numplayers] = &players[i].skin; - data.match.name[data.match.numplayers] = player_names[i]; - data.match.spectator[data.match.numplayers] = players[i].spectator; - data.match.num[data.match.numplayers] = i; - } - } - completed[data.match.num[data.match.numplayers]] = true; - data.match.numplayers++; - } -} - -/* -// -// Y_CalculateTimeRaceWinners -// -static void Y_CalculateTimeRaceWinners(void) -{ - INT32 i, j; - boolean completed[MAXPLAYERS]; - - // Initialize variables - - for (i = 0; i < MAXPLAYERS; i++) - data.match.scores[i] = INT32_MAX; - - memset(data.match.color, 0, sizeof (data.match.color)); - memset(data.match.character, 0, sizeof (data.match.character)); - memset(data.match.spectator, 0, sizeof (data.match.spectator)); - memset(completed, 0, sizeof (completed)); - data.match.numplayers = 0; - i = j = 0; - - for (j = 0; j < MAXPLAYERS; j++) - { - if (!playeringame[j]) - continue; - - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i]) - continue; - - if (players[i].realtime <= data.match.scores[data.match.numplayers] && completed[i] == false) - { - data.match.scores[data.match.numplayers] = players[i].realtime; - data.match.color[data.match.numplayers] = &players[i].skincolor; - data.match.character[data.match.numplayers] = &players[i].skin; - data.match.name[data.match.numplayers] = player_names[i]; - data.match.num[data.match.numplayers] = i; - } - } - completed[data.match.num[data.match.numplayers]] = true; - data.match.numplayers++; - } -} -*/ - -// -// Y_CalculateCompetitionWinners -// -static void Y_CalculateCompetitionWinners(void) -{ - INT32 i, j; - boolean bestat[5]; - boolean completed[MAXPLAYERS]; - INT32 winner; // shortcut - - UINT32 points[MAXPLAYERS]; - UINT32 times[MAXPLAYERS]; - UINT32 rings[MAXPLAYERS]; - UINT32 maxrings[MAXPLAYERS]; - UINT32 monitors[MAXPLAYERS]; - UINT32 scores[MAXPLAYERS]; - - memset(data.competition.points, 0, sizeof (data.competition.points)); - memset(points, 0, sizeof (points)); - memset(completed, 0, sizeof (completed)); - - // Award points. - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i]) - continue; - - for (j = 0; j < 5; j++) - bestat[j] = true; - - times[i] = players[i].realtime; - rings[i] = (UINT32)max(players[i].health-1, 0); - maxrings[i] = (UINT32)players[i].totalring; - monitors[i] = (UINT32)players[i].numboxes; - scores[i] = (UINT32)min(players[i].score, 99999990); - - for (j = 0; j < MAXPLAYERS; j++) - { - if (!playeringame[j] || j == i) - continue; - - if (players[i].realtime <= players[j].realtime) - points[i]++; - else - bestat[0] = false; - - if (max(players[i].health-1, 0) >= max(players[j].health-1, 0)) - points[i]++; - else - bestat[1] = false; - - if (players[i].totalring >= players[j].totalring) - points[i]++; - else - bestat[2] = false; - - if (players[i].numboxes >= players[j].numboxes) - points[i]++; - else - bestat[3] = false; - - if (players[i].score >= players[j].score) - points[i]++; - else - bestat[4] = false; - } - - // Highlight best scores - if (bestat[0]) - times[i] |= 0x80000000; - if (bestat[1]) - rings[i] |= 0x80000000; - if (bestat[2]) - maxrings[i] |= 0x80000000; - if (bestat[3]) - monitors[i] |= 0x80000000; - if (bestat[4]) - scores[i] |= 0x80000000; - } - - // Now we go through and set the data.competition struct properly - data.competition.numplayers = 0; - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i]) - continue; - - winner = 0; - - for (j = 0; j < MAXPLAYERS; j++) - { - if (!playeringame[j]) - continue; - - if (points[j] >= data.competition.points[data.competition.numplayers] && completed[j] == false) - { - data.competition.points[data.competition.numplayers] = points[j]; - data.competition.num[data.competition.numplayers] = winner = j; - } - } - // We know this person won this spot, now let's set everything appropriately - data.competition.times[data.competition.numplayers] = times[winner]; - data.competition.rings[data.competition.numplayers] = rings[winner]; - data.competition.maxrings[data.competition.numplayers] = maxrings[winner]; - data.competition.monitors[data.competition.numplayers] = monitors[winner]; - data.competition.scores[data.competition.numplayers] = scores[winner]; - - snprintf(data.competition.name[data.competition.numplayers], 9, "%s", player_names[winner]); - data.competition.name[data.competition.numplayers][8] = '\0'; - - data.competition.color[data.competition.numplayers] = &players[winner].skincolor; - data.competition.character[data.competition.numplayers] = &players[winner].skin; - - completed[winner] = true; - data.competition.numplayers++; - } -} - -// ============ -// COOP BONUSES -// ============ - -// -// Y_SetNullBonus -// No bonus in this slot, but we need to set some things anyway. -// -static void Y_SetNullBonus(player_t *player, y_bonus_t *bstruct) -{ - (void)player; - memset(bstruct, 0, sizeof(y_bonus_t)); - strncpy(bstruct->patch, "MISSING", sizeof(bstruct->patch)); -} - -// -// Y_SetTimeBonus -// -static void Y_SetTimeBonus(player_t *player, y_bonus_t *bstruct) -{ - INT32 secs, bonus; - - strncpy(bstruct->patch, "YB_TIME", sizeof(bstruct->patch)); - bstruct->display = true; - - // calculate time bonus - secs = player->realtime / TICRATE; - if (secs < 30) /* :30 */ bonus = 100000; - else if (secs < 45) /* :45 */ bonus = 50000; - else if (secs < 60) /* 1:00 */ bonus = 10000; - else if (secs < 90) /* 1:30 */ bonus = 5000; - else if (secs < 120) /* 2:00 */ bonus = 4000; - else if (secs < 180) /* 3:00 */ bonus = 3000; - else if (secs < 240) /* 4:00 */ bonus = 2000; - else if (secs < 300) /* 5:00 */ bonus = 1000; - else if (secs < 360) /* 6:00 */ bonus = 500; - else if (secs < 420) /* 7:00 */ bonus = 400; - else if (secs < 480) /* 8:00 */ bonus = 300; - else if (secs < 540) /* 9:00 */ bonus = 200; - else if (secs < 600) /* 10:00 */ bonus = 100; - else /* TIME TAKEN: TOO LONG */ bonus = 0; - bstruct->points = bonus; -} - -// -// Y_SetRingBonus -// -static void Y_SetRingBonus(player_t *player, y_bonus_t *bstruct) -{ - strncpy(bstruct->patch, "YB_RING", sizeof(bstruct->patch)); - bstruct->display = true; - bstruct->points = max(0, (player->health-1) * 100); -} - -// -// Y_SetLinkBonus -// -/* -static void Y_SetLinkBonus(player_t *player, y_bonus_t *bstruct) // SRB2kart - unused. -{ - strncpy(bstruct->patch, "YB_LINK", sizeof(bstruct->patch)); - bstruct->display = true; - bstruct->points = max(0, (player->maxlink - 1) * 100); -} -*/ - -// -// Y_SetGuardBonus -// -static void Y_SetGuardBonus(player_t *player, y_bonus_t *bstruct) -{ - INT32 bonus; - strncpy(bstruct->patch, "YB_GUARD", sizeof(bstruct->patch)); - bstruct->display = true; - - if (player->timeshit == 0) bonus = 10000; - else if (player->timeshit == 1) bonus = 5000; - else if (player->timeshit == 2) bonus = 1000; - else if (player->timeshit == 3) bonus = 500; - else if (player->timeshit == 4) bonus = 100; - else bonus = 0; - bstruct->points = bonus; -} - -// -// Y_SetPerfectBonus -// -static void Y_SetPerfectBonus(player_t *player, y_bonus_t *bstruct) -{ - INT32 i; - - (void)player; - memset(bstruct, 0, sizeof(y_bonus_t)); - strncpy(bstruct->patch, "YB_PERFE", sizeof(bstruct->patch)); - - if (data.coop.gotperfbonus == -1) - { - INT32 sharedringtotal = 0; - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i]) continue; - sharedringtotal += players[i].health - 1; - } - if (!sharedringtotal || sharedringtotal < nummaprings) - data.coop.gotperfbonus = 0; - else - data.coop.gotperfbonus = 1; - } - if (!data.coop.gotperfbonus) - return; - - bstruct->display = true; - bstruct->points = 50000; -} - -// This list can be extended in the future with SOC/Lua, perhaps. -typedef void (*bonus_f)(player_t *, y_bonus_t *); -bonus_f bonuses_list[4][4] = { - { - Y_SetNullBonus, - Y_SetNullBonus, - Y_SetNullBonus, - Y_SetNullBonus, - }, - { - Y_SetNullBonus, - Y_SetTimeBonus, - Y_SetRingBonus, - Y_SetPerfectBonus, - }, - { - Y_SetNullBonus, - Y_SetGuardBonus, - Y_SetRingBonus, - Y_SetNullBonus, - }, - { - Y_SetNullBonus, - Y_SetGuardBonus, - Y_SetRingBonus, - Y_SetPerfectBonus, - }, -}; - - -/* // SRB2kart 230117 - Replaced with Y_CalculateTournamentPoints -// -// Y_AwardCoopBonuses -// -// Awards the time and ring bonuses. -// -static void Y_AwardCoopBonuses(void) -{ - INT32 i, j, bonusnum, oldscore, ptlives; - y_bonus_t localbonuses[4]; - - // set score/total first - data.coop.total = 0; - data.coop.score = players[consoleplayer].score; - data.coop.gotperfbonus = -1; - memset(data.coop.bonuses, 0, sizeof(data.coop.bonuses)); - memset(data.coop.bonuspatches, 0, sizeof(data.coop.bonuspatches)); - - for (i = 0; i < MAXPLAYERS; ++i) - { - if (!playeringame[i] || players[i].lives < 1) // not active or game over - bonusnum = 0; // all null - else - bonusnum = mapheaderinfo[prevmap]->bonustype + 1; // -1 is none - - oldscore = players[i].score; - - for (j = 0; j < 4; ++j) // Set bonuses - { - (bonuses_list[bonusnum][j])(&players[i], &localbonuses[j]); - players[i].score += localbonuses[j].points; - } - - ptlives = (!ultimatemode && !modeattacking) ? max((players[i].score/50000) - (oldscore/50000), 0) : 0; - if (ptlives) - P_GivePlayerLives(&players[i], ptlives); - - if (i == consoleplayer) - { - data.coop.gotlife = ptlives; - M_Memcpy(&data.coop.bonuses, &localbonuses, sizeof(data.coop.bonuses)); - } - } - - // Just in case the perfect bonus wasn't checked. - if (data.coop.gotperfbonus < 0) - data.coop.gotperfbonus = 0; -} - -// -// Y_AwardSpecialStageBonus -// -// Gives a ring bonus only. -static void Y_AwardSpecialStageBonus(void) -{ - INT32 i, oldscore, ptlives; - y_bonus_t localbonus; - - data.spec.score = players[consoleplayer].score; - memset(&data.spec.bonus, 0, sizeof(data.spec.bonus)); - data.spec.bonuspatch = NULL; - - for (i = 0; i < MAXPLAYERS; i++) - { - oldscore = players[i].score; - - if (!playeringame[i] || players[i].lives < 1) // not active or game over - Y_SetNullBonus(&players[i], &localbonus); - else if (useNightsSS) // Link instead of Score - Y_SetLinkBonus(&players[i], &localbonus); - else - Y_SetRingBonus(&players[i], &localbonus); - players[i].score += localbonus.points; - - // grant extra lives right away since tally is faked - ptlives = (!ultimatemode && !modeattacking) ? max((players[i].score/50000) - (oldscore/50000), 0) : 0; - if (ptlives) - P_GivePlayerLives(&players[i], ptlives); - - if (i == consoleplayer) - { - M_Memcpy(&data.spec.bonus, &localbonus, sizeof(data.spec.bonus)); - - data.spec.gotlife = ptlives; - - // Continues related - data.spec.continues = min(players[i].continues, 8); - if (players[i].gotcontinue) - data.spec.continues |= 0x80; - data.spec.playercolor = &players[i].skincolor; - data.spec.playerchar = &players[i].skin; - } - } -} -*/ - -// -// Y_CalculateTournamentPoints -// -static void Y_CalculateTournamentPoints(void) -{ - INT32 i, j; - boolean completed[MAXPLAYERS]; - INT32 numplayersingame = 0; - INT32 increase[MAXPLAYERS]; - - for (i = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i]) - numplayersingame++; - } - - for (i = 0; i < numplayersingame; i++) - { - increase[i] = numplayersingame-i; - - if (increase[i] < 0) - increase[i] = 0; - } - - // Initialize variables - for (j = 0; j < MAXPLAYERS; j++) - data.match.scores[j] = INT32_MAX; - - memset(data.match.time, 0, sizeof (data.match.time)); - memset(data.match.color, 0, sizeof (data.match.color)); - memset(data.match.character, 0, sizeof (data.match.character)); - memset(data.match.spectator, 0, sizeof (data.match.spectator)); - memset(data.match.increase, 0, sizeof (data.match.increase)); - memset(completed, 0, sizeof (completed)); - data.match.numplayers = 0; - i = j = 0; - - for (j = 0; j < MAXPLAYERS; j++) - { - if (!playeringame[j]) - continue; - - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i]) - continue; - - if (players[i].realtime <= data.match.scores[data.match.numplayers] && completed[i] == false) - { - data.match.time[data.match.numplayers] = players[i].realtime; - data.match.scores[data.match.numplayers] = players[i].realtime; - data.match.color[data.match.numplayers] = &players[i].skincolor; - data.match.character[data.match.numplayers] = &players[i].skin; - data.match.name[data.match.numplayers] = player_names[i]; - data.match.spectator[data.match.numplayers] = players[i].spectator; - data.match.num[data.match.numplayers] = i; - } - } - completed[data.match.num[data.match.numplayers]] = true; - if (!(players[data.match.num[data.match.numplayers]].pflags & PF_TIMEOVER - || players[data.match.num[data.match.numplayers]].spectator)) - data.match.increase[data.match.numplayers] = increase[data.match.numplayers]; - players[data.match.num[data.match.numplayers]].score += data.match.increase[data.match.numplayers]; - data.match.scores[data.match.numplayers] = players[data.match.num[data.match.numplayers]].score; - - data.match.numplayers++; + //bgtile = W_CachePatchName("SRB2BACK", PU_STATIC); + usetile = useinterpic = false; + usebuffer = true; } } @@ -2013,6 +804,7 @@ void Y_EndIntermission(void) Y_UnloadData(); endtic = -1; + sorttic = -1; intertype = int_none; usebuffer = false; } @@ -2094,9 +886,8 @@ static void Y_UnloadData(void) UNLOAD(bgtile); UNLOAD(interpic); - switch (intertype) + /*switch (intertype) { - /* case int_coop: // unload the coop and single player patches UNLOAD(data.coop.ttlnum); @@ -2114,21 +905,14 @@ static void Y_UnloadData(void) UNLOAD(data.spec.pscore); UNLOAD(data.spec.pcontinues); break; - */ case int_match: case int_race: - UNLOAD(data.match.result); - break; - case int_ctf: - UNLOAD(data.match.blueflag); - UNLOAD(data.match.redflag); - break; default: //without this default, //int_none, int_tag, int_chaos, and int_classicrace //are not handled break; - } + }*/ } // SRB2Kart: Voting! @@ -2149,6 +933,9 @@ void Y_VoteDrawer(void) if (votetic >= voteendtic && voteendtic != -1) return; + if (!voteclient.loaded) + return; + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); if (widebgpatch && rendermode == render_soft && vid.width / vid.dupx > 320) @@ -2185,9 +972,7 @@ void Y_VoteDrawer(void) { char str[40]; patch_t *pic; - UINT8 sizeadd = selected[i]; - UINT8 j; - UINT8 color; + UINT8 j, color; if (i == 3) { @@ -2203,19 +988,23 @@ void Y_VoteDrawer(void) if (selected[i]) { + UINT8 sizeadd = selected[i]; + for (j = 0; j <= splitscreen; j++) // another loop for drawing the selection backgrounds in the right order, grumble grumble.. { INT32 handy = y; + UINT8 p; UINT8 *colormap; patch_t *thiscurs; if (voteclient.playerinfo[j].selection != i) continue; - if (splitscreen == 0) + if (!splitscreen) { thiscurs = cursor; - color = colortranslations[players[consoleplayer].skincolor][7]; + p = consoleplayer; + color = levelinfo[i].gtc; colormap = NULL; } else @@ -2224,31 +1013,33 @@ void Y_VoteDrawer(void) { case 1: thiscurs = cursor2; - color = colortranslations[players[secondarydisplayplayer].skincolor][7]; - colormap = R_GetTranslationColormap(-1, players[secondarydisplayplayer].skincolor, GTC_CACHE); + p = secondarydisplayplayer; break; case 2: thiscurs = cursor3; - color = colortranslations[players[thirddisplayplayer].skincolor][7]; - colormap = R_GetTranslationColormap(-1, players[thirddisplayplayer].skincolor, GTC_CACHE); + p = thirddisplayplayer; break; case 3: thiscurs = cursor4; - color = colortranslations[players[fourthdisplayplayer].skincolor][7]; - colormap = R_GetTranslationColormap(-1, players[fourthdisplayplayer].skincolor, GTC_CACHE); + p = fourthdisplayplayer; break; default: thiscurs = cursor1; - color = colortranslations[players[consoleplayer].skincolor][7]; - colormap = R_GetTranslationColormap(-1, players[consoleplayer].skincolor, GTC_CACHE); + p = displayplayer; break; } + + color = colortranslations[players[p].skincolor][7]; + colormap = R_GetTranslationColormap(TC_DEFAULT, players[p].skincolor, GTC_CACHE); } + if (votes[p] != -1 || players[p].spectator) + continue; + handy += 6*(3-splitscreen) + (13*j); V_DrawMappedPatch(BASEVIDWIDTH-124, handy, V_SNAPTORIGHT, thiscurs, colormap); - if (votetic % 5 == 0) + if (votetic % 10 < 4) V_DrawFill(BASEVIDWIDTH-100-sizeadd, y-sizeadd, 80+(sizeadd*2), 50+(sizeadd*2), 120|V_SNAPTORIGHT); else V_DrawFill(BASEVIDWIDTH-100-sizeadd, y-sizeadd, 80+(sizeadd*2), 50+(sizeadd*2), color|V_SNAPTORIGHT); @@ -2258,11 +1049,26 @@ void Y_VoteDrawer(void) V_DrawSmallScaledPatch(BASEVIDWIDTH-100, y, V_SNAPTORIGHT, pic); V_DrawRightAlignedThinString(BASEVIDWIDTH-20, 40+y, V_SNAPTORIGHT, str); + if (levelinfo[i].gts) + { + INT32 w = V_ThinStringWidth(levelinfo[i].gts, V_SNAPTORIGHT)+1; + V_DrawFill(BASEVIDWIDTH-100, y+10, w+1, 2, V_SNAPTORIGHT|31); + V_DrawFill(BASEVIDWIDTH-100, y, w, 11, V_SNAPTORIGHT|levelinfo[i].gtc); + V_DrawDiag(BASEVIDWIDTH-100+w+1, y, 12, V_SNAPTORIGHT|31); + V_DrawDiag(BASEVIDWIDTH-100+w, y, 11, V_SNAPTORIGHT|levelinfo[i].gtc); + V_DrawThinString(BASEVIDWIDTH-99, y+1, V_SNAPTORIGHT, levelinfo[i].gts); + } + y += 50; } else { V_DrawTinyScaledPatch(BASEVIDWIDTH-60, y, V_SNAPTORIGHT, pic); + if (levelinfo[i].gts) + { + V_DrawDiag(BASEVIDWIDTH-60, y, 8, V_SNAPTORIGHT|31); + V_DrawDiag(BASEVIDWIDTH-60, y, 6, V_SNAPTORIGHT|levelinfo[i].gtc); + } y += 25; } @@ -2281,7 +1087,7 @@ void Y_VoteDrawer(void) { patch_t *pic; - if (votes[i] == 3 && (i != pickedvote || voteendtic == -1)) + if (votes[i] >= 3 && (i != pickedvote || voteendtic == -1)) pic = randomlvl; else pic = levelinfo[votes[i]].pic; @@ -2289,13 +1095,18 @@ void Y_VoteDrawer(void) if (!timer && i == voteclient.ranim) { V_DrawScaledPatch(x-18, y+9, V_SNAPTOLEFT, cursor); - if (votetic % 4 > 1) + if (voteendtic != -1 && !(votetic % 4)) V_DrawFill(x-1, y-1, 42, 27, 120|V_SNAPTOLEFT); else - V_DrawFill(x-1, y-1, 42, 27, 103|V_SNAPTOLEFT); + V_DrawFill(x-1, y-1, 42, 27, levelinfo[votes[i]].gtc|V_SNAPTOLEFT); } V_DrawTinyScaledPatch(x, y, V_SNAPTOLEFT, pic); + if (levelinfo[votes[i]].gts) + { + V_DrawDiag(x, y, 8, V_SNAPTOLEFT|31); + V_DrawDiag(x, y, 6, V_SNAPTOLEFT|levelinfo[votes[i]].gtc); + } if (players[i].skincolor == 0) V_DrawSmallScaledPatch(x+24, y+9, V_SNAPTOLEFT, faceprefix[players[i].skin]); @@ -2316,8 +1127,45 @@ void Y_VoteDrawer(void) } if (timer) - V_DrawCenteredString(BASEVIDWIDTH/2, 188, V_YELLOWMAP|V_SNAPTOBOTTOM, - va("Vote ends in %d seconds", timer/TICRATE)); + { + INT32 hilicol, tickdown = (timer+1)/TICRATE; + if (cons_menuhighlight.value) + hilicol = cons_menuhighlight.value; + else if (gametype == GT_RACE) + hilicol = V_SKYMAP; + else //if (gametype == GT_MATCH) + hilicol = V_REDMAP; + V_DrawCenteredString(BASEVIDWIDTH/2, 188, hilicol, + va("Vote ends in %d", tickdown)); + } +} + +// +// Y_VoteStop +// +// Vote screen's selection stops moving +// +SINT8 deferredlevel = 0; +static void Y_VoteStops(SINT8 pick, SINT8 level) +{ + nextmap = votelevels[level][0]; + + if (level == 4) + S_StartSound(NULL, sfx_noooo2); // gasp + else if (mapheaderinfo[nextmap] && (mapheaderinfo[nextmap]->menuflags & LF2_HIDEINMENU)) + S_StartSound(NULL, sfx_noooo1); // this is bad + else if (!splitscreen && pick == consoleplayer) + S_StartSound(NULL, sfx_yeeeah); // yeeeah! + else + S_StartSound(NULL, sfx_kc48); // just a cool sound + + if (gametype != votelevels[level][1]) + { + INT16 lastgametype = gametype; + gametype = votelevels[level][1]; + D_GameTypeChanged(lastgametype); + forceresetplayers = true; + } } // @@ -2329,14 +1177,14 @@ void Y_VoteTicker(void) { INT32 i; - if (paused || P_AutoPause()) + if (paused || P_AutoPause() || !voteclient.loaded) return; votetic++; if (votetic == voteendtic) { - Y_UnloadVoteData(); // Y_EndVote resets voteendtic too early apparently, causing the game to try to render patches that we just unloaded... + Y_EndVote(); Y_FollowIntermission(); return; } @@ -2378,7 +1226,7 @@ void Y_VoteTicker(void) if (numvotes < 1) // Whoops! Get outta here. { - Y_UnloadVoteData(); + Y_EndVote(); Y_FollowIntermission(); return; } @@ -2399,17 +1247,25 @@ void Y_VoteTicker(void) { if (voteclient.rendoff == 0) { - if (tempvotes[((pickedvote + voteclient.roffset + 4) % numvotes)] == pickedvote - && voteclient.rsynctime % 51 == 0) // Song is 1.45 seconds long (sorry @ whoever wants to replace it in a music wad :V) + if (voteclient.rsynctime % 51 == 0) // Song is 1.45 seconds long (sorry @ whoever wants to replace it in a music wad :V) { - voteclient.rendoff = voteclient.roffset+4; - S_ChangeMusicInternal("voteeb", false); + for (i = 5; i >= 3; i--) // Find a suitable place to stop + { + if (tempvotes[((pickedvote + voteclient.roffset + i) % numvotes)] == pickedvote) + { + voteclient.rendoff = voteclient.roffset+i; + if (M_RandomChance(FRACUNIT/32)) // Let it cheat occasionally~ + voteclient.rendoff++; + S_ChangeMusicInternal("voteeb", false); + break; + } + } } } else if (voteclient.roffset >= voteclient.rendoff) { voteendtic = votetic + (3*TICRATE); - S_StartSound(NULL, sfx_kc48); + Y_VoteStops(pickedvote, deferredlevel); } } } @@ -2522,8 +1378,8 @@ void Y_StartVote(void) I_Error("voteendtic is dirty"); #endif - widebgpatch = W_CachePatchName("INTERSCW", PU_STATIC); - bgpatch = W_CachePatchName("INTERSCR", PU_STATIC); + widebgpatch = W_CachePatchName(((gametype == GT_MATCH) ? "BATTLSCW" : "INTERSCW"), PU_STATIC); + bgpatch = W_CachePatchName(((gametype == GT_MATCH) ? "BATTLSCR" : "INTERSCR"), PU_STATIC); cursor = W_CachePatchName("M_CURSOR", PU_STATIC); cursor1 = W_CachePatchName("P1CURSOR", PU_STATIC); cursor2 = W_CachePatchName("P2CURSOR", PU_STATIC); @@ -2549,46 +1405,61 @@ void Y_StartVote(void) for (i = 0; i < MAXPLAYERS; i++) votes[i] = -1; - for (i = 0; i < 4; i++) + for (i = 0; i < 5; i++) { lumpnum_t lumpnum; // set up the str - if (strlen(mapheaderinfo[votelevels[i]]->zonttl) > 0) - { - if (strlen(mapheaderinfo[votelevels[i]]->actnum) > 0) - snprintf(levelinfo[i].str, - sizeof levelinfo[i].str, - "%.32s %.32s %s", - mapheaderinfo[votelevels[i]]->lvlttl, mapheaderinfo[votelevels[i]]->zonttl, mapheaderinfo[votelevels[i]]->actnum); - else - snprintf(levelinfo[i].str, - sizeof levelinfo[i].str, - "%.32s %.32s", - mapheaderinfo[votelevels[i]]->lvlttl, mapheaderinfo[votelevels[i]]->zonttl); - } + if (i == 4) + levelinfo[i].str[0] = '\0'; else { - if (strlen(mapheaderinfo[votelevels[i]]->actnum) > 0) - snprintf(levelinfo[i].str, - sizeof levelinfo[i].str, - "%.32s %s", - mapheaderinfo[votelevels[i]]->lvlttl, mapheaderinfo[votelevels[i]]->actnum); + if (strlen(mapheaderinfo[votelevels[i][0]]->zonttl) > 0) + { + if (strlen(mapheaderinfo[votelevels[i][0]]->actnum) > 0) + snprintf(levelinfo[i].str, + sizeof levelinfo[i].str, + "%.32s %.32s %s", + mapheaderinfo[votelevels[i][0]]->lvlttl, mapheaderinfo[votelevels[i][0]]->zonttl, mapheaderinfo[votelevels[i][0]]->actnum); + else + snprintf(levelinfo[i].str, + sizeof levelinfo[i].str, + "%.32s %.32s", + mapheaderinfo[votelevels[i][0]]->lvlttl, mapheaderinfo[votelevels[i][0]]->zonttl); + } else - snprintf(levelinfo[i].str, - sizeof levelinfo[i].str, - "%.32s", - mapheaderinfo[votelevels[i]]->lvlttl); + { + if (strlen(mapheaderinfo[votelevels[i][0]]->actnum) > 0) + snprintf(levelinfo[i].str, + sizeof levelinfo[i].str, + "%.32s %s", + mapheaderinfo[votelevels[i][0]]->lvlttl, mapheaderinfo[votelevels[i][0]]->actnum); + else + snprintf(levelinfo[i].str, + sizeof levelinfo[i].str, + "%.32s", + mapheaderinfo[votelevels[i][0]]->lvlttl); + } + + levelinfo[i].str[sizeof levelinfo[i].str - 1] = '\0'; } - levelinfo[i].str[sizeof levelinfo[i].str - 1] = '\0'; + // set up the gtc and gts + levelinfo[i].gtc = G_GetGametypeColor(votelevels[i][1]); + if (i == 2 && votelevels[i][1] != votelevels[0][1]) + levelinfo[i].gts = gametype_cons_t[votelevels[i][1]].strvalue; + else + levelinfo[i].gts = NULL; - lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(votelevels[i]+1))); + // set up the pic + lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(votelevels[i][0]+1))); if (lumpnum != LUMPERROR) - levelinfo[i].pic = W_CachePatchName(va("%sP", G_BuildMapName(votelevels[i]+1)), PU_STATIC); + levelinfo[i].pic = W_CachePatchName(va("%sP", G_BuildMapName(votelevels[i][0]+1)), PU_STATIC); else levelinfo[i].pic = W_CachePatchName("BLANKLVL", PU_STATIC); } + + voteclient.loaded = true; } // @@ -2608,6 +1479,8 @@ static void Y_UnloadVoteData(void) if (rendermode != render_soft) return; + voteclient.loaded = false; + UNLOAD(widebgpatch); UNLOAD(bgpatch); UNLOAD(cursor); @@ -2617,6 +1490,7 @@ static void Y_UnloadVoteData(void) UNLOAD(cursor4); UNLOAD(randomlvl); + UNLOAD(levelinfo[4].pic); UNLOAD(levelinfo[3].pic); UNLOAD(levelinfo[2].pic); UNLOAD(levelinfo[1].pic); @@ -2630,9 +1504,11 @@ void Y_SetupVoteFinish(SINT8 pick, SINT8 level) { if (pick == -1) // No other votes? We gotta get out of here, then! { - timer = 0; - Y_UnloadVoteData(); - Y_FollowIntermission(); + if (voteclient.loaded) + { + Y_EndVote(); + Y_FollowIntermission(); + } return; } @@ -2652,6 +1528,15 @@ void Y_SetupVoteFinish(SINT8 pick, SINT8 level) if (votes[i] == -1 || endtype > 1) // Don't need to go on continue; + if (level == 4) + { + votes[i] = 4; + continue; + } + + if (endtype == 2) + continue; + if (votecompare == -1) { votecompare = votes[i]; @@ -2661,24 +1546,26 @@ void Y_SetupVoteFinish(SINT8 pick, SINT8 level) endtype = 2; } - if (endtype == 0) // Might as well put this here, too. - { - timer = 0; - Y_UnloadVoteData(); - Y_FollowIntermission(); - return; - } - else if (endtype == 1) // Only one unique vote, so just end it immediately. + if (level == 4 || endtype == 1) // Only one unique vote, so just end it immediately. { voteendtic = votetic + (5*TICRATE); - S_StartSound(NULL, sfx_kc48); S_ChangeMusicInternal("voteeb", false); + Y_VoteStops(pick, level); + } + else if (endtype == 0) // Might as well put this here, too. + { + if (voteclient.loaded) + { + Y_EndVote(); + Y_FollowIntermission(); + } + return; } else S_ChangeMusicInternal("voteea", true); } + deferredlevel = level; pickedvote = pick; - nextmap = votelevels[level]; timer = 0; -} \ No newline at end of file +}